@srsholmes/tauri-playwright 0.1.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.
@@ -0,0 +1,935 @@
1
+ import * as _playwright_test from '@playwright/test';
2
+ import { Page } from '@playwright/test';
3
+ import { Buffer } from 'node:buffer';
4
+
5
+ /**
6
+ * Any object with TauriLocator/BrowserLocatorAdapter-compatible methods.
7
+ */
8
+ interface LocatorLike {
9
+ isVisible(): Promise<boolean>;
10
+ isHidden(): Promise<boolean>;
11
+ isEnabled(): Promise<boolean>;
12
+ isDisabled(): Promise<boolean>;
13
+ isEditable(): Promise<boolean>;
14
+ isChecked(): Promise<boolean>;
15
+ isFocused?(): Promise<boolean>;
16
+ textContent(): Promise<string | null>;
17
+ innerText(): Promise<string>;
18
+ inputValue(): Promise<string>;
19
+ getAttribute(name: string): Promise<string | null>;
20
+ count(): Promise<number>;
21
+ }
22
+ /**
23
+ * Page-like object for page-level assertions (toHaveURL, toHaveTitle).
24
+ */
25
+ interface PageLike {
26
+ url(): Promise<string>;
27
+ title(): Promise<string>;
28
+ }
29
+ /**
30
+ * Extended expect with Playwright-style locator assertions.
31
+ *
32
+ * Usage:
33
+ * ```ts
34
+ * await expect(locator).toBeVisible();
35
+ * await expect(locator).toContainText('Hello');
36
+ * await expect(locator).not.toBeVisible();
37
+ * ```
38
+ */
39
+ declare const tauriExpect: _playwright_test.Expect<{
40
+ toBeVisible(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, options?: {
41
+ timeout?: number;
42
+ }): Promise<{
43
+ pass: boolean;
44
+ name: string;
45
+ message: () => string;
46
+ }>;
47
+ toBeHidden(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, options?: {
48
+ timeout?: number;
49
+ }): Promise<{
50
+ pass: boolean;
51
+ name: string;
52
+ message: () => string;
53
+ }>;
54
+ toBeEnabled(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, options?: {
55
+ timeout?: number;
56
+ }): Promise<{
57
+ pass: boolean;
58
+ name: string;
59
+ message: () => string;
60
+ }>;
61
+ toBeDisabled(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, options?: {
62
+ timeout?: number;
63
+ }): Promise<{
64
+ pass: boolean;
65
+ name: string;
66
+ message: () => string;
67
+ }>;
68
+ toBeEditable(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, options?: {
69
+ timeout?: number;
70
+ }): Promise<{
71
+ pass: boolean;
72
+ name: string;
73
+ message: () => string;
74
+ }>;
75
+ toBeChecked(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, options?: {
76
+ timeout?: number;
77
+ }): Promise<{
78
+ pass: boolean;
79
+ name: string;
80
+ message: () => string;
81
+ }>;
82
+ toBeAttached(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, options?: {
83
+ timeout?: number;
84
+ }): Promise<{
85
+ pass: boolean;
86
+ name: string;
87
+ message: () => string;
88
+ }>;
89
+ toBeEmpty(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, options?: {
90
+ timeout?: number;
91
+ }): Promise<{
92
+ pass: boolean;
93
+ name: string;
94
+ message: () => string;
95
+ }>;
96
+ toContainText(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, expected: string | RegExp, options?: {
97
+ timeout?: number;
98
+ }): Promise<{
99
+ pass: boolean;
100
+ name: string;
101
+ message: () => string;
102
+ }>;
103
+ toHaveText(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, expected: string | RegExp, options?: {
104
+ timeout?: number;
105
+ }): Promise<{
106
+ pass: boolean;
107
+ name: string;
108
+ message: () => string;
109
+ }>;
110
+ toHaveValue(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, expected: string | RegExp, options?: {
111
+ timeout?: number;
112
+ }): Promise<{
113
+ pass: boolean;
114
+ name: string;
115
+ message: () => string;
116
+ }>;
117
+ toHaveAttribute(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, name: string, value?: string | RegExp, options?: {
118
+ timeout?: number;
119
+ }): Promise<{
120
+ pass: boolean;
121
+ name: string;
122
+ message: () => string;
123
+ }>;
124
+ toHaveClass(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, expected: string | RegExp, options?: {
125
+ timeout?: number;
126
+ }): Promise<{
127
+ pass: boolean;
128
+ name: string;
129
+ message: () => string;
130
+ }>;
131
+ toHaveId(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, expected: string, options?: {
132
+ timeout?: number;
133
+ }): Promise<{
134
+ pass: boolean;
135
+ name: string;
136
+ message: () => string;
137
+ }>;
138
+ toHaveCount(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, expected: number, options?: {
139
+ timeout?: number;
140
+ }): Promise<{
141
+ pass: boolean;
142
+ name: string;
143
+ message: () => string;
144
+ }>;
145
+ toBeFocused(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, options?: {
146
+ timeout?: number;
147
+ }): Promise<{
148
+ pass: boolean;
149
+ name: string;
150
+ message: () => string;
151
+ }>;
152
+ toHaveCSS(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, property: string, expected: string | RegExp, options?: {
153
+ timeout?: number;
154
+ }): Promise<{
155
+ pass: boolean;
156
+ name: string;
157
+ message: () => string;
158
+ }>;
159
+ toHaveURL(this: _playwright_test.ExpectMatcherState, page: PageLike, expected: string | RegExp, options?: {
160
+ timeout?: number;
161
+ }): Promise<{
162
+ pass: boolean;
163
+ name: string;
164
+ message: () => string;
165
+ }>;
166
+ toHaveTitle(this: _playwright_test.ExpectMatcherState, page: PageLike, expected: string | RegExp, options?: {
167
+ timeout?: number;
168
+ }): Promise<{
169
+ pass: boolean;
170
+ name: string;
171
+ message: () => string;
172
+ }>;
173
+ }>;
174
+
175
+ /**
176
+ * Client that connects to the tauri-plugin-playwright socket server.
177
+ * Sends newline-delimited JSON commands and receives JSON responses.
178
+ */
179
+ declare class PluginClient {
180
+ private socketPath?;
181
+ private tcpPort?;
182
+ private socket;
183
+ private readline;
184
+ private pending;
185
+ private seq;
186
+ private responseQueue;
187
+ private waitingForResponse;
188
+ constructor(socketPath?: string | undefined, tcpPort?: number | undefined);
189
+ /** Connect to the plugin's socket server. */
190
+ connect(): Promise<void>;
191
+ /** Disconnect from the server. */
192
+ disconnect(): void;
193
+ /** Send a command and wait for the response. */
194
+ send(command: Record<string, unknown>): Promise<PluginResponse>;
195
+ private waitForLine;
196
+ }
197
+ interface PluginResponse {
198
+ ok: boolean;
199
+ data?: unknown;
200
+ error?: string;
201
+ }
202
+
203
+ /**
204
+ * A Playwright-like Page API backed by the tauri-plugin-playwright socket bridge.
205
+ * Commands are sent to the plugin, which injects JS into the real Tauri webview.
206
+ */
207
+ type TimeoutOption = {
208
+ timeout?: number;
209
+ };
210
+ declare class TauriPage {
211
+ private client;
212
+ private _defaultTimeout;
213
+ constructor(client: PluginClient);
214
+ /** Set the default timeout for all auto-waiting operations (ms). */
215
+ setDefaultTimeout(timeout: number): void;
216
+ private _t;
217
+ /** Execute arbitrary JavaScript in the webview and return the result. */
218
+ evaluate<T = unknown>(script: string): Promise<T>;
219
+ /** Click an element matching the CSS selector. Auto-waits. */
220
+ click(selector: string, options?: TimeoutOption): Promise<void>;
221
+ /** Double-click an element. Auto-waits. */
222
+ dblclick(selector: string, options?: TimeoutOption): Promise<void>;
223
+ /** Hover over an element. Auto-waits. */
224
+ hover(selector: string, options?: TimeoutOption): Promise<void>;
225
+ /** Clear and fill an input element with text. Auto-waits. */
226
+ fill(selector: string, text: string, options?: TimeoutOption): Promise<void>;
227
+ /** Type text character by character into an element. Auto-waits. */
228
+ type(selector: string, text: string, options?: TimeoutOption): Promise<void>;
229
+ /** Press a key on an element (e.g., 'Enter', 'Tab', 'Escape'). Auto-waits. */
230
+ press(selector: string, key: string, options?: TimeoutOption): Promise<void>;
231
+ /** Check a checkbox or radio button. Auto-waits. */
232
+ check(selector: string, options?: TimeoutOption): Promise<void>;
233
+ /** Uncheck a checkbox. Auto-waits. */
234
+ uncheck(selector: string, options?: TimeoutOption): Promise<void>;
235
+ /** Select an option from a <select> element by value. Auto-waits. */
236
+ selectOption(selector: string, value: string, options?: TimeoutOption): Promise<string>;
237
+ /** Focus an element. Auto-waits. */
238
+ focus(selector: string, options?: TimeoutOption): Promise<void>;
239
+ /** Blur (unfocus) an element. Auto-waits. */
240
+ blur(selector: string, options?: TimeoutOption): Promise<void>;
241
+ /** Get the text content of an element. Auto-waits for element. */
242
+ textContent(selector: string, options?: TimeoutOption): Promise<string | null>;
243
+ /** Get the innerHTML of an element. Auto-waits for element. */
244
+ innerHTML(selector: string, options?: TimeoutOption): Promise<string>;
245
+ /** Get the innerText of an element (visible text only). Auto-waits for element. */
246
+ innerText(selector: string, options?: TimeoutOption): Promise<string>;
247
+ /** Get textContent of all elements matching a selector. No wait (works on zero matches). */
248
+ allTextContents(selector: string): Promise<string[]>;
249
+ /** Get innerText of all elements matching a selector. No wait (works on zero matches). */
250
+ allInnerTexts(selector: string): Promise<string[]>;
251
+ /** Get an attribute value from an element. Auto-waits for element. */
252
+ getAttribute(selector: string, name: string, options?: TimeoutOption): Promise<string | null>;
253
+ /** Get the input value of a form element. Auto-waits for element. */
254
+ inputValue(selector: string, options?: TimeoutOption): Promise<string>;
255
+ /** Get the bounding box of an element. Auto-waits for element. */
256
+ boundingBox(selector: string, options?: TimeoutOption): Promise<{
257
+ x: number;
258
+ y: number;
259
+ width: number;
260
+ height: number;
261
+ } | null>;
262
+ /** Check if an element matching the selector is visible. */
263
+ isVisible(selector: string): Promise<boolean>;
264
+ /** Check if an element is checked (checkbox/radio). */
265
+ isChecked(selector: string): Promise<boolean>;
266
+ /** Check if an element is disabled. */
267
+ isDisabled(selector: string): Promise<boolean>;
268
+ /** Check if an element is editable. */
269
+ isEditable(selector: string): Promise<boolean>;
270
+ /** Check if an element is hidden. */
271
+ isHidden(selector: string): Promise<boolean>;
272
+ /** Check if an element is enabled. */
273
+ isEnabled(selector: string): Promise<boolean>;
274
+ /** Wait for an element matching the selector to become visible. */
275
+ waitForSelector(selector: string, timeout?: number): Promise<void>;
276
+ /** Wait for a JS expression to return truthy. */
277
+ waitForFunction(expression: string, timeout?: number): Promise<void>;
278
+ /** Count elements matching a selector. */
279
+ count(selector: string): Promise<number>;
280
+ /** Get the page title. */
281
+ title(): Promise<string>;
282
+ /** Get the current URL. */
283
+ url(): Promise<string>;
284
+ /** Get the full page HTML. */
285
+ content(): Promise<string>;
286
+ /** Navigate to a URL. */
287
+ goto(url: string): Promise<void>;
288
+ /** Reload the page. */
289
+ reload(): Promise<void>;
290
+ /** Navigate back in history. */
291
+ goBack(): Promise<void>;
292
+ /** Navigate forward in history. */
293
+ goForward(): Promise<void>;
294
+ /** Wait for the URL to contain or match a pattern. */
295
+ waitForURL(pattern: string, options?: TimeoutOption): Promise<void>;
296
+ /** Check if an element is the active/focused element. */
297
+ isFocused(selector: string): Promise<boolean>;
298
+ /** Get a computed CSS style value from an element. Auto-waits. */
299
+ getComputedStyle(selector: string, property: string, options?: TimeoutOption): Promise<string>;
300
+ /** Dispatch a custom DOM event on an element. Auto-waits. */
301
+ dispatchEvent(selector: string, eventType: string, options?: TimeoutOption): Promise<void>;
302
+ /** Drag one element onto another. Auto-waits. */
303
+ dragAndDrop(source: string, target: string, options?: TimeoutOption): Promise<void>;
304
+ /** Set files on a file input element. */
305
+ setInputFiles(selector: string, files: Array<{
306
+ name: string;
307
+ mimeType: string;
308
+ buffer: Buffer;
309
+ }>, options?: TimeoutOption): Promise<number>;
310
+ /** Install dialog interception (alert/confirm/prompt). */
311
+ installDialogHandler(options?: {
312
+ defaultConfirm?: boolean;
313
+ defaultPromptText?: string;
314
+ }): Promise<void>;
315
+ /** Get captured dialogs since last check. */
316
+ getDialogs(): Promise<Array<{
317
+ type: 'alert' | 'confirm' | 'prompt';
318
+ message: string;
319
+ default?: string;
320
+ }>>;
321
+ /** Clear captured dialogs. */
322
+ clearDialogs(): Promise<void>;
323
+ /** Add a network route that intercepts matching fetch/XHR requests. */
324
+ route(pattern: string, response: {
325
+ status?: number;
326
+ body?: string;
327
+ contentType?: string;
328
+ }): Promise<void>;
329
+ /** Remove a network route. */
330
+ unroute(pattern: string): Promise<void>;
331
+ /** Clear all network routes. */
332
+ clearRoutes(): Promise<void>;
333
+ /** Get captured network requests. */
334
+ getNetworkRequests(): Promise<Array<{
335
+ url: string;
336
+ method: string;
337
+ timestamp: number;
338
+ }>>;
339
+ /** Clear captured network requests. */
340
+ clearNetworkRequests(): Promise<void>;
341
+ /** Take a native screenshot of the Tauri window. Returns PNG buffer. */
342
+ screenshot(options?: {
343
+ path?: string;
344
+ }): Promise<Buffer>;
345
+ /** Start recording the Tauri window as video (native frame capture). */
346
+ startRecording(options?: {
347
+ path?: string;
348
+ fps?: number;
349
+ }): Promise<{
350
+ dir: string;
351
+ fps: number;
352
+ }>;
353
+ /** Stop recording and return the video path (if ffmpeg is available). */
354
+ stopRecording(): Promise<{
355
+ dir: string;
356
+ frame_count: number;
357
+ fps: number;
358
+ video: string | null;
359
+ }>;
360
+ /** Create a locator for chained operations. */
361
+ locator(selector: string): TauriLocator;
362
+ getByTestId(testId: string): TauriLocator;
363
+ getByPlaceholder(text: string, options?: {
364
+ exact?: boolean;
365
+ }): TauriLocator;
366
+ getByAltText(text: string, options?: {
367
+ exact?: boolean;
368
+ }): TauriLocator;
369
+ getByTitle(text: string, options?: {
370
+ exact?: boolean;
371
+ }): TauriLocator;
372
+ getByRole(role: string, options?: {
373
+ name?: string;
374
+ }): TauriLocator;
375
+ getByText(text: string, options?: {
376
+ exact?: boolean;
377
+ }): TauriLocator;
378
+ getByLabel(text: string, options?: {
379
+ exact?: boolean;
380
+ }): TauriLocator;
381
+ readonly keyboard: TauriKeyboard;
382
+ readonly mouse: TauriMouse;
383
+ /** Send a command to the plugin and handle errors. */
384
+ private command;
385
+ }
386
+ /**
387
+ * A Playwright-like Locator for chained element interactions.
388
+ * Supports both CSS selectors and JS-based selectors (for getByText, getByLabel).
389
+ */
390
+ declare class TauriLocator {
391
+ private page;
392
+ private selector;
393
+ private _jsFind?;
394
+ constructor(page: TauriPage, selector: string, options?: {
395
+ jsFind?: string;
396
+ });
397
+ /** Whether this locator uses JS-based element resolution. */
398
+ get isJsBased(): boolean;
399
+ /**
400
+ * Execute an action/query. For CSS selectors, delegates to TauriPage.
401
+ * For JS-based selectors, uses evaluate with the JS find expression.
402
+ */
403
+ private _eval;
404
+ private _actionScript;
405
+ private _queryScript;
406
+ click(options?: TimeoutOption): Promise<void>;
407
+ dblclick(options?: TimeoutOption): Promise<void>;
408
+ hover(options?: TimeoutOption): Promise<void>;
409
+ fill(text: string, options?: TimeoutOption): Promise<void>;
410
+ press(key: string, options?: TimeoutOption): Promise<void>;
411
+ check(options?: TimeoutOption): Promise<void>;
412
+ uncheck(options?: TimeoutOption): Promise<void>;
413
+ selectOption(value: string, options?: TimeoutOption): Promise<string>;
414
+ focus(options?: TimeoutOption): Promise<void>;
415
+ blur(options?: TimeoutOption): Promise<void>;
416
+ clear(): Promise<void>;
417
+ /** Type text character-by-character (Playwright's replacement for deprecated type()). */
418
+ pressSequentially(text: string, options?: {
419
+ delay?: number;
420
+ }): Promise<void>;
421
+ /** Dispatch a custom DOM event on the element. */
422
+ dispatchEvent(eventType: string, options?: TimeoutOption): Promise<void>;
423
+ /** Run a JS function on the matched element. The function receives `el` as argument. */
424
+ evaluate<T = unknown>(fn: string): Promise<T>;
425
+ /** Check if this element is the active/focused element. */
426
+ isFocused(): Promise<boolean>;
427
+ scrollIntoViewIfNeeded(): Promise<void>;
428
+ textContent(options?: TimeoutOption): Promise<string | null>;
429
+ innerHTML(options?: TimeoutOption): Promise<string>;
430
+ innerText(options?: TimeoutOption): Promise<string>;
431
+ getAttribute(name: string, options?: TimeoutOption): Promise<string | null>;
432
+ inputValue(options?: TimeoutOption): Promise<string>;
433
+ boundingBox(): Promise<{
434
+ x: number;
435
+ y: number;
436
+ width: number;
437
+ height: number;
438
+ } | null>;
439
+ isVisible(): Promise<boolean>;
440
+ isHidden(): Promise<boolean>;
441
+ isChecked(): Promise<boolean>;
442
+ isDisabled(): Promise<boolean>;
443
+ isEditable(): Promise<boolean>;
444
+ isEnabled(): Promise<boolean>;
445
+ waitFor(timeout?: number): Promise<void>;
446
+ count(): Promise<number>;
447
+ nth(index: number): TauriLocator;
448
+ first(): TauriLocator;
449
+ last(): TauriLocator;
450
+ filter(options: {
451
+ hasText?: string | RegExp;
452
+ }): TauriLocator;
453
+ all(): Promise<TauriLocator[]>;
454
+ getByTestId(testId: string): TauriLocator;
455
+ getByPlaceholder(text: string, options?: {
456
+ exact?: boolean;
457
+ }): TauriLocator;
458
+ getByText(text: string, options?: {
459
+ exact?: boolean;
460
+ }): TauriLocator;
461
+ getByRole(role: string, options?: {
462
+ name?: string;
463
+ }): TauriLocator;
464
+ locator(selector: string): TauriLocator;
465
+ }
466
+ declare class TauriKeyboard {
467
+ private page;
468
+ private _modifiers;
469
+ constructor(page: TauriPage);
470
+ press(key: string): Promise<void>;
471
+ down(key: string): Promise<void>;
472
+ up(key: string): Promise<void>;
473
+ type(text: string, options?: {
474
+ delay?: number;
475
+ }): Promise<void>;
476
+ insertText(text: string): Promise<void>;
477
+ }
478
+ declare class TauriMouse {
479
+ private page;
480
+ constructor(page: TauriPage);
481
+ click(x: number, y: number, options?: {
482
+ button?: 'left' | 'right' | 'middle';
483
+ }): Promise<void>;
484
+ dblclick(x: number, y: number): Promise<void>;
485
+ move(x: number, y: number): Promise<void>;
486
+ down(options?: {
487
+ button?: 'left' | 'right' | 'middle';
488
+ }): Promise<void>;
489
+ up(options?: {
490
+ button?: 'left' | 'right' | 'middle';
491
+ }): Promise<void>;
492
+ wheel(deltaX: number, deltaY: number): Promise<void>;
493
+ }
494
+
495
+ /**
496
+ * Wraps a Playwright Page to provide the same API surface as TauriPage.
497
+ * This allows the same tests to run in both browser-only and Tauri modes.
498
+ */
499
+ declare class BrowserPageAdapter {
500
+ private page;
501
+ constructor(page: Page);
502
+ /** Set the default timeout for all auto-waiting operations (ms). */
503
+ setDefaultTimeout(timeout: number): void;
504
+ get playwrightPage(): Page;
505
+ evaluate<T = unknown>(script: string): Promise<T>;
506
+ click(selector: string): Promise<void>;
507
+ dblclick(selector: string): Promise<void>;
508
+ hover(selector: string): Promise<void>;
509
+ fill(selector: string, text: string): Promise<void>;
510
+ type(selector: string, text: string): Promise<void>;
511
+ press(selector: string, key: string): Promise<void>;
512
+ check(selector: string): Promise<void>;
513
+ uncheck(selector: string): Promise<void>;
514
+ selectOption(selector: string, value: string): Promise<string>;
515
+ focus(selector: string): Promise<void>;
516
+ blur(selector: string): Promise<void>;
517
+ textContent(selector: string): Promise<string | null>;
518
+ innerHTML(selector: string): Promise<string>;
519
+ innerText(selector: string): Promise<string>;
520
+ allTextContents(selector: string): Promise<string[]>;
521
+ allInnerTexts(selector: string): Promise<string[]>;
522
+ getAttribute(selector: string, name: string): Promise<string | null>;
523
+ inputValue(selector: string): Promise<string>;
524
+ boundingBox(selector: string): Promise<{
525
+ x: number;
526
+ y: number;
527
+ width: number;
528
+ height: number;
529
+ } | null>;
530
+ isVisible(selector: string): Promise<boolean>;
531
+ isChecked(selector: string): Promise<boolean>;
532
+ isDisabled(selector: string): Promise<boolean>;
533
+ isEditable(selector: string): Promise<boolean>;
534
+ isHidden(selector: string): Promise<boolean>;
535
+ isEnabled(selector: string): Promise<boolean>;
536
+ waitForSelector(selector: string, timeout?: number): Promise<void>;
537
+ waitForFunction(expression: string, timeout?: number): Promise<void>;
538
+ count(selector: string): Promise<number>;
539
+ title(): Promise<string>;
540
+ url(): Promise<string>;
541
+ content(): Promise<string>;
542
+ goto(url: string): Promise<void>;
543
+ reload(): Promise<void>;
544
+ goBack(): Promise<void>;
545
+ goForward(): Promise<void>;
546
+ waitForURL(pattern: string, options?: {
547
+ timeout?: number;
548
+ }): Promise<void>;
549
+ isFocused(selector: string): Promise<boolean>;
550
+ getComputedStyle(selector: string, property: string): Promise<string>;
551
+ dispatchEvent(selector: string, eventType: string): Promise<void>;
552
+ dragAndDrop(source: string, target: string): Promise<void>;
553
+ setInputFiles(selector: string, files: Array<{
554
+ name: string;
555
+ mimeType: string;
556
+ buffer: Buffer;
557
+ }>): Promise<number>;
558
+ private dialogHandler;
559
+ private capturedDialogs;
560
+ installDialogHandler(options?: {
561
+ defaultConfirm?: boolean;
562
+ defaultPromptText?: string;
563
+ }): Promise<void>;
564
+ getDialogs(): Promise<Array<{
565
+ type: string;
566
+ message: string;
567
+ default?: string;
568
+ }>>;
569
+ clearDialogs(): Promise<void>;
570
+ private capturedRequests;
571
+ private activeRoutes;
572
+ route(pattern: string, response: {
573
+ status?: number;
574
+ body?: string;
575
+ contentType?: string;
576
+ }): Promise<void>;
577
+ unroute(pattern: string): Promise<void>;
578
+ clearRoutes(): Promise<void>;
579
+ getNetworkRequests(): Promise<Array<{
580
+ url: string;
581
+ method: string;
582
+ timestamp: number;
583
+ }>>;
584
+ clearNetworkRequests(): Promise<void>;
585
+ getByTestId(testId: string): _playwright_test.Locator;
586
+ getByPlaceholder(text: string, options?: {
587
+ exact?: boolean;
588
+ }): _playwright_test.Locator;
589
+ getByAltText(text: string, options?: {
590
+ exact?: boolean;
591
+ }): _playwright_test.Locator;
592
+ getByTitle(text: string, options?: {
593
+ exact?: boolean;
594
+ }): _playwright_test.Locator;
595
+ getByRole(role: Parameters<Page['getByRole']>[0], options?: Parameters<Page['getByRole']>[1]): _playwright_test.Locator;
596
+ getByText(text: string, options?: {
597
+ exact?: boolean;
598
+ }): _playwright_test.Locator;
599
+ getByLabel(text: string, options?: {
600
+ exact?: boolean;
601
+ }): _playwright_test.Locator;
602
+ get keyboard(): _playwright_test.Keyboard;
603
+ get mouse(): _playwright_test.Mouse;
604
+ screenshot(options?: {
605
+ path?: string;
606
+ }): Promise<Buffer>;
607
+ startRecording(): Promise<{
608
+ dir: string;
609
+ fps: number;
610
+ }>;
611
+ stopRecording(): Promise<{
612
+ dir: string;
613
+ frame_count: number;
614
+ fps: number;
615
+ video: string | null;
616
+ }>;
617
+ locator(selector: string): _playwright_test.Locator;
618
+ }
619
+
620
+ /**
621
+ * Configuration for creating a Tauri Playwright test fixture.
622
+ */
623
+ interface TauriTestConfig {
624
+ /**
625
+ * Vite/dev server URL for browser-only mode.
626
+ * @example 'http://localhost:1420'
627
+ */
628
+ devUrl: string;
629
+ /**
630
+ * Mock IPC handler map for browser-only mode.
631
+ * Keys are Tauri command names, values are functions that receive
632
+ * the command args and return mock data.
633
+ */
634
+ ipcMocks?: Record<string, (args?: Record<string, unknown>) => unknown>;
635
+ /**
636
+ * Command to start the Tauri app for full E2E mode.
637
+ * If not set, assumes the app is already running.
638
+ * @example 'npx tauri dev'
639
+ */
640
+ tauriCommand?: string;
641
+ /** Working directory for the Tauri command. */
642
+ tauriCwd?: string;
643
+ /** Cargo features to enable (e.g. ['e2e-testing']). */
644
+ tauriFeatures?: string[];
645
+ /** Plugin socket path. Default: /tmp/tauri-playwright.sock */
646
+ mcpSocket?: string;
647
+ /** Startup timeout in seconds. Default: 120 */
648
+ startTimeout?: number;
649
+ /**
650
+ * CDP endpoint for connecting to WebView2 on Windows.
651
+ * When mode is 'cdp', Playwright connects directly via Chrome DevTools Protocol.
652
+ * @example 'http://localhost:9222'
653
+ */
654
+ cdpEndpoint?: string;
655
+ }
656
+ /**
657
+ * Test mode selector.
658
+ * - 'browser': Runs against dev server with mocked Tauri IPC (headless, fast)
659
+ * - 'tauri': Runs against real Tauri app via plugin socket bridge (all platforms)
660
+ * - 'cdp': Connects to WebView2 via Chrome DevTools Protocol (Windows only, full Playwright)
661
+ */
662
+ type TestMode = 'browser' | 'tauri' | 'cdp';
663
+ /**
664
+ * Extended Playwright fixtures provided by tauri-playwright.
665
+ * In browser mode, tauriPage is a Playwright Page.
666
+ * In tauri mode, tauriPage is a TauriPage with Playwright-like API.
667
+ */
668
+ interface TauriFixtures {
669
+ tauriPage: TauriPage | BrowserPageAdapter;
670
+ mode: TestMode;
671
+ }
672
+ /**
673
+ * Shape of a captured IPC invoke call (browser mode only).
674
+ */
675
+ interface CapturedInvoke {
676
+ cmd: string;
677
+ args: Record<string, unknown>;
678
+ timestamp: number;
679
+ }
680
+
681
+ /**
682
+ * Creates a Playwright test instance with Tauri-specific fixtures.
683
+ *
684
+ * **Browser mode** (default): Headless Chromium with mocked Tauri IPC. Fast, no Rust needed.
685
+ * **Tauri mode**: Socket bridge to the real Tauri webview. Works on all platforms.
686
+ * **CDP mode**: Direct Chrome DevTools Protocol to WebView2. Windows only, full Playwright.
687
+ */
688
+ declare function createTauriTest(config: TauriTestConfig): {
689
+ test: _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & TauriFixtures, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions>;
690
+ expect: _playwright_test.Expect<{
691
+ toBeVisible(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, options?: {
692
+ timeout?: number;
693
+ }): Promise<{
694
+ pass: boolean;
695
+ name: string;
696
+ message: () => string;
697
+ }>;
698
+ toBeHidden(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, options?: {
699
+ timeout?: number;
700
+ }): Promise<{
701
+ pass: boolean;
702
+ name: string;
703
+ message: () => string;
704
+ }>;
705
+ toBeEnabled(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, options?: {
706
+ timeout?: number;
707
+ }): Promise<{
708
+ pass: boolean;
709
+ name: string;
710
+ message: () => string;
711
+ }>;
712
+ toBeDisabled(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, options?: {
713
+ timeout?: number;
714
+ }): Promise<{
715
+ pass: boolean;
716
+ name: string;
717
+ message: () => string;
718
+ }>;
719
+ toBeEditable(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, options?: {
720
+ timeout?: number;
721
+ }): Promise<{
722
+ pass: boolean;
723
+ name: string;
724
+ message: () => string;
725
+ }>;
726
+ toBeChecked(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, options?: {
727
+ timeout?: number;
728
+ }): Promise<{
729
+ pass: boolean;
730
+ name: string;
731
+ message: () => string;
732
+ }>;
733
+ toBeAttached(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, options?: {
734
+ timeout?: number;
735
+ }): Promise<{
736
+ pass: boolean;
737
+ name: string;
738
+ message: () => string;
739
+ }>;
740
+ toBeEmpty(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, options?: {
741
+ timeout?: number;
742
+ }): Promise<{
743
+ pass: boolean;
744
+ name: string;
745
+ message: () => string;
746
+ }>;
747
+ toContainText(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, expected: string | RegExp, options?: {
748
+ timeout?: number;
749
+ }): Promise<{
750
+ pass: boolean;
751
+ name: string;
752
+ message: () => string;
753
+ }>;
754
+ toHaveText(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, expected: string | RegExp, options?: {
755
+ timeout?: number;
756
+ }): Promise<{
757
+ pass: boolean;
758
+ name: string;
759
+ message: () => string;
760
+ }>;
761
+ toHaveValue(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, expected: string | RegExp, options?: {
762
+ timeout?: number;
763
+ }): Promise<{
764
+ pass: boolean;
765
+ name: string;
766
+ message: () => string;
767
+ }>;
768
+ toHaveAttribute(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, name: string, value?: string | RegExp, options?: {
769
+ timeout?: number;
770
+ }): Promise<{
771
+ pass: boolean;
772
+ name: string;
773
+ message: () => string;
774
+ }>;
775
+ toHaveClass(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, expected: string | RegExp, options?: {
776
+ timeout?: number;
777
+ }): Promise<{
778
+ pass: boolean;
779
+ name: string;
780
+ message: () => string;
781
+ }>;
782
+ toHaveId(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, expected: string, options?: {
783
+ timeout?: number;
784
+ }): Promise<{
785
+ pass: boolean;
786
+ name: string;
787
+ message: () => string;
788
+ }>;
789
+ toHaveCount(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, expected: number, options?: {
790
+ timeout?: number;
791
+ }): Promise<{
792
+ pass: boolean;
793
+ name: string;
794
+ message: () => string;
795
+ }>;
796
+ toBeFocused(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, options?: {
797
+ timeout?: number;
798
+ }): Promise<{
799
+ pass: boolean;
800
+ name: string;
801
+ message: () => string;
802
+ }>;
803
+ toHaveCSS(this: _playwright_test.ExpectMatcherState, locator: LocatorLike, property: string, expected: string | RegExp, options?: {
804
+ timeout?: number;
805
+ }): Promise<{
806
+ pass: boolean;
807
+ name: string;
808
+ message: () => string;
809
+ }>;
810
+ toHaveURL(this: _playwright_test.ExpectMatcherState, page: PageLike, expected: string | RegExp, options?: {
811
+ timeout?: number;
812
+ }): Promise<{
813
+ pass: boolean;
814
+ name: string;
815
+ message: () => string;
816
+ }>;
817
+ toHaveTitle(this: _playwright_test.ExpectMatcherState, page: PageLike, expected: string | RegExp, options?: {
818
+ timeout?: number;
819
+ }): Promise<{
820
+ pass: boolean;
821
+ name: string;
822
+ message: () => string;
823
+ }>;
824
+ }>;
825
+ };
826
+ /**
827
+ * Helper to retrieve captured IPC calls from the page (browser mode only).
828
+ */
829
+ declare function getCapturedInvokes(page: Page): Promise<CapturedInvoke[]>;
830
+ /**
831
+ * Clear the captured IPC call log (browser mode only).
832
+ */
833
+ declare function clearCapturedInvokes(page: Page): Promise<void>;
834
+ /**
835
+ * Emit a mock Tauri event into the page (browser mode only).
836
+ */
837
+ declare function emitMockEvent(page: Page, event: string, payload: unknown): Promise<void>;
838
+
839
+ /**
840
+ * IPC Mock Generator for Tauri apps running in browser-only mode.
841
+ *
842
+ * When `withGlobalTauri: true` is set in tauri.conf.json, the app accesses
843
+ * Tauri APIs through `window.__TAURI_INTERNALS__`. This module generates
844
+ * a script that mocks that global so the app runs in a plain browser.
845
+ *
846
+ * The mock intercepts:
847
+ * - `invoke()` calls — returns data from the mock handler map
848
+ * - `plugin:event|listen` — stores listeners for mock event emission
849
+ * - `plugin:event|unlisten` — no-ops
850
+ * - `convertFileSrc()` — passthrough
851
+ * - `transformCallback()` — creates callback IDs
852
+ */
853
+ /**
854
+ * Generate a JavaScript string to inject via `page.addInitScript()`.
855
+ * This sets up `window.__TAURI_INTERNALS__` with mock implementations.
856
+ *
857
+ * Mock handlers are serialized as functions so they receive the actual
858
+ * invoke args at call time. This supports dynamic responses like:
859
+ * ```ts
860
+ * greet: (args) => `Hello, ${args?.name}!`
861
+ * ```
862
+ */
863
+ declare function generateIpcMockScript(mocks: Record<string, (args?: Record<string, unknown>) => unknown>): string;
864
+ /**
865
+ * Type declarations for the mock globals injected into the page.
866
+ */
867
+ declare global {
868
+ interface Window {
869
+ __TAURI_MOCK_CALLS__: Array<{
870
+ cmd: string;
871
+ args: Record<string, unknown>;
872
+ timestamp: number;
873
+ }>;
874
+ __TAURI_MOCK_LISTENERS__: Record<string, string[]>;
875
+ __TAURI_EMIT_MOCK_EVENT__: (event: string, payload: unknown) => void;
876
+ __TAURI_GET_MOCK_CALLS__: () => Array<{
877
+ cmd: string;
878
+ args: Record<string, unknown>;
879
+ timestamp: number;
880
+ }>;
881
+ __TAURI_CLEAR_MOCK_CALLS__: () => void;
882
+ __TAURI_INTERNALS__: {
883
+ invoke: (cmd: string, args?: Record<string, unknown>) => Promise<unknown>;
884
+ convertFileSrc: (path: string) => string;
885
+ transformCallback: (callback: (response: unknown) => void) => string;
886
+ metadata: Record<string, unknown>;
887
+ };
888
+ }
889
+ }
890
+
891
+ /**
892
+ * Manages the lifecycle of a Tauri app process for E2E testing.
893
+ * Spawns the process, waits for the plugin socket to become ready,
894
+ * and handles cleanup.
895
+ */
896
+ declare class TauriProcessManager {
897
+ private config;
898
+ private process;
899
+ private socketPath;
900
+ private tcpPort;
901
+ constructor(config: ProcessConfig);
902
+ /**
903
+ * Start the Tauri app and wait for the plugin socket to become available.
904
+ * Returns the socket path or TCP port to connect to.
905
+ */
906
+ start(): Promise<{
907
+ socketPath?: string;
908
+ tcpPort?: number;
909
+ }>;
910
+ /**
911
+ * Also supports connecting to an already-running Tauri app.
912
+ * Just waits for the socket file to appear.
913
+ */
914
+ waitForSocket(timeoutMs?: number): Promise<void>;
915
+ /** Kill the Tauri process. */
916
+ stop(): void;
917
+ }
918
+ interface ProcessConfig {
919
+ /** Command to run. Default: 'cargo' */
920
+ command?: string;
921
+ /** Command args. Default: ['tauri', 'dev'] */
922
+ args?: string[];
923
+ /** Working directory */
924
+ cwd?: string;
925
+ /** Cargo features to enable */
926
+ features?: string[];
927
+ /** Socket path. Default: /tmp/tauri-playwright.sock */
928
+ socketPath?: string;
929
+ /** TCP port (Windows fallback) */
930
+ tcpPort?: number;
931
+ /** Startup timeout in seconds. Default: 120 */
932
+ startTimeout?: number;
933
+ }
934
+
935
+ export { BrowserPageAdapter, type CapturedInvoke, type LocatorLike, PluginClient, type PluginResponse, type ProcessConfig, type TauriFixtures, TauriKeyboard, TauriLocator, TauriMouse, TauriPage, TauriProcessManager, type TauriTestConfig, type TestMode, type TimeoutOption, clearCapturedInvokes, createTauriTest, emitMockEvent, generateIpcMockScript, getCapturedInvokes, tauriExpect };