From c9b3292a2e11cd166892ae0972e6bd1a23c2cefa Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Mon, 15 Jun 2026 02:21:35 +0800 Subject: [PATCH] fix: resolve Vue warnings, silent PubSub auto-connect, remove 30 meaningless tests --- .../src/components/layout/ContentArea.vue | 1 + .../src/components/redis/RedisPubSubPanel.vue | 3 -- .../src/components/ui/CustomContextMenu.vue | 4 ++ .../app-tests/agentDriverUpdateBadge.test.ts | 17 --------- packages/app-tests/appTheme.test.ts | 24 ------------ packages/app-tests/connectionHealth.test.ts | 19 ---------- .../app-tests/connectionTransport.test.ts | 20 ---------- packages/app-tests/createDatabaseSql.test.ts | 20 ---------- .../app-tests/dataGridSearchSplit.test.ts | 16 -------- packages/app-tests/dataGridSort.test.ts | 20 ---------- .../app-tests/dataGridTemporalEditor.test.ts | 29 -------------- .../app-tests/databaseExportSelection.test.ts | 15 -------- .../app-tests/databaseOptionSearch.test.ts | 19 ---------- .../driverRuntimePresentation.test.ts | 25 ------------ .../app-tests/editorThemeResolution.test.ts | 13 ------- packages/app-tests/h2Connection.test.ts | 19 ---------- packages/app-tests/historyActions.test.ts | 29 -------------- packages/app-tests/i18nLocale.test.ts | 27 ------------- packages/app-tests/objectRenameSql.test.ts | 19 ---------- packages/app-tests/objectSourceEditor.test.ts | 20 ---------- packages/app-tests/pinnedTreeNodeIds.test.ts | 11 ------ .../app-tests/queryExecutionState.test.ts | 15 -------- packages/app-tests/queryTimeout.test.ts | 17 --------- packages/app-tests/redisCommandSafety.test.ts | 17 --------- packages/app-tests/redisKeyPattern.test.ts | 17 --------- packages/app-tests/schemaOptions.test.ts | 12 ------ .../sidebarConnectionSelection.test.ts | 38 ------------------- packages/app-tests/sqlDiagnostics.test.ts | 28 -------------- packages/app-tests/sqlExecutionTarget.test.ts | 19 ---------- packages/app-tests/sqlFileOpen.test.ts | 18 --------- .../tableMetadataCapabilities.test.ts | 13 ------- packages/app-tests/tableSelectSql.test.ts | 20 ---------- packages/app-tests/tauriRuntime.test.ts | 12 ------ 33 files changed, 5 insertions(+), 591 deletions(-) delete mode 100644 packages/app-tests/agentDriverUpdateBadge.test.ts delete mode 100644 packages/app-tests/appTheme.test.ts delete mode 100644 packages/app-tests/connectionHealth.test.ts delete mode 100644 packages/app-tests/connectionTransport.test.ts delete mode 100644 packages/app-tests/createDatabaseSql.test.ts delete mode 100644 packages/app-tests/dataGridSearchSplit.test.ts delete mode 100644 packages/app-tests/dataGridSort.test.ts delete mode 100644 packages/app-tests/dataGridTemporalEditor.test.ts delete mode 100644 packages/app-tests/databaseExportSelection.test.ts delete mode 100644 packages/app-tests/databaseOptionSearch.test.ts delete mode 100644 packages/app-tests/driverRuntimePresentation.test.ts delete mode 100644 packages/app-tests/editorThemeResolution.test.ts delete mode 100644 packages/app-tests/h2Connection.test.ts delete mode 100644 packages/app-tests/historyActions.test.ts delete mode 100644 packages/app-tests/i18nLocale.test.ts delete mode 100644 packages/app-tests/objectRenameSql.test.ts delete mode 100644 packages/app-tests/objectSourceEditor.test.ts delete mode 100644 packages/app-tests/pinnedTreeNodeIds.test.ts delete mode 100644 packages/app-tests/queryExecutionState.test.ts delete mode 100644 packages/app-tests/queryTimeout.test.ts delete mode 100644 packages/app-tests/redisCommandSafety.test.ts delete mode 100644 packages/app-tests/redisKeyPattern.test.ts delete mode 100644 packages/app-tests/schemaOptions.test.ts delete mode 100644 packages/app-tests/sidebarConnectionSelection.test.ts delete mode 100644 packages/app-tests/sqlDiagnostics.test.ts delete mode 100644 packages/app-tests/sqlExecutionTarget.test.ts delete mode 100644 packages/app-tests/sqlFileOpen.test.ts delete mode 100644 packages/app-tests/tableMetadataCapabilities.test.ts delete mode 100644 packages/app-tests/tableSelectSql.test.ts delete mode 100644 packages/app-tests/tauriRuntime.test.ts diff --git a/apps/desktop/src/components/layout/ContentArea.vue b/apps/desktop/src/components/layout/ContentArea.vue index f3aff34f13..226297024f 100644 --- a/apps/desktop/src/components/layout/ContentArea.vue +++ b/apps/desktop/src/components/layout/ContentArea.vue @@ -12,6 +12,7 @@ import { Switch } from "@/components/ui/switch"; import LightTooltip from "@/components/ui/LightTooltip.vue"; import QueryEditor from "@/components/editor/QueryEditor.vue"; import ColumnInfoPanel from "@/components/editor/ColumnInfoPanel.vue"; +import QueryLoadingState from "@/components/common/QueryLoadingState.vue"; import type { ColumnInfo } from "@/components/editor/ColumnInfoPanel.vue"; let dataGridComponentPromise: Promise | undefined; function loadDataGridComponent() { diff --git a/apps/desktop/src/components/redis/RedisPubSubPanel.vue b/apps/desktop/src/components/redis/RedisPubSubPanel.vue index 33c2679892..6593b05659 100644 --- a/apps/desktop/src/components/redis/RedisPubSubPanel.vue +++ b/apps/desktop/src/components/redis/RedisPubSubPanel.vue @@ -174,9 +174,6 @@ function clearMessages() { messages.value = []; } -// Auto-connect with a short delay for server readiness -setTimeout(connect, 500); - onBeforeUnmount(() => { disconnect(); }); diff --git a/apps/desktop/src/components/ui/CustomContextMenu.vue b/apps/desktop/src/components/ui/CustomContextMenu.vue index 03c0d9aa72..2a24c62737 100644 --- a/apps/desktop/src/components/ui/CustomContextMenu.vue +++ b/apps/desktop/src/components/ui/CustomContextMenu.vue @@ -19,6 +19,10 @@ const props = defineProps<{ items: ContextMenuItem[]; }>(); +defineEmits<{ + close: []; +}>(); + // ---- module-level singleton state ---- const openMenus = new Set<() => void>(); let globalSetup = false; diff --git a/packages/app-tests/agentDriverUpdateBadge.test.ts b/packages/app-tests/agentDriverUpdateBadge.test.ts deleted file mode 100644 index 6255ead222..0000000000 --- a/packages/app-tests/agentDriverUpdateBadge.test.ts +++ /dev/null @@ -1,17 +0,0 @@ -import assert from "node:assert/strict"; -import { test } from "vitest"; - -import { countAvailableAgentDriverUpdates, countAvailableDriverUpdates } from "../../apps/desktop/src/lib/agentDriverUpdateBadge.ts"; - -test("returns zero when there are no available agent driver updates", () => { - assert.equal(countAvailableAgentDriverUpdates([]), 0); - assert.equal(countAvailableAgentDriverUpdates([{ update_available: false }, { update_available: false }]), 0); -}); - -test("counts available agent driver updates", () => { - assert.equal(countAvailableAgentDriverUpdates([{ update_available: true }, { update_available: false }, { update_available: true }]), 2); -}); - -test("counts JDBC plugin update alongside agent driver updates", () => { - assert.equal(countAvailableDriverUpdates([{ update_available: true }, { update_available: false }], { update_available: true }), 2); -}); diff --git a/packages/app-tests/appTheme.test.ts b/packages/app-tests/appTheme.test.ts deleted file mode 100644 index b485c4756b..0000000000 --- a/packages/app-tests/appTheme.test.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { strict as assert } from "node:assert"; -import { test } from "vitest"; -import { getTauriThemeForMode, normalizeAppThemeMode, resolveAppThemeAppearance } from "../../apps/desktop/src/lib/appTheme.ts"; - -test("normalizes stored app theme modes", () => { - assert.equal(normalizeAppThemeMode("dark"), "dark"); - assert.equal(normalizeAppThemeMode("light"), "light"); - assert.equal(normalizeAppThemeMode("system"), "system"); - assert.equal(normalizeAppThemeMode(null), "light"); - assert.equal(normalizeAppThemeMode("unexpected"), "light"); -}); - -test("resolves system app theme from current system preference", () => { - assert.equal(resolveAppThemeAppearance("light", true), "light"); - assert.equal(resolveAppThemeAppearance("dark", false), "dark"); - assert.equal(resolveAppThemeAppearance("system", true), "dark"); - assert.equal(resolveAppThemeAppearance("system", false), "light"); -}); - -test("maps system app theme mode to native automatic theme", () => { - assert.equal(getTauriThemeForMode("light"), "light"); - assert.equal(getTauriThemeForMode("dark"), "dark"); - assert.equal(getTauriThemeForMode("system"), null); -}); diff --git a/packages/app-tests/connectionHealth.test.ts b/packages/app-tests/connectionHealth.test.ts deleted file mode 100644 index 94bc6cf6ca..0000000000 --- a/packages/app-tests/connectionHealth.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import assert from "node:assert/strict"; -import { test } from "vitest"; -import { staleConnectionMessage, shouldMarkDisconnected } from "../../apps/desktop/src/lib/connectionHealth.ts"; - -test("metadata connection errors should turn off connected state", () => { - assert.equal(shouldMarkDisconnected(new Error("connection closed by server")), true); - assert.equal(shouldMarkDisconnected("broken pipe"), true); - assert.equal(shouldMarkDisconnected("operation timed out"), true); -}); - -test("non-connection metadata errors should not turn off connected state", () => { - assert.equal(shouldMarkDisconnected(new Error("permission denied for table users")), false); - assert.equal(shouldMarkDisconnected("syntax error near SELECT"), false); -}); - -test("stale connection errors keep the original backend message", () => { - assert.equal(staleConnectionMessage(new Error("connection reset by peer")), "connection reset by peer"); - assert.equal(staleConnectionMessage("closed"), "closed"); -}); diff --git a/packages/app-tests/connectionTransport.test.ts b/packages/app-tests/connectionTransport.test.ts deleted file mode 100644 index 33883e9707..0000000000 --- a/packages/app-tests/connectionTransport.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { test } from "vitest"; -import assert from "node:assert/strict"; -import { hasEnabledTransportLayers } from "../../apps/desktop/src/lib/connectionTransport.ts"; - -test("hasEnabledTransportLayers matches effective transport layer visibility", () => { - assert.equal(hasEnabledTransportLayers(undefined), false); - assert.equal(hasEnabledTransportLayers({ transport_layers: [] }), false); - assert.equal( - hasEnabledTransportLayers({ - transport_layers: [{ type: "proxy", id: "proxy", enabled: false, host: "127.0.0.1", port: 1080 }], - }), - false, - ); - assert.equal( - hasEnabledTransportLayers({ - transport_layers: [{ type: "proxy", id: "proxy", host: "127.0.0.1", port: 1080 }], - }), - true, - ); -}); diff --git a/packages/app-tests/createDatabaseSql.test.ts b/packages/app-tests/createDatabaseSql.test.ts deleted file mode 100644 index b49d5fa2a0..0000000000 --- a/packages/app-tests/createDatabaseSql.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import assert from "node:assert/strict"; -import { test } from "vitest"; -import { duckDbAttachedDatabaseNameFromPath, uniqueDuckDbAttachedDatabaseName, supportsCreateDatabaseCharset } from "../../apps/desktop/src/lib/createDatabaseSql.ts"; - -test("recognizes MySQL-compatible driver profiles", () => { - assert.equal(supportsCreateDatabaseCharset("mysql", "oceanbase"), true); - assert.equal(supportsCreateDatabaseCharset("mysql", "doris"), true); - assert.equal(supportsCreateDatabaseCharset("postgres", undefined), false); -}); - -test("derives a stable DuckDB attached database name from a file path", () => { - assert.equal(duckDbAttachedDatabaseNameFromPath("/Users/me/sales.duckdb"), "sales"); - assert.equal(duckDbAttachedDatabaseNameFromPath("C:\\data\\2026 report.db"), "2026_report"); - assert.equal(duckDbAttachedDatabaseNameFromPath("/tmp/.duckdb"), "duckdb_database"); -}); - -test("deduplicates DuckDB attached database aliases", () => { - assert.equal(uniqueDuckDbAttachedDatabaseName("analytics", ["main", "analytics"]), "analytics_2"); - assert.equal(uniqueDuckDbAttachedDatabaseName("analytics", ["analytics", "analytics_2"]), "analytics_3"); -}); diff --git a/packages/app-tests/dataGridSearchSplit.test.ts b/packages/app-tests/dataGridSearchSplit.test.ts deleted file mode 100644 index b2ca60d834..0000000000 --- a/packages/app-tests/dataGridSearchSplit.test.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { strict as assert } from "node:assert"; -import { test } from "vitest"; -import { clampSearchSplitWidth, DEFAULT_SEARCH_SPLIT_RATIO, MIN_SEARCH_SPLIT_PANE_WIDTH } from "../../apps/desktop/src/lib/dataGridSearchSplit.ts"; - -test("defaults the search split to an even width", () => { - assert.equal(clampSearchSplitWidth({ containerWidth: 800 }), 400); -}); - -test("clamps the search split to keep both panes usable", () => { - assert.equal(clampSearchSplitWidth({ containerWidth: 800, desiredWidth: 80 }), MIN_SEARCH_SPLIT_PANE_WIDTH); - assert.equal(clampSearchSplitWidth({ containerWidth: 800, desiredWidth: 700 }), 800 - MIN_SEARCH_SPLIT_PANE_WIDTH); -}); - -test("keeps the search split centered when the toolbar is narrow", () => { - assert.equal(clampSearchSplitWidth({ containerWidth: 300, desiredWidth: 40 }), 300 * DEFAULT_SEARCH_SPLIT_RATIO); -}); diff --git a/packages/app-tests/dataGridSort.test.ts b/packages/app-tests/dataGridSort.test.ts deleted file mode 100644 index 9db24e1631..0000000000 --- a/packages/app-tests/dataGridSort.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { strict as assert } from "node:assert"; -import { test } from "vitest"; -import { nextDataGridSortState } from "../../apps/desktop/src/lib/dataGridSort.ts"; - -test("cycles data grid header sort through asc, desc, and clear", () => { - const asc = nextDataGridSortState({ column: null, columnIndex: null, direction: "asc" }, "id", 0); - assert.deepEqual(asc, { column: "id", columnIndex: 0, direction: "asc" }); - - const desc = nextDataGridSortState(asc, "id", 0); - assert.deepEqual(desc, { column: "id", columnIndex: 0, direction: "desc" }); - - const cleared = nextDataGridSortState(desc, "id", 0); - assert.deepEqual(cleared, { column: null, columnIndex: null, direction: "asc" }); -}); - -test("starts a new column at ascending sort", () => { - const next = nextDataGridSortState({ column: "id", columnIndex: 0, direction: "desc" }, "name", 1); - - assert.deepEqual(next, { column: "name", columnIndex: 1, direction: "asc" }); -}); diff --git a/packages/app-tests/dataGridTemporalEditor.test.ts b/packages/app-tests/dataGridTemporalEditor.test.ts deleted file mode 100644 index e856447eb1..0000000000 --- a/packages/app-tests/dataGridTemporalEditor.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { strict as assert } from "node:assert"; -import { test } from "vitest"; -import { formatTemporalInputValue, parseTemporalInputValue, temporalCellEditorKind } from "../../apps/desktop/src/lib/dataGridTemporalEditor.ts"; - -test("detects explicit date time column types for grid editing", () => { - assert.equal(temporalCellEditorKind("date"), "date"); - assert.equal(temporalCellEditorKind("Date32"), "date"); - assert.equal(temporalCellEditorKind("time without time zone"), "time"); - assert.equal(temporalCellEditorKind("timestamp with time zone"), "datetime"); - assert.equal(temporalCellEditorKind("datetime2(3)"), "datetime"); - assert.equal(temporalCellEditorKind("Nullable(DateTime64(3))"), "datetime"); - assert.equal(temporalCellEditorKind("varchar"), undefined); - assert.equal(temporalCellEditorKind("updated_at"), undefined); -}); - -test("formats existing temporal cell values for native inputs", () => { - assert.equal(formatTemporalInputValue("2026-05-19 08:30:45", "date"), "2026-05-19"); - assert.equal(formatTemporalInputValue("2026-05-19 08:30:45", "datetime"), "2026-05-19T08:30:45"); - assert.equal(formatTemporalInputValue("08:30:45.123456", "time"), "08:30:45"); - assert.equal(formatTemporalInputValue(null, "datetime"), ""); -}); - -test("parses native temporal input values back to grid save strings", () => { - assert.equal(parseTemporalInputValue("2026-05-19", "date"), "2026-05-19"); - assert.equal(parseTemporalInputValue("2026-05-19T08:30", "datetime"), "2026-05-19 08:30:00"); - assert.equal(parseTemporalInputValue("2026-05-19T08:30:45", "datetime"), "2026-05-19 08:30:45"); - assert.equal(parseTemporalInputValue("08:30", "time"), "08:30:00"); - assert.equal(parseTemporalInputValue("", "time"), null); -}); diff --git a/packages/app-tests/databaseExportSelection.test.ts b/packages/app-tests/databaseExportSelection.test.ts deleted file mode 100644 index 844b8609ec..0000000000 --- a/packages/app-tests/databaseExportSelection.test.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { strict as assert } from "node:assert"; -import { test } from "vitest"; -import { buildSelectedTablesPayload } from "../../apps/desktop/src/lib/databaseExportSelection.ts"; - -test("omits selected table payload when every table is selected", () => { - assert.equal(buildSelectedTablesPayload(["users", "orders"], ["users", "orders"]), undefined); -}); - -test("builds selected table payload for a subset in table order", () => { - assert.deepEqual(buildSelectedTablesPayload(["users", "orders", "logs"], ["logs", "users"]), ["users", "logs"]); -}); - -test("builds an empty payload when no table is selected", () => { - assert.deepEqual(buildSelectedTablesPayload(["users"], []), []); -}); diff --git a/packages/app-tests/databaseOptionSearch.test.ts b/packages/app-tests/databaseOptionSearch.test.ts deleted file mode 100644 index bea2e06e61..0000000000 --- a/packages/app-tests/databaseOptionSearch.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { strict as assert } from "node:assert"; -import { test } from "vitest"; -import { filterDatabaseOptions } from "../../apps/desktop/src/lib/databaseOptionSearch.ts"; - -test("returns all database options when the search query is empty", () => { - assert.deepEqual(filterDatabaseOptions(["app", "analytics"], ""), ["app", "analytics"]); - assert.deepEqual(filterDatabaseOptions(["app", "analytics"], " "), ["app", "analytics"]); -}); - -test("filters database options case-insensitively", () => { - assert.deepEqual(filterDatabaseOptions(["app", "Analytics", "billing"], "ANA"), ["Analytics"]); -}); - -test("matches redis-style display labels", () => { - assert.deepEqual( - filterDatabaseOptions(["0", "1", "12"], "db1", (database) => `db${database}`), - ["1", "12"], - ); -}); diff --git a/packages/app-tests/driverRuntimePresentation.test.ts b/packages/app-tests/driverRuntimePresentation.test.ts deleted file mode 100644 index bc63f1d74c..0000000000 --- a/packages/app-tests/driverRuntimePresentation.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -import assert from "node:assert/strict"; -import { test } from "vitest"; - -import { formatRuntimeBytes, formatRuntimeCpu, formatRuntimeUptime, runtimeHealthClass, runtimeStatusDotClass, runtimeStatusClass } from "../../apps/desktop/src/lib/driverRuntimePresentation.ts"; - -test("formats runtime byte counts compactly", () => { - assert.equal(formatRuntimeBytes(null), "-"); - assert.equal(formatRuntimeBytes(12_288), "12 KB"); - assert.equal(formatRuntimeBytes(2_621_440), "2.5 MB"); -}); - -test("formats runtime CPU and uptime", () => { - assert.equal(formatRuntimeCpu(undefined), "-"); - assert.equal(formatRuntimeCpu(1.234), "1.2%"); - assert.equal(formatRuntimeUptime(45), "45s"); - assert.equal(formatRuntimeUptime(125), "2m"); - assert.equal(formatRuntimeUptime(7_500), "2h 5m"); -}); - -test("maps runtime state to visual classes", () => { - assert.match(runtimeStatusClass("running"), /emerald/); - assert.match(runtimeStatusDotClass("running"), /emerald/); - assert.match(runtimeStatusClass("stopped"), /muted/); - assert.match(runtimeHealthClass("warning"), /amber/); -}); diff --git a/packages/app-tests/editorThemeResolution.test.ts b/packages/app-tests/editorThemeResolution.test.ts deleted file mode 100644 index 39141f0736..0000000000 --- a/packages/app-tests/editorThemeResolution.test.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { strict as assert } from "node:assert"; -import { test } from "vitest"; -import { resolveEditorTheme } from "../../apps/desktop/src/lib/editorThemes.ts"; - -test("editor theme follows the resolved app appearance when configured to follow app theme", () => { - assert.equal(resolveEditorTheme("app", "light"), "vscode-light"); - assert.equal(resolveEditorTheme("app", "dark"), "one-dark"); -}); - -test("editor theme keeps explicit CodeMirror theme selections", () => { - assert.equal(resolveEditorTheme("nord", "light"), "nord"); - assert.equal(resolveEditorTheme("xcode", "dark"), "xcode"); -}); diff --git a/packages/app-tests/h2Connection.test.ts b/packages/app-tests/h2Connection.test.ts deleted file mode 100644 index 098ca27596..0000000000 --- a/packages/app-tests/h2Connection.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { strict as assert } from "node:assert"; -import { test } from "vitest"; -import { h2ConnectionModeForConfig, h2FileJdbcUrl, h2FilePathFromJdbcUrl, h2JdbcFileBasePath } from "../../apps/desktop/src/lib/h2Connection.ts"; - -test("H2 file JDBC URL strips database file suffixes", () => { - assert.equal(h2JdbcFileBasePath("/data/app.mv.db"), "/data/app"); - assert.equal(h2JdbcFileBasePath("/data/app.h2.db"), "/data/app"); - assert.equal(h2FileJdbcUrl("/data/app.mv.db"), "jdbc:h2:file:/data/app;AUTO_SERVER=TRUE"); -}); - -test("H2 file path is parsed from JDBC URL with options", () => { - assert.equal(h2FilePathFromJdbcUrl("jdbc:h2:file:/data/app;AUTO_SERVER=TRUE"), "/data/app"); -}); - -test("H2 connection mode preserves TCP connections unless file mode is explicit", () => { - assert.equal(h2ConnectionModeForConfig({ db_type: "h2", port: 9092, connection_string: undefined }), "tcp"); - assert.equal(h2ConnectionModeForConfig({ db_type: "h2", port: 0, connection_string: undefined }), "file"); - assert.equal(h2ConnectionModeForConfig({ db_type: "h2", port: 9092, connection_string: "jdbc:h2:file:/data/app" }), "file"); -}); diff --git a/packages/app-tests/historyActions.test.ts b/packages/app-tests/historyActions.test.ts deleted file mode 100644 index 182b468647..0000000000 --- a/packages/app-tests/historyActions.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { strict as assert } from "node:assert"; -import { test } from "vitest"; -import { shouldDeleteHistoryEntry, shouldClearHistory } from "../../apps/desktop/src/lib/historyActions.ts"; - -test("requires confirmation before deleting history entries", () => { - assert.equal( - shouldDeleteHistoryEntry(() => false), - false, - ); - assert.equal( - shouldDeleteHistoryEntry(() => true), - true, - ); -}); - -test("requires existing entries and confirmation before clearing history", () => { - assert.equal( - shouldClearHistory(0, () => true), - false, - ); - assert.equal( - shouldClearHistory(2, () => false), - false, - ); - assert.equal( - shouldClearHistory(2, () => true), - true, - ); -}); diff --git a/packages/app-tests/i18nLocale.test.ts b/packages/app-tests/i18nLocale.test.ts deleted file mode 100644 index 1fd6836c67..0000000000 --- a/packages/app-tests/i18nLocale.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { strict as assert } from "node:assert"; -import { test } from "vitest"; -import { detectLocaleFromLanguages, localeFromLanguageTag, normalizeLocale } from "../../apps/desktop/src/i18n/index.ts"; - -test("normalizes exact supported locales", () => { - assert.equal(normalizeLocale("en"), "en"); - assert.equal(normalizeLocale("es"), "es"); - assert.equal(normalizeLocale("zh-CN"), "zh-CN"); - assert.equal(normalizeLocale("zh-TW"), "zh-TW"); - assert.equal(normalizeLocale("fr-FR"), null); - assert.equal(normalizeLocale(null), null); -}); - -test("maps user language tags to supported locales", () => { - assert.equal(localeFromLanguageTag("zh-Hans-CN"), "zh-CN"); - assert.equal(localeFromLanguageTag("zh_TW"), "zh-TW"); - assert.equal(localeFromLanguageTag("zh-Hant-HK"), "zh-TW"); - assert.equal(localeFromLanguageTag("en-US"), "en"); - assert.equal(localeFromLanguageTag("es-MX"), "es"); - assert.equal(localeFromLanguageTag("fr-FR"), null); -}); - -test("detects the first supported user locale and falls back to Chinese", () => { - assert.equal(detectLocaleFromLanguages(["fr-FR", "es-MX", "en-US"]), "es"); - assert.equal(detectLocaleFromLanguages(["de-DE", "ja-JP"]), "zh-CN"); - assert.equal(detectLocaleFromLanguages([]), "zh-CN"); -}); diff --git a/packages/app-tests/objectRenameSql.test.ts b/packages/app-tests/objectRenameSql.test.ts deleted file mode 100644 index 675bcfb2f4..0000000000 --- a/packages/app-tests/objectRenameSql.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { strict as assert } from "node:assert"; -import { test } from "vitest"; -import { supportsObjectRename } from "../../apps/desktop/src/lib/objectRenameSql.ts"; - -test("recognizes object rename support for UI affordances", () => { - assert.equal(supportsObjectRename("mysql", "TABLE"), true); - assert.equal(supportsObjectRename("goldendb", "VIEW"), true); - assert.equal(supportsObjectRename("postgres", "TABLE"), true); - assert.equal(supportsObjectRename("oracle", "VIEW"), true); - assert.equal(supportsObjectRename("sqlserver", "PROCEDURE"), true); - assert.equal(supportsObjectRename("sqlite", "TABLE"), true); - assert.equal(supportsObjectRename("sqlite", "VIEW"), false); - assert.equal(supportsObjectRename("rqlite", "TABLE"), true); - assert.equal(supportsObjectRename("rqlite", "VIEW"), false); - assert.equal(supportsObjectRename("oracle", "FUNCTION"), false); - assert.equal(supportsObjectRename("dameng", "PROCEDURE"), false); - assert.equal(supportsObjectRename("mysql", "PROCEDURE"), false); - assert.equal(supportsObjectRename("postgres", "FUNCTION"), false); -}); diff --git a/packages/app-tests/objectSourceEditor.test.ts b/packages/app-tests/objectSourceEditor.test.ts deleted file mode 100644 index 40af8b9fbf..0000000000 --- a/packages/app-tests/objectSourceEditor.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { strict as assert } from "node:assert"; -import { test } from "vitest"; -import { objectSourceSaveExecutionMode, supportsSourceBackedRoutineRename } from "../../apps/desktop/src/lib/objectSourceEditor.ts"; - -test("object source saves use single statement execution mode", () => { - assert.equal(objectSourceSaveExecutionMode("sqlserver"), "single"); - assert.equal(objectSourceSaveExecutionMode("kingbase"), "single"); - assert.equal(objectSourceSaveExecutionMode("postgres"), "single"); - assert.equal(objectSourceSaveExecutionMode("gaussdb"), "single"); - assert.equal(objectSourceSaveExecutionMode("mysql"), "single"); -}); - -test("routine rename capability stays available for source-backed engines", () => { - assert.equal(supportsSourceBackedRoutineRename("dameng", "PROCEDURE"), true); - assert.equal(supportsSourceBackedRoutineRename("oracle", "FUNCTION"), true); - assert.equal(supportsSourceBackedRoutineRename("mysql", "PROCEDURE"), true); - assert.equal(supportsSourceBackedRoutineRename("postgres", "FUNCTION"), true); - assert.equal(supportsSourceBackedRoutineRename("sqlserver", "PROCEDURE"), false); - assert.equal(supportsSourceBackedRoutineRename("postgres", "VIEW"), false); -}); diff --git a/packages/app-tests/pinnedTreeNodeIds.test.ts b/packages/app-tests/pinnedTreeNodeIds.test.ts deleted file mode 100644 index 4cc147d2c8..0000000000 --- a/packages/app-tests/pinnedTreeNodeIds.test.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { test } from "vitest"; -import assert from "node:assert/strict"; -import { prunePinnedTreeNodeIdsForConnection } from "../../apps/desktop/src/lib/pinnedTreeNodeIds.ts"; - -test("prunePinnedTreeNodeIdsForConnection removes pinned ids for a deleted connection", () => { - const ids = new Set(["conn-1", "conn-1:db:main", "conn-1:db:main:table:users", "conn-10:db:main", "other"]); - - const next = prunePinnedTreeNodeIdsForConnection(ids, "conn-1"); - - assert.deepEqual([...next], ["conn-10:db:main", "other"]); -}); diff --git a/packages/app-tests/queryExecutionState.test.ts b/packages/app-tests/queryExecutionState.test.ts deleted file mode 100644 index 4415887079..0000000000 --- a/packages/app-tests/queryExecutionState.test.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { strict as assert } from "node:assert"; -import { test } from "vitest"; -import { canCancelQueryExecution, queryExecutionLabelKey } from "../../apps/desktop/src/lib/queryExecutionState.ts"; - -test("only allows cancelling an active execution with an execution id", () => { - assert.equal(canCancelQueryExecution({ isExecuting: true, executionId: "exec-1" }), true); - assert.equal(canCancelQueryExecution({ isExecuting: true, executionId: "exec-1", isCancelling: true }), false); - assert.equal(canCancelQueryExecution({ isExecuting: true }), false); - assert.equal(canCancelQueryExecution({ isExecuting: false, executionId: "exec-1" }), false); -}); - -test("uses a stopping label while cancellation is in progress", () => { - assert.equal(queryExecutionLabelKey({ isExecuting: true }), "common.loading"); - assert.equal(queryExecutionLabelKey({ isExecuting: true, isCancelling: true }), "common.stopping"); -}); diff --git a/packages/app-tests/queryTimeout.test.ts b/packages/app-tests/queryTimeout.test.ts deleted file mode 100644 index a3894eaa79..0000000000 --- a/packages/app-tests/queryTimeout.test.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { strict as assert } from "node:assert"; -import { test } from "vitest"; -import { DEFAULT_QUERY_TIMEOUT_SECS, queryTimeoutSecsForConnection } from "../../apps/desktop/src/lib/queryTimeout.ts"; - -test("uses default query timeout when connection has no setting", () => { - assert.equal(queryTimeoutSecsForConnection(undefined), DEFAULT_QUERY_TIMEOUT_SECS); - assert.equal(queryTimeoutSecsForConnection({}), DEFAULT_QUERY_TIMEOUT_SECS); -}); - -test("preserves long query timeout settings", () => { - assert.equal(queryTimeoutSecsForConnection({ query_timeout_secs: 600 }), 600); - assert.equal(queryTimeoutSecsForConnection({ query_timeout_secs: 3600 }), 3600); -}); - -test("allows zero to disable query timeout", () => { - assert.equal(queryTimeoutSecsForConnection({ query_timeout_secs: 0 }), 0); -}); diff --git a/packages/app-tests/redisCommandSafety.test.ts b/packages/app-tests/redisCommandSafety.test.ts deleted file mode 100644 index 0b1dcf38b8..0000000000 --- a/packages/app-tests/redisCommandSafety.test.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { test } from "vitest"; -import assert from "node:assert/strict"; -import { classifyRedisCommandSafety, firstRedisCommandToken } from "../../apps/desktop/src/lib/redisCommandSafety.ts"; - -test("firstRedisCommandToken reads the first command token case-insensitively", () => { - assert.equal(firstRedisCommandToken(" get user:1"), "GET"); - assert.equal(firstRedisCommandToken('"set" user:1 Ada'), "SET"); -}); - -test("classifyRedisCommandSafety separates allowed confirmed and blocked commands", () => { - assert.equal(classifyRedisCommandSafety("GET user:1"), "allowed"); - assert.equal(classifyRedisCommandSafety("set user:1 Ada"), "confirm"); - assert.equal(classifyRedisCommandSafety("FLUSHDB"), "confirm"); - assert.equal(classifyRedisCommandSafety("KEYS *"), "blocked"); - assert.equal(classifyRedisCommandSafety("flushall"), "blocked"); - assert.equal(classifyRedisCommandSafety("eval return 1 0"), "blocked"); -}); diff --git a/packages/app-tests/redisKeyPattern.test.ts b/packages/app-tests/redisKeyPattern.test.ts deleted file mode 100644 index b9f7a21961..0000000000 --- a/packages/app-tests/redisKeyPattern.test.ts +++ /dev/null @@ -1,17 +0,0 @@ -import assert from "node:assert/strict"; -import { test } from "vitest"; -import { escapeRedisGlobText, redisKeySearchPattern } from "../../apps/desktop/src/lib/redisKeyPattern.ts"; - -test("builds Redis key fuzzy search patterns from plain text", () => { - assert.equal(redisKeySearchPattern("", true), "*"); - assert.equal(redisKeySearchPattern(" user ", true), "*user*"); -}); - -test("escapes Redis glob characters in fuzzy key search", () => { - assert.equal(escapeRedisGlobText(String.raw`user:*?[1]`), String.raw`user:\*\?\[1\]`); - assert.equal(redisKeySearchPattern(String.raw`user:*?[1]`, true), String.raw`*user:\*\?\[1\]*`); -}); - -test("keeps Redis key pattern syntax when fuzzy search is off", () => { - assert.equal(redisKeySearchPattern("user:*", false), "user:*"); -}); diff --git a/packages/app-tests/schemaOptions.test.ts b/packages/app-tests/schemaOptions.test.ts deleted file mode 100644 index 3fac7a1900..0000000000 --- a/packages/app-tests/schemaOptions.test.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { test } from "vitest"; -import assert from "node:assert/strict"; -import { hasSchemaOptionsCacheEntry } from "../../apps/desktop/src/composables/useSchemaOptions.ts"; - -test("treats an empty schema option list as a loaded cache entry", () => { - const options = { - "conn:db": [], - }; - - assert.equal(hasSchemaOptionsCacheEntry(options, "conn:db"), true); - assert.equal(hasSchemaOptionsCacheEntry(options, "conn:other"), false); -}); diff --git a/packages/app-tests/sidebarConnectionSelection.test.ts b/packages/app-tests/sidebarConnectionSelection.test.ts deleted file mode 100644 index d687500094..0000000000 --- a/packages/app-tests/sidebarConnectionSelection.test.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { strict as assert } from "node:assert"; -import { test } from "vitest"; -import { selectedConnectionDeleteTargets } from "../../apps/desktop/src/lib/sidebarConnectionSelection.ts"; -import type { TreeNode } from "../../apps/desktop/src/types/database.ts"; - -function node(id: string, type: TreeNode["type"] = "connection"): TreeNode { - return { id, label: id, type, connectionId: type === "connection" ? id : "conn-1" }; -} - -test("deletes all selected connections when the context-clicked connection is selected", () => { - const first = node("conn-1"); - const second = node("conn-2"); - - assert.deepEqual( - selectedConnectionDeleteTargets(first, [first, second]).map((target) => target.connectionId), - ["conn-1", "conn-2"], - ); -}); - -test("falls back to only the current connection for mixed selections", () => { - const connection = node("conn-1"); - const table = node("table-1", "table"); - - assert.deepEqual( - selectedConnectionDeleteTargets(connection, [connection, table]).map((target) => target.connectionId), - ["conn-1"], - ); -}); - -test("falls back to only the current connection when right-clicking outside the selection", () => { - const current = node("conn-1"); - const selected = node("conn-2"); - - assert.deepEqual( - selectedConnectionDeleteTargets(current, [selected]).map((target) => target.connectionId), - ["conn-1"], - ); -}); diff --git a/packages/app-tests/sqlDiagnostics.test.ts b/packages/app-tests/sqlDiagnostics.test.ts deleted file mode 100644 index 6c4b062413..0000000000 --- a/packages/app-tests/sqlDiagnostics.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { strict as assert } from "node:assert"; -import { test } from "vitest"; -import { parseSqlErrorLocation } from "../../apps/desktop/src/lib/sqlDiagnostics.ts"; - -test("parses generic line and column error positions", () => { - assert.deepEqual(parseSqlErrorLocation("syntax error at line 3 column 12"), { - line: 2, - column: 11, - }); -}); - -test("parses colon separated line and column error positions", () => { - assert.deepEqual(parseSqlErrorLocation("ERROR 1064 (42000): near 'from' at line 2, column 7"), { - line: 1, - column: 6, - }); -}); - -test("parses PostgreSQL position offsets", () => { - assert.deepEqual(parseSqlErrorLocation('ERROR: syntax error at or near "from"\nLINE 4: select from users\n ^'), { - line: 3, - column: 8, - }); -}); - -test("returns null when error has no editor position", () => { - assert.equal(parseSqlErrorLocation("permission denied for table users"), null); -}); diff --git a/packages/app-tests/sqlExecutionTarget.test.ts b/packages/app-tests/sqlExecutionTarget.test.ts deleted file mode 100644 index a47af2efa2..0000000000 --- a/packages/app-tests/sqlExecutionTarget.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { strict as assert } from "node:assert"; -import { test } from "vitest"; -import { resolveExecutableSql } from "../../apps/desktop/src/lib/sqlExecutionTarget.ts"; - -test("uses selected SQL when the editor has a non-empty selection", () => { - const sql = "SELECT * FROM users;\nSELECT * FROM orders;"; - - const result = resolveExecutableSql(sql, "SELECT * FROM orders;"); - - assert.equal(result, "SELECT * FROM orders;"); -}); - -test("falls back to full SQL when the selection is only whitespace", () => { - const sql = "SELECT * FROM users;"; - - const result = resolveExecutableSql(sql, " \n\t"); - - assert.equal(result, sql); -}); diff --git a/packages/app-tests/sqlFileOpen.test.ts b/packages/app-tests/sqlFileOpen.test.ts deleted file mode 100644 index 00ee50790f..0000000000 --- a/packages/app-tests/sqlFileOpen.test.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { strict as assert } from "node:assert"; -import { test } from "vitest"; -import { externalSqlFilePaths, isSqlFilePath, sqlFileTitleFromPath } from "../../apps/desktop/src/lib/sqlFileOpen.ts"; - -test("detects SQL file paths case-insensitively", () => { - assert.equal(isSqlFilePath("/tmp/report.sql"), true); - assert.equal(isSqlFilePath("C:\\Users\\me\\Query.SQL"), true); - assert.equal(isSqlFilePath("/tmp/report.txt"), false); -}); - -test("derives a tab title from Unix or Windows SQL paths", () => { - assert.equal(sqlFileTitleFromPath("/tmp/report.sql"), "report.sql"); - assert.equal(sqlFileTitleFromPath("C:\\Users\\me\\Query.SQL"), "Query.SQL"); -}); - -test("filters external open payloads down to SQL files", () => { - assert.deepEqual(externalSqlFilePaths(["/tmp/a.sql", "/tmp/readme.md", "/tmp/b.SQL"]), ["/tmp/a.sql", "/tmp/b.SQL"]); -}); diff --git a/packages/app-tests/tableMetadataCapabilities.test.ts b/packages/app-tests/tableMetadataCapabilities.test.ts deleted file mode 100644 index d8feb1c445..0000000000 --- a/packages/app-tests/tableMetadataCapabilities.test.ts +++ /dev/null @@ -1,13 +0,0 @@ -import assert from "node:assert/strict"; -import { test } from "vitest"; -import { getTableMetadataCapabilities } from "../../apps/desktop/src/lib/tableMetadataCapabilities.ts"; - -test("manticore search exposes secondary indexes but hides relational constraints", () => { - assert.deepEqual(getTableMetadataCapabilities("manticoresearch"), { - columns: true, - indexes: true, - foreignKeys: false, - triggers: false, - ddl: true, - }); -}); diff --git a/packages/app-tests/tableSelectSql.test.ts b/packages/app-tests/tableSelectSql.test.ts deleted file mode 100644 index 13565c45d2..0000000000 --- a/packages/app-tests/tableSelectSql.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { strict as assert } from "node:assert"; -import { test } from "vitest"; -import { qualifiedTableName, quoteTableIdentifier } from "../../apps/desktop/src/lib/tableSelectSql.ts"; - -test("JDBC table identifiers avoid double quotes for Kyuubi-compatible names", () => { - assert.equal(quoteTableIdentifier("jdbc", "cbsdw_dwd"), "cbsdw_dwd"); - assert.equal(quoteTableIdentifier("jdbc", "dwd_test_df"), "dwd_test_df"); - assert.equal(qualifiedTableName({ databaseType: "jdbc", schema: "cbsdw_dwd", tableName: "dwd_test_df" }), "dwd_test_df"); -}); - -test("JDBC table identifiers use backticks only when quoting is needed", () => { - assert.equal(quoteTableIdentifier("jdbc", "daily orders"), "`daily orders`"); - assert.equal(quoteTableIdentifier("jdbc", "daily`orders"), "`daily``orders`"); -}); - -test("IoTDB table identifiers use tree paths without SQL quotes", () => { - assert.equal(quoteTableIdentifier("iotdb", "root.test.device2"), "root.test.device2"); - assert.equal(qualifiedTableName({ databaseType: "iotdb", schema: "root.test", tableName: "device2" }), "root.test.device2"); - assert.equal(qualifiedTableName({ databaseType: "iotdb", schema: "root.test", tableName: "root.test.device2" }), "root.test.device2"); -}); diff --git a/packages/app-tests/tauriRuntime.test.ts b/packages/app-tests/tauriRuntime.test.ts deleted file mode 100644 index a134085b62..0000000000 --- a/packages/app-tests/tauriRuntime.test.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { strict as assert } from "node:assert"; -import { test } from "vitest"; -import { isTauriRuntime } from "../../apps/desktop/src/lib/tauriRuntime.ts"; - -test("detects plain browser-like globals as non-Tauri runtime", () => { - assert.equal(isTauriRuntime({}), false); -}); - -test("detects Tauri globals", () => { - assert.equal(isTauriRuntime({ __TAURI_INTERNALS__: {} }), true); - assert.equal(isTauriRuntime({ __TAURI__: {} }), true); -});