守护程序不会在browser.end()后终止

我启动启动我的本地服务器的subprocess后运行Nightwatch。 Nightwatch运行testing,它们成功完成,浏览器窗口全部closures,但是在打印“确定”10个总断言通过之后, nightwatch进程继续运行。

我认为这可能与我如何看nightwatch过程中的事件有关,但据我所知,我正在观看所有可能表明守夜人正在退出的事件。

runner.js shutdown()方法永远不会被调用。 testing结束后,如何让Nightwatch终止?

更新

如果我删除sign-in.js中的最后一个testing,则Nightwatch按预期退出。

runner.js

 import spawn from 'cross-spawn' // 1. start the dev server using production config process.env.NODE_ENV = 'testing' let servers function shutdown (result) { console.log('HERE', result) try { // Passing a negative PID to kill will terminate all child processes, not just the parent if (servers) process.kill(-servers.pid) } catch (e) { console.error('Unable to shutdown servers, may need to be killed manually') } if (result) { console.error(result) process.exit(1) } else { process.exit(0) } } function watch (child) { child.on('close', shutdown) child.on('disconnect', shutdown) child.on('error', shutdown) child.on('exit', shutdown) child.on('uncaughtException', shutdown) } try { servers = spawn('yarn', ['run', 'dev-all'], { cwd: '..', stdio: 'inherit', detached: true }) watch(servers) // 2. run the nightwatch test suite against it // to run in additional browsers: // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings" // 2. add it to the --env flag below // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` // For more information on Nightwatch's config file, see // http://nightwatchjs.org/guide#settings-file var opts = process.argv.slice(2) if (opts.indexOf('--config') === -1) { opts = opts.concat(['--config', 'e2e/nightwatch.conf.js']) } if (opts.indexOf('--env') === -1) { opts = opts.concat(['--env', 'chrome']) } var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) watch(runner) watch(process) } catch (error) { shutdown(error) } 

nightwatch.conf.js

 require('babel-register') var config = require('../../frontend/config') // http://nightwatchjs.org/guide#settings-file module.exports = { src_folders: ['e2e/specs'], output_folder: 'e2e/reports', custom_assertions_path: ['e2e/custom-assertions'], selenium: { start_process: true, server_path: 'node_modules/selenium-server/lib/runner/selenium-server-standalone-3.0.1.jar', host: '127.0.0.1', port: 4444, cli_args: { 'webdriver.chrome.driver': require('chromedriver').path } }, test_settings: { default: { selenium_port: 4444, selenium_host: 'localhost', silent: true, globals: { devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port) } }, chrome: { desiredCapabilities: { browserName: 'chrome', javascriptEnabled: true, acceptSslCerts: true } }, firefox: { desiredCapabilities: { browserName: 'firefox', javascriptEnabled: true, acceptSslCerts: true } } } } 

sign-in.js (其中一个testing)

 import firebase from 'firebase-admin' import uuid from 'uuid' import * as firebaseSettings from '../../../backend/src/firebase-settings' const PASSWORD = 'toomanysecrets' function createUser (user) { console.log('Creating user', user.uid) let db = firebase.database() return Promise.all([ firebase.auth().createUser({ uid: user.uid, email: user.email, emailVerified: true, displayName: user.fullName, password: PASSWORD }), db.ref('users').child(user.uid).set({ email: user.email, fullName: user.fullName }), db.ref('roles').child(user.uid).set({ instructor: false }) ]) } function destroyUser (user) { if (!user) return console.log('Removing user', user.uid) let db = firebase.database() try { db.ref('roles').child(user.uid).remove() } catch (e) {} try { db.ref('users').child(user.uid).remove() } catch (e) {} try { firebase.auth().deleteUser(user.uid) } catch (e) {} } module.exports = { 'Sign In links exist': browser => { // automatically uses dev Server port from /config.index.js // default: http://localhost:8080 // see nightwatch.conf.js const devServer = browser.globals.devServerURL browser .url(devServer) .waitForElementVisible('#container', 5000) browser.expect.element('.main-nav').to.be.present browser.expect.element('.main-nav a[href^=\'https://oauth.ais.msu.edu/oauth/authorize\']').to.be.present browser.expect.element('.main-nav a[href^=\'/email-sign-in\']').to.be.present browser.end() }, 'Successful Sign In with Email shows dashboard': browser => { const devServer = browser.globals.devServerURL firebase.initializeApp(firebaseSettings.appConfig) let userId = uuid.v4() let user = { uid: userId, email: `${userId}@test.com`, fullName: 'Test User' } createUser(user) browser.url(devServer) .waitForElementVisible('.main-nav a[href^=\'/email-sign-in\']', 5000) .click('.main-nav a[href^=\'/email-sign-in\']') .waitForElementVisible('button', 5000) .setValue('input[type=text]', user.email) .setValue('input[type=password]', PASSWORD) .click('button') .waitForElementVisible('.main-nav a[href^=\'/sign-out\']', 5000) .end(() => { destroyUser(user) }) } } 

testing成功完成后,我看到以下内容:

 grimlock:backend egillespie$ ps -ef | grep nightwatch 501 13087 13085 0 1:51AM ttys000 0:02.18 node ./node_modules/.bin/nightwatch --presets es2015,stage-0 --config e2e/nightwatch.conf.js --env chrome 

我没有明确closuresFirebase连接。 这导致最后的testing无限期地挂起。

以下是我在做testing清理后如何closures连接:

 browser.end(() => { destroyUser(user).then(() => { firebase.app().delete() }) }) 

destroyUser函数现在看起来像这样:

 function destroyUser (user) { if (!user) return Promise.resolve() let db = firebase.database() return Promise.all([ db.ref('roles').child(user.uid).remove(), db.ref('users').child(user.uid).remove(), firebase.auth().deleteUser(user.uid) ]) }