ohos-playwright 0.2.7 → 0.2.8

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/dist/fixture.mjs CHANGED
@@ -12,20 +12,9 @@ export const test = base.extend({
12
12
  },
13
13
  { scope: 'worker' },
14
14
  ],
15
- context: async ({ browser }, use, testInfo) => {
16
- const ctx = browser.contexts()[0];
17
- const baseURL = testInfo.project.use.baseURL;
18
- if (baseURL) {
19
- try {
20
- const opts = ctx._options;
21
- if (opts && typeof opts === 'object')
22
- opts.baseURL = baseURL;
23
- }
24
- catch (e) {
25
- console.warn(`[ohos-playwright] Failed to inject baseURL: ${e instanceof Error ? e.message : e}`);
26
- }
27
- }
28
- await use(ctx);
15
+ context: async ({ browser }, use) => {
16
+ // baseURL 通过 page fixture 重写 page.goto 实现;不再触碰 BrowserContext 私有字段 _options。
17
+ await use(browser.contexts()[0]);
29
18
  },
30
19
  page: async ({ context }, use, testInfo) => {
31
20
  const pages = context.pages();
package/dist/setup.d.mts CHANGED
@@ -8,6 +8,7 @@ export declare function findBrowserPid(): number | null;
8
8
  export declare function hasDeviceConnected(): boolean;
9
9
  export declare function discoverDevices(): string[];
10
10
  export declare function tryLocalDevice(): boolean;
11
+ export declare function ensureHdcKey(): boolean;
11
12
  export declare function ensureDeviceConnected(): Promise<void>;
12
13
  export default function globalSetup(): Promise<void>;
13
14
  export {};
package/dist/setup.mjs CHANGED
@@ -1,8 +1,11 @@
1
1
  import { execFileSync } from 'node:child_process';
2
- import { writeFileSync, mkdirSync } from 'node:fs';
2
+ import { writeFileSync, mkdirSync, existsSync, copyFileSync } from 'node:fs';
3
+ import { isAbsolute, join } from 'node:path';
3
4
  import { createServer } from 'node:net';
4
5
  import { dirname } from 'node:path';
5
6
  import { createInterface } from 'node:readline';
7
+ import { homedir } from 'node:os';
8
+ import { generateKeyPairSync } from 'node:crypto';
6
9
  import http from 'node:http';
7
10
  import { INFO_PATH } from "./info-path.mjs";
8
11
  const HDC = process.env.OHOS_PW_HDC ?? '/data/service/hnp/bin/hdc';
@@ -18,6 +21,15 @@ if (!SAFE_BUNDLE_RE.test(BUNDLE) || BUNDLE.length > 256) {
18
21
  if (!SAFE_URL_RE.test(LAUNCH_URL) || LAUNCH_URL.length > 2048) {
19
22
  throw new Error(`[ohos-playwright] OHOS_PW_LAUNCH_URL "${LAUNCH_URL}" 不是合法的 URL`);
20
23
  }
24
+ if (!isAbsolute(HDC) || !existsSync(HDC)) {
25
+ throw new Error(`[ohos-playwright] OHOS_PW_HDC "${HDC}" 不是有效的可执行文件路径(需绝对路径且文件存在)`);
26
+ }
27
+ // HarmonyOS host 提示:系统自带 hdc 与本机设备 hdcd 协议匹配;
28
+ // 其他 hdc(如 OHOS SDK 3.x)连本机设备会握手失败。
29
+ const SYSTEM_HDC_ON_HARMONY = '/data/service/hnp/bin/hdc';
30
+ if (existsSync(SYSTEM_HDC_ON_HARMONY) && HDC !== SYSTEM_HDC_ON_HARMONY) {
31
+ console.warn(`[ohos-playwright] 注意:当前 OHOS_PW_HDC="${HDC}",但系统自带 ${SYSTEM_HDC_ON_HARMONY} 才能与本机 HarmonyOS 设备通信;如握手失败请改用系统 hdc。`);
32
+ }
21
33
  const HDC_OPTS = { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] };
22
34
  function hdc(args, opts) {
23
35
  return String(execFileSync(HDC, args, { ...HDC_OPTS, ...opts })).trim();
@@ -126,9 +138,11 @@ export function discoverDevices() {
126
138
  }
127
139
  return out.split('\n').map(s => s.trim()).filter(s => IP_PORT_RE.test(s));
128
140
  }
141
+ // 已连接时 hdc tconn 返回 "Target is connected, repeat operation",也视作成功。
129
142
  function tconn(addr) {
130
143
  try {
131
- return hdc(['tconn', addr], { timeout: 10000 }).includes('Connect OK');
144
+ const out = hdc(['tconn', addr], { timeout: 10000 });
145
+ return out.includes('Connect OK') || out.includes('repeat operation');
132
146
  }
133
147
  catch {
134
148
  return false;
@@ -166,9 +180,70 @@ export function tryLocalDevice() {
166
180
  catch { }
167
181
  return false;
168
182
  }
183
+ // HarmonyOS host 自愈:缺 hdc key 时自动生成 RSA-3072,并重启本机 hdc server。
184
+ // 仅在 host 看似 HarmonyOS 时触发(/data/service/hnp/bin/hdc 存在);最多 1 次。
185
+ const HARMONY_HDC_PATH = '/data/service/hnp/bin/hdc';
186
+ const HARMONY_KEY_DIR = join(homedir(), '.harmony');
187
+ let selfHealAttempted = false;
188
+ function isHarmonyHost() { return existsSync(HARMONY_HDC_PATH); }
189
+ export function ensureHdcKey() {
190
+ const priv = join(HARMONY_KEY_DIR, 'hdckey');
191
+ const pub = join(HARMONY_KEY_DIR, 'hdckey.pub');
192
+ if (existsSync(priv) && existsSync(pub))
193
+ return false;
194
+ mkdirSync(HARMONY_KEY_DIR, { recursive: true });
195
+ for (const f of [priv, pub]) {
196
+ if (existsSync(f)) {
197
+ try {
198
+ copyFileSync(f, f + '.bak');
199
+ }
200
+ catch { }
201
+ }
202
+ }
203
+ const { privateKey, publicKey } = generateKeyPairSync('rsa', {
204
+ modulusLength: 3072,
205
+ privateKeyEncoding: { type: 'pkcs1', format: 'pem' },
206
+ publicKeyEncoding: { type: 'spki', format: 'pem' },
207
+ });
208
+ writeFileSync(priv, privateKey, { mode: 0o600 });
209
+ writeFileSync(pub, publicKey, { mode: 0o644 });
210
+ console.warn(`[ohos-playwright] generated RSA-3072 hdc key at ${priv} (设备首次连接需 UI 授权)`);
211
+ return true;
212
+ }
213
+ async function restartHdcServer() {
214
+ try {
215
+ hdc(['kill']);
216
+ }
217
+ catch { }
218
+ await sleep(500);
219
+ try {
220
+ hdc(['start']);
221
+ }
222
+ catch (e) {
223
+ console.warn(`[ohos-playwright] hdc start failed: ${e instanceof Error ? e.message : e}`);
224
+ }
225
+ }
226
+ async function selfHealHdc() {
227
+ if (selfHealAttempted)
228
+ return;
229
+ selfHealAttempted = true;
230
+ if (process.env.OHOS_PW_AUTO_HEAL === '0')
231
+ return;
232
+ if (!isHarmonyHost())
233
+ return;
234
+ console.log('[ohos-playwright] self-heal: 检查 hdc key 与重启本机 hdc server...');
235
+ const keyChanged = ensureHdcKey();
236
+ await restartHdcServer();
237
+ await sleep(keyChanged ? 1500 : 500);
238
+ }
169
239
  export async function ensureDeviceConnected() {
170
240
  if (process.env.OHOS_PW_AUTO_CONNECT === '0')
171
241
  return;
242
+ if (hasDeviceConnected())
243
+ return;
244
+ if (tryLocalDevice())
245
+ return;
246
+ await selfHealHdc();
172
247
  if (hasDeviceConnected())
173
248
  return;
174
249
  if (tryLocalDevice())
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ohos-playwright",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "Playwright adapter for OpenHarmony / ArkWeb via hdc + CDP",
5
5
  "license": "MIT",
6
6
  "author": "social4hyq",