playwright-persona
Version:
Authentication in Playwright using personas.
65 lines (64 loc) • 2.38 kB
JavaScript
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,
destroySession: options.destroySession
};
}
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) => {
return persona.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 newContext.setStorageState(sessionFile);
return persona.verifySession({
page: newPage,
session: sessionFile.session
}, testInfo).then(async () => {
await context.setStorageState(sessionFile);
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);
}
//#endregion
export { combinePersonas, definePersona };