@mobilewright/core 0.0.41 → 0.0.43

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.
Files changed (103) hide show
  1. package/dist/device.d.ts +7 -1
  2. package/dist/device.d.ts.map +1 -1
  3. package/dist/device.js +17 -2
  4. package/dist/device.js.map +1 -1
  5. package/dist/device.test.d.ts +2 -0
  6. package/dist/device.test.d.ts.map +1 -0
  7. package/dist/device.test.js +39 -0
  8. package/dist/device.test.js.map +1 -0
  9. package/dist/expect.d.ts +82 -11
  10. package/dist/expect.d.ts.map +1 -1
  11. package/dist/expect.js +181 -22
  12. package/dist/expect.js.map +1 -1
  13. package/dist/expect.test.js +17 -0
  14. package/dist/expect.test.js.map +1 -1
  15. package/dist/fake-webview-session.d.ts +14 -0
  16. package/dist/fake-webview-session.d.ts.map +1 -0
  17. package/dist/fake-webview-session.js +26 -0
  18. package/dist/fake-webview-session.js.map +1 -0
  19. package/dist/index.d.ts +4 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +3 -0
  22. package/dist/index.js.map +1 -1
  23. package/dist/locator.d.ts +26 -5
  24. package/dist/locator.d.ts.map +1 -1
  25. package/dist/locator.js +31 -10
  26. package/dist/locator.js.map +1 -1
  27. package/dist/locator.test.js +213 -0
  28. package/dist/locator.test.js.map +1 -1
  29. package/dist/page.d.ts +52 -0
  30. package/dist/page.d.ts.map +1 -0
  31. package/dist/page.js +226 -0
  32. package/dist/page.js.map +1 -0
  33. package/dist/page.test.d.ts +2 -0
  34. package/dist/page.test.d.ts.map +1 -0
  35. package/dist/page.test.js +263 -0
  36. package/dist/page.test.js.map +1 -0
  37. package/dist/playwright-engine.d.ts +23 -0
  38. package/dist/playwright-engine.d.ts.map +1 -0
  39. package/dist/playwright-engine.js +79 -0
  40. package/dist/playwright-engine.js.map +1 -0
  41. package/dist/playwright-engine.test.d.ts +2 -0
  42. package/dist/playwright-engine.test.d.ts.map +1 -0
  43. package/dist/playwright-engine.test.js +45 -0
  44. package/dist/playwright-engine.test.js.map +1 -0
  45. package/dist/query-engine.d.ts +19 -0
  46. package/dist/query-engine.d.ts.map +1 -1
  47. package/dist/query-engine.js +80 -0
  48. package/dist/query-engine.js.map +1 -1
  49. package/dist/query-engine.test.js +187 -1
  50. package/dist/query-engine.test.js.map +1 -1
  51. package/dist/screen.d.ts +11 -1
  52. package/dist/screen.d.ts.map +1 -1
  53. package/dist/screen.js +16 -0
  54. package/dist/screen.js.map +1 -1
  55. package/dist/screen.test.d.ts +2 -0
  56. package/dist/screen.test.d.ts.map +1 -0
  57. package/dist/screen.test.js +69 -0
  58. package/dist/screen.test.js.map +1 -0
  59. package/dist/stackTrace.d.ts +3 -0
  60. package/dist/stackTrace.d.ts.map +1 -1
  61. package/dist/stackTrace.js +10 -0
  62. package/dist/stackTrace.js.map +1 -1
  63. package/dist/stackTrace.test.d.ts +2 -0
  64. package/dist/stackTrace.test.d.ts.map +1 -0
  65. package/dist/stackTrace.test.js +43 -0
  66. package/dist/stackTrace.test.js.map +1 -0
  67. package/dist/web-expect-matcher.d.ts +29 -0
  68. package/dist/web-expect-matcher.d.ts.map +1 -0
  69. package/dist/web-expect-matcher.js +23 -0
  70. package/dist/web-expect-matcher.js.map +1 -0
  71. package/dist/web-expect-matcher.test.d.ts +2 -0
  72. package/dist/web-expect-matcher.test.d.ts.map +1 -0
  73. package/dist/web-expect-matcher.test.js +21 -0
  74. package/dist/web-expect-matcher.test.js.map +1 -0
  75. package/dist/web-expect.test.d.ts +2 -0
  76. package/dist/web-expect.test.d.ts.map +1 -0
  77. package/dist/web-expect.test.js +93 -0
  78. package/dist/web-expect.test.js.map +1 -0
  79. package/dist/web-locator-pwexpect.test.d.ts +2 -0
  80. package/dist/web-locator-pwexpect.test.d.ts.map +1 -0
  81. package/dist/web-locator-pwexpect.test.js +36 -0
  82. package/dist/web-locator-pwexpect.test.js.map +1 -0
  83. package/dist/web-locator-reinjection.test.d.ts +2 -0
  84. package/dist/web-locator-reinjection.test.d.ts.map +1 -0
  85. package/dist/web-locator-reinjection.test.js +83 -0
  86. package/dist/web-locator-reinjection.test.js.map +1 -0
  87. package/dist/web-locator.d.ts +120 -0
  88. package/dist/web-locator.d.ts.map +1 -0
  89. package/dist/web-locator.js +332 -0
  90. package/dist/web-locator.js.map +1 -0
  91. package/dist/web-locator.test.d.ts +2 -0
  92. package/dist/web-locator.test.d.ts.map +1 -0
  93. package/dist/web-locator.test.js +424 -0
  94. package/dist/web-locator.test.js.map +1 -0
  95. package/dist/webview-locator.d.ts +14 -0
  96. package/dist/webview-locator.d.ts.map +1 -0
  97. package/dist/webview-locator.js +95 -0
  98. package/dist/webview-locator.js.map +1 -0
  99. package/dist/webview-locator.test.d.ts +2 -0
  100. package/dist/webview-locator.test.d.ts.map +1 -0
  101. package/dist/webview-locator.test.js +203 -0
  102. package/dist/webview-locator.test.js.map +1 -0
  103. package/package.json +3 -2
package/dist/device.d.ts CHANGED
@@ -1,8 +1,12 @@
1
- import type { AppInfo, ConnectionConfig, LaunchOptions, MobilewrightDriver, Orientation, RecordingOptions, RecordingResult, Session } from '@mobilewright/protocol';
1
+ import type { AppInfo, ConnectionConfig, LaunchOptions, MobilewrightDriver, Orientation, RecordingOptions, RecordingResult, ScreenSize, Session } from '@mobilewright/protocol';
2
2
  import { Screen } from './screen.js';
3
3
  import type { LocatorOptions } from './locator.js';
4
4
  export interface DeviceOptions {
5
5
  locatorDefaults?: LocatorOptions;
6
+ /** Timeout waiting for app to reach foreground after launch, in ms. Default: 20000. */
7
+ appLaunchTimeout?: number;
8
+ /** Timeout for app installation in ms. Default: none (no limit). */
9
+ installTimeout?: number;
6
10
  }
7
11
  export declare class Device {
8
12
  readonly driver: MobilewrightDriver;
@@ -19,6 +23,8 @@ export declare class Device {
19
23
  get screen(): Screen;
20
24
  getOrientation(): Promise<Orientation>;
21
25
  setOrientation(orientation: Orientation): Promise<void>;
26
+ /** Screen dimensions and pixel density: { width, height, scale }. */
27
+ screenSize(): Promise<ScreenSize>;
22
28
  openUrl(url: string): Promise<void>;
23
29
  /** Alias for openUrl — matches Playwright's page.goto(). */
24
30
  goto(url: string): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../src/device.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,OAAO,EACP,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,OAAO,EACR,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAOnD,MAAM,WAAW,aAAa;IAC5B,eAAe,CAAC,EAAE,cAAc,CAAC;CAClC;AAED,qBAAa,MAAM;IACjB,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,OAAO,CAAC,gBAAgB,CAAkC;IAC1D,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;gBAEzB,MAAM,EAAE,kBAAkB,EAAE,IAAI,GAAE,aAAkB;IAKhE,4EAA4E;IAC5E,OAAO,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAMtC,OAAO,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;IAInD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC,uEAAuE;IACjE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ5B,IAAI,MAAM,IAAI,MAAM,CAGnB;IAIK,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC;IAItC,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvD,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzC,4DAA4D;IACtD,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMhC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BhE,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK7C,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAI9B,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC;IAIpC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM7C,cAAc,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrD,aAAa,IAAI,OAAO,CAAC,eAAe,CAAC;CAGhD"}
1
+ {"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../src/device.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,OAAO,EACP,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,OAAO,EACR,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAOnD,MAAM,WAAW,aAAa;IAC5B,eAAe,CAAC,EAAE,cAAc,CAAC;IACjC,uFAAuF;IACvF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oEAAoE;IACpE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAYD,qBAAa,MAAM;IACjB,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,OAAO,CAAC,gBAAgB,CAAkC;IAC1D,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;gBAEzB,MAAM,EAAE,kBAAkB,EAAE,IAAI,GAAE,aAAkB;IAKhE,4EAA4E;IAC5E,OAAO,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAMtC,OAAO,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;IAInD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC,uEAAuE;IACjE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ5B,IAAI,MAAM,IAAI,MAAM,CAGnB;IAIK,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC;IAItC,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7D,qEAAqE;IAC/D,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC;IAIjC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzC,4DAA4D;IACtD,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMhC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BhE,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK7C,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAI9B,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC;IAIpC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYvC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM7C,cAAc,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrD,aAAa,IAAI,OAAO,CAAC,eAAe,CAAC;CAGhD"}
package/dist/device.js CHANGED
@@ -3,6 +3,12 @@ import { Screen } from './screen.js';
3
3
  import { retryUntil } from './poll.js';
4
4
  const debug = createDebug('mw:device');
5
5
  const LAUNCH_APP_TIMEOUT = 20_000;
6
+ function raceWithTimeout(promise, ms, message) {
7
+ return new Promise((resolve, reject) => {
8
+ const timer = setTimeout(() => reject(new Error(message)), ms);
9
+ promise.then((value) => { clearTimeout(timer); resolve(value); }, (err) => { clearTimeout(timer); reject(err); });
10
+ });
11
+ }
6
12
  export class Device {
7
13
  constructor(driver, opts = {}) {
8
14
  this.cleanupCallbacks = [];
@@ -40,6 +46,10 @@ export class Device {
40
46
  async setOrientation(orientation) {
41
47
  return this.driver.setOrientation(orientation);
42
48
  }
49
+ /** Screen dimensions and pixel density: { width, height, scale }. */
50
+ async screenSize() {
51
+ return this.driver.getScreenSize();
52
+ }
43
53
  async openUrl(url) {
44
54
  return this.driver.openUrl(url);
45
55
  }
@@ -53,9 +63,10 @@ export class Device {
53
63
  if (opts?.noWaitAfter) {
54
64
  return;
55
65
  }
66
+ const timeout = this.opts.appLaunchTimeout ?? LAUNCH_APP_TIMEOUT;
56
67
  debug('waiting for %s to reach foreground', bundleId);
57
68
  try {
58
- await retryUntil(() => this.getForegroundApp(), (app) => app.bundleId === bundleId, LAUNCH_APP_TIMEOUT, `launchApp: timed out waiting for "${bundleId}" to be in foreground`);
69
+ await retryUntil(() => this.getForegroundApp(), (app) => app.bundleId === bundleId, timeout, `launchApp: timed out waiting for "${bundleId}" to be in foreground`);
59
70
  debug('%s is in foreground', bundleId);
60
71
  }
61
72
  catch (err) {
@@ -80,7 +91,11 @@ export class Device {
80
91
  return this.driver.getForegroundApp();
81
92
  }
82
93
  async installApp(path) {
83
- return this.driver.installApp(path);
94
+ const { installTimeout } = this.opts;
95
+ if (installTimeout === undefined) {
96
+ return this.driver.installApp(path);
97
+ }
98
+ return raceWithTimeout(this.driver.installApp(path), installTimeout, `installApp timed out after ${installTimeout}ms`);
84
99
  }
85
100
  async uninstallApp(bundleId) {
86
101
  return this.driver.uninstallApp(bundleId);
@@ -1 +1 @@
1
- {"version":3,"file":"device.js","sourceRoot":"","sources":["../src/device.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"device.js","sourceRoot":"","sources":["../src/device.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=device.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device.test.d.ts","sourceRoot":"","sources":["../src/device.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,39 @@
1
+ import { test, expect } from '@playwright/test';
2
+ import { Device } from './device.js';
3
+ function createMockDriver(screenSize) {
4
+ return {
5
+ connect: async () => ({ deviceId: 'device1', platform: 'ios' }),
6
+ disconnect: async () => { },
7
+ getViewHierarchy: async () => [],
8
+ tap: async () => { },
9
+ doubleTap: async () => { },
10
+ longPress: async () => { },
11
+ typeText: async () => { },
12
+ swipe: async () => { },
13
+ gesture: async () => { },
14
+ pressButton: async () => { },
15
+ screenshot: async () => Buffer.from(''),
16
+ getScreenSize: async () => screenSize,
17
+ getOrientation: async () => 'portrait',
18
+ setOrientation: async () => { },
19
+ launchApp: async () => { },
20
+ terminateApp: async () => { },
21
+ listApps: async () => [],
22
+ getForegroundApp: async () => ({ bundleId: 'com.test' }),
23
+ installApp: async () => { },
24
+ uninstallApp: async () => { },
25
+ listDevices: async () => [],
26
+ openUrl: async () => { },
27
+ startRecording: async () => { },
28
+ stopRecording: async () => ({}),
29
+ };
30
+ }
31
+ test.describe('Device.screenSize', () => {
32
+ test('returns the width, height, and scale from the driver', async () => {
33
+ const driver = createMockDriver({ width: 390, height: 844, scale: 3 });
34
+ const device = new Device(driver);
35
+ const size = await device.screenSize();
36
+ expect(size).toEqual({ width: 390, height: 844, scale: 3 });
37
+ });
38
+ });
39
+ //# sourceMappingURL=device.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device.test.js","sourceRoot":"","sources":["../src/device.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAQhD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,SAAS,gBAAgB,CAAC,UAAsB;IAC9C,OAAO;QACL,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAc,EAAE,CAAC;QACxE,UAAU,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;QAC1B,gBAAgB,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE;QAChC,GAAG,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;QACnB,SAAS,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;QACzB,SAAS,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;QACzB,QAAQ,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;QACxB,KAAK,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;QACrB,OAAO,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;QACvB,WAAW,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;QAC3B,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,aAAa,EAAE,KAAK,IAAI,EAAE,CAAC,UAAU;QACrC,cAAc,EAAE,KAAK,IAAI,EAAE,CAAC,UAAyB;QACrD,cAAc,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;QAC9B,SAAS,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;QACzB,YAAY,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;QAC5B,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,EAAe;QACrC,gBAAgB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;QACxD,UAAU,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;QAC1B,YAAY,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;QAC5B,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC,EAAkB;QAC3C,OAAO,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;QACvB,cAAc,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;QAC9B,aAAa,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;KAChC,CAAC;AACJ,CAAC;AAED,IAAI,CAAC,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACtC,IAAI,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,MAAM,GAAG,gBAAgB,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACvE,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC;QAElC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;QAEvC,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/dist/expect.d.ts CHANGED
@@ -1,24 +1,55 @@
1
- import type { Locator } from './locator.js';
1
+ import type { Locator, StepFn } from './locator.js';
2
+ import { Page } from './page.js';
3
+ import { WebLocator } from './web-locator.js';
2
4
  export interface ExpectOptions {
3
5
  timeout?: number;
4
6
  }
5
7
  /**
6
- * Playwright-style expect for mobile locators and plain values.
8
+ * Playwright-style expect for mobile locators, web locators, pages, and plain values.
7
9
  *
8
10
  * Usage:
9
11
  * expect(locator).toBeVisible()
10
- * expect(locator).not.toBeVisible()
11
- * expect(locator).toHaveText('Hello')
12
+ * expect(page).toHaveURL(/dashboard/)
13
+ * expect(webLocator).toHaveText('Hello')
12
14
  * expect(42).toBe(42)
13
15
  */
16
+ export declare function expect(actual: Page): PageAssertions;
17
+ export declare function expect(actual: WebLocator): WebLocatorAssertions;
14
18
  export declare function expect(actual: Locator): LocatorAssertions;
15
19
  export declare function expect<T>(actual: T): ValueAssertions<T>;
20
+ interface LocatorLike {
21
+ isVisible(opts?: {
22
+ timeout?: number;
23
+ }): Promise<boolean>;
24
+ isEnabled(opts?: {
25
+ timeout?: number;
26
+ }): Promise<boolean>;
27
+ isChecked(opts?: {
28
+ timeout?: number;
29
+ }): Promise<boolean>;
30
+ isSelected?(opts?: {
31
+ timeout?: number;
32
+ }): Promise<boolean>;
33
+ isFocused?(opts?: {
34
+ timeout?: number;
35
+ }): Promise<boolean>;
36
+ getText(opts?: {
37
+ timeout?: number;
38
+ }): Promise<string>;
39
+ getValue(opts?: {
40
+ timeout?: number;
41
+ }): Promise<string>;
42
+ count(): Promise<number>;
43
+ expectTimeout?: number;
44
+ _stepFn?: StepFn | null;
45
+ }
16
46
  declare class LocatorAssertions {
17
- private readonly locator;
18
- private readonly negated;
19
- constructor(locator: Locator, negated: boolean);
47
+ protected readonly locator: LocatorLike;
48
+ protected readonly negated: boolean;
49
+ constructor(locator: LocatorLike, negated: boolean);
20
50
  get not(): LocatorAssertions;
21
- private _wrapAssertion;
51
+ private assertionTimeout;
52
+ protected _wrapAssertion<T>(method: string, fn: () => Promise<T>): Promise<T>;
22
53
  toBeVisible(opts?: ExpectOptions): Promise<void>;
23
54
  toBeHidden(opts?: ExpectOptions): Promise<void>;
24
55
  toBeEnabled(opts?: ExpectOptions): Promise<void>;
@@ -31,9 +62,9 @@ declare class LocatorAssertions {
31
62
  toHaveCount(expected: number, opts?: ExpectOptions): Promise<void>;
32
63
  toBeEmpty(opts?: ExpectOptions): Promise<void>;
33
64
  toHaveValue(expected: string | RegExp, opts?: ExpectOptions): Promise<void>;
34
- private assertBoolean;
35
- private assertText;
36
- private retryAssertion;
65
+ protected assertBoolean(name: string, poll: () => Promise<boolean>, opts?: ExpectOptions): Promise<void>;
66
+ protected assertText(predicate: (text: string) => boolean, expected: string | RegExp, opts?: ExpectOptions): Promise<void>;
67
+ protected retryAssertion<T>(poll: () => Promise<T>, predicate: (value: T) => boolean, timeout: number, failMessage: string | (() => string)): Promise<void>;
37
68
  }
38
69
  declare class ValueAssertions<T> {
39
70
  private readonly actual;
@@ -64,6 +95,46 @@ declare class ValueAssertions<T> {
64
95
  toThrow(expected?: string | RegExp): void;
65
96
  private assert;
66
97
  }
98
+ declare class PageAssertions {
99
+ private readonly page;
100
+ private readonly negated;
101
+ constructor(page: Page, negated: boolean);
102
+ get not(): PageAssertions;
103
+ private _wrapAssertion;
104
+ private matches;
105
+ toHaveURL(url: string | RegExp, opts?: ExpectOptions): Promise<void>;
106
+ toHaveTitle(title: string | RegExp, opts?: ExpectOptions): Promise<void>;
107
+ }
108
+ declare class WebLocatorAssertions {
109
+ private readonly webLocator;
110
+ private readonly negated;
111
+ constructor(webLocator: WebLocator, negated: boolean);
112
+ get not(): WebLocatorAssertions;
113
+ private assertionTimeout;
114
+ private runMatcher;
115
+ toBeVisible(opts?: ExpectOptions): Promise<void>;
116
+ toBeHidden(opts?: ExpectOptions): Promise<void>;
117
+ toBeEnabled(opts?: ExpectOptions): Promise<void>;
118
+ toBeDisabled(opts?: ExpectOptions): Promise<void>;
119
+ toBeEditable(opts?: ExpectOptions): Promise<void>;
120
+ toBeFocused(opts?: ExpectOptions): Promise<void>;
121
+ toBeAttached(opts?: ExpectOptions): Promise<void>;
122
+ toBeInViewport(opts?: ExpectOptions & {
123
+ ratio?: number;
124
+ }): Promise<void>;
125
+ toBeChecked(opts?: ExpectOptions): Promise<void>;
126
+ toBeEmpty(opts?: ExpectOptions): Promise<void>;
127
+ toHaveText(expected: string | RegExp, opts?: ExpectOptions): Promise<void>;
128
+ toContainText(expected: string | RegExp, opts?: ExpectOptions): Promise<void>;
129
+ toHaveValue(expected: string | RegExp, opts?: ExpectOptions): Promise<void>;
130
+ toHaveCount(expected: number, opts?: ExpectOptions): Promise<void>;
131
+ toHaveAttribute(name: string, expected: string | RegExp, opts?: ExpectOptions): Promise<void>;
132
+ toHaveClass(expected: string | RegExp, opts?: ExpectOptions): Promise<void>;
133
+ toContainClass(expected: string | RegExp, opts?: ExpectOptions): Promise<void>;
134
+ toHaveCSS(name: string, expected: string | RegExp, opts?: ExpectOptions): Promise<void>;
135
+ toHaveId(expected: string | RegExp, opts?: ExpectOptions): Promise<void>;
136
+ toHaveJSProperty(name: string, expected: unknown, opts?: ExpectOptions): Promise<void>;
137
+ }
67
138
  export declare class ExpectError extends Error {
68
139
  constructor(message: string);
69
140
  }
@@ -1 +1 @@
1
- {"version":3,"file":"expect.d.ts","sourceRoot":"","sources":["../src/expect.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"expect.d.ts","sourceRoot":"","sources":["../src/expect.ts"],"names":[],"mappings":"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"}
package/dist/expect.js CHANGED
@@ -1,13 +1,38 @@
1
1
  import { LocatorError } from './locator.js';
2
+ import { Page } from './page.js';
3
+ import { WebLocator } from './web-locator.js';
2
4
  import { retryUntil } from './poll.js';
3
- import { filterStack, captureLocation } from './stackTrace.js';
5
+ import { filterStack, runStep } from './stackTrace.js';
6
+ import { textValue } from './web-expect-matcher.js';
4
7
  const DEFAULT_TIMEOUT = 5_000;
5
8
  export function expect(actual) {
9
+ if (actual instanceof Page) {
10
+ return new PageAssertions(actual, false);
11
+ }
12
+ if (actual instanceof WebLocator) {
13
+ return new WebLocatorAssertions(actual, false);
14
+ }
6
15
  if (actual && typeof actual === 'object' && 'tap' in actual && 'getText' in actual) {
7
16
  return new LocatorAssertions(actual, false);
8
17
  }
9
18
  return new ValueAssertions(actual, false);
10
19
  }
20
+ // Wrap an assertion body as a reporter step titled after the matcher, shared by
21
+ // all assertion classes so the title/negation convention lives in one place.
22
+ function wrapAssertion(stepFn, negated, method, fn) {
23
+ const title = negated ? `expect.not.${method}()` : `expect.${method}()`;
24
+ return runStep(stepFn, title, fn);
25
+ }
26
+ // Poll until `predicate` holds (or the timeout elapses), re-raising any failure
27
+ // as an ExpectError. The predicate must already account for negation.
28
+ async function retryAssertion(poll, predicate, timeout, failMessage) {
29
+ try {
30
+ await retryUntil(poll, predicate, timeout, failMessage);
31
+ }
32
+ catch (e) {
33
+ throw new ExpectError(e instanceof Error ? e.message : String(e));
34
+ }
35
+ }
11
36
  class LocatorAssertions {
12
37
  constructor(locator, negated) {
13
38
  this.locator = locator;
@@ -16,14 +41,11 @@ class LocatorAssertions {
16
41
  get not() {
17
42
  return new LocatorAssertions(this.locator, !this.negated);
18
43
  }
44
+ assertionTimeout(opts) {
45
+ return opts?.timeout ?? this.locator.expectTimeout ?? DEFAULT_TIMEOUT;
46
+ }
19
47
  _wrapAssertion(method, fn) {
20
- const stepFn = this.locator._stepFn;
21
- const title = this.negated ? `expect.not.${method}()` : `expect.${method}()`;
22
- if (stepFn) {
23
- const location = captureLocation();
24
- return stepFn(title, fn, location);
25
- }
26
- return fn();
48
+ return wrapAssertion(this.locator._stepFn, this.negated, method, fn);
27
49
  }
28
50
  async toBeVisible(opts) {
29
51
  return this._wrapAssertion('toBeVisible', async () => {
@@ -53,12 +75,20 @@ class LocatorAssertions {
53
75
  }
54
76
  async toBeSelected(opts) {
55
77
  return this._wrapAssertion('toBeSelected', async () => {
56
- await this.assertBoolean('selected', () => this.locator.isSelected({ timeout: 0 }), opts);
78
+ const isSelected = this.locator.isSelected?.bind(this.locator);
79
+ if (!isSelected) {
80
+ throw new ExpectError('toBeSelected() is not supported for this locator');
81
+ }
82
+ await this.assertBoolean('selected', () => isSelected({ timeout: 0 }), opts);
57
83
  });
58
84
  }
59
85
  async toBeFocused(opts) {
60
86
  return this._wrapAssertion('toBeFocused', async () => {
61
- await this.assertBoolean('focused', () => this.locator.isFocused({ timeout: 0 }), opts);
87
+ const isFocused = this.locator.isFocused?.bind(this.locator);
88
+ if (!isFocused) {
89
+ throw new ExpectError('toBeFocused() is not supported for this locator');
90
+ }
91
+ await this.assertBoolean('focused', () => isFocused({ timeout: 0 }), opts);
62
92
  });
63
93
  }
64
94
  async toBeChecked(opts) {
@@ -82,7 +112,7 @@ class LocatorAssertions {
82
112
  await this.retryAssertion(async () => { lastCount = await this.locator.count(); return lastCount; }, (count) => {
83
113
  const matches = count === expected;
84
114
  return this.negated ? !matches : matches;
85
- }, opts?.timeout ?? DEFAULT_TIMEOUT, () => this.negated
115
+ }, this.assertionTimeout(opts), () => this.negated
86
116
  ? `Expected element count NOT to be ${expected}, but got ${lastCount}`
87
117
  : `Expected element count to be ${expected}, but got ${lastCount}`);
88
118
  });
@@ -107,7 +137,7 @@ class LocatorAssertions {
107
137
  }
108
138
  const isEmpty = value === '';
109
139
  return this.negated ? !isEmpty : isEmpty;
110
- }, opts?.timeout ?? DEFAULT_TIMEOUT, () => this.negated
140
+ }, this.assertionTimeout(opts), () => this.negated
111
141
  ? 'Expected element NOT to be empty, but it was'
112
142
  : `Expected element to be empty, but got "${lastValue}"`);
113
143
  });
@@ -132,13 +162,13 @@ class LocatorAssertions {
132
162
  }
133
163
  const matches = expected instanceof RegExp ? expected.test(value) : value === expected;
134
164
  return this.negated ? !matches : matches;
135
- }, opts?.timeout ?? DEFAULT_TIMEOUT, () => this.negated
165
+ }, this.assertionTimeout(opts), () => this.negated
136
166
  ? `Expected element NOT to have value "${expected}", but got "${lastValue}"`
137
167
  : `Expected element to have value "${expected}", but got "${lastValue}"`);
138
168
  });
139
169
  }
140
170
  async assertBoolean(name, poll, opts) {
141
- await this.retryAssertion(poll, (result) => (this.negated ? !result : result), opts?.timeout ?? DEFAULT_TIMEOUT, this.negated
171
+ await this.retryAssertion(poll, (result) => (this.negated ? !result : result), this.assertionTimeout(opts), this.negated
142
172
  ? `Expected element to NOT be ${name}, but it was`
143
173
  : `Expected element to be ${name}, but it was not`);
144
174
  }
@@ -161,17 +191,12 @@ class LocatorAssertions {
161
191
  }
162
192
  const matches = predicate(text);
163
193
  return this.negated ? !matches : matches;
164
- }, opts?.timeout ?? DEFAULT_TIMEOUT, () => this.negated
194
+ }, this.assertionTimeout(opts), () => this.negated
165
195
  ? `Expected element NOT to have text "${expected}", but got "${lastText}"`
166
196
  : `Expected element to have text "${expected}", but got "${lastText}"`);
167
197
  }
168
- async retryAssertion(poll, predicate, timeout, failMessage) {
169
- try {
170
- await retryUntil(poll, predicate, timeout, failMessage);
171
- }
172
- catch (e) {
173
- throw new ExpectError(e instanceof Error ? e.message : String(e));
174
- }
198
+ retryAssertion(poll, predicate, timeout, failMessage) {
199
+ return retryAssertion(poll, predicate, timeout, failMessage);
175
200
  }
176
201
  }
177
202
  class ValueAssertions {
@@ -297,6 +322,140 @@ class ValueAssertions {
297
322
  }
298
323
  }
299
324
  }
325
+ // ─── PageAssertions ───────────────────────────────────────────
326
+ class PageAssertions {
327
+ constructor(page, negated) {
328
+ this.page = page;
329
+ this.negated = negated;
330
+ }
331
+ get not() {
332
+ return new PageAssertions(this.page, !this.negated);
333
+ }
334
+ _wrapAssertion(method, fn) {
335
+ return wrapAssertion(this.page._stepFn, this.negated, method, fn);
336
+ }
337
+ // Applies negation so callers pass the plain "does it match?" predicate.
338
+ matches(pass) {
339
+ return this.negated ? !pass : pass;
340
+ }
341
+ async toHaveURL(url, opts) {
342
+ return this._wrapAssertion('toHaveURL', async () => {
343
+ let last = '';
344
+ await retryAssertion(async () => { try {
345
+ last = await this.page.url();
346
+ }
347
+ catch {
348
+ last = '';
349
+ } return last; }, (current) => this.matches(url instanceof RegExp ? url.test(current) : current === url), opts?.timeout ?? DEFAULT_TIMEOUT, () => `Expected page URL to ${this.negated ? 'not ' : ''}match "${url}", but got "${last}"`);
350
+ });
351
+ }
352
+ async toHaveTitle(title, opts) {
353
+ return this._wrapAssertion('toHaveTitle', async () => {
354
+ let last = '';
355
+ await retryAssertion(async () => { try {
356
+ last = await this.page.title();
357
+ }
358
+ catch {
359
+ last = '';
360
+ } return last; }, (current) => this.matches(title instanceof RegExp ? title.test(current) : current === title), opts?.timeout ?? DEFAULT_TIMEOUT, () => `Expected page title to ${this.negated ? 'not ' : ''}match "${title}", but got "${last}"`);
361
+ });
362
+ }
363
+ }
364
+ // ─── WebLocatorAssertions ─────────────────────────────────────
365
+ // Standalone: every web matcher routes through Playwright's injected expect()
366
+ // (window.__mwInjected.expect) for byte-exact matcher semantics. Native
367
+ // LocatorAssertions and PageAssertions are unaffected.
368
+ class WebLocatorAssertions {
369
+ constructor(webLocator, negated) {
370
+ this.webLocator = webLocator;
371
+ this.negated = negated;
372
+ }
373
+ get not() {
374
+ return new WebLocatorAssertions(this.webLocator, !this.negated);
375
+ }
376
+ assertionTimeout(opts) {
377
+ return opts?.timeout ?? this.webLocator.expectTimeout ?? DEFAULT_TIMEOUT;
378
+ }
379
+ // Poll the injected matcher until matches !== isNot, or throw ExpectError.
380
+ runMatcher(method, params, opts) {
381
+ return wrapAssertion(this.webLocator._stepFn, this.negated, method, async () => {
382
+ const isNot = this.negated;
383
+ let received;
384
+ let missingReceived = false;
385
+ await retryAssertion(async () => {
386
+ const result = await this.webLocator._runInjectedExpect({ ...params, isNot, timeout: 0 });
387
+ received = result.received;
388
+ missingReceived = result.missingReceived ?? false;
389
+ return result.matches;
390
+ }, (matches) => matches !== isNot, this.assertionTimeout(opts), () => {
391
+ const got = missingReceived ? 'no element' : fmt(received);
392
+ return isNot
393
+ ? `Expected ${method} NOT to match, but it did (received ${got})`
394
+ : `Expected ${method} to match, but it did not (received ${got})`;
395
+ });
396
+ });
397
+ }
398
+ toBeVisible(opts) {
399
+ return this.runMatcher('toBeVisible', { expression: 'to.be.visible' }, opts);
400
+ }
401
+ toBeHidden(opts) {
402
+ return this.runMatcher('toBeHidden', { expression: 'to.be.hidden' }, opts);
403
+ }
404
+ toBeEnabled(opts) {
405
+ return this.runMatcher('toBeEnabled', { expression: 'to.be.enabled' }, opts);
406
+ }
407
+ toBeDisabled(opts) {
408
+ return this.runMatcher('toBeDisabled', { expression: 'to.be.disabled' }, opts);
409
+ }
410
+ toBeEditable(opts) {
411
+ return this.runMatcher('toBeEditable', { expression: 'to.be.editable' }, opts);
412
+ }
413
+ toBeFocused(opts) {
414
+ return this.runMatcher('toBeFocused', { expression: 'to.be.focused' }, opts);
415
+ }
416
+ toBeAttached(opts) {
417
+ return this.runMatcher('toBeAttached', { expression: 'to.be.attached' }, opts);
418
+ }
419
+ toBeInViewport(opts) {
420
+ return this.runMatcher('toBeInViewport', { expression: 'to.be.in.viewport', expectedNumber: opts?.ratio }, opts);
421
+ }
422
+ toBeChecked(opts) {
423
+ return this.runMatcher('toBeChecked', { expression: 'to.be.checked', expectedValue: { checked: true, indeterminate: false } }, opts);
424
+ }
425
+ toBeEmpty(opts) {
426
+ return this.runMatcher('toBeEmpty', { expression: 'to.be.empty' }, opts);
427
+ }
428
+ toHaveText(expected, opts) {
429
+ return this.runMatcher('toHaveText', { expression: 'to.have.text', expectedText: [textValue(expected, { normalizeWhiteSpace: true })] }, opts);
430
+ }
431
+ toContainText(expected, opts) {
432
+ return this.runMatcher('toContainText', { expression: 'to.have.text', expectedText: [textValue(expected, { normalizeWhiteSpace: true, matchSubstring: true })] }, opts);
433
+ }
434
+ toHaveValue(expected, opts) {
435
+ return this.runMatcher('toHaveValue', { expression: 'to.have.value', expectedText: [textValue(expected)] }, opts);
436
+ }
437
+ toHaveCount(expected, opts) {
438
+ return this.runMatcher('toHaveCount', { expression: 'to.have.count', expectedNumber: expected }, opts);
439
+ }
440
+ toHaveAttribute(name, expected, opts) {
441
+ return this.runMatcher('toHaveAttribute', { expression: 'to.have.attribute.value', expressionArg: name, expectedText: [textValue(expected)] }, opts);
442
+ }
443
+ toHaveClass(expected, opts) {
444
+ return this.runMatcher('toHaveClass', { expression: 'to.have.class', expectedText: [textValue(expected)] }, opts);
445
+ }
446
+ toContainClass(expected, opts) {
447
+ return this.runMatcher('toContainClass', { expression: 'to.contain.class', expectedText: [textValue(expected)] }, opts);
448
+ }
449
+ toHaveCSS(name, expected, opts) {
450
+ return this.runMatcher('toHaveCSS', { expression: 'to.have.css', expressionArg: name, expectedText: [textValue(expected)] }, opts);
451
+ }
452
+ toHaveId(expected, opts) {
453
+ return this.runMatcher('toHaveId', { expression: 'to.have.id', expectedText: [textValue(expected)] }, opts);
454
+ }
455
+ toHaveJSProperty(name, expected, opts) {
456
+ return this.runMatcher('toHaveJSProperty', { expression: 'to.have.property', expressionArg: name, expectedValue: expected }, opts);
457
+ }
458
+ }
300
459
  function fmt(value) {
301
460
  return typeof value === 'string' ? `"${value}"` : String(value);
302
461
  }