system-testing 1.0.25 → 1.0.27

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.
@@ -0,0 +1,23 @@
1
+ import js from "@eslint/js"
2
+ import {jsdoc} from "eslint-plugin-jsdoc"
3
+ import globals from "globals"
4
+ import { defineConfig } from "eslint/config"
5
+
6
+ export default defineConfig([
7
+ {
8
+ files: ["**/*.{js,mjs,cjs}"],
9
+ plugins: {js},
10
+ extends: ["js/recommended"],
11
+ languageOptions: {
12
+ globals: {...globals.browser, ...globals.node}
13
+ }
14
+ },
15
+ jsdoc({
16
+ config: "flat/recommended",
17
+ rules: {
18
+ "jsdoc/reject-any-type": "off",
19
+ "jsdoc/require-param-description": "off",
20
+ "jsdoc/require-returns-description": "off"
21
+ }
22
+ })
23
+ ])
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "system-testing",
3
- "version": "1.0.25",
3
+ "version": "1.0.27",
4
4
  "description": "System testing with Selenium and browsers.",
5
5
  "keywords": [
6
6
  "system",
@@ -21,6 +21,7 @@
21
21
  "type": "module",
22
22
  "main": "src/index.js",
23
23
  "scripts": {
24
+ "lint": "eslint",
24
25
  "test": "echo \"Error: no test specified\" && exit 1"
25
26
  },
26
27
  "dependencies": {
@@ -34,5 +35,11 @@
34
35
  },
35
36
  "peerDependencies": {
36
37
  "selenium-webdriver": "^4.34.0"
38
+ },
39
+ "devDependencies": {
40
+ "@eslint/js": "^9.39.1",
41
+ "eslint": "^9.39.1",
42
+ "eslint-plugin-jsdoc": "^61.4.1",
43
+ "globals": "^16.5.0"
37
44
  }
38
45
  }
package/peak_flow.yml ADDED
@@ -0,0 +1,4 @@
1
+ before_script:
2
+ - npm install
3
+ script:
4
+ - npm run lint
@@ -100,15 +100,20 @@ export default class SystemTestBrowserHelper {
100
100
  this.communicator.sendCommand(data)
101
101
  }
102
102
 
103
+ /**
104
+ * @returns {void}
105
+ */
103
106
  connectWebSocket() {
104
- this.ws = new WebSocket("ws://localhost:1985") // eslint-disable-line no-undef
105
-
107
+ this.ws = new WebSocket("ws://localhost:1985")
106
108
  this.communicator.ws = this.ws
107
109
  this.ws.addEventListener("error", digg(this, "communicator", "onError"))
108
110
  this.ws.addEventListener("open", digg(this, "communicator", "onOpen"))
109
111
  this.ws.addEventListener("message", (event) => this.communicator.onMessage(event.data))
110
112
  }
111
113
 
114
+ /**
115
+ * @returns {void}
116
+ */
112
117
  enableOnBrowser() {
113
118
  this._enabled = true
114
119
  this.connectWebSocket()
@@ -117,7 +122,14 @@ export default class SystemTestBrowserHelper {
117
122
  this.overrideConsoleLog()
118
123
  }
119
124
 
125
+ /**
126
+ * @returns {boolean}
127
+ */
120
128
  getEnabled() { return this._enabled }
129
+
130
+ /**
131
+ * @returns {EventEmitter}
132
+ */
121
133
  getEvents() { return this.events }
122
134
 
123
135
  fakeConsoleError = (...args) => {
@@ -186,10 +198,17 @@ export default class SystemTestBrowserHelper {
186
198
  }
187
199
  }
188
200
 
201
+ /**
202
+ * @param {function() : void} callback
203
+ * @returns {void}
204
+ */
189
205
  onInitialize(callback) {
190
206
  this._onInitializeCallback = callback
191
207
  }
192
208
 
209
+ /**
210
+ * @returns {void}
211
+ */
193
212
  overrideConsoleLog() {
194
213
  if (this.originalConsoleError || this.originalConsoleLog) {
195
214
  throw new Error("Console methods has already been overridden!")
@@ -202,6 +221,10 @@ export default class SystemTestBrowserHelper {
202
221
  console.log = this.fakeConsoleLog
203
222
  }
204
223
 
224
+ /**
225
+ * @param {string} sql
226
+ * @returns {Promise<Array<Record<string, any>>>}
227
+ */
205
228
  async sendQuery(sql) {
206
229
  return await this.communicator.sendCommand({type: "query", sql})
207
230
  }
@@ -65,9 +65,8 @@ export default class SystemTestCommunicator {
65
65
 
66
66
  /**
67
67
  * Sends a command and returns a promise that resolves with the response.
68
- *
69
- * @param {Object} data - The command data to send.
70
- * @returns {Promise} A promise that resolves with the response data.
68
+ * @param {object} data - The command data to send.
69
+ * @returns {Promise<void>} A promise that resolves with the response data.
71
70
  */
72
71
  sendCommand(data) {
73
72
  return new Promise((resolve, error) => {
@@ -4,6 +4,7 @@ import mime from "mime"
4
4
  import url from "url"
5
5
 
6
6
  export default class SystemTestHttpServer {
7
+ /** @returns {void} */
7
8
  close() {
8
9
  this.httpServer.close()
9
10
  }
@@ -21,7 +22,7 @@ export default class SystemTestHttpServer {
21
22
  try {
22
23
  await fs.stat(filePath)
23
24
  fileExists = true
24
- } catch (_error) {
25
+ } catch (_error) { // eslint-disable-line no-unused-vars
25
26
  fileExists = false
26
27
  }
27
28
 
@@ -37,12 +38,13 @@ export default class SystemTestHttpServer {
37
38
  response.end(fileContent)
38
39
  }
39
40
 
41
+ /** @returns {Promise<void>} */
40
42
  async start() {
41
- this.basePath = await fs.realpath(`${__dirname}/../..`) // eslint-disable-line no-undef
42
-
43
+ this.basePath = await fs.realpath(`${__dirname}/../..`)
43
44
  await this.startHttpServer()
44
45
  }
45
46
 
47
+ /** @returns {Promise<void>} */
46
48
  startHttpServer() {
47
49
  return new Promise((resolve) => {
48
50
  this.httpServer = http.createServer(this.onHttpServerRequest)
@@ -1,4 +1,4 @@
1
- import {Builder, By} from "selenium-webdriver"
1
+ import {Builder, By, until} from "selenium-webdriver"
2
2
  import chrome from "selenium-webdriver/chrome.js"
3
3
  import {digg} from "diggerize"
4
4
  import fs from "node:fs/promises"
@@ -19,7 +19,6 @@ export default class SystemTest {
19
19
 
20
20
  /**
21
21
  * Gets the current system test instance
22
- *
23
22
  * @param {object} args
24
23
  * @returns {SystemTest}
25
24
  */
@@ -33,8 +32,8 @@ export default class SystemTest {
33
32
 
34
33
  /**
35
34
  * Runs a system test
36
- *
37
35
  * @param {function(SystemTest): Promise<void>} callback
36
+ * @returns {Promise<void>}
38
37
  */
39
38
  static async run(callback) {
40
39
  const systemTest = this.current()
@@ -54,7 +53,6 @@ export default class SystemTest {
54
53
 
55
54
  /**
56
55
  * Creates a new SystemTest instance
57
- *
58
56
  * @param {object} args
59
57
  * @param {string} args.host
60
58
  * @param {number} args.port
@@ -76,21 +74,18 @@ export default class SystemTest {
76
74
 
77
75
  /**
78
76
  * Gets the base selector for scoping element searches
79
- *
80
77
  * @returns {string}
81
78
  */
82
79
  getBaseSelector() { return this._baseSelector }
83
80
 
84
81
  /**
85
82
  * Sets the base selector for scoping element searches
86
- *
87
83
  * @param {string} baseSelector
88
84
  */
89
85
  setBaseSelector(baseSelector) { this._baseSelector = baseSelector }
90
86
 
91
87
  /**
92
88
  * Gets a selector scoped to the base selector
93
- *
94
89
  * @param {string} selector
95
90
  * @returns {string}
96
91
  */
@@ -98,13 +93,19 @@ export default class SystemTest {
98
93
  return this.getBaseSelector() ? `${this.getBaseSelector()} ${selector}` : selector
99
94
  }
100
95
 
101
- /** Starts Scoundrel server which the browser connects to for remote evaluation in the browser */
96
+ /**
97
+ * Starts Scoundrel server which the browser connects to for remote evaluation in the browser
98
+ * @returns {void}
99
+ */
102
100
  startScoundrel() {
103
101
  this.wss = new WebSocketServer({port: 8090})
104
102
  this.serverWebSocket = new ServerWebSocket(this.wss)
105
103
  this.server = new Server(this.serverWebSocket)
106
104
  }
107
105
 
106
+ /**
107
+ * @returns {void}
108
+ */
108
109
  stopScoundrel() {
109
110
  this.server?.close()
110
111
  this.wss?.close()
@@ -112,10 +113,8 @@ export default class SystemTest {
112
113
 
113
114
  /**
114
115
  * Finds all elements by CSS selector
115
- *
116
116
  * @param {string} selector
117
117
  * @param {object} args
118
- *
119
118
  * @returns {import("selenium-webdriver").WebElement[]}
120
119
  */
121
120
  async all(selector, args = {}) {
@@ -148,9 +147,9 @@ export default class SystemTest {
148
147
 
149
148
  /**
150
149
  * Clicks an element that has children which fills out the element and would otherwise have caused a ElementClickInterceptedError
151
- *
152
- * @param {import("selenium-webdriver").WebElement} element
153
- **/
150
+ * @param {string|import("selenium-webdriver").WebElement} elementOrIdentifier
151
+ * @returns {Promise<void>}
152
+ */
154
153
  async click(elementOrIdentifier) {
155
154
  let tries = 0
156
155
 
@@ -166,13 +165,13 @@ export default class SystemTest {
166
165
  } catch (error) {
167
166
  if (error.constructor.name === "ElementNotInteractableError") {
168
167
  if (tries >= 3) {
169
- throw new Error(`Element ${element.constructor.name} click failed after ${tries} tries - ${error.constructor.name}: ${error.message}`)
168
+ throw new Error(`Element ${elementOrIdentifier.constructor.name} click failed after ${tries} tries - ${error.constructor.name}: ${error.message}`)
170
169
  } else {
171
170
  await wait(50)
172
171
  }
173
172
  } else {
174
173
  // Re-throw with un-corrupted stack trace
175
- throw new Error(`Element ${element.constructor.name} click failed - ${error.constructor.name}: ${error.message}`)
174
+ throw new Error(`Element ${elementOrIdentifier.constructor.name} click failed - ${error.constructor.name}: ${error.message}`)
176
175
  }
177
176
  }
178
177
  }
@@ -180,7 +179,6 @@ export default class SystemTest {
180
179
 
181
180
  /**
182
181
  * Finds a single element by CSS selector
183
- *
184
182
  * @param {string} selector
185
183
  * @param {object} args
186
184
  * @returns {import("selenium-webdriver").WebElement}
@@ -208,13 +206,16 @@ export default class SystemTest {
208
206
 
209
207
  /**
210
208
  * Finds a single element by test ID
211
- *
212
209
  * @param {string} testID
213
210
  * @param {object} args
214
- * @returns {import("selenium-webdriver").WebElement}
211
+ * @returns {Promise<import("selenium-webdriver").WebElement>}
215
212
  */
216
213
  async findByTestID(testID, args) { return await this.find(`[data-testid='${testID}']`, args) }
217
214
 
215
+ /**
216
+ * @param {string|import("selenium-webdriver").WebElement} elementOrIdentifier
217
+ * @returns {Promise<import("selenium-webdriver").WebElement>}
218
+ */
218
219
  async _findElement(elementOrIdentifier) {
219
220
  let element
220
221
 
@@ -229,9 +230,9 @@ export default class SystemTest {
229
230
 
230
231
  /**
231
232
  * Finds a single element by CSS selector without waiting
232
- *
233
233
  * @param {string} selector
234
- * @returns {import("selenium-webdriver").WebElement}
234
+ * @param {object} args
235
+ * @returns {Promise<import("selenium-webdriver").WebElement>}
235
236
  */
236
237
  async findNoWait(selector, args) {
237
238
  await this.driverSetTimeouts(0)
@@ -245,7 +246,6 @@ export default class SystemTest {
245
246
 
246
247
  /**
247
248
  * Gets browser logs
248
- *
249
249
  * @returns {Promise<string[]>}
250
250
  */
251
251
  async getBrowserLogs() {
@@ -268,20 +268,24 @@ export default class SystemTest {
268
268
  return browserLogs
269
269
  }
270
270
 
271
+ /**
272
+ * @returns {Promise<string>}
273
+ */
271
274
  async getCurrentUrl() {
272
275
  return await this.driver.getCurrentUrl()
273
276
  }
274
277
 
278
+ /**
279
+ * @returns {number}
280
+ */
275
281
  getTimeouts() { return this._timeouts }
276
282
 
277
283
  /**
278
284
  * Interacts with an element by calling a method on it with the given arguments.
279
285
  * Retrying on ElementNotInteractableError.
280
- *
281
286
  * @param {import("selenium-webdriver").WebElement|string} elementOrIdentifier - The element or a CSS selector to find the element.
282
287
  * @param {string} methodName - The method name to call on the element.
283
288
  * @param {...any} args - Arguments to pass to the method.
284
- *
285
289
  * @returns {Promise<any>}
286
290
  */
287
291
  async interact(elementOrIdentifier, methodName, ...args) {
@@ -326,8 +330,8 @@ export default class SystemTest {
326
330
 
327
331
  /**
328
332
  * Expects no element to be found by CSS selector
329
- *
330
333
  * @param {string} selector
334
+ * @returns {Promise<void>}
331
335
  */
332
336
  async expectNoElement(selector) {
333
337
  let found = false
@@ -346,9 +350,41 @@ export default class SystemTest {
346
350
  }
347
351
  }
348
352
 
353
+ /**
354
+ * @param {string} selector
355
+ * @param {object} args
356
+ * @returns {Promise<void>}
357
+ */
358
+ async waitForNoSelector(selector, args) {
359
+ const timeStart = new Date().getTime()
360
+ const timeout = this.getTimeouts()
361
+ const {useBaseSelector, ...restArgs} = args
362
+
363
+ if (Object.keys(restArgs).length > 0) {
364
+ throw new Error(`Unexpected args: ${Object.keys(restArgs).join(", ")}`)
365
+ }
366
+
367
+ while (true) {
368
+ try {
369
+ const actualSelector = useBaseSelector ? this.getSelector(selector) : selector
370
+
371
+ await this.driver.wait(until.elementIsNotVisible(By.css(actualSelector)), 0)
372
+
373
+ const timeElapsed = new Date().getTime() - timeStart
374
+
375
+ if (timeElapsed > timeout) {
376
+ throw new Error(`Element still found after ${timeout}ms: ${selector}`)
377
+ }
378
+ } catch (error) {
379
+ if (error.message.startsWith("Element couldn't be found after ")) {
380
+ break
381
+ }
382
+ }
383
+ }
384
+ }
385
+
349
386
  /**
350
387
  * Gets notification messages
351
- *
352
388
  * @returns {Promise<string[]>}
353
389
  */
354
390
  async notificationMessages() {
@@ -366,45 +402,65 @@ export default class SystemTest {
366
402
 
367
403
  /**
368
404
  * Expects a notification message to appear and waits for it if necessary.
369
- *
370
405
  * @param {string} expectedNotificationMessage
406
+ * @returns {Promise<void>}
371
407
  */
372
408
  async expectNotificationMessage(expectedNotificationMessage) {
373
409
  const allDetectedNotificationMessages = []
410
+ let foundNotificationMessageElement
374
411
 
375
412
  await waitFor(async () => {
376
- const notificationMessages = await this.notificationMessages()
413
+ const notificationMessageElements = await this.all("[data-class='notification-message']", {useBaseSelector: false})
414
+
415
+ for (const notificationMessageElement of notificationMessageElements) {
416
+ const notificationMessage = await notificationMessageElement.getText()
377
417
 
378
- for (const notificationMessage of notificationMessages) {
379
418
  if (!allDetectedNotificationMessages.includes(notificationMessage)) {
380
419
  allDetectedNotificationMessages.push(notificationMessage)
381
420
  }
382
421
 
383
422
  if (notificationMessage == expectedNotificationMessage) {
423
+ foundNotificationMessageElement = notificationMessageElement
384
424
  return
385
425
  }
386
426
  }
387
427
 
388
428
  throw new Error(`Notification message ${expectedNotificationMessage} wasn't included in: ${allDetectedNotificationMessages.join(", ")}`)
389
429
  })
430
+
431
+ if (foundNotificationMessageElement) {
432
+ await this.interact(foundNotificationMessageElement, "click") // Dismiss the notification message
433
+ }
434
+ }
435
+
436
+ /**
437
+ * @returns {Promise<void>}
438
+ */
439
+ async dismissNotificationMessages() {
440
+ const notificationMessageElements = await this.all("[data-class='notification-message']", {useBaseSelector: false})
441
+
442
+ for (const notificationMessageElement of notificationMessageElements) {
443
+ await this.interact(notificationMessageElement, "click")
444
+ }
445
+
446
+ await this.waitForNoSelector("[data-class='notification-message']", {useBaseSelector: false})
390
447
  }
391
448
 
392
449
  /**
393
450
  * Indicates whether the system test has been started
394
- *
395
451
  * @returns {boolean}
396
452
  */
397
453
  isStarted() { return this._started }
398
454
 
399
455
  /**
400
456
  * Gets the HTML of the current page
401
- *
402
457
  * @returns {Promise<string>}
403
458
  */
404
459
  async getHTML() { return await this.driver.getPageSource() }
405
460
 
406
461
  /**
407
462
  * Starts the system test
463
+ * @returns {Promise<void>}
408
464
  */
409
465
  async start() {
410
466
  if (process.env.SYSTEM_TEST_HOST == "expo-dev-server") {
@@ -444,8 +500,7 @@ export default class SystemTest {
444
500
  await this.find("body > #root", {useBaseSelector: false})
445
501
  await this.find("[data-testid='systemTestingComponent']", {visible: null, useBaseSelector: false})
446
502
  } catch (error) {
447
- await systemTest.takeScreenshot()
448
-
503
+ await this.takeScreenshot()
449
504
  throw error
450
505
  }
451
506
 
@@ -453,11 +508,12 @@ export default class SystemTest {
453
508
  await this.waitForClientWebSocket()
454
509
 
455
510
  this._started = true
456
- systemTest.setBaseSelector("[data-testid='systemTestingComponent'][data-focussed='true']")
511
+ this.setBaseSelector("[data-testid='systemTestingComponent'][data-focussed='true']")
457
512
  }
458
513
 
459
514
  /**
460
515
  * Restores previously set timeouts
516
+ * @returns {Promise<void>}
461
517
  */
462
518
  async restoreTimeouts() {
463
519
  if (!this.getTimeouts()) {
@@ -469,8 +525,8 @@ export default class SystemTest {
469
525
 
470
526
  /**
471
527
  * Sets driver timeouts
472
- *
473
528
  * @param {number} newTimeout
529
+ * @returns {Promise<void>}
474
530
  */
475
531
  async driverSetTimeouts(newTimeout) {
476
532
  await this.driver.manage().setTimeouts({implicit: newTimeout})
@@ -478,8 +534,8 @@ export default class SystemTest {
478
534
 
479
535
  /**
480
536
  * Sets timeouts and stores the previous timeouts
481
- *
482
537
  * @param {number} newTimeout
538
+ * @returns {Promise<void>}
483
539
  */
484
540
  async setTimeouts(newTimeout) {
485
541
  this._timeouts = newTimeout
@@ -488,7 +544,6 @@ export default class SystemTest {
488
544
 
489
545
  /**
490
546
  * Waits for the client web socket to connect
491
- *
492
547
  * @returns {Promise<void>}
493
548
  */
494
549
  waitForClientWebSocket() {
@@ -503,6 +558,7 @@ export default class SystemTest {
503
558
 
504
559
  /**
505
560
  * Starts the web socket server
561
+ * @returns {void}
506
562
  */
507
563
  startWebSocketServer() {
508
564
  this.wss = new WebSocketServer({port: 1985})
@@ -512,6 +568,8 @@ export default class SystemTest {
512
568
 
513
569
  /**
514
570
  * Sets the on command callback
571
+ * @param {function(object) : void} callback
572
+ * @returns {void}
515
573
  */
516
574
  onCommand(callback) {
517
575
  this._onCommandCallback = callback
@@ -519,8 +577,8 @@ export default class SystemTest {
519
577
 
520
578
  /**
521
579
  * Handles a command received from the browser
522
- *
523
- * @param {Object} data
580
+ * @param {object} data
581
+ * @param {object} data.data
524
582
  * @returns {Promise<any>}
525
583
  */
526
584
  onCommandReceived = async ({data}) => {
@@ -553,8 +611,8 @@ export default class SystemTest {
553
611
 
554
612
  /**
555
613
  * Handles a new web socket connection
556
- *
557
614
  * @param {WebSocket} ws
615
+ * @returns {void}
558
616
  */
559
617
  onWebSocketConnection = async (ws) => {
560
618
  this.ws = ws
@@ -569,6 +627,9 @@ export default class SystemTest {
569
627
  }
570
628
  }
571
629
 
630
+ /**
631
+ * @returns {void}
632
+ */
572
633
  onWebSocketClose = () => {
573
634
  this.ws = null
574
635
  this.communicator.ws = null
@@ -576,8 +637,8 @@ export default class SystemTest {
576
637
 
577
638
  /**
578
639
  * Handles an error reported from the browser
579
- *
580
- * @param {Object} data
640
+ * @param {object} data
641
+ * @returns {void}
581
642
  */
582
643
  handleError(data) {
583
644
  if (data.message.includes("Minified React error #419")) {
@@ -596,6 +657,7 @@ export default class SystemTest {
596
657
 
597
658
  /**
598
659
  * Stops the system test
660
+ * @returns {Promise<void>}
599
661
  */
600
662
  async stop() {
601
663
  this.stopScoundrel()
@@ -606,8 +668,8 @@ export default class SystemTest {
606
668
 
607
669
  /**
608
670
  * Visits a path in the browser
609
- *
610
671
  * @param {string} path
672
+ * @returns {Promise<void>}
611
673
  */
612
674
  async driverVisit(path) {
613
675
  const url = `${this.currentUrl}${path}`
@@ -617,6 +679,7 @@ export default class SystemTest {
617
679
 
618
680
  /**
619
681
  * Takes a screenshot, saves HTML and browser logs
682
+ * @returns {Promise<void>}
620
683
  */
621
684
  async takeScreenshot() {
622
685
  const path = `${process.cwd()}/tmp/screenshots`
@@ -644,8 +707,8 @@ export default class SystemTest {
644
707
 
645
708
  /**
646
709
  * Visits a path in the browser
647
- *
648
710
  * @param {string} path
711
+ * @returns {Promise<void>}
649
712
  */
650
713
  async visit(path) {
651
714
  await this.communicator.sendCommand({type: "visit", path})
@@ -653,8 +716,8 @@ export default class SystemTest {
653
716
 
654
717
  /**
655
718
  * Dismisses to a path in the browser
656
- *
657
719
  * @param {string} path
720
+ * @returns {Promise<void>}
658
721
  */
659
722
  async dismissTo(path) {
660
723
  await this.communicator.sendCommand({type: "dismissTo", path})
@@ -9,7 +9,10 @@ const shared = {
9
9
  systemTestBrowserHelper: null
10
10
  }
11
11
 
12
- const isSystemTestEnabled = () => {
12
+ /**
13
+ * @returns {boolean}
14
+ */
15
+ function isSystemTestEnabled() {
13
16
  let enabled = false
14
17
  const initialUrl = globalThis.location?.href
15
18
 
@@ -25,7 +28,10 @@ const isSystemTestEnabled = () => {
25
28
  return enabled
26
29
  }
27
30
 
28
- const getSystemTestBrowserHelper = () => {
31
+ /**
32
+ * @returns {SystemTestBrowserHelper}
33
+ */
34
+ function getSystemTestBrowserHelper() {
29
35
  if (!shared.systemTestBrowserHelper) {
30
36
  shared.systemTestBrowserHelper = new SystemTestBrowserHelper()
31
37
  shared.systemTestBrowserHelper.enableOnBrowser()
@@ -36,13 +42,9 @@ const getSystemTestBrowserHelper = () => {
36
42
 
37
43
  /**
38
44
  * A hook that provides system test capabilities.
39
- *
40
- * @param {Object} options - Options for the hook.
41
- * @param {Function} options.onInitialize - A callback function that is called when the system test browser helper is initialized.
42
- *
43
- * @returns {Object} An object containing:
44
- * - enabled: A boolean indicating if system test mode is enabled.
45
- * - systemTestBrowserHelper: An instance of SystemTestBrowserHelper if enabled, otherwise null.
45
+ * @param {object} options - Options for the hook.
46
+ * @param {function() : void} options.onInitialize - A callback function that is called when the system test browser helper is initialized.
47
+ * @returns {{enabled: boolean, systemTestBrowserHelper: SystemTestBrowserHelper}}
46
48
  */
47
49
  export default function useSystemTest({onInitialize, ...restArgs} = {}) {
48
50
  const router = useRouter()