UNPKG

playwright-persona

Version:

Authentication in Playwright using personas.

77 lines (76 loc) 3.66 kB
import { Page, TestFixture, TestInfo } from "@playwright/test"; //#region src/index.d.ts type SessionValueType = string | number | Date | null | undefined | Array<SessionValueType> | { [key: string]: SessionValueType; }; type SessionType = Record<string, SessionValueType>; interface PersonaOptions<Session extends SessionType> { /** * Create a new session for this persona. * Returns the context object to share state across other methods. * * @example * async createSession({ page }) { * const user = await createMockUser() * await page.goto('/login') * await page.getByLabel('Username').fill(user.name) * await page.getByLagbel('Password').fill(user.password) * await page.getByRole('button', { name: 'Log in' }).click() * * return { user } * } */ createSession: CreateSessionFunction<Session>; /** * Verify that the given session belongs to this persona. * Used to determine if the authentication state stored on disk * should still be used or a new session should be created. * * @example * async verifySession({ page, session }) { * await page.goto('/dashboard') * await expect(page.getByText(session.user.name)).toBeVisible() * } */ verifySession: VerifySessionFunction<Session>; /** * Destroy the given session. * Used to properly dispose of test resources related to a stored session * (e.g. test records in a database). * * @example * async destroySession({ session }) { * await deleteUser({ where: { id: session.user.id } }) * } */ destroySession?: DestroySessionFunction<Session>; } interface CreateSessionContext { page: Page; } interface VerifySessionContext<Session extends SessionType> { session: Session; page: Page; } interface DestroySessionContext<Session extends SessionType> { session: Session; page: Page; } interface Persona<Name extends string, Session extends SessionType> { name: Name; createSession: CreateSessionFunction<Session>; verifySession: VerifySessionFunction<Session>; destroySession?: DestroySessionFunction<Session>; } type CreateSessionFunction<Session extends SessionType> = (context: CreateSessionContext, testInfo: TestInfo) => Promise<Session>; type VerifySessionFunction<Session extends SessionType> = (context: VerifySessionContext<Session>, testInfo: TestInfo) => Promise<void>; type DestroySessionFunction<Session extends SessionType> = (context: DestroySessionContext<Session>, testInfo: TestInfo) => Promise<void>; declare function definePersona<Name extends string, Session extends SessionType>(name: Name, options: PersonaOptions<Session>): Persona<Name, Session>; type AuthenticateFunction<Personas extends Array<Persona<any, any>>> = <Name extends ExtractPersonaNames<Personas>>(options: { as: Name; }) => Promise<MapPersonasToRecord<Personas>[Name]>; type MapPersonasToRecord<Personas extends Array<Persona<any, any>>> = Personas extends Array<infer P> ? { [Name in P extends Persona<infer Name, any> ? Name : never]: P extends Persona<Name, infer Session> ? Session : never } : never; type ExtractPersonaNames<Personas extends Array<Persona<any, any>>> = Personas extends Array<infer P> ? P extends Persona<infer Name, any> ? Name : never : never; declare function combinePersonas<Personas extends Array<Persona<any, any>>>(...personas: Personas): TestFixture<AuthenticateFunction<Personas>, any>; //#endregion export { AuthenticateFunction, CreateSessionContext, CreateSessionFunction, DestroySessionContext, DestroySessionFunction, Persona, PersonaOptions, SessionType, VerifySessionContext, VerifySessionFunction, combinePersonas, definePersona };