提交 253f2f4f 编写于 作者: J Jas 提交者: GitHub

Merge pull request #2 from wechaty/master

merge new code
...@@ -53,3 +53,4 @@ t.* ...@@ -53,3 +53,4 @@ t.*
.DS_Store .DS_Store
/dist/ /dist/
yarn.lock yarn.lock
.yarn/
...@@ -6,11 +6,12 @@ ...@@ -6,11 +6,12 @@
# #
# Docker image for Alpine Linux with latest ShellCheck, a static analysis tool for shell scripts. # Docker image for Alpine Linux with latest ShellCheck, a static analysis tool for shell scripts.
# https://hub.docker.com/r/nlknguyen/alpine-shellcheck/ # https://hub.docker.com/r/nlknguyen/alpine-shellcheck/
FROM nlknguyen/alpine-shellcheck # FROM nlknguyen/alpine-shellcheck
FROM mhart/alpine-node:7
MAINTAINER Zhuophuan LI <zixia@zixia.net> MAINTAINER Zhuophuan LI <zixia@zixia.net>
RUN apk update && apk upgrade \ RUN apk update && apk upgrade \
&& apk add nodejs \ && apk add \
bash \ bash \
ca-certificates \ ca-certificates \
chromium-chromedriver \ chromium-chromedriver \
......
...@@ -113,6 +113,8 @@ function wechaty::runBot() { ...@@ -113,6 +113,8 @@ function wechaty::runBot() {
echo "Install dependencies modules ..." echo "Install dependencies modules ..."
yarn < /dev/null # yarn will close stdin??? cause `read` command fail after yarn yarn < /dev/null # yarn will close stdin??? cause `read` command fail after yarn
} }
npm --progress=false install @types/node > /dev/null
# echo -n "Linking Wechaty module to bot ... " # echo -n "Linking Wechaty module to bot ... "
# npm link wechaty < /dev/null > /dev/null 2>&1 # npm link wechaty < /dev/null > /dev/null 2>&1
...@@ -137,6 +139,17 @@ function wechaty::runBot() { ...@@ -137,6 +139,17 @@ function wechaty::runBot() {
return "$ret" return "$ret"
} }
function wechaty::help() {
echo <<HELP
Usage: wechaty <mybot.js | mybot.ts | command>
1. mybot.js: a JavaScript program for your bot. will run by node v6
2. mybot.ts: a TypeScript program for your bot. will run by ts-node
3. command: demo, test, doctor
HELP
}
function main() { function main() {
wechaty::banner wechaty::banner
figlet Connecting figlet Connecting
...@@ -175,6 +188,14 @@ function main() { ...@@ -175,6 +188,14 @@ function main() {
npm "$@" || ret=$? npm "$@" || ret=$?
;; ;;
'')
if [ -n "$WECHATY_TOKEN" ]; then
npm start
else
wechaty::help
fi
;;
# #
# 4. Default to execute npm run ... # 4. Default to execute npm run ...
# #
......
...@@ -8,6 +8,7 @@ machine: ...@@ -8,6 +8,7 @@ machine:
test: test:
override: override:
- docker info - docker info
- docker run -ti -v "$(pwd)":/mnt nlknguyen/alpine-shellcheck bin/*.sh
- ./script/docker.sh build - ./script/docker.sh build
- ./script/docker.sh run shlint - ./script/docker.sh run shlint
- ./script/docker.sh test - ./script/docker.sh test
......
...@@ -30,3 +30,4 @@ export { ...@@ -30,3 +30,4 @@ export {
, Wechaty , Wechaty
, log // for convenionce use npmlog with environment variable LEVEL , log // for convenionce use npmlog with environment variable LEVEL
} }
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
"lint": "npm run eslint && npm run tslint", "lint": "npm run eslint && npm run tslint",
"eslint": "eslint \"{bin,example,src,test}/**/*.js\"", "eslint": "eslint \"{bin,example,src,test}/**/*.js\"",
"tslint": "tslint \"{bin,example,src,test}/**/*.ts\" && tsc --noEmit", "tslint": "tslint \"{bin,example,src,test}/**/*.ts\" && tsc --noEmit",
"shlint": "bash -n bin/*.sh && shellcheck bin/*.sh", "shlint": "bash -n bin/*.sh",
"pretest": "npm run clean && npm run lint && npm run build", "pretest": "npm run clean && npm run lint && npm run build",
"sloc": "sloc bin example src test index.ts --details --format cli-table --keys total,source,comment && sloc bin example src test index.ts", "sloc": "sloc bin example src test index.ts --details --format cli-table --keys total,source,comment && sloc bin example src test index.ts",
"test": "npm run test:chrome", "test": "npm run test:chrome",
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
"test:chrome": "cross-env LC_ALL=C WECHATY_LOG=verbose WECHATY_HEAD=chrome ava --serial --fail-fast --verbose --ext js --timeout=7m \"dist/{src,test}/**/*.spec.js\"", "test:chrome": "cross-env LC_ALL=C WECHATY_LOG=verbose WECHATY_HEAD=chrome ava --serial --fail-fast --verbose --ext js --timeout=7m \"dist/{src,test}/**/*.spec.js\"",
"testdev": "cross-env LC_ALL=C WECHATY_LOG=silly ava --ext ts --serial --verbose --fail-fast --timeout=3m", "testdev": "cross-env LC_ALL=C WECHATY_LOG=silly ava --ext ts --serial --verbose --fail-fast --timeout=3m",
"testdist": "cross-env WECHATY_LOG=SILLY WECHATY_HEAD=chrome ava --ext ts --verbose --fail-fast --timeout=2m", "testdist": "cross-env WECHATY_LOG=SILLY WECHATY_HEAD=chrome ava --ext ts --verbose --fail-fast --timeout=2m",
"ava": "cross-env LC_ALL=C WECHATY_LOG=verbose ts-node node_modules/.bin/ava \"{src,test}/**/*.spec.js\"", "ava": "cross-env LC_ALL=C WECHATY_LOG=verbose node_modules/.bin/ava --ext js",
"start": "ts-node bin/client", "start": "ts-node bin/client",
"dev": "ts-node dev.ts", "dev": "ts-node dev.ts",
"demo": "ts-node example/ding-dong-bot.ts" "demo": "ts-node example/ding-dong-bot.ts"
......
#!/bin/sh #!/bin/bash
# #
# 1. CircleCI with `Btrfs volume error` # 1. CircleCI with `Btrfs volume error`
# https://circleci.com/docs/docker-btrfs-error/ # https://circleci.com/docs/docker-btrfs-error/
# #
set -e
imageName='wechaty:test' imageName='wechaty:test'
optRm='--rm' optRm='--rm'
[ -n "$CIRCLECI" ] && optRm='--rm=false' [ -n "$CIRCLECI" ] && optRm='--rm=false'
if [ "$1" = "build" ] || [ "$1" = "" ]; then declare -i ret=0
echo docker build "$optRm" -t "$imageName" . case "$1" in
exec docker build "$optRm" -t "$imageName" . build | '')
echo docker build "$optRm" -t "$imageName" .
exec docker build "$optRm" -t "$imageName" .
ret=$?
;;
test)
echo docker run -ti "$optRm" -v /dev/shm:/dev/shm -v "$(pwd)":/bot "$imageName" test/docker-bot/js-bot.js
docker run -ti "$optRm" -v /dev/shm:/dev/shm -v "$(pwd)":/bot "$imageName" test/docker-bot/js-bot.js
ret=$? echo docker run -ti "$optRm" -v /dev/shm:/dev/shm -v "$(pwd)":/bot "$imageName" test/docker-bot/ts-bot.ts
echo "ERROR: exec return $ret ???" docker run -ti "$optRm" -v /dev/shm:/dev/shm -v "$(pwd)":/bot "$imageName" test/docker-bot/ts-bot.ts
exit $ret
fi
echo docker run -ti "$optRm" -v /dev/shm:/dev/shm "$imageName" $@ echo docker run -ti "$optRm" -v /dev/shm:/dev/shm "$imageName" "$@"
exec docker run -ti "$optRm" -v /dev/shm:/dev/shm "$imageName" $@ exec docker run -ti "$optRm" -v /dev/shm:/dev/shm "$imageName" "$@"
ret=$?
;;
*)
echo docker run -ti "$optRm" -v /dev/shm:/dev/shm "$imageName" "$@"
exec docker run -ti "$optRm" -v /dev/shm:/dev/shm "$imageName" "$@"
ret=$?
;;
esac
ret=$?
echo "ERROR: exec return $ret ???" echo "ERROR: exec return $ret ???"
exit $ret exit $ret
/**
* Wechaty - Wechat for Bot. Connecting ChatBots
*
* Licenst: ISC
* https://github.com/wechaty/wechaty
*
*/
import { test } from 'ava'
import {
// Config
// , log
} from '../config'
import {
Browser
} from './browser'
test('quit()', async t => {
const browser = new Browser()
await browser.driver.init() // init driver, not init browser
t.throws(browser.quit(), Error, 'should throw on an un-inited browser')
browser.state.current('open', false)
t.notThrows(browser.quit(), 'should not throw exception when call quit() on an `inprocess` `open` state browser')
browser.state.current('close')
t.throws(browser.quit(), Error, 'should throw exception when call quit() twice on browser')
})
test('init()', async t => {
const browser = new Browser()
browser.state.current('open')
t.throws(browser.init(), Error, 'should throw exception when call init() on an `open` state browser')
browser.state.current('open', false)
t.throws(browser.init(), Error, 'should throw exception when call init() on a `open`-`ing` state browser')
})
...@@ -53,6 +53,17 @@ export class Browser extends EventEmitter { ...@@ -53,6 +53,17 @@ export class Browser extends EventEmitter {
public async init(): Promise<void> { public async init(): Promise<void> {
log.verbose('PuppetWebBrowser', 'init()') log.verbose('PuppetWebBrowser', 'init()')
if (this.state.current() === 'open') {
let e: Error
if (this.state.inprocess()) {
e = new Error('init() fail: current state is `open`-`ing`')
} else {
e = new Error('init() fail: current state is `open`')
}
log.error('PuppetWebBrowser', e.message)
throw e
}
this.state.target('open') this.state.target('open')
this.state.current('open', false) this.state.current('open', false)
...@@ -134,15 +145,14 @@ export class Browser extends EventEmitter { ...@@ -134,15 +145,14 @@ export class Browser extends EventEmitter {
log.verbose('PuppetWebBrowser', 'quit()') log.verbose('PuppetWebBrowser', 'quit()')
if (this.state.current() === 'close') { if (this.state.current() === 'close') {
let e: Error
if (this.state.inprocess()) { if (this.state.inprocess()) {
const e = new Error('quit() on a browser with state.current():`close` and inprocess():`true` ?') e = new Error('quit() fail: on a browser with state.current():`close` and inprocess():`true` ?')
log.warn('PuppetWebBrowser', e.message)
throw e
} else { // stable } else { // stable
const e = new Error('quit() on a already quit-ed browser') e = new Error('quit() fail: on a already quit-ed browser')
log.warn('PuppetWebBrowser', e.message)
throw e
} }
log.warn('PuppetWebBrowser', e.message)
throw e
} }
this.state.current('close', false) this.state.current('close', false)
...@@ -275,6 +285,7 @@ export class Browser extends EventEmitter { ...@@ -275,6 +285,7 @@ export class Browser extends EventEmitter {
return await this.driver.executeScript.apply(this.driver, arguments) return await this.driver.executeScript.apply(this.driver, arguments)
} catch (e) { } catch (e) {
// this.dead(e) // this.dead(e)
log.verbose('PuppetWebBrowser', 'execute() script: %s', script)
log.warn('PuppetWebBrowser', 'execute() exception: %s, %s', e.message.substr(0, 99), e.stack) log.warn('PuppetWebBrowser', 'execute() exception: %s, %s', e.message.substr(0, 99), e.stack)
throw e throw e
} }
......
const { Wechaty } = require('wechaty')
const bot = Wechaty.instance()
console.log(bot.version())
import { Wechaty } from 'wechaty'
const bot = Wechaty.instance()
console.log(bot.version())
...@@ -20,7 +20,7 @@ import { ...@@ -20,7 +20,7 @@ import {
const PROFILE = Config.DEFAULT_PROFILE + '-' + process.pid + '-' const PROFILE = Config.DEFAULT_PROFILE + '-' + process.pid + '-'
let profileCounter = 1 let profileCounter = 1
test('Browser Cookie smoking test', async t => { test('Cookie smoking test', async t => {
const browser = new Browser() const browser = new Browser()
t.truthy(browser, 'should instanciate a browser instance') t.truthy(browser, 'should instanciate a browser instance')
...@@ -83,10 +83,10 @@ test('Browser Cookie smoking test', async t => { ...@@ -83,10 +83,10 @@ test('Browser Cookie smoking test', async t => {
await browser.driver.quit() await browser.driver.quit()
}) })
test('Browser Cookie save/load test', async t => { test('Cookie save/load', async t => {
const profileName = PROFILE + profileCounter++ + 'wechaty.json' const profileName = PROFILE + profileCounter++ + 'wechaty.json'
let b = new Browser({ let browser = new Browser({
head: Config.head head: Config.head
, sessionFile: profileName , sessionFile: profileName
}) })
...@@ -95,14 +95,14 @@ test('Browser Cookie save/load test', async t => { ...@@ -95,14 +95,14 @@ test('Browser Cookie save/load test', async t => {
* use exception to call b.quit() to clean up * use exception to call b.quit() to clean up
*/ */
try { try {
t.truthy(b, 'should get a new Browser') t.truthy(browser, 'should get a new Browser')
b.state.target('open') browser.state.target('open')
await b.driver.init() await browser.driver.init()
t.pass('should init driver') t.pass('should init driver')
await b.open() await browser.open()
t.pass('opened') t.pass('opened')
const EXPECTED_COOKIE = { const EXPECTED_COOKIE = {
...@@ -115,43 +115,43 @@ test('Browser Cookie save/load test', async t => { ...@@ -115,43 +115,43 @@ test('Browser Cookie save/load test', async t => {
} }
const EXPECTED_NAME_REGEX = new RegExp('^' + EXPECTED_COOKIE.name + '$') const EXPECTED_NAME_REGEX = new RegExp('^' + EXPECTED_COOKIE.name + '$')
await b.driver.manage().deleteAllCookies() await browser.driver.manage().deleteAllCookies()
let cookies = await b.driver.manage().getCookies() let cookies = await browser.driver.manage().getCookies()
t.is(cookies.length, 0, 'should no cookie after deleteAllCookies()') t.is(cookies.length, 0, 'should no cookie after deleteAllCookies()')
await b.addCookie(EXPECTED_COOKIE) await browser.addCookie(EXPECTED_COOKIE)
const cookieFromBrowser = await b.driver.manage().getCookie(EXPECTED_COOKIE.name) const cookieFromBrowser = await browser.driver.manage().getCookie(EXPECTED_COOKIE.name)
t.is(cookieFromBrowser.name, EXPECTED_COOKIE.name, 'cookie from getCookie() should be same as we just set') t.is(cookieFromBrowser.name, EXPECTED_COOKIE.name, 'cookie from getCookie() should be same as we just set')
let cookiesFromCheck = await b.readCookie() let cookiesFromCheck = await browser.readCookie()
t.truthy(cookiesFromCheck.length, 'should get cookies from checkSession() after addCookies()') t.truthy(cookiesFromCheck.length, 'should get cookies from checkSession() after addCookies()')
let cookieFromCheck = cookiesFromCheck.filter(c => EXPECTED_NAME_REGEX.test(c['name'])) let cookieFromCheck = cookiesFromCheck.filter(c => EXPECTED_NAME_REGEX.test(c['name']))
t.is(cookieFromCheck[0]['name'], EXPECTED_COOKIE.name, 'cookie from checkSession() return should be same as we just set by addCookies()') t.is(cookieFromCheck[0]['name'], EXPECTED_COOKIE.name, 'cookie from checkSession() return should be same as we just set by addCookies()')
await b.saveCookie() await browser.saveCookie()
const cookiesFromSave = await b.readCookie() const cookiesFromSave = await browser.readCookie()
t.truthy(cookiesFromSave.length, 'should get cookies from saveSession()') t.truthy(cookiesFromSave.length, 'should get cookies from saveSession()')
const cookieFromSave = cookiesFromSave.filter(c => EXPECTED_NAME_REGEX.test(c['name'])) const cookieFromSave = cookiesFromSave.filter(c => EXPECTED_NAME_REGEX.test(c['name']))
t.is(cookieFromSave.length, 1, 'should has the cookie we just set') 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') 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 browser.driver.manage().deleteAllCookies()
cookiesFromCheck = await b.readCookie() cookiesFromCheck = await browser.readCookie()
t.is(cookiesFromCheck.length, 0, 'should no cookie from checkSession() after deleteAllCookies()') t.is(cookiesFromCheck.length, 0, 'should no cookie from checkSession() after deleteAllCookies()')
await b.loadCookie().catch(() => { /* fail safe */ }) await browser.loadCookie().catch(() => { /* fail safe */ })
const cookiesFromLoad = await b.readCookie() const cookiesFromLoad = await browser.readCookie()
t.truthy(cookiesFromLoad.length, 'should get cookies after loadSession()') t.truthy(cookiesFromLoad.length, 'should get cookies after loadSession()')
const cookieFromLoad = cookiesFromLoad.filter(c => EXPECTED_NAME_REGEX.test(c.name)) const cookieFromLoad = cookiesFromLoad.filter(c => EXPECTED_NAME_REGEX.test(c.name))
t.is(cookieFromLoad[0].name, EXPECTED_COOKIE.name, 'cookie from loadSession() should has expected cookie') t.is(cookieFromLoad[0].name, EXPECTED_COOKIE.name, 'cookie from loadSession() should has expected cookie')
cookiesFromCheck = await b.readCookie() cookiesFromCheck = await browser.readCookie()
t.truthy(cookiesFromCheck.length, 'should get cookies from checkSession() after loadSession()') t.truthy(cookiesFromCheck.length, 'should get cookies from checkSession() after loadSession()')
cookieFromCheck = cookiesFromCheck.filter(c => EXPECTED_NAME_REGEX.test(c['name'])) cookieFromCheck = cookiesFromCheck.filter(c => EXPECTED_NAME_REGEX.test(c['name']))
t.truthy(cookieFromCheck.length, 'should has cookie after filtered after loadSession()') t.truthy(cookieFromCheck.length, 'should has cookie after filtered after loadSession()')
t.is(cookieFromCheck[0]['name'], EXPECTED_COOKIE.name, 'cookie from checkSession() return should has expected cookie after loadSession') t.is(cookieFromCheck[0]['name'], EXPECTED_COOKIE.name, 'cookie from checkSession() return should has expected cookie after loadSession')
await b.quit() await browser.driver.quit()
t.pass('quited') t.pass('quited')
/** /**
...@@ -159,24 +159,24 @@ test('Browser Cookie save/load test', async t => { ...@@ -159,24 +159,24 @@ test('Browser Cookie save/load test', async t => {
* with the same sessionFile: profileName * with the same sessionFile: profileName
*/ */
b = new Browser({ browser = new Browser({
head: Config.head head: Config.head
, sessionFile: profileName , sessionFile: profileName
}) })
t.pass('should started a new Browser') t.pass('should started a new Browser')
b.state.target('open') browser.state.target('open')
await b.driver.init() await browser.driver.init()
t.pass('should inited the new Browser') t.pass('should inited the new Browser')
await b.open() await browser.open()
t.pass('should opened') t.pass('should opened')
await b.loadCookie() await browser.loadCookie()
t.pass('should loadSession for new Browser(process)') t.pass('should loadSession for new Browser(process)')
const cookieAfterQuit = await b.driver.manage().getCookie(EXPECTED_COOKIE.name) const cookieAfterQuit = await browser.driver.manage().getCookie(EXPECTED_COOKIE.name)
t.truthy(cookieAfterQuit, 'should get cookie from getCookie()') 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') t.is(cookieAfterQuit.name, EXPECTED_COOKIE.name, 'cookie from getCookie() after browser quit, should load the right cookie back')
...@@ -186,10 +186,10 @@ test('Browser Cookie save/load test', async t => { ...@@ -186,10 +186,10 @@ test('Browser Cookie save/load test', async t => {
} }
}) })
await b.quit() await browser.driver.quit()
} catch (e) { } catch (e) {
if (b) { if (browser) {
await b.quit() await browser.driver.quit()
} }
t.fail('exception: ' + e.message) t.fail('exception: ' + e.message)
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册