From c43ab681cdb09ae6532b3dd09d526bfbf45a982c Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Sun, 10 May 2026 22:34:37 +0800 Subject: [PATCH] test: add backend API contract coverage --- .../sql-file/SqlFileExecutionDialog.vue | 2 +- src/lib/http.ts | 23 +------------------ src/lib/httpSqlFileProgress.ts | 19 +++++++++++++++ tests/apiBackendContract.test.ts | 12 ++++++++++ 4 files changed, 33 insertions(+), 23 deletions(-) create mode 100644 src/lib/httpSqlFileProgress.ts create mode 100644 tests/apiBackendContract.test.ts diff --git a/src/components/sql-file/SqlFileExecutionDialog.vue b/src/components/sql-file/SqlFileExecutionDialog.vue index 0a148e58a..6446b5eb7 100644 --- a/src/components/sql-file/SqlFileExecutionDialog.vue +++ b/src/components/sql-file/SqlFileExecutionDialog.vue @@ -261,7 +261,7 @@ async function listenProgress(id: string, handler: (next: SqlFileProgress) => vo if (isTauriRuntime()) { return listenSqlFileProgress(handler); } - const { listenSqlFileProgressById } = await import("@/lib/http"); + const { listenSqlFileProgressById } = await import("@/lib/httpSqlFileProgress"); return listenSqlFileProgressById(id, handler); } diff --git a/src/lib/http.ts b/src/lib/http.ts index 36b02990a..90a4467a0 100644 --- a/src/lib/http.ts +++ b/src/lib/http.ts @@ -382,31 +382,10 @@ export async function listenSqlFileProgress(_handler: (progress: SqlFileProgress // For HTTP mode we need an executionId, but the tauri API does not take one. // The SSE endpoint requires a specific executionId. As a workaround we return // a no-op unlisten; callers that need progress in web mode should use - // listenSqlFileProgressById instead. + // the web-specific SQL file progress listener instead. return () => {}; } -/** - * Web-specific: listen to SQL file execution progress for a given executionId via SSE. - */ -export function listenSqlFileProgressById( - executionId: string, - handler: (progress: SqlFileProgress) => void, -): () => void { - const es = new EventSource(`/api/sql-file/progress/${executionId}`); - es.onmessage = (e) => { - const progress: SqlFileProgress = JSON.parse(e.data); - handler(progress); - if (progress.status === "done" || progress.status === "error" || progress.status === "cancelled") { - es.close(); - } - }; - es.onerror = () => { - es.close(); - }; - return () => es.close(); -} - // --------------------------------------------------------------------------- // Data Transfer // --------------------------------------------------------------------------- diff --git a/src/lib/httpSqlFileProgress.ts b/src/lib/httpSqlFileProgress.ts new file mode 100644 index 000000000..f7d072064 --- /dev/null +++ b/src/lib/httpSqlFileProgress.ts @@ -0,0 +1,19 @@ +import type { SqlFileProgress } from "./tauri"; + +export function listenSqlFileProgressById( + executionId: string, + handler: (progress: SqlFileProgress) => void, +): () => void { + const es = new EventSource(`/api/sql-file/progress/${executionId}`); + es.onmessage = (e) => { + const progress: SqlFileProgress = JSON.parse(e.data); + handler(progress); + if (progress.status === "done" || progress.status === "error" || progress.status === "cancelled") { + es.close(); + } + }; + es.onerror = () => { + es.close(); + }; + return () => es.close(); +} diff --git a/tests/apiBackendContract.test.ts b/tests/apiBackendContract.test.ts new file mode 100644 index 000000000..3f985c602 --- /dev/null +++ b/tests/apiBackendContract.test.ts @@ -0,0 +1,12 @@ +import { readFileSync } from "node:fs"; +import { strict as assert } from "node:assert"; +import test from "node:test"; + +function exportedFunctions(path: string): string[] { + const source = readFileSync(path, "utf8"); + return [...source.matchAll(/^export (?:async )?function (\w+)/gm)].map((match) => match[1]).sort(); +} + +test("Tauri and HTTP backends expose the same API functions", () => { + assert.deepEqual(exportedFunctions("src/lib/http.ts"), exportedFunctions("src/lib/tauri.ts")); +});