codeceptjs 4.0.0-rc.23 → 4.0.0-rc.25
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 +0 -35
- package/lib/command/run-multiple.js +1 -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/analyze.js +3 -4
- package/lib/plugin/pauseOnFail.js +3 -1
- package/lib/plugin/retryFailedStep.js +7 -7
- package/lib/plugin/screenshot.js +0 -5
- package/lib/plugin/screenshotOnFail.js +3 -1
- package/lib/plugin/stepTimeout.js +1 -1
- package/lib/recorder.js +1 -1
- 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
|
@@ -1,352 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
permalink: /helpers/SoftExpectHelper
|
|
3
|
-
editLink: false
|
|
4
|
-
sidebar: auto
|
|
5
|
-
title: SoftExpectHelper
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
|
|
9
|
-
|
|
10
|
-
## SoftAssertHelper
|
|
11
|
-
|
|
12
|
-
**Extends ExpectHelper**
|
|
13
|
-
|
|
14
|
-
SoftAssertHelper is a utility class for performing soft assertions.
|
|
15
|
-
Unlike traditional assertions that stop the execution on failure,
|
|
16
|
-
soft assertions allow the execution to continue and report all failures at the end.
|
|
17
|
-
|
|
18
|
-
### Examples
|
|
19
|
-
|
|
20
|
-
Zero-configuration when paired with other helpers like REST, Playwright:
|
|
21
|
-
|
|
22
|
-
```js
|
|
23
|
-
// inside codecept.conf.js
|
|
24
|
-
{
|
|
25
|
-
helpers: {
|
|
26
|
-
Playwright: {...},
|
|
27
|
-
SoftExpectHelper: {},
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
```js
|
|
33
|
-
// in scenario
|
|
34
|
-
I.softExpectEqual('a', 'b')
|
|
35
|
-
I.flushSoftAssertions() // Throws an error if any soft assertions have failed. The error message contains all the accumulated failures.
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Methods
|
|
39
|
-
|
|
40
|
-
### flushSoftAssertions
|
|
41
|
-
|
|
42
|
-
Throws an error if any soft assertions have failed.
|
|
43
|
-
The error message contains all the accumulated failures.
|
|
44
|
-
|
|
45
|
-
- Throws **[Error][1]** If there are any soft assertion failures.
|
|
46
|
-
|
|
47
|
-
### softAssert
|
|
48
|
-
|
|
49
|
-
Performs a soft assertion by executing the provided assertion function.
|
|
50
|
-
If the assertion fails, the error is caught and stored without halting the execution.
|
|
51
|
-
|
|
52
|
-
#### Parameters
|
|
53
|
-
|
|
54
|
-
- `assertionFn` **[Function][2]** The assertion function to execute.
|
|
55
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
56
|
-
|
|
57
|
-
### softExpectAbove
|
|
58
|
-
|
|
59
|
-
Softly asserts that the target data is above a specified value.
|
|
60
|
-
|
|
61
|
-
#### Parameters
|
|
62
|
-
|
|
63
|
-
- `targetData` **any** The data to check.
|
|
64
|
-
- `aboveThan` **any** The value that the target data should be above.
|
|
65
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
66
|
-
|
|
67
|
-
### softExpectBelow
|
|
68
|
-
|
|
69
|
-
Softly asserts that the target data is below a specified value.
|
|
70
|
-
|
|
71
|
-
#### Parameters
|
|
72
|
-
|
|
73
|
-
- `targetData` **any** The data to check.
|
|
74
|
-
- `belowThan` **any** The value that the target data should be below.
|
|
75
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
76
|
-
|
|
77
|
-
### softExpectContain
|
|
78
|
-
|
|
79
|
-
Softly asserts that a value contains the expected value.
|
|
80
|
-
|
|
81
|
-
#### Parameters
|
|
82
|
-
|
|
83
|
-
- `actualValue` **any** The actual value.
|
|
84
|
-
- `expectedValueToContain` **any** The value that should be contained within the actual value.
|
|
85
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
86
|
-
|
|
87
|
-
### softExpectDeepEqual
|
|
88
|
-
|
|
89
|
-
Softly asserts that two values are deeply equal.
|
|
90
|
-
|
|
91
|
-
#### Parameters
|
|
92
|
-
|
|
93
|
-
- `actualValue` **any** The actual value.
|
|
94
|
-
- `expectedValue` **any** The expected value.
|
|
95
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
96
|
-
|
|
97
|
-
### softExpectDeepEqualExcluding
|
|
98
|
-
|
|
99
|
-
Softly asserts that two objects are deeply equal, excluding specified fields.
|
|
100
|
-
|
|
101
|
-
#### Parameters
|
|
102
|
-
|
|
103
|
-
- `actualValue` **[Object][4]** The actual object.
|
|
104
|
-
- `expectedValue` **[Object][4]** The expected object.
|
|
105
|
-
- `fieldsToExclude` **[Array][5]<[string][3]>** The fields to exclude from the comparison.
|
|
106
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
107
|
-
|
|
108
|
-
### softExpectDeepIncludeMembers
|
|
109
|
-
|
|
110
|
-
Softly asserts that an array (superset) deeply includes all members of another array (set).
|
|
111
|
-
|
|
112
|
-
#### Parameters
|
|
113
|
-
|
|
114
|
-
- `superset` **[Array][5]** The array that should contain the expected members.
|
|
115
|
-
- `set` **[Array][5]** The array with members that should be included.
|
|
116
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
117
|
-
|
|
118
|
-
### softExpectDeepMembers
|
|
119
|
-
|
|
120
|
-
Softly asserts that two arrays have deep equality, considering members in any order.
|
|
121
|
-
|
|
122
|
-
#### Parameters
|
|
123
|
-
|
|
124
|
-
- `actualValue` **[Array][5]** The actual array.
|
|
125
|
-
- `expectedValue` **[Array][5]** The expected array.
|
|
126
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
127
|
-
|
|
128
|
-
### softExpectEmpty
|
|
129
|
-
|
|
130
|
-
Softly asserts that the target data is empty.
|
|
131
|
-
|
|
132
|
-
#### Parameters
|
|
133
|
-
|
|
134
|
-
- `targetData` **any** The data to check.
|
|
135
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
136
|
-
|
|
137
|
-
### softExpectEndsWith
|
|
138
|
-
|
|
139
|
-
Softly asserts that a value ends with the expected value.
|
|
140
|
-
|
|
141
|
-
#### Parameters
|
|
142
|
-
|
|
143
|
-
- `actualValue` **any** The actual value.
|
|
144
|
-
- `expectedValueToEndWith` **any** The value that the actual value should end with.
|
|
145
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
146
|
-
|
|
147
|
-
### softExpectEqual
|
|
148
|
-
|
|
149
|
-
Softly asserts that two values are equal.
|
|
150
|
-
|
|
151
|
-
#### Parameters
|
|
152
|
-
|
|
153
|
-
- `actualValue` **any** The actual value.
|
|
154
|
-
- `expectedValue` **any** The expected value.
|
|
155
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
156
|
-
|
|
157
|
-
### softExpectEqualIgnoreCase
|
|
158
|
-
|
|
159
|
-
Softly asserts that two values are equal, ignoring case.
|
|
160
|
-
|
|
161
|
-
#### Parameters
|
|
162
|
-
|
|
163
|
-
- `actualValue` **[string][3]** The actual string value.
|
|
164
|
-
- `expectedValue` **[string][3]** The expected string value.
|
|
165
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
166
|
-
|
|
167
|
-
### softExpectFalse
|
|
168
|
-
|
|
169
|
-
Softly asserts that the target data is false.
|
|
170
|
-
|
|
171
|
-
#### Parameters
|
|
172
|
-
|
|
173
|
-
- `targetData` **any** The data to check.
|
|
174
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
175
|
-
|
|
176
|
-
### softExpectHasAProperty
|
|
177
|
-
|
|
178
|
-
Softly asserts that the target data has a property with the specified name.
|
|
179
|
-
|
|
180
|
-
#### Parameters
|
|
181
|
-
|
|
182
|
-
- `targetData` **any** The data to check.
|
|
183
|
-
- `propertyName` **[string][3]** The property name to check for.
|
|
184
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
185
|
-
|
|
186
|
-
### softExpectHasProperty
|
|
187
|
-
|
|
188
|
-
Softly asserts that the target data has the specified property.
|
|
189
|
-
|
|
190
|
-
#### Parameters
|
|
191
|
-
|
|
192
|
-
- `targetData` **any** The data to check.
|
|
193
|
-
- `propertyName` **[string][3]** The property name to check for.
|
|
194
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion
|
|
195
|
-
fails.
|
|
196
|
-
|
|
197
|
-
### softExpectJsonSchema
|
|
198
|
-
|
|
199
|
-
Softly asserts that the target data matches the given JSON schema.
|
|
200
|
-
|
|
201
|
-
#### Parameters
|
|
202
|
-
|
|
203
|
-
- `targetData` **any** The data to validate.
|
|
204
|
-
- `jsonSchema` **[Object][4]** The JSON schema to validate against.
|
|
205
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
206
|
-
|
|
207
|
-
### softExpectJsonSchemaUsingAJV
|
|
208
|
-
|
|
209
|
-
Softly asserts that the target data matches the given JSON schema using AJV.
|
|
210
|
-
|
|
211
|
-
#### Parameters
|
|
212
|
-
|
|
213
|
-
- `targetData` **any** The data to validate.
|
|
214
|
-
- `jsonSchema` **[Object][4]** The JSON schema to validate against.
|
|
215
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
216
|
-
- `ajvOptions` **[Object][4]** Options to pass to AJV.
|
|
217
|
-
|
|
218
|
-
### softExpectLengthAboveThan
|
|
219
|
-
|
|
220
|
-
Softly asserts that the length of the target data is above a specified value.
|
|
221
|
-
|
|
222
|
-
#### Parameters
|
|
223
|
-
|
|
224
|
-
- `targetData` **any** The data to check.
|
|
225
|
-
- `lengthAboveThan` **[number][6]** The length that the target data should be above.
|
|
226
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
227
|
-
|
|
228
|
-
### softExpectLengthBelowThan
|
|
229
|
-
|
|
230
|
-
Softly asserts that the length of the target data is below a specified value.
|
|
231
|
-
|
|
232
|
-
#### Parameters
|
|
233
|
-
|
|
234
|
-
- `targetData` **any** The data to check.
|
|
235
|
-
- `lengthBelowThan` **[number][6]** The length that the target data should be below.
|
|
236
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
237
|
-
|
|
238
|
-
### softExpectLengthOf
|
|
239
|
-
|
|
240
|
-
Softly asserts that the target data has a specified length.
|
|
241
|
-
|
|
242
|
-
#### Parameters
|
|
243
|
-
|
|
244
|
-
- `targetData` **any** The data to check.
|
|
245
|
-
- `length` **[number][6]** The expected length.
|
|
246
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
247
|
-
|
|
248
|
-
### softExpectMatchesPattern
|
|
249
|
-
|
|
250
|
-
Softly asserts that a value matches the expected pattern.
|
|
251
|
-
|
|
252
|
-
#### Parameters
|
|
253
|
-
|
|
254
|
-
- `actualValue` **any** The actual value.
|
|
255
|
-
- `expectedPattern` **any** The pattern the value should match.
|
|
256
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
257
|
-
|
|
258
|
-
### softExpectNotContain
|
|
259
|
-
|
|
260
|
-
Softly asserts that a value does not contain the expected value.
|
|
261
|
-
|
|
262
|
-
#### Parameters
|
|
263
|
-
|
|
264
|
-
- `actualValue` **any** The actual value.
|
|
265
|
-
- `expectedValueToNotContain` **any** The value that should not be contained within the actual value.
|
|
266
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
267
|
-
|
|
268
|
-
### softExpectNotDeepEqual
|
|
269
|
-
|
|
270
|
-
Softly asserts that two values are not deeply equal.
|
|
271
|
-
|
|
272
|
-
#### Parameters
|
|
273
|
-
|
|
274
|
-
- `actualValue` **any** The actual value.
|
|
275
|
-
- `expectedValue` **any** The expected value.
|
|
276
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
277
|
-
|
|
278
|
-
### softExpectNotEndsWith
|
|
279
|
-
|
|
280
|
-
Softly asserts that a value does not end with the expected value.
|
|
281
|
-
|
|
282
|
-
#### Parameters
|
|
283
|
-
|
|
284
|
-
- `actualValue` **any** The actual value.
|
|
285
|
-
- `expectedValueToNotEndWith` **any** The value that the actual value should not end with.
|
|
286
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
287
|
-
|
|
288
|
-
### softExpectNotEqual
|
|
289
|
-
|
|
290
|
-
Softly asserts that two values are not equal.
|
|
291
|
-
|
|
292
|
-
#### Parameters
|
|
293
|
-
|
|
294
|
-
- `actualValue` **any** The actual value.
|
|
295
|
-
- `expectedValue` **any** The expected value.
|
|
296
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
297
|
-
|
|
298
|
-
### softExpectNotStartsWith
|
|
299
|
-
|
|
300
|
-
Softly asserts that a value does not start with the expected value.
|
|
301
|
-
|
|
302
|
-
#### Parameters
|
|
303
|
-
|
|
304
|
-
- `actualValue` **any** The actual value.
|
|
305
|
-
- `expectedValueToNotStartWith` **any** The value that the actual value should not start with.
|
|
306
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
307
|
-
|
|
308
|
-
### softExpectStartsWith
|
|
309
|
-
|
|
310
|
-
Softly asserts that a value starts with the expected value.
|
|
311
|
-
|
|
312
|
-
#### Parameters
|
|
313
|
-
|
|
314
|
-
- `actualValue` **any** The actual value.
|
|
315
|
-
- `expectedValueToStartWith` **any** The value that the actual value should start with.
|
|
316
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
317
|
-
|
|
318
|
-
### softExpectToBeA
|
|
319
|
-
|
|
320
|
-
Softly asserts that the target data is of a specific type.
|
|
321
|
-
|
|
322
|
-
#### Parameters
|
|
323
|
-
|
|
324
|
-
- `targetData` **any** The data to check.
|
|
325
|
-
- `type` **[string][3]** The expected type (e.g., 'string', 'number').
|
|
326
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
327
|
-
|
|
328
|
-
### softExpectToBeAn
|
|
329
|
-
|
|
330
|
-
Softly asserts that the target data is of a specific type (alternative for articles).
|
|
331
|
-
|
|
332
|
-
#### Parameters
|
|
333
|
-
|
|
334
|
-
- `targetData` **any** The data to check.
|
|
335
|
-
- `type` **[string][3]** The expected type (e.g., 'string', 'number').
|
|
336
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
337
|
-
|
|
338
|
-
### softExpectTrue
|
|
339
|
-
|
|
340
|
-
Softly asserts that the target data is true.
|
|
341
|
-
|
|
342
|
-
#### Parameters
|
|
343
|
-
|
|
344
|
-
- `targetData` **any** The data to check.
|
|
345
|
-
- `customErrorMsg` **[string][3]** A custom error message to display if the assertion fails.
|
|
346
|
-
|
|
347
|
-
[1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
|
|
348
|
-
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function
|
|
349
|
-
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
|
|
350
|
-
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
|
|
351
|
-
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
|
|
352
|
-
[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
|
package/docs/react.md
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
permalink: /react
|
|
3
|
-
title: Testing React Applications
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Testing React Applications
|
|
7
|
-
|
|
8
|
-
React applications require some additional love for end to end testing.
|
|
9
|
-
At first, it is very hard to test an application which was never designed to be tested!
|
|
10
|
-
This happens to many React application. While building components developers often forget to keep the element's semantic.
|
|
11
|
-
|
|
12
|
-
Generated HTML code may often look like this:
|
|
13
|
-
|
|
14
|
-
```js
|
|
15
|
-
<div class="jss607 jss869 jss618 jss871 jss874 jss876" tabindex="0" role="tab" aria-selected="true" style="pointer-events: auto;">
|
|
16
|
-
<span class="jss877">
|
|
17
|
-
<span class="jss878">
|
|
18
|
-
<span class="jss879">Click Me!</span>
|
|
19
|
-
</span>
|
|
20
|
-
</span>
|
|
21
|
-
<span class="jss610"></span></div>
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
It's quite common that clickable elements are not actual `a` or `button` elements. This way `I.click('Click Me!');` won't work, as well as `fillField('name', 'value)`. Finding a correct locator for such cases turns to be almost impossible.
|
|
25
|
-
|
|
26
|
-
In this case test engineers have two options:
|
|
27
|
-
|
|
28
|
-
1. Update JSX files to change output HTML and rebuild the application
|
|
29
|
-
1. Test the application how it is.
|
|
30
|
-
|
|
31
|
-
We recommend for long-running projects to go with the first option. The better you write your initial HTML the cleaner and less fragile will be your tests. Replace divs with correct HTML elements, add `data-` attributes, add labels, and names to input fields to make all CodeceptJS magic like clicking link by a text to work.
|
|
32
|
-
|
|
33
|
-
However, if you can't update the code you can go to the second option. In this case, you should bind your locators to visible text on page and available semantic attribues. For instance, instead of using generated locator as this one:
|
|
34
|
-
|
|
35
|
-
```
|
|
36
|
-
//*[@id="document"]/div[2]/div/div[2]/div
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
use [Locator Builder](/locators#locator-builder) to make clean semantic locator:
|
|
40
|
-
|
|
41
|
-
```js
|
|
42
|
-
locate('[role=tab]').withText('Click Me!');
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
This way you can build very flexible and stable locators even on application never designed for testing.
|
|
46
|
-
|
|
47
|
-
## Locators
|
|
48
|
-
|
|
49
|
-
For React apps a special `react` locator is available. It allows to select an element by its component name, props and state.
|
|
50
|
-
|
|
51
|
-
```js
|
|
52
|
-
{ react: 'MyComponent' }
|
|
53
|
-
{ react: 'Button', props: { title: 'Click Me' }}
|
|
54
|
-
{ react: 'Button', state: { some: 'state' }}
|
|
55
|
-
{ react: 'Input', state: 'valid'}
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
In WebDriver, Puppeteer, and Playwright you can use React locators in any method where locator is required:
|
|
59
|
-
|
|
60
|
-
```js
|
|
61
|
-
I.click({ react: 'Tab', props: { title: 'Click Me!' }});
|
|
62
|
-
I.seeElement({ react: 't', props: { title: 'Clicked' }});
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
To find React element names and props in a tree use [React DevTools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi) extension.
|
|
66
|
-
|
|
67
|
-
> Turn off minification for application builds otherwise component names will be uglified as well
|
|
68
|
-
|
|
69
|
-
- With WebDriver and Puppeteer, React locators work via [resq](https://github.com/baruchvlz/resq) library, which handles React 16 and above.
|
|
70
|
-
- With Playwright, React locators work via [Playwright React Locator](https://playwright.dev/docs/other-locators#react-locator).
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
let currentTest
|
|
2
|
-
let currentSuite
|
|
3
|
-
|
|
4
|
-
import Helper from '@codeceptjs/helper'
|
|
5
|
-
import { createRequire } from 'module'
|
|
6
|
-
import { clearString } from '../utils.js'
|
|
7
|
-
import { testToFileName } from '../mocha/test.js'
|
|
8
|
-
|
|
9
|
-
class Mochawesome extends Helper {
|
|
10
|
-
constructor(config) {
|
|
11
|
-
super(config)
|
|
12
|
-
|
|
13
|
-
// set defaults
|
|
14
|
-
this.options = {
|
|
15
|
-
uniqueScreenshotNames: false,
|
|
16
|
-
disableScreenshots: false,
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// ESM-compatible require for CommonJS module
|
|
20
|
-
const require = createRequire(import.meta.url)
|
|
21
|
-
this._addContext = require('mochawesome/addContext')
|
|
22
|
-
|
|
23
|
-
this._createConfig(config)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
_createConfig(config) {
|
|
27
|
-
// override defaults with config
|
|
28
|
-
Object.assign(this.options, config)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
_beforeSuite(suite) {
|
|
32
|
-
currentSuite = suite
|
|
33
|
-
currentTest = ''
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
_before() {
|
|
37
|
-
if (currentSuite && currentSuite.ctx) {
|
|
38
|
-
currentTest = { test: currentSuite.ctx.currentTest }
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
_test(test) {
|
|
43
|
-
// If this is a retried test, we want to add context to the retried test
|
|
44
|
-
// but also potentially preserve context from the original test
|
|
45
|
-
const originalTest = test.retriedTest && test.retriedTest()
|
|
46
|
-
if (originalTest) {
|
|
47
|
-
// This is a retried test - use the retried test for context
|
|
48
|
-
currentTest = { test }
|
|
49
|
-
|
|
50
|
-
// Optionally copy context from original test if it exists
|
|
51
|
-
// Note: mochawesome context is stored in test.ctx, but we need to be careful
|
|
52
|
-
// not to break the mocha context structure
|
|
53
|
-
} else {
|
|
54
|
-
// Normal test (not a retry)
|
|
55
|
-
currentTest = { test }
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
_failed(test) {
|
|
60
|
-
if (this.options.disableScreenshots) return
|
|
61
|
-
let fileName
|
|
62
|
-
// Get proper name if we are fail on hook
|
|
63
|
-
if (test.ctx?.test?.type === 'hook') {
|
|
64
|
-
currentTest = { test: test.ctx.test }
|
|
65
|
-
// ignore retries if we are in hook
|
|
66
|
-
test._retries = -1
|
|
67
|
-
fileName = clearString(`${test.title}_${currentTest.test.title}`)
|
|
68
|
-
} else {
|
|
69
|
-
currentTest = { test }
|
|
70
|
-
fileName = testToFileName(test)
|
|
71
|
-
}
|
|
72
|
-
if (this.options.uniqueScreenshotNames) {
|
|
73
|
-
fileName = testToFileName(test, { unique: true })
|
|
74
|
-
}
|
|
75
|
-
if (test._retries < 1 || test._retries === test.retryNum) {
|
|
76
|
-
fileName = `${fileName}.failed.png`
|
|
77
|
-
return this._addContext(currentTest, fileName)
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
addMochawesomeContext(context) {
|
|
82
|
-
if (currentTest === '') currentTest = { test: currentSuite.ctx.test }
|
|
83
|
-
|
|
84
|
-
// For retried tests, make sure we're adding context to the current (retried) test
|
|
85
|
-
// not the original test
|
|
86
|
-
let targetTest = currentTest
|
|
87
|
-
if (currentTest.test && currentTest.test.retriedTest && currentTest.test.retriedTest()) {
|
|
88
|
-
// This test has been retried, make sure we're using the current test for context
|
|
89
|
-
targetTest = { test: currentTest.test }
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return this._addContext(targetTest, context)
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export default Mochawesome
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import fs from 'fs'
|
|
2
|
-
import { fileURLToPath } from 'url'
|
|
3
|
-
|
|
4
|
-
let resqScript
|
|
5
|
-
|
|
6
|
-
async function findReact(matcher, locator) {
|
|
7
|
-
const reactLocator = locator.locator || locator
|
|
8
|
-
const page = typeof matcher.page === 'function' ? matcher.page() : matcher
|
|
9
|
-
|
|
10
|
-
if (!resqScript) {
|
|
11
|
-
resqScript = fs.readFileSync(fileURLToPath(import.meta.resolve('resq'))).toString()
|
|
12
|
-
}
|
|
13
|
-
await page.evaluate(resqScript)
|
|
14
|
-
await page.evaluate(() => window.resq.waitToLoadReact())
|
|
15
|
-
|
|
16
|
-
const arrayHandle = await page.evaluateHandle(
|
|
17
|
-
({ selector, props, state }) => {
|
|
18
|
-
let elements = window.resq.resq$$(selector)
|
|
19
|
-
if (Object.keys(props).length) elements = elements.byProps(props)
|
|
20
|
-
if (Object.keys(state).length) elements = elements.byState(state)
|
|
21
|
-
if (!elements.length) return []
|
|
22
|
-
|
|
23
|
-
let nodes = []
|
|
24
|
-
elements.forEach(element => {
|
|
25
|
-
let { node, isFragment } = element
|
|
26
|
-
if (!node) {
|
|
27
|
-
isFragment = true
|
|
28
|
-
node = element.children
|
|
29
|
-
}
|
|
30
|
-
if (isFragment) nodes = nodes.concat(node)
|
|
31
|
-
else nodes.push(node)
|
|
32
|
-
})
|
|
33
|
-
return [...nodes]
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
selector: reactLocator.react,
|
|
37
|
-
props: reactLocator.props || {},
|
|
38
|
-
state: reactLocator.state || {},
|
|
39
|
-
},
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
const properties = await arrayHandle.getProperties()
|
|
43
|
-
await arrayHandle.dispose()
|
|
44
|
-
const result = []
|
|
45
|
-
for (const property of properties.values()) {
|
|
46
|
-
const elementHandle = property.asElement()
|
|
47
|
-
if (elementHandle) result.push(elementHandle)
|
|
48
|
-
}
|
|
49
|
-
return result
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async function findByPlaywrightLocator(matcher, locator) {
|
|
53
|
-
const pwLocator = locator.locator || locator
|
|
54
|
-
if (pwLocator && pwLocator.toString && pwLocator.toString().includes(process.env.testIdAttribute)) {
|
|
55
|
-
return matcher.getByTestId(pwLocator.pw.value.split('=')[1])
|
|
56
|
-
}
|
|
57
|
-
const pwValue = typeof pwLocator.pw === 'string' ? pwLocator.pw : pwLocator.pw
|
|
58
|
-
return matcher.locator(pwValue).all()
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export { findReact, findByPlaywrightLocator }
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import fs from 'fs'
|
|
2
|
-
|
|
3
|
-
let resqScript
|
|
4
|
-
|
|
5
|
-
export default async function findReact(matcher, locator) {
|
|
6
|
-
if (!resqScript) resqScript = fs.readFileSync(new URL('resq', import.meta.resolve('resq')).pathname)
|
|
7
|
-
await matcher.evaluate(resqScript.toString())
|
|
8
|
-
await matcher.evaluate(() => window.resq.waitToLoadReact())
|
|
9
|
-
const arrayHandle = await matcher.evaluateHandle(
|
|
10
|
-
obj => {
|
|
11
|
-
const { selector, props, state } = obj
|
|
12
|
-
|
|
13
|
-
let elements = window.resq.resq$$(selector)
|
|
14
|
-
if (Object.keys(props).length) {
|
|
15
|
-
elements = elements.byProps(props)
|
|
16
|
-
}
|
|
17
|
-
if (Object.keys(state).length) {
|
|
18
|
-
elements = elements.byState(state)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (!elements.length) {
|
|
22
|
-
return []
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// resq returns an array of HTMLElements if the React component is a fragment
|
|
26
|
-
// this avoids having nested arrays of nodes which the driver does not understand
|
|
27
|
-
// [[div, div], [div, div]] => [div, div, div, div]
|
|
28
|
-
let nodes = []
|
|
29
|
-
|
|
30
|
-
elements.forEach(element => {
|
|
31
|
-
let { node, isFragment } = element
|
|
32
|
-
|
|
33
|
-
if (!node) {
|
|
34
|
-
isFragment = true
|
|
35
|
-
node = element.children
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (isFragment) {
|
|
39
|
-
nodes = nodes.concat(node)
|
|
40
|
-
} else {
|
|
41
|
-
nodes.push(node)
|
|
42
|
-
}
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
return [...nodes]
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
selector: locator.react,
|
|
49
|
-
props: locator.props || {},
|
|
50
|
-
state: locator.state || {},
|
|
51
|
-
},
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
const properties = await arrayHandle.getProperties()
|
|
55
|
-
await arrayHandle.dispose()
|
|
56
|
-
const result = []
|
|
57
|
-
for (const property of properties.values()) {
|
|
58
|
-
const elementHandle = property.asElement()
|
|
59
|
-
if (elementHandle) {
|
|
60
|
-
result.push(elementHandle)
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return result
|
|
65
|
-
}
|