39 lines
4.4 KiB
JavaScript
39 lines
4.4 KiB
JavaScript
async (page) => {
|
|
const origin = new URL(page.url()).origin; const browser = page.context().browser(); const context = await browser.newContext(); context.setDefaultTimeout(10000);
|
|
let target = await context.newPage(); const username = `remember_${Date.now()}`; const password = 'Remember-login-smoke-password'; const results = [];
|
|
async function stored() {
|
|
return target.evaluate(async () => {
|
|
const db = await new Promise((resolve, reject) => { const req = indexedDB.open('webdrop-account-local-2'); req.onsuccess = () => resolve(req.result); req.onerror = () => reject(req.error); });
|
|
const tx = db.transaction(['sessions', 'credentials'], 'readonly');
|
|
const read = (name) => new Promise((resolve, reject) => { const req = tx.objectStore(name).getAll(); req.onsuccess = () => resolve(req.result); req.onerror = () => reject(req.error); });
|
|
const [sessions, credentials] = await Promise.all([read('sessions'), read('credentials')]); db.close();
|
|
return { sessions: sessions.length, credentials: credentials.length, plaintext: credentials.some((value) => 'password' in value || 'username' in value), exportable: credentials.some((value) => value.key.extractable) };
|
|
});
|
|
}
|
|
async function reopen() { await target.close(); target = await context.newPage(); await target.goto(origin); }
|
|
try {
|
|
await target.goto(origin); await target.getByLabel('用户名', { exact: true }).fill(username); await target.getByLabel('密码', { exact: true }).fill(password);
|
|
await target.getByRole('button', { name: '创建账号', exact: true }).click(); await target.getByRole('button', { name: '退出登录', exact: true }).waitFor();
|
|
const record = await stored(); if (record.credentials !== 1 || record.plaintext || record.exportable) throw new Error('Login was not stored as non-exportable encrypted data');
|
|
await reopen(); await target.getByRole('button', { name: '退出登录', exact: true }).waitFor(); results.push('fresh page restores the remembered account');
|
|
await target.getByRole('button', { name: '退出登录', exact: true }).click(); await target.getByRole('button', { name: '登录并同步', exact: true }).waitFor();
|
|
if (await target.getByLabel('用户名', { exact: true }).inputValue() !== username || await target.getByLabel('密码', { exact: true }).inputValue() !== password) throw new Error('Saved account/password were not filled');
|
|
results.push('normal logout preserves encrypted credentials and fills the login form');
|
|
await target.getByRole('checkbox', { name: '记住账号和密码(本机)', exact: true }).uncheck(); await target.getByRole('button', { name: '登录并同步', exact: true }).click();
|
|
await target.getByRole('button', { name: '退出登录', exact: true }).waitFor(); await target.getByRole('button', { name: '立即同步', exact: true }).click();
|
|
await target.getByText('资源保险库已同步。', { exact: true }).waitFor();
|
|
const temporary = await stored(); if (temporary.sessions || temporary.credentials) throw new Error('Unremembered login was persisted by sync');
|
|
await reopen(); await target.getByLabel('用户名', { exact: true }).waitFor();
|
|
if (await target.getByLabel('用户名', { exact: true }).inputValue() || await target.getByLabel('密码', { exact: true }).inputValue()) throw new Error('Temporary login reappeared');
|
|
results.push('unchecked remember only keeps the current page session');
|
|
await target.getByRole('button', { name: '已有账号', exact: true }).click(); await target.getByLabel('用户名', { exact: true }).fill(username); await target.getByLabel('密码', { exact: true }).fill(password);
|
|
await target.getByRole('button', { name: '登录并同步', exact: true }).click(); await target.getByRole('button', { name: '清除本机保存', exact: true }).click();
|
|
await target.getByRole('button', { name: '立即同步', exact: true }).click(); await target.getByText('资源保险库已同步。', { exact: true }).waitFor();
|
|
const cleared = await stored(); if (cleared.sessions || cleared.credentials) throw new Error('Cleared login was restored by sync');
|
|
await reopen(); await target.getByLabel('密码', { exact: true }).waitFor();
|
|
if (await target.getByLabel('密码', { exact: true }).inputValue()) throw new Error('Password returned after clearing');
|
|
results.push('clearing local saves survives synchronization and page restart');
|
|
return { passed: results };
|
|
} finally { await context.close(); }
|
|
}
|