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 +1 -1
- package/dist/fixture.d.mts +1 -0
- package/dist/fixture.mjs +91 -8
- package/package.json +1 -1
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()` —
|
|
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 |
|
package/dist/fixture.d.mts
CHANGED
|
@@ -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
|
-
//
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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 { }
|