ohos-playwright 0.3.5 → 0.4.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.
@@ -31,11 +31,6 @@ export declare function installPageWrappers(page: Page, context: BrowserContext,
31
31
  export declare const test: import("@playwright/test").TestType<import("@playwright/test").PlaywrightTestArgs & import("@playwright/test").PlaywrightTestOptions & {
32
32
  emulateDevice: (descriptor: DeviceDescriptor) => Promise<void>;
33
33
  tap: (x: number, y: number) => Promise<void>;
34
- mouseMove: (x: number, y: number, opts?: {
35
- steps?: number;
36
- }) => Promise<void>;
37
- mouseDown: (x: number, y: number) => Promise<void>;
38
- mouseUp: (x: number, y: number) => Promise<void>;
39
34
  saveStorageState: (origin?: string) => Promise<StorageState>;
40
35
  loadStorageState: (state: StorageState) => Promise<void>;
41
36
  emulateLocale: (locale: string) => Promise<void>;
package/dist/fixture.mjs CHANGED
@@ -18,14 +18,6 @@ function readInfo() {
18
18
  function readEndpoint() { return readInfo().endpoint; }
19
19
  export async function installPageWrappers(page, context, baseURL) {
20
20
  const ctxEmit = context.emit.bind(context);
21
- // Patch baseURL — save and restore to prevent wrapper accumulation across
22
- // tests that share the same page object.
23
- const savedGoto = page['goto'];
24
- if (baseURL) {
25
- const root = baseURL.replace(/\/+$/, '');
26
- const origGoto = page.goto.bind(page);
27
- page.goto = ((url, opts) => origGoto((url.startsWith('/') && !url.startsWith('//')) ? root + url : url, opts));
28
- }
29
21
  // connectOverCDP reuses an existing tab — Playwright has no record of its
30
22
  // viewport size and viewportSize() returns null. Pre-fetch via CDP.
31
23
  const session = await context.newCDPSession(page);
@@ -42,18 +34,6 @@ export async function installPageWrappers(page, context, baseURL) {
42
34
  catch {
43
35
  // Non-critical — viewportSize() will still return null if CDP call fails.
44
36
  }
45
- // Bring the tab to foreground so Input.dispatchMouseEvent reaches DOM listeners.
46
- // page.mouse.move/down/up events are silently dropped when the tab is not active.
47
- try {
48
- const targets = await session.send('Target.getTargets');
49
- const pageTarget = targets.targetInfos.find((t) => t.type === 'page' && t.url === page.url());
50
- if (pageTarget) {
51
- await session.send('Target.activateTarget', { targetId: pageTarget.targetId });
52
- }
53
- }
54
- catch {
55
- // Non-fatal: some ArkWeb versions may not support Target.activateTarget.
56
- }
57
37
  }
58
38
  finally {
59
39
  await session.detach();
@@ -110,39 +90,19 @@ export async function installPageWrappers(page, context, baseURL) {
110
90
  }
111
91
  return null;
112
92
  };
113
- // Override locator().hover() to bypass Playwright's internal visibility check
114
- // (which can hang on ArkWeb), but still go through the real Input.dispatchMouseEvent
115
- // path so the pointer position is set and CSS :hover activates. The earlier
116
- // JS-dispatch workaround was disproved by the 2026-06-27 reaudit ab-hover-css
117
- // shows the native path delivers both DOM events and :hover activation.
93
+ // Override locator().hover() to use page.mouse.move() directly so CSS :hover
94
+ // activates. Playwright's built-in hover() goes through a visibility check path
95
+ // that can hang on ArkWeb; bypassing it is safe because mouse.move() has been
96
+ // verified to deliver both DOM events and :hover activation (ab-hover-css probe).
118
97
  const savedLocator = page['locator'];
119
98
  const origLocator = page.locator.bind(page);
120
99
  page.locator = (...args) => {
121
100
  const loc = origLocator(...args);
122
101
  loc.hover = async (_options) => {
123
- // Try the real Input.dispatchMouseEvent path first (activates :hover).
124
- // Some pages (e.g. ones with MutationObservers that re-enter layout) can
125
- // make Playwright's evaluate/boundingBox hang on ArkWeb; fall back to a
126
- // JS-only dispatch with a tight timeout so hover() at least returns and
127
- // DOM listeners fire.
128
- const viaRealMouse = await Promise.race([
129
- (async () => {
130
- const box = await loc.boundingBox();
131
- if (!box)
132
- return false;
133
- await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2);
134
- return true;
135
- })(),
136
- new Promise(r => setTimeout(() => r(false), 5000)),
137
- ]);
138
- if (!viaRealMouse) {
139
- await Promise.race([
140
- loc.evaluate((el) => {
141
- el.dispatchEvent(new MouseEvent('mouseover', { bubbles: true, cancelable: true }));
142
- }),
143
- new Promise(r => setTimeout(r, 2000)),
144
- ]).catch(() => { });
145
- }
102
+ const box = await loc.boundingBox();
103
+ if (!box)
104
+ return;
105
+ await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2);
146
106
  };
147
107
  return loc;
148
108
  };
@@ -206,15 +166,13 @@ export async function installPageWrappers(page, context, baseURL) {
206
166
  page.evaluate = savedEvaluate;
207
167
  page.locator = savedLocator;
208
168
  if (opts?.navigateTo) {
209
- // Reset the shared tab before restoring gotokeeps the connection alive.
210
- // page.close() would terminate the ArkWeb DevTools socket.
169
+ // Reset the shared tab to a neutral state page.close() would terminate
170
+ // the ArkWeb DevTools socket so we navigate instead.
211
171
  try {
212
172
  await page.goto(opts.navigateTo);
213
173
  }
214
174
  catch { }
215
175
  }
216
- ;
217
- page.goto = savedGoto;
218
176
  };
219
177
  }
220
178
  export const test = base.extend({
@@ -342,45 +300,6 @@ export const test = base.extend({
342
300
  }
343
301
  });
344
302
  },
345
- mouseMove: async ({ page }, use) => {
346
- // ArkWeb CDP limitation: events dispatched via locator.evaluate() only reach
347
- // page-script listeners if the listener body contains no closure references and
348
- // the element has only a single addEventListener call. Any script complexity
349
- // (outer variable declarations, multiple listeners) causes ArkWeb to route the
350
- // callback into an isolated CDP execution context where closures are inaccessible,
351
- // silently suppressing the event. For typical web applications this fixture
352
- // will not deliver events. Prefer locator.click() / locator.fill() where possible.
353
- await use(async (x, y, opts) => {
354
- const steps = Math.max(1, opts?.steps ?? 1);
355
- for (let i = 0; i < steps; i++) {
356
- await page.locator(':root').evaluate((root, [x, y]) => {
357
- const el = root.ownerDocument.elementFromPoint(x, y);
358
- if (el)
359
- el.dispatchEvent(new MouseEvent('mousemove', { bubbles: true, cancelable: true, clientX: x, clientY: y }));
360
- }, [x, y]);
361
- }
362
- });
363
- },
364
- mouseDown: async ({ page }, use) => {
365
- await use(async (x, y) => {
366
- await page.locator(':root').evaluate((root, [x, y]) => {
367
- const el = root.ownerDocument.elementFromPoint(x, y);
368
- if (el)
369
- el.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, cancelable: true, clientX: x, clientY: y, button: 0, buttons: 1 }));
370
- }, [x, y]);
371
- });
372
- },
373
- mouseUp: async ({ page }, use) => {
374
- await use(async (x, y) => {
375
- await page.locator(':root').evaluate((root, [x, y]) => {
376
- const el = root.ownerDocument.elementFromPoint(x, y);
377
- if (el) {
378
- el.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, cancelable: true, clientX: x, clientY: y, button: 0 }));
379
- el.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, clientX: x, clientY: y, button: 0 }));
380
- }
381
- }, [x, y]);
382
- });
383
- },
384
303
  saveStorageState: async ({ page, context }, use) => {
385
304
  await use(async (origin) => {
386
305
  const derivedOrigin = origin ?? new URL(page.url()).origin;
@@ -2,11 +2,6 @@ import type { BrowserContext, Page } from '@playwright/test';
2
2
  export declare const test: import("@playwright/test").TestType<import("@playwright/test").PlaywrightTestArgs & import("@playwright/test").PlaywrightTestOptions & {
3
3
  emulateDevice: (descriptor: import("./fixture.mts").DeviceDescriptor) => Promise<void>;
4
4
  tap: (x: number, y: number) => Promise<void>;
5
- mouseMove: (x: number, y: number, opts?: {
6
- steps?: number;
7
- }) => Promise<void>;
8
- mouseDown: (x: number, y: number) => Promise<void>;
9
- mouseUp: (x: number, y: number) => Promise<void>;
10
5
  saveStorageState: (origin?: string) => Promise<import("./fixture.mts").StorageState>;
11
6
  loadStorageState: (state: import("./fixture.mts").StorageState) => Promise<void>;
12
7
  emulateLocale: (locale: string) => Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ohos-playwright",
3
- "version": "0.3.5",
3
+ "version": "0.4.0",
4
4
  "description": "Playwright adapter for OpenHarmony / ArkWeb via hdc + CDP",
5
5
  "license": "MIT",
6
6
  "author": "social4hyq",