codeceptjs 3.5.6 → 3.5.7
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 +5 -1
- package/docs/advanced.md +1 -1
- package/docs/bdd.md +11 -7
- package/docs/build/ApiDataFactory.js +2 -1
- package/docs/build/Appium.js +26 -23
- package/docs/build/Expect.js +422 -0
- package/docs/build/Nightmare.js +53 -56
- package/docs/build/Playwright.js +202 -103
- package/docs/build/Protractor.js +66 -69
- package/docs/build/Puppeteer.js +124 -81
- package/docs/build/TestCafe.js +56 -55
- package/docs/build/WebDriver.js +81 -82
- package/docs/changelog.md +562 -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 +360 -261
- package/docs/helpers/Protractor.md +229 -169
- package/docs/helpers/Puppeteer.md +270 -187
- 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/docs/webdriver.md +1 -1
- 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 +8 -5
- package/lib/helper/Expect.js +422 -0
- package/lib/helper/Playwright.js +127 -32
- package/lib/helper/Puppeteer.js +47 -4
- package/lib/interfaces/gherkin.js +21 -2
- package/lib/output.js +1 -1
- package/lib/plugin/autoLogin.js +41 -3
- package/lib/utils.js +1 -1
- package/lib/workers.js +23 -2
- package/package.json +25 -16
- 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 +928 -862
- package/typings/types.d.ts +932 -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
|
@@ -116,6 +116,10 @@ const config = {};
|
|
|
116
116
|
* npm i playwright-core@^1.18 --save
|
|
117
117
|
* ```
|
|
118
118
|
*
|
|
119
|
+
* Breaking Changes: if you use Playwright v1.38 and later, it will no longer download browsers automatically.
|
|
120
|
+
*
|
|
121
|
+
* Run `npx playwright install` to download browsers after `npm install`.
|
|
122
|
+
*
|
|
119
123
|
* Using playwright-core package, will prevent the download of browser binaries and allow connecting to an existing browser installation or for connecting to a remote one.
|
|
120
124
|
*
|
|
121
125
|
*
|
|
@@ -942,14 +946,14 @@ class Playwright extends Helper {
|
|
|
942
946
|
* Set headers for all next requests
|
|
943
947
|
*
|
|
944
948
|
* ```js
|
|
945
|
-
* I.
|
|
949
|
+
* I.setPlaywrightRequestHeaders({
|
|
946
950
|
* 'X-Sent-By': 'CodeceptJS',
|
|
947
951
|
* });
|
|
948
952
|
* ```
|
|
949
953
|
*
|
|
950
954
|
* @param {object} customHeaders headers to set
|
|
951
955
|
*/
|
|
952
|
-
async
|
|
956
|
+
async setPlaywrightRequestHeaders(customHeaders) {
|
|
953
957
|
if (!customHeaders) {
|
|
954
958
|
throw new Error('Cannot send empty headers.');
|
|
955
959
|
}
|
|
@@ -993,6 +997,38 @@ class Playwright extends Helper {
|
|
|
993
997
|
await el.blur(options);
|
|
994
998
|
return this._waitForAction();
|
|
995
999
|
}
|
|
1000
|
+
/**
|
|
1001
|
+
* Return the checked status of given element.
|
|
1002
|
+
*
|
|
1003
|
+
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
1004
|
+
* @param {object} [options] See https://playwright.dev/docs/api/class-locator#locator-is-checked
|
|
1005
|
+
* @return {Promise<boolean>}
|
|
1006
|
+
*
|
|
1007
|
+
*/
|
|
1008
|
+
|
|
1009
|
+
async grabCheckedElementStatus(locator, options = {}) {
|
|
1010
|
+
const supportedTypes = ['checkbox', 'radio'];
|
|
1011
|
+
const el = await this._locateElement(locator);
|
|
1012
|
+
const type = await el.getAttribute('type');
|
|
1013
|
+
|
|
1014
|
+
if (supportedTypes.includes(type)) {
|
|
1015
|
+
return el.isChecked(options);
|
|
1016
|
+
}
|
|
1017
|
+
throw new Error(`Element is not a ${supportedTypes.join(' or ')} input`);
|
|
1018
|
+
}
|
|
1019
|
+
/**
|
|
1020
|
+
* Return the disabled status of given element.
|
|
1021
|
+
*
|
|
1022
|
+
* @param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
1023
|
+
* @param {object} [options] See https://playwright.dev/docs/api/class-locator#locator-is-disabled
|
|
1024
|
+
* @return {Promise<boolean>}
|
|
1025
|
+
*
|
|
1026
|
+
*/
|
|
1027
|
+
|
|
1028
|
+
async grabDisabledElementStatus(locator, options = {}) {
|
|
1029
|
+
const el = await this._locateElement(locator);
|
|
1030
|
+
return el.isDisabled(options);
|
|
1031
|
+
}
|
|
996
1032
|
|
|
997
1033
|
/**
|
|
998
1034
|
* {{> dragAndDrop }}
|
|
@@ -2365,10 +2401,11 @@ class Playwright extends Helper {
|
|
|
2365
2401
|
locator = new Locator(locator, 'css');
|
|
2366
2402
|
|
|
2367
2403
|
const context = await this._getContext();
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2404
|
+
try {
|
|
2405
|
+
await context.locator(buildLocatorString(locator)).first().waitFor({ timeout: waitTimeout, state: 'attached' });
|
|
2406
|
+
} catch (e) {
|
|
2407
|
+
throw new Error(`element (${locator.toString()}) still not present on page after ${waitTimeout / 1000} sec\n${e.message}`);
|
|
2408
|
+
}
|
|
2372
2409
|
}
|
|
2373
2410
|
|
|
2374
2411
|
/**
|
|
@@ -2380,10 +2417,26 @@ class Playwright extends Helper {
|
|
|
2380
2417
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
2381
2418
|
locator = new Locator(locator, 'css');
|
|
2382
2419
|
const context = await this._getContext();
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2420
|
+
let count = 0;
|
|
2421
|
+
|
|
2422
|
+
// we have this as https://github.com/microsoft/playwright/issues/26829 is not yet implemented
|
|
2423
|
+
let waiter;
|
|
2424
|
+
if (this.frame) {
|
|
2425
|
+
do {
|
|
2426
|
+
waiter = await this.frame.locator(buildLocatorString(locator)).first().isVisible();
|
|
2427
|
+
await this.wait(1);
|
|
2428
|
+
count += 1000;
|
|
2429
|
+
if (waiter) break;
|
|
2430
|
+
} while (count <= waitTimeout);
|
|
2431
|
+
|
|
2432
|
+
if (!waiter) throw new Error(`element (${locator.toString()}) still not visible after ${waitTimeout / 1000} sec.`);
|
|
2433
|
+
}
|
|
2434
|
+
|
|
2435
|
+
try {
|
|
2436
|
+
await context.locator(buildLocatorString(locator)).first().waitFor({ timeout: waitTimeout, state: 'visible' });
|
|
2437
|
+
} catch (e) {
|
|
2438
|
+
throw new Error(`element (${locator.toString()}) still not visible after ${waitTimeout / 1000} sec\n${e.message}`);
|
|
2439
|
+
}
|
|
2387
2440
|
}
|
|
2388
2441
|
|
|
2389
2442
|
/**
|
|
@@ -2393,10 +2446,27 @@ class Playwright extends Helper {
|
|
|
2393
2446
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
2394
2447
|
locator = new Locator(locator, 'css');
|
|
2395
2448
|
const context = await this._getContext();
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2449
|
+
let waiter;
|
|
2450
|
+
let count = 0;
|
|
2451
|
+
|
|
2452
|
+
// we have this as https://github.com/microsoft/playwright/issues/26829 is not yet implemented
|
|
2453
|
+
if (this.frame) {
|
|
2454
|
+
do {
|
|
2455
|
+
waiter = await this.frame.locator(buildLocatorString(locator)).first().isHidden();
|
|
2456
|
+
await this.wait(1);
|
|
2457
|
+
count += 1000;
|
|
2458
|
+
if (waiter) break;
|
|
2459
|
+
} while (count <= waitTimeout);
|
|
2460
|
+
|
|
2461
|
+
if (!waiter) throw new Error(`element (${locator.toString()}) still visible after ${waitTimeout / 1000} sec.`);
|
|
2462
|
+
return;
|
|
2463
|
+
}
|
|
2464
|
+
|
|
2465
|
+
try {
|
|
2466
|
+
await context.locator(buildLocatorString(locator)).first().waitFor({ timeout: waitTimeout, state: 'hidden' });
|
|
2467
|
+
} catch (e) {
|
|
2468
|
+
throw new Error(`element (${locator.toString()}) still visible after ${waitTimeout / 1000} sec\n${e.message}`);
|
|
2469
|
+
}
|
|
2400
2470
|
}
|
|
2401
2471
|
|
|
2402
2472
|
/**
|
|
@@ -2406,7 +2476,23 @@ class Playwright extends Helper {
|
|
|
2406
2476
|
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
|
|
2407
2477
|
locator = new Locator(locator, 'css');
|
|
2408
2478
|
const context = await this._getContext();
|
|
2409
|
-
|
|
2479
|
+
let waiter;
|
|
2480
|
+
let count = 0;
|
|
2481
|
+
|
|
2482
|
+
// we have this as https://github.com/microsoft/playwright/issues/26829 is not yet implemented
|
|
2483
|
+
if (this.frame) {
|
|
2484
|
+
do {
|
|
2485
|
+
waiter = await this.frame.locator(buildLocatorString(locator)).first().isHidden();
|
|
2486
|
+
await this.wait(1);
|
|
2487
|
+
count += 1000;
|
|
2488
|
+
if (waiter) break;
|
|
2489
|
+
} while (count <= waitTimeout);
|
|
2490
|
+
|
|
2491
|
+
if (!waiter) throw new Error(`element (${locator.toString()}) still not hidden after ${waitTimeout / 1000} sec.`);
|
|
2492
|
+
return;
|
|
2493
|
+
}
|
|
2494
|
+
|
|
2495
|
+
return context.locator(buildLocatorString(locator)).first().waitFor({ timeout: waitTimeout, state: 'hidden' }).catch((err) => {
|
|
2410
2496
|
throw new Error(`element (${locator.toString()}) still not hidden after ${waitTimeout / 1000} sec\n${err.message}`);
|
|
2411
2497
|
});
|
|
2412
2498
|
}
|
|
@@ -2473,7 +2559,12 @@ class Playwright extends Helper {
|
|
|
2473
2559
|
if (context) {
|
|
2474
2560
|
const locator = new Locator(context, 'css');
|
|
2475
2561
|
if (!locator.isXPath()) {
|
|
2476
|
-
|
|
2562
|
+
try {
|
|
2563
|
+
await contextObject.locator(`${locator.isCustom() ? `${locator.type}=${locator.value}` : locator.simplify()} >> text=${text}`).first().waitFor({ timeout: waitTimeout, state: 'visible' });
|
|
2564
|
+
} catch (e) {
|
|
2565
|
+
console.log(e);
|
|
2566
|
+
throw new Error(`Text "${text}" was not found on page after ${waitTimeout / 1000} sec\n${e.message}`);
|
|
2567
|
+
}
|
|
2477
2568
|
}
|
|
2478
2569
|
|
|
2479
2570
|
if (locator.isXPath()) {
|
|
@@ -2486,18 +2577,17 @@ class Playwright extends Helper {
|
|
|
2486
2577
|
}
|
|
2487
2578
|
} else {
|
|
2488
2579
|
// we have this as https://github.com/microsoft/playwright/issues/26829 is not yet implemented
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2580
|
+
// eslint-disable-next-line no-lonely-if
|
|
2581
|
+
const _contextObject = this.frame ? this.frame : contextObject;
|
|
2582
|
+
let count = 0;
|
|
2583
|
+
do {
|
|
2584
|
+
waiter = await _contextObject.locator(`:has-text('${text}')`).first().isVisible();
|
|
2585
|
+
await this.wait(1);
|
|
2586
|
+
count += 1000;
|
|
2587
|
+
} while (count <= waitTimeout);
|
|
2588
|
+
|
|
2589
|
+
if (!waiter) throw new Error(`Text "${text}" was not found on page after ${waitTimeout / 1000} sec`);
|
|
2497
2590
|
}
|
|
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
2591
|
}
|
|
2502
2592
|
|
|
2503
2593
|
/**
|
|
@@ -2656,17 +2746,21 @@ class Playwright extends Helper {
|
|
|
2656
2746
|
let waiter;
|
|
2657
2747
|
const context = await this._getContext();
|
|
2658
2748
|
if (!locator.isXPath()) {
|
|
2659
|
-
|
|
2749
|
+
try {
|
|
2750
|
+
await context.locator(`${locator.isCustom() ? `${locator.type}=${locator.value}` : locator.simplify()}`).first().waitFor({ timeout: waitTimeout, state: 'detached' });
|
|
2751
|
+
} catch (e) {
|
|
2752
|
+
throw new Error(`element (${locator.toString()}) still on page after ${waitTimeout / 1000} sec\n${e.message}`);
|
|
2753
|
+
}
|
|
2660
2754
|
} else {
|
|
2661
2755
|
const visibleFn = function ([locator, $XPath]) {
|
|
2662
2756
|
eval($XPath); // eslint-disable-line no-eval
|
|
2663
2757
|
return $XPath(null, locator).length === 0;
|
|
2664
2758
|
};
|
|
2665
2759
|
waiter = context.waitForFunction(visibleFn, [locator.value, $XPath.toString()], { timeout: waitTimeout });
|
|
2760
|
+
return waiter.catch((err) => {
|
|
2761
|
+
throw new Error(`element (${locator.toString()}) still on page after ${waitTimeout / 1000} sec\n${err.message}`);
|
|
2762
|
+
});
|
|
2666
2763
|
}
|
|
2667
|
-
return waiter.catch((err) => {
|
|
2668
|
-
throw new Error(`element (${locator.toString()}) still on page after ${waitTimeout / 1000} sec\n${err.message}`);
|
|
2669
|
-
});
|
|
2670
2764
|
}
|
|
2671
2765
|
|
|
2672
2766
|
async _waitForAction() {
|
|
@@ -3354,7 +3448,8 @@ async function proceedSee(assertType, text, context, strict = false) {
|
|
|
3354
3448
|
if (!context) {
|
|
3355
3449
|
const el = await this.context;
|
|
3356
3450
|
|
|
3357
|
-
allText = [await el.locator('body').innerText()];
|
|
3451
|
+
allText = el.constructor.name ? [await el.locator('body').innerText()] : [await el.innerText()];
|
|
3452
|
+
|
|
3358
3453
|
description = 'web application';
|
|
3359
3454
|
} else {
|
|
3360
3455
|
const locator = new Locator(context, 'css');
|