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

codeceptjs

Package Overview
Dependencies
Maintainers
1
Versions
235
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

codeceptjs - npm Package Compare versions

Comparing version 0.3.5 to 0.4.0

lib/helper/clientscripts/nightmare.js

1

bin/codecept.js

@@ -57,2 +57,3 @@ #!/usr/bin/env node

.option('--debug', 'output additional information')
.option('--verbose', 'output internal logging information')

@@ -59,0 +60,0 @@ // mocha options

@@ -0,1 +1,11 @@

## 0.4.0
* **Nightmare Helper** added [http://codecept.io/nightmare] for faster web testing.
* [Protractor][SeleniumWebdriver][WebDriverIO] added `restart: false` option to reuse one browser between tests
* **Protractor 4.0** compatibility. Please upgrade Protractor library.
* Added `--verbose` option for `run` command to log and print global promise and events.
* Fixed errors with shutting down and cleanup.
* Fixed starting interactive shell with `codeceptjs shell`.
* Fixed handling of failures inside within block
## 0.3.5

@@ -2,0 +12,0 @@

8

lib/codecept.js

@@ -13,3 +13,3 @@ 'use strict';

let fileExists = require('./utils').fileExists;
const scenarioUi = fsPath.join(__dirname, './interfaces/codeceptjs.js');
const scenarioUi = fsPath.join(__dirname, './interfaces/bdd.js');

@@ -23,3 +23,3 @@ class Codecept {

this.mocha.ui(scenarioUi);
if (opts.reporter) {
if (opts.reporter) {
// custom reporters

@@ -68,5 +68,5 @@ this.mocha.reporter(opts.reporter, opts.reporterOptions);

this.mocha.run(() => {
event.dispatcher.emit(event.all.result, this);
event.emit(event.all.result, this);
});
}

@@ -73,0 +73,0 @@

@@ -18,6 +18,6 @@ 'use strict';

recorder.start();
recorder.finishHandler(() => event.dispatcher.emit(event.test.teardown));
event.dispatcher.emit(event.test.setup);
recorder.finishHandler(() => event.emit(event.test.teardown));
event.emit(event.test.setup);
require('../pause')();
recorder.finalize();
};

@@ -19,9 +19,16 @@ 'use strict';

module.exports.getConfig = function (testsPath) {
let configFile = path.join(testsPath, 'codecept.json');
if (!fileExists(configFile)) {
output.error(`Can not load config from ${configFile}\nCodeceptJS is not initialized in this dir. Execute 'codeceptjs init' to start`);
module.exports.getConfig = function (testRoot) {
let config,
jsConfigFile = path.join(testRoot, 'codecept.js'),
jsonConfigFile = path.join(testRoot, 'codecept.json');
if (fileExists(jsConfigFile)) {
config = require(jsConfigFile).config;
} else if (fileExists(jsonConfigFile)) {
config = JSON.parse(fs.readFileSync(jsonConfigFile, 'utf8'));
} else {
output.error(`Can not load config from ${jsConfigFile} or ${jsonConfigFile}\nCodeceptJS is not initialized in this dir. Execute 'codeceptjs init' to start`);
process.exit(1);
}
let config = JSON.parse(fs.readFileSync(configFile, 'utf8'));
if (!config.include) config.include = {};

@@ -28,0 +35,0 @@ if (!config.helpers) config.helpers = {};

var events = require('events');
var dispatcher = new events.EventEmitter();
var log = require('./output').log;

@@ -26,2 +27,11 @@ module.exports = {

},
emit: function(event, param) {
var msg = 'Emitted | '+event;
if (param && param.toString()) {
msg += ` (${param.toString()})`;
}
log(msg);
this.dispatcher.emit.apply(this.dispatcher, arguments);
},
// for testing only!

@@ -28,0 +38,0 @@ cleanDispatcher: () => {

@@ -58,2 +58,11 @@ 'use strict';

/**
* Hook executed after each failed test
*
* @param test
*/
_failed() {
}
/**
* Hook executed before each step

@@ -77,2 +86,20 @@ *

/**
* Hook executed before each suite
*
* @param suite
*/
_beforeSuite() {
}
/**
* Hook executed after each suite
*
* @param suite
*/
_afterSuite() {
}
/**
* Access another configured helper: `this.helpers['AnotherHelper']`

@@ -79,0 +106,0 @@ */

@@ -42,2 +42,3 @@ 'use strict';

* * `driver` - which protrator driver to use (local, direct, session, hosted, sauce, browserstack). By default set to 'hosted' which requires selenium server to be started.
* * `restart` - restart browser between tests (default: true), if set to false cookies will be cleaned but browser window will be kept.
* * `seleniumAddress` - Selenium address to connect (default: http://localhost:4444/wd/hub)

@@ -85,7 +86,6 @@ * * `rootElement` - Root element of AngularJS application (default: body)

}
protractorWrapper = requireg('protractor').wrapDriver;
EC = requireg('protractor').ExpectedConditions;
protractorWrapper = requireg('protractor').Browser.wrapDriver;
EC = requireg('protractor').Browser.ExpectedConditions;
global.by = requireg('protractor').Browser.By;
global.by = requireg('protractor').By;
global.element = requireg('protractor').element;
let driverProviderModule = requireg('protractor/built/driverProviders/'+this.options.driver);

@@ -101,5 +101,6 @@ let className = Object.keys(driverProviderModule)[0];

requireg("protractor");
require('assert').ok(requireg("protractor").Browser);
require('assert').ok(requireg("protractor/built/driverProviders/hosted").Hosted);
} catch(e) {
return ["protractor@^3.3.0"];
return ["protractor@^4.0.0"];
}

@@ -117,4 +118,10 @@ }

_startBrowser() {
this.browser = this.driverProvider.getNewDriver();
global.element = this.browser.element;
return this.browser;
}
_before() {
this.browser = this.driverProvider.getNewDriver();
super._before();
this.amInsideAngularApp();

@@ -125,6 +132,2 @@ this.context = this.options.rootElement;

_after() {
return this.browser.quit();
}
_withinBegin(locator) {

@@ -140,5 +143,5 @@ withinStore.elFn = this.browser.findElement;

this.browser.findElements = (l) => context.all(l).getWebElements();
return;
return context;
}
super._withinBegin(locator);
return super._withinBegin(locator);
}

@@ -170,2 +173,3 @@

if (this.browser.driver && this.insideAngular) {
console.log(this.browser.driver);
this.browser = this.browser.driver;

@@ -172,0 +176,0 @@ this.insideAngular = false;

@@ -44,2 +44,3 @@ 'use strict';

* * `driver` - which protrator driver to use (local, direct, session, hosted, sauce, browserstack). By default set to 'hosted' which requires selenium server to be started.
* * `restart` - restart browser between tests (default: true), if set to false cookies will be cleaned but browser window will be kept.
* * `seleniumAddress` - Selenium address to connect (default: http://localhost:4444/wd/hub)

@@ -67,2 +68,3 @@ * * `waitForTimeout`: (optional) sets default wait time in _ms_ for all `wait*` functions. 1000 by default;

seleniumAddress: 'http://localhost:4444/wd/hub',
restart: true,
waitforTimeout: 1000, // ms

@@ -106,10 +108,31 @@ capabilities: {}

_startBrowser() {
this.browser = this.browserBuilder.build();
return this.browser;
}
_beforeSuite() {
if (!this.options.restart) {
this.debugSection('Session','Starting singleton browser session');
return this._startBrowser();
}
}
_before() {
return this.browser = this.browserBuilder.build();
if (this.options.restart) return this._startBrowser();
}
_after() {
return this.browser.quit();
if (this.options.restart) return this.browser.quit();
// if browser should not be restarted
this.debugSection('Session', 'cleaning cookies and localStorage');
return this.browser.executeScript('localStorage.clear();').then(() => {
return this.browser.manage().deleteAllCookies();
})
}
_afterSuite() {
if (!this.options.restart) return this.browser.quit();
}
_failed(test) {

@@ -129,2 +152,3 @@ let fileName = test.title.replace(/ /g, '_') + '.failed.png';

this.browser.findElements = (l) => context.findElements(l);
return context;
}

@@ -325,4 +349,3 @@

*/
seeCheckboxIsChecked(field)
{
seeCheckboxIsChecked(field) {
return co.wrap(proceedIsChecked).call(this, 'assert', field);

@@ -540,3 +563,3 @@ }

clearCookie(cookie) {
if (cookie) {
if (!cookie) {
return this.browser.manage().deleteAllCookies();

@@ -543,0 +566,0 @@ }

@@ -41,5 +41,6 @@ 'use strict';

* * `browser` - browser in which perform testing
* * `restart` - restart browser between tests (default: true), if set to false cookies will be cleaned but browser window will be kept.
* * `windowSize`: (optional) default window size. Set to `maximize` or a dimension in the format `640x480`.
* * `waitForTimeout`: (optional) sets default wait time in *ms* for all `wait*` functions. 1000 by default;
* * `desiredCapabilities`:
* * `desiredCapabilities`: Selenium capabilities
*

@@ -174,3 +175,4 @@ *

waitforTimeout: 1000, // ms
desiredCapabilities: {}
desiredCapabilities: {},
restart: true
};

@@ -218,4 +220,10 @@

_before() {
this.failedTestName = null;
_beforeSuite() {
if (!this.options.restart) {
this.debugSection('Session','Starting singleton browser session');
return this._startBrowser();
}
}
_startBrowser() {
if (this.options.multiremote) {

@@ -234,2 +242,8 @@ this.browser = webdriverio.multiremote(this.options.multiremote);

}
return this.browser;
}
_before() {
if (this.options.restart) this._startBrowser();
this.failedTestName = null;
this.context = 'body';

@@ -240,5 +254,13 @@ return this.browser;

_after() {
return this.browser.end();
if (this.options.restart) return this.browser.end();
this.debugSection('Session', 'cleaning cookies and localStorage');
return this.browser.execute('localStorage.clear();').then(() => {
return this.browser.deleteCookie();
});
}
_afterSuite() {
if (!this.options.restart) return this.browser.end();
}
_failed(test) {

@@ -282,2 +304,41 @@ let fileName = test.title.replace(/ /g, '_') + '.failed.png';

/**
* Find a checkbox by providing human readable text:
*
* ```js
* this.helpers['WebDriverIO']._locateCheckable('I agree with terms and conditions').then // ...
* ```
*/
_locateCheckable(locator) {
return findCheckable(this.browser, locator).then(function(res){
return res.value;
})
}
/**
* Find a clickable element by providing human readable text:
*
* ```js
* this.helpers['WebDriverIO']._locateClickable('Next page').then // ...
* ```
*/
_locateClickable(locator) {
return findClickable(this.browser, locator).then(function(res){
return res.value;
})
}
/**
* Find field elements by providing human readable text:
*
* ```js
* this.helpers['WebDriverIO']._locateFields('Your email').then // ...
* ```
*/
_locateFields(locator) {
return findFields(this.browser, locator).then(function(res){
return res.value;
})
}
/**
* {{> ../webapi/amOnPage }}

@@ -837,3 +898,3 @@ */

* Drag an item to a destination element.
*
* ```js

@@ -879,4 +940,3 @@ * I.dragAndDrop('#dragHandle', '#container');

context = context || 'body';
return this.browser
.waitUntil(function () {
return this.browser.waitUntil(function () {
return this.getText(context).then(function (source) {

@@ -890,3 +950,3 @@ if (Array.isArray(source)) {

.catch((e) => {
if (e.type === 'CommandError') {
if (e.type === 'WaitUntilTimeoutError') {
return proceedSee.call(this, 'assert', text, context);

@@ -1102,3 +1162,3 @@ } else {

case 'id': return '#' + value;
case 'name': return `[name="value"]`;
case 'name': return `[name="${value}"]`;
}

@@ -1105,0 +1165,0 @@ }

@@ -19,3 +19,3 @@ 'use strict';

debug(`${key}.${hook}`);
recorder.add(() => helpers[key][hook](param), force);
recorder.add(`hook ${key}.${hook}()`, () => helpers[key][hook](param), force);
});

@@ -28,2 +28,10 @@ };

event.dispatcher.on(event.suite.before, function () {
runHelpersHook('_beforeSuite');
});
event.dispatcher.on(event.suite.after, function () {
runAsyncHelpersHook('_afterSuite');
});
event.dispatcher.on(event.test.before, function () {

@@ -35,2 +43,4 @@ runAsyncHelpersHook('_before');

runAsyncHelpersHook('_failed', test, true);
// should not fail test execution, so errors should be catched
recorder.catch((e) => debug(e));
});

@@ -37,0 +47,0 @@

@@ -18,2 +18,8 @@ 'use strict';

event.dispatcher.on(event.test.failed, function () {
// last step is failing step
if (!steps.length) return;
steps.slice(-1)[0].status = 'failed';
});
event.dispatcher.on(event.step.before, function (step) {

@@ -20,0 +26,0 @@ if (!currentTest || !currentTest.steps) return;

@@ -12,3 +12,4 @@ 'use strict';

basic: colors.white,
debug: colors.cyan
debug: colors.cyan,
log: colors.grey
};

@@ -29,5 +30,10 @@

debug: (msg) => {
if (outputLevel === 2) print(' '.repeat(this.stepShift), styles.debug("> " + msg));
if (outputLevel >= 2) print(' '.repeat(this.stepShift), styles.debug("> " + msg));
},
log: (msg) => {
if (outputLevel >= 3) print(' '.repeat(this.stepShift), styles.log(" " + msg));
},
error: (msg) => {

@@ -43,2 +49,3 @@ print(styles.error(msg));

if (outputLevel === 0) return;
if (!step) return;
let sym = process.platform === 'win32' ? '*' : '•';

@@ -45,0 +52,0 @@ print(' '.repeat(this.stepShift), `${sym} ${step.toString()}`);

@@ -17,4 +17,4 @@ 'use strict';

module.exports = function () {
recorder.add(function () {
recorder.session.start();
recorder.add('Start new session' ,function () {
recorder.session.start('pause');
output.print(colors.yellow(" Interative debug session started"));

@@ -54,3 +54,3 @@ output.print(colors.yellow(" Use JavaScript syntax to try steps in action"));

});
recorder.add(askForStep);
recorder.add('ask for next step', askForStep);
nextStep();

@@ -57,0 +57,0 @@ }

@@ -7,3 +7,8 @@ 'use strict';

let next;
let queueId = 0;
let sessionId = null;
let log = require('./output').log;
let tasks = [];
/**

@@ -13,2 +18,3 @@ * Singlton object to record all test steps as promises and run them in chain.

module.exports = {
start() {

@@ -26,8 +32,20 @@ running = true;

if (promise && running) this.catch();
queueId++;
sessionId = null;
log(currentQueue() + `Starting recording promises`);
promise = Promise.resolve();
oldpromise = null;
tasks = [];
this.session.running = false;
},
session: {
start(errFn) {
running: false,
start(name) {
log(currentQueue() + `Starting <${name}> session`);
tasks.push('--->');
oldpromise = promise;
this.running = true;
sessionId = name;
promise = Promise.resolve();

@@ -37,2 +55,6 @@ },

restore() {
tasks.push('<---');
log(currentQueue() + `Starting <${this.name}> session`);
this.running = false;
sessionId = null;
promise = promise.then(() => oldpromise);

@@ -47,6 +69,12 @@ },

add(fn, force) {
add(taskName, fn, force) {
if (typeof taskName === "function") {
fn = taskName;
taskName = fn.toString();
}
if (!running && !force) {
return;
}
tasks.push(taskName);
log(currentQueue() + `Queued | ${taskName}`);
return promise = promise.then(fn);

@@ -56,8 +84,15 @@ },

addStep(step, args) {
this.add(() => step.run.apply(step, args));
step.status = 'queued';
let task = `${step.name}: ${Object.keys(args).map(key => args[key]).join(', ')}`;
this.add(task, () => step.run.apply(step, args));
},
catch() {
catch(customErrFn) {
return promise = promise.catch((err) => {
if (errFn) errFn(err);
log(currentQueue() + `Error | ${err}`);
if (customErrFn) {
customErrFn(err);
} else if (errFn) {
errFn(err);
}
this.stop();

@@ -68,3 +103,3 @@ });

throw(err) {
return this.add(function () {
return this.add('throw error ' + err,function () {
throw err;

@@ -74,3 +109,5 @@ });

stop() {
stop() {
log(currentQueue() + `Stopping recording promises`);
var err = new Error();
running = false;

@@ -81,3 +118,19 @@ },

return promise;
},
scheduled() {
return tasks.join("\n");
},
toString() {
return `Queue: ${currentQueue()}\n\nTasks: ${this.scheduled()}`;
}
};
function currentQueue() {
let session = '';
if (sessionId) session = `<${sessionId}> `;
return `[${queueId}] ${session}`;
}

@@ -18,4 +18,6 @@ 'use strict';

let level = 0;
if (opts.steps) level = 1;
if (opts.debug) level = 2;
if (opts.steps) level = 1;
if (opts.verbose) level = 3;
output.level(level);

@@ -29,3 +31,2 @@ let showSteps = level >= 1;

runner.on('start', function () {

@@ -32,0 +33,0 @@ console.log();

@@ -20,9 +20,10 @@ 'use strict';

test.fn = function (done) {
recorder.errHandler(function (err){
event.dispatcher.emit(event.test.failed, test, err);
recorder.add(() => done(err), true);
recorder.errHandler(function (err) {
recorder.session.start('teardown');
event.emit(event.test.failed, test, err);
recorder.add(() => done(err));
});
try {
event.dispatcher.emit(event.test.started, test);
event.emit(event.test.started, test);
let res = testFn.apply(test, getInjectedArguments(testFn));

@@ -38,8 +39,8 @@ if (isGenerator(testFn)) {

let resumeTest = function () {
recorder.add(function (data) {
recorder.reset(); // creating a new promise chain
recorder.add('create new promises queue for generator',function (data) {
recorder.session.start('generator'); // creating a new promise chain
try {
let resume = res.next(data);
if (resume.done) {
recorder.add(() => done()); // finish him
recorder.add('finish generator with no error', () => done()); // finish him
} else {

@@ -60,3 +61,3 @@ resumeTest();

if (!isGenerator(testFn)) {
recorder.add(() => done());
recorder.add('finish test', () => done());
recorder.catch();

@@ -88,8 +89,7 @@ }

recorder.start();
event.dispatcher.emit(event.test.before);
event.emit(event.test.before);
};
module.exports.teardown = function () {
// recorder.reset();
event.dispatcher.emit(event.test.after);
event.emit(event.test.after);
};

@@ -101,4 +101,3 @@

function getInjectedArguments(fn)
{
function getInjectedArguments(fn) {
let testArguments = [];

@@ -105,0 +104,0 @@ let params = getParamNames(fn) || [];

@@ -20,5 +20,3 @@ 'use strict';

this.args = Array.prototype.slice.call(arguments);
event.dispatcher.emit(event.step.init, this);
this.status = 'queued';
event.dispatcher.emit(event.step.before, this);
event.emit(event.step.before, this);
let result;

@@ -32,3 +30,3 @@ try {

} finally {
event.dispatcher.emit(event.step.after, this);
event.emit(event.step.after, this);
}

@@ -35,0 +33,0 @@ return result;

@@ -8,5 +8,5 @@ 'use strict';

function within(context, fn) {
recorder.add(function () {
recorder.add('register within wrapper', function () {
recorder.session.start();
recorder.session.start('within');
let helpers = container.helpers();

@@ -22,3 +22,3 @@ let locator = typeof context === 'object' ? JSON.parse(context) : context;

Object.keys(helpers).forEach((helper) => {
if (helpers[helper]._withinBegin) recorder.add(() => helpers[helper]._withinBegin(context));
if (helpers[helper]._withinBegin) recorder.add('start within block', () => helpers[helper]._withinBegin(context));
});

@@ -29,8 +29,10 @@

Object.keys(helpers).forEach((helper) => {
if (helpers[helper]._withinEnd) recorder.add(() => helpers[helper]._withinEnd());
if (helpers[helper]._withinEnd) recorder.add('finish within block', () => helpers[helper]._withinEnd());
});
recorder.add(() => recorder.session.restore());
recorder.add(() => event.dispatcher.removeListener(event.step.after, addContextToStep));
recorder.add(() => output.stepShift = 1);
recorder.add('restore session', () => {
recorder.session.restore();
output.stepShift = 1;
event.dispatcher.removeListener(event.step.after, addContextToStep)
});
return recorder.promise();

@@ -37,0 +39,0 @@ });

{
"name": "codeceptjs",
"version": "0.3.5",
"version": "0.4.0",
"description": "Modern Era Aceptance Testing Framework for NodeJS",

@@ -55,3 +55,5 @@ "homepage": "http://codecept.io",

"guppy-pre-commit": "^0.3.0",
"protractor": "^3.3.0",
"nightmare": "^2.5.2",
"nightmare-upload": "^0.1.1",
"protractor": "^4.0.0",
"selenium-webdriver": "^2.53.1",

@@ -58,0 +60,0 @@ "sinon": "^1.17.2",

@@ -47,2 +47,3 @@ # CodeceptJS [![NPM version][npm-image]][npm-url] [![Build Status](https://travis-ci.org/Codeception/CodeceptJS.svg)](https://travis-ci.org/Codeception/CodeceptJS) [![Join the chat at https://gitter.im/Codeception/CodeceptJS](https://badges.gitter.im/Codeception/CodeceptJS.svg)](https://gitter.im/Codeception/CodeceptJS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

* Uses ES6 natively without transpiler.
* Also plays nice with TypeScript.
* Selenium WebDriver integration using [webdriverio](http://webdriver.io).

@@ -81,2 +82,10 @@ * Smart locators: use names, labels, matching text, CSS or XPath to locate elements.

If you want to write your tests using TypeScript just generate standard Type Definitions by executing:
```
codeceptjs def .
```
Later you can even automagically update Type Definitions to include your own custom [helpers methods](docs/helpers.md).
## Usage

@@ -83,0 +92,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