UNPKG

playwright-persona

Version:
82 lines (80 loc) 3 kB
import * as fs from "node:fs"; import * as path from "node:path"; import { invariant } from "outvariant"; //#region src/index.ts const STORAGE_STATE_DIRECTORY = path.join(process.cwd(), "./playwright/.auth/"); function definePersona(name, options) { return { name, createSession: options.createSession, verifySession: options.verifySession }; } function combinePersonas(...personas) { return async ({ browser, context, page }, use, testInfo) => { const createSessionFilePath = (persona) => { return path.join(STORAGE_STATE_DIRECTORY, `./${testInfo.testId}-${persona.name}.json`); }; const createSession = async (persona) => { const session = await persona.createSession({ page }, testInfo); const sessionFilePath = createSessionFilePath(persona); await context.storageState({ path: sessionFilePath }); const sessionFile = await readSessionFile(sessionFilePath); sessionFile.session = session; await fs.promises.writeFile(sessionFilePath, JSON.stringify(sessionFile, null, 2)); return session; }; await use(async (options) => { const persona = personas.find((persona$1) => { return persona$1.name === options.as; }); invariant(persona, "Failed to authenticate: cannot find persona by name \"%s\" (known personas: %s)", options.as, personas.join(", ")); const sessionFilePath = createSessionFilePath(persona); if (fs.existsSync(sessionFilePath)) { const sessionFile = await readSessionFile(sessionFilePath); const newContext = await browser.newContext({ storageState: sessionFile }); const newPage = await newContext.newPage(); await restoreSessionState(sessionFile, newPage); return persona.verifySession({ page: newPage, session: sessionFile.session }, testInfo).then(async () => { await restoreSessionState(sessionFile, page); return sessionFile.session; }).catch(async () => { await persona.destroySession?.({ page, session: sessionFile.session }, testInfo); return createSession(persona); }).finally(async () => { await newContext.close(); }); } return createSession(persona); }); }; } async function readSessionFile(filePath) { const textContent = await fs.promises.readFile(filePath, "utf8"); return JSON.parse(textContent); } async function restoreSessionState(sesionFile, page) { await page.context().addCookies(sesionFile.cookies); if (sesionFile.origins.length > 0) { const newPage = await page.context().newPage(); await newPage.route(/.+/, async (route) => { await route.fulfill({ body: `<html></html>` }).catch(() => {}); }); await Promise.allSettled(sesionFile.origins.map(async (state) => { const frame = newPage.mainFrame(); await frame.goto(state.origin); for (const item of state.localStorage) await frame.evaluate(([key, value]) => { localStorage.setItem(key, value); }, [item.name, item.value]); })); await newPage.close(); } } //#endregion export { combinePersonas, definePersona };