test(cookies): add Playwright e2e test for sign-out cookie clearing (#8275)

This commit is contained in:
Alex Yang
2026-03-02 15:07:34 +09:00
committed by GitHub
parent 19dd96d186
commit 913bd5babe
3 changed files with 74 additions and 2 deletions

View File

@@ -1,11 +1,13 @@
import { createServer } from "node:http";
import { DatabaseSync } from "node:sqlite";
import type { BetterAuthOptions } from "better-auth";
import { betterAuth } from "better-auth";
import { getMigrations } from "better-auth/db/migration";
import { toNodeHandler } from "better-auth/node";
export async function createAuthServer(
baseURL: string = "http://localhost:3000",
overrides?: Partial<BetterAuthOptions>,
) {
const database = new DatabaseSync(":memory:");
@@ -20,6 +22,7 @@ export async function createAuthServer(
"http://localhost:*", // Dynamic frontend port
"http://test.com:*", // Cross-domain test
],
...overrides,
});
const { runMigrations } = await getMigrations(auth.options);

View File

@@ -0,0 +1,68 @@
import { expect, test } from "@playwright/test";
import { runClient, setup } from "./utils";
/**
* @see https://github.com/better-auth/better-auth/issues/8273
*/
const { ref, start, clean } = setup({
session: {
cookieCache: {
enabled: true,
maxAge: 60,
strategy: "compact",
},
},
});
test.describe("sign-out with cookieCache", () => {
test.beforeEach(async () => start());
test.afterEach(async () => clean());
test("should clear both session_token and session_data cookies on sign-out", async ({
page,
}) => {
await page.goto(
`http://localhost:${ref.clientPort}/?port=${ref.serverPort}`,
);
await page.locator("text=Ready").waitFor();
// Sign in
await runClient(page, ({ client }) =>
client.signIn.email({
email: "test@test.com",
password: "password123",
}),
);
// Verify both cookies are set
let cookies = await page.context().cookies();
expect(
cookies.find((c) => c.name === "better-auth.session_token"),
).toBeDefined();
expect(
cookies.find((c) => c.name === "better-auth.session_data"),
).toBeDefined();
// Verify session is valid
const session = await runClient(page, ({ client }) => client.getSession());
expect(session.data?.user.email).toBe("test@test.com");
// Sign out
await runClient(page, ({ client }) => client.signOut());
// Verify both cookies are cleared by the browser
cookies = await page.context().cookies();
expect(
cookies.find((c) => c.name === "better-auth.session_token"),
).toBeUndefined();
expect(
cookies.find((c) => c.name === "better-auth.session_data"),
).toBeUndefined();
// Verify session is null
const sessionAfter = await runClient(page, ({ client }) =>
client.getSession(),
);
expect(sessionAfter.data).toBeNull();
});
});

View File

@@ -3,6 +3,7 @@ import { spawn } from "node:child_process";
import { fileURLToPath } from "node:url";
import { terminate } from "@better-auth-test/test-utils/playwright";
import type { Page } from "@playwright/test";
import type { BetterAuthOptions } from "better-auth";
import { createAuthServer } from "./app";
const root = fileURLToPath(new URL("../", import.meta.url));
@@ -15,7 +16,7 @@ export async function runClient<R>(
return page.evaluate(fn, { client });
}
export function setup() {
export function setup(overrides?: Partial<BetterAuthOptions>) {
let server: Awaited<ReturnType<typeof createAuthServer>>;
let clientChild: ChildProcessWithoutNullStreams;
const ref: {
@@ -28,7 +29,7 @@ export function setup() {
return {
ref,
start: async () => {
server = await createAuthServer();
server = await createAuthServer(undefined, overrides);
clientChild = spawn("pnpm", ["run", "start:client"], {
cwd: root,
stdio: "pipe",