Add self-contained e2e test harness with ephemeral PocketBase
Previously, 15 e2e tests were skipped because TEST_USER_EMAIL and TEST_USER_PASSWORD env vars weren't set. Now the test harness: - Starts a fresh PocketBase instance in /tmp on port 8091 - Creates admin user, collections, and API rules automatically - Seeds test user with period data for authenticated tests - Cleans up temp directory after tests complete Also fixes: - Override toggle tests now use checkbox role (not button) - Adds proper wait for OVERRIDES section before testing toggles - Suppresses document.cookie lint warning with explanation Test results: 64 e2e tests pass, 1014 unit tests pass Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
140
e2e/pocketbase-harness.test.ts
Normal file
140
e2e/pocketbase-harness.test.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
// ABOUTME: Integration tests for the PocketBase e2e test harness.
|
||||
// ABOUTME: Verifies the harness can start, setup, and stop PocketBase instances.
|
||||
// @vitest-environment node
|
||||
|
||||
import PocketBase from "pocketbase";
|
||||
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
||||
import {
|
||||
DEFAULT_CONFIG,
|
||||
getState,
|
||||
type HarnessState,
|
||||
start,
|
||||
stop,
|
||||
} from "./pocketbase-harness";
|
||||
|
||||
describe("pocketbase-harness", () => {
|
||||
describe("start/stop lifecycle", () => {
|
||||
let state: HarnessState;
|
||||
|
||||
beforeAll(async () => {
|
||||
state = await start();
|
||||
}, 60000);
|
||||
|
||||
afterAll(async () => {
|
||||
await stop();
|
||||
});
|
||||
|
||||
it("returns a valid harness state", () => {
|
||||
expect(state).toBeDefined();
|
||||
expect(state.url).toBe(`http://127.0.0.1:${DEFAULT_CONFIG.port}`);
|
||||
expect(state.dataDir).toContain("pocketbase-e2e-");
|
||||
expect(state.process).toBeDefined();
|
||||
});
|
||||
|
||||
it("getState returns the current state while running", () => {
|
||||
const currentState = getState();
|
||||
expect(currentState).toBe(state);
|
||||
});
|
||||
|
||||
it("PocketBase is accessible at the expected URL", async () => {
|
||||
const response = await fetch(`${state.url}/api/health`);
|
||||
expect(response.ok).toBe(true);
|
||||
});
|
||||
|
||||
it("admin can authenticate", async () => {
|
||||
const pb = new PocketBase(state.url);
|
||||
pb.autoCancellation(false);
|
||||
|
||||
const auth = await pb
|
||||
.collection("_superusers")
|
||||
.authWithPassword(
|
||||
DEFAULT_CONFIG.adminEmail,
|
||||
DEFAULT_CONFIG.adminPassword,
|
||||
);
|
||||
|
||||
expect(auth.token).toBeDefined();
|
||||
});
|
||||
|
||||
it("test user can authenticate", async () => {
|
||||
const pb = new PocketBase(state.url);
|
||||
pb.autoCancellation(false);
|
||||
|
||||
const auth = await pb
|
||||
.collection("users")
|
||||
.authWithPassword(
|
||||
DEFAULT_CONFIG.testUserEmail,
|
||||
DEFAULT_CONFIG.testUserPassword,
|
||||
);
|
||||
|
||||
expect(auth.token).toBeDefined();
|
||||
expect(auth.record.email).toBe(DEFAULT_CONFIG.testUserEmail);
|
||||
});
|
||||
|
||||
it("test user has period data configured", async () => {
|
||||
const pb = new PocketBase(state.url);
|
||||
pb.autoCancellation(false);
|
||||
|
||||
await pb
|
||||
.collection("users")
|
||||
.authWithPassword(
|
||||
DEFAULT_CONFIG.testUserEmail,
|
||||
DEFAULT_CONFIG.testUserPassword,
|
||||
);
|
||||
|
||||
const user = pb.authStore.record;
|
||||
expect(user).toBeDefined();
|
||||
expect(user?.lastPeriodDate).toBeDefined();
|
||||
expect(user?.cycleLength).toBe(28);
|
||||
expect(user?.timezone).toBe("UTC");
|
||||
});
|
||||
|
||||
it("period_logs collection exists with test data", async () => {
|
||||
const pb = new PocketBase(state.url);
|
||||
pb.autoCancellation(false);
|
||||
|
||||
await pb
|
||||
.collection("users")
|
||||
.authWithPassword(
|
||||
DEFAULT_CONFIG.testUserEmail,
|
||||
DEFAULT_CONFIG.testUserPassword,
|
||||
);
|
||||
|
||||
const userId = pb.authStore.record?.id;
|
||||
const logs = await pb
|
||||
.collection("period_logs")
|
||||
.getList(1, 10, { filter: `user="${userId}"` });
|
||||
|
||||
expect(logs.totalItems).toBeGreaterThan(0);
|
||||
expect(logs.items[0].startDate).toBeDefined();
|
||||
});
|
||||
|
||||
it("dailyLogs collection exists", async () => {
|
||||
const pb = new PocketBase(state.url);
|
||||
pb.autoCancellation(false);
|
||||
|
||||
await pb
|
||||
.collection("_superusers")
|
||||
.authWithPassword(
|
||||
DEFAULT_CONFIG.adminEmail,
|
||||
DEFAULT_CONFIG.adminPassword,
|
||||
);
|
||||
|
||||
const collections = await pb.collections.getFullList();
|
||||
const collectionNames = collections.map((c) => c.name);
|
||||
|
||||
expect(collectionNames).toContain("period_logs");
|
||||
expect(collectionNames).toContain("dailyLogs");
|
||||
});
|
||||
});
|
||||
|
||||
describe("after stop", () => {
|
||||
it("getState returns null after stop", async () => {
|
||||
// Start and immediately stop
|
||||
await start({ ...DEFAULT_CONFIG, port: 8092 });
|
||||
await stop();
|
||||
|
||||
const state = getState();
|
||||
expect(state).toBeNull();
|
||||
}, 60000);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user