async (page) => { const origin = new URL(page.url()).origin; const context = await page.context().browser().newContext(); const owner = await context.newPage(); const cdp = await context.newCDPSession(owner); const results = []; const username = `passkey_${Date.now()}`; const password = 'Passkey-test-password-2026'; const errors = []; const calls = []; owner.on('pageerror', error => errors.push(error.message)); owner.on('request', request => { if (request.url().includes('/api/v1/')) calls.push(new URL(request.url()).pathname); }); await cdp.send('WebAuthn.enable'); const { authenticatorId } = await cdp.send('WebAuthn.addVirtualAuthenticator', { options: { protocol: 'ctap2', ctap2Version: 'ctap2_1', transport: 'internal', hasResidentKey: true, hasUserVerification: true, isUserVerified: true, automaticPresenceSimulation: true, hasPrf: true } }); let secretExtensionSent = false; owner.on('request', request => { if (request.url().includes('/accounts/passkeys/') && request.postData()) { const body = JSON.parse(request.postData()); if (body.credential && JSON.parse(body.credential).clientExtensionResults?.prf?.results) secretExtensionSent = true; } }); try { await owner.goto(origin); await owner.getByLabel('用户名', { exact: true }).fill(username); await owner.getByLabel('密码', { exact: true }).fill(password); await owner.getByRole('button', { name: '创建账号', exact: true }).click(); await owner.getByRole('button', { name: '新建空间', exact: true }).waitFor(); await owner.getByLabel('Passkey名称', { exact: true }).fill('测试恢复凭据'); await owner.getByLabel('验证账号密码', { exact: true }).fill(password); await owner.getByRole('button', { name: '绑定Passkey', exact: true }).click(); await owner.getByText('测试恢复凭据 · 登录与解密恢复', { exact: true }).waitFor(); if (secretExtensionSent) throw new Error('PRF results were sent to the API'); results.push('verified WebAuthn binding enables encrypted recovery without sending PRF outputs to the server'); await owner.getByRole('button', { name: '新建空间', exact: true }).click(); await owner.getByLabel('空间名称(加入者和服务端可见)').fill('Passkey恢复测试'); await owner.getByRole('button', { name: '创建', exact: true }).click(); await owner.getByRole('button', { name: '常规', exact: true }).waitFor(); await owner.getByRole('region', { name: '常规 聊天', exact: true }).locator('textarea').fill('Passkey恢复后的私密内容'); await owner.getByRole('button', { name: '发送消息', exact: true }).click(); await owner.getByRole('article').getByText('Passkey恢复后的私密内容', { exact: true }).waitFor(); const path = new URL(owner.url()).pathname; await owner.goto(origin); await owner.getByRole('button', { name: '退出登录', exact: true }).click(); await owner.getByRole('button', { name: '使用Passkey登录', exact: true }).waitFor(); await owner.getByRole('button', { name: '使用Passkey登录', exact: true }).click(); await owner.getByRole('button', { name: '新建空间', exact: true }).waitFor(); await owner.goto(origin + path); await owner.getByRole('article').getByText('Passkey恢复后的私密内容', { exact: true }).waitFor(); results.push('Passkey restores the vault and decrypts resources without entering the password'); await owner.goto(origin); await owner.getByRole('button', { name: '撤销 测试恢复凭据', exact: true }).click(); await owner.getByText('Passkey已撤销', { exact: true }).waitFor(); await owner.getByRole('button', { name: '退出登录', exact: true }).click(); await owner.getByLabel('用户名', { exact: true }).fill(username); await owner.getByLabel('密码', { exact: true }).fill(password); await owner.getByRole('button', { name: '登录并同步', exact: true }).click(); await owner.getByRole('button', { name: '新建空间', exact: true }).waitFor(); results.push('revocation removes the credential while password recovery remains available'); return { passed: results }; } catch (error) { const inputs = await owner.locator('input').evaluateAll(inputs => inputs.map(input => ({ name: input.name, type: input.type, length: input.value.length, valid: input.validity.valid, message: input.validationMessage }))); throw new Error(`Passkey smoke failed after ${results.length} checks: ${error.message}; body=${(await owner.locator('body').innerText()).slice(0, 800)}; inputs=${JSON.stringify(inputs)}; errors=${JSON.stringify(errors)}; calls=${JSON.stringify(calls)}`); } finally { await cdp.send('WebAuthn.removeVirtualAuthenticator', { authenticatorId }).catch(() => {}); await context.close(); } }