codeceptjs 3.2.1 → 3.3.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +67 -0
- package/docs/advanced.md +3 -3
- package/docs/api.md +227 -188
- package/docs/basics.md +26 -1
- package/docs/bdd.md +2 -2
- package/docs/build/ApiDataFactory.js +13 -6
- package/docs/build/Appium.js +98 -36
- package/docs/build/FileSystem.js +11 -1
- package/docs/build/GraphQL.js +11 -0
- package/docs/build/JSONResponse.js +297 -0
- package/docs/build/Nightmare.js +48 -48
- package/docs/build/Playwright.js +282 -151
- package/docs/build/Puppeteer.js +76 -67
- package/docs/build/REST.js +36 -0
- package/docs/build/TestCafe.js +44 -44
- package/docs/build/WebDriver.js +70 -70
- package/docs/changelog.md +17 -0
- package/docs/configuration.md +8 -8
- package/docs/custom-helpers.md +1 -1
- package/docs/data.md +9 -9
- package/docs/helpers/ApiDataFactory.md +7 -0
- package/docs/helpers/Appium.md +240 -198
- package/docs/helpers/FileSystem.md +11 -1
- package/docs/helpers/JSONResponse.md +230 -0
- package/docs/helpers/Playwright.md +283 -216
- package/docs/helpers/Puppeteer.md +9 -1
- package/docs/helpers/REST.md +30 -9
- package/docs/installation.md +3 -1
- package/docs/internal-api.md +265 -0
- package/docs/mobile.md +11 -11
- package/docs/nightmare.md +3 -3
- package/docs/pageobjects.md +2 -0
- package/docs/playwright.md +73 -18
- package/docs/plugins.md +138 -38
- package/docs/puppeteer.md +28 -12
- package/docs/quickstart.md +2 -3
- package/docs/reports.md +44 -3
- package/docs/testcafe.md +1 -1
- package/docs/translation.md +2 -2
- package/docs/videos.md +2 -2
- package/docs/visual.md +2 -2
- package/docs/vue.md +1 -1
- package/docs/webdriver.md +92 -4
- package/lib/actor.js +2 -2
- package/lib/cli.js +25 -20
- package/lib/command/init.js +5 -15
- package/lib/command/workers/runTests.js +25 -7
- package/lib/config.js +17 -13
- package/lib/helper/ApiDataFactory.js +13 -6
- package/lib/helper/Appium.js +65 -3
- package/lib/helper/FileSystem.js +11 -1
- package/lib/helper/GraphQL.js +11 -0
- package/lib/helper/JSONResponse.js +297 -0
- package/lib/helper/Playwright.js +220 -89
- package/lib/helper/Puppeteer.js +12 -3
- package/lib/helper/REST.js +36 -0
- package/lib/helper/WebDriver.js +1 -1
- package/lib/helper/extras/Console.js +8 -0
- package/lib/helper/extras/PlaywrightRestartOpts.js +35 -0
- package/lib/interfaces/bdd.js +3 -1
- package/lib/listener/timeout.js +4 -3
- package/lib/plugin/allure.js +12 -0
- package/lib/plugin/autoLogin.js +1 -1
- package/lib/plugin/eachElement.js +127 -0
- package/lib/plugin/stepTimeout.js +5 -4
- package/lib/plugin/tryTo.js +6 -0
- package/lib/recorder.js +2 -1
- package/lib/step.js +57 -2
- package/lib/utils.js +20 -0
- package/package.json +24 -22
- package/translations/pt-BR.js +8 -0
- package/typings/index.d.ts +4 -0
- package/typings/types.d.ts +345 -110
package/docs/webdriver.md
CHANGED
|
@@ -203,8 +203,6 @@ Scenario('login test', ({ I }) => {
|
|
|
203
203
|
I.see('Welcome, John');
|
|
204
204
|
});
|
|
205
205
|
```
|
|
206
|
-
> ▶ Actions like `amOnPage`, `click`, `fillField` are not limited to WebDriver only. They work similarly for all available helpers. [Go to Basics guide to learn them](/basics#writing-tests).
|
|
207
|
-
|
|
208
206
|
|
|
209
207
|
An empty test case can be created with `npx codeceptjs gt` command.
|
|
210
208
|
|
|
@@ -212,6 +210,43 @@ An empty test case can be created with `npx codeceptjs gt` command.
|
|
|
212
210
|
npx codeceptjs gt
|
|
213
211
|
```
|
|
214
212
|
|
|
213
|
+
|
|
214
|
+
### Actions
|
|
215
|
+
|
|
216
|
+
Tests consist with a scenario of user's action taken on a page. The most widely used ones are:
|
|
217
|
+
|
|
218
|
+
* `amOnPage` - to open a webpage (accepts relative or absolute url)
|
|
219
|
+
* `click` - to locate a button or link and click on it
|
|
220
|
+
* `fillField` - to enter a text inside a field
|
|
221
|
+
* `selectOption`, `checkOption` - to interact with a form
|
|
222
|
+
* `wait*` to wait for some parts of page to be fully rendered (important for testing SPA)
|
|
223
|
+
* `grab*` to get values from page sources
|
|
224
|
+
* `see`, `dontSee` - to check for a text on a page
|
|
225
|
+
* `seeElement`, `dontSeeElement` - to check for elements on a page
|
|
226
|
+
|
|
227
|
+
> ℹ All actions are listed in [WebDriver helper reference](https://codecept.io/helpers/WebDriver/).*
|
|
228
|
+
|
|
229
|
+
All actions which interact with elements **support CSS and XPath locators**. Actions like `click` or `fillField` by locate elements by their name or value on a page:
|
|
230
|
+
|
|
231
|
+
```js
|
|
232
|
+
// search for link or button
|
|
233
|
+
I.click('Login');
|
|
234
|
+
// locate field by its label
|
|
235
|
+
I.fillField('Name', 'Miles');
|
|
236
|
+
// we can use input name
|
|
237
|
+
I.fillField('user[email]','miles@davis.com');
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
You can also specify the exact locator type with strict locators:
|
|
241
|
+
|
|
242
|
+
```js
|
|
243
|
+
I.click({css: 'button.red'});
|
|
244
|
+
I.fillField({name: 'user[email]'},'miles@davis.com');
|
|
245
|
+
I.seeElement({xpath: '//body/header'});
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Interactive Pause
|
|
249
|
+
|
|
215
250
|
It's easy to start writing a test if you use [interactive pause](/basics#debug). Just open a web page and pause execution.
|
|
216
251
|
|
|
217
252
|
```js
|
|
@@ -250,7 +285,7 @@ An interactive shell output may look like this:
|
|
|
250
285
|
```
|
|
251
286
|
After typing in successful commands you can copy them into a test.
|
|
252
287
|
|
|
253
|
-
Here is a test checking basic [todo application](
|
|
288
|
+
Here is a test checking basic [todo application](https://todomvc.com/).
|
|
254
289
|
|
|
255
290
|
```js
|
|
256
291
|
Feature('TodoMVC');
|
|
@@ -268,6 +303,59 @@ Scenario('create todo item', ({ I }) => {
|
|
|
268
303
|
|
|
269
304
|
WebDriver helper supports standard [CSS/XPath and text locators](/locators) as well as non-trivial [React locators](/react) and [Shadow DOM](/shadow).
|
|
270
305
|
|
|
306
|
+
### Grabbers
|
|
307
|
+
|
|
308
|
+
If you need to get element's value inside a test you can use `grab*` methods. They should be used with `await` operator inside `async` function:
|
|
309
|
+
|
|
310
|
+
```js
|
|
311
|
+
const assert = require('assert');
|
|
312
|
+
Scenario('get value of current tasks', async ({ I }) => {
|
|
313
|
+
I.fillField('.todo', 'my first item');
|
|
314
|
+
I.pressKey('Enter')
|
|
315
|
+
I.fillField('.todo', 'my second item');
|
|
316
|
+
I.pressKey('Enter')
|
|
317
|
+
let numTodos = await I.grabTextFrom('.todo-count strong');
|
|
318
|
+
assert.equal(2, numTodos);
|
|
319
|
+
});
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Within
|
|
323
|
+
|
|
324
|
+
In case some actions should be taken inside one element (a container or modal window or iframe) you can use `within` block to narrow the scope.
|
|
325
|
+
Please take a note that you can't use within inside another within in Puppeteer helper:
|
|
326
|
+
|
|
327
|
+
```js
|
|
328
|
+
await within('.todoapp', () => {
|
|
329
|
+
I.fillField('.todo', 'my new item');
|
|
330
|
+
I.pressKey('Enter')
|
|
331
|
+
I.see('1 item left', '.todo-count');
|
|
332
|
+
I.click('.todo-list input.toggle');
|
|
333
|
+
});
|
|
334
|
+
I.see('0 items left', '.todo-count');
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Each Element <Badge text="Since 3.3" type="warning"/>
|
|
338
|
+
|
|
339
|
+
Usually, CodeceptJS performs an action on the first matched element.
|
|
340
|
+
In case you want to do an action on each element found, use the special function `eachElement` which comes from [eachElement](https://codecept.io/plugins/#eachelement) plugin.
|
|
341
|
+
|
|
342
|
+
`eachElement` function matches all elements by locator and performs a callback on each of those element. A callback function receives element of webdriverio. `eachElement` may perform arbitrary actions on a page, so the first argument should by a description of the actions performed. This description will be used for logging purposes.
|
|
343
|
+
|
|
344
|
+
Usage example
|
|
345
|
+
|
|
346
|
+
```js
|
|
347
|
+
await eachElement(
|
|
348
|
+
'click all checkboxes',
|
|
349
|
+
'input.custom-checkbox',
|
|
350
|
+
async (el, index) => {
|
|
351
|
+
await el.click();
|
|
352
|
+
});
|
|
353
|
+
);
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
> ℹ Learn more about [eachElement plugin](/plugins/#eachelement)
|
|
357
|
+
|
|
358
|
+
|
|
271
359
|
## Waiting
|
|
272
360
|
|
|
273
361
|
Web applications do not always respond instantly. That's why WebDriver protocol has methods to wait for changes on a page. CodeceptJS provides such commands prefixed with `wait*` so you could explicitly define what effects we wait for.
|
|
@@ -295,7 +383,7 @@ exports.config = {
|
|
|
295
383
|
|
|
296
384
|
## SmartWait
|
|
297
385
|
|
|
298
|
-
It is possible to wait for elements pragmatically. If a test uses element which is not on a page yet, CodeceptJS will wait for few extra seconds before failing. This feature is based on [Implicit Wait](
|
|
386
|
+
It is possible to wait for elements pragmatically. If a test uses element which is not on a page yet, CodeceptJS will wait for few extra seconds before failing. This feature is based on [Implicit Wait](https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp#implicit-waits) of Selenium. CodeceptJS enables implicit wait only when searching for a specific element and disables in all other cases. Thus, the performance of a test is not affected.
|
|
299
387
|
|
|
300
388
|
SmartWait can be enabled by setting wait option in WebDriver config.
|
|
301
389
|
Add `smartWait: 5000` to wait for additional 5s.
|
package/lib/actor.js
CHANGED
|
@@ -38,7 +38,7 @@ class Actor {
|
|
|
38
38
|
|
|
39
39
|
event.dispatcher.prependOnceListener(event.step.before, (step) => {
|
|
40
40
|
output.log(`Timeout to ${step}: ${timeout}s`);
|
|
41
|
-
step.
|
|
41
|
+
step.setTimeout(timeout * 1000, Step.TIMEOUT_ORDER.codeLimitTime);
|
|
42
42
|
});
|
|
43
43
|
|
|
44
44
|
return this;
|
|
@@ -132,7 +132,7 @@ function recordStep(step, args) {
|
|
|
132
132
|
step.startTime = Date.now();
|
|
133
133
|
}
|
|
134
134
|
return val = step.run(...args);
|
|
135
|
-
}, false, undefined, step.
|
|
135
|
+
}, false, undefined, step.getTimeout());
|
|
136
136
|
|
|
137
137
|
event.emit(event.step.after, step);
|
|
138
138
|
|
package/lib/cli.js
CHANGED
|
@@ -7,6 +7,7 @@ const { MetaStep } = require('./step');
|
|
|
7
7
|
|
|
8
8
|
const cursor = Base.cursor;
|
|
9
9
|
let currentMetaStep = [];
|
|
10
|
+
let codeceptjsEventDispatchersRegistered = false;
|
|
10
11
|
|
|
11
12
|
class Cli extends Base {
|
|
12
13
|
constructor(runner, opts) {
|
|
@@ -77,29 +78,33 @@ class Cli extends Base {
|
|
|
77
78
|
}
|
|
78
79
|
});
|
|
79
80
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const metaSteps = [];
|
|
83
|
-
while (processingStep.metaStep) {
|
|
84
|
-
metaSteps.unshift(processingStep.metaStep);
|
|
85
|
-
processingStep = processingStep.metaStep;
|
|
86
|
-
}
|
|
87
|
-
const shift = metaSteps.length;
|
|
81
|
+
if (!codeceptjsEventDispatchersRegistered) {
|
|
82
|
+
codeceptjsEventDispatchersRegistered = true;
|
|
88
83
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
84
|
+
event.dispatcher.on(event.step.started, (step) => {
|
|
85
|
+
let processingStep = step;
|
|
86
|
+
const metaSteps = [];
|
|
87
|
+
while (processingStep.metaStep) {
|
|
88
|
+
metaSteps.unshift(processingStep.metaStep);
|
|
89
|
+
processingStep = processingStep.metaStep;
|
|
93
90
|
}
|
|
94
|
-
|
|
95
|
-
currentMetaStep = metaSteps;
|
|
96
|
-
output.stepShift = 3 + 2 * shift;
|
|
97
|
-
output.step(step);
|
|
98
|
-
});
|
|
91
|
+
const shift = metaSteps.length;
|
|
99
92
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
93
|
+
for (let i = 0; i < Math.max(currentMetaStep.length, metaSteps.length); i++) {
|
|
94
|
+
if (currentMetaStep[i] !== metaSteps[i]) {
|
|
95
|
+
output.stepShift = 3 + 2 * i;
|
|
96
|
+
if (metaSteps[i]) output.step(metaSteps[i]);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
currentMetaStep = metaSteps;
|
|
100
|
+
output.stepShift = 3 + 2 * shift;
|
|
101
|
+
output.step(step);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
event.dispatcher.on(event.step.finished, () => {
|
|
105
|
+
output.stepShift = 0;
|
|
106
|
+
});
|
|
107
|
+
}
|
|
103
108
|
}
|
|
104
109
|
|
|
105
110
|
runner.on('suite end', suite => {
|
package/lib/command/init.js
CHANGED
|
@@ -22,7 +22,7 @@ const defaultConfig = {
|
|
|
22
22
|
mocha: {},
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
const helpers = ['Playwright', 'WebDriver', 'Puppeteer', '
|
|
25
|
+
const helpers = ['Playwright', 'WebDriver', 'Puppeteer', 'REST', 'GraphQL', 'Appium', 'TestCafe', 'Nightmare'];
|
|
26
26
|
const translations = Object.keys(require('../../translations'));
|
|
27
27
|
|
|
28
28
|
const noTranslation = 'English (no localization)';
|
|
@@ -30,12 +30,15 @@ translations.unshift(noTranslation);
|
|
|
30
30
|
|
|
31
31
|
let packages;
|
|
32
32
|
|
|
33
|
-
const configHeader = `const { setHeadlessWhen } = require('@codeceptjs/configure');
|
|
33
|
+
const configHeader = `const { setHeadlessWhen, setCommonPlugins } = require('@codeceptjs/configure');
|
|
34
34
|
|
|
35
35
|
// turn on headless mode when running with HEADLESS=true environment variable
|
|
36
36
|
// export HEADLESS=true && npx codeceptjs run
|
|
37
37
|
setHeadlessWhen(process.env.HEADLESS);
|
|
38
38
|
|
|
39
|
+
// enable all common plugins https://github.com/codeceptjs/configure#setcommonplugins
|
|
40
|
+
setCommonPlugins();
|
|
41
|
+
|
|
39
42
|
`;
|
|
40
43
|
|
|
41
44
|
const defaultActor = `// in this file you can append custom step methods to 'I' object
|
|
@@ -150,19 +153,6 @@ module.exports = function (initPath) {
|
|
|
150
153
|
config.include.I = stepFile;
|
|
151
154
|
print(`Steps file created at ${stepFile}`);
|
|
152
155
|
|
|
153
|
-
config.plugins = {
|
|
154
|
-
pauseOnFail: {},
|
|
155
|
-
retryFailedStep: {
|
|
156
|
-
enabled: true,
|
|
157
|
-
},
|
|
158
|
-
tryTo: {
|
|
159
|
-
enabled: true,
|
|
160
|
-
},
|
|
161
|
-
screenshotOnFail: {
|
|
162
|
-
enabled: true,
|
|
163
|
-
},
|
|
164
|
-
};
|
|
165
|
-
|
|
166
156
|
let configSource = beautify(`exports.config = ${inspect(config, false, 4, false)}`);
|
|
167
157
|
|
|
168
158
|
if (require.resolve('@codeceptjs/configure') && isLocal && !initPath) {
|
|
@@ -73,6 +73,27 @@ function filterTests() {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
function initializeListeners() {
|
|
76
|
+
function simplifyError(error) {
|
|
77
|
+
if (error) {
|
|
78
|
+
const {
|
|
79
|
+
stack,
|
|
80
|
+
uncaught,
|
|
81
|
+
message,
|
|
82
|
+
actual,
|
|
83
|
+
expected,
|
|
84
|
+
} = error;
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
stack,
|
|
88
|
+
uncaught,
|
|
89
|
+
message,
|
|
90
|
+
actual,
|
|
91
|
+
expected,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
76
97
|
function simplifyTest(test, err = null) {
|
|
77
98
|
test = { ...test };
|
|
78
99
|
|
|
@@ -82,13 +103,10 @@ function initializeListeners() {
|
|
|
82
103
|
}
|
|
83
104
|
|
|
84
105
|
if (test.err) {
|
|
85
|
-
err =
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
actual: test.err.actual,
|
|
90
|
-
expected: test.err.expected,
|
|
91
|
-
};
|
|
106
|
+
err = simplifyError(test.err);
|
|
107
|
+
test.status = 'failed';
|
|
108
|
+
} else if (err) {
|
|
109
|
+
err = simplifyError(err);
|
|
92
110
|
test.status = 'failed';
|
|
93
111
|
}
|
|
94
112
|
const parent = {};
|
package/lib/config.js
CHANGED
|
@@ -38,6 +38,14 @@ const defaultConfig = {
|
|
|
38
38
|
let hooks = [];
|
|
39
39
|
let config = {};
|
|
40
40
|
|
|
41
|
+
const configFileNames = [
|
|
42
|
+
'codecept.config.js',
|
|
43
|
+
'codecept.conf.js',
|
|
44
|
+
'codecept.json',
|
|
45
|
+
'codecept.config.ts',
|
|
46
|
+
'codecept.conf.ts',
|
|
47
|
+
];
|
|
48
|
+
|
|
41
49
|
/**
|
|
42
50
|
* Current configuration
|
|
43
51
|
*/
|
|
@@ -59,6 +67,7 @@ class Config {
|
|
|
59
67
|
* If js file provided: require it and get .config key
|
|
60
68
|
* If json file provided: load and parse JSON
|
|
61
69
|
* If directory provided:
|
|
70
|
+
* * try to load `codecept.config.js` from it
|
|
62
71
|
* * try to load `codecept.conf.js` from it
|
|
63
72
|
* * try to load `codecept.json` from it
|
|
64
73
|
* If none of above: fail.
|
|
@@ -78,23 +87,18 @@ class Config {
|
|
|
78
87
|
return loadConfigFile(configFile);
|
|
79
88
|
}
|
|
80
89
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return loadConfigFile(jsConfig);
|
|
85
|
-
}
|
|
90
|
+
for (const name of configFileNames) {
|
|
91
|
+
// is path to directory
|
|
92
|
+
const jsConfig = path.join(configFile, name);
|
|
86
93
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
94
|
+
if (isFile(jsConfig)) {
|
|
95
|
+
return loadConfigFile(jsConfig);
|
|
96
|
+
}
|
|
90
97
|
}
|
|
91
98
|
|
|
92
|
-
const
|
|
93
|
-
if (isFile(tsConfig)) {
|
|
94
|
-
return loadConfigFile(tsConfig);
|
|
95
|
-
}
|
|
99
|
+
const configPaths = configFileNames.map(name => path.join(configFile, name)).join(' or ');
|
|
96
100
|
|
|
97
|
-
throw new Error(`Can not load config from ${
|
|
101
|
+
throw new Error(`Can not load config from ${configPaths}\nCodeceptJS is not initialized in this dir. Execute 'codeceptjs init' to start`);
|
|
98
102
|
}
|
|
99
103
|
|
|
100
104
|
/**
|
|
@@ -257,13 +257,16 @@ class ApiDataFactory extends Helper {
|
|
|
257
257
|
* // create user with defined email
|
|
258
258
|
* // and receive it when inside async function
|
|
259
259
|
* const user = await I.have('user', { email: 'user@user.com'});
|
|
260
|
+
* // create a user with options that will not be included in the final request
|
|
261
|
+
* I.have('user', { }, { age: 33, height: 55 })
|
|
260
262
|
* ```
|
|
261
263
|
*
|
|
262
264
|
* @param {*} factory factory to use
|
|
263
265
|
* @param {*} params predefined parameters
|
|
266
|
+
* @param {*} options options for programmatically generate the attributes
|
|
264
267
|
*/
|
|
265
|
-
have(factory, params) {
|
|
266
|
-
const item = this._createItem(factory, params);
|
|
268
|
+
have(factory, params, options) {
|
|
269
|
+
const item = this._createItem(factory, params, options);
|
|
267
270
|
this.debug(`Creating ${factory} ${JSON.stringify(item)}`);
|
|
268
271
|
return this._requestCreate(factory, item);
|
|
269
272
|
}
|
|
@@ -277,21 +280,25 @@ class ApiDataFactory extends Helper {
|
|
|
277
280
|
*
|
|
278
281
|
* // create 3 posts by one author
|
|
279
282
|
* I.haveMultiple('post', 3, { author: 'davert' });
|
|
283
|
+
*
|
|
284
|
+
* // create 3 posts by one author with options
|
|
285
|
+
* I.haveMultiple('post', 3, { author: 'davert' }, { publish_date: '01.01.1997' });
|
|
280
286
|
* ```
|
|
281
287
|
*
|
|
282
288
|
* @param {*} factory
|
|
283
289
|
* @param {*} times
|
|
284
290
|
* @param {*} params
|
|
291
|
+
* @param {*} options
|
|
285
292
|
*/
|
|
286
|
-
haveMultiple(factory, times, params) {
|
|
293
|
+
haveMultiple(factory, times, params, options) {
|
|
287
294
|
const promises = [];
|
|
288
295
|
for (let i = 0; i < times; i++) {
|
|
289
|
-
promises.push(this.have(factory, params));
|
|
296
|
+
promises.push(this.have(factory, params, options));
|
|
290
297
|
}
|
|
291
298
|
return Promise.all(promises);
|
|
292
299
|
}
|
|
293
300
|
|
|
294
|
-
_createItem(model, data) {
|
|
301
|
+
_createItem(model, data, options) {
|
|
295
302
|
if (!this.factories[model]) {
|
|
296
303
|
throw new Error(`Factory ${model} is not defined in config`);
|
|
297
304
|
}
|
|
@@ -303,7 +310,7 @@ class ApiDataFactory extends Helper {
|
|
|
303
310
|
modulePath = path.join(global.codecept_dir, modulePath);
|
|
304
311
|
}
|
|
305
312
|
const builder = require(modulePath);
|
|
306
|
-
return builder.build(data);
|
|
313
|
+
return builder.build(data, options);
|
|
307
314
|
} catch (err) {
|
|
308
315
|
throw new Error(`Couldn't load factory file from ${modulePath}, check that
|
|
309
316
|
|