Skip to content

Commit 03c5c91

Browse files
DavertMikMykhailo Bodnarchukpablopaul
authored
Simplified bootstrap (#2385)
* updated missing dependency * bootstrap simplified * fixed tests * added documentation * updated api documentation * updated tests * codestyle improv * Apply suggestions from code review Co-authored-by: Paul <pbeigang@gmail.com> Co-authored-by: Mykhailo Bodnarchuk <mykhailo.bodnarchuk@Mykhailos-MacBook-Pro.local> Co-authored-by: Paul <pbeigang@gmail.com>
1 parent 5f3572e commit 03c5c91

34 files changed

+710
-608
lines changed

bin/codecept.js

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -119,44 +119,6 @@ program.command('run [test]')
119119
.option('--child <string>', 'option for child processes')
120120

121121
.action(require('../lib/command/run'));
122-
123-
program.command('run-rerun [test]')
124-
.description('Executes tests in more than one test suite run')
125-
126-
// codecept-only options
127-
.option('--steps', 'show step-by-step execution')
128-
.option('--debug', 'output additional information')
129-
.option('--verbose', 'output internal logging information')
130-
.option('-o, --override [value]', 'override current config options')
131-
.option('--profile [value]', 'configuration profile to be used')
132-
.option('-c, --config [file]', 'configuration file to be used')
133-
.option('--features', 'run only *.feature files and skip tests')
134-
.option('--tests', 'run only JS test files and skip features')
135-
.option('-p, --plugins <k=v,k2=v2,...>', 'enable plugins, comma-separated')
136-
137-
// mocha options
138-
.option('--colors', 'force enabling of colors')
139-
.option('--no-colors', 'force disabling of colors')
140-
.option('-G, --growl', 'enable growl notification support')
141-
.option('-O, --reporter-options <k=v,k2=v2,...>', 'reporter-specific options')
142-
.option('-R, --reporter <name>', 'specify the reporter to use')
143-
.option('-S, --sort', 'sort test files')
144-
.option('-b, --bail', 'bail after first test failure')
145-
.option('-d, --debug', "enable node's debugger, synonym for node --debug")
146-
.option('-g, --grep <pattern>', 'only run tests matching <pattern>')
147-
.option('-f, --fgrep <string>', 'only run tests containing <string>')
148-
.option('-i, --invert', 'inverts --grep and --fgrep matches')
149-
.option('--full-trace', 'display the full stack trace')
150-
.option('--compilers <ext>:<module>,...', 'use the given module(s) to compile files')
151-
.option('--debug-brk', "enable node's debugger breaking on the first line")
152-
.option('--inline-diffs', 'display actual/expected differences inline within each string')
153-
.option('--no-exit', 'require a clean shutdown of the event loop: mocha will not call process.exit')
154-
.option('--recursive', 'include sub directories')
155-
.option('--trace', 'trace function calls')
156-
.option('--child <string>', 'option for child processes')
157-
158-
.action(require('../lib/command/run-rerun'));
159-
160122
program.command('run-workers <workers>')
161123
.description('Executes tests in workers')
162124
.option('-c, --config [file]', 'configuration file to be used')

docs/api.md

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
---
2+
permalink: /internal-api
3+
title: Internal API
4+
---
5+
6+
## Concepts
7+
8+
In this guide we will overview the internal API of CodeceptJS.
9+
This knowledge is required for customization, writing plugins, etc.
10+
11+
CodeceptJS provides an API which can be loaded via `require('codeceptjs')` when CodeceptJS is installed locally. Otherwise, you can load codeceptjs API via global `codeceptjs` object:
12+
13+
```js
14+
// via module
15+
const { recorder, event, output } = require('codeceptjs');
16+
// or using global object
17+
const { recorder, event, output } = codeceptjs;
18+
```
19+
20+
These internal objects are available:
21+
22+
* [`codecept`](https://github.com/Codeception/CodeceptJS/blob/master/lib/codecept.js): test runner class
23+
* [`config`](https://github.com/Codeception/CodeceptJS/blob/master/lib/config.js): current codecept config
24+
* [`event`](https://github.com/Codeception/CodeceptJS/blob/master/lib/event.js): event listener
25+
* [`recorder`](https://github.com/Codeception/CodeceptJS/blob/master/lib/recorder.js): global promise chain
26+
* [`output`](https://github.com/Codeception/CodeceptJS/blob/master/lib/output.js): internal printer
27+
* [`container`](https://github.com/Codeception/CodeceptJS/blob/master/lib/container.js): dependency injection container for tests, includes current helpers and support objects
28+
* [`helper`](https://github.com/Codeception/CodeceptJS/blob/master/lib/helper.js): basic helper class
29+
* [`actor`](https://github.com/Codeception/CodeceptJS/blob/master/lib/actor.js): basic actor (I) class
30+
31+
[API reference](https://github.com/Codeception/CodeceptJS/tree/master/docs/api) is available on GitHub.
32+
Also please check the source code of corresponding modules.
33+
34+
### Container
35+
36+
CodeceptJS has a dependency injection container with helpers and support objects.
37+
They can be retrieved from the container:
38+
39+
```js
40+
const { container } = require('codeceptjs');
41+
42+
// get object with all helpers
43+
const helpers = container.helpers();
44+
45+
// get helper by name
46+
const { WebDriver } = container.helpers();
47+
48+
// get support objects
49+
const supportObjects = container.support();
50+
51+
// get support object by name
52+
const { UserPage } = container.support();
53+
54+
// get all registered plugins
55+
const plugins = container.plugins();
56+
```
57+
58+
New objects can also be added to container in runtime:
59+
60+
```js
61+
const { container } = require('codeceptjs');
62+
63+
container.append({
64+
helpers: { // add helper
65+
MyHelper: new MyHelper({ config1: 'val1' });
66+
},
67+
support: { // add page object
68+
UserPage: require('./pages/user');
69+
}
70+
})
71+
```
72+
73+
> Use this trick to define custom objects inside `boostrap` script
74+
75+
The container also contains the current Mocha instance:
76+
77+
```js
78+
const mocha = container.mocha();
79+
```
80+
81+
### Event Listeners
82+
83+
CodeceptJS provides a module with an [event dispatcher and set of predefined events](https://github.com/Codeception/CodeceptJS/blob/master/lib/event.js).
84+
85+
It can be required from codeceptjs package if it is installed locally.
86+
87+
```js
88+
const { event } = require('codeceptjs');
89+
90+
module.exports = function() {
91+
92+
event.dispatcher.on(event.test.before, function (test) {
93+
94+
console.log('--- I am before test --');
95+
96+
});
97+
}
98+
```
99+
100+
Available events:
101+
102+
* `event.test.before(test)` - *async* when `Before` hooks from helpers and from test is executed
103+
* `event.test.after(test)` - *async* after each test
104+
* `event.test.started(test)` - *sync* at the very beginning of a test.
105+
* `event.test.passed(test)` - *sync* when test passed
106+
* `event.test.failed(test, error)` - *sync* when test failed
107+
* `event.test.finished(test)` - *sync* when test finished
108+
* `event.suite.before(suite)` - *async* before a suite
109+
* `event.suite.after(suite)` - *async* after a suite
110+
* `event.step.before(step)` - *async* when the step is scheduled for execution
111+
* `event.step.after(step)`- *async* after a step
112+
* `event.step.started(step)` - *sync* when step starts.
113+
* `event.step.passed(step)` - *sync* when step passed.
114+
* `event.step.failed(step, err)` - *sync* when step failed.
115+
* `event.step.finished(step)` - *sync* when step finishes.
116+
* `event.step.comment(step)` - *sync* fired for comments like `I.say`.
117+
* `event.all.before` - before running tests
118+
* `event.all.after` - after running tests
119+
* `event.all.result` - when results are printed
120+
* `event.workers.before` - before spawning workers in parallel run
121+
* `event.workers.after` - after workers finished in parallel run
122+
123+
124+
> *sync* - means that event is fired in the moment of the action happening.
125+
*async* - means that event is fired when an action is scheduled. Use `recorder` to schedule your actions.
126+
127+
For further reference look for [currently available listeners](https://github.com/Codeception/CodeceptJS/tree/master/lib/listener) using the event system.
128+
129+
130+
### Recorder
131+
132+
To inject asynchronous functions in a test or before/after a test you can subscribe to corresponding event and register a function inside a recorder object. [Recorder](https://github.com/Codeception/CodeceptJS/blob/master/lib/recorder.js) represents a global promises chain.
133+
134+
Provide a function in the first parameter, a function must be async or must return a promise:
135+
136+
```js
137+
const { event, recorder } = require('codeceptjs');
138+
139+
module.exports = function() {
140+
141+
event.dispatcher.on(event.test.before, function (test) {
142+
143+
const request = require('request');
144+
145+
recorder.add('create fixture data via API', function() {
146+
return new Promise((doneFn, errFn) => {
147+
request({
148+
baseUrl: 'http://api.site.com/',
149+
method: 'POST',
150+
url: '/users',
151+
json: { name: 'john', email: 'john@john.com' }
152+
}), (err, httpResponse, body) => {
153+
if (err) return errFn(err);
154+
doneFn();
155+
}
156+
});
157+
}
158+
});
159+
}
160+
```
161+
162+
### Config
163+
164+
CodeceptJS config can be accessed from `require('codeceptjs').config.get()`:
165+
166+
```js
167+
const { config } = require('codeceptjs');
168+
169+
// config object has access to all values of the current config file
170+
171+
if (config.get().myKey == 'value') {
172+
// run something
173+
}
174+
```
175+
176+
177+
### Output
178+
179+
Output module provides four verbosity levels. Depending on the mode you can have different information printed using corresponding functions.
180+
181+
* `default`: prints basic information using `output.print`
182+
* `steps`: toggled by `--steps` option, prints step execution
183+
* `debug`: toggled by `--debug` option, prints steps, and debug information with `output.debug`
184+
* `verbose`: toggled by `--verbose` prints debug information and internal logs with `output.log`
185+
186+
It is recommended to avoid `console.log` and use output.* methods for printing.
187+
188+
```js
189+
const output = require('codeceptjs').output;
190+
191+
output.print('This is basic information');
192+
output.debug('This is debug information');
193+
output.log('This is verbose logging information');
194+
```
195+
196+
#### Test Object
197+
198+
The test events are providing a test object with following properties:
199+
200+
* `title` title of the test
201+
* `body` test function as a string
202+
* `opts` additional test options like retries, and others
203+
* `pending` true if test is scheduled for execution and false if a test has finished
204+
* `tags` array of tags for this test
205+
* `artifacts` list of files attached to this test. Screenshots, videos and other files can be saved here and shared accross different reporters
206+
* `file` path to a file with a test
207+
* `steps` array of executed steps (available only in `test.passed`, `test.failed`, `test.finished` event)
208+
* `skipInfo` additional test options when test skipped
209+
* * `message` string with reason for skip
210+
* * `description` string with test body
211+
and others
212+
213+
#### Step Object
214+
215+
Step events provide step objects with following fields:
216+
217+
* `name` name of a step, like 'see', 'click', and others
218+
* `actor` current actor, in most cases it is `I`
219+
* `helper` current helper instance used to execute this step
220+
* `helperMethod` corresponding helper method, in most cases is the same as `name`
221+
* `status` status of a step (passed or failed)
222+
* `prefix` if a step is executed inside `within` block contain within text, like: 'Within .js-signup-form'.
223+
* `args` passed arguments
224+
225+
Whenever you execute tests with `--verbose` option you will see registered events and promises executed by a recorder.
226+
227+
## Custom Runner
228+
229+
You can run CodeceptJS tests from your script.
230+
231+
```js
232+
const { codecept: Codecept } = require('codeceptjs');
233+
234+
// define main config
235+
const config = {
236+
helpers: {
237+
WebDriver: {
238+
browser: 'chrome',
239+
url: 'http://localhost'
240+
}
241+
}
242+
};
243+
244+
const opts = { steps: true };
245+
246+
// run CodeceptJS inside async function
247+
(async () => {
248+
const codecept = new Codecept(config, options);
249+
codecept.init(__dirname);
250+
251+
try {
252+
await codecept.bootstrap();
253+
codecept.loadTests('**_test.js');
254+
// run tests
255+
await codecept.run(test);
256+
} catch (err) {
257+
printError(err);
258+
process.exitCode = 1;
259+
} finally {
260+
await codecept.teardown();
261+
}
262+
})();
263+
```
264+
265+
> Also, you can run tests inside workers in a custom scripts. Please refer to the [parallel execution](/parallel) guide for more details.

0 commit comments

Comments
 (0)