chore(repo): move app tests under packages

This commit is contained in:
t8y2 2026-05-18 02:23:58 +08:00
parent 84018eae89
commit 5dabdb3985
100 changed files with 125 additions and 125 deletions

View File

@ -20,7 +20,7 @@ jobs:
node-version: 22
- name: Generate changelog JSON
run: node scripts/sync-changelog.mjs
run: node .github/scripts/sync-changelog.mjs
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}

View File

@ -20,8 +20,8 @@
"check": "oxfmt --check \"src/**/*.{ts,vue}\" && pnpm lint && vue-tsc --noEmit && pnpm test",
"lint": "oxlint --vue-plugin src",
"fmt": "oxfmt \"src/**/*.{ts,vue}\"",
"test": "tsx --test tests/*.test.ts",
"test:coverage": "c8 --reporter=lcov --reporter=text tsx --test tests/*.test.ts",
"test": "tsx --test packages/app-tests/*.test.ts",
"test:coverage": "c8 --reporter=lcov --reporter=text tsx --test packages/app-tests/*.test.ts",
"preview": "vite preview",
"tauri": "tauri",
"prepare": "husky"

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { shouldSuppressRepeatedActivation, tryStartExclusiveActivation } from "../src/lib/actionActivation.ts";
import { shouldSuppressRepeatedActivation, tryStartExclusiveActivation } from "../../src/lib/actionActivation.ts";
test("allows the first activation", () => {
const guard = {};

View File

@ -1,6 +1,6 @@
import assert from "node:assert/strict";
import test from "node:test";
import { showAgentDriverInstallHint } from "../src/lib/agentDriverInstallHint.ts";
import { showAgentDriverInstallHint } from "../../src/lib/agentDriverInstallHint.ts";
test("hides the agent driver install hint when the selected driver is installed", () => {
assert.equal(showAgentDriverInstallHint("informix", [{ db_type: "informix", installed: true }]), false);

View File

@ -1,7 +1,7 @@
import assert from "node:assert/strict";
import test from "node:test";
import { countAvailableAgentDriverUpdates } from "../src/lib/agentDriverUpdateBadge.ts";
import { countAvailableAgentDriverUpdates } from "../../src/lib/agentDriverUpdateBadge.ts";
test("returns zero when there are no available agent driver updates", () => {
assert.equal(countAvailableAgentDriverUpdates([]), 0);

View File

@ -1,8 +1,8 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { buildAiAgentPlan } from "../src/lib/aiAgentPlan.ts";
import type { AiAction, AiAssistantMode } from "../src/lib/ai.ts";
import type { ConnectionConfig } from "../src/types/database.ts";
import { buildAiAgentPlan } from "../../src/lib/aiAgentPlan.ts";
import type { AiAction, AiAssistantMode } from "../../src/lib/ai.ts";
import type { ConnectionConfig } from "../../src/types/database.ts";
function conn(overrides: Partial<ConnectionConfig> = {}): ConnectionConfig {
return {

View File

@ -1,7 +1,7 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { buildAiAgentStepItems } from "../src/lib/aiAgentStepPresentation.ts";
import type { AiAgentPlan } from "../src/lib/aiAgentPlan.ts";
import { buildAiAgentStepItems } from "../../src/lib/aiAgentStepPresentation.ts";
import type { AiAgentPlan } from "../../src/lib/aiAgentPlan.ts";
test("presents auto-execute agent plans as completed generation, safety, and execution steps", () => {
const plan: AiAgentPlan = {

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import type { AiContext } from "../src/lib/ai.ts";
import type { AiContext } from "../../src/lib/ai.ts";
class MemoryStorage {
private values = new Map<string, string>();
@ -27,7 +27,7 @@ Object.defineProperty(globalThis, "localStorage", {
configurable: true,
});
const { buildSystemPrompt } = await import("../src/lib/ai.ts");
const { buildSystemPrompt } = await import("../../src/lib/ai.ts");
function context(overrides: Partial<AiContext> = {}): AiContext {
return {

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import type { AiAction, AiAssistantMode, AiContext } from "../src/lib/ai.ts";
import type { AiAction, AiAssistantMode, AiContext } from "../../src/lib/ai.ts";
class MemoryStorage {
private values = new Map<string, string>();
@ -27,7 +27,7 @@ Object.defineProperty(globalThis, "localStorage", {
configurable: true,
});
const { buildSystemPrompt } = await import("../src/lib/ai.ts");
const { buildSystemPrompt } = await import("../../src/lib/ai.ts");
function baseContext(overrides: Partial<AiContext> = {}): AiContext {
return {

View File

@ -1,7 +1,7 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import type { AiAction } from "../src/lib/ai.ts";
import { AI_SKILL_DEFINITIONS, aiSkillForAction } from "../src/lib/aiSkills.ts";
import type { AiAction } from "../../src/lib/ai.ts";
import { AI_SKILL_DEFINITIONS, aiSkillForAction } from "../../src/lib/aiSkills.ts";
const actions: AiAction[] = ["generate", "explain", "optimize", "fix", "convert", "sampleData"];

View File

@ -4,8 +4,8 @@ import {
classifyAiSqlExecution,
classifyConnectionEnvironment,
shouldAttemptAiAutoExecute,
} from "../src/lib/aiSqlExecutionPolicy.ts";
import type { ConnectionConfig } from "../src/types/database.ts";
} from "../../src/lib/aiSqlExecutionPolicy.ts";
import type { ConnectionConfig } from "../../src/types/database.ts";
function conn(overrides: Partial<ConnectionConfig> = {}): ConnectionConfig {
return {

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { formatAiTableMention, parseAiTableMentions } from "../src/lib/aiTableMentions.ts";
import { formatAiTableMention, parseAiTableMentions } from "../../src/lib/aiTableMentions.ts";
test("parses simple and schema-qualified AI table mentions", () => {
assert.deepEqual(parseAiTableMentions("show @users and join @public.orders"), [

View File

@ -4,7 +4,7 @@ import {
getTauriThemeForMode,
normalizeAppThemeMode,
resolveAppThemeAppearance,
} from "../src/lib/appTheme.ts";
} from "../../src/lib/appTheme.ts";
test("normalizes stored app theme modes", () => {
assert.equal(normalizeAppThemeMode("dark"), "dark");

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { displayCellValue } from "../src/lib/cellValue.ts";
import { displayCellValue } from "../../src/lib/cellValue.ts";
test("displayCellValue returns NULL for null", () => {
assert.equal(displayCellValue(null), "NULL");

View File

@ -6,7 +6,7 @@ import {
resolveColumnFormatter,
normalizeColumnFormatter,
type ColumnFormatterConfig,
} from "../src/lib/columnFormatter.ts";
} from "../../src/lib/columnFormatter.ts";
test("formats unix timestamps in seconds, milliseconds, and auto mode", () => {
assert.equal(

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { encryptConfig, decryptConfig, isEncryptedConfig } from "../src/lib/configCrypto.ts";
import { encryptConfig, decryptConfig, isEncryptedConfig } from "../../src/lib/configCrypto.ts";
test("encrypts and decrypts config round-trip", async () => {
const original = JSON.stringify([{ id: "1", name: "test", password: "secret123" }]);

View File

@ -1,6 +1,6 @@
import assert from "node:assert/strict";
import test from "node:test";
import { staleConnectionMessage, shouldMarkDisconnected } from "../src/lib/connectionHealth.ts";
import { staleConnectionMessage, shouldMarkDisconnected } from "../../src/lib/connectionHealth.ts";
test("metadata connection errors should turn off connected state", () => {
assert.equal(shouldMarkDisconnected(new Error("connection closed by server")), true);

View File

@ -1,7 +1,7 @@
import test from "node:test";
import assert from "node:assert/strict";
import type { ConnectionConfig } from "../src/types/database.ts";
import { connectionDriverLabel, connectionEndpointLabel, connectionIconType, connectionOptionSubtitle } from "../src/lib/connectionPresentation.ts";
import type { ConnectionConfig } from "../../src/types/database.ts";
import { connectionDriverLabel, connectionEndpointLabel, connectionIconType, connectionOptionSubtitle } from "../../src/lib/connectionPresentation.ts";
const baseConnection: ConnectionConfig = {
id: "conn-1",

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { parseConnectionUrl } from "../src/lib/connectionUrl.ts";
import { parseConnectionUrl } from "../../src/lib/connectionUrl.ts";
test("parses postgres connection URLs", () => {
assert.deepEqual(parseConnectionUrl("postgresql://alice:secret@db.example.com:5433/app?sslmode=require"), {

View File

@ -1,6 +1,6 @@
import test from "node:test";
import assert from "node:assert/strict";
import { connectionUrlPlaceholder } from "../src/lib/connectionPresentation.ts";
import { connectionUrlPlaceholder } from "../../src/lib/connectionPresentation.ts";
const expected: Record<string, string> = {
mysql: "mysql://user:password@host:port/database",

View File

@ -1,6 +1,6 @@
import assert from "node:assert/strict";
import test from "node:test";
import { buildCreateDatabaseSql, supportsCreateDatabaseCharset } from "../src/lib/createDatabaseSql.ts";
import { buildCreateDatabaseSql, supportsCreateDatabaseCharset } from "../../src/lib/createDatabaseSql.ts";
test("builds MySQL create database SQL with charset and collation", () => {
assert.equal(

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { compareDataRows, generateDataSyncSql } from "../src/lib/dataCompare.ts";
import { compareDataRows, generateDataSyncSql } from "../../src/lib/dataCompare.ts";
test("compares rows by primary key and reports added, removed, and modified rows", () => {
const diff = compareDataRows({

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { calculateDataGridColumnWidth, DATA_GRID_HEADER_CONTROL_WIDTH } from "../src/lib/dataGridColumnWidth.ts";
import { calculateDataGridColumnWidth, DATA_GRID_HEADER_CONTROL_WIDTH } from "../../src/lib/dataGridColumnWidth.ts";
test("reserves header control space when auto-sizing a column from the header", () => {
const width = calculateDataGridColumnWidth({

View File

@ -2,8 +2,8 @@ import { strict as assert } from "node:assert";
import test from "node:test";
import { computed, nextTick, ref } from "vue";
import { createPinia, setActivePinia } from "pinia";
import { useDataGridEditor } from "../src/composables/useDataGridEditor.ts";
import type { ColumnInfo } from "../src/types/database.ts";
import { useDataGridEditor } from "../../src/composables/useDataGridEditor.ts";
import type { ColumnInfo } from "../../src/types/database.ts";
type CellValue = string | number | boolean | null;

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { dataGridHeaderContentWidth, scrollbarGutterWidth } from "../src/lib/dataGridScrollGutter.ts";
import { dataGridHeaderContentWidth, scrollbarGutterWidth } from "../../src/lib/dataGridScrollGutter.ts";
test("calculates scrollbar gutter from element dimensions", () => {
assert.equal(scrollbarGutterWidth({ offsetWidth: 1000, clientWidth: 985 }), 15);

View File

@ -7,8 +7,8 @@ import {
normalizeDataGridSaveError,
formatGridSqlLiteral,
validateDataGridSave,
} from "../src/lib/dataGridSql.ts";
import { DBX_NEO4J_ELEMENT_ID_COLUMN } from "../src/lib/tableEditing.ts";
} from "../../src/lib/dataGridSql.ts";
import { DBX_NEO4J_ELEMENT_ID_COLUMN } from "../../src/lib/tableEditing.ts";
test("builds SQL Server grid save statements with schema and bracket quoting", () => {
const statements = buildDataGridSaveStatements({

View File

@ -7,7 +7,7 @@ import {
transposeFieldWidth,
transposeScrollLeftForRecord,
visibleTransposeRecordWindow,
} from "../src/lib/dataGridTranspose.ts";
} from "../../src/lib/dataGridTranspose.ts";
test("row number double click opens transpose for a row", () => {
assert.deepEqual(nextTransposeState(false, null, 2), {

View File

@ -18,7 +18,7 @@ import {
supportsTransfer,
usesPostgresLikeStructureCopy,
usesTreeSchemaMode,
} from "../src/lib/databaseCapabilities.ts";
} from "../../src/lib/databaseCapabilities.ts";
test("treats Trino catalogs as schema tree roots", () => {
assert.equal(TREE_SCHEMA_TYPES.has("trino"), true);

View File

@ -7,7 +7,7 @@ import {
buildDatabaseSqlExport,
buildInsertStatements,
formatSqlLiteral,
} from "../src/lib/databaseExport.ts";
} from "../../src/lib/databaseExport.ts";
test("formats SQL literals for exported INSERT statements", () => {
assert.equal(formatSqlLiteral(null), "NULL");

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { buildSelectedTablesPayload } from "../src/lib/databaseExportSelection.ts";
import { buildSelectedTablesPayload } from "../../src/lib/databaseExportSelection.ts";
test("omits selected table payload when every table is selected", () => {
assert.equal(buildSelectedTablesPayload(["users", "orders"], ["users", "orders"]), undefined);

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { filterDatabaseOptions } from "../src/lib/databaseOptionSearch.ts";
import { filterDatabaseOptions } from "../../src/lib/databaseOptionSearch.ts";
test("returns all database options when the search query is empty", () => {
assert.deepEqual(filterDatabaseOptions(["app", "analytics"], ""), ["app", "analytics"]);

View File

@ -1,11 +1,11 @@
import test from "node:test";
import assert from "node:assert/strict";
import type { ColumnInfo } from "../src/types/database.ts";
import type { ColumnInfo } from "../../src/types/database.ts";
import {
buildDatabaseSearchSql,
buildSearchResultWhere,
findMatchedSearchColumns,
} from "../src/lib/databaseSearch.ts";
} from "../../src/lib/databaseSearch.ts";
function col(name: string, dataType: string, primary = false): ColumnInfo {
return {

View File

@ -1,6 +1,6 @@
import assert from "node:assert/strict";
import test from "node:test";
import { buildDatabaseTreeNodes } from "../src/lib/databaseTree.ts";
import { buildDatabaseTreeNodes } from "../../src/lib/databaseTree.ts";
test("设置默认库后侧边栏数据库树仍保留全部数据库", () => {
const nodes = buildDatabaseTreeNodes("conn-1", [

View File

@ -1,6 +1,6 @@
import assert from "node:assert/strict";
import test from "node:test";
import { isDefaultDatabase, resolveDefaultDatabase } from "../src/lib/defaultDatabase.ts";
import { isDefaultDatabase, resolveDefaultDatabase } from "../../src/lib/defaultDatabase.ts";
test("优先使用连接上已保存的默认数据库", () => {
assert.equal(resolveDefaultDatabase({ database: "analytics" }, ["app", "analytics"]), "analytics");

View File

@ -1,12 +1,12 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { buildEngineeringDiagram } from "../src/lib/engineeringDiagram.ts";
import { buildEngineeringDiagram } from "../../src/lib/engineeringDiagram.ts";
import {
buildEngineeringDiagramSvg,
buildTableDiagramSvg,
diagramSvgFileName,
} from "../src/lib/diagramSvgExport.ts";
import { buildDiagramRelationships, type DiagramTable } from "../src/lib/erDiagram.ts";
} from "../../src/lib/diagramSvgExport.ts";
import { buildDiagramRelationships, type DiagramTable } from "../../src/lib/erDiagram.ts";
const tables: DiagramTable[] = [
{

View File

@ -4,7 +4,7 @@ import {
clampDiagramZoom,
zoomFromGestureScale,
zoomFromWheelDelta,
} from "../src/lib/diagramZoom.ts";
} from "../../src/lib/diagramZoom.ts";
test("clamps diagram zoom to supported bounds", () => {
assert.equal(clampDiagramZoom(0.2), 0.6);

View File

@ -1,8 +1,8 @@
import { readFileSync } from "node:fs";
import { strict as assert } from "node:assert";
import test from "node:test";
import appPackage from "../package.json" with { type: "json" };
import downloadLinks from "../docs/lib/downloadLinks.ts";
import appPackage from "../../package.json" with { type: "json" };
import downloadLinks from "../../docs/lib/downloadLinks.ts";
const { createInstallOptions } = downloadLinks;

View File

@ -1,7 +1,7 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { buildEngineeringDiagram } from "../src/lib/engineeringDiagram.ts";
import type { DiagramRelationship, DiagramTable } from "../src/lib/erDiagram.ts";
import { buildEngineeringDiagram } from "../../src/lib/engineeringDiagram.ts";
import type { DiagramRelationship, DiagramTable } from "../../src/lib/erDiagram.ts";
const tables: DiagramTable[] = [
{

View File

@ -4,7 +4,7 @@ import {
buildDiagramRelationships,
filterDiagramTables,
layoutDiagramTables,
} from "../src/lib/erDiagram.ts";
} from "../../src/lib/erDiagram.ts";
test("builds relationships only between tables in the diagram", () => {
const relationships = buildDiagramRelationships([

View File

@ -5,7 +5,7 @@ import {
flattenExplainPlanNodes,
parseExplainResult,
supportsExplainPlan,
} from "../src/lib/explainPlan.ts";
} from "../../src/lib/explainPlan.ts";
test("builds PostgreSQL JSON explain SQL from a selected query", () => {
const result = buildExplainSql("postgres", " select * from users where id = 1; ");

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { analyzeFieldLineage, identifierInSql, summarizeLineageCounts } from "../src/lib/fieldLineage.ts";
import { analyzeFieldLineage, identifierInSql, summarizeLineageCounts } from "../../src/lib/fieldLineage.ts";
test("detects outgoing and incoming foreign key lineage as certain", () => {
const result = analyzeFieldLineage({

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { matchesRowStatusFilter, rowStatusFilterAfterAddingRow, type RowStatus } from "../src/lib/gridRowStatus.ts";
import { matchesRowStatusFilter, rowStatusFilterAfterAddingRow, type RowStatus } from "../../src/lib/gridRowStatus.ts";
const statuses: RowStatus[] = ["clean", "edited", "new", "deleted"];

View File

@ -8,7 +8,7 @@ import {
formatSelectionAsTsv,
isCellInSelection,
normalizeSelectionRange,
} from "../src/lib/gridSelection.ts";
} from "../../src/lib/gridSelection.ts";
test("normalizes a dragged cell range in either direction", () => {
const range = normalizeSelectionRange(

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { shouldDeleteHistoryEntry, shouldClearHistory } from "../src/lib/historyActions.ts";
import { shouldDeleteHistoryEntry, shouldClearHistory } from "../../src/lib/historyActions.ts";
test("requires confirmation before deleting history entries", () => {
assert.equal(shouldDeleteHistoryEntry(() => false), false);

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { resolveHistoryActivityKind } from "../src/lib/historyActivityKind.ts";
import { resolveHistoryActivityKind } from "../../src/lib/historyActivityKind.ts";
test("legacy INSERT history entries are treated as data changes", () => {
assert.equal(

View File

@ -4,7 +4,7 @@ import {
buildHistoryAiAnalysisPrompt,
canRollbackHistoryEntry,
type HistoryAiAnalysisEntry,
} from "../src/lib/historyAiAnalysis.ts";
} from "../../src/lib/historyAiAnalysis.ts";
const baseEntry: HistoryAiAnalysisEntry = {
id: "h1",

View File

@ -4,7 +4,7 @@ import {
HISTORY_ROW_HEIGHT,
HISTORY_SCROLL_BUFFER,
shouldVirtualizeHistory,
} from "../src/lib/historyVirtualList.ts";
} from "../../src/lib/historyVirtualList.ts";
test("history list virtualizes every non-empty result set", () => {
assert.equal(shouldVirtualizeHistory(0), false);

View File

@ -8,8 +8,8 @@ import {
isFocusSearchShortcut,
isObjectSourceSaveShortcutTarget,
isSaveShortcut,
} from "../src/lib/keyboardShortcuts.ts";
import { shortcutToCodeMirrorKey } from "../src/lib/shortcutRegistry.ts";
} from "../../src/lib/keyboardShortcuts.ts";
import { shortcutToCodeMirrorKey } from "../../src/lib/shortcutRegistry.ts";
test("matches Cmd+Enter for SQL execution", () => {
assert.equal(isExecuteSqlShortcut({ key: "Enter", metaKey: true }), true);

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { formatMarkdownTable } from "../src/lib/markdownTable.ts";
import { formatMarkdownTable } from "../../src/lib/markdownTable.ts";
test("escapes markdown table pipes and normalizes newlines", () => {
const markdown = formatMarkdownTable({

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { mongoDocumentsToQueryResult, parseMongoFindCommand } from "../src/lib/mongoShellCommand.ts";
import { mongoDocumentsToQueryResult, parseMongoFindCommand } from "../../src/lib/mongoShellCommand.ts";
test("parseMongoFindCommand parses db collection find with an empty JSON filter", () => {
assert.deepEqual(parseMongoFindCommand("db.users.find({})"), {

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { buildRenameObjectSql, supportsObjectRename } from "../src/lib/objectRenameSql.ts";
import { buildRenameObjectSql, supportsObjectRename } from "../../src/lib/objectRenameSql.ts";
test("builds MySQL table and view rename statements", () => {
assert.equal(

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { buildExecutableObjectSourceSql, objectSourceSaveExecutionMode } from "../src/lib/objectSourceEditor.ts";
import { buildExecutableObjectSourceSql, objectSourceSaveExecutionMode } from "../../src/lib/objectSourceEditor.ts";
test("SQL Server edited source saves as ALTER", () => {
const sql = buildExecutableObjectSourceSql({

View File

@ -1,7 +1,7 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { restoreOpenTabsState, serializeOpenTabs } from "../src/lib/openTabsPersistence.ts";
import type { QueryTab } from "../src/types/database.ts";
import { restoreOpenTabsState, serializeOpenTabs } from "../../src/lib/openTabsPersistence.ts";
import type { QueryTab } from "../../src/types/database.ts";
function queryTab(overrides: Partial<QueryTab> = {}): QueryTab {
return {

View File

@ -1,7 +1,7 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { applyPinnedTreeNodeState, orderPinnedFirst } from "../src/lib/pinnedItems.ts";
import type { TreeNode } from "../src/types/database.ts";
import { applyPinnedTreeNodeState, orderPinnedFirst } from "../../src/lib/pinnedItems.ts";
import type { TreeNode } from "../../src/types/database.ts";
test("orders pinned items before unpinned items without changing relative order", () => {
const items = [

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { canCancelQueryExecution, queryExecutionLabelKey } from "../src/lib/queryExecutionState.ts";
import { canCancelQueryExecution, queryExecutionLabelKey } from "../../src/lib/queryExecutionState.ts";
test("only allows cancelling an active execution with an execution id", () => {
assert.equal(canCancelQueryExecution({ isExecuting: true, executionId: "exec-1" }), true);

View File

@ -4,7 +4,7 @@ import {
buildCountQuerySql,
buildPaginatedQuerySql,
buildQueryPaginationExecutionPlan,
} from "../src/lib/queryResultPagination.ts";
} from "../../src/lib/queryResultPagination.ts";
test("wraps a single select query with limit and offset", () => {
const result = buildPaginatedQuerySql("SELECT id, name FROM users;", "postgres", 100, 200);

View File

@ -1,6 +1,6 @@
import assert from "node:assert/strict";
import test from "node:test";
import { buildSortedQuerySql } from "../src/lib/queryResultSort.ts";
import { buildSortedQuerySql } from "../../src/lib/queryResultSort.ts";
test("wraps a single select query with outer order by", () => {
const result = buildSortedQuerySql("SELECT id, name FROM users;", "postgres", ["id", "name"], 1, "name", "asc");

View File

@ -1,7 +1,7 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { createPinia, setActivePinia } from "pinia";
import { useQueryStore } from "../src/stores/queryStore.ts";
import { useQueryStore } from "../../src/stores/queryStore.ts";
test("setErrorResult stops loading and shows the error result", () => {
setActivePinia(createPinia());

View File

@ -1,6 +1,6 @@
import test from "node:test";
import assert from "node:assert/strict";
import { classifyRedisCommandSafety, firstRedisCommandToken } from "../src/lib/redisCommandSafety.ts";
import { classifyRedisCommandSafety, firstRedisCommandToken } from "../../src/lib/redisCommandSafety.ts";
test("firstRedisCommandToken reads the first command token case-insensitively", () => {
assert.equal(firstRedisCommandToken(" get user:1"), "GET");

View File

@ -6,8 +6,8 @@ import {
collectExpandedGroupIds,
flattenVisibleRedisKeyTree,
type RedisKeyTreeNode,
} from "../src/lib/redisKeyTree.ts";
import type { RedisKeyInfo } from "../src/lib/api.ts";
} from "../../src/lib/redisKeyTree.ts";
import type { RedisKeyInfo } from "../../src/lib/api.ts";
function makeKey(key_display: string, key_raw: string, key_type = "string", ttl = -1): RedisKeyInfo {
return { key_display, key_raw, key_type, ttl };

View File

@ -6,7 +6,7 @@ import {
formatRedisMemberDetail,
getRedisMemberSelectionKey,
highlightRedisJsonDetail,
} from "../src/lib/redisValuePresentation.ts";
} from "../../src/lib/redisValuePresentation.ts";
test("formats JSON object strings for Redis member details", () => {
const detail = formatRedisMemberDetail('{"id":1,"name":"Ada","tags":["dbx","redis"]}');

View File

@ -1,7 +1,7 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { diffForeignKeys, diffIndexes, generateSyncSql, type TableDiff } from "../src/lib/schemaDiff.ts";
import type { ForeignKeyInfo, IndexInfo } from "../src/types/database.ts";
import { diffForeignKeys, diffIndexes, generateSyncSql, type TableDiff } from "../../src/lib/schemaDiff.ts";
import type { ForeignKeyInfo, IndexInfo } from "../../src/types/database.ts";
function index(overrides: Partial<IndexInfo>): IndexInfo {
return {

View File

@ -1,6 +1,6 @@
import test from "node:test";
import assert from "node:assert/strict";
import { hasSchemaOptionsCacheEntry } from "../src/composables/useSchemaOptions.ts";
import { hasSchemaOptionsCacheEntry } from "../../src/composables/useSchemaOptions.ts";
test("treats an empty schema option list as a loaded cache entry", () => {
const options = {

View File

@ -4,7 +4,7 @@ import {
SCHEMA_TREE_CACHE_TTL_MS,
decodeSchemaTreeCache,
encodeSchemaTreeCache,
} from "../src/lib/schemaTreeCache.ts";
} from "../../src/lib/schemaTreeCache.ts";
const children = [{ id: "conn:db", label: "db", type: "database" }];
const now = Date.parse("2026-05-17T10:00:00.000Z");

View File

@ -5,7 +5,7 @@ import {
DEFAULT_EDITOR_SETTINGS,
normalizeAiConfig,
normalizeEditorSettings,
} from "../src/stores/settingsStore.ts";
} from "../../src/stores/settingsStore.ts";
test("defaults Redis scan page size to 1000 keys", () => {
assert.equal(DEFAULT_EDITOR_SETTINGS.redisScanPageSize, 1000);

View File

@ -12,8 +12,8 @@ import {
appendConnectionToLayout,
removeConnectionFromSidebarLayout,
emptyLayout,
} from "../src/lib/sidebarLayout.ts";
import type { ConnectionConfig, SidebarLayout } from "../src/types/database.ts";
} from "../../src/lib/sidebarLayout.ts";
import type { ConnectionConfig, SidebarLayout } from "../../src/types/database.ts";
function conn(id: string, name?: string): ConnectionConfig {
return {

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import { test } from "node:test";
import { matchSidebarLabel } from "../src/lib/sidebarSearch.ts";
import { matchSidebarLabel } from "../../src/lib/sidebarSearch.ts";
test("matches exact and prefix labels first", () => {
assert.equal(matchSidebarLabel("orders", "orders")?.kind, "exact");

View File

@ -1,7 +1,7 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { filterSidebarTree } from "../src/lib/sidebarSearchTree.ts";
import type { TreeNode } from "../src/types/database.ts";
import { filterSidebarTree } from "../../src/lib/sidebarSearchTree.ts";
import type { TreeNode } from "../../src/types/database.ts";
test("preserves loaded table children when the table itself matches search", () => {
const nodes: TreeNode[] = [

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { canTreeNodeExpand, canTreeNodeShowExpander, treeItemPaddingLeft } from "../src/lib/sidebarTreeItemLayout.ts";
import { canTreeNodeExpand, canTreeNodeShowExpander, treeItemPaddingLeft } from "../../src/lib/sidebarTreeItemLayout.ts";
test("treeItemPaddingLeft converts tree depth to sidebar indentation", () => {
assert.equal(treeItemPaddingLeft(0), "8px");

View File

@ -6,7 +6,7 @@ import {
analyzeEditableQuery,
analyzeEditableQueryEditability,
queryEditabilityMessageKey,
} from "../src/lib/sqlAnalysis.ts";
} from "../../src/lib/sqlAnalysis.ts";
test("recognizes a simple single-table SELECT as editable", () => {
const result = analyzeEditableQueryEditability("select id, name from public.users where active = true order by id");

View File

@ -6,7 +6,7 @@ import {
shouldAutoOpenSqlCompletion,
type SqlCompletionColumn,
type SqlCompletionTable,
} from "../src/lib/sqlCompletion.ts";
} from "../../src/lib/sqlCompletion.ts";
const tables: SqlCompletionTable[] = [
{ name: "users", schema: "public", type: "table" },

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { parseSqlErrorLocation } from "../src/lib/sqlDiagnostics.ts";
import { parseSqlErrorLocation } from "../../src/lib/sqlDiagnostics.ts";
test("parses generic line and column error positions", () => {
assert.deepEqual(parseSqlErrorLocation("syntax error at line 3 column 12"), {

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { resolveExecutableSql } from "../src/lib/sqlExecutionTarget.ts";
import { resolveExecutableSql } from "../../src/lib/sqlExecutionTarget.ts";
test("uses selected SQL when the editor has a non-empty selection", () => {
const sql = "SELECT * FROM users;\nSELECT * FROM orders;";

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { externalSqlFilePaths, isSqlFilePath, sqlFileTitleFromPath } from "../src/lib/sqlFileOpen.ts";
import { externalSqlFilePaths, isSqlFilePath, sqlFileTitleFromPath } from "../../src/lib/sqlFileOpen.ts";
test("detects SQL file paths case-insensitively", () => {
assert.equal(isSqlFilePath("/tmp/report.sql"), true);

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { formatSqlText } from "../src/lib/sqlFormatter.ts";
import { formatSqlText } from "../../src/lib/sqlFormatter.ts";
test("formats SQL with uppercase keywords and readable line breaks", async () => {
const formatted = await formatSqlText("select id, name from users where active = 1 order by name", "postgres");

View File

@ -1,6 +1,6 @@
import assert from "node:assert/strict";
import test from "node:test";
import { sqlMetadataRefreshScope, sqlMetadataRefreshTarget } from "../src/lib/sqlMetadataRefresh.ts";
import { sqlMetadataRefreshScope, sqlMetadataRefreshTarget } from "../../src/lib/sqlMetadataRefresh.ts";
test("database DDL refreshes the connection database list", () => {
assert.equal(sqlMetadataRefreshScope("CREATE DATABASE app;"), "connection");

View File

@ -1,7 +1,7 @@
import test from "node:test";
import assert from "node:assert/strict";
import { buildSqlServerDatabaseTreeNodes } from "../src/lib/sqlServerTree.ts";
import type { ObjectInfo } from "../src/types/database.ts";
import { buildSqlServerDatabaseTreeNodes } from "../../src/lib/sqlServerTree.ts";
import type { ObjectInfo } from "../../src/types/database.ts";
function obj(name: string, objectType = "TABLE"): ObjectInfo {
return {

View File

@ -1,6 +1,6 @@
import test from "node:test";
import assert from "node:assert/strict";
import { findStatementAtCursor } from "../src/lib/sqlStatementSplit.ts";
import { findStatementAtCursor } from "../../src/lib/sqlStatementSplit.ts";
test("finds single statement", () => {
assert.equal(findStatementAtCursor("SELECT 1", 3), "SELECT 1");

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { closeAllTabsState, closeOtherTabsState } from "../src/lib/tabCloseActions.ts";
import { closeAllTabsState, closeOtherTabsState } from "../../src/lib/tabCloseActions.ts";
test("close other tabs keeps the target tab and makes it active", () => {
const tabs = [{ id: "a" }, { id: "b" }, { id: "c" }];

View File

@ -1,7 +1,7 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { fetchTableDataForExport, TABLE_DATA_EXPORT_PAGE_SIZE } from "../src/lib/tableDataExport.ts";
import type { QueryResult } from "../src/types/database.ts";
import { fetchTableDataForExport, TABLE_DATA_EXPORT_PAGE_SIZE } from "../../src/lib/tableDataExport.ts";
import type { QueryResult } from "../../src/types/database.ts";
function result(rows: QueryResult["rows"]): QueryResult {
return {

View File

@ -12,8 +12,8 @@ import {
isTableDataEditable,
supportsDataGridTransaction,
usesSyntheticRowIdKey,
} from "../src/lib/tableEditing.ts";
import type { ColumnInfo } from "../src/types/database.ts";
} from "../../src/lib/tableEditing.ts";
import type { ColumnInfo } from "../../src/types/database.ts";
function column(name: string, isPrimaryKey = false): ColumnInfo {
return {

View File

@ -3,7 +3,7 @@ import test from "node:test";
import {
autoMapImportColumns,
normalizeImportColumnName,
} from "../src/lib/tableImport.ts";
} from "../../src/lib/tableImport.ts";
test("normalizes import column names for matching", () => {
assert.equal(normalizeImportColumnName(" User ID "), "user id");

View File

@ -1,7 +1,7 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { DBX_ROWID_COLUMN } from "../src/lib/tableEditing.ts";
import { buildTableSelectSql } from "../src/lib/tableSelectSql.ts";
import { DBX_ROWID_COLUMN } from "../../src/lib/tableEditing.ts";
import { buildTableSelectSql } from "../../src/lib/tableSelectSql.ts";
test("builds a MySQL table WHERE query from search input", () => {
const sql = buildTableSelectSql({

View File

@ -4,7 +4,7 @@ import {
buildTableStructureChangeSql,
type EditableStructureColumn,
type EditableStructureIndex,
} from "../src/lib/tableStructureEditorSql.ts";
} from "../../src/lib/tableStructureEditorSql.ts";
function column(overrides: Partial<EditableStructureColumn>): EditableStructureColumn {
return {

View File

@ -4,8 +4,8 @@ import {
createColumnDrafts,
createIndexDrafts,
toColumnNames,
} from "../src/lib/tableStructureEditorState.ts";
import type { ColumnInfo, IndexInfo } from "../src/types/database.ts";
} from "../../src/lib/tableStructureEditorState.ts";
import type { ColumnInfo, IndexInfo } from "../../src/types/database.ts";
const columns: ColumnInfo[] = [
{

View File

@ -1,7 +1,7 @@
import assert from "node:assert/strict";
import test from "node:test";
import { buildTableTreeNodes, expandCachedObjectBrowserNodes, objectGroupRefreshParentId } from "../src/lib/tableTree.ts";
import type { TableInfo } from "../src/types/database.ts";
import { buildTableTreeNodes, expandCachedObjectBrowserNodes, objectGroupRefreshParentId } from "../../src/lib/tableTree.ts";
import type { TableInfo } from "../../src/types/database.ts";
function table(name: string, tableType: "TABLE" | "VIEW" = "TABLE"): TableInfo {
return { name, table_type: tableType };

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { isTauriRuntime } from "../src/lib/tauriRuntime.ts";
import { isTauriRuntime } from "../../src/lib/tauriRuntime.ts";
test("detects plain browser-like globals as non-Tauri runtime", () => {
assert.equal(isTauriRuntime({}), false);

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { nextTransferTerminalState } from "../src/lib/transferProgressState.ts";
import { nextTransferTerminalState } from "../../src/lib/transferProgressState.ts";
test("marks transfer as failed when a table progress event reports error", () => {
const state = nextTransferTerminalState(

View File

@ -1,6 +1,6 @@
import test from "node:test";
import assert from "node:assert/strict";
import { sidebarSelectionCopyAction, treeNodeRowAction, treeNodeRowDoubleClickAction } from "../src/lib/treeNodeClick.ts";
import { sidebarSelectionCopyAction, treeNodeRowAction, treeNodeRowDoubleClickAction } from "../../src/lib/treeNodeClick.ts";
test("table and view rows open data without toggling structure groups", () => {
assert.equal(treeNodeRowAction("table", true), "open-data");

View File

@ -1,7 +1,7 @@
import assert from "node:assert/strict";
import test from "node:test";
import { findDatabaseTreeNode } from "../src/lib/treeRefreshTarget.ts";
import type { TreeNode } from "../src/types/database.ts";
import { findDatabaseTreeNode } from "../../src/lib/treeRefreshTarget.ts";
import type { TreeNode } from "../../src/types/database.ts";
test("finds database refresh targets inside grouped sidebar trees", () => {
const target: TreeNode = {

View File

@ -6,8 +6,8 @@ import {
SIDEBAR_TREE_SCROLL_BUFFER,
flattenTree,
shouldVirtualizeFlatTree,
} from "../src/composables/useFlatTree.ts";
import type { TreeNode } from "../src/types/database.ts";
} from "../../src/composables/useFlatTree.ts";
import type { TreeNode } from "../../src/types/database.ts";
test("flattenTree preserves depth and node type for virtualized sidebar rows", () => {
const nodes: TreeNode[] = [

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { isDangerousSql, stripSqlComments } from "../src/composables/useSqlExecution.ts";
import { isDangerousSql, stripSqlComments } from "../../src/composables/useSqlExecution.ts";
test("stripSqlComments removes block comments", () => {
assert.equal(stripSqlComments("SELECT /* drop */ 1").includes("drop"), false);

View File

@ -4,7 +4,7 @@ import {
filterVisibleDatabaseNames,
normalizeVisibleDatabaseSelection,
visibleDatabaseFilterIsEnabled,
} from "../src/lib/visibleDatabases.ts";
} from "../../src/lib/visibleDatabases.ts";
test("undefined visible database filter keeps every database", () => {
assert.deepEqual(filterVisibleDatabaseNames(["app", "analytics"], undefined), ["app", "analytics"]);

View File

@ -1,6 +1,6 @@
import { strict as assert } from "node:assert";
import test from "node:test";
import { buildXlsxWorkbook } from "../src/lib/xlsxExport.ts";
import { buildXlsxWorkbook } from "../../src/lib/xlsxExport.ts";
test("builds an xlsx workbook zip with worksheet data", () => {
const workbook = buildXlsxWorkbook({