codeceptjs 3.5.6 → 3.5.7-beta.1
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 +2950 -0
- package/docs/bdd.md +11 -7
- package/docs/build/ApiDataFactory.js +2 -1
- package/docs/build/Appium.js +25 -23
- package/docs/build/Expect.js +422 -0
- package/docs/build/Nightmare.js +53 -56
- package/docs/build/Playwright.js +166 -103
- package/docs/build/Protractor.js +66 -69
- package/docs/build/Puppeteer.js +79 -79
- package/docs/build/TestCafe.js +56 -55
- package/docs/build/WebDriver.js +81 -82
- package/docs/changelog.md +388 -1
- package/docs/commands.md +12 -0
- package/docs/community-helpers.md +8 -4
- package/docs/examples.md +8 -2
- package/docs/helpers/Appium.md +50 -32
- package/docs/helpers/Expect.md +275 -0
- package/docs/helpers/Nightmare.md +141 -94
- package/docs/helpers/Playwright.md +280 -211
- package/docs/helpers/Protractor.md +229 -169
- package/docs/helpers/Puppeteer.md +256 -185
- package/docs/helpers/TestCafe.md +201 -149
- package/docs/helpers/WebDriver.md +252 -178
- package/docs/mobile.md +17 -21
- package/docs/plugins.md +35 -1
- package/docs/webapi/amOnPage.mustache +1 -1
- package/docs/webapi/appendField.mustache +1 -1
- package/docs/webapi/attachFile.mustache +1 -1
- package/docs/webapi/blur.mustache +1 -0
- package/docs/webapi/checkOption.mustache +1 -1
- package/docs/webapi/clearCookie.mustache +1 -1
- package/docs/webapi/clearField.mustache +1 -1
- package/docs/webapi/click.mustache +1 -1
- package/docs/webapi/clickLink.mustache +1 -1
- package/docs/webapi/closeCurrentTab.mustache +1 -1
- package/docs/webapi/closeOtherTabs.mustache +1 -1
- package/docs/webapi/dontSee.mustache +1 -1
- package/docs/webapi/dontSeeCheckboxIsChecked.mustache +1 -1
- package/docs/webapi/dontSeeCookie.mustache +1 -1
- package/docs/webapi/dontSeeCurrentUrlEquals.mustache +1 -1
- package/docs/webapi/dontSeeElement.mustache +1 -1
- package/docs/webapi/dontSeeElementInDOM.mustache +1 -1
- package/docs/webapi/dontSeeInCurrentUrl.mustache +1 -1
- package/docs/webapi/dontSeeInField.mustache +1 -1
- package/docs/webapi/dontSeeInSource.mustache +1 -1
- package/docs/webapi/dontSeeInTitle.mustache +1 -1
- package/docs/webapi/doubleClick.mustache +1 -1
- package/docs/webapi/downloadFile.mustache +1 -1
- package/docs/webapi/dragAndDrop.mustache +1 -1
- package/docs/webapi/dragSlider.mustache +1 -1
- package/docs/webapi/executeAsyncScript.mustache +0 -2
- package/docs/webapi/executeScript.mustache +0 -2
- package/docs/webapi/fillField.mustache +1 -1
- package/docs/webapi/focus.mustache +1 -0
- package/docs/webapi/forceClick.mustache +1 -1
- package/docs/webapi/forceRightClick.mustache +1 -1
- package/docs/webapi/grabCookie.mustache +1 -1
- package/docs/webapi/grabDataFromPerformanceTiming.mustache +1 -1
- package/docs/webapi/moveCursorTo.mustache +1 -1
- package/docs/webapi/openNewTab.mustache +1 -1
- package/docs/webapi/pressKey.mustache +1 -1
- package/docs/webapi/pressKeyDown.mustache +1 -1
- package/docs/webapi/pressKeyUp.mustache +1 -1
- package/docs/webapi/pressKeyWithKeyNormalization.mustache +1 -1
- package/docs/webapi/refreshPage.mustache +1 -1
- package/docs/webapi/resizeWindow.mustache +1 -1
- package/docs/webapi/rightClick.mustache +1 -1
- package/docs/webapi/saveElementScreenshot.mustache +1 -1
- package/docs/webapi/saveScreenshot.mustache +1 -1
- package/docs/webapi/say.mustache +1 -1
- package/docs/webapi/scrollIntoView.mustache +1 -1
- package/docs/webapi/scrollPageToBottom.mustache +1 -1
- package/docs/webapi/scrollPageToTop.mustache +1 -1
- package/docs/webapi/scrollTo.mustache +1 -1
- package/docs/webapi/see.mustache +1 -1
- package/docs/webapi/seeAttributesOnElements.mustache +1 -1
- package/docs/webapi/seeCheckboxIsChecked.mustache +1 -1
- package/docs/webapi/seeCookie.mustache +1 -1
- package/docs/webapi/seeCssPropertiesOnElements.mustache +1 -1
- package/docs/webapi/seeCurrentUrlEquals.mustache +1 -1
- package/docs/webapi/seeElement.mustache +1 -1
- package/docs/webapi/seeElementInDOM.mustache +1 -1
- package/docs/webapi/seeInCurrentUrl.mustache +1 -1
- package/docs/webapi/seeInField.mustache +1 -1
- package/docs/webapi/seeInPopup.mustache +1 -1
- package/docs/webapi/seeInSource.mustache +1 -1
- package/docs/webapi/seeInTitle.mustache +1 -1
- package/docs/webapi/seeNumberOfElements.mustache +1 -1
- package/docs/webapi/seeNumberOfVisibleElements.mustache +1 -1
- package/docs/webapi/seeTextEquals.mustache +1 -1
- package/docs/webapi/seeTitleEquals.mustache +1 -1
- package/docs/webapi/selectOption.mustache +1 -1
- package/docs/webapi/setCookie.mustache +1 -1
- package/docs/webapi/setGeoLocation.mustache +1 -1
- package/docs/webapi/switchTo.mustache +1 -1
- package/docs/webapi/switchToNextTab.mustache +1 -1
- package/docs/webapi/switchToPreviousTab.mustache +1 -1
- package/docs/webapi/type.mustache +1 -1
- package/docs/webapi/uncheckOption.mustache +1 -1
- package/docs/webapi/wait.mustache +1 -1
- package/docs/webapi/waitForClickable.mustache +1 -1
- package/docs/webapi/waitForDetached.mustache +1 -1
- package/docs/webapi/waitForElement.mustache +1 -1
- package/docs/webapi/waitForEnabled.mustache +1 -1
- package/docs/webapi/waitForFunction.mustache +1 -1
- package/docs/webapi/waitForInvisible.mustache +1 -1
- package/docs/webapi/waitForText.mustache +1 -1
- package/docs/webapi/waitForValue.mustache +1 -1
- package/docs/webapi/waitForVisible.mustache +1 -1
- package/docs/webapi/waitInUrl.mustache +1 -1
- package/docs/webapi/waitNumberOfVisibleElements.mustache +1 -1
- package/docs/webapi/waitToHide.mustache +1 -1
- package/docs/webapi/waitUrlEquals.mustache +1 -1
- package/lib/ai.js +12 -3
- package/lib/cli.js +3 -1
- package/lib/command/dryRun.js +2 -1
- package/lib/helper/ApiDataFactory.js +2 -1
- package/lib/helper/Appium.js +7 -5
- package/lib/helper/Expect.js +422 -0
- package/lib/helper/Playwright.js +91 -32
- package/lib/helper/Puppeteer.js +2 -2
- package/lib/html.js +3 -3
- package/lib/interfaces/gherkin.js +21 -2
- package/lib/output.js +1 -1
- package/lib/pause.js +6 -3
- package/lib/plugin/autoLogin.js +35 -3
- package/lib/plugin/heal.js +40 -7
- package/lib/recorder.js +12 -5
- package/package.json +15 -8
- package/translations/de-DE.js +5 -0
- package/translations/fr-FR.js +1 -0
- package/translations/it-IT.js +1 -0
- package/translations/ja-JP.js +5 -0
- package/translations/pl-PL.js +5 -0
- package/translations/pt-BR.js +1 -0
- package/translations/ru-RU.js +1 -0
- package/translations/zh-CN.js +5 -0
- package/translations/zh-TW.js +5 -0
- package/typings/promiseBasedTypes.d.ts +904 -862
- package/typings/types.d.ts +904 -845
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
const chai = require('chai');
|
|
2
|
+
const output = require('../output');
|
|
3
|
+
|
|
4
|
+
const { expect } = chai;
|
|
5
|
+
|
|
6
|
+
chai.use(require('chai-string'));
|
|
7
|
+
// @ts-ignore
|
|
8
|
+
chai.use(require('chai-exclude'));
|
|
9
|
+
chai.use(require('chai-match-pattern'));
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* This helper allows performing assertions based on Chai.
|
|
13
|
+
*
|
|
14
|
+
* ### Examples
|
|
15
|
+
*
|
|
16
|
+
* Zero-configuration when paired with other helpers like REST, Playwright:
|
|
17
|
+
*
|
|
18
|
+
* ```js
|
|
19
|
+
* // inside codecept.conf.js
|
|
20
|
+
*{
|
|
21
|
+
* helpers: {
|
|
22
|
+
* Playwright: {...},
|
|
23
|
+
* ExpectHelper: {},
|
|
24
|
+
* }
|
|
25
|
+
*}
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* ## Methods
|
|
29
|
+
*/
|
|
30
|
+
class ExpectHelper {
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
* @param {*} actualValue
|
|
34
|
+
* @param {*} expectedValue
|
|
35
|
+
* @param {*} customErrorMsg
|
|
36
|
+
*/
|
|
37
|
+
expectEqual(actualValue, expectedValue, customErrorMsg = '') {
|
|
38
|
+
// @ts-ignore
|
|
39
|
+
output.step(`I expect "${JSON.stringify(actualValue)}" to equal "${JSON.stringify(expectedValue)}"`);
|
|
40
|
+
return expect(actualValue, customErrorMsg).to.equal(expectedValue);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
*
|
|
45
|
+
* @param {*} actualValue
|
|
46
|
+
* @param {*} expectedValue
|
|
47
|
+
* @param {*} customErrorMsg
|
|
48
|
+
*/
|
|
49
|
+
expectNotEqual(actualValue, expectedValue, customErrorMsg = '') {
|
|
50
|
+
// @ts-ignore
|
|
51
|
+
output.step(`I expect "${JSON.stringify(actualValue)}" to not equal "${JSON.stringify(expectedValue)}"`);
|
|
52
|
+
return expect(actualValue, customErrorMsg).not.to.equal(expectedValue);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
*
|
|
57
|
+
* @param {*} actualValue
|
|
58
|
+
* @param {*} expectedValue
|
|
59
|
+
* @param {*} customErrorMsg
|
|
60
|
+
|
|
61
|
+
*/
|
|
62
|
+
expectDeepEqual(actualValue, expectedValue, customErrorMsg = '') {
|
|
63
|
+
// @ts-ignore
|
|
64
|
+
output.step(`I expect "${JSON.stringify(actualValue)}" to deep equal "${JSON.stringify(expectedValue)}"`);
|
|
65
|
+
return expect(actualValue, customErrorMsg).to.deep.equal(expectedValue);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
*
|
|
70
|
+
* @param {*} actualValue
|
|
71
|
+
* @param {*} expectedValue
|
|
72
|
+
* @param {*} customErrorMsg
|
|
73
|
+
*/
|
|
74
|
+
expectNotDeepEqual(actualValue, expectedValue, customErrorMsg = '') {
|
|
75
|
+
// @ts-ignore
|
|
76
|
+
output.step(`I expect "${JSON.stringify(actualValue)}" to not deep equal "${JSON.stringify(expectedValue)}"`);
|
|
77
|
+
return expect(actualValue, customErrorMsg).to.not.deep.equal(expectedValue);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
*
|
|
82
|
+
* @param {*} actualValue
|
|
83
|
+
* @param {*} expectedValueToContain
|
|
84
|
+
* @param {*} customErrorMsg
|
|
85
|
+
*/
|
|
86
|
+
expectContain(actualValue, expectedValueToContain, customErrorMsg = '') {
|
|
87
|
+
// @ts-ignore
|
|
88
|
+
output.step(`I expect "${JSON.stringify(actualValue)}" to contain "${JSON.stringify(expectedValueToContain)}"`);
|
|
89
|
+
return expect(actualValue, customErrorMsg).to.contain(
|
|
90
|
+
expectedValueToContain,
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
*
|
|
96
|
+
* @param {*} actualValue
|
|
97
|
+
* @param {*} expectedValueToNotContain
|
|
98
|
+
* @param {*} customErrorMsg
|
|
99
|
+
*/
|
|
100
|
+
expectNotContain(
|
|
101
|
+
actualValue,
|
|
102
|
+
expectedValueToNotContain,
|
|
103
|
+
customErrorMsg = '',
|
|
104
|
+
) {
|
|
105
|
+
// @ts-ignore
|
|
106
|
+
output.step(`I expect "${JSON.stringify(actualValue)}" to not contain "${JSON.stringify(expectedValueToNotContain)}"`);
|
|
107
|
+
return expect(actualValue, customErrorMsg).not.to.contain(
|
|
108
|
+
expectedValueToNotContain,
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
*
|
|
114
|
+
* @param {*} actualValue
|
|
115
|
+
* @param {*} expectedValueToStartWith
|
|
116
|
+
* @param {*} customErrorMsg
|
|
117
|
+
*/
|
|
118
|
+
expectStartsWith(actualValue, expectedValueToStartWith, customErrorMsg = '') {
|
|
119
|
+
// @ts-ignore
|
|
120
|
+
output.step(`I expect "${JSON.stringify(actualValue)}" to start with "${JSON.stringify(expectedValueToStartWith)}"`);
|
|
121
|
+
return expect(actualValue, customErrorMsg).to.startsWith(
|
|
122
|
+
expectedValueToStartWith,
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
*
|
|
128
|
+
* @param {*} actualValue
|
|
129
|
+
* @param {*} expectedValueToNotStartWith
|
|
130
|
+
* @param {*} customErrorMsg
|
|
131
|
+
*/
|
|
132
|
+
expectNotStartsWith(
|
|
133
|
+
actualValue,
|
|
134
|
+
expectedValueToNotStartWith,
|
|
135
|
+
customErrorMsg = '',
|
|
136
|
+
) {
|
|
137
|
+
// @ts-ignore
|
|
138
|
+
output.step(`I expect "${JSON.stringify(actualValue)}" to not start with "${JSON.stringify(expectedValueToNotStartWith)}"`);
|
|
139
|
+
return expect(actualValue, customErrorMsg).not.to.startsWith(
|
|
140
|
+
expectedValueToNotStartWith,
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @param {*} actualValue
|
|
146
|
+
* @param {*} expectedValueToEndWith
|
|
147
|
+
* @param {*} customErrorMsg
|
|
148
|
+
*/
|
|
149
|
+
expectEndsWith(actualValue, expectedValueToEndWith, customErrorMsg = '') {
|
|
150
|
+
// @ts-ignore
|
|
151
|
+
output.step(`I expect "${JSON.stringify(actualValue)}" to end with "${JSON.stringify(expectedValueToEndWith)}"`);
|
|
152
|
+
return expect(actualValue, customErrorMsg).to.endsWith(
|
|
153
|
+
expectedValueToEndWith,
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* @param {*} actualValue
|
|
159
|
+
* @param {*} expectedValueToNotEndWith
|
|
160
|
+
* @param {*} customErrorMsg
|
|
161
|
+
*/
|
|
162
|
+
expectNotEndsWith(
|
|
163
|
+
actualValue,
|
|
164
|
+
expectedValueToNotEndWith,
|
|
165
|
+
customErrorMsg = '',
|
|
166
|
+
) {
|
|
167
|
+
// @ts-ignore
|
|
168
|
+
output.step(`I expect "${JSON.stringify(actualValue)}" to not end with "${JSON.stringify(expectedValueToNotEndWith)}"`);
|
|
169
|
+
return expect(actualValue, customErrorMsg).not.to.endsWith(
|
|
170
|
+
expectedValueToNotEndWith,
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* @param {*} targetData
|
|
176
|
+
* @param {*} jsonSchema
|
|
177
|
+
* @param {*} customErrorMsg
|
|
178
|
+
*/
|
|
179
|
+
expectJsonSchema(targetData, jsonSchema, customErrorMsg = '') {
|
|
180
|
+
// @ts-ignore
|
|
181
|
+
output.step(`I expect "${JSON.stringify(targetData)}" to match this JSON schema "${JSON.stringify(jsonSchema)}"`);
|
|
182
|
+
chai.use(require('chai-json-schema'));
|
|
183
|
+
return expect(targetData, customErrorMsg).to.be.jsonSchema(jsonSchema);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* @param {*} targetData
|
|
188
|
+
* @param {*} jsonSchema
|
|
189
|
+
* @param {*} customErrorMsg
|
|
190
|
+
* @param {*} ajvOptions Pass AJV options
|
|
191
|
+
*/
|
|
192
|
+
expectJsonSchemaUsingAJV(
|
|
193
|
+
targetData,
|
|
194
|
+
jsonSchema,
|
|
195
|
+
customErrorMsg = '',
|
|
196
|
+
ajvOptions = { allErrors: true },
|
|
197
|
+
) {
|
|
198
|
+
// @ts-ignore
|
|
199
|
+
output.step(`I expect "${JSON.stringify(targetData)}" to match this JSON schema using AJV "${JSON.stringify(jsonSchema)}"`);
|
|
200
|
+
chai.use(require('chai-json-schema-ajv').create(ajvOptions));
|
|
201
|
+
return expect(targetData, customErrorMsg).to.be.jsonSchema(jsonSchema);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* @param {*} targetData
|
|
206
|
+
* @param {*} propertyName
|
|
207
|
+
* @param {*} customErrorMsg
|
|
208
|
+
*/
|
|
209
|
+
expectHasProperty(targetData, propertyName, customErrorMsg = '') {
|
|
210
|
+
// @ts-ignore
|
|
211
|
+
output.step(`I expect "${JSON.stringify(targetData)}" to have property: "${JSON.stringify(propertyName)}"`);
|
|
212
|
+
return expect(targetData, customErrorMsg).to.have.property(propertyName);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* @param {*} targetData
|
|
217
|
+
* @param {*} propertyName
|
|
218
|
+
* @param {*} customErrorMsg
|
|
219
|
+
*/
|
|
220
|
+
expectHasAProperty(targetData, propertyName, customErrorMsg = '') {
|
|
221
|
+
// @ts-ignore
|
|
222
|
+
output.step(`I expect "${JSON.stringify(targetData)}" to have a property: "${JSON.stringify(propertyName)}"`);
|
|
223
|
+
return expect(targetData, customErrorMsg).to.have.a.property(propertyName);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* @param {*} targetData
|
|
228
|
+
* @param {*} type
|
|
229
|
+
* @param {*} customErrorMsg
|
|
230
|
+
*/
|
|
231
|
+
expectToBeA(targetData, type, customErrorMsg = '') {
|
|
232
|
+
// @ts-ignore
|
|
233
|
+
output.step(`I expect "${JSON.stringify(targetData)}" to be a "${JSON.stringify(type)}"`);
|
|
234
|
+
return expect(targetData, customErrorMsg).to.be.a(type);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* @param {*} targetData
|
|
239
|
+
* @param {*} type
|
|
240
|
+
* @param {*} customErrorMsg
|
|
241
|
+
*/
|
|
242
|
+
expectToBeAn(targetData, type, customErrorMsg = '') {
|
|
243
|
+
// @ts-ignore
|
|
244
|
+
output.step(`I expect "${JSON.stringify(targetData)}" to be an "${JSON.stringify(type)}"`);
|
|
245
|
+
return expect(targetData, customErrorMsg).to.be.an(type);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* @param {*} targetData
|
|
250
|
+
* @param {*} regex
|
|
251
|
+
* @param {*} customErrorMsg
|
|
252
|
+
*/
|
|
253
|
+
expectMatchRegex(targetData, regex, customErrorMsg = '') {
|
|
254
|
+
// @ts-ignore
|
|
255
|
+
output.step(`I expect "${JSON.stringify(targetData)}" to match the regex "${JSON.stringify(regex)}"`);
|
|
256
|
+
return expect(targetData, customErrorMsg).to.match(regex);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* @param {*} targetData
|
|
261
|
+
* @param {*} length
|
|
262
|
+
* @param {*} customErrorMsg
|
|
263
|
+
*/
|
|
264
|
+
expectLengthOf(targetData, length, customErrorMsg = '') {
|
|
265
|
+
// @ts-ignore
|
|
266
|
+
output.step(`I expect "${JSON.stringify(targetData)}" to have length of "${JSON.stringify(length)}"`);
|
|
267
|
+
return expect(targetData, customErrorMsg).to.have.lengthOf(length);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* @param {*} targetData
|
|
272
|
+
* @param {*} customErrorMsg
|
|
273
|
+
*/
|
|
274
|
+
expectEmpty(targetData, customErrorMsg = '') {
|
|
275
|
+
// @ts-ignore
|
|
276
|
+
output.step(`I expect "${JSON.stringify(targetData)}" to be empty`);
|
|
277
|
+
return expect(targetData, customErrorMsg).to.be.empty;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* @param {*} targetData
|
|
282
|
+
* @param {*} customErrorMsg
|
|
283
|
+
*/
|
|
284
|
+
expectTrue(targetData, customErrorMsg = '') {
|
|
285
|
+
// @ts-ignore
|
|
286
|
+
output.step(`I expect "${JSON.stringify(targetData)}" to be true`);
|
|
287
|
+
return expect(targetData, customErrorMsg).to.be.true;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* @param {*} targetData
|
|
292
|
+
* @param {*} customErrorMsg
|
|
293
|
+
*/
|
|
294
|
+
expectFalse(targetData, customErrorMsg = '') {
|
|
295
|
+
// @ts-ignore
|
|
296
|
+
output.step(`I expect "${JSON.stringify(targetData)}" to be false`);
|
|
297
|
+
return expect(targetData, customErrorMsg).to.be.false;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* @param {*} targetData
|
|
302
|
+
* @param {*} aboveThan number | Date
|
|
303
|
+
* @param {*} customErrorMsg
|
|
304
|
+
*/
|
|
305
|
+
expectAbove(targetData, aboveThan, customErrorMsg = '') {
|
|
306
|
+
// @ts-ignore
|
|
307
|
+
output.step(`I expect "${JSON.stringify(targetData)}" to be above ${JSON.stringify(aboveThan)}`);
|
|
308
|
+
return expect(targetData, customErrorMsg).to.be.above(aboveThan);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* @param {*} targetData
|
|
313
|
+
* @param {*} belowThan number | Date
|
|
314
|
+
* @param {*} customErrorMsg
|
|
315
|
+
*/
|
|
316
|
+
expectBelow(targetData, belowThan, customErrorMsg = '') {
|
|
317
|
+
// @ts-ignore
|
|
318
|
+
output.step(`I expect "${JSON.stringify(targetData)}" to be below ${JSON.stringify(belowThan)}`);
|
|
319
|
+
return expect(targetData, customErrorMsg).to.be.below(belowThan);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* @param {*} targetData
|
|
324
|
+
* @param {*} lengthAboveThan
|
|
325
|
+
* @param {*} customErrorMsg
|
|
326
|
+
*/
|
|
327
|
+
expectLengthAboveThan(targetData, lengthAboveThan, customErrorMsg = '') {
|
|
328
|
+
// @ts-ignore
|
|
329
|
+
output.step(`I expect "${JSON.stringify(targetData)}" to have length of above ${JSON.stringify(lengthAboveThan)}`);
|
|
330
|
+
return expect(targetData, customErrorMsg).to.have.lengthOf.above(
|
|
331
|
+
lengthAboveThan,
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* @param {*} targetData
|
|
337
|
+
* @param {*} lengthBelowThan
|
|
338
|
+
* @param {*} customErrorMsg
|
|
339
|
+
*/
|
|
340
|
+
expectLengthBelowThan(targetData, lengthBelowThan, customErrorMsg = '') {
|
|
341
|
+
// @ts-ignore
|
|
342
|
+
output.step(`I expect "${JSON.stringify(targetData)}" to have length of below ${JSON.stringify(lengthBelowThan)}`);
|
|
343
|
+
return expect(targetData, customErrorMsg).to.have.lengthOf.below(
|
|
344
|
+
lengthBelowThan,
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* @param {*} actualValue
|
|
350
|
+
* @param {*} expectedValue
|
|
351
|
+
* @param {*} customErrorMsg
|
|
352
|
+
*/
|
|
353
|
+
expectEqualIgnoreCase(actualValue, expectedValue, customErrorMsg = '') {
|
|
354
|
+
// @ts-ignore
|
|
355
|
+
output.step(`I expect and ingore case "${JSON.stringify(actualValue)}" to equal "${JSON.stringify(expectedValue)}"`);
|
|
356
|
+
return expect(actualValue, customErrorMsg).to.equalIgnoreCase(
|
|
357
|
+
expectedValue,
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* expects members of two arrays are deeply equal
|
|
363
|
+
* @param {*} actualValue
|
|
364
|
+
* @param {*} expectedValue
|
|
365
|
+
* @param {*} customErrorMsg
|
|
366
|
+
*/
|
|
367
|
+
expectDeepMembers(actualValue, expectedValue, customErrorMsg = '') {
|
|
368
|
+
// @ts-ignore
|
|
369
|
+
output.step(`I expect members of "${JSON.stringify(actualValue)}" and "${JSON.stringify(expectedValue)}" arrays are deeply equal`);
|
|
370
|
+
return expect(actualValue, customErrorMsg).to.have.deep.members(
|
|
371
|
+
expectedValue,
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* expects an array to be a superset of another array
|
|
377
|
+
* @param {*} superset
|
|
378
|
+
* @param {*} set
|
|
379
|
+
* @param {*} customErrorMsg
|
|
380
|
+
*/
|
|
381
|
+
expectDeepIncludeMembers(superset, set, customErrorMsg = '') {
|
|
382
|
+
// @ts-ignore
|
|
383
|
+
output.step(`I expect "${JSON.stringify(superset)}" array to be a superset of "${JSON.stringify(set)}" array`);
|
|
384
|
+
return expect(superset, customErrorMsg).to.deep.include.members(
|
|
385
|
+
set,
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* expects members of two JSON objects are deeply equal excluding some properties
|
|
391
|
+
* @param {*} actualValue
|
|
392
|
+
* @param {*} expectedValue
|
|
393
|
+
* @param {*} fieldsToExclude
|
|
394
|
+
* @param {*} customErrorMsg
|
|
395
|
+
*/
|
|
396
|
+
expectDeepEqualExcluding(
|
|
397
|
+
actualValue,
|
|
398
|
+
expectedValue,
|
|
399
|
+
fieldsToExclude,
|
|
400
|
+
customErrorMsg = '',
|
|
401
|
+
) {
|
|
402
|
+
// @ts-ignore
|
|
403
|
+
output.step(`I expect members of "${JSON.stringify(actualValue)}" and "${JSON.stringify(expectedValue)}" JSON objects are deeply equal excluding properties: ${JSON.stringify(fieldsToExclude)}`);
|
|
404
|
+
return expect(actualValue, customErrorMsg)
|
|
405
|
+
.excludingEvery(fieldsToExclude)
|
|
406
|
+
.to.deep.equal(expectedValue);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* expects a JSON object matches a provided pattern
|
|
411
|
+
* @param {*} actualValue
|
|
412
|
+
* @param {*} expectedPattern
|
|
413
|
+
* @param {*} customErrorMsg
|
|
414
|
+
*/
|
|
415
|
+
expectMatchesPattern(actualValue, expectedPattern, customErrorMsg = '') {
|
|
416
|
+
// @ts-ignore
|
|
417
|
+
output.step(`I expect "${JSON.stringify(actualValue)}" to match the ${JSON.stringify(expectedPattern)} pattern`);
|
|
418
|
+
return expect(actualValue, customErrorMsg).to.matchPattern(expectedPattern);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
module.exports = ExpectHelper;
|
package/lib/helper/Playwright.js
CHANGED
|
@@ -942,14 +942,14 @@ class Playwright extends Helper {
|
|
|
942
942
|
* Set headers for all next requests
|
|
943
943
|
*
|
|
944
944
|
* ```js
|
|
945
|
-
* I.
|
|
945
|
+
* I.setPlaywrightRequestHeaders({
|
|
946
946
|
* 'X-Sent-By': 'CodeceptJS',
|
|
947
947
|
* });
|
|
948
948
|
* ```
|
|
949
949
|
*
|
|
950
950
|
* @param {object} customHeaders headers to set
|
|
951
951
|
*/
|
|
952
|
-
async
|
|
952
|
+
async setPlaywrightRequestHeaders(customHeaders) {
|
|
953
953
|
if (!customHeaders) {
|
|
954
954
|
throw new Error('Cannot send empty headers.');
|
|
955
955
|
}
|
|
@@ -2365,10 +2365,11 @@ class Playwright extends Helper {
|
|
|
2365
2365
|
locator = new Locator(locator, 'css');
|
|
2366
2366
|
|
|
2367
2367
|
const context = await this._getContext();
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2368
|
+
try {
|
|
2369
|
+
await context.locator(buildLocatorString(locator)).first().waitFor({ timeout: waitTimeout, state: 'attached' });
|
|
2370
|
+
} catch (e) {
|
|
2371
|
+
throw new Error(`element (${locator.toString()}) still not present on page after ${waitTimeout / 1000} sec\n${e.message}`);
|
|
2372
|
+
}
|
|
2372
2373
|
}
|
|
2373
2374
|
|
|
2374
2375
|
/**
|
|
@@ -2380,10 +2381,26 @@ class Playwright extends Helper {
|
|
|
2380
2381
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
2381
2382
|
locator = new Locator(locator, 'css');
|
|
2382
2383
|
const context = await this._getContext();
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2384
|
+
let count = 0;
|
|
2385
|
+
|
|
2386
|
+
// we have this as https://github.com/microsoft/playwright/issues/26829 is not yet implemented
|
|
2387
|
+
let waiter;
|
|
2388
|
+
if (this.frame) {
|
|
2389
|
+
do {
|
|
2390
|
+
waiter = await this.frame.locator(buildLocatorString(locator)).first().isVisible();
|
|
2391
|
+
await this.wait(1);
|
|
2392
|
+
count += 1000;
|
|
2393
|
+
if (waiter) break;
|
|
2394
|
+
} while (count <= waitTimeout);
|
|
2395
|
+
|
|
2396
|
+
if (!waiter) throw new Error(`element (${locator.toString()}) still not visible after ${waitTimeout / 1000} sec.`);
|
|
2397
|
+
}
|
|
2398
|
+
|
|
2399
|
+
try {
|
|
2400
|
+
await context.locator(buildLocatorString(locator)).first().waitFor({ timeout: waitTimeout, state: 'visible' });
|
|
2401
|
+
} catch (e) {
|
|
2402
|
+
throw new Error(`element (${locator.toString()}) still not visible after ${waitTimeout / 1000} sec\n${e.message}`);
|
|
2403
|
+
}
|
|
2387
2404
|
}
|
|
2388
2405
|
|
|
2389
2406
|
/**
|
|
@@ -2393,10 +2410,27 @@ class Playwright extends Helper {
|
|
|
2393
2410
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
2394
2411
|
locator = new Locator(locator, 'css');
|
|
2395
2412
|
const context = await this._getContext();
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2413
|
+
let waiter;
|
|
2414
|
+
let count = 0;
|
|
2415
|
+
|
|
2416
|
+
// we have this as https://github.com/microsoft/playwright/issues/26829 is not yet implemented
|
|
2417
|
+
if (this.frame) {
|
|
2418
|
+
do {
|
|
2419
|
+
waiter = await this.frame.locator(buildLocatorString(locator)).first().isHidden();
|
|
2420
|
+
await this.wait(1);
|
|
2421
|
+
count += 1000;
|
|
2422
|
+
if (waiter) break;
|
|
2423
|
+
} while (count <= waitTimeout);
|
|
2424
|
+
|
|
2425
|
+
if (!waiter) throw new Error(`element (${locator.toString()}) still visible after ${waitTimeout / 1000} sec.`);
|
|
2426
|
+
return;
|
|
2427
|
+
}
|
|
2428
|
+
|
|
2429
|
+
try {
|
|
2430
|
+
await context.locator(buildLocatorString(locator)).first().waitFor({ timeout: waitTimeout, state: 'hidden' });
|
|
2431
|
+
} catch (e) {
|
|
2432
|
+
throw new Error(`element (${locator.toString()}) still visible after ${waitTimeout / 1000} sec\n${e.message}`);
|
|
2433
|
+
}
|
|
2400
2434
|
}
|
|
2401
2435
|
|
|
2402
2436
|
/**
|
|
@@ -2406,7 +2440,23 @@ class Playwright extends Helper {
|
|
|
2406
2440
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
2407
2441
|
locator = new Locator(locator, 'css');
|
|
2408
2442
|
const context = await this._getContext();
|
|
2409
|
-
|
|
2443
|
+
let waiter;
|
|
2444
|
+
let count = 0;
|
|
2445
|
+
|
|
2446
|
+
// we have this as https://github.com/microsoft/playwright/issues/26829 is not yet implemented
|
|
2447
|
+
if (this.frame) {
|
|
2448
|
+
do {
|
|
2449
|
+
waiter = await this.frame.locator(buildLocatorString(locator)).first().isHidden();
|
|
2450
|
+
await this.wait(1);
|
|
2451
|
+
count += 1000;
|
|
2452
|
+
if (waiter) break;
|
|
2453
|
+
} while (count <= waitTimeout);
|
|
2454
|
+
|
|
2455
|
+
if (!waiter) throw new Error(`element (${locator.toString()}) still not hidden after ${waitTimeout / 1000} sec.`);
|
|
2456
|
+
return;
|
|
2457
|
+
}
|
|
2458
|
+
|
|
2459
|
+
return context.locator(buildLocatorString(locator)).first().waitFor({ timeout: waitTimeout, state: 'hidden' }).catch((err) => {
|
|
2410
2460
|
throw new Error(`element (${locator.toString()}) still not hidden after ${waitTimeout / 1000} sec\n${err.message}`);
|
|
2411
2461
|
});
|
|
2412
2462
|
}
|
|
@@ -2473,7 +2523,12 @@ class Playwright extends Helper {
|
|
|
2473
2523
|
if (context) {
|
|
2474
2524
|
const locator = new Locator(context, 'css');
|
|
2475
2525
|
if (!locator.isXPath()) {
|
|
2476
|
-
|
|
2526
|
+
try {
|
|
2527
|
+
await contextObject.locator(`${locator.isCustom() ? `${locator.type}=${locator.value}` : locator.simplify()} >> text=${text}`).first().waitFor({ timeout: waitTimeout, state: 'visible' });
|
|
2528
|
+
} catch (e) {
|
|
2529
|
+
console.log(e);
|
|
2530
|
+
throw new Error(`Text "${text}" was not found on page after ${waitTimeout / 1000} sec\n${e.message}`);
|
|
2531
|
+
}
|
|
2477
2532
|
}
|
|
2478
2533
|
|
|
2479
2534
|
if (locator.isXPath()) {
|
|
@@ -2486,18 +2541,17 @@ class Playwright extends Helper {
|
|
|
2486
2541
|
}
|
|
2487
2542
|
} else {
|
|
2488
2543
|
// we have this as https://github.com/microsoft/playwright/issues/26829 is not yet implemented
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2544
|
+
// eslint-disable-next-line no-lonely-if
|
|
2545
|
+
const _contextObject = this.frame ? this.frame : contextObject;
|
|
2546
|
+
let count = 0;
|
|
2547
|
+
do {
|
|
2548
|
+
waiter = await _contextObject.locator(`:has-text('${text}')`).first().isVisible();
|
|
2549
|
+
await this.wait(1);
|
|
2550
|
+
count += 1000;
|
|
2551
|
+
} while (count <= waitTimeout);
|
|
2552
|
+
|
|
2553
|
+
if (!waiter) throw new Error(`Text "${text}" was not found on page after ${waitTimeout / 1000} sec`);
|
|
2497
2554
|
}
|
|
2498
|
-
return waiter.catch((err) => {
|
|
2499
|
-
throw new Error(`Text "${text}" was not found on page after ${waitTimeout / 1000} sec\n${err.message}`);
|
|
2500
|
-
});
|
|
2501
2555
|
}
|
|
2502
2556
|
|
|
2503
2557
|
/**
|
|
@@ -2656,17 +2710,21 @@ class Playwright extends Helper {
|
|
|
2656
2710
|
let waiter;
|
|
2657
2711
|
const context = await this._getContext();
|
|
2658
2712
|
if (!locator.isXPath()) {
|
|
2659
|
-
|
|
2713
|
+
try {
|
|
2714
|
+
await context.locator(`${locator.isCustom() ? `${locator.type}=${locator.value}` : locator.simplify()}`).first().waitFor({ timeout: waitTimeout, state: 'detached' });
|
|
2715
|
+
} catch (e) {
|
|
2716
|
+
throw new Error(`element (${locator.toString()}) still on page after ${waitTimeout / 1000} sec\n${e.message}`);
|
|
2717
|
+
}
|
|
2660
2718
|
} else {
|
|
2661
2719
|
const visibleFn = function ([locator, $XPath]) {
|
|
2662
2720
|
eval($XPath); // eslint-disable-line no-eval
|
|
2663
2721
|
return $XPath(null, locator).length === 0;
|
|
2664
2722
|
};
|
|
2665
2723
|
waiter = context.waitForFunction(visibleFn, [locator.value, $XPath.toString()], { timeout: waitTimeout });
|
|
2724
|
+
return waiter.catch((err) => {
|
|
2725
|
+
throw new Error(`element (${locator.toString()}) still on page after ${waitTimeout / 1000} sec\n${err.message}`);
|
|
2726
|
+
});
|
|
2666
2727
|
}
|
|
2667
|
-
return waiter.catch((err) => {
|
|
2668
|
-
throw new Error(`element (${locator.toString()}) still on page after ${waitTimeout / 1000} sec\n${err.message}`);
|
|
2669
|
-
});
|
|
2670
2728
|
}
|
|
2671
2729
|
|
|
2672
2730
|
async _waitForAction() {
|
|
@@ -3354,7 +3412,8 @@ async function proceedSee(assertType, text, context, strict = false) {
|
|
|
3354
3412
|
if (!context) {
|
|
3355
3413
|
const el = await this.context;
|
|
3356
3414
|
|
|
3357
|
-
allText = [await el.locator('body').innerText()];
|
|
3415
|
+
allText = el.constructor.name ? [await el.locator('body').innerText()] : [await el.innerText()];
|
|
3416
|
+
|
|
3358
3417
|
description = 'web application';
|
|
3359
3418
|
} else {
|
|
3360
3419
|
const locator = new Locator(context, 'css');
|
package/lib/helper/Puppeteer.js
CHANGED
|
@@ -682,14 +682,14 @@ class Puppeteer extends Helper {
|
|
|
682
682
|
* Set headers for all next requests
|
|
683
683
|
*
|
|
684
684
|
* ```js
|
|
685
|
-
* I.
|
|
685
|
+
* I.setPuppeteerRequestHeaders({
|
|
686
686
|
* 'X-Sent-By': 'CodeceptJS',
|
|
687
687
|
* });
|
|
688
688
|
* ```
|
|
689
689
|
*
|
|
690
690
|
* @param {object} customHeaders headers to set
|
|
691
691
|
*/
|
|
692
|
-
async
|
|
692
|
+
async setPuppeteerRequestHeaders(customHeaders) {
|
|
693
693
|
if (!customHeaders) {
|
|
694
694
|
throw new Error('Cannot send empty headers.');
|
|
695
695
|
}
|
package/lib/html.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { parse, serialize } = require('parse5');
|
|
2
|
-
const { minify } = require('html-minifier');
|
|
2
|
+
const { minify } = require('html-minifier-terser');
|
|
3
3
|
|
|
4
|
-
function minifyHtml(html) {
|
|
4
|
+
async function minifyHtml(html) {
|
|
5
5
|
return minify(html, {
|
|
6
6
|
collapseWhitespace: true,
|
|
7
7
|
removeComments: true,
|
|
@@ -11,7 +11,7 @@ function minifyHtml(html) {
|
|
|
11
11
|
removeStyleLinkTypeAttributes: true,
|
|
12
12
|
collapseBooleanAttributes: true,
|
|
13
13
|
useShortDoctype: true,
|
|
14
|
-
})
|
|
14
|
+
});
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
const defaultHtmlOpts = {
|