codeceptjs 4.0.0-rc.22 → 4.0.0-rc.24
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/README.md +9 -10
- package/docs/ai.md +3 -51
- package/docs/architecture.md +16 -0
- package/docs/bootstrap.md +1 -1
- package/docs/continuous-integration.md +16 -44
- package/docs/custom-helpers.md +1 -1
- package/docs/detox.md +1 -1
- package/docs/docker.md +1 -30
- package/docs/examples.md +0 -1
- package/docs/helpers/Appium.md +16 -2
- package/docs/helpers/Playwright.md +161 -160
- package/docs/helpers/Puppeteer.md +143 -250
- package/docs/helpers/WebDriver.md +134 -177
- package/docs/hooks.md +11 -1
- package/docs/index.md +1 -1
- package/docs/installation.md +2 -19
- package/docs/locators.md +1 -1
- package/docs/migrate-from-cypress.md +98 -0
- package/docs/migrate-from-java.md +108 -0
- package/docs/migrate-from-protractor.md +101 -0
- package/docs/migrate-from-testcafe.md +99 -0
- package/docs/migration-4.md +195 -8
- package/docs/plugins/aiTrace.md +49 -0
- package/docs/plugins/analyze.md +66 -0
- package/docs/plugins/auth.md +241 -0
- package/docs/plugins/autoDelay.md +48 -0
- package/docs/plugins/browser.md +41 -0
- package/docs/plugins/coverage.md +39 -0
- package/docs/plugins/customLocator.md +119 -0
- package/docs/plugins/customReporter.md +16 -0
- package/docs/plugins/expose.md +75 -0
- package/docs/plugins/heal.md +44 -0
- package/docs/plugins/junitReporter.md +51 -0
- package/docs/plugins/pageInfo.md +34 -0
- package/docs/plugins/pause.md +43 -0
- package/docs/plugins/pauseOnFail.md +18 -0
- package/docs/plugins/retryFailedStep.md +75 -0
- package/docs/plugins/screencast.md +55 -0
- package/docs/plugins/screenshot.md +58 -0
- package/docs/plugins/screenshotOnFail.md +18 -0
- package/docs/plugins/stepTimeout.md +65 -0
- package/docs/plugins.md +40 -862
- package/docs/reports.md +18 -4
- package/docs/retry.md +48 -18
- package/docs/store.md +94 -0
- package/docs/timeouts.md +1 -1
- package/docs/tutorial.md +207 -155
- package/docs/webdriver.md +6 -73
- package/lib/actor.js +1 -36
- package/lib/command/run-multiple.js +1 -2
- package/lib/heal.js +2 -2
- package/lib/helper/Playwright.js +1 -15
- package/lib/helper/Puppeteer.js +0 -103
- package/lib/helper/WebDriver.js +1 -28
- package/lib/helper/extras/PlaywrightLocator.js +10 -0
- package/lib/locator.js +0 -13
- package/lib/plugin/aiTrace.js +4 -3
- package/lib/plugin/analyze.js +3 -4
- package/lib/plugin/junitReporter.js +1 -1
- package/lib/plugin/pauseOnFail.js +3 -1
- package/lib/plugin/retryFailedStep.js +11 -10
- package/lib/plugin/screencast.js +1 -1
- package/lib/plugin/screenshot.js +2 -7
- package/lib/plugin/screenshotOnFail.js +3 -1
- package/lib/plugin/stepTimeout.js +3 -2
- package/lib/recorder.js +1 -1
- package/lib/step/base.js +7 -7
- package/lib/step/comment.js +2 -2
- package/lib/step/helper.js +4 -4
- package/lib/step/meta.js +3 -3
- package/lib/step/record.js +3 -3
- package/lib/workers.js +0 -4
- package/package.json +3 -4
- package/docs/helpers/Mochawesome.md +0 -8
- package/docs/helpers/MockServer.md +0 -212
- package/docs/helpers/Polly.md +0 -44
- package/docs/helpers/Protractor.md +0 -1769
- package/docs/helpers/SoftExpectHelper.md +0 -352
- package/docs/react.md +0 -70
- package/lib/helper/Mochawesome.js +0 -96
- package/lib/helper/extras/PlaywrightReactVueLocator.js +0 -61
- package/lib/helper/extras/React.js +0 -65
|
@@ -8,7 +8,10 @@ const debug = debugModule('codeceptjs:retryFailedStep')
|
|
|
8
8
|
const defaultConfig = {
|
|
9
9
|
retries: 3,
|
|
10
10
|
defaultIgnoredSteps: ['amOnPage', 'wait*', 'send*', 'execute*', 'run*', 'have*'],
|
|
11
|
+
minTimeout: 150,
|
|
12
|
+
maxTimeout: 10000,
|
|
11
13
|
factor: 1.5,
|
|
14
|
+
randomize: false,
|
|
12
15
|
ignoredSteps: [],
|
|
13
16
|
deferToScenarioRetries: true,
|
|
14
17
|
}
|
|
@@ -44,10 +47,9 @@ const RETRY_PRIORITIES = {
|
|
|
44
47
|
* #### Configuration:
|
|
45
48
|
*
|
|
46
49
|
* * `retries` - number of retries (by default 3),
|
|
47
|
-
* * `when` - function, when to perform a retry (accepts error as parameter)
|
|
48
50
|
* * `factor` - The exponential factor to use. Default is 1.5.
|
|
49
|
-
* * `minTimeout` - The number of milliseconds before starting the first retry. Default is
|
|
50
|
-
* * `maxTimeout` - The maximum number of milliseconds between two retries. Default is
|
|
51
|
+
* * `minTimeout` - The number of milliseconds before starting the first retry. Default is 150.
|
|
52
|
+
* * `maxTimeout` - The maximum number of milliseconds between two retries. Default is 10000.
|
|
51
53
|
* * `randomize` - Randomizes the timeouts by multiplying with a factor from 1 to 2. Default is false.
|
|
52
54
|
* * `defaultIgnoredSteps` - an array of steps to be ignored for retry. Includes:
|
|
53
55
|
* * `amOnPage`
|
|
@@ -77,7 +79,7 @@ const RETRY_PRIORITIES = {
|
|
|
77
79
|
*
|
|
78
80
|
* #### Disable Per Test
|
|
79
81
|
*
|
|
80
|
-
* This plugin can be disabled per test. In this case you will need to
|
|
82
|
+
* This plugin can be disabled per test. In this case you will need to add `step.retry()` to all flaky steps:
|
|
81
83
|
*
|
|
82
84
|
* Use scenario configuration to disable plugin for a test
|
|
83
85
|
*
|
|
@@ -89,9 +91,8 @@ const RETRY_PRIORITIES = {
|
|
|
89
91
|
*
|
|
90
92
|
*/
|
|
91
93
|
export default function (config) {
|
|
92
|
-
config = Object.assign(defaultConfig, config)
|
|
94
|
+
config = Object.assign({}, defaultConfig, config)
|
|
93
95
|
config.ignoredSteps = config.ignoredSteps.concat(config.defaultIgnoredSteps)
|
|
94
|
-
const customWhen = config.when
|
|
95
96
|
|
|
96
97
|
let enableRetry = false
|
|
97
98
|
|
|
@@ -101,7 +102,6 @@ export default function (config) {
|
|
|
101
102
|
if (!store.autoRetries) return false
|
|
102
103
|
if (err && err.isTerminal) return false
|
|
103
104
|
if (err && err.message && (err.message.includes('ERR_ABORTED') || err.message.includes('frame was detached') || err.message.includes('Target page, context or browser has been closed'))) return false
|
|
104
|
-
if (customWhen) return customWhen(err)
|
|
105
105
|
return true
|
|
106
106
|
}
|
|
107
107
|
config.when = when
|
|
@@ -111,11 +111,12 @@ export default function (config) {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
event.dispatcher.on(event.step.started, step => {
|
|
114
|
+
if (!step.title) return
|
|
114
115
|
for (const ignored of config.ignoredSteps) {
|
|
115
|
-
if (step.
|
|
116
|
+
if (step.title === ignored) return
|
|
116
117
|
if (ignored instanceof RegExp) {
|
|
117
|
-
if (step.
|
|
118
|
-
} else if (ignored.indexOf('*') && step.
|
|
118
|
+
if (step.title.match(ignored)) return
|
|
119
|
+
} else if (ignored.indexOf('*') && step.title.startsWith(ignored.slice(0, -1))) return
|
|
119
120
|
}
|
|
120
121
|
enableRetry = true
|
|
121
122
|
})
|
package/lib/plugin/screencast.js
CHANGED
|
@@ -258,7 +258,7 @@ function formatTimestamp(timestampInMs) {
|
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
function stepTitle(step) {
|
|
261
|
-
let title = `${step.actor}.${step.
|
|
261
|
+
let title = `${step.actor}.${step.title}(${step.args ? step.args.join(',') : ''})`
|
|
262
262
|
if (title.length > 100) title = `${title.substring(0, 100)}...`
|
|
263
263
|
return title
|
|
264
264
|
}
|
package/lib/plugin/screenshot.js
CHANGED
|
@@ -86,14 +86,9 @@ export default function (config = {}) {
|
|
|
86
86
|
const trigger = resolveTrigger(cliArgs, config, { on: defaultConfig.on }, { name: 'screenshot' })
|
|
87
87
|
if (!trigger) return
|
|
88
88
|
|
|
89
|
-
const helpers = Container.helpers()
|
|
90
89
|
const options = Object.assign({}, defaultConfig, helper.options, config)
|
|
91
90
|
options.slides = cliArgs.slides ?? config.slides ?? defaultConfig.slides
|
|
92
91
|
|
|
93
|
-
if (helpers.Mochawesome?.config) {
|
|
94
|
-
options.uniqueScreenshotNames = helpers.Mochawesome.config.uniqueScreenshotNames
|
|
95
|
-
}
|
|
96
|
-
|
|
97
92
|
if (Codeceptjs.container.mocha()) {
|
|
98
93
|
options.reportDir = Codeceptjs.container.mocha()?.options?.reporterOptions
|
|
99
94
|
&& Codeceptjs.container.mocha()?.options?.reporterOptions?.reportDir
|
|
@@ -325,7 +320,7 @@ function wireSlides(options, trigger) {
|
|
|
325
320
|
if (stepNum === -1) return
|
|
326
321
|
if (savedStep === step) return
|
|
327
322
|
if (scenarioFailed) return
|
|
328
|
-
if (step.metaStep && step.metaStep.
|
|
323
|
+
if (step.metaStep && step.metaStep.title === 'BeforeSuite') return
|
|
329
324
|
if (!currentTest) return
|
|
330
325
|
if (!stepFilter(step)) return
|
|
331
326
|
if (isStepIgnored(step, options.ignoreSteps)) return
|
|
@@ -404,7 +399,7 @@ function makeStepFilter(trigger, options) {
|
|
|
404
399
|
function isStepIgnored(step, patterns) {
|
|
405
400
|
if (!patterns || !patterns.length) return false
|
|
406
401
|
for (const pattern of patterns) {
|
|
407
|
-
if (step.
|
|
402
|
+
if (step.title && step.title.match(pattern)) return true
|
|
408
403
|
}
|
|
409
404
|
return false
|
|
410
405
|
}
|
|
@@ -4,7 +4,9 @@ import screenshot from './screenshot.js'
|
|
|
4
4
|
let warned = false
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* Saves a screenshot when a test fails.
|
|
8
|
+
*
|
|
9
|
+
* **Deprecated:** use the `screenshot` plugin with `on: 'fail'`, which is the default behavior.
|
|
8
10
|
*/
|
|
9
11
|
export default function (config = {}) {
|
|
10
12
|
if (!warned) {
|
|
@@ -32,7 +32,7 @@ const defaultConfig = {
|
|
|
32
32
|
* #### Configuration:
|
|
33
33
|
*
|
|
34
34
|
* * `timeout` - global step timeout, default 150 seconds
|
|
35
|
-
* * `overrideStepLimits` - whether to use timeouts set in plugin config to override step timeouts set in code with I.
|
|
35
|
+
* * `overrideStepLimits` - whether to use timeouts set in plugin config to override step timeouts set in code with `I.action(..., step.timeout(x))`, default false
|
|
36
36
|
* * `noTimeoutSteps` - an array of steps with no timeout. Default:
|
|
37
37
|
* * `amOnPage`
|
|
38
38
|
* * `wait*`
|
|
@@ -68,6 +68,7 @@ export default function(config) {
|
|
|
68
68
|
config.customTimeoutSteps = config.customTimeoutSteps.concat(config.noTimeoutSteps).concat(config.customTimeoutSteps)
|
|
69
69
|
|
|
70
70
|
event.dispatcher.on(event.step.before, step => {
|
|
71
|
+
if (!step.title) return
|
|
71
72
|
let stepTimeout
|
|
72
73
|
for (let stepRule of config.customTimeoutSteps) {
|
|
73
74
|
let customTimeout = 0
|
|
@@ -75,7 +76,7 @@ export default function(config) {
|
|
|
75
76
|
if (stepRule.length > 1) customTimeout = stepRule[1]
|
|
76
77
|
stepRule = stepRule[0]
|
|
77
78
|
}
|
|
78
|
-
if (stepRule instanceof RegExp ? step.
|
|
79
|
+
if (stepRule instanceof RegExp ? step.title.match(stepRule) : step.title === stepRule || (stepRule.indexOf('*') && step.title.startsWith(stepRule.slice(0, -1)))) {
|
|
79
80
|
stepTimeout = customTimeout
|
|
80
81
|
break
|
|
81
82
|
}
|
package/lib/recorder.js
CHANGED
|
@@ -217,7 +217,7 @@ export default {
|
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
const retryRules = this.retries.slice().reverse()
|
|
220
|
-
return promiseRetry(Object.assign(defaultRetryOptions, retryOpts), (retry, number) => {
|
|
220
|
+
return promiseRetry(Object.assign({}, defaultRetryOptions, retryOpts), (retry, number) => {
|
|
221
221
|
if (number > 1) output.log(`${currentQueue()}Retrying... Attempt #${number}`)
|
|
222
222
|
const [promise, timer] = getTimeoutPromise(timeout, taskName)
|
|
223
223
|
return Promise.race([promise, Promise.resolve(res).then(fn)])
|
package/lib/step/base.js
CHANGED
|
@@ -10,12 +10,12 @@ const STACK_LINE = 5
|
|
|
10
10
|
/**
|
|
11
11
|
* Each command in test executed through `I.` object is wrapped in Step.
|
|
12
12
|
* Step allows logging executed commands and triggers hook before and after step execution.
|
|
13
|
-
* @param {string}
|
|
13
|
+
* @param {string} title
|
|
14
14
|
*/
|
|
15
15
|
class Step {
|
|
16
|
-
constructor(
|
|
16
|
+
constructor(title) {
|
|
17
17
|
/** @member {string} */
|
|
18
|
-
this.
|
|
18
|
+
this.title = title
|
|
19
19
|
/** @member {Map<number, number>} */
|
|
20
20
|
this.timeouts = new Map()
|
|
21
21
|
|
|
@@ -43,7 +43,7 @@ class Step {
|
|
|
43
43
|
/** @member {any} */
|
|
44
44
|
this.helper = null
|
|
45
45
|
/** @member {string} */
|
|
46
|
-
this.helperMethod =
|
|
46
|
+
this.helperMethod = title
|
|
47
47
|
|
|
48
48
|
this.startTime = 0
|
|
49
49
|
this.endTime = 0
|
|
@@ -103,7 +103,7 @@ class Step {
|
|
|
103
103
|
|
|
104
104
|
/** @return {string} */
|
|
105
105
|
humanize() {
|
|
106
|
-
return humanizeString(this.
|
|
106
|
+
return humanizeString(this.title)
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
/** @return {string} */
|
|
@@ -180,7 +180,7 @@ class Step {
|
|
|
180
180
|
|
|
181
181
|
/** @return {string} */
|
|
182
182
|
toCode() {
|
|
183
|
-
return `${this.prefix}${this.actor}.${this.
|
|
183
|
+
return `${this.prefix}${this.actor}.${this.title}(${this.humanizeArgs()})${this.suffix}`
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
isMetaStep() {
|
|
@@ -223,7 +223,7 @@ class Step {
|
|
|
223
223
|
|
|
224
224
|
return {
|
|
225
225
|
opts: step.opts || {},
|
|
226
|
-
title: step.
|
|
226
|
+
title: step.title,
|
|
227
227
|
args: args,
|
|
228
228
|
status: step.status,
|
|
229
229
|
startTime: step.startTime,
|
package/lib/step/comment.js
CHANGED
package/lib/step/helper.js
CHANGED
|
@@ -2,12 +2,12 @@ import Step from './base.js'
|
|
|
2
2
|
import store from '../store.js'
|
|
3
3
|
|
|
4
4
|
class HelperStep extends Step {
|
|
5
|
-
constructor(helper,
|
|
6
|
-
super(
|
|
5
|
+
constructor(helper, title) {
|
|
6
|
+
super(title)
|
|
7
7
|
/** @member {CodeceptJS.Helper} helper corresponding helper */
|
|
8
8
|
this.helper = helper
|
|
9
|
-
/** @member {string} helperMethod
|
|
10
|
-
this.helperMethod =
|
|
9
|
+
/** @member {string} helperMethod title of method to be executed */
|
|
10
|
+
this.helperMethod = title
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
/**
|
package/lib/step/meta.js
CHANGED
|
@@ -29,7 +29,7 @@ class MetaStep extends Step {
|
|
|
29
29
|
const actorText = this.actor
|
|
30
30
|
|
|
31
31
|
if (this.isBDD()) {
|
|
32
|
-
return `${this.prefix}${actorText} ${this.
|
|
32
|
+
return `${this.prefix}${actorText} ${this.title} "${this.humanizeArgs()}${this.suffix}"`
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
if (actorText === 'I') {
|
|
@@ -37,14 +37,14 @@ class MetaStep extends Step {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
if (!this.actor) {
|
|
40
|
-
return `${this.
|
|
40
|
+
return `${this.title} ${this.humanizeArgs()}${this.suffix}`.trim()
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
return `On ${this.prefix}${actorText}: ${this.humanize()} ${this.humanizeArgs()}${this.suffix}`.trim()
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
humanize() {
|
|
47
|
-
return humanizeString(this.
|
|
47
|
+
return humanizeString(this.title)
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
setTrace() {}
|
package/lib/step/record.js
CHANGED
|
@@ -16,12 +16,12 @@ function recordStep(step, args) {
|
|
|
16
16
|
const { opts, timeout, retry } = stepConfig.getConfig()
|
|
17
17
|
|
|
18
18
|
if (opts) {
|
|
19
|
-
output.debug(`Step ${step.
|
|
19
|
+
output.debug(`Step ${step.title}: options applied ${JSON.stringify(opts)}`)
|
|
20
20
|
store.stepOptions = opts
|
|
21
21
|
step.opts = opts
|
|
22
22
|
}
|
|
23
23
|
if (timeout) {
|
|
24
|
-
output.debug(`Step ${step.
|
|
24
|
+
output.debug(`Step ${step.title} timeout ${timeout}s`)
|
|
25
25
|
step.setTimeout(timeout * 1000, TIMEOUT_ORDER.codeLimitTime)
|
|
26
26
|
}
|
|
27
27
|
if (retry) retryStep(retry)
|
|
@@ -31,7 +31,7 @@ function recordStep(step, args) {
|
|
|
31
31
|
// run async before step hooks
|
|
32
32
|
event.emit(event.step.before, step)
|
|
33
33
|
|
|
34
|
-
const task = `${step.
|
|
34
|
+
const task = `${step.title}: ${step.humanizeArgs()}`
|
|
35
35
|
let val
|
|
36
36
|
|
|
37
37
|
// run step inside promise
|
package/lib/workers.js
CHANGED
|
@@ -118,11 +118,9 @@ const createWorkerObjects = (testGroups, config, testRoot, options, selectedRuns
|
|
|
118
118
|
const workersToExecute = []
|
|
119
119
|
|
|
120
120
|
const currentOutputFolder = config.output
|
|
121
|
-
let currentMochawesomeReportDir
|
|
122
121
|
let currentMochaJunitReporterFile
|
|
123
122
|
|
|
124
123
|
if (config.mocha && config.mocha.reporterOptions) {
|
|
125
|
-
currentMochawesomeReportDir = config.mocha.reporterOptions?.mochawesome.options.reportDir
|
|
126
124
|
currentMochaJunitReporterFile = config.mocha.reporterOptions['mocha-junit-reporter'].options.mochaFile
|
|
127
125
|
}
|
|
128
126
|
|
|
@@ -132,8 +130,6 @@ const createWorkerObjects = (testGroups, config, testRoot, options, selectedRuns
|
|
|
132
130
|
let workerName = worker.name.replace(':', '_')
|
|
133
131
|
_config.output = `${currentOutputFolder}${separator}${workerName}`
|
|
134
132
|
if (config.mocha && config.mocha.reporterOptions) {
|
|
135
|
-
_config.mocha.reporterOptions.mochawesome.options.reportDir = `${currentMochawesomeReportDir}${separator}${workerName}`
|
|
136
|
-
|
|
137
133
|
const _tempArray = currentMochaJunitReporterFile.split(separator)
|
|
138
134
|
_tempArray.splice(
|
|
139
135
|
_tempArray.findIndex(item => item.includes('.xml')),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeceptjs",
|
|
3
|
-
"version": "4.0.0-rc.
|
|
3
|
+
"version": "4.0.0-rc.24",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Supercharged End 2 End Testing Framework for NodeJS",
|
|
6
6
|
"keywords": [
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"translations",
|
|
28
28
|
"typings/**/*.d.ts",
|
|
29
29
|
"docs/*.md",
|
|
30
|
-
"docs/helpers/**"
|
|
30
|
+
"docs/helpers/**",
|
|
31
|
+
"docs/plugins/**"
|
|
31
32
|
],
|
|
32
33
|
"main": "lib/index.js",
|
|
33
34
|
"module": "lib/index.js",
|
|
@@ -130,7 +131,6 @@
|
|
|
130
131
|
"parse-function": "5.6.10",
|
|
131
132
|
"parse5": "7.3.0",
|
|
132
133
|
"promise-retry": "1.1.1",
|
|
133
|
-
"resq": "1.11.0",
|
|
134
134
|
"sprintf-js": "1.1.3",
|
|
135
135
|
"uuid": "11.1.0",
|
|
136
136
|
"xpath": "0.0.34",
|
|
@@ -175,7 +175,6 @@
|
|
|
175
175
|
"jsdoc": "^3.6.11",
|
|
176
176
|
"jsdoc-typeof-plugin": "1.0.0",
|
|
177
177
|
"json-server": "0.17.4",
|
|
178
|
-
"mochawesome": "^7.1.3",
|
|
179
178
|
"playwright": "^1.59.0",
|
|
180
179
|
"prettier": "^3.3.2",
|
|
181
180
|
"puppeteer": "24.36.0",
|
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
permalink: /helpers/MockServer
|
|
3
|
-
editLink: false
|
|
4
|
-
sidebar: auto
|
|
5
|
-
title: MockServer
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
|
|
9
|
-
|
|
10
|
-
## MockServer
|
|
11
|
-
|
|
12
|
-
MockServer
|
|
13
|
-
|
|
14
|
-
The MockServer Helper in CodeceptJS empowers you to mock any server or service via HTTP or HTTPS, making it an excellent tool for simulating REST endpoints and other HTTP-based APIs.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
## Configuration
|
|
19
|
-
|
|
20
|
-
This helper should be configured in codecept.conf.(js|ts)
|
|
21
|
-
|
|
22
|
-
Type: [object][1]
|
|
23
|
-
|
|
24
|
-
### Properties
|
|
25
|
-
|
|
26
|
-
- `port` **[number][2]?** Mock server port
|
|
27
|
-
- `host` **[string][3]?** Mock server host
|
|
28
|
-
- `httpsOpts` **[object][1]?** key & cert values are the paths to .key and .crt files
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
#### Examples
|
|
33
|
-
|
|
34
|
-
You can seamlessly integrate MockServer with other helpers like REST or Playwright. Here's a configuration example inside the `codecept.conf.js` file:
|
|
35
|
-
|
|
36
|
-
```javascript
|
|
37
|
-
{
|
|
38
|
-
helpers: {
|
|
39
|
-
REST: {...},
|
|
40
|
-
MockServer: {
|
|
41
|
-
// default mock server config
|
|
42
|
-
port: 9393,
|
|
43
|
-
host: '0.0.0.0',
|
|
44
|
-
httpsOpts: {
|
|
45
|
-
key: '',
|
|
46
|
-
cert: '',
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
#### Adding Interactions
|
|
54
|
-
|
|
55
|
-
Interactions add behavior to the mock server. Use the `I.addInteractionToMockServer()` method to include interactions. It takes an interaction object as an argument, containing request and response details.
|
|
56
|
-
|
|
57
|
-
```javascript
|
|
58
|
-
I.addInteractionToMockServer({
|
|
59
|
-
request: {
|
|
60
|
-
method: 'GET',
|
|
61
|
-
path: '/api/hello'
|
|
62
|
-
},
|
|
63
|
-
response: {
|
|
64
|
-
status: 200,
|
|
65
|
-
body: {
|
|
66
|
-
'say': 'hello to mock server'
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
#### Request Matching
|
|
73
|
-
|
|
74
|
-
When a real request is sent to the mock server, it matches the received request with the interactions. If a match is found, it returns the specified response; otherwise, a 404 status code is returned.
|
|
75
|
-
|
|
76
|
-
- Strong match on HTTP Method, Path, Query Params & JSON body.
|
|
77
|
-
- Loose match on Headers.
|
|
78
|
-
|
|
79
|
-
##### Strong Match on Query Params
|
|
80
|
-
|
|
81
|
-
You can send different responses based on query parameters:
|
|
82
|
-
|
|
83
|
-
```javascript
|
|
84
|
-
I.addInteractionToMockServer({
|
|
85
|
-
request: {
|
|
86
|
-
method: 'GET',
|
|
87
|
-
path: '/api/users',
|
|
88
|
-
queryParams: {
|
|
89
|
-
id: 1
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
response: {
|
|
93
|
-
status: 200,
|
|
94
|
-
body: 'user 1'
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
I.addInteractionToMockServer({
|
|
99
|
-
request: {
|
|
100
|
-
method: 'GET',
|
|
101
|
-
path: '/api/users',
|
|
102
|
-
queryParams: {
|
|
103
|
-
id: 2
|
|
104
|
-
}
|
|
105
|
-
},
|
|
106
|
-
response: {
|
|
107
|
-
status: 200,
|
|
108
|
-
body: 'user 2'
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
- GET to `/api/users?id=1` will return 'user 1'.
|
|
114
|
-
- GET to `/api/users?id=2` will return 'user 2'.
|
|
115
|
-
- For all other requests, it returns a 404 status code.
|
|
116
|
-
|
|
117
|
-
##### Loose Match on Body
|
|
118
|
-
|
|
119
|
-
When `strict` is set to false, it performs a loose match on query params and response body:
|
|
120
|
-
|
|
121
|
-
```javascript
|
|
122
|
-
I.addInteractionToMockServer({
|
|
123
|
-
strict: false,
|
|
124
|
-
request: {
|
|
125
|
-
method: 'POST',
|
|
126
|
-
path: '/api/users',
|
|
127
|
-
body: {
|
|
128
|
-
name: 'john'
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
|
-
response: {
|
|
132
|
-
status: 200
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
- POST to `/api/users` with the body containing `name` as 'john' will return a 200 status code.
|
|
138
|
-
- POST to `/api/users` without the `name` property in the body will return a 404 status code.
|
|
139
|
-
|
|
140
|
-
Happy testing with MockServer in CodeceptJS! 🚀
|
|
141
|
-
|
|
142
|
-
## Methods
|
|
143
|
-
|
|
144
|
-
### Parameters
|
|
145
|
-
|
|
146
|
-
- `passedConfig`
|
|
147
|
-
|
|
148
|
-
### addInteractionToMockServer
|
|
149
|
-
|
|
150
|
-
An interaction adds behavior to the mock server
|
|
151
|
-
|
|
152
|
-
```js
|
|
153
|
-
I.addInteractionToMockServer({
|
|
154
|
-
request: {
|
|
155
|
-
method: 'GET',
|
|
156
|
-
path: '/api/hello'
|
|
157
|
-
},
|
|
158
|
-
response: {
|
|
159
|
-
status: 200,
|
|
160
|
-
body: {
|
|
161
|
-
'say': 'hello to mock server'
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
```js
|
|
168
|
-
// with query params
|
|
169
|
-
I.addInteractionToMockServer({
|
|
170
|
-
request: {
|
|
171
|
-
method: 'GET',
|
|
172
|
-
path: '/api/hello',
|
|
173
|
-
queryParams: {
|
|
174
|
-
id: 2
|
|
175
|
-
}
|
|
176
|
-
},
|
|
177
|
-
response: {
|
|
178
|
-
status: 200,
|
|
179
|
-
body: {
|
|
180
|
-
'say': 'hello to mock server'
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
});
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
#### Parameters
|
|
187
|
-
|
|
188
|
-
- `interaction` **(CodeceptJS.MockInteraction | [object][1])** add behavior to the mock server
|
|
189
|
-
|
|
190
|
-
Returns **any** void
|
|
191
|
-
|
|
192
|
-
### startMockServer
|
|
193
|
-
|
|
194
|
-
Start the mock server
|
|
195
|
-
|
|
196
|
-
#### Parameters
|
|
197
|
-
|
|
198
|
-
- `port` **[number][2]?** start the mock server with given port
|
|
199
|
-
|
|
200
|
-
Returns **any** void
|
|
201
|
-
|
|
202
|
-
### stopMockServer
|
|
203
|
-
|
|
204
|
-
Stop the mock server
|
|
205
|
-
|
|
206
|
-
Returns **any** void
|
|
207
|
-
|
|
208
|
-
[1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
|
|
209
|
-
|
|
210
|
-
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
|
|
211
|
-
|
|
212
|
-
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
|
package/docs/helpers/Polly.md
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
id: Polly
|
|
3
|
-
title: Polly
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
|
|
7
|
-
|
|
8
|
-
## Polly
|
|
9
|
-
|
|
10
|
-
**Extends MockRequest**
|
|
11
|
-
|
|
12
|
-
This helper works the same as MockRequest helper. It has been included for backwards compatibility
|
|
13
|
-
reasons. So use MockRequest helper instead of this.
|
|
14
|
-
|
|
15
|
-
Please refer to MockRequest helper documentation for details.
|
|
16
|
-
|
|
17
|
-
### Installations
|
|
18
|
-
|
|
19
|
-
Requires [Polly.js][1] library by Netflix installed
|
|
20
|
-
|
|
21
|
-
npm i @pollyjs/core @pollyjs/adapter-puppeteer --save-dev
|
|
22
|
-
|
|
23
|
-
Requires Puppeteer helper or WebDriver helper enabled
|
|
24
|
-
|
|
25
|
-
### Configuration
|
|
26
|
-
|
|
27
|
-
Just enable helper in config file:
|
|
28
|
-
|
|
29
|
-
```js
|
|
30
|
-
helpers: {
|
|
31
|
-
Puppeteer: {
|
|
32
|
-
// regular Puppeteer config here
|
|
33
|
-
},
|
|
34
|
-
Polly: {}
|
|
35
|
-
}
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
The same can be done when using WebDriver helper..
|
|
39
|
-
|
|
40
|
-
### Usage
|
|
41
|
-
|
|
42
|
-
Use `I.mockRequest` to intercept and mock requests.
|
|
43
|
-
|
|
44
|
-
[1]: https://netflix.github.io/pollyjs/#/
|