ohos-playwright 0.5.1 → 0.5.2

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 CHANGED
@@ -56,7 +56,7 @@ The following Playwright APIs have been validated on ArkWeb / HarmonyOS 6.1 (Chr
56
56
  | File upload | `page.setInputFiles()` — fires `change`, file content readable |
57
57
  | Cookies | `context.addCookies()`, `context.cookies()`, `context.clearCookies()` |
58
58
  | Dialog | `page.on('dialog')`, `dialog.accept()`, `dialog.dismiss()`, `dialog.message()`, `dialog.type()` |
59
- | Popup | `context.waitForEvent('page')` + `window.open()` — stub Page with `url()`, `waitForLoadState()`, `close()` |
59
+ | Popup | `context.waitForEvent('page')` + `window.open()` — real Page with full API. Requires `PW_CHROMIUM_ATTACH_TO_OTHER=1`. Falls back to idle-tab proxy or minimal stub when Target.createTarget is unavailable. |
60
60
  | Page events | `page.on('pageerror')`, `page.on('console')`, `page.on('download')` |
61
61
  | Script / style injection | `page.addScriptTag({ content \| path \| type:'module' })`, `page.addStyleTag({ content })` |
62
62
  | Init script | `page.addInitScript()` — function or string, persists across `goto()` navigations |
@@ -27,6 +27,7 @@ export interface StorageState {
27
27
  export type PageCleanup = (opts?: {
28
28
  navigateTo?: string;
29
29
  }) => Promise<void>;
30
+ export declare function createPopupPage(context: BrowserContext, seedPage: Page, popupUrl: string): Promise<Page | null>;
30
31
  export declare function installPageWrappers(page: Page, context: BrowserContext, baseURL: string | undefined): Promise<PageCleanup>;
31
32
  export declare const test: import("@playwright/test").TestType<import("@playwright/test").PlaywrightTestArgs & import("@playwright/test").PlaywrightTestOptions & {
32
33
  emulateDevice: (descriptor: DeviceDescriptor) => Promise<void>;
package/dist/fixture.mjs CHANGED
@@ -16,6 +16,64 @@ function readInfo() {
16
16
  return JSON.parse(readFileSync(INFO_PATH, 'utf8'));
17
17
  }
18
18
  function readEndpoint() { return readInfo().endpoint; }
19
+ // Create a real Page in the default context via Target.createTarget.
20
+ // Returns the new page (already navigated to popupUrl) on success, or null
21
+ // to let the caller fall back to idle-tab proxy or stub.
22
+ //
23
+ // Precondition: PW_CHROMIUM_ATTACH_TO_OTHER=1 must be set, otherwise the new
24
+ // target created by ArkWeb will be type:'other' and Playwright won't pick
25
+ // it up into ctx.pages().
26
+ export async function createPopupPage(context, seedPage, popupUrl) {
27
+ let session = null;
28
+ try {
29
+ session = await context.newCDPSession(seedPage);
30
+ const r = await Promise.race([
31
+ session
32
+ .send('Target.createTarget', { url: 'about:blank' }),
33
+ new Promise((_, rej) => setTimeout(() => rej(new Error('createTarget timeout')), 3000)),
34
+ ]);
35
+ if (!r.targetId)
36
+ return null;
37
+ // Poll ctx.pages() until Playwright picks up the new target (max 2s).
38
+ const pagesBefore = context.pages().length;
39
+ const deadline = Date.now() + 2000;
40
+ while (Date.now() < deadline) {
41
+ if (context.pages().length > pagesBefore)
42
+ break;
43
+ await new Promise((r) => setTimeout(r, 50));
44
+ }
45
+ const allPages = context.pages();
46
+ if (allPages.length <= pagesBefore)
47
+ return null;
48
+ // Pick the newly-added page (any page not equal to seedPage, preferring
49
+ // about:blank which is the createTarget's initial URL).
50
+ const newPage = allPages.find((p) => p !== seedPage && p.url() === 'about:blank') ??
51
+ allPages.find((p) => p !== seedPage);
52
+ if (!newPage)
53
+ return null;
54
+ // Navigate to the popup URL (skip for about:blank which is already loaded).
55
+ // On navigation failure, close the tab and return null — otherwise a
56
+ // half-loaded popup tab (url stuck at about:blank) gets mistaken for the
57
+ // launchUrl tab by the next test's fixture-page selector.
58
+ if (popupUrl && popupUrl !== 'about:blank') {
59
+ try {
60
+ await newPage.goto(popupUrl, { timeout: 5000 });
61
+ }
62
+ catch {
63
+ await newPage.close().catch(() => { });
64
+ return null;
65
+ }
66
+ }
67
+ return newPage;
68
+ }
69
+ catch {
70
+ return null;
71
+ }
72
+ finally {
73
+ if (session)
74
+ await session.detach().catch(() => { });
75
+ }
76
+ }
19
77
  export async function installPageWrappers(page, context, baseURL) {
20
78
  const ctxEmit = context.emit.bind(context);
21
79
  // connectOverCDP reuses an existing tab — Playwright has no record of its
@@ -143,14 +201,39 @@ export async function installPageWrappers(page, context, baseURL) {
143
201
  return q;
144
202
  });
145
203
  for (const { url } of pending ?? []) {
146
- // context.newPage() calls Target.createTarget which hangs in ArkWeb.
147
- // Emit a minimal stub — satisfies waitForLoadState / url / close.
148
- const stub = {
149
- waitForLoadState: async () => { },
150
- url: () => url,
151
- close: async () => { },
152
- };
153
- ctxEmit('page', stub);
204
+ // 1) Target.createTarget(首选)
205
+ let emitted = null;
206
+ try {
207
+ emitted = await createPopupPage(context, page, url || 'about:blank');
208
+ }
209
+ catch { }
210
+ // 2) Fallback A:默认 context 闲置 about:blank tab
211
+ if (!emitted) {
212
+ const idle = context
213
+ .pages()
214
+ .find((p) => p !== page && p.url() === 'about:blank');
215
+ if (idle) {
216
+ try {
217
+ if (url && url !== 'about:blank') {
218
+ await idle.goto(url, { timeout: 5000 });
219
+ }
220
+ emitted = idle;
221
+ }
222
+ catch { }
223
+ }
224
+ }
225
+ // 3) Fallback B:退回原 stub(保持兼容)
226
+ if (!emitted) {
227
+ const stub = {
228
+ waitForLoadState: async () => { },
229
+ url: () => url,
230
+ close: async () => { },
231
+ };
232
+ ctxEmit('page', stub);
233
+ }
234
+ else {
235
+ ctxEmit('page', emitted);
236
+ }
154
237
  }
155
238
  }
156
239
  catch { }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ohos-playwright",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "Playwright adapter for OpenHarmony / ArkWeb via hdc + CDP",
5
5
  "license": "MIT",
6
6
  "author": "social4hyq",