From a43cecb0f02946e26f133cbe05f36b3ea06a71cc Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 19 Apr 2026 12:36:28 +0300 Subject: [PATCH] e2e(standalone): integration test database not loaded --- .github/workflows/playwright.yml | 2 +- apps/client-standalone/package.json | 2 +- apps/client-standalone/playwright.config.ts | 3 ++ .../src/lightweight/platform_provider.ts | 1 + .../src/local-server-worker.ts | 47 +++++++++++++------ apps/client-standalone/vite.config.mts | 21 +++++++++ packages/trilium-e2e/src/support/app.ts | 21 ++++++++- 7 files changed, 78 insertions(+), 19 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index e27b6bc3f7..f80f072c23 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -119,7 +119,7 @@ jobs: run: pnpm exec playwright install --with-deps - name: Build standalone - run: pnpm --filter client-standalone build + run: TRILIUM_INTEGRATION_TEST=memory pnpm --filter client-standalone build - name: Start standalone preview server run: | diff --git a/apps/client-standalone/package.json b/apps/client-standalone/package.json index 02c6811d48..4396bd1092 100644 --- a/apps/client-standalone/package.json +++ b/apps/client-standalone/package.json @@ -11,7 +11,7 @@ "start-prod": "pnpm build && pnpm vite preview --port 8888", "coverage": "vitest --coverage", "e2e": "playwright test", - "start-prod-no-dir": "pnpm build && pnpm vite preview --port ${TRILIUM_PORT:-8082} --host 127.0.0.1" + "start-prod-no-dir": "cross-env TRILIUM_INTEGRATION_TEST=memory pnpm build && pnpm vite preview --port ${TRILIUM_PORT:-8082} --host 127.0.0.1" }, "dependencies": { "@excalidraw/excalidraw": "0.18.0", diff --git a/apps/client-standalone/playwright.config.ts b/apps/client-standalone/playwright.config.ts index 196757bfb7..50e15a5ca8 100644 --- a/apps/client-standalone/playwright.config.ts +++ b/apps/client-standalone/playwright.config.ts @@ -3,6 +3,9 @@ import { createBaseConfig } from "../../packages/trilium-e2e/src/base-config"; const port = process.env["TRILIUM_PORT"] ?? "8082"; const baseURL = process.env["BASE_URL"] || `http://127.0.0.1:${port}`; +// Standalone needs the integrationTest query param to load the test fixture DB +process.env["TRILIUM_E2E_QUERY_PARAMS"] = "integrationTest=memory"; + export default createBaseConfig({ appDir: __dirname, projectName: "standalone", diff --git a/apps/client-standalone/src/lightweight/platform_provider.ts b/apps/client-standalone/src/lightweight/platform_provider.ts index 85f3bc18bc..6da914e806 100644 --- a/apps/client-standalone/src/lightweight/platform_provider.ts +++ b/apps/client-standalone/src/lightweight/platform_provider.ts @@ -4,6 +4,7 @@ import type { PlatformProvider } from "@triliumnext/core"; const QUERY_TO_ENV: Record = { "safeMode": "TRILIUM_SAFE_MODE", "startNoteId": "TRILIUM_START_NOTE_ID", + "integrationTest": "TRILIUM_INTEGRATION_TEST", }; export default class StandalonePlatformProvider implements PlatformProvider { diff --git a/apps/client-standalone/src/local-server-worker.ts b/apps/client-standalone/src/local-server-worker.ts index 283889d7be..647db5384b 100644 --- a/apps/client-standalone/src/local-server-worker.ts +++ b/apps/client-standalone/src/local-server-worker.ts @@ -145,8 +145,21 @@ async function initialize(): Promise { console.log("[Worker] Initializing SQLite WASM..."); await sqlProvider!.initWasm(); - // Try to use OPFS for persistent storage - if (sqlProvider!.isOpfsAvailable()) { + // Check if we're in integration test mode (loaded via ?integrationTest=memory) + const params = new URLSearchParams(queryString); + const integrationTestMode = params.get("integrationTest"); + + if (integrationTestMode === "memory") { + // Load the pre-built test fixture database for e2e tests + console.log("[Worker] Integration test mode: loading fixture database..."); + const response = await fetch("/test-fixtures/document.db"); + if (!response.ok) { + throw new Error(`Failed to fetch test fixture: ${response.status} ${response.statusText}`); + } + const buffer = new Uint8Array(await response.arrayBuffer()); + sqlProvider!.loadFromBuffer(buffer); + } else if (sqlProvider!.isOpfsAvailable()) { + // Try to use OPFS for persistent storage console.log("[Worker] OPFS available, loading persistent database..."); sqlProvider!.loadFromOpfs("/trilium.db"); } else { @@ -256,19 +269,9 @@ async function dispatch(request: LocalRequest) { return appRouter.dispatch(request.method, request.url, request.body, request.headers); } -// Start initialization immediately when the worker loads -console.log("[Worker] Starting initialization..."); -initialize().catch(err => { - console.error("[Worker] Initialization failed:", err); - // Post error to main thread - self.postMessage({ - type: "WORKER_ERROR", - error: { - message: String(err?.message || err), - stack: err?.stack - } - }); -}); +// Wait for the INIT message before initializing so that queryString +// (which may contain ?integrationTest=memory for e2e) is available. +let initReceived = false; self.onmessage = async (event) => { const msg = event.data; @@ -276,6 +279,20 @@ self.onmessage = async (event) => { if (msg.type === "INIT") { queryString = msg.queryString || ""; + if (!initReceived) { + initReceived = true; + console.log("[Worker] Starting initialization..."); + initialize().catch(err => { + console.error("[Worker] Initialization failed:", err); + self.postMessage({ + type: "WORKER_ERROR", + error: { + message: String(err?.message || err), + stack: err?.stack + } + }); + }); + } return; } diff --git a/apps/client-standalone/vite.config.mts b/apps/client-standalone/vite.config.mts index 73b1ff09c6..c53855e2ed 100644 --- a/apps/client-standalone/vite.config.mts +++ b/apps/client-standalone/vite.config.mts @@ -155,6 +155,21 @@ if (!isDev) { ] } +// Include the integration test fixture database for e2e tests +if (process.env.TRILIUM_INTEGRATION_TEST) { + plugins = [ + ...plugins, + viteStaticCopy({ + targets: [ + { + src: "../../../packages/trilium-core/src/test/fixtures/document.db", + dest: "test-fixtures", + } + ] + }) + ] +} + export default defineConfig(() => ({ root: join(__dirname, 'src'), // Set src as root so index.html is served from / envDir: __dirname, // Load .env files from client-standalone directory, not src/ @@ -219,6 +234,12 @@ export default defineConfig(() => ({ "Cross-Origin-Embedder-Policy": "require-corp" } }, + preview: { + headers: { + "Cross-Origin-Opener-Policy": "same-origin", + "Cross-Origin-Embedder-Policy": "require-corp" + } + }, optimizeDeps: { exclude: ['@sqlite.org/sqlite-wasm', '@triliumnext/core'] }, diff --git a/packages/trilium-e2e/src/support/app.ts b/packages/trilium-e2e/src/support/app.ts index 665741cee9..8a09db7cdc 100644 --- a/packages/trilium-e2e/src/support/app.ts +++ b/packages/trilium-e2e/src/support/app.ts @@ -1,12 +1,20 @@ import type { BrowserContext } from "@playwright/test"; import { expect, Locator, Page } from "@playwright/test"; -interface GotoOpts { +export interface GotoOpts { url?: string; isMobile?: boolean; preserveTabs?: boolean; } +/** + * Extra query parameters to append to all navigations (e.g. "integrationTest=memory"). + * Set via the TRILIUM_E2E_QUERY_PARAMS environment variable. + */ +function getDefaultQueryParams(): string { + return process.env["TRILIUM_E2E_QUERY_PARAMS"] ?? ""; +} + export function getBaseUrl(): string { const port = process.env["TRILIUM_PORT"] ?? "8082"; return process.env["BASE_URL"] || `http://127.0.0.1:${port}`; @@ -61,10 +69,19 @@ export default class App { url = "/"; } + // Append default query params (e.g. ?integrationTest=memory for standalone) + const extraParams = getDefaultQueryParams(); + if (extraParams) { + const separator = url.includes("?") ? "&" : "?"; + url = `${url}${separator}${extraParams}`; + } + + const isRoot = url === "/" || url.startsWith("/?"); + await this.page.goto(url, { waitUntil: "networkidle", timeout: 30_000 }); // Wait for the page to load. - if (url === "/") { + if (isRoot) { await expect(this.page.locator(".tree", { hasText: "Trilium Integration Test" })).toBeVisible(); if (!preserveTabs) { await this.closeAllTabs();