Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

e2e-helper

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

e2e-helper - npm Package Compare versions

Comparing version 0.9.0 to 0.9.1

11

CHANGELOG.md

@@ -0,1 +1,12 @@

e2e-helper
==========
## 0.9.1
- allow better customization for cover mode
- add eslint definitions
## 0.9.0 - official release
predecessor:
mocha-e2e

@@ -2,0 +13,0 @@ ==========

266

lib/index.js
'use strict'
const assign = Object.assign
const {assign} = Object
const path = require('path')
const fs = require('fs')
const run = require('child_process').spawn
let log

@@ -13,3 +13,3 @@ const defaults =

, readyNotice : 'listening on port'
, console : console
, console
, args : []

@@ -20,19 +20,14 @@ , timeout : 10000

, term_timeout : 3000
, coverIgnore :
[ '**/test-e2e/**'
, '**/test/**'
]
, coverSvc : './node_modules/istanbul/lib/cli'
, coverArgs : ['cover', '--dir', './coverage/e2e-test', '--handle-sigint']
, coverIgnore : []
}
const coverArgs =
[ './node_modules/istanbul/lib/cli', 'cover'
, '--dir', './coverage/e2e-test'
, '--handle-sigint'
]
/**
returns a before-all mocha handler that setups the server with the provided
@description
returns a before-all mocha handler that setups the server with the provided
options.
while being called, it sets `e2e.teardown` with the matching teardown
while being called, it sets `e2e.teardown` with the matching teardown
function that shuts down the service gracefully.

@@ -43,6 +38,6 @@

@param {string|object} options - when provided as string - it's understood as `options.svc`
@param {string} options.svc - system under test - path to the script that
@param {string} options.svc - system under test - path to the script that
runs the target server
@param {string} options.logPath - path to log file
@param {string} options.readyNotice - output line expected on stdout of
@param {string} options.readyNotice - output line expected on stdout of
the started service that indicates that the service is ready

@@ -66,5 +61,5 @@ @param {array} options.args - args to concat to the node command

e2e.internal =
{ initCtx : initCtx
, setup : setup
, teardown : teardown
{ initCtx
, setup
, teardown
}

@@ -78,22 +73,24 @@

ctx_teardown
return ctx_setup
//TRICKY: these must be 'oldschool' functions - mocha relays on the `this` keyword
function ctx_setup (done) { setup (ctx, this, done) }
function ctx_setup(done) { setup(ctx, this, done) }
function ctx_teardown(done) { teardown(ctx, this, done) }
}
function mocha_bdd(options) {
const console = options.console || global.console
describe(
function mocha_functions_api(options, {suite, setup, teardown, console = options.console || global.console}) {
suite(
options.title || defaults.title
, () => {
process.env.SUT
? console.log('test target: ', process.env.SUT)
: [ before(e2e(options)), after(e2e.teardown) ]
if (process.env.SUT) {
console.log('test target: ', process.env.SUT)
} else {
setup(e2e(options))
teardown(e2e.teardown)
}
options.suites
.map( p => path.resolve(p) )
.forEach(global.require /* istanbul ignore next */ || require)
.forEach(global.require /* istanbul ignore next */|| require)
}

@@ -103,14 +100,16 @@ )

function mocha_bdd(options) {
mocha_functions_api(options
, { suite: global.describe
, setup: global.before
, teardown: global.after
}
)
}
function mocha_tdd(options) {
const console = options.console || global.console
suite(
options.title || defaults.title
, () => {
process.env.SUT
? console.log('test target: ', process.env.SUT)
: [ suiteSetup(e2e(options)), suiteteardown(e2e.teardown) ]
options.suites
.map( p => path.resolve(p) )
.forEach(global.require /* istanbul ignore next */|| require)
mocha_functions_api(options
, { suite: global.suite
, setup: global.suiteSetup
, teardown: global.suiteTeardown
}

@@ -125,10 +124,11 @@ )

const suite = {}
process.env.SUT
? console.log('test target: ', process.env.SUT)
: Object.assign(suite, {
beforeAll: e2e(options),
afterAll: e2e.teardown
})
: Object.assign(suite
, { beforeAll: e2e(options)
, afterAll: e2e.teardown
}
)
options.suites.forEach(

@@ -138,5 +138,5 @@ endpointTest =>

)
res[ options.title || defaults.title ] = suite
return res

@@ -146,37 +146,37 @@ }

function initCtx(options) {
let msg
if ('object' != typeof options) options = { svc: options }
options = assign({}, defaults, options)
options.args = options.args.concat()
msg = (
!options.svc && ('options.svc is not provided')
|| 'string' != typeof options.svc && ('options.svc must be a string')
|| 'string' != typeof options.cwd && ('options.cwd must be a string')
|| !fs.existsSync(options.cwd) && (options.cwd + ' is not found on disk')
|| !isFileFound(path.join(options.cwd, options.svc))
&& (options.svc + ' is not found on disk')
|| !options.logPath && ('options.logPath is expected to be a path')
|| 'string' != typeof options.logPath && ('options.logPath is expected to be a path')
|| !options.readyNotice && ('options.readyNotice must be a string')
|| 'string' != typeof options.readyNotice && ('options.readyNotice must be a string')
|| !Array.isArray(options.args) && ('options.args must be an array')
|| 'number' != typeof options.timeout && ('options.timeout must be a number')
|| 'number' != typeof options.slow && ('options.slow must be a number')
|| options.env
&& 'object' != typeof options.env && ('options.env, when provided must be an object')
options.coverArgs = options.coverArgs.concat()
const stringArray = (arr) => Array.isArray(arr) && !arr.find(s => 'string' != typeof s)
const targetSvc = path.join(String(options.cwd), String(options.svc))
const msg =
!options.svc && 'options.svc is not provided'
|| 'string' != typeof options.svc && 'options.svc must be a string'
|| 'string' != typeof options.cwd && 'options.cwd must be a string'
|| !fs.existsSync(options.cwd) && options.cwd + ' is not found on disk'
|| !isFileFound(targetSvc) && options.svc + ' is not found on disk'
|| !options.logPath && 'options.logPath is expected to be a path'
|| 'string' != typeof options.logPath && 'options.logPath is expected to be a path'
|| !options.readyNotice && 'options.readyNotice must be a string'
|| 'string' != typeof options.readyNotice && 'options.readyNotice must be a string'
|| !Array.isArray(options.args) && 'options.args must be an array'
|| 'number' != typeof options.timeout && 'options.timeout must be a number'
|| 'number' != typeof options.slow && 'options.slow must be a number'
|| options.env
&& 'object' != typeof options.env && 'options.env, when provided must be an object'
|| !( 'number' == typeof options.term_timeout
&& 0 < options.term_timeout
) && ('options.term_timeout, when provided - must be a positive number')
|| !~['SIGTERM','SIGINT','SIGQUIT',
'SIGKILL','SIGHUP'
].indexOf(options.term_code) && ('options.term_code, when provided - must be a valid process signal')
|| options.coverIgnore
&& ( !Array.isArray(options.coverIgnore)
|| options.coverIgnore.find(s => 'string' != typeof s)
) && ('options.coverIgnore, when provided - must be an array of glob pattern strings')
)
&& 0 < options.term_timeout
) && 'options.term_timeout, when provided - must be a positive number'
|| !~[ 'SIGTERM', 'SIGINT', 'SIGQUIT'
, 'SIGKILL', 'SIGHUP'
].indexOf(options.term_code) && 'options.term_code, when provided - must be a valid process signal'
|| 'string' != typeof options.coverSvc && 'options.svc, when provided - must be path node CLI script, such as istanbul'
|| !stringArray(options.coverArgs) && 'options.coverArgs, when provided - must be an array of CLI arguments'
|| !stringArray(options.coverIgnore) && 'options.coverIgnore, when provided - must be an array of glob pattern strings'
if (msg) throw assign(

@@ -189,15 +189,21 @@ new Error(

, " if you need to provide an absolute path - you may use .cwd as the absolute path"
, " when options is string - it is uderstood as options.svc"
, " when options is string - it is uderstood as options.svc, applying defaults to all the rest"
, " - cwd - string, optional - the work directory the process should run in. defaults to current dir"
, " - logPath - string, optional - path to logfile. default: './e2e.log'"
, " - timeout - integer, optional - timeout for server setup"
, " - slow - integer, optional - slow bar indicator for server setup"
, " - timeout - integer, optional - timeout for server setup, default: " + defaults.timeout
, " - slow - integer, optional - slow bar indicator for server setup, default: " + defaults.timeout
, " - readyNotice - string, optional - message to expect on service output that"
, " indicates the service is ready. default: 'listening on port'"
, " - args - array, argumnets to be concatenated to the running command"
, " - cwd - string, optional - the work directory the process should run in"
, " - term_code - string, optional, the termination message to send to the child, default: SIGTERM"
, " - term_ipc - optional, any value provided will be used to child.send(term_ipc) before escalating to child.kill(term_code)"
, " indicates the service is ready. default: " + defaults.readyNotice
, " - args - array, optional, argumnets to be concatenated to the running command"
, " - term_code - string, optional, the termination message to send to the child, default: " + defaults.term_code
, " - term_ipc - optional, any value provided will be used to child.send(term_ipc) before escalating"
, " to term-code. When not provided - starts with term-code"
, " - term_timeout - optional, number, timeout in miliseconds before escalations( ipc->term->kill)"
, " - coverIgnore - optional, array of glob-pattern strings"
, "reason: ",
, " default: " + defaults.term_timeout
, " - coverSvc - optional, path to cover-tool node-script which should run .svc to gather coverage"
, " default: " + defaults.coverSvc
, " - coverArgs - optional, array of CLI arguments to the cover tool"
, " default: " + JSON.stringify(defaults.coverArgs)
, " - coverIgnore - optional, array of glob-pattern strings for files to exclude from coverage"
, "reason: "
, " " + msg

@@ -208,9 +214,8 @@ ].join('\n')

)
if (process.env.COVER) {
const args = coverArgs.concat()
const ignore = options.coverIgnore
const args = [options.coverSvc].concat(options.coverArgs)
options.coverIgnore.forEach((pattern) => args.push('-x', pattern))
args.push(

@@ -221,5 +226,5 @@ options.svc.match(/\.js$/)

)
options.args =
options.args.length
options.args =
options.args.length
? args.concat(['--'], options.args)

@@ -232,5 +237,5 @@ : args

return options
function isFileFound(path) {
return fs.existsSync(path)
return fs.existsSync(path)
|| fs.existsSync(path + '.js')

@@ -241,13 +246,13 @@ }

/**
@param {object} options
@param {string} options.sut - system under test - path to the script that
@param {object} ctx - context
@param {string} ctx.sut - system under test - path to the script that
runs the target server
@param {string} options.logPath - path to log file
@param {string} options.readyNotice - output line expected on stdout of
@param {string} ctx.logPath - path to log file
@param {string} ctx.readyNotice - output line expected on stdout of
the started target service that indicates that the service is running
@param {mocha.Test} test - the test context that implements .timetout(n), .slow(n) ....
@param {callback} callback
@param {callback} done - callback
@returns {undefined}
*/
function setup(ctx, test, done) {
try { fs.unlinkSync( ctx.logPath ) } catch(e) {}

@@ -261,15 +266,19 @@

fs.createWriteStream(ctx.logPath, { flags: 'a'} )
log.writable = true
const writeLog = (...args) => log.writable && log.write.apply(log, args)
const child =
ctx.child =
run(process.execPath, ctx.args, {
env: assign({}, process.env, ctx.env || {}),
cwd: ctx.cwd,
stdio: ['pipe','pipe', 'pipe', 'ipc']
})
run(process.execPath, ctx.args
, { env: assign({}, process.env, ctx.env || {})
, cwd: ctx.cwd
, stdio: ['pipe', 'pipe', 'pipe', 'ipc']
}
)
/* istanbul ignore next */
child.on('error', (err) => {
if (log.writable) log.write('ERR: ', err)
writeLog('ERR: ', err)
done(err)

@@ -279,11 +288,12 @@ })

child.stderr.on('data', (data) => {
data = data + ''
if (log.writable) log.write('ERR: ' + data)
if (~data.indexOf('Error: listen EADDRINUSE'))
done(new Error('Server could not start: Address In Use'))
data = data.toString()
/* istanbul ignore if */
writeLog('ERR: ' + data)
if (~data.indexOf('Error: listen EADDRINUSE')) done(new Error('Server could not start: Address In Use'))
})
child.stdout.on('data', function(data) {
child.stdout.on('data', (data) => {
data = data.toString()
if (log.writable) log.write(data)
writeLog(data)

@@ -295,8 +305,8 @@ if (~data.indexOf(ctx.readyNotice)) {

})
child.on('exit', function(e) {
child.on('exit', (e) => {
child.exitted = true
ctx.console.log('\n\nservice termination ended', e || 'OK')
ctx.log.writable = false
ctx.log.end(function() {
ctx.log.end(() => {
child.emit('--over--')

@@ -308,5 +318,9 @@ })

/**
@param {callback} callback
@param {object} ctx - the context
@param {mocha.Test} test - the Test object
@param {callback} done - callback
@returns {undefined}
*/
function teardown(ctx, test, done) {
/* istanbul ignore if */
if (ctx.child.exitted) return done()

@@ -316,3 +330,3 @@ test.slow(ctx.term_timeout * 1.5)

ctx.child.on('--over--', done)
ctx.child.on('--over--', done)
ctx.term_ipc

@@ -328,3 +342,3 @@ ? ipc()

function term() {
ctx.child.kill(ctx.term_code)
ctx.child.kill(ctx.term_code)
setTimeout(kill, ctx.term_timeout)

@@ -336,2 +350,2 @@ }

}
}
}
{
"name": "e2e-helper",
"version": "0.9.0",
"version": "0.9.1",
"description": "end-to-end test helper, with facilitators for mocha",
"main": "lib",
"scripts": {
"test": "mocha",
"cover": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot",
"postcover": "npm run cover-enforce",
"cover-enforce": "node node_modules/istanbul/lib/cli.js check-coverage --function 90 --lines 90 --branches 90 --statements 90"
},
"repository": {

@@ -28,2 +22,4 @@ "type": "git",

"devDependencies": {
"coveralls": "^3.0.0",
"eslint": "^4.15.0",
"istanbul": "*",

@@ -33,3 +29,10 @@ "mocha": "~2.3.4",

"should": "^9.0.0"
},
"scripts": {
"test": "mocha",
"cover": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot",
"postcover": "npm run cover-enforce",
"cover-enforce": "node node_modules/istanbul/lib/cli.js check-coverage --function 90 --lines 90 --branches 90 --statements 90",
"coveralls": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- --reporter dot && cat coverage/lcov.info | coveralls --verbose"
}
}

@@ -15,2 +15,3 @@ # e2e-helper

- [![Build Status](https://secure.travis-ci.org/osher/e2e-helper.png?branch=master)](http://travis-ci.org/osher/e2e-helper) Tested on latests node versions of 6,7,8
- [![Coverage Status](https://coveralls.io/repos/github/osher/e2e-helper/badge.svg?branch=master)](https://coveralls.io/github/osher/e2e-helper?branch=master)

@@ -69,18 +70,21 @@ # Features list:

- `svc` - string, mandatory, should be relative path. a path to the script that starts the service.
if you need to provide an absolute path - you may use .cwd as the absolute path
when options is string - it is uderstood as options.svc
- `logPath` - string, optional - path to logfile. default: './e2e.log'
- `timeout` - integer, optional - timeout for server setup
- `slow` - integer, optional - slow bar indicator for server setup
if you need to provide an absolute path - you may use `.cwd` to provide the absolute path
when options is string - it is uderstood as options.svc, applying defaults to all the rest
- `cwd` - string, optional - the work directory the process should run in. defaults to current dir
- `logPath` - string, optional - path to logfile. default: `'./e2e.log'`
- `timeout` - integer, optional - timeout for server setup, default: `10000`
- `slow` - integer, optional - slow bar indicator for server setup, default: `10000`
- `readyNotice` - string, optional - message to expect on service output that
indicates the service is ready. default: 'listening on port'
- `args` - array, argumnets to be concatenated to the running command
- `cwd` - string, optional - the work directory the process should run in
- `term_code` - string, optional, the termination message to send to the child, default: SIGTERM
- `term_ipc` - optional, any value provided will be used to child.send(term_ipc) before escalating to child.kill(term_code)
indicates the service is ready. default: `'listening on port'`
- `args` - array, optional, argumnets to be concatenated to the running command
- `term_code` - string, optional, the termination message to send to the child, default: `'SIGINT'`
- `term_ipc` - optional, any value provided will be used to child.send(term_ipc) before escalating
to term-code. When not provided - starts with term-code
- `term_timeout` - optional, number, timeout in miliseconds before escalations( ipc->term->kill)
- `coverIgnore` - optional, array of glob-pattern strings to exclude from cover tool, meaningful only for istanbul COVER mode
on top of that list, the higher facilitators accept as well
- `title` - string - the root level test title
default: `3000`
- `coverSvc` - optional, path to cover-tool node-script which should run `.svc` to gather coverage
default: `'./node_modules/istanbul/lib/cli'`
- `coverArgs` - optional, array of CLI arguments to the cover tool
default: `["cover","--dir","./coverage/e2e-test","--handle-sigint"]`
- `coverIgnore` - optional, array of glob-pattern strings for files to exclude from coverage

@@ -176,3 +180,3 @@ ## with mocha

There may be edge-cases with cover mode on windows - that's the only part I'm yet to be satisfied with.
I don't expect API changes for fixing any of these might-be issues.
I don't expect API changes for fixing any of these issues.

@@ -182,4 +186,3 @@ # Contribute

- if you add functionality - add tests :)
- don't really worry much about the style...
I hope it doesn't freak you out (it just might if you're using IDE)
- don't worry about the style. I tried to add eslint to help with that, although it's not bullet-proof.
If I'll really need to - I'll ask you to permit me on your fork, I'll help as best I can with styles or with anything else :)

@@ -186,0 +189,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc