@progress/kendo-e2e 4.11.3 → 4.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1309 @@
1
+ # API Reference
2
+
3
+ Complete reference for kendo-e2e Browser API.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Browser Class](#browser-class)
8
+ - [Element Finding](#element-finding)
9
+ - [Element Interaction](#element-interaction)
10
+ - [Keyboard Input](#keyboard-input)
11
+ - [Waiting and Conditions](#waiting-and-conditions)
12
+ - [Expect API](#expect-api)
13
+ - [Navigation](#navigation)
14
+ - [Window Management](#window-management)
15
+ - [Testing Utilities](#testing-utilities)
16
+
17
+ ---
18
+
19
+ ## Browser Class
20
+
21
+ Main class for browser automation with automatic waiting.
22
+
23
+ ### Constructor
24
+
25
+ ```typescript
26
+ new Browser(options?: BrowserOptions | ThenableWebDriver)
27
+ ```
28
+
29
+ Create a new Browser instance.
30
+
31
+ **Parameters:**
32
+ - `options` - Configuration object or existing WebDriver instance
33
+
34
+ **BrowserOptions:**
35
+ ```typescript
36
+ {
37
+ driver?: ThenableWebDriver; // Use existing driver
38
+ mobileEmulation?: { // Mobile device emulation
39
+ deviceName: string // e.g., 'iPhone 14 Pro Max'
40
+ } | {
41
+ width: number;
42
+ height: number;
43
+ pixelRatio: number;
44
+ };
45
+ enableBidi?: boolean; // Enable BiDi protocol
46
+ }
47
+ ```
48
+
49
+ **Examples:**
50
+ ```typescript
51
+ // Default browser
52
+ const browser = new Browser();
53
+
54
+ // With mobile emulation
55
+ const mobile = new Browser({
56
+ mobileEmulation: { deviceName: 'iPhone 14 Pro Max' }
57
+ });
58
+
59
+ // Custom dimensions
60
+ const custom = new Browser({
61
+ mobileEmulation: { width: 390, height: 844, pixelRatio: 3 }
62
+ });
63
+
64
+ // With BiDi enabled
65
+ const advanced = new Browser({ enableBidi: true });
66
+
67
+ // With existing driver
68
+ const browser = new Browser(existingDriver);
69
+ ```
70
+
71
+ ### close()
72
+
73
+ ```typescript
74
+ await browser.close(): Promise<void>
75
+ ```
76
+
77
+ Closes the browser and ends the WebDriver session. Always call this to clean up resources.
78
+
79
+ **Example:**
80
+ ```typescript
81
+ afterAll(async () => {
82
+ await browser.close();
83
+ });
84
+ ```
85
+
86
+ ---
87
+
88
+ ## Element Finding
89
+
90
+ Methods for locating elements with automatic waiting.
91
+
92
+ ### find()
93
+
94
+ ```typescript
95
+ await browser.find(
96
+ locator: By | string,
97
+ options?: { timeout?: number; pollTimeout?: number }
98
+ ): Promise<WebElement>
99
+ ```
100
+
101
+ Finds a single element with automatic waiting. **This is the foundation** - most methods use this internally.
102
+
103
+ **Parameters:**
104
+ - `locator` - CSS selector string or Selenium By locator
105
+ - `options.timeout` - Max wait time in ms (default: 10000)
106
+ - `options.pollTimeout` - Retry interval in ms (default: 25)
107
+
108
+ **Returns:** Promise resolving to WebElement
109
+
110
+ **Examples:**
111
+ ```typescript
112
+ // CSS selector
113
+ const button = await browser.find('#submit-button');
114
+ const header = await browser.find('.page-header');
115
+ const input = await browser.find('input[name="email"]');
116
+
117
+ // By locator
118
+ const element = await browser.find(By.xpath('//div[@data-test="value"]'));
119
+ const link = await browser.find(By.linkText('Click here'));
120
+
121
+ // With custom timeout
122
+ const slowElement = await browser.find('#async-content', { timeout: 20000 });
123
+ ```
124
+
125
+ ### findAll()
126
+
127
+ ```typescript
128
+ await browser.findAll(locator: By | string): Promise<WebElement[]>
129
+ ```
130
+
131
+ Finds all matching elements **without waiting**. Returns empty array if none found.
132
+
133
+ **Example:**
134
+ ```typescript
135
+ const items = await browser.findAll('.list-item');
136
+ console.log(`Found ${items.length} items`);
137
+
138
+ for (const item of items) {
139
+ const text = await item.getText();
140
+ console.log(text);
141
+ }
142
+ ```
143
+
144
+ ### findAllWithTimeout()
145
+
146
+ ```typescript
147
+ await browser.findAllWithTimeout(
148
+ locator: By | string,
149
+ options?: { timeout?: number; pollTimeout?: number }
150
+ ): Promise<WebElement[]>
151
+ ```
152
+
153
+ Finds all matching elements, **waiting for at least one** to appear.
154
+
155
+ **Example:**
156
+ ```typescript
157
+ // Wait for search results to load
158
+ const results = await browser.findAllWithTimeout('.search-result');
159
+
160
+ // With custom timeout
161
+ const items = await browser.findAllWithTimeout('.async-item', { timeout: 15000 });
162
+ ```
163
+
164
+ ### findChild()
165
+
166
+ ```typescript
167
+ await browser.findChild(
168
+ rootElement: WebElement | By | string,
169
+ locator: By | string,
170
+ options?: { waitForChild?: boolean; timeout?: number; pollTimeout?: number }
171
+ ): Promise<WebElement>
172
+ ```
173
+
174
+ Finds a child element within a parent element with automatic waiting.
175
+
176
+ **Example:**
177
+ ```typescript
178
+ // Find button within dialog
179
+ const dialog = await browser.find('.modal-dialog');
180
+ const closeBtn = await browser.findChild(dialog, '.close-button');
181
+
182
+ // Or find child directly using parent selector
183
+ const button = await browser.findChild('.modal-dialog', 'button.submit');
184
+ ```
185
+
186
+ ### findChildren()
187
+
188
+ ```typescript
189
+ await browser.findChildren(
190
+ rootElement: WebElement | By | string,
191
+ locator: By | string,
192
+ options?: { waitForChild?: boolean; timeout?: number; pollTimeout?: number }
193
+ ): Promise<WebElement[]>
194
+ ```
195
+
196
+ Finds all child elements within a parent.
197
+
198
+ **Example:**
199
+ ```typescript
200
+ // Find all rows in specific table
201
+ const table = await browser.find('#data-table');
202
+ const rows = await browser.findChildren(table, 'tr');
203
+
204
+ // Or directly
205
+ const items = await browser.findChildren('.dropdown-menu', 'li');
206
+ ```
207
+
208
+ ---
209
+
210
+ ## Element Interaction
211
+
212
+ Methods for interacting with elements (all with automatic waiting).
213
+
214
+ ### click()
215
+
216
+ ```typescript
217
+ await browser.click(
218
+ element: WebElement | By | string,
219
+ options?: { timeout?: number; pollTimeout?: number }
220
+ ): Promise<void>
221
+ ```
222
+
223
+ Clicks an element. **Automatically waits** for element to be present, visible, and enabled.
224
+
225
+ **Example:**
226
+ ```typescript
227
+ await browser.click('#submit-button');
228
+ await browser.click(By.xpath('//button[text()="Submit"]'));
229
+
230
+ // With custom timeout
231
+ await browser.click('.slow-loading-btn', { timeout: 15000 });
232
+ ```
233
+
234
+ ### type()
235
+
236
+ ```typescript
237
+ await browser.type(
238
+ element: WebElement | By | string,
239
+ text: string,
240
+ options?: { clear?: boolean; sendEnter?: boolean }
241
+ ): Promise<void>
242
+ ```
243
+
244
+ Types text into an input element.
245
+
246
+ **Parameters:**
247
+ - `element` - Element to type into
248
+ - `text` - Text to type
249
+ - `options.clear` - Clear existing text first (default: true)
250
+ - `options.sendEnter` - Press Enter after typing (default: false)
251
+
252
+ **Example:**
253
+ ```typescript
254
+ // Type into input (clears existing text)
255
+ await browser.type('#username', 'testuser');
256
+
257
+ // Type and submit
258
+ await browser.type('#search', 'search query', { sendEnter: true });
259
+
260
+ // Type without clearing
261
+ await browser.type('#notes', 'additional text', { clear: false });
262
+ ```
263
+
264
+ ### hover()
265
+
266
+ ```typescript
267
+ await browser.hover(
268
+ element: WebElement | By | string,
269
+ options?: { timeout?: number; pollTimeout?: number }
270
+ ): Promise<void>
271
+ ```
272
+
273
+ Moves mouse over an element (hover action).
274
+
275
+ **Example:**
276
+ ```typescript
277
+ // Hover to reveal dropdown
278
+ await browser.hover('.menu-item');
279
+ await browser.click('.submenu-option');
280
+
281
+ // Hover to show tooltip
282
+ await browser.hover('#info-icon');
283
+ const tooltip = await browser.find('.tooltip');
284
+ ```
285
+
286
+ ### focus()
287
+
288
+ ```typescript
289
+ await browser.focus(
290
+ element: WebElement | By | string,
291
+ options?: { timeout?: number; pollTimeout?: number }
292
+ ): Promise<void>
293
+ ```
294
+
295
+ Sets keyboard focus on an element.
296
+
297
+ **Example:**
298
+ ```typescript
299
+ // Focus input field
300
+ await browser.focus('#email');
301
+
302
+ // Focus before typing
303
+ await browser.focus('#search-box');
304
+ await browser.type('#search-box', 'test query');
305
+ ```
306
+
307
+ ### doubleClick()
308
+
309
+ ```typescript
310
+ await browser.doubleClick(
311
+ element: WebElement | By | string,
312
+ options?: { timeout?: number; pollTimeout?: number }
313
+ ): Promise<void>
314
+ ```
315
+
316
+ Performs a double-click on an element.
317
+
318
+ **Example:**
319
+ ```typescript
320
+ // Double-click to open file
321
+ await browser.doubleClick('.file-icon');
322
+
323
+ // Double-click to select word
324
+ await browser.doubleClick('.text-content');
325
+ ```
326
+
327
+ ### contextClick()
328
+
329
+ ```typescript
330
+ await browser.contextClick(
331
+ element: WebElement | By | string,
332
+ options?: { timeout?: number; pollTimeout?: number }
333
+ ): Promise<void>
334
+ ```
335
+
336
+ Performs a right-click (context menu).
337
+
338
+ **Example:**
339
+ ```typescript
340
+ // Open context menu
341
+ await browser.contextClick('.file-item');
342
+ await browser.click('.context-menu-delete');
343
+ ```
344
+
345
+ ### scrollAndClick()
346
+
347
+ ```typescript
348
+ await browser.scrollAndClick(
349
+ element: WebElement | By | string,
350
+ options?: { timeout?: number; pollTimeout?: number }
351
+ ): Promise<void>
352
+ ```
353
+
354
+ Scrolls element into view and then clicks it. Use for off-screen elements.
355
+
356
+ **Example:**
357
+ ```typescript
358
+ // Click element at bottom of page
359
+ await browser.scrollAndClick('#footer-button');
360
+ ```
361
+
362
+ ### scrollIntoView()
363
+
364
+ ```typescript
365
+ await browser.scrollIntoView(
366
+ locator: By | string,
367
+ options?: { timeout?: number; pollTimeout?: number }
368
+ ): Promise<void>
369
+ ```
370
+
371
+ Scrolls element into viewport without clicking.
372
+
373
+ **Example:**
374
+ ```typescript
375
+ // Scroll to element for screenshot
376
+ await browser.scrollIntoView('#chart');
377
+ const screenshot = await browser.getScreenshot();
378
+ ```
379
+
380
+ ### waitForAnimationAndClick()
381
+
382
+ ```typescript
383
+ await browser.waitForAnimationAndClick(
384
+ element: WebElement | By | string,
385
+ options?: { timeout?: number; pollTimeout?: number }
386
+ ): Promise<void>
387
+ ```
388
+
389
+ Waits for element to stop animating, then clicks it.
390
+
391
+ **Example:**
392
+ ```typescript
393
+ // Click button that slides into view
394
+ await browser.waitForAnimationAndClick('.animated-button');
395
+ ```
396
+
397
+ ### dragTo()
398
+
399
+ ```typescript
400
+ await browser.dragTo(
401
+ source: WebElement | By,
402
+ target: WebElement | By
403
+ ): Promise<void>
404
+ ```
405
+
406
+ Drags source element and drops it on target element.
407
+
408
+ **Example:**
409
+ ```typescript
410
+ // Drag list item to reorder
411
+ await browser.dragTo(
412
+ By.css('.list-item:nth-child(1)'),
413
+ By.css('.list-item:nth-child(3)')
414
+ );
415
+
416
+ // Drag card between columns
417
+ await browser.dragTo('#card-1', '#column-done');
418
+ ```
419
+
420
+ ### dragByOffset()
421
+
422
+ ```typescript
423
+ await browser.dragByOffset(
424
+ element: WebElement | By | string,
425
+ offsetX: number,
426
+ offsetY: number
427
+ ): Promise<void>
428
+ ```
429
+
430
+ Drags an element by pixel offset.
431
+
432
+ **Parameters:**
433
+ - `element` - Element to drag
434
+ - `offsetX` - Horizontal offset (positive = right, negative = left)
435
+ - `offsetY` - Vertical offset (positive = down, negative = up)
436
+
437
+ **Example:**
438
+ ```typescript
439
+ // Drag slider to the right
440
+ await browser.dragByOffset('.slider-handle', 100, 0);
441
+
442
+ // Drag element down and left
443
+ await browser.dragByOffset('.draggable-box', -50, 75);
444
+ ```
445
+
446
+ ---
447
+
448
+ ## Keyboard Input
449
+
450
+ Methods for keyboard interactions.
451
+
452
+ ### sendKey()
453
+
454
+ ```typescript
455
+ await browser.sendKey(key: string): Promise<void>
456
+ ```
457
+
458
+ Sends a single keyboard key press.
459
+
460
+ **Example:**
461
+ ```typescript
462
+ import { Key } from '@kendo/kendo-e2e';
463
+
464
+ // Press Enter
465
+ await browser.sendKey(Key.ENTER);
466
+
467
+ // Press Tab
468
+ await browser.sendKey(Key.TAB);
469
+
470
+ // Press Escape
471
+ await browser.sendKey(Key.ESCAPE);
472
+
473
+ // Arrow keys
474
+ await browser.sendKey(Key.ARROW_DOWN);
475
+ await browser.sendKey(Key.ARROW_UP);
476
+ ```
477
+
478
+ ### sendKeyCombination()
479
+
480
+ ```typescript
481
+ await browser.sendKeyCombination(key1: string, key2: string): Promise<void>
482
+ ```
483
+
484
+ Sends a two-key combination.
485
+
486
+ **Example:**
487
+ ```typescript
488
+ import { Key } from '@kendo/kendo-e2e';
489
+
490
+ // Copy
491
+ await browser.sendKeyCombination(Key.CONTROL, 'c');
492
+
493
+ // Paste
494
+ await browser.sendKeyCombination(Key.CONTROL, 'v');
495
+ ```
496
+
497
+ ### sendKeysCombination()
498
+
499
+ ```typescript
500
+ await browser.sendKeysCombination(keys: string[]): Promise<void>
501
+ ```
502
+
503
+ Sends multiple keys simultaneously.
504
+
505
+ **Example:**
506
+ ```typescript
507
+ import { Key } from '@kendo/kendo-e2e';
508
+
509
+ // Ctrl+Shift+Delete
510
+ await browser.sendKeysCombination([Key.CONTROL, Key.SHIFT, Key.DELETE]);
511
+
512
+ // Select all
513
+ await browser.sendKeysCombination([Key.CONTROL, 'a']);
514
+ ```
515
+
516
+ ### sendControlKeyCombination()
517
+
518
+ ```typescript
519
+ await browser.sendControlKeyCombination(key: string): Promise<void>
520
+ ```
521
+
522
+ Sends Ctrl+key on Windows/Linux or Cmd+key on macOS automatically.
523
+
524
+ **Example:**
525
+ ```typescript
526
+ // Copy (cross-platform)
527
+ await browser.sendControlKeyCombination('c');
528
+
529
+ // Paste (cross-platform)
530
+ await browser.sendControlKeyCombination('v');
531
+
532
+ // Select all (cross-platform)
533
+ await browser.sendControlKeyCombination('a');
534
+ ```
535
+
536
+ ---
537
+
538
+ ## Waiting and Conditions
539
+
540
+ Methods for waiting and checking conditions.
541
+
542
+ ### wait()
543
+
544
+ ```typescript
545
+ await browser.wait(
546
+ condition: WebElementCondition | WaitCondition,
547
+ options?: { timeout?: number; message?: string; pollTimeout?: number }
548
+ ): Promise<void>
549
+ ```
550
+
551
+ Waits for a condition to become true. Throws error if timeout is reached.
552
+
553
+ **Example:**
554
+ ```typescript
555
+ import { EC } from '@kendo/kendo-e2e';
556
+
557
+ // Wait for element to be visible
558
+ await browser.wait(EC.isVisible('#modal'));
559
+
560
+ // Wait with custom timeout and message
561
+ await browser.wait(EC.hasText(element, 'Success'), {
562
+ timeout: 15000,
563
+ message: 'Success message did not appear'
564
+ });
565
+
566
+ // Wait for custom condition
567
+ await browser.wait(async () => {
568
+ const items = await browser.findAll('.item');
569
+ return items.length > 5;
570
+ }, { message: 'Less than 5 items found' });
571
+ ```
572
+
573
+ ### waitSafely()
574
+
575
+ ```typescript
576
+ await browser.waitSafely(
577
+ condition: WebElementCondition | WaitCondition,
578
+ options?: { timeout?: number; pollTimeout?: number }
579
+ ): Promise<boolean>
580
+ ```
581
+
582
+ Waits for a condition **without throwing an error**. Returns true if met, false if timeout.
583
+
584
+ **Example:**
585
+ ```typescript
586
+ import { EC } from '@kendo/kendo-e2e';
587
+
588
+ // Check if element appears
589
+ const appeared = await browser.waitSafely(EC.isVisible('.optional-message'));
590
+ if (appeared) {
591
+ console.log('Message was shown');
592
+ }
593
+
594
+ // Conditional test flow
595
+ const hasModal = await browser.waitSafely(EC.isVisible('.modal'), { timeout: 3000 });
596
+ if (hasModal) {
597
+ await browser.click('.modal .close');
598
+ }
599
+ ```
600
+
601
+ ### waitForAnimation()
602
+
603
+ ```typescript
604
+ await browser.waitForAnimation(
605
+ element: WebElement | By | string,
606
+ options?: { timeout?: number; pollTimeout?: number }
607
+ ): Promise<void>
608
+ ```
609
+
610
+ Waits for an element to stop moving or resizing (animation to complete).
611
+
612
+ **Example:**
613
+ ```typescript
614
+ // Wait for sliding panel to stop
615
+ await browser.waitForAnimation('.slide-panel');
616
+ await browser.click('.slide-panel button');
617
+
618
+ // Wait before screenshot
619
+ await browser.waitForAnimation('.chart');
620
+ const screenshot = await browser.getScreenshot();
621
+ ```
622
+
623
+ ### sleep()
624
+
625
+ ```typescript
626
+ await browser.sleep(milliseconds: number): Promise<void>
627
+ ```
628
+
629
+ Pauses execution for specified time. **Avoid using this** - use `wait()` or `expect()` instead.
630
+
631
+ **Example:**
632
+ ```typescript
633
+ // ❌ Don't do this
634
+ await browser.sleep(2000);
635
+
636
+ // ✅ Do this instead
637
+ await browser.expect('#element').toBeVisible();
638
+ ```
639
+
640
+ ### Expected Conditions (EC)
641
+
642
+ Pre-built condition functions for use with `wait()` and `waitSafely()`.
643
+
644
+ ```typescript
645
+ import { EC } from '@kendo/kendo-e2e';
646
+ ```
647
+
648
+ #### EC.isVisible()
649
+ ```typescript
650
+ EC.isVisible(element: WebElement | By | string): WaitCondition
651
+ ```
652
+
653
+ Wait for element to be visible.
654
+
655
+ ```typescript
656
+ await browser.wait(EC.isVisible('#modal'));
657
+ ```
658
+
659
+ #### EC.notVisible()
660
+ ```typescript
661
+ EC.notVisible(element: WebElement | By | string): WaitCondition
662
+ ```
663
+
664
+ Wait for element to become hidden or be removed.
665
+
666
+ ```typescript
667
+ await browser.wait(EC.notVisible('.spinner'));
668
+ ```
669
+
670
+ #### EC.hasText()
671
+ ```typescript
672
+ EC.hasText(element: WebElement, text: string): WaitCondition
673
+ ```
674
+
675
+ Wait for element to have specific text.
676
+
677
+ ```typescript
678
+ const message = await browser.find('#message');
679
+ await browser.wait(EC.hasText(message, 'Operation completed'));
680
+ ```
681
+
682
+ #### EC.hasValue()
683
+ ```typescript
684
+ EC.hasValue(element: WebElement, value: string): WaitCondition
685
+ ```
686
+
687
+ Wait for input element to have specific value.
688
+
689
+ ```typescript
690
+ const input = await browser.find('#email');
691
+ await browser.wait(EC.hasValue(input, 'user@example.com'));
692
+ ```
693
+
694
+ #### EC.hasFocus()
695
+ ```typescript
696
+ EC.hasFocus(element: WebElement): WaitCondition
697
+ ```
698
+
699
+ Wait for element to have keyboard focus.
700
+
701
+ ```typescript
702
+ const input = await browser.find('#search');
703
+ await browser.wait(EC.hasFocus(input));
704
+ ```
705
+
706
+ #### EC.hasNoFocus()
707
+ ```typescript
708
+ EC.hasNoFocus(element: WebElement): WaitCondition
709
+ ```
710
+
711
+ Wait for element to lose keyboard focus.
712
+
713
+ ```typescript
714
+ const input = await browser.find('#field');
715
+ await browser.wait(EC.hasNoFocus(input));
716
+ ```
717
+
718
+ #### EC.hasAttribute()
719
+ ```typescript
720
+ EC.hasAttribute(
721
+ element: WebElement,
722
+ attribute: string,
723
+ value: string,
724
+ exactMatch?: boolean
725
+ ): WaitCondition
726
+ ```
727
+
728
+ Wait for element to have specific attribute value.
729
+
730
+ ```typescript
731
+ const button = await browser.find('#submit');
732
+ await browser.wait(EC.hasAttribute(button, 'disabled', 'true'));
733
+ ```
734
+
735
+ #### EC.hasClass()
736
+ ```typescript
737
+ EC.hasClass(
738
+ element: WebElement,
739
+ value: string,
740
+ exactMatch?: boolean
741
+ ): WaitCondition
742
+ ```
743
+
744
+ Wait for element to have specific CSS class.
745
+
746
+ ```typescript
747
+ const button = await browser.find('#toggle');
748
+ await browser.wait(EC.hasClass(button, 'active'));
749
+ ```
750
+
751
+ #### EC.hasChild()
752
+ ```typescript
753
+ EC.hasChild(element: WebElement, locator: By | string): WaitCondition
754
+ ```
755
+
756
+ Wait for element to have at least one child matching locator.
757
+
758
+ ```typescript
759
+ const list = await browser.find('ul#results');
760
+ await browser.wait(EC.hasChild(list, 'li'));
761
+ ```
762
+
763
+ #### EC.isInViewport()
764
+ ```typescript
765
+ EC.isInViewport(element: WebElement | By | string): WaitCondition
766
+ ```
767
+
768
+ Wait for element to be in visible viewport.
769
+
770
+ ```typescript
771
+ await browser.wait(EC.isInViewport('.footer-content'));
772
+ ```
773
+
774
+ #### EC.notInViewport()
775
+ ```typescript
776
+ EC.notInViewport(element: WebElement | By | string): WaitCondition
777
+ ```
778
+
779
+ Wait for element to be outside visible viewport.
780
+
781
+ ```typescript
782
+ await browser.wait(EC.notInViewport('#top-element'));
783
+ ```
784
+
785
+ ---
786
+
787
+ ## Expect API
788
+
789
+ Modern, fluent API for assertions with automatic retry. See [expect.md](./expect.md) for full details.
790
+
791
+ ### expect()
792
+
793
+ ```typescript
794
+ browser.expect(selector: string | By): ExpectApi
795
+ ```
796
+
797
+ Creates an expectation API for element assertions.
798
+
799
+ **Returns:** ExpectApi with assertion methods
800
+
801
+ ### toHaveText()
802
+
803
+ ```typescript
804
+ await browser.expect(selector).toHaveText(
805
+ text: string | RegExp,
806
+ opts?: { timeout?: number; message?: string; pollInterval?: number }
807
+ ): Promise<void>
808
+ ```
809
+
810
+ Assert element has specific text (auto-retries until timeout).
811
+
812
+ **Example:**
813
+ ```typescript
814
+ // Exact match
815
+ await browser.expect('#message').toHaveText('Success');
816
+
817
+ // Regex pattern
818
+ await browser.expect('#status').toHaveText(/complete|success/i);
819
+
820
+ // Custom timeout
821
+ await browser.expect('#result').toHaveText('Done', { timeout: 5000 });
822
+ ```
823
+
824
+ ### toBeVisible()
825
+
826
+ ```typescript
827
+ await browser.expect(selector).toBeVisible(
828
+ opts?: { timeout?: number; message?: string; pollInterval?: number }
829
+ ): Promise<void>
830
+ ```
831
+
832
+ Assert element is visible (auto-retries).
833
+
834
+ **Example:**
835
+ ```typescript
836
+ await browser.expect('.modal').toBeVisible();
837
+ await browser.expect('#notification').toBeVisible({ timeout: 5000 });
838
+ ```
839
+
840
+ ### toHaveValue()
841
+
842
+ ```typescript
843
+ await browser.expect(selector).toHaveValue(
844
+ value: string,
845
+ opts?: { timeout?: number; message?: string; pollInterval?: number }
846
+ ): Promise<void>
847
+ ```
848
+
849
+ Assert input has specific value (auto-retries).
850
+
851
+ **Example:**
852
+ ```typescript
853
+ await browser.expect('#email').toHaveValue('user@example.com');
854
+ ```
855
+
856
+ ### toHaveFocus()
857
+
858
+ ```typescript
859
+ await browser.expect(selector).toHaveFocus(
860
+ opts?: { timeout?: number; message?: string; pollInterval?: number }
861
+ ): Promise<void>
862
+ ```
863
+
864
+ Assert element has keyboard focus (auto-retries).
865
+
866
+ **Example:**
867
+ ```typescript
868
+ await browser.expect('#activeInput').toHaveFocus();
869
+ ```
870
+
871
+ ### toHaveAttribute()
872
+
873
+ ```typescript
874
+ await browser.expect(selector).toHaveAttribute(
875
+ attribute: string,
876
+ value: string,
877
+ opts?: { timeout?: number; message?: string; pollInterval?: number; exactMatch?: boolean }
878
+ ): Promise<void>
879
+ ```
880
+
881
+ Assert element has specific attribute value (auto-retries).
882
+
883
+ **Example:**
884
+ ```typescript
885
+ await browser.expect('#submit').toHaveAttribute('disabled', 'true');
886
+ await browser.expect('#link').toHaveAttribute('href', '/dashboard', { exactMatch: false });
887
+ ```
888
+
889
+ ### toHaveClass()
890
+
891
+ ```typescript
892
+ await browser.expect(selector).toHaveClass(
893
+ className: string,
894
+ opts?: { timeout?: number; message?: string; pollInterval?: number; exactMatch?: boolean }
895
+ ): Promise<void>
896
+ ```
897
+
898
+ Assert element has specific CSS class (auto-retries).
899
+
900
+ **Example:**
901
+ ```typescript
902
+ await browser.expect('#button').toHaveClass('active');
903
+ await browser.expect('#div').toHaveClass('btn btn-primary', { exactMatch: true });
904
+ ```
905
+
906
+ ### Negative Assertions
907
+
908
+ ```typescript
909
+ browser.expect(selector).not.toBeVisible(opts?): Promise<void>
910
+ browser.expect(selector).not.toHaveFocus(opts?): Promise<void>
911
+ ```
912
+
913
+ **Example:**
914
+ ```typescript
915
+ // Wait for element to disappear
916
+ await browser.expect('.spinner').not.toBeVisible();
917
+
918
+ // Wait for focus to move away
919
+ await browser.expect('#previous-field').not.toHaveFocus();
920
+ ```
921
+
922
+ ---
923
+
924
+ ## Navigation
925
+
926
+ Methods for browser navigation.
927
+
928
+ ### navigateTo()
929
+
930
+ ```typescript
931
+ await browser.navigateTo(url: string): Promise<void>
932
+ ```
933
+
934
+ Navigates to a URL.
935
+
936
+ **Example:**
937
+ ```typescript
938
+ await browser.navigateTo('https://example.com');
939
+ await browser.navigateTo('http://localhost:3000');
940
+ ```
941
+
942
+ ### refresh()
943
+
944
+ ```typescript
945
+ await browser.refresh(): Promise<void>
946
+ ```
947
+
948
+ Refreshes the current page.
949
+
950
+ **Example:**
951
+ ```typescript
952
+ await browser.click('#update-settings');
953
+ await browser.refresh();
954
+ ```
955
+
956
+ ### getCurrentUrl()
957
+
958
+ ```typescript
959
+ await browser.getCurrentUrl(): Promise<string>
960
+ ```
961
+
962
+ Gets the current URL.
963
+
964
+ **Example:**
965
+ ```typescript
966
+ const url = await browser.getCurrentUrl();
967
+ expect(url).toContain('/products');
968
+ ```
969
+
970
+ ### switchToIFrame()
971
+
972
+ ```typescript
973
+ await browser.switchToIFrame(elementLocator: By): Promise<void>
974
+ ```
975
+
976
+ Switches context to an iframe.
977
+
978
+ **Example:**
979
+ ```typescript
980
+ // Switch to iframe
981
+ await browser.switchToIFrame(By.css('#my-iframe'));
982
+ await browser.click('#button-inside-iframe');
983
+
984
+ // Switch back to main page
985
+ await browser.driver.switchTo().defaultContent();
986
+ ```
987
+
988
+ ---
989
+
990
+ ## Window Management
991
+
992
+ Methods for controlling the browser window.
993
+
994
+ ### resizeWindow()
995
+
996
+ ```typescript
997
+ await browser.resizeWindow(width: number, height: number): Promise<void>
998
+ ```
999
+
1000
+ Resizes the browser window.
1001
+
1002
+ **Example:**
1003
+ ```typescript
1004
+ // Desktop size
1005
+ await browser.resizeWindow(1920, 1080);
1006
+
1007
+ // Mobile size
1008
+ await browser.resizeWindow(375, 667);
1009
+ ```
1010
+
1011
+ ### getRect()
1012
+
1013
+ ```typescript
1014
+ await browser.getRect(): Promise<IRectangle>
1015
+ ```
1016
+
1017
+ Gets current window dimensions and position.
1018
+
1019
+ **Returns:** `{ width, height, x, y }`
1020
+
1021
+ ### setRect()
1022
+
1023
+ ```typescript
1024
+ await browser.setRect(rect: {
1025
+ width?: number;
1026
+ height?: number;
1027
+ x?: number;
1028
+ y?: number;
1029
+ }): Promise<void>
1030
+ ```
1031
+
1032
+ Sets window dimensions and/or position.
1033
+
1034
+ ---
1035
+
1036
+ ## Testing Utilities
1037
+
1038
+ Methods for testing and debugging.
1039
+
1040
+ ### getScreenshot()
1041
+
1042
+ ```typescript
1043
+ await browser.getScreenshot(): Promise<string>
1044
+ ```
1045
+
1046
+ Takes a screenshot, returns base64-encoded image.
1047
+
1048
+ **Example:**
1049
+ ```typescript
1050
+ const screenshot = await browser.getScreenshot();
1051
+ // Save or compare screenshot
1052
+ ```
1053
+
1054
+ ### hideCursor()
1055
+
1056
+ ```typescript
1057
+ await browser.hideCursor(
1058
+ element?: WebElement | By | string,
1059
+ options?: { timeout?: number; pollTimeout?: number }
1060
+ ): Promise<void>
1061
+ ```
1062
+
1063
+ Hides text cursor for cleaner screenshots. Perfect for visual testing where blinking cursor can cause inconsistencies.
1064
+
1065
+ **Example:**
1066
+ ```typescript
1067
+ // Hide all cursors globally
1068
+ await browser.hideCursor();
1069
+
1070
+ // Hide cursor for specific element
1071
+ await browser.hideCursor('#input');
1072
+ ```
1073
+
1074
+ ### clearLogs()
1075
+
1076
+ ```typescript
1077
+ await browser.clearLogs(): Promise<void>
1078
+ ```
1079
+
1080
+ Clears browser console logs.
1081
+
1082
+ **Example:**
1083
+ ```typescript
1084
+ await browser.clearLogs();
1085
+ await browser.click('#trigger-action');
1086
+ const errors = await browser.getErrorLogs();
1087
+ ```
1088
+
1089
+ ### getErrorLogs()
1090
+
1091
+ ```typescript
1092
+ await browser.getErrorLogs(
1093
+ excludeList?: string[],
1094
+ logLevel?: Level
1095
+ ): Promise<string[]>
1096
+ ```
1097
+
1098
+ Gets console errors from browser (Chrome only).
1099
+
1100
+ **Parameters:**
1101
+ - `excludeList` - Strings to filter out (default: `['favicon.ico']`)
1102
+ - `logLevel` - Minimum severity (default: `Level.SEVERE`)
1103
+
1104
+ **Example:**
1105
+ ```typescript
1106
+ const errors = await browser.getErrorLogs();
1107
+ expect(errors.length).toBe(0);
1108
+
1109
+ // Exclude known warnings
1110
+ const errors = await browser.getErrorLogs(['favicon', 'analytics']);
1111
+ ```
1112
+
1113
+ ### getAccessibilityViolations()
1114
+
1115
+ ```typescript
1116
+ await browser.getAccessibilityViolations(
1117
+ cssSelector?: string,
1118
+ disableRules?: string[]
1119
+ ): Promise<[]>
1120
+ ```
1121
+
1122
+ Runs accessibility tests using axe-core.
1123
+
1124
+ **Parameters:**
1125
+ - `cssSelector` - Limit scope (default: `'html'`)
1126
+ - `disableRules` - Rules to skip (default: `['color-contrast']`)
1127
+
1128
+ **Example:**
1129
+ ```typescript
1130
+ // Scan entire page
1131
+ const violations = await browser.getAccessibilityViolations();
1132
+ expect(violations.length).toBe(0);
1133
+
1134
+ // Scan specific component
1135
+ const formViolations = await browser.getAccessibilityViolations('#login-form');
1136
+
1137
+ // Enable all rules
1138
+ const allViolations = await browser.getAccessibilityViolations('html', []);
1139
+ ```
1140
+
1141
+ ### getBrowserName()
1142
+
1143
+ ```typescript
1144
+ await browser.getBrowserName(): Promise<string>
1145
+ ```
1146
+
1147
+ Gets the browser name ('chrome', 'firefox', 'safari', 'edge').
1148
+
1149
+ **Example:**
1150
+ ```typescript
1151
+ const browserName = await browser.getBrowserName();
1152
+ if (browserName === 'safari') {
1153
+ // Skip Safari-specific test
1154
+ return;
1155
+ }
1156
+ ```
1157
+
1158
+ ### executeScript()
1159
+
1160
+ ```typescript
1161
+ await browser.executeScript(
1162
+ script: string,
1163
+ waitBeforeMs?: number,
1164
+ waitAfterMs?: number
1165
+ ): Promise<unknown>
1166
+ ```
1167
+
1168
+ Executes JavaScript in the browser context.
1169
+
1170
+ **Example:**
1171
+ ```typescript
1172
+ // Get page title
1173
+ const title = await browser.executeScript('return document.title;');
1174
+
1175
+ // With waits
1176
+ const height = await browser.executeScript(
1177
+ 'return document.body.scrollHeight;',
1178
+ 500, // wait before
1179
+ 200 // wait after
1180
+ );
1181
+ ```
1182
+
1183
+ ### getText()
1184
+
1185
+ ```typescript
1186
+ await browser.getText(element: WebElement | By | string): Promise<string>
1187
+ ```
1188
+
1189
+ Gets visible text content of an element.
1190
+
1191
+ **Example:**
1192
+ ```typescript
1193
+ const text = await browser.getText('#message');
1194
+ const buttonText = await browser.getText('.submit-btn');
1195
+ ```
1196
+
1197
+ ### getAttribute()
1198
+
1199
+ ```typescript
1200
+ await browser.getAttribute(
1201
+ element: WebElement | By | string,
1202
+ attribute: string
1203
+ ): Promise<string>
1204
+ ```
1205
+
1206
+ Gets an HTML attribute value.
1207
+
1208
+ **Example:**
1209
+ ```typescript
1210
+ const href = await browser.getAttribute('a.download', 'href');
1211
+ const isDisabled = await browser.getAttribute('#submit', 'disabled');
1212
+ const dataId = await browser.getAttribute('.user', 'data-user-id');
1213
+ ```
1214
+
1215
+ ### getProperty()
1216
+
1217
+ ```typescript
1218
+ await browser.getProperty(
1219
+ element: WebElement | By | string,
1220
+ property: string
1221
+ ): Promise<string>
1222
+ ```
1223
+
1224
+ Gets a JavaScript property value (different from attribute).
1225
+
1226
+ **Example:**
1227
+ ```typescript
1228
+ const isChecked = await browser.getProperty('#agree', 'checked');
1229
+ const currentValue = await browser.getProperty('#username', 'value');
1230
+ ```
1231
+
1232
+ ### getColor()
1233
+
1234
+ ```typescript
1235
+ await browser.getColor(element: WebElement | By | string): Promise<string>
1236
+ ```
1237
+
1238
+ Gets text color as hex value.
1239
+
1240
+ **Example:**
1241
+ ```typescript
1242
+ const errorColor = await browser.getColor('.error-message');
1243
+ expect(errorColor).toBe('#ff0000');
1244
+ ```
1245
+
1246
+ ### getBackgroundColor()
1247
+
1248
+ ```typescript
1249
+ await browser.getBackgroundColor(element: WebElement | By | string): Promise<string>
1250
+ ```
1251
+
1252
+ Gets background color as hex value.
1253
+
1254
+ **Example:**
1255
+ ```typescript
1256
+ const btnBg = await browser.getBackgroundColor('#primary-btn');
1257
+ expect(btnBg).toBe('#007bff');
1258
+ ```
1259
+
1260
+ ---
1261
+
1262
+ ## Environment Variables
1263
+
1264
+ Configure browser behavior via environment variables:
1265
+
1266
+ | Variable | Values | Default | Description |
1267
+ |----------|--------|---------|-------------|
1268
+ | `BROWSER_NAME` | `chrome`, `firefox`, `safari`, `MicrosoftEdge` | `chrome` | Browser to use |
1269
+ | `BROWSER_WIDTH` | number | `1366` | Browser window width |
1270
+ | `BROWSER_HEIGHT` | number | `768` | Browser window height |
1271
+ | `HEADLESS` | `true`, `false` | `false` | Run in headless mode |
1272
+
1273
+ **Example:**
1274
+ ```bash
1275
+ BROWSER_NAME=firefox HEADLESS=true npm test
1276
+ ```
1277
+
1278
+ ---
1279
+
1280
+ ## Key Imports
1281
+
1282
+ ```typescript
1283
+ import { Browser, By, Key, EC } from '@kendo/kendo-e2e';
1284
+ ```
1285
+
1286
+ - `Browser` - Main browser class
1287
+ - `By` - Selenium locator strategies
1288
+ - `Key` - Keyboard key constants
1289
+ - `EC` - Expected Conditions helpers
1290
+
1291
+ ---
1292
+
1293
+ ## TypeScript Types
1294
+
1295
+ ```typescript
1296
+ import type {
1297
+ ThenableWebDriver,
1298
+ WebElement,
1299
+ WebElementCondition,
1300
+ ExpectApi,
1301
+ WaitCondition
1302
+ } from '@kendo/kendo-e2e';
1303
+ ```
1304
+
1305
+ ---
1306
+
1307
+ For more details:
1308
+ - **Getting Started:** [GETTING_STARTED.md](./GETTING_STARTED.md)
1309
+ - **Common Patterns:** [PATTERNS.md](./PATTERNS.md)