codeceptjs
Advanced tools
Comparing version 1.4.2 to 1.4.3
@@ -0,1 +1,18 @@ | ||
## 1.4.3 | ||
* Groups renamed to Tags for compatibility with BDD layer | ||
* Test and suite objects to contain tags property which can be accessed from internal API | ||
* Fixed adding tags for Scenario Outline in BDD | ||
* Added `tag()` method to ScenarioConfig and FeatureConfig: | ||
```js | ||
Scenario('update user profile', () => { | ||
// test goes here | ||
}).tag('@slow'); | ||
``` | ||
* Fixed attaching Allure screenshot on exception. Fix by @DevinWatson | ||
* Improved type definitions for custom steps. By @Akxe | ||
* Fixed setting `multiple.parallel.chunks` as environment variable in config. See [#1238](https://github.com/Codeception/CodeceptJS/pull/1238) by @ngadiyak | ||
## 1.4.2 | ||
@@ -2,0 +19,0 @@ |
@@ -79,6 +79,5 @@ # Advanced Usage | ||
## Groups | ||
## Tags | ||
Append `@tag` to your test name, so | ||
all tests with `@tag` could be executed with `--grep @tag` option. | ||
@@ -89,2 +88,12 @@ ```js | ||
Alternativly, use `tag` method of Scenario to set additional tags: | ||
```js | ||
Scenario('update user profile', () => { | ||
// test goes here | ||
}).tag('@slow').tag('important'); | ||
``` | ||
All tests with `@tag` could be executed with `--grep @tag` option. | ||
```sh | ||
@@ -97,3 +106,3 @@ codeceptjs run --grep @slow | ||
* `--grep '(?=.*@smoke2)(?=.*@smoke3)'` - run tests with @smoke2 and @smoke3 in name | ||
* `--grep '@smoke2|@smoke3'` - run tests with @smoke2 or @smoke3 in name | ||
* `--grep "\@smoke2|\@smoke3"` - run tests with @smoke2 or @smoke3 in name | ||
* `--grep '((?=.*@smoke2)(?=.*@smoke3))|@smoke4'` - run tests with (@smoke2 and @smoke3) or @smoke4 in name | ||
@@ -103,2 +112,4 @@ * `--grep '(?=.*@smoke2)^(?!.*@smoke3)'` - run tests with @smoke2 but without @smoke3 in name | ||
## Debug | ||
@@ -105,0 +116,0 @@ |
@@ -170,66 +170,3 @@ # Hooks | ||
## Plugins | ||
Plugins allow to use CodeceptJS internal API to extend functionality. Use internal event dispatcher, container, output, promise recorder, to create your own reporters, test listeners, etc. | ||
CodeceptJS includes [built-in plugins](https://codecept.io/plugins/) which extend basic functionality and can be turned on and off on purpose. Taking them as [examples](https://github.com/Codeception/CodeceptJS/tree/master/lib/plugin) you can develop your custom plugins. | ||
A plugin is a basic JS module returning a function. Plugins can have individual configs which are passed into this function: | ||
```js | ||
const defaultConfig = { | ||
someDefaultOption: true | ||
} | ||
module.exports = function(config) { | ||
config = Object.assign(defaultConfig, config); | ||
// do stuff | ||
} | ||
``` | ||
Plugin can register event listeners or hook into promise chain with recorder. See [API reference](https://github.com/Codeception/CodeceptJS/tree/master/lib/helper). | ||
To enable your custom plugin in config add it to `plugins` section. Specify path to node module using `require`. | ||
```js | ||
"plugins": { | ||
"myPlugin": { | ||
"require": "./path/to/my/module", | ||
"enabled": true | ||
} | ||
} | ||
``` | ||
* `require` - specifies relative path to a plugin file. Path is relative to config file. | ||
* `enabled` - to enable this plugin. | ||
If a plugin is disabled (`enabled` is not set or false) this plugin can be enabled from command line: | ||
``` | ||
./node_modules/.bin/codeceptjs run --plugin myPlugin | ||
``` | ||
Several plugins can be enabled as well: | ||
``` | ||
./node_modules/.bin/codeceptjs run --plugin myPlugin,allure | ||
``` | ||
## Custom Hooks | ||
*(deprecated, use [plugins](#plugins))* | ||
Hooks are JavaScript files same as for bootstrap and teardown, which can be registered inside `hooks` section of config. Unlike `bootstrap` you can have multiple hooks registered: | ||
```json | ||
"hooks": [ | ||
"./server.js", | ||
"./data_builder.js", | ||
"./report_notification.js" | ||
] | ||
``` | ||
Inside those JS files you can use CodeceptJS API (see below) to access its internals. | ||
## API | ||
@@ -306,2 +243,3 @@ | ||
* `pending` true if test is scheduled for execution and false if a test has finished | ||
* `tags` array of tags for this test | ||
* `file` path to a file with a test. | ||
@@ -437,2 +375,89 @@ * `steps` array of executed steps (available only in `test.passed`, `test.failed`, `test.finished` event) | ||
## Plugins | ||
Plugins allow to use CodeceptJS internal API to extend functionality. Use internal event dispatcher, container, output, promise recorder, to create your own reporters, test listeners, etc. | ||
CodeceptJS includes [built-in plugins](https://codecept.io/plugins/) which extend basic functionality and can be turned on and off on purpose. Taking them as [examples](https://github.com/Codeception/CodeceptJS/tree/master/lib/plugin) you can develop your custom plugins. | ||
A plugin is a basic JS module returning a function. Plugins can have individual configs which are passed into this function: | ||
```js | ||
const defaultConfig = { | ||
someDefaultOption: true | ||
} | ||
module.exports = function(config) { | ||
config = Object.assign(defaultConfig, config); | ||
// do stuff | ||
} | ||
``` | ||
Plugin can register event listeners or hook into promise chain with recorder. See [API reference](https://github.com/Codeception/CodeceptJS/tree/master/lib/helper). | ||
To enable your custom plugin in config add it to `plugins` section. Specify path to node module using `require`. | ||
```js | ||
"plugins": { | ||
"myPlugin": { | ||
"require": "./path/to/my/module", | ||
"enabled": true | ||
} | ||
} | ||
``` | ||
* `require` - specifies relative path to a plugin file. Path is relative to config file. | ||
* `enabled` - to enable this plugin. | ||
If a plugin is disabled (`enabled` is not set or false) this plugin can be enabled from command line: | ||
``` | ||
./node_modules/.bin/codeceptjs run --plugin myPlugin | ||
``` | ||
Several plugins can be enabled as well: | ||
``` | ||
./node_modules/.bin/codeceptjs run --plugin myPlugin,allure | ||
``` | ||
### Example: Execute code for a specific group of tests | ||
If you need to execute some code before a group of tests, you can [mark these tests with a same tag](https://codecept.io/advanced/#tags). Then to listen for tests where this tag is included (see [test object api](#test-object)). | ||
Let's say we need to populate database for a group of tests. | ||
```js | ||
// populate database for slow tests | ||
const event = require('codeceptjs').event; | ||
module.exports = function() { | ||
event.dispatcher.on(event.test.before, function (test) { | ||
if (test.tags.indexOf('@populate') >= 0) { | ||
recorder.add('populate database', async () => { | ||
// populate database for this test | ||
}) | ||
} | ||
}); | ||
} | ||
``` | ||
## Custom Hooks | ||
*(deprecated, use [plugins](#plugins))* | ||
Hooks are JavaScript files same as for bootstrap and teardown, which can be registered inside `hooks` section of config. Unlike `bootstrap` you can have multiple hooks registered: | ||
```json | ||
"hooks": [ | ||
"./server.js", | ||
"./data_builder.js", | ||
"./report_notification.js" | ||
] | ||
``` | ||
Inside those JS files you can use CodeceptJS API (see below) to access its internals. | ||
## Custom Runner | ||
@@ -439,0 +464,0 @@ |
@@ -105,9 +105,13 @@ const getConfig = require('./utils').getConfig; | ||
declare function actor(customSteps?: { | ||
[action: string]: (this: CodeceptJS.I, ...args: any[]) => void | ||
}): CodeceptJS.{{I}}; | ||
declare function actor(customSteps?: {}): CodeceptJS.{{I}}; | ||
declare function Feature(title: string, opts?: {}): FeatureConfig; | ||
declare const Scenario: { | ||
(title: string, callback: ICodeceptCallback): ScenarioConfig; | ||
(title: string, opts: {}, callback: ICodeceptCallback): ScenarioConfig; | ||
only(title: string, callback: ICodeceptCallback): ScenarioConfig; | ||
only(title: string, opts: {}, callback: ICodeceptCallback): ScenarioConfig; | ||
(title: string, callback: ICodeceptCallback): ScenarioConfig; | ||
(title: string, opts: {}, callback: ICodeceptCallback): ScenarioConfig; | ||
only(title: string, callback: ICodeceptCallback): ScenarioConfig; | ||
only(title: string, opts: {}, callback: ICodeceptCallback): ScenarioConfig; | ||
} | ||
@@ -114,0 +118,0 @@ declare function xScenario(title: string, callback: ICodeceptCallback): ScenarioConfig; |
@@ -65,3 +65,3 @@ const glob = require('glob'); | ||
chunks = config.chunks.call(this, files); | ||
} else if (typeof config.chunks === 'number') { | ||
} else if (typeof config.chunks === 'number' || typeof config.chunks === 'string') { | ||
chunks = splitFiles(files, Math.ceil(files.length / config.chunks)); | ||
@@ -68,0 +68,0 @@ } else { |
@@ -43,4 +43,18 @@ class FeatureConfig { | ||
} | ||
/** | ||
* Append a tag name to scenario title | ||
* @param {*} tagName | ||
*/ | ||
tag(tagName) { | ||
if (tagName[0] !== '@') { | ||
tagName = `@${tagName}`; | ||
} | ||
this.suite.tags.push(tagName); | ||
this.suite.title = `${this.suite.title.trim()} ${tagName}`; | ||
return this; | ||
} | ||
} | ||
module.exports = FeatureConfig; |
@@ -18,3 +18,5 @@ const { Parser } = require('gherkin'); | ||
const suite = new Suite(ast.feature.name, new Context()); | ||
suite.title = `${suite.title} ${ast.feature.tags.map(t => t.name).join(' ')}`.trim(); | ||
const tags = ast.feature.tags.map(t => t.name); | ||
suite.title = `${suite.title} ${tags.join(' ')}`.trim(); | ||
suite.tags = tags || []; | ||
suite.comment = ast.feature.description; | ||
@@ -77,3 +79,6 @@ suite.feature = ast.feature; | ||
} | ||
const test = new Test(`${child.name} ${JSON.stringify(current)}`, async () => runSteps(exampleSteps)); | ||
const tags = child.tags.map(t => t.name); | ||
const title = `${child.name} ${JSON.stringify(current)} ${tags.join(' ')}`.trim(); | ||
const test = new Test(title, async () => runSteps(exampleSteps)); | ||
test.tags = suite.tags.concat(tags); | ||
test.timeout(0); | ||
@@ -86,5 +91,7 @@ test.async = true; | ||
} | ||
const title = `${child.name} ${child.tags.map(t => t.name).join(' ')}`.trim(); | ||
const tags = child.tags.map(t => t.name); | ||
const title = `${child.name} ${tags.join(' ')}`.trim(); | ||
const test = new Test(title, async () => runSteps(child.steps)); | ||
test.timeout(0); | ||
test.tags = suite.tags.concat(tags); | ||
test.async = true; | ||
@@ -91,0 +98,0 @@ suite.addTest(scenario.test(test)); |
@@ -73,6 +73,17 @@ class ScenarioConfig { | ||
this.test.config[helper] = obj; | ||
return this.test; | ||
return this; | ||
} | ||
/** | ||
* Append a tag name to scenario title | ||
* @param {*} tagName | ||
*/ | ||
tag(tagName) { | ||
if (tagName[0] !== '@') tagName = `@${tagName}`; | ||
this.test.tags.push(tagName); | ||
this.test.title = `${this.test.title.trim()} ${tagName}`; | ||
return this; | ||
} | ||
} | ||
module.exports = ScenarioConfig; |
@@ -42,3 +42,3 @@ const event = require('../event'); | ||
// schedule config to revert changes | ||
runAsyncHelpersHook('_before'); | ||
runAsyncHelpersHook('_before', test, true); | ||
}); | ||
@@ -45,0 +45,0 @@ |
@@ -83,2 +83,6 @@ const Container = require('../container'); | ||
await helper.saveScreenshot(fileName, options.fullPageScreenshots); | ||
const allureReporter = Container.plugins('allure'); | ||
if (allureReporter) { | ||
allureReporter.addAttachment('Last Seen Screenshot', fs.readFileSync(path.join(global.output_dir, fileName)), 'image/png'); | ||
} | ||
} catch (err) { | ||
@@ -94,9 +98,4 @@ if (err && | ||
} | ||
const allureReporter = Container.plugins('allure'); | ||
if (allureReporter) { | ||
allureReporter.addAttachment('Last Seen Screenshot', fs.readFileSync(path.join(global.output_dir, fileName)), 'image/png'); | ||
} | ||
}, true); | ||
}); | ||
}; |
@@ -37,3 +37,3 @@ /** | ||
const addScenario = function (title, opts, fn, data) { | ||
const addScenario = function (title, opts = {}, fn, data) { | ||
const suite = suites[0]; | ||
@@ -55,2 +55,4 @@ | ||
}; | ||
test.tags = (suite.tags || []).concat(title.match(/(\@\w+)/g)); // match tags from title | ||
test.file = file; | ||
@@ -100,2 +102,3 @@ test.async = true; | ||
suite.tags = title.match(/(\@\w+)/g) || []; // match tags from title | ||
suite.file = file; | ||
@@ -102,0 +105,0 @@ suite.fullTitle = () => `${suite.title}:`; |
{ | ||
"name": "codeceptjs", | ||
"version": "1.4.2", | ||
"version": "1.4.3", | ||
"description": "Modern Era Acceptance Testing Framework for NodeJS", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1190086
24619