Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
weixin_46011646
wechaty
提交
4f18b15d
W
wechaty
项目概览
weixin_46011646
/
wechaty
与 Fork 源项目一致
Fork自
wechaty / wechaty
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
W
wechaty
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
4f18b15d
编写于
10月 26, 2016
作者:
Huan (李卓桓)
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add new class: `BrowserDriver` for modulize webdriver code from `Browser` class
上级
e86194d1
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
311 addition
and
268 deletion
+311
-268
src/config.ts
src/config.ts
+4
-4
src/puppet-web/browser-cookie.ts
src/puppet-web/browser-cookie.ts
+18
-17
src/puppet-web/browser-driver.ts
src/puppet-web/browser-driver.ts
+225
-0
src/puppet-web/browser.ts
src/puppet-web/browser.ts
+29
-216
src/puppet-web/puppet-web.ts
src/puppet-web/puppet-web.ts
+8
-4
src/wechaty.ts
src/wechaty.ts
+8
-11
test/puppet-web/browser.spec.ts
test/puppet-web/browser.spec.ts
+18
-15
test/webdriver.spec.ts
test/webdriver.spec.ts
+1
-1
未找到文件。
src/config.ts
浏览文件 @
4f18b15d
...
...
@@ -9,12 +9,12 @@ import * as fs from 'fs'
import
Puppet
from
'
./puppet
'
export
type
PuppetType
=
'
web
'
|
'
android
'
|
'
ios
'
export
type
Head
Type
=
'
chrome
'
|
'
phantomjs
'
export
type
Head
Name
=
'
chrome
'
|
'
phantomjs
'
|
'
firefox
'
export
interface
ConfigSetting
{
DEFAULT_HEAD
:
string
DEFAULT_PUPPET
:
string
DEFAULT_HEAD
:
HeadName
DEFAULT_PUPPET
:
PuppetType
DEFAULT_APIHOST
:
string
DEFAULT_PROFILE
:
string
DEFAULT_TOKEN
:
string
...
...
@@ -28,7 +28,7 @@ export interface ConfigSetting {
debug
:
boolean
puppet
:
PuppetType
head
:
Head
Typ
e
head
:
Head
Nam
e
apihost
:
string
validApiHost
:
(
host
:
string
)
=>
boolean
...
...
src/puppet-web/browser-cookie.ts
浏览文件 @
4f18b15d
...
...
@@ -12,8 +12,9 @@
import
*
as
fs
from
'
fs
'
const
arrify
=
require
(
'
arrify
'
)
import
Browser
from
'
./browser
'
import
log
from
'
../brolog-env
'
import
log
from
'
../brolog-env
'
import
BrowserDriver
from
'
./browser-driver
'
/**
* DriverCookie type exits is because @types/selenium is not updated
...
...
@@ -30,9 +31,9 @@ export type CookieType = {
}
export
class
BrowserCookie
{
constructor
(
private
browser
:
Brows
er
,
private
storeFile
?:
string
)
{
constructor
(
private
driver
:
BrowserDriv
er
,
private
storeFile
?:
string
)
{
log
.
verbose
(
'
PuppetWebBrowserCookie
'
,
'
constructor(%s, %s)
'
,
brows
er
.
constructor
.
name
,
driv
er
.
constructor
.
name
,
storeFile
?
storeFile
:
''
)
}
...
...
@@ -41,14 +42,14 @@ export class BrowserCookie {
// just check cookies, no file operation
log
.
verbose
(
'
PuppetWebBrowserCookie
'
,
'
checkSession()
'
)
if
(
this
.
browser
.
dead
())
{
throw
new
Error
(
'
checkSession() - browser dead
'
)
}
//
if (this.browser.dead()) {
//
throw new Error('checkSession() - browser dead')
//
}
// return new Promise((resolve, reject) => {
try
{
// `as any as DriverCookie` because selenium-webdriver @types is outdated with 2.x, where we r using 3.0
const
cookies
=
await
this
.
browser
.
driver
()
.
manage
().
getCookies
()
as
any
as
CookieType
[]
const
cookies
=
await
this
.
driver
.
manage
().
getCookies
()
as
any
as
CookieType
[]
log
.
silly
(
'
PuppetWebBrowserCookie
'
,
'
checkSession %s
'
,
cookies
.
map
(
c
=>
c
.
name
).
join
(
'
,
'
))
return
cookies
}
catch
(
e
)
{
...
...
@@ -63,7 +64,7 @@ export class BrowserCookie {
return
}
if
(
this
.
browser
.
dead
())
{
return
Promise
.
reject
(
new
Error
(
'
cleanSession() - browser dead
'
))}
//
if (this.browser.dead()) { return Promise.reject(new Error('cleanSession() - browser dead'))}
const
filename
=
this
.
storeFile
await
new
Promise
((
resolve
,
reject
)
=>
{
...
...
@@ -85,9 +86,9 @@ export class BrowserCookie {
}
const
storeFile
=
this
.
storeFile
if
(
this
.
browser
.
dead
())
{
throw
new
Error
(
'
saveSession() - browser dead
'
)
}
//
if (this.browser.dead()) {
//
throw new Error('saveSession() - browser dead')
//
}
const
filename
=
this
.
storeFile
...
...
@@ -108,7 +109,7 @@ export class BrowserCookie {
try
{
// return new Promise((resolve, reject) => {
// `as any as DriverCookie` because selenium-webdriver @types is outdated with 2.x, where we r using 3.0
let
cookies
:
CookieType
[]
=
await
this
.
browser
.
driver
()
.
manage
().
getCookies
()
as
any
as
CookieType
[]
let
cookies
:
CookieType
[]
=
await
this
.
driver
.
manage
().
getCookies
()
as
any
as
CookieType
[]
cookies
=
cookieFilter
(
cookies
)
// .then(cookies => {
// log.silly('PuppetWeb', 'saving %d cookies for session: %s', cookies.length
...
...
@@ -140,8 +141,8 @@ export class BrowserCookie {
if
(
!
this
.
storeFile
)
{
log
.
verbose
(
'
PuppetWebBrowserCookie
'
,
'
load() no session store file
'
)
return
}
else
if
(
this
.
browser
.
dead
())
{
throw
new
Error
(
'
loadSession() - browser dead
'
)
//
} else if (this.browser.dead()) {
//
throw new Error('loadSession() - browser dead')
}
const
storeFile
=
this
.
storeFile
...
...
@@ -175,7 +176,7 @@ export class BrowserCookie {
*/
// TypeScript Overloading: http://stackoverflow.com/a/21385587/1123955
public
async
add
(
cookie
:
CookieType
|
CookieType
[]):
Promise
<
void
>
{
if
(
this
.
browser
.
dead
())
{
return
Promise
.
reject
(
new
Error
(
'
addCookies() - browser dead
'
))}
//
if (this.browser.dead()) { return Promise.reject(new Error('addCookies() - browser dead'))}
if
(
Array
.
isArray
(
cookie
))
{
for
(
let
c
of
cookie
)
{
...
...
@@ -195,7 +196,7 @@ export class BrowserCookie {
// return new Promise((resolve, reject) => {
try
{
await
(
this
.
browser
.
driver
()
.
manage
()
as
any
).
addCookie
(
cookie
)
await
(
this
.
driver
.
manage
()
as
any
).
addCookie
(
cookie
)
// this is old webdriver format
// .addCookie(cookie.name, cookie.value, cookie.path
// , cookie.domain, cookie.secure, cookie.expiry)
...
...
src/puppet-web/browser-driver.ts
0 → 100644
浏览文件 @
4f18b15d
/**
* Wechat for Bot. Connecting ChatBots
*
* BrowserDriver
*
* Licenst: ISC
* https://github.com/wechaty/wechaty
*
*/
import
{
Builder
,
Capabilities
,
WebDriver
}
from
'
selenium-webdriver
'
import
{
Config
,
HeadName
}
from
'
../config
'
import
log
from
'
../brolog-env
'
export
class
BrowserDriver
{
private
driver
:
WebDriver
constructor
(
private
head
:
HeadName
)
{
log
.
verbose
(
'
PuppetWebBrowserDriver
'
,
'
constructor(%s)
'
,
head
)
}
public
async
init
():
Promise
<
this
>
{
log
.
verbose
(
'
PuppetWebBrowser
'
,
'
initDriver() for head: %s
'
,
this
.
head
)
if
(
this
.
driver
)
{
await
this
.
driver
.
close
()
await
this
.
driver
.
quit
()
}
const
head
=
this
.
head
switch
(
true
)
{
case
!
head
:
// no head default to phantomjs
case
/phantomjs/i
.
test
(
head
):
case
/phantom/i
.
test
(
head
):
this
.
driver
=
this
.
getPhantomJsDriver
()
break
case
/firefox/i
.
test
(
head
):
this
.
driver
=
new
Builder
()
.
setAlertBehavior
(
'
ignore
'
)
.
forBrowser
(
'
firefox
'
)
.
build
()
break
case
/chrome/i
.
test
(
head
):
this
.
driver
=
this
.
getChromeDriver
()
break
default
:
// unsupported browser head
throw
new
Error
(
'
unsupported head:
'
+
head
)
}
this
.
driver
.
manage
()
.
timeouts
()
.
setScriptTimeout
(
10000
)
return
this
}
private
getChromeDriver
():
WebDriver
{
log
.
verbose
(
'
PuppetWebBrowser
'
,
'
getChromeDriver()
'
)
/**
* http://stackoverflow.com/a/27733960/1123955
* issue #56
* only need under win32 with cygwin
* and will cause strange error:
* `The previously configured ChromeDriver service is still running. You must shut it down before you may adjust its configuration.`
const chrome = require('selenium-webdriver/chrome')
const path = require('chromedriver').path
const service = new chrome.ServiceBuilder(path).build()
chrome.setDefaultService(service)
*/
const
options
=
{
args
:
[
'
--no-sandbox
'
]
// issue #26 for run inside docker
// , binary: require('chromedriver').path
}
if
(
Config
.
isDocker
)
{
options
[
'
binary
'
]
=
Config
.
CMD_CHROMIUM
}
const
customChrome
=
Capabilities
.
chrome
()
.
set
(
'
chromeOptions
'
,
options
)
return
new
Builder
()
.
setAlertBehavior
(
'
ignore
'
)
.
forBrowser
(
'
chrome
'
)
.
withCapabilities
(
customChrome
)
.
build
()
}
private
getPhantomJsDriver
():
WebDriver
{
// setup custom phantomJS capability https://github.com/SeleniumHQ/selenium/issues/2069
const
phantomjsExe
=
require
(
'
phantomjs-prebuilt
'
).
path
if
(
!
phantomjsExe
)
{
throw
new
Error
(
'
phantomjs binary path not found
'
)
}
// const phantomjsExe = require('phantomjs2').path
const
phantomjsArgs
=
[
'
--load-images=false
'
,
'
--ignore-ssl-errors=true
'
// this help socket.io connect with localhost
,
'
--web-security=false
'
// https://github.com/ariya/phantomjs/issues/12440#issuecomment-52155299
,
'
--ssl-protocol=any
'
// http://stackoverflow.com/a/26503588/1123955
// , '--ssl-protocol=TLSv1' // https://github.com/ariya/phantomjs/issues/11239#issuecomment-42362211
// issue: Secure WebSocket(wss) do not work with Self Signed Certificate in PhantomJS #12
// , '--ssl-certificates-path=D:\\cygwin64\\home\\zixia\\git\\wechaty' // http://stackoverflow.com/a/32690349/1123955
// , '--ssl-client-certificate-file=cert.pem' //
]
if
(
Config
.
debug
)
{
phantomjsArgs
.
push
(
'
--remote-debugger-port=8080
'
)
// XXX: be careful when in production env.
phantomjsArgs
.
push
(
'
--webdriver-loglevel=DEBUG
'
)
// phantomjsArgs.push('--webdriver-logfile=webdriver.debug.log')
}
else
{
if
(
log
&&
log
.
level
()
===
'
silent
'
)
{
phantomjsArgs
.
push
(
'
--webdriver-loglevel=NONE
'
)
}
else
{
phantomjsArgs
.
push
(
'
--webdriver-loglevel=ERROR
'
)
}
}
const
customPhantom
=
Capabilities
.
phantomjs
()
.
setAlertBehavior
(
'
ignore
'
)
.
set
(
'
phantomjs.binary.path
'
,
phantomjsExe
)
.
set
(
'
phantomjs.cli.args
'
,
phantomjsArgs
)
log
.
silly
(
'
PuppetWebBrowser
'
,
'
phantomjs binary:
'
+
phantomjsExe
)
log
.
silly
(
'
PuppetWebBrowser
'
,
'
phantomjs args:
'
+
phantomjsArgs
.
join
(
'
'
))
const
driver
=
new
Builder
()
.
withCapabilities
(
customPhantom
)
.
build
()
/* tslint:disable:jsdoc-format */
/**
* FIXME: ISSUE #21 - https://github.com/zixia/wechaty/issues/21
*
* http://phantomjs.org/api/webpage/handler/on-resource-requested.html
* http://stackoverflow.com/a/29544970/1123955
* https://github.com/geeeeeeeeek/electronic-wechat/pull/319
*
*/
// driver.executePhantomJS(`
// this.onResourceRequested = function(request, net) {
// console.log('REQUEST ' + request.url);
// blockRe = /wx\.qq\.com\/\?t=v2\/fake/i
// if (blockRe.test(request.url)) {
// console.log('Abort ' + request.url);
// net.abort();
// }
// }
// `)
// https://github.com/detro/ghostdriver/blob/f976007a431e634a3ca981eea743a2686ebed38e/src/session.js#L233
// driver.manage().timeouts().pageLoadTimeout(2000)
return
driver
}
// public driver1(): WebDriver
// public driver1(empty: null): void
// public driver1(newDriver: WebDriver): WebDriver
// public driver1(newDriver?: WebDriver | null): WebDriver | void {
// if (newDriver !== undefined) {
// log.verbose('PuppetWebBrowser', 'driver(%s)'
// , newDriver
// ? newDriver.constructor.name
// : null
// )
// }
// if (newDriver !== undefined) {
// if (newDriver) {
// this.driver = newDriver
// return this.driver
// } else { // null
// if (this.driver && this.driver.getSession()) {
// throw new Error('driver still has session, can not set null')
// }
// this.driver = null
// return
// }
// }
// if (!this.driver) {
// const e = new Error('no driver')
// log.warn('PuppetWebBrowser', 'driver() exception: %s', e.message)
// throw e
// }
// // if (!this.driver.getSession()) {
// // const e = new Error('no driver session')
// // log.warn('PuppetWebBrowser', 'driver() exception: %s', e.message)
// // this.driver.quit()
// // throw e
// // }
// return this.driver
// }
public
close
()
{
return
this
.
driver
.
close
()
}
public
executeScript
()
{
return
this
.
driver
.
executeScript
.
apply
(
this
.
driver
,
arguments
)
}
public
executeAsyncScript
()
{
return
this
.
driver
.
executeAsyncScript
.
apply
(
this
.
driver
,
arguments
)
}
public
get
(
url
:
string
)
{
return
this
.
driver
.
get
(
url
)
}
public
getSession
()
{
return
this
.
driver
.
getSession
()
}
public
manage
()
{
return
this
.
driver
.
manage
()
}
public
navigate
()
{
return
this
.
driver
.
navigate
()
}
public
quit
()
{
return
this
.
driver
.
quit
()
}
}
export
default
BrowserDriver
src/puppet-web/browser.ts
浏览文件 @
4f18b15d
...
...
@@ -8,26 +8,25 @@
*
*/
import
{
EventEmitter
}
from
'
events
'
import
{
Builder
,
Capabilities
,
WebDriver
}
from
'
selenium-webdriver
'
/* tslint:disable:no-var-requires */
const
retryPromise
=
require
(
'
retry-promise
'
).
default
// https://github.com/olalonde/retry-promise
import
Config
from
'
../config
'
import
{
Config
,
HeadName
}
from
'
../config
'
import
StateMonitor
from
'
../state-monitor
'
import
log
from
'
../brolog-env
'
import
{
CookieType
,
BrowserCookie
}
from
'
./browser-cookie
'
}
from
'
./browser-cookie
'
import
BrowserDriver
from
'
./browser-driver
'
export
type
BrowserSetting
=
{
head
?:
string
head
:
HeadName
sessionFile
?:
string
}
...
...
@@ -36,20 +35,22 @@ export class Browser extends EventEmitter {
private
cookie
:
BrowserCookie
public
state
=
new
StateMonitor
<
'
open
'
,
'
close
'
>
(
'
Browser
'
,
'
close
'
)
public
_driver
:
WebDriver
|
null
=
null
public
driver
:
BrowserDriver
constructor
(
private
setting
:
BrowserSetting
=
{})
{
constructor
(
private
setting
:
BrowserSetting
=
{
head
:
Config
.
head
,
sessionFile
:
''
})
{
super
()
log
.
verbose
(
'
PuppetWebBrowser
'
,
'
constructor() with head(%s) sessionFile(%s)
'
,
setting
.
head
,
setting
.
sessionFile
)
setting
.
head
=
setting
.
head
||
process
.
env
[
'
WECHATY_HEAD
'
]
||
Config
.
DEFAULT_HEAD
// this.targetState('close')
// this.currentState('close')
this
.
state
.
target
(
'
close
'
)
this
.
state
.
current
(
'
close
'
)
this
.
cookie
=
new
BrowserCookie
(
this
,
this
.
setting
.
sessionFile
)
this
.
driver
=
new
BrowserDriver
(
this
.
setting
.
head
)
this
.
cookie
=
new
BrowserCookie
(
this
.
driver
,
this
.
setting
.
sessionFile
)
}
public
toString
()
{
return
`Browser({head:
${
this
.
setting
.
head
}
)`
}
...
...
@@ -65,7 +66,9 @@ export class Browser extends EventEmitter {
const
jumpUrl
=
'
https://wx.qq.com/zh_CN/htmledition/v2/images/webwxgeticon.jpg
'
try
{
await
this
.
initDriver
()
// await this.initDriver()
await
this
.
driver
.
init
()
// this.live = true
await
this
.
open
(
jumpUrl
)
...
...
@@ -105,7 +108,7 @@ export class Browser extends EventEmitter {
// TODO: set a timer to guard driver.get timeout, then retry 3 times 201607
try
{
await
this
.
driver
()
.
get
(
url
)
await
this
.
driver
.
get
(
url
)
}
catch
(
e
)
{
log
.
error
(
'
PuppetWebBrowser
'
,
'
open() exception: %s
'
,
e
.
message
)
this
.
dead
(
e
.
message
)
...
...
@@ -113,201 +116,13 @@ export class Browser extends EventEmitter {
}
}
public
async
initDriver
():
Promise
<
WebDriver
>
{
log
.
verbose
(
'
PuppetWebBrowser
'
,
'
initDriver() for head: %s
'
,
this
.
setting
.
head
)
if
(
this
.
_driver
)
{
await
this
.
_driver
.
close
()
await
this
.
_driver
.
quit
()
this
.
_driver
=
null
}
let
driver
:
WebDriver
const
head
=
<
string
>
this
.
setting
.
head
switch
(
true
)
{
case
!
head
:
// no head default to phantomjs
case
/phantomjs/i
.
test
(
head
):
case
/phantom/i
.
test
(
head
):
driver
=
this
.
getPhantomJsDriver
()
break
case
/firefox/i
.
test
(
head
):
driver
=
new
Builder
()
.
setAlertBehavior
(
'
ignore
'
)
.
forBrowser
(
'
firefox
'
)
.
build
()
break
case
/chrome/i
.
test
(
head
):
driver
=
this
.
getChromeDriver
()
break
default
:
// unsupported browser head
throw
new
Error
(
'
unsupported head:
'
+
head
)
}
driver
.
manage
()
.
timeouts
()
.
setScriptTimeout
(
10000
)
return
this
.
driver
(
driver
)
}
public
driver
():
WebDriver
public
driver
(
empty
:
null
):
void
public
driver
(
newDriver
:
WebDriver
):
WebDriver
public
driver
(
newDriver
?:
WebDriver
|
null
):
WebDriver
|
void
{
if
(
newDriver
!==
undefined
)
{
log
.
verbose
(
'
PuppetWebBrowser
'
,
'
driver(%s)
'
,
newDriver
?
newDriver
.
constructor
.
name
:
null
)
}
if
(
newDriver
!==
undefined
)
{
if
(
newDriver
)
{
this
.
_driver
=
newDriver
return
this
.
_driver
}
else
{
// null
if
(
this
.
_driver
&&
this
.
_driver
.
getSession
())
{
throw
new
Error
(
'
driver still has session, can not set null
'
)
}
this
.
_driver
=
null
return
}
}
if
(
!
this
.
_driver
)
{
const
e
=
new
Error
(
'
no driver
'
)
log
.
warn
(
'
PuppetWebBrowser
'
,
'
driver() exception: %s
'
,
e
.
message
)
throw
e
}
// if (!this._driver.getSession()) {
// const e = new Error('no driver session')
// log.warn('PuppetWebBrowser', 'driver() exception: %s', e.message)
// this._driver.quit()
// throw e
// }
return
this
.
_driver
}
public
async
refresh
():
Promise
<
any
>
{
log
.
verbose
(
'
PuppetWebBrowser
'
,
'
refresh()
'
)
return
await
this
.
driver
()
return
await
this
.
driver
.
navigate
()
.
refresh
()
}
private
getChromeDriver
():
WebDriver
{
log
.
verbose
(
'
PuppetWebBrowser
'
,
'
getChromeDriver()
'
)
/**
* http://stackoverflow.com/a/27733960/1123955
* issue #56
* only need under win32 with cygwin
* and will cause strange error:
* `The previously configured ChromeDriver service is still running. You must shut it down before you may adjust its configuration.`
const chrome = require('selenium-webdriver/chrome')
const path = require('chromedriver').path
const service = new chrome.ServiceBuilder(path).build()
chrome.setDefaultService(service)
*/
const
options
=
{
args
:
[
'
--no-sandbox
'
]
// issue #26 for run inside docker
// , binary: require('chromedriver').path
}
if
(
Config
.
isDocker
)
{
options
[
'
binary
'
]
=
Config
.
CMD_CHROMIUM
}
const
customChrome
=
Capabilities
.
chrome
()
.
set
(
'
chromeOptions
'
,
options
)
return
new
Builder
()
.
setAlertBehavior
(
'
ignore
'
)
.
forBrowser
(
'
chrome
'
)
.
withCapabilities
(
customChrome
)
.
build
()
}
private
getPhantomJsDriver
():
WebDriver
{
// setup custom phantomJS capability https://github.com/SeleniumHQ/selenium/issues/2069
const
phantomjsExe
=
require
(
'
phantomjs-prebuilt
'
).
path
if
(
!
phantomjsExe
)
{
throw
new
Error
(
'
phantomjs binary path not found
'
)
}
// const phantomjsExe = require('phantomjs2').path
const
phantomjsArgs
=
[
'
--load-images=false
'
,
'
--ignore-ssl-errors=true
'
// this help socket.io connect with localhost
,
'
--web-security=false
'
// https://github.com/ariya/phantomjs/issues/12440#issuecomment-52155299
,
'
--ssl-protocol=any
'
// http://stackoverflow.com/a/26503588/1123955
// , '--ssl-protocol=TLSv1' // https://github.com/ariya/phantomjs/issues/11239#issuecomment-42362211
// issue: Secure WebSocket(wss) do not work with Self Signed Certificate in PhantomJS #12
// , '--ssl-certificates-path=D:\\cygwin64\\home\\zixia\\git\\wechaty' // http://stackoverflow.com/a/32690349/1123955
// , '--ssl-client-certificate-file=cert.pem' //
]
if
(
Config
.
debug
)
{
phantomjsArgs
.
push
(
'
--remote-debugger-port=8080
'
)
// XXX: be careful when in production env.
phantomjsArgs
.
push
(
'
--webdriver-loglevel=DEBUG
'
)
// phantomjsArgs.push('--webdriver-logfile=webdriver.debug.log')
}
else
{
if
(
log
&&
log
.
level
()
===
'
silent
'
)
{
phantomjsArgs
.
push
(
'
--webdriver-loglevel=NONE
'
)
}
else
{
phantomjsArgs
.
push
(
'
--webdriver-loglevel=ERROR
'
)
}
}
const
customPhantom
=
Capabilities
.
phantomjs
()
.
setAlertBehavior
(
'
ignore
'
)
.
set
(
'
phantomjs.binary.path
'
,
phantomjsExe
)
.
set
(
'
phantomjs.cli.args
'
,
phantomjsArgs
)
log
.
silly
(
'
PuppetWebBrowser
'
,
'
phantomjs binary:
'
+
phantomjsExe
)
log
.
silly
(
'
PuppetWebBrowser
'
,
'
phantomjs args:
'
+
phantomjsArgs
.
join
(
'
'
))
const
driver
=
new
Builder
()
.
withCapabilities
(
customPhantom
)
.
build
()
/* tslint:disable:jsdoc-format */
/**
* FIXME: ISSUE #21 - https://github.com/zixia/wechaty/issues/21
*
* http://phantomjs.org/api/webpage/handler/on-resource-requested.html
* http://stackoverflow.com/a/29544970/1123955
* https://github.com/geeeeeeeeek/electronic-wechat/pull/319
*
*/
// driver.executePhantomJS(`
// this.onResourceRequested = function(request, net) {
// console.log('REQUEST ' + request.url);
// blockRe = /wx\.qq\.com\/\?t=v2\/fake/i
// if (blockRe.test(request.url)) {
// console.log('Abort ' + request.url);
// net.abort();
// }
// }
// `)
// https://github.com/detro/ghostdriver/blob/f976007a431e634a3ca981eea743a2686ebed38e/src/session.js#L233
// driver.manage().timeouts().pageLoadTimeout(2000)
return
driver
}
public
async
restart
():
Promise
<
void
>
{
log
.
verbose
(
'
PuppetWebBrowser
'
,
'
restart()
'
)
...
...
@@ -336,12 +151,10 @@ export class Browser extends EventEmitter {
this
.
state
.
current
(
'
close
'
,
false
)
try
{
await
this
.
driver
()
.
close
().
catch
(
e
=>
{
/* fail safe */
})
// http://stackoverflow.com/a/32341885/1123955
await
this
.
driver
.
close
().
catch
(
e
=>
{
/* fail safe */
})
// http://stackoverflow.com/a/32341885/1123955
log
.
silly
(
'
PuppetWebBrowser
'
,
'
quit() driver.close()-ed
'
)
await
this
.
driver
()
.
quit
()
await
this
.
driver
.
quit
()
log
.
silly
(
'
PuppetWebBrowser
'
,
'
quit() driver.quit()-ed
'
)
this
.
driver
(
null
)
log
.
silly
(
'
PuppetWebBrowser
'
,
'
quit() this.driver = null
'
)
/**
*
...
...
@@ -461,11 +274,11 @@ export class Browser extends EventEmitter {
+
(
script
.
length
>
80
?
'
...
'
:
''
)
)
)
// log.verbose('PuppetWebBrowser', `Browser.execute() driver.getSession: %s`, util.inspect(this.driver
()
.getSession()))
// log.verbose('PuppetWebBrowser', `Browser.execute() driver.getSession: %s`, util.inspect(this.driver.getSession()))
if
(
this
.
dead
())
{
throw
new
Error
(
'
browser dead
'
)
}
try
{
return
await
this
.
driver
().
executeScript
.
apply
(
this
.
driver
()
,
arguments
)
return
await
this
.
driver
.
executeScript
.
apply
(
this
.
driver
,
arguments
)
}
catch
(
e
)
{
// this.dead(e)
log
.
warn
(
'
PuppetWebBrowser
'
,
'
execute() exception: %s
'
,
e
.
message
.
substr
(
0
,
99
))
...
...
@@ -478,7 +291,7 @@ export class Browser extends EventEmitter {
if
(
this
.
dead
())
{
throw
new
Error
(
'
browser dead
'
)
}
try
{
return
await
this
.
driver
().
executeAsyncScript
.
apply
(
this
.
driver
()
,
arguments
)
return
await
this
.
driver
.
executeAsyncScript
.
apply
(
this
.
driver
,
arguments
)
}
catch
(
e
)
{
// this.dead(e)
log
.
warn
(
'
PuppetWebBrowser
'
,
'
executeAsync() exception: %s
'
,
e
.
message
.
slice
(
0
,
99
))
...
...
@@ -531,7 +344,7 @@ export class Browser extends EventEmitter {
}
else
if
(
this
.
state
.
target
()
!==
'
open
'
)
{
dead
=
true
msg
=
'
state.target() not open
'
}
else
if
(
!
this
.
driver
())
{
}
else
if
(
!
this
.
driver
)
{
// FIXME: this.driver is BrowserDriver, should add a method to check if availble 201610
dead
=
true
msg
=
'
no driver or session
'
}
...
...
@@ -567,10 +380,10 @@ export class Browser extends EventEmitter {
return
dead
}
public
a
sync
addCookie
(
cookies
:
CookieType
[]):
Promise
<
void
>
public
a
sync
addCookie
(
cookie
:
CookieType
):
Promise
<
void
>
public
a
sync
a
ddCookie
(
cookie
:
CookieType
|
CookieType
[]):
Promise
<
void
>
{
await
this
.
cookie
.
add
(
cookie
)
public
a
ddCookie
(
cookies
:
CookieType
[]):
Promise
<
void
>
public
a
ddCookie
(
cookie
:
CookieType
):
Promise
<
void
>
public
addCookie
(
cookie
:
CookieType
|
CookieType
[]):
Promise
<
void
>
{
return
this
.
cookie
.
add
(
cookie
)
}
public
saveCookie
()
{
return
this
.
cookie
.
save
()
}
...
...
src/puppet-web/puppet-web.ts
浏览文件 @
4f18b15d
...
...
@@ -14,8 +14,9 @@
*
*/
import
{
// Config
ScanInfo
Config
,
HeadName
,
ScanInfo
,
WatchdogFood
}
from
'
../config
'
...
...
@@ -34,7 +35,7 @@ import Server from './server'
import
Watchdog
from
'
./watchdog
'
export
type
PuppetWebSetting
=
{
head
?:
string
head
?:
HeadName
profile
?:
string
}
const
DEFAULT_PUPPET_PORT
=
18788
// // W(87) X(88), ascii char code ;-]
...
...
@@ -56,6 +57,9 @@ export class PuppetWeb extends Puppet {
constructor
(
public
setting
:
PuppetWebSetting
=
{})
{
super
()
if
(
!
setting
.
head
)
{
setting
.
head
=
Config
.
head
}
this
.
on
(
'
watchdog
'
,
Watchdog
.
onFeed
.
bind
(
this
))
}
...
...
@@ -180,7 +184,7 @@ export class PuppetWeb extends Puppet {
public
async
initBrowser
():
Promise
<
Browser
>
{
log
.
verbose
(
'
PuppetWeb
'
,
'
initBrowser()
'
)
const
browser
=
new
Browser
({
head
:
this
.
setting
.
head
head
:
<
HeadName
>
this
.
setting
.
head
,
sessionFile
:
this
.
setting
.
profile
})
...
...
src/wechaty.ts
浏览文件 @
4f18b15d
...
...
@@ -15,7 +15,7 @@ import * as path from 'path'
import
{
Config
,
Head
Typ
e
,
Head
Nam
e
,
PuppetType
,
Sayable
}
from
'
./config
'
...
...
@@ -32,9 +32,9 @@ import UtilLib from './util-lib'
import
log
from
'
./brolog-env
'
export
type
WechatySetting
=
{
profile
?:
string
head
?:
Head
Type
type
?:
PuppetType
head
?:
HeadName
type
?:
Puppet
Type
profile
?:
string
}
export
type
WechatyEventName
=
'
error
'
...
...
@@ -74,14 +74,11 @@ export class Wechaty extends EventEmitter implements Sayable {
super
()
log
.
verbose
(
'
Wechaty
'
,
'
contructor()
'
)
// if (Wechaty._instance instanceof Wechaty) {
// throw new Error('Wechaty must be singleton')
// }
setting
.
type
=
setting
.
type
||
Config
.
puppet
setting
.
head
=
setting
.
head
||
Config
.
head
setting
.
type
=
setting
.
type
||
Config
.
puppet
setting
.
profile
=
setting
.
profile
||
Config
.
profile
// setting.port = setting.port || Config.port
setting
.
profile
=
setting
.
profile
||
Config
.
profile
// no profile, no session save/restore
if
(
setting
.
profile
)
{
setting
.
profile
=
/
\.
wechaty
\.
json$/i
.
test
(
setting
.
profile
)
...
...
@@ -214,7 +211,7 @@ export class Wechaty extends EventEmitter implements Sayable {
switch
(
this
.
setting
.
type
)
{
case
'
web
'
:
puppet
=
new
PuppetWeb
({
head
:
this
.
setting
.
head
head
:
<
HeadName
>
this
.
setting
.
head
,
profile
:
this
.
setting
.
profile
})
break
...
...
test/puppet-web/browser.spec.ts
浏览文件 @
4f18b15d
...
...
@@ -19,7 +19,8 @@ test('Browser class cookie smoking tests', async t => {
// b.targetState('open')
b
.
state
.
target
(
'
open
'
)
await
b
.
initDriver
()
// await b.initDriver()
await
b
.
driver
.
init
()
t
.
pass
(
'
should init driver
'
)
await
b
.
open
()
...
...
@@ -28,11 +29,11 @@ test('Browser class cookie smoking tests', async t => {
const
two
=
await
b
.
execute
(
'
return 1+1
'
)
t
.
is
(
two
,
2
,
'
should got 2 after execute script 1+1
'
)
let
cookies
=
await
b
.
driver
()
.
manage
().
getCookies
()
let
cookies
=
await
b
.
driver
.
manage
().
getCookies
()
t
.
truthy
(
cookies
.
length
,
'
should got plenty of cookies
'
)
await
b
.
driver
()
.
manage
().
deleteAllCookies
()
cookies
=
await
b
.
driver
()
.
manage
().
getCookies
()
await
b
.
driver
.
manage
().
deleteAllCookies
()
cookies
=
await
b
.
driver
.
manage
().
getCookies
()
t
.
is
(
cookies
.
length
,
0
,
'
should no cookie anymore after deleteAllCookies()
'
)
const
EXPECTED_COOKIES
=
[{
...
...
@@ -56,7 +57,7 @@ test('Browser class cookie smoking tests', async t => {
const
tt
=
await
b
.
readCookie
()
await
Promise
.
all
(
tt
)
cookies
=
await
b
.
driver
()
.
manage
().
getCookies
()
cookies
=
await
b
.
driver
.
manage
().
getCookies
()
const
cookies0
=
cookies
.
filter
(
c
=>
{
return
RegExp
(
EXPECTED_COOKIES
[
0
].
name
).
test
(
c
.
name
)
})
t
.
is
(
cookies0
[
0
].
name
,
EXPECTED_COOKIES
[
0
].
name
,
'
getCookies() should filter out the cookie named wechaty0
'
)
const
cookies1
=
cookies
.
filter
(
c
=>
{
return
RegExp
(
EXPECTED_COOKIES
[
1
].
name
).
test
(
c
.
name
)
})
...
...
@@ -65,7 +66,7 @@ test('Browser class cookie smoking tests', async t => {
await
b
.
open
()
t
.
pass
(
'
re-opened url
'
)
const
cookieAfterOpen
=
await
b
.
driver
()
.
manage
().
getCookie
(
EXPECTED_COOKIES
[
0
].
name
)
const
cookieAfterOpen
=
await
b
.
driver
.
manage
().
getCookie
(
EXPECTED_COOKIES
[
0
].
name
)
t
.
is
(
cookieAfterOpen
.
name
,
EXPECTED_COOKIES
[
0
].
name
,
'
getCookie() should get expected cookie named after re-open url
'
)
const
dead
=
b
.
dead
()
...
...
@@ -81,7 +82,8 @@ test('Browser session save before quit, and load after restart', async t => {
const
profileName
=
PROFILE
+
profileCounter
++
let
b
=
new
Browser
({
sessionFile
:
profileName
head
:
Config
.
head
,
sessionFile
:
profileName
})
/**
...
...
@@ -93,7 +95,7 @@ test('Browser session save before quit, and load after restart', async t => {
// b.targetState('open')
b
.
state
.
target
(
'
open
'
)
await
b
.
initDriver
()
await
b
.
driver
.
init
()
t
.
pass
(
'
should init driver
'
)
await
b
.
open
()
...
...
@@ -109,12 +111,12 @@ test('Browser session save before quit, and load after restart', async t => {
}
const
EXPECTED_NAME_REGEX
=
new
RegExp
(
'
^
'
+
EXPECTED_COOKIE
.
name
+
'
$
'
)
await
b
.
driver
()
.
manage
().
deleteAllCookies
()
let
cookies
=
await
b
.
driver
()
.
manage
().
getCookies
()
await
b
.
driver
.
manage
().
deleteAllCookies
()
let
cookies
=
await
b
.
driver
.
manage
().
getCookies
()
t
.
is
(
cookies
.
length
,
0
,
'
should no cookie after deleteAllCookies()
'
)
await
b
.
addCookie
(
EXPECTED_COOKIE
)
const
cookieFromBrowser
=
await
b
.
driver
()
.
manage
().
getCookie
(
EXPECTED_COOKIE
.
name
)
const
cookieFromBrowser
=
await
b
.
driver
.
manage
().
getCookie
(
EXPECTED_COOKIE
.
name
)
t
.
is
(
cookieFromBrowser
.
name
,
EXPECTED_COOKIE
.
name
,
'
cookie from getCookie() should be same as we just set
'
)
let
cookiesFromCheck
=
await
b
.
readCookie
()
...
...
@@ -129,7 +131,7 @@ test('Browser session save before quit, and load after restart', async t => {
t
.
is
(
cookieFromSave
.
length
,
1
,
'
should has the cookie we just set
'
)
t
.
is
(
cookieFromSave
[
0
][
'
name
'
],
EXPECTED_COOKIE
.
name
,
'
cookie from saveSession() return should be same as we just set
'
)
await
b
.
driver
()
.
manage
().
deleteAllCookies
()
await
b
.
driver
.
manage
().
deleteAllCookies
()
cookiesFromCheck
=
await
b
.
readCookie
()
t
.
is
(
cookiesFromCheck
.
length
,
0
,
'
should no cookie from checkSession() after deleteAllCookies()
'
)
...
...
@@ -154,7 +156,8 @@ test('Browser session save before quit, and load after restart', async t => {
*/
b
=
new
Browser
({
sessionFile
:
profileName
head
:
Config
.
head
,
sessionFile
:
profileName
})
t
.
pass
(
'
should started a new Browser
'
)
...
...
@@ -162,7 +165,7 @@ test('Browser session save before quit, and load after restart', async t => {
// b.targetState('open')
b
.
state
.
target
(
'
open
'
)
await
b
.
initDriver
()
await
b
.
driver
.
init
()
t
.
pass
(
'
should inited the new Browser
'
)
await
b
.
open
()
t
.
pass
(
'
should opened
'
)
...
...
@@ -170,7 +173,7 @@ test('Browser session save before quit, and load after restart', async t => {
await
b
.
loadCookie
()
t
.
pass
(
'
should loadSession for new Browser(process)
'
)
const
cookieAfterQuit
=
await
b
.
driver
()
.
manage
().
getCookie
(
EXPECTED_COOKIE
.
name
)
const
cookieAfterQuit
=
await
b
.
driver
.
manage
().
getCookie
(
EXPECTED_COOKIE
.
name
)
t
.
truthy
(
cookieAfterQuit
,
'
should get cookie from getCookie()
'
)
t
.
is
(
cookieAfterQuit
.
name
,
EXPECTED_COOKIE
.
name
,
'
cookie from getCookie() after browser quit, should load the right cookie back
'
)
...
...
test/webdriver.spec.ts
浏览文件 @
4f18b15d
...
...
@@ -56,7 +56,7 @@ test.serial('WebDriver smoke testing', async t => {
const
m
=
(
await
wb
.
getBrowserPids
()).
length
t
.
is
(
m
,
0
,
'
should has no browser process before get()
'
)
driver
=
await
wb
.
initDriver
()
driver
=
await
wb
.
driver
.
init
()
t
.
truthy
(
driver
,
'
should init driver success
'
)
const
injectio
=
bridge
.
getInjectio
()
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录