codeceptjs 4.0.0-beta.4 → 4.0.0-beta.5
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 +134 -119
- package/bin/codecept.js +12 -2
- package/bin/test-server.js +53 -0
- package/docs/webapi/clearCookie.mustache +1 -1
- package/lib/actor.js +66 -102
- package/lib/ai.js +130 -121
- package/lib/assert/empty.js +3 -5
- package/lib/assert/equal.js +4 -7
- package/lib/assert/include.js +4 -6
- package/lib/assert/throws.js +2 -4
- package/lib/assert/truth.js +2 -2
- package/lib/codecept.js +139 -87
- package/lib/command/check.js +201 -0
- package/lib/command/configMigrate.js +2 -4
- package/lib/command/definitions.js +8 -26
- package/lib/command/generate.js +10 -14
- package/lib/command/gherkin/snippets.js +75 -73
- package/lib/command/gherkin/steps.js +1 -1
- package/lib/command/info.js +42 -8
- package/lib/command/init.js +13 -12
- package/lib/command/interactive.js +10 -2
- package/lib/command/list.js +1 -1
- package/lib/command/run-multiple/chunk.js +48 -45
- package/lib/command/run-multiple.js +12 -35
- package/lib/command/run-workers.js +21 -58
- package/lib/command/utils.js +5 -6
- package/lib/command/workers/runTests.js +262 -220
- package/lib/container.js +386 -238
- package/lib/data/context.js +10 -13
- package/lib/data/dataScenarioConfig.js +8 -8
- package/lib/data/dataTableArgument.js +6 -6
- package/lib/data/table.js +5 -11
- package/lib/effects.js +223 -0
- package/lib/element/WebElement.js +327 -0
- package/lib/els.js +158 -0
- package/lib/event.js +21 -17
- package/lib/heal.js +88 -80
- package/lib/helper/AI.js +2 -1
- package/lib/helper/ApiDataFactory.js +3 -6
- package/lib/helper/Appium.js +47 -51
- package/lib/helper/FileSystem.js +3 -3
- package/lib/helper/GraphQLDataFactory.js +3 -3
- package/lib/helper/JSONResponse.js +75 -37
- package/lib/helper/Mochawesome.js +31 -9
- package/lib/helper/Nightmare.js +35 -53
- package/lib/helper/Playwright.js +262 -267
- package/lib/helper/Protractor.js +54 -77
- package/lib/helper/Puppeteer.js +246 -260
- package/lib/helper/REST.js +5 -17
- package/lib/helper/TestCafe.js +21 -44
- package/lib/helper/WebDriver.js +151 -170
- package/lib/helper/extras/Popup.js +22 -22
- package/lib/helper/testcafe/testcafe-utils.js +26 -27
- package/lib/listener/emptyRun.js +55 -0
- package/lib/listener/exit.js +7 -10
- package/lib/listener/{retry.js → globalRetry.js} +5 -5
- package/lib/listener/globalTimeout.js +165 -0
- package/lib/listener/helpers.js +15 -15
- package/lib/listener/mocha.js +1 -1
- package/lib/listener/result.js +12 -0
- package/lib/listener/retryEnhancer.js +85 -0
- package/lib/listener/steps.js +32 -18
- package/lib/listener/store.js +20 -0
- package/lib/mocha/asyncWrapper.js +231 -0
- package/lib/{interfaces → mocha}/bdd.js +3 -3
- package/lib/mocha/cli.js +308 -0
- package/lib/mocha/factory.js +104 -0
- package/lib/{interfaces → mocha}/featureConfig.js +32 -12
- package/lib/{interfaces → mocha}/gherkin.js +26 -28
- package/lib/mocha/hooks.js +112 -0
- package/lib/mocha/index.js +12 -0
- package/lib/mocha/inject.js +29 -0
- package/lib/{interfaces → mocha}/scenarioConfig.js +31 -7
- package/lib/mocha/suite.js +82 -0
- package/lib/mocha/test.js +181 -0
- package/lib/mocha/types.d.ts +42 -0
- package/lib/mocha/ui.js +232 -0
- package/lib/output.js +82 -62
- package/lib/pause.js +160 -138
- package/lib/plugin/analyze.js +396 -0
- package/lib/plugin/auth.js +435 -0
- package/lib/plugin/autoDelay.js +8 -8
- package/lib/plugin/autoLogin.js +3 -338
- package/lib/plugin/commentStep.js +6 -1
- package/lib/plugin/coverage.js +10 -19
- package/lib/plugin/customLocator.js +3 -3
- package/lib/plugin/customReporter.js +52 -0
- package/lib/plugin/eachElement.js +1 -1
- package/lib/plugin/fakerTransform.js +1 -1
- package/lib/plugin/heal.js +36 -9
- package/lib/plugin/htmlReporter.js +1947 -0
- package/lib/plugin/pageInfo.js +140 -0
- package/lib/plugin/retryFailedStep.js +17 -18
- package/lib/plugin/retryTo.js +2 -113
- package/lib/plugin/screenshotOnFail.js +17 -58
- package/lib/plugin/selenoid.js +15 -35
- package/lib/plugin/standardActingHelpers.js +4 -1
- package/lib/plugin/stepByStepReport.js +56 -17
- package/lib/plugin/stepTimeout.js +5 -12
- package/lib/plugin/subtitles.js +4 -4
- package/lib/plugin/tryTo.js +3 -102
- package/lib/plugin/wdio.js +8 -10
- package/lib/recorder.js +155 -124
- package/lib/rerun.js +43 -42
- package/lib/result.js +161 -0
- package/lib/secret.js +1 -1
- package/lib/step/base.js +239 -0
- package/lib/step/comment.js +10 -0
- package/lib/step/config.js +50 -0
- package/lib/step/func.js +46 -0
- package/lib/step/helper.js +50 -0
- package/lib/step/meta.js +99 -0
- package/lib/step/record.js +74 -0
- package/lib/step/retry.js +11 -0
- package/lib/step/section.js +55 -0
- package/lib/step.js +21 -332
- package/lib/steps.js +50 -0
- package/lib/store.js +37 -5
- package/lib/template/heal.js +2 -11
- package/lib/test-server.js +323 -0
- package/lib/timeout.js +66 -0
- package/lib/utils.js +351 -218
- package/lib/within.js +75 -55
- package/lib/workerStorage.js +2 -1
- package/lib/workers.js +386 -276
- package/package.json +76 -70
- package/translations/de-DE.js +4 -3
- package/translations/fr-FR.js +4 -3
- package/translations/index.js +1 -0
- package/translations/it-IT.js +4 -3
- package/translations/ja-JP.js +4 -3
- package/translations/nl-NL.js +76 -0
- package/translations/pl-PL.js +4 -3
- package/translations/pt-BR.js +4 -3
- package/translations/ru-RU.js +4 -3
- package/translations/utils.js +9 -0
- package/translations/zh-CN.js +4 -3
- package/translations/zh-TW.js +4 -3
- package/typings/index.d.ts +188 -186
- package/typings/promiseBasedTypes.d.ts +18 -705
- package/typings/types.d.ts +301 -804
- package/lib/cli.js +0 -256
- package/lib/helper/ExpectHelper.js +0 -391
- package/lib/helper/SoftExpectHelper.js +0 -381
- package/lib/listener/artifacts.js +0 -19
- package/lib/listener/timeout.js +0 -109
- package/lib/mochaFactory.js +0 -113
- package/lib/plugin/debugErrors.js +0 -67
- package/lib/scenario.js +0 -224
- package/lib/ui.js +0 -236
package/lib/helper/REST.js
CHANGED
|
@@ -205,10 +205,7 @@ class REST extends Helper {
|
|
|
205
205
|
|
|
206
206
|
if (request.data instanceof Secret) {
|
|
207
207
|
_debugRequest.data = '*****'
|
|
208
|
-
request.data =
|
|
209
|
-
typeof request.data === 'object' && !(request.data instanceof Secret)
|
|
210
|
-
? { ...request.data.toString() }
|
|
211
|
-
: request.data.toString()
|
|
208
|
+
request.data = typeof request.data === 'object' && !(request.data instanceof Secret) ? { ...request.data.toString() } : request.data.toString()
|
|
212
209
|
}
|
|
213
210
|
|
|
214
211
|
if (typeof request.data === 'string') {
|
|
@@ -221,9 +218,7 @@ class REST extends Helper {
|
|
|
221
218
|
await this.config.onRequest(request)
|
|
222
219
|
}
|
|
223
220
|
|
|
224
|
-
this.options.prettyPrintJson
|
|
225
|
-
? this.debugSection('Request', beautify(JSON.stringify(_debugRequest)))
|
|
226
|
-
: this.debugSection('Request', JSON.stringify(_debugRequest))
|
|
221
|
+
this.options.prettyPrintJson ? this.debugSection('Request', beautify(JSON.stringify(_debugRequest))) : this.debugSection('Request', JSON.stringify(_debugRequest))
|
|
227
222
|
|
|
228
223
|
if (this.options.printCurl) {
|
|
229
224
|
this.debugSection('CURL Request', curlize(request))
|
|
@@ -240,9 +235,7 @@ class REST extends Helper {
|
|
|
240
235
|
if (this.config.onResponse) {
|
|
241
236
|
await this.config.onResponse(response)
|
|
242
237
|
}
|
|
243
|
-
this.options.prettyPrintJson
|
|
244
|
-
? this.debugSection('Response', beautify(JSON.stringify(response.data)))
|
|
245
|
-
: this.debugSection('Response', JSON.stringify(response.data))
|
|
238
|
+
this.options.prettyPrintJson ? this.debugSection('Response', beautify(JSON.stringify(response.data))) : this.debugSection('Response', JSON.stringify(response.data))
|
|
246
239
|
return response
|
|
247
240
|
}
|
|
248
241
|
|
|
@@ -437,13 +430,8 @@ class REST extends Helper {
|
|
|
437
430
|
module.exports = REST
|
|
438
431
|
|
|
439
432
|
function curlize(request) {
|
|
440
|
-
if (request.data?.constructor.name.toLowerCase() === 'formdata')
|
|
441
|
-
|
|
442
|
-
let curl =
|
|
443
|
-
`curl --location --request ${request.method ? request.method.toUpperCase() : 'GET'} ${request.baseURL} `.replace(
|
|
444
|
-
"'",
|
|
445
|
-
'',
|
|
446
|
-
)
|
|
433
|
+
if (request.data?.constructor.name.toLowerCase() === 'formdata') return 'cURL is not printed as the request body is not a JSON'
|
|
434
|
+
let curl = `curl --location --request ${request.method ? request.method.toUpperCase() : 'GET'} ${request.baseURL} `.replace("'", '')
|
|
447
435
|
|
|
448
436
|
if (request.headers) {
|
|
449
437
|
Object.entries(request.headers).forEach(([key, value]) => {
|
package/lib/helper/TestCafe.js
CHANGED
|
@@ -21,9 +21,8 @@ const Locator = require('../locator')
|
|
|
21
21
|
/**
|
|
22
22
|
* Client Functions
|
|
23
23
|
*/
|
|
24
|
-
const getPageUrl =
|
|
25
|
-
const getHtmlSource = (
|
|
26
|
-
ClientFunction(() => document.getElementsByTagName('html')[0].innerHTML).with({ boundTestRun: t })
|
|
24
|
+
const getPageUrl = t => ClientFunction(() => document.location.href).with({ boundTestRun: t })
|
|
25
|
+
const getHtmlSource = t => ClientFunction(() => document.getElementsByTagName('html')[0].innerHTML).with({ boundTestRun: t })
|
|
27
26
|
|
|
28
27
|
/**
|
|
29
28
|
* Uses [TestCafe](https://github.com/DevExpress/testcafe) library to run cross-browser tests.
|
|
@@ -187,7 +186,7 @@ class TestCafe extends Helper {
|
|
|
187
186
|
assertionTimeout: this.options.waitForTimeout,
|
|
188
187
|
takeScreenshotsOnFails: true,
|
|
189
188
|
})
|
|
190
|
-
.catch(
|
|
189
|
+
.catch(err => {
|
|
191
190
|
this.debugSection('_before', `Error ${err.toString()}`)
|
|
192
191
|
this.isRunning = false
|
|
193
192
|
this.testcafe.close()
|
|
@@ -208,7 +207,7 @@ class TestCafe extends Helper {
|
|
|
208
207
|
skipJsErrors: true,
|
|
209
208
|
skipUncaughtErrors: true,
|
|
210
209
|
})
|
|
211
|
-
.catch(
|
|
210
|
+
.catch(err => {
|
|
212
211
|
this.debugSection('_before', `Error ${err.toString()}`)
|
|
213
212
|
this.isRunning = false
|
|
214
213
|
this.testcafe.close()
|
|
@@ -260,7 +259,7 @@ class TestCafe extends Helper {
|
|
|
260
259
|
await this.clearCookie()
|
|
261
260
|
|
|
262
261
|
// TODO IMHO that should only happen when
|
|
263
|
-
await this.executeScript(() => localStorage.clear()).catch(
|
|
262
|
+
await this.executeScript(() => localStorage.clear()).catch(err => {
|
|
264
263
|
if (!(err.message.indexOf("Storage is disabled inside 'data:' URLs.") > -1)) throw err
|
|
265
264
|
})
|
|
266
265
|
}
|
|
@@ -383,7 +382,6 @@ class TestCafe extends Helper {
|
|
|
383
382
|
* {{> refreshPage }}
|
|
384
383
|
*/
|
|
385
384
|
async refreshPage() {
|
|
386
|
-
// eslint-disable-next-line no-restricted-globals
|
|
387
385
|
return this.t.eval(() => location.reload(true), { boundTestRun: this.t }).catch(mapError)
|
|
388
386
|
}
|
|
389
387
|
|
|
@@ -394,9 +392,7 @@ class TestCafe extends Helper {
|
|
|
394
392
|
async waitForVisible(locator, sec) {
|
|
395
393
|
const timeout = sec ? sec * 1000 : undefined
|
|
396
394
|
|
|
397
|
-
return (await findElements.call(this, this.context, locator))
|
|
398
|
-
.with({ visibilityCheck: true, timeout })()
|
|
399
|
-
.catch(mapError)
|
|
395
|
+
return (await findElements.call(this, this.context, locator)).with({ visibilityCheck: true, timeout })().catch(mapError)
|
|
400
396
|
}
|
|
401
397
|
|
|
402
398
|
/**
|
|
@@ -565,7 +561,6 @@ class TestCafe extends Helper {
|
|
|
565
561
|
await this.t.click(optEl).catch(mapError)
|
|
566
562
|
continue
|
|
567
563
|
}
|
|
568
|
-
// eslint-disable-next-line no-empty
|
|
569
564
|
} catch (err) {}
|
|
570
565
|
|
|
571
566
|
try {
|
|
@@ -574,7 +569,6 @@ class TestCafe extends Helper {
|
|
|
574
569
|
if (await optEl.count) {
|
|
575
570
|
await this.t.click(optEl).catch(mapError)
|
|
576
571
|
}
|
|
577
|
-
// eslint-disable-next-line no-empty
|
|
578
572
|
} catch (err) {}
|
|
579
573
|
}
|
|
580
574
|
}
|
|
@@ -634,10 +628,7 @@ class TestCafe extends Helper {
|
|
|
634
628
|
els = (await findElements.call(this, this.context, 'body')).withText(text)
|
|
635
629
|
}
|
|
636
630
|
|
|
637
|
-
return this.t
|
|
638
|
-
.expect(els.filterVisible().count)
|
|
639
|
-
.eql(0, `Element with text "${text}" can still be seen`)
|
|
640
|
-
.catch(mapError)
|
|
631
|
+
return this.t.expect(els.filterVisible().count).eql(0, `Element with text "${text}" can still be seen`).catch(mapError)
|
|
641
632
|
}
|
|
642
633
|
|
|
643
634
|
/**
|
|
@@ -789,7 +780,7 @@ class TestCafe extends Helper {
|
|
|
789
780
|
* {{> wait }}
|
|
790
781
|
*/
|
|
791
782
|
async wait(sec) {
|
|
792
|
-
return new Promise(
|
|
783
|
+
return new Promise(done => {
|
|
793
784
|
setTimeout(done, sec * 1000)
|
|
794
785
|
})
|
|
795
786
|
}
|
|
@@ -938,10 +929,7 @@ class TestCafe extends Helper {
|
|
|
938
929
|
return ClientFunction(() => {
|
|
939
930
|
const body = document.body
|
|
940
931
|
const html = document.documentElement
|
|
941
|
-
window.scrollTo(
|
|
942
|
-
0,
|
|
943
|
-
Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight),
|
|
944
|
-
)
|
|
932
|
+
window.scrollTo(0, Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight))
|
|
945
933
|
})
|
|
946
934
|
.with({ boundTestRun: this.t })()
|
|
947
935
|
.catch(mapError)
|
|
@@ -957,7 +945,7 @@ class TestCafe extends Helper {
|
|
|
957
945
|
locator = null
|
|
958
946
|
}
|
|
959
947
|
|
|
960
|
-
const scrollBy = ClientFunction(
|
|
948
|
+
const scrollBy = ClientFunction(offset => {
|
|
961
949
|
if (window && window.scrollBy && offset) {
|
|
962
950
|
window.scrollBy(offset.x, offset.y)
|
|
963
951
|
}
|
|
@@ -1042,10 +1030,10 @@ class TestCafe extends Helper {
|
|
|
1042
1030
|
async grabCookie(name) {
|
|
1043
1031
|
if (!name) {
|
|
1044
1032
|
const getCookie = ClientFunction(() => {
|
|
1045
|
-
return document.cookie.split(';').map(
|
|
1033
|
+
return document.cookie.split(';').map(c => c.split('='))
|
|
1046
1034
|
}).with({ boundTestRun: this.t })
|
|
1047
1035
|
const cookies = await getCookie()
|
|
1048
|
-
return cookies.map(
|
|
1036
|
+
return cookies.map(cookie => ({ name: cookie[0].trim(), value: cookie[1] }))
|
|
1049
1037
|
}
|
|
1050
1038
|
const getCookie = ClientFunction(
|
|
1051
1039
|
() => {
|
|
@@ -1088,7 +1076,7 @@ class TestCafe extends Helper {
|
|
|
1088
1076
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
|
|
1089
1077
|
|
|
1090
1078
|
const clientFn = createClientFunction(
|
|
1091
|
-
|
|
1079
|
+
urlPart => {
|
|
1092
1080
|
const currUrl = decodeURIComponent(decodeURIComponent(decodeURIComponent(window.location.href)))
|
|
1093
1081
|
return currUrl.indexOf(urlPart) > -1
|
|
1094
1082
|
},
|
|
@@ -1113,7 +1101,7 @@ class TestCafe extends Helper {
|
|
|
1113
1101
|
}
|
|
1114
1102
|
|
|
1115
1103
|
const clientFn = createClientFunction(
|
|
1116
|
-
|
|
1104
|
+
urlPart => {
|
|
1117
1105
|
const currUrl = decodeURIComponent(decodeURIComponent(decodeURIComponent(window.location.href)))
|
|
1118
1106
|
return currUrl === urlPart
|
|
1119
1107
|
},
|
|
@@ -1174,9 +1162,7 @@ class TestCafe extends Helper {
|
|
|
1174
1162
|
async waitToHide(locator, sec) {
|
|
1175
1163
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
|
|
1176
1164
|
|
|
1177
|
-
return this.t
|
|
1178
|
-
.expect(createSelector(locator).filterHidden().with({ boundTestRun: this.t }).exists)
|
|
1179
|
-
.notOk({ timeout: waitTimeout })
|
|
1165
|
+
return this.t.expect(createSelector(locator).filterHidden().with({ boundTestRun: this.t }).exists).notOk({ timeout: waitTimeout })
|
|
1180
1166
|
}
|
|
1181
1167
|
|
|
1182
1168
|
/**
|
|
@@ -1185,9 +1171,7 @@ class TestCafe extends Helper {
|
|
|
1185
1171
|
async waitForInvisible(locator, sec) {
|
|
1186
1172
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
|
|
1187
1173
|
|
|
1188
|
-
return this.t
|
|
1189
|
-
.expect(createSelector(locator).filterVisible().with({ boundTestRun: this.t }).exists)
|
|
1190
|
-
.ok({ timeout: waitTimeout })
|
|
1174
|
+
return this.t.expect(createSelector(locator).filterVisible().with({ boundTestRun: this.t }).exists).ok({ timeout: waitTimeout })
|
|
1191
1175
|
}
|
|
1192
1176
|
|
|
1193
1177
|
/**
|
|
@@ -1214,7 +1198,7 @@ class TestCafe extends Helper {
|
|
|
1214
1198
|
|
|
1215
1199
|
async function waitForFunction(browserFn, waitTimeout) {
|
|
1216
1200
|
const pause = () =>
|
|
1217
|
-
new Promise(
|
|
1201
|
+
new Promise(done => {
|
|
1218
1202
|
setTimeout(done, 50)
|
|
1219
1203
|
})
|
|
1220
1204
|
|
|
@@ -1238,13 +1222,13 @@ async function waitForFunction(browserFn, waitTimeout) {
|
|
|
1238
1222
|
}
|
|
1239
1223
|
}
|
|
1240
1224
|
|
|
1241
|
-
const createSelector =
|
|
1225
|
+
const createSelector = locator => {
|
|
1242
1226
|
locator = new Locator(locator, 'css')
|
|
1243
1227
|
if (locator.isXPath()) return elementByXPath(locator.value)
|
|
1244
1228
|
return Selector(locator.simplify())
|
|
1245
1229
|
}
|
|
1246
1230
|
|
|
1247
|
-
const elementByXPath =
|
|
1231
|
+
const elementByXPath = xpath => {
|
|
1248
1232
|
assert(xpath, 'xpath is required')
|
|
1249
1233
|
|
|
1250
1234
|
return Selector(
|
|
@@ -1277,9 +1261,7 @@ async function findElements(matcher, locator) {
|
|
|
1277
1261
|
locator = new Locator(locator, 'css')
|
|
1278
1262
|
|
|
1279
1263
|
if (!locator.isXPath()) {
|
|
1280
|
-
return matcher
|
|
1281
|
-
? matcher.find(locator.simplify())
|
|
1282
|
-
: Selector(locator.simplify()).with({ timeout: 0, boundTestRun: this.t })
|
|
1264
|
+
return matcher ? matcher.find(locator.simplify()) : Selector(locator.simplify()).with({ timeout: 0, boundTestRun: this.t })
|
|
1283
1265
|
}
|
|
1284
1266
|
|
|
1285
1267
|
if (!matcher) return elementByXPath(locator.value).with({ timeout: 0, boundTestRun: this.t })
|
|
@@ -1308,12 +1290,7 @@ async function proceedClick(locator, context = null) {
|
|
|
1308
1290
|
|
|
1309
1291
|
const els = await findClickable.call(this, matcher, locator)
|
|
1310
1292
|
if (context) {
|
|
1311
|
-
await assertElementExists(
|
|
1312
|
-
els,
|
|
1313
|
-
locator,
|
|
1314
|
-
'Clickable element',
|
|
1315
|
-
`was not found inside element ${new Locator(context).toString()}`,
|
|
1316
|
-
)
|
|
1293
|
+
await assertElementExists(els, locator, 'Clickable element', `was not found inside element ${new Locator(context).toString()}`)
|
|
1317
1294
|
} else {
|
|
1318
1295
|
await assertElementExists(els, locator, 'Clickable element')
|
|
1319
1296
|
}
|