import assert from "node:assert/strict"; import { createPinia, setActivePinia } from "pinia"; import { beforeEach, test, vi } from "vitest"; import type { SavedSqlFile, SavedSqlFolder, SavedSqlLibrary } from "../../apps/desktop/src/types/database.ts"; import { useSavedSqlStore } from "../../apps/desktop/src/stores/savedSqlStore.ts"; const apiMock = vi.hoisted(() => ({ loadSavedSqlLibrary: vi.fn<() => Promise>(), loadSavedSqlFile: vi.fn<(id: string) => Promise>(), saveSavedSqlFolder: vi.fn<(folder: SavedSqlFolder) => Promise>(), saveSavedSqlFile: vi.fn<(file: SavedSqlFile) => Promise>(), syncSavedSqlDirectory: vi.fn<() => Promise>(), })); vi.mock("@/lib/backend/api", () => apiMock); beforeEach(() => { setActivePinia(createPinia()); apiMock.loadSavedSqlLibrary.mockResolvedValue({ folders: [], files: [] }); apiMock.loadSavedSqlFile.mockResolvedValue(null); apiMock.saveSavedSqlFolder.mockImplementation(async (folder) => folder); apiMock.saveSavedSqlFile.mockImplementation(async (file) => file); apiMock.syncSavedSqlDirectory.mockResolvedValue(); vi.clearAllMocks(); }); test("concurrent saved SQL folder creates reuse the same pending folder", async () => { let resolveSave: ((folder: SavedSqlFolder) => void) | undefined; apiMock.saveSavedSqlFolder.mockImplementation( (folder) => new Promise((resolve) => { resolveSave = () => resolve(folder); }), ); const store = useSavedSqlStore(); const first = store.createFolder("conn-1", "新建文件夹"); const second = store.createFolder("conn-1", "新建文件夹"); assert.equal(apiMock.saveSavedSqlFolder.mock.calls.length, 1); resolveSave?.(apiMock.saveSavedSqlFolder.mock.calls[0]![0]); const [firstFolder, secondFolder] = await Promise.all([first, second]); assert.equal(firstFolder.id, secondFolder.id); assert.equal(store.folders.length, 1); assert.equal(store.folders[0]?.id, firstFolder.id); }); test("saved SQL summaries load file content on demand", async () => { const summaryFile: SavedSqlFile = { id: "sql-1", connectionId: "conn-1", name: "large.sql", database: "", sql: "", sqlLoaded: false, createdAt: "2026-06-27T00:00:00.000Z", updatedAt: "2026-06-27T00:00:00.000Z", }; const loadedFile = { ...summaryFile, sql: "SELECT 1;", sqlLoaded: true }; apiMock.loadSavedSqlLibrary.mockResolvedValue({ folders: [], files: [summaryFile] }); apiMock.loadSavedSqlFile.mockResolvedValue(loadedFile); const store = useSavedSqlStore(); await store.initFromStorage(); assert.equal(store.files[0]?.sql, ""); assert.equal(store.files[0]?.sqlLoaded, false); const hydrated = await store.ensureFileContent("sql-1"); assert.equal(hydrated?.sql, "SELECT 1;"); assert.equal(store.files[0]?.sql, "SELECT 1;"); assert.equal(apiMock.loadSavedSqlFile.mock.calls.length, 1); }); test("saving an existing SQL file without folderId keeps its folder", async () => { const file: SavedSqlFile = { id: "sql-1", connectionId: "conn-1", folderId: "folder-1", name: "query.sql", database: "db", sql: "SELECT 1;", sqlLoaded: true, createdAt: "2026-06-27T00:00:00.000Z", updatedAt: "2026-06-27T00:00:00.000Z", }; apiMock.loadSavedSqlLibrary.mockResolvedValue({ folders: [], files: [file] }); const store = useSavedSqlStore(); await store.initFromStorage(); const saved = await store.saveFile({ id: "sql-1", connectionId: "conn-2", name: "query.sql", database: "other_db", sql: "SELECT 1;", }); assert.equal(saved.folderId, "folder-1"); assert.equal(apiMock.saveSavedSqlFile.mock.calls[0]?.[0].folderId, "folder-1"); assert.equal(store.getFile("sql-1")?.folderId, "folder-1"); }); test("saving an existing SQL file with root folder explicitly moves it to root", async () => { const file: SavedSqlFile = { id: "sql-1", connectionId: "conn-1", folderId: "folder-1", name: "query.sql", database: "db", sql: "SELECT 1;", sqlLoaded: true, createdAt: "2026-06-27T00:00:00.000Z", updatedAt: "2026-06-27T00:00:00.000Z", }; apiMock.loadSavedSqlLibrary.mockResolvedValue({ folders: [], files: [file] }); const store = useSavedSqlStore(); await store.initFromStorage(); const saved = await store.saveFile({ id: "sql-1", connectionId: "conn-1", folderId: undefined, name: "query.sql", database: "db", sql: "SELECT 1;", }); assert.equal(saved.folderId, undefined); assert.equal(apiMock.saveSavedSqlFile.mock.calls[0]?.[0].folderId, undefined); assert.equal(store.getFile("sql-1")?.folderId, undefined); }); test("moving multiple saved SQL files to a folder keeps existing target files", async () => { const files: SavedSqlFile[] = [ { id: "sql-1", connectionId: "conn-1", name: "one.sql", database: "db", sql: "SELECT 1;", orderIndex: 0, createdAt: "2026-06-27T00:00:00.000Z", updatedAt: "2026-06-27T00:00:00.000Z", }, { id: "sql-2", connectionId: "conn-1", name: "two.sql", database: "db", sql: "SELECT 2;", orderIndex: 1, createdAt: "2026-06-27T00:00:00.000Z", updatedAt: "2026-06-27T00:00:00.000Z", }, { id: "sql-3", connectionId: "conn-1", folderId: "folder-1", name: "three.sql", database: "db", sql: "SELECT 3;", orderIndex: 0, createdAt: "2026-06-27T00:00:00.000Z", updatedAt: "2026-06-27T00:00:00.000Z", }, ]; apiMock.loadSavedSqlLibrary.mockResolvedValue({ folders: [], files }); const store = useSavedSqlStore(); await store.initFromStorage(); await store.moveFilesToFolder(["sql-1", "sql-2"], "folder-1"); assert.deepEqual( store.filesInFolder("folder-1").map((file) => [file.id, file.folderId, file.orderIndex]), [ ["sql-3", "folder-1", 0], ["sql-1", "folder-1", 1], ["sql-2", "folder-1", 2], ], ); assert.deepEqual( store.filesWithoutFolder().map((file) => file.id), [], ); }); test("moving selected files already in the target folder keeps them in place", async () => { const files: SavedSqlFile[] = [ { id: "sql-1", connectionId: "conn-1", name: "one.sql", database: "db", sql: "SELECT 1;", orderIndex: 0, createdAt: "2026-06-27T00:00:00.000Z", updatedAt: "2026-06-27T00:00:00.000Z", }, { id: "sql-2", connectionId: "conn-1", folderId: "folder-1", name: "two.sql", database: "db", sql: "SELECT 2;", orderIndex: 0, createdAt: "2026-06-27T00:00:00.000Z", updatedAt: "2026-06-27T00:00:00.000Z", }, ]; apiMock.loadSavedSqlLibrary.mockResolvedValue({ folders: [], files }); const store = useSavedSqlStore(); await store.initFromStorage(); await store.moveFilesToFolder(["sql-1", "sql-2"], "folder-1"); assert.deepEqual( store.filesInFolder("folder-1").map((file) => file.id), ["sql-2", "sql-1"], ); });