@progress/kendo-e2e 4.11.2 → 4.12.0
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 +33 -111
- package/dist/selenium/browser.d.ts +245 -4
- package/dist/selenium/browser.js +245 -4
- package/dist/selenium/browser.js.map +1 -1
- package/dist/selenium/conditions.d.ts +255 -0
- package/dist/selenium/conditions.js +251 -0
- package/dist/selenium/conditions.js.map +1 -1
- package/dist/selenium/driver-manager.d.ts +123 -0
- package/dist/selenium/driver-manager.js +118 -0
- package/dist/selenium/driver-manager.js.map +1 -1
- package/dist/selenium/electron-app.d.ts +32 -2
- package/dist/selenium/electron-app.js +32 -2
- package/dist/selenium/electron-app.js.map +1 -1
- package/dist/selenium/expect.d.ts +227 -0
- package/dist/selenium/expect.js +22 -0
- package/dist/selenium/expect.js.map +1 -1
- package/dist/selenium/web-app.d.ts +779 -9
- package/dist/selenium/web-app.js +778 -9
- package/dist/selenium/web-app.js.map +1 -1
- package/docs/API_REFERENCE.md +1309 -0
- package/docs/GETTING_STARTED.md +337 -0
- package/docs/PATTERNS.md +629 -0
- package/package.json +4 -3
|
@@ -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)
|