UNPKG

siesta-lite

Version:

Stress-free JavaScript unit testing and functional testing tool, works in NodeJS and browsers

159 lines (117 loc) 5.19 kB
/* Siesta 5.6.1 Copyright(c) 2009-2022 Bryntum AB https://bryntum.com/contact https://bryntum.com/products/siesta/license */ !function () { const child_process = require('child_process') const { LogLevel } = require('../src/generic/util/role/CanLog.js') const { NodeJsPageRpcFunctionCall } = require('../src/nodejs/launcher/NodeJsPageRpc') const { NodeJsPageParentEndPoint } = require('../src/nodejs/launcher/NodeJsPageRpcParent') Class('Siesta.Launcher.Page.NodeJS', { isa : Siesta.Launcher.Page.BasePage, does : [ ], has : { nodeJsProcess : null, channel : null }, methods : { openHarness : function (projectUrl, callback) { // avoid normalization to http url return this.SUPER(this.dispatcher.options[ 'project-url' ], callback) }, open : function (url, callback) { var me = this var options = me.dispatcher.options // prepare browser args var nodeJsArgs = options[ 'node-arg' ] || [] if (!(nodeJsArgs instanceof Array)) nodeJsArgs = [ nodeJsArgs ] var stdio = options[ 'isolate-console' ] ? 'ignore' : 'inherit' var inspect = options[ 'inspect' ] || options[ 'inspect-brk' ] let nodeJsProcess = me.nodeJsProcess = child_process.fork( process.argv[ 1 ], [ 'AS_CONNECTOR' ].concat(process.argv.slice(2)), { stdio : [ stdio, stdio, stdio, 'ipc' ], execArgv : nodeJsArgs.concat( inspect ? inspect instanceof Boolean ? '--inspect' : '--inspect=' + inspect : [] ) } ) nodeJsProcess.on('exit', () => { me.nodeJsProcess = null }) me.channel = new NodeJsPageParentEndPoint({ logLevel : LogLevel.debug }) me.channel.connect(nodeJsProcess).then(() => { // in debugging mode, the inspector need some time to "attach" to external debugging UI, // so we wait 300ms by default // otherwise, some of the `debugger` breakpoints can be ignored // https://github.com/nodejs/node/issues/25215 return !inspect ? Promise.resolve() : new Promise(resolve => setTimeout(resolve, options[ 'inspect-delay' ] || 300)) }).then( () => callback(), e => callback(e) ) }, gracefullyKillDuring : function (subProcess, timeout) { return new Promise(resolve => { subProcess.once('exit', () => { clearTimeout(handler) resolve() }) subProcess.kill('SIGTERM') var handler = setTimeout(() => { subProcess.kill('SIGKILL') setTimeout(resolve, 10) }, timeout) }) }, close : function () { this.channel.disconnect() var nodeJsProcess = this.nodeJsProcess // child process has already exit if (!nodeJsProcess) return this.SUPER() var me = this var options = me.dispatcher.options var inspect = options[ 'inspect' ] || options[ 'inspect-brk' ] if (inspect) { // in debugging mode, need to make sure previous nodejs processes have been closed // otherwise the debugger port will be busy and opening new session will fail // so we wait for `gracefullyKillDuring` promise to resolve return Promise.all([ this.SUPER(), this.gracefullyKillDuring(nodeJsProcess, 100) ]) } else { nodeJsProcess.kill('SIGTERM') // in normal mode, we just initiate the page close and return immediately, w/o waiting for close to complete return this.SUPER() } }, executeSmallScriptPromised : function (text, ignoreException) { var me = this return this.channel.sendRpcCall( new NodeJsPageRpcFunctionCall({ func : '(function() {' + text + '})' }).toJson() ).then( res => res, e => { if (!ignoreException) { me.print("<Exception from launcher>") me.print(" While running small script: " + text.substring(0, 150)) me.print(" Exception: " + e) me.print("</Exception from launcher>") return Promise.reject(e) } else return Promise.resolve(null) } ) } } // eof methods }) }();