system-testing 1.0.21 → 1.0.22
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/package.json +1 -1
- package/src/system-test.js +66 -13
package/package.json
CHANGED
package/src/system-test.js
CHANGED
|
@@ -41,7 +41,7 @@ export default class SystemTest {
|
|
|
41
41
|
await systemTest.visit("/blank")
|
|
42
42
|
|
|
43
43
|
try {
|
|
44
|
-
await systemTest.findByTestID("blankText")
|
|
44
|
+
await systemTest.findByTestID("blankText", {useBaseSelector: false})
|
|
45
45
|
await callback(systemTest)
|
|
46
46
|
} catch (error) {
|
|
47
47
|
await systemTest.takeScreenshot()
|
|
@@ -72,6 +72,30 @@ export default class SystemTest {
|
|
|
72
72
|
this.communicator = new SystemTestCommunicator({onCommand: this.onCommandReceived})
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Gets the base selector for scoping element searches
|
|
77
|
+
*
|
|
78
|
+
* @returns {string}
|
|
79
|
+
*/
|
|
80
|
+
getBaseSelector() { return this._baseSelector }
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Sets the base selector for scoping element searches
|
|
84
|
+
*
|
|
85
|
+
* @param {string} baseSelector
|
|
86
|
+
*/
|
|
87
|
+
setBaseSelector(baseSelector) { this._baseSelector = baseSelector }
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Gets a selector scoped to the base selector
|
|
91
|
+
*
|
|
92
|
+
* @param {string} selector
|
|
93
|
+
* @returns {string}
|
|
94
|
+
*/
|
|
95
|
+
getSelector(selector) {
|
|
96
|
+
return this.getBaseSelector() ? `${this.getBaseSelector()} ${selector}` : selector
|
|
97
|
+
}
|
|
98
|
+
|
|
75
99
|
/** Starts Scoundrel server which the browser connects to for remote evaluation in the browser */
|
|
76
100
|
startScoundrel() {
|
|
77
101
|
this.wss = new WebSocketServer({port: 8090})
|
|
@@ -93,8 +117,15 @@ export default class SystemTest {
|
|
|
93
117
|
* @returns {import("selenium-webdriver").WebElement[]}
|
|
94
118
|
*/
|
|
95
119
|
async all(selector, args = {}) {
|
|
96
|
-
const {visible = true} = args
|
|
97
|
-
const
|
|
120
|
+
const {visible = true, useBaseSelector = true, ...restArgs} = args
|
|
121
|
+
const restArgsKeys = Object.keys(restArgs)
|
|
122
|
+
|
|
123
|
+
if (restArgsKeys.length > 0) {
|
|
124
|
+
throw new Error(`Unknown arguments: ${restArgsKeys.join(", ")}`)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const actualSelector = useBaseSelector ? this.getSelector(selector) : selector
|
|
128
|
+
const elements = await this.driver.findElements(By.css(actualSelector))
|
|
98
129
|
const activeElements = []
|
|
99
130
|
|
|
100
131
|
for (const element of elements) {
|
|
@@ -142,15 +173,15 @@ export default class SystemTest {
|
|
|
142
173
|
elements = await this.all(selector, args)
|
|
143
174
|
} catch (error) {
|
|
144
175
|
// Re-throw to recover stack trace
|
|
145
|
-
throw new Error(`${error.message} (selector: ${selector})`)
|
|
176
|
+
throw new Error(`${error.message} (selector: ${this.getSelector(selector)})`)
|
|
146
177
|
}
|
|
147
178
|
|
|
148
179
|
if (elements.length > 1) {
|
|
149
|
-
throw new Error(`More than 1 elements (${elements.length}) was found by CSS: ${selector}`)
|
|
180
|
+
throw new Error(`More than 1 elements (${elements.length}) was found by CSS: ${this.getSelector(selector)}`)
|
|
150
181
|
}
|
|
151
182
|
|
|
152
183
|
if (!elements[0]) {
|
|
153
|
-
throw new ElementNotFoundError(`Element couldn't be found by CSS: ${selector}`)
|
|
184
|
+
throw new ElementNotFoundError(`Element couldn't be found after ${(this.getTimeouts() / 1000).toFixed(2)}s by CSS: ${this.getSelector(selector)}`)
|
|
154
185
|
}
|
|
155
186
|
|
|
156
187
|
return elements[0]
|
|
@@ -171,11 +202,11 @@ export default class SystemTest {
|
|
|
171
202
|
* @param {string} selector
|
|
172
203
|
* @returns {import("selenium-webdriver").WebElement}
|
|
173
204
|
*/
|
|
174
|
-
async findNoWait(selector) {
|
|
205
|
+
async findNoWait(selector, args) {
|
|
175
206
|
await this.driverSetTimeouts(0)
|
|
176
207
|
|
|
177
208
|
try {
|
|
178
|
-
return await this.find(selector)
|
|
209
|
+
return await this.find(selector, args)
|
|
179
210
|
} finally {
|
|
180
211
|
await this.restoreTimeouts()
|
|
181
212
|
}
|
|
@@ -210,6 +241,8 @@ export default class SystemTest {
|
|
|
210
241
|
return await this.driver.getCurrentUrl()
|
|
211
242
|
}
|
|
212
243
|
|
|
244
|
+
getTimeouts() { return this._timeouts }
|
|
245
|
+
|
|
213
246
|
/**
|
|
214
247
|
* Interacts with an element by calling a method on it with the given arguments.
|
|
215
248
|
* Retrying on ElementNotInteractableError.
|
|
@@ -283,7 +316,7 @@ export default class SystemTest {
|
|
|
283
316
|
* @returns {Promise<string[]>}
|
|
284
317
|
*/
|
|
285
318
|
async notificationMessages() {
|
|
286
|
-
const notificationMessageElements = await this.all("[data-class='notification-message']")
|
|
319
|
+
const notificationMessageElements = await this.all("[data-class='notification-message']", {useBaseSelector: false})
|
|
287
320
|
const notificationMessageTexts = []
|
|
288
321
|
|
|
289
322
|
for (const notificationMessageElement of notificationMessageElements) {
|
|
@@ -372,8 +405,8 @@ export default class SystemTest {
|
|
|
372
405
|
await this.driverVisit("/?systemTest=true")
|
|
373
406
|
|
|
374
407
|
try {
|
|
375
|
-
await this.find("body > #root")
|
|
376
|
-
await this.find("[data-testid='systemTestingComponent']", {visible: null})
|
|
408
|
+
await this.find("body > #root", {useBaseSelector: false})
|
|
409
|
+
await this.find("[data-testid='systemTestingComponent']", {visible: null, useBaseSelector: false})
|
|
377
410
|
} catch (error) {
|
|
378
411
|
await systemTest.takeScreenshot()
|
|
379
412
|
|
|
@@ -384,17 +417,18 @@ export default class SystemTest {
|
|
|
384
417
|
await this.waitForClientWebSocket()
|
|
385
418
|
|
|
386
419
|
this._started = true
|
|
420
|
+
systemTest.setBaseSelector("[data-testid='systemTestingComponent'][data-focussed='true']")
|
|
387
421
|
}
|
|
388
422
|
|
|
389
423
|
/**
|
|
390
424
|
* Restores previously set timeouts
|
|
391
425
|
*/
|
|
392
426
|
async restoreTimeouts() {
|
|
393
|
-
if (!this.
|
|
427
|
+
if (!this.getTimeouts()) {
|
|
394
428
|
throw new Error("Timeouts haven't previously been set")
|
|
395
429
|
}
|
|
396
430
|
|
|
397
|
-
await this.driverSetTimeouts(this.
|
|
431
|
+
await this.driverSetTimeouts(this.getTimeouts())
|
|
398
432
|
}
|
|
399
433
|
|
|
400
434
|
/**
|
|
@@ -440,10 +474,19 @@ export default class SystemTest {
|
|
|
440
474
|
this.wss.on("close", this.onWebSocketClose)
|
|
441
475
|
}
|
|
442
476
|
|
|
477
|
+
/**
|
|
478
|
+
* Sets the on command callback
|
|
479
|
+
*/
|
|
443
480
|
onCommand(callback) {
|
|
444
481
|
this._onCommandCallback = callback
|
|
445
482
|
}
|
|
446
483
|
|
|
484
|
+
/**
|
|
485
|
+
* Handles a command received from the browser
|
|
486
|
+
*
|
|
487
|
+
* @param {Object} data
|
|
488
|
+
* @returns {Promise<any>}
|
|
489
|
+
*/
|
|
447
490
|
onCommandReceived = async ({data}) => {
|
|
448
491
|
const type = data.type
|
|
449
492
|
let result
|
|
@@ -472,6 +515,11 @@ export default class SystemTest {
|
|
|
472
515
|
return result
|
|
473
516
|
}
|
|
474
517
|
|
|
518
|
+
/**
|
|
519
|
+
* Handles a new web socket connection
|
|
520
|
+
*
|
|
521
|
+
* @param {WebSocket} ws
|
|
522
|
+
*/
|
|
475
523
|
onWebSocketConnection = async (ws) => {
|
|
476
524
|
this.ws = ws
|
|
477
525
|
this.communicator.ws = ws
|
|
@@ -490,6 +538,11 @@ export default class SystemTest {
|
|
|
490
538
|
this.communicator.ws = null
|
|
491
539
|
}
|
|
492
540
|
|
|
541
|
+
/**
|
|
542
|
+
* Handles an error reported from the browser
|
|
543
|
+
*
|
|
544
|
+
* @param {Object} data
|
|
545
|
+
*/
|
|
493
546
|
handleError(data) {
|
|
494
547
|
if (data.message.includes("Minified React error #419")) {
|
|
495
548
|
// Ignore this error message
|