fix(sidebar): preserve objects for ancestor search matches
Closes #5613
This commit is contained in:
1 parent
cce36ae058
commit
e0a7bc996d
9 files changed
+282
-41
No files matched your search
+78
-11
@@ -2968,17 +2968,15 @@ describe("connectionStore metadata loading", () => {
|
||||
}));
|
||||
let resolveSearchClearReload!: (tables: TableInfo[]) => void;
|
||||
let unfilteredFirstPageCalls = 0;
|
||||
const listTables = vi.fn(
|
||||
(_connectionId: string, _database: string, _schema: string, searchFilter?: string, limit?: number, offset?: number) => {
|
||||
if (searchFilter) return Promise.resolve(tables.filter((table) => table.name.includes(searchFilter)));
|
||||
if ((offset ?? 0) === 0 && ++unfilteredFirstPageCalls === 1) {
|
||||
return new Promise<TableInfo[]>((resolve) => {
|
||||
resolveSearchClearReload = resolve;
|
||||
});
|
||||
}
|
||||
return Promise.resolve(tables.slice(offset ?? 0, (offset ?? 0) + (limit ?? tables.length)));
|
||||
},
|
||||
);
|
||||
const listTables = vi.fn((_connectionId: string, _database: string, _schema: string, searchFilter?: string, limit?: number, offset?: number) => {
|
||||
if (searchFilter) return Promise.resolve(tables.filter((table) => table.name.includes(searchFilter)));
|
||||
if ((offset ?? 0) === 0 && ++unfilteredFirstPageCalls === 1) {
|
||||
return new Promise<TableInfo[]>((resolve) => {
|
||||
resolveSearchClearReload = resolve;
|
||||
});
|
||||
}
|
||||
return Promise.resolve(tables.slice(offset ?? 0, (offset ?? 0) + (limit ?? tables.length)));
|
||||
});
|
||||
|
||||
vi.doMock("@/lib/backend/tauriRuntime", () => ({ isTauriRuntime: () => false }));
|
||||
vi.doMock("@/lib/backend/api", () => ({
|
||||
@@ -3060,6 +3058,75 @@ describe("connectionStore metadata loading", () => {
|
||||
expect(listTables).toHaveBeenCalledTimes(5);
|
||||
});
|
||||
|
||||
it("keeps connection-name matches out of object metadata filters", async () => {
|
||||
const listTables = vi.fn((_connectionId: string, _database: string, _schema: string, searchFilter?: string) => Promise.resolve(searchFilter === "orders" || !searchFilter ? [{ name: "orders", table_type: "TABLE" as const, comment: null }] : []));
|
||||
|
||||
vi.doMock("@/lib/backend/tauriRuntime", () => ({ isTauriRuntime: () => false }));
|
||||
vi.doMock("@/lib/backend/api", () => ({
|
||||
checkConnectionHealth: vi.fn().mockResolvedValue(undefined),
|
||||
deleteSchemaCachePrefix: vi.fn().mockResolvedValue(undefined),
|
||||
listTables,
|
||||
loadSchemaCache: vi.fn().mockResolvedValue(null),
|
||||
saveConnections: vi.fn().mockResolvedValue(undefined),
|
||||
saveSchemaCache: vi.fn().mockResolvedValue(undefined),
|
||||
saveSidebarLayout: vi.fn().mockResolvedValue(undefined),
|
||||
}));
|
||||
|
||||
const { useConnectionStore } = await import("@/stores/connectionStore");
|
||||
const { useSettingsStore } = await import("@/stores/settingsStore");
|
||||
const store = useConnectionStore();
|
||||
const settingsStore = useSettingsStore();
|
||||
settingsStore.editorSettings.sidebarObjectDisplay = "grouped";
|
||||
settingsStore.desktopSettings.sidebar_table_page_size = 200;
|
||||
const connection = { ...mysqlConnection(), name: "60307" };
|
||||
const tablesGroup: TreeNode = {
|
||||
id: "mysql-1:basic:__tables",
|
||||
label: "tree.tables",
|
||||
type: "group-tables",
|
||||
connectionId: connection.id,
|
||||
database: "basic",
|
||||
isExpanded: true,
|
||||
children: [],
|
||||
};
|
||||
store.connections = [connection];
|
||||
store.connectedIds.add(connection.id);
|
||||
store.treeNodes = [{ id: connection.id, label: connection.name, type: "connection", connectionId: connection.id, children: [tablesGroup] }];
|
||||
|
||||
store.sidebarSearchQuery = "60307";
|
||||
await store.loadObjectGroupChildren(tablesGroup, { force: true, searchFilter: "", allowGlobalSearchMismatch: true, expectedSidebarSearchQuery: "60307" });
|
||||
|
||||
expect(listTables).toHaveBeenLastCalledWith(connection.id, "basic", "basic", undefined, 201, 0, ["TABLE"]);
|
||||
expect(tablesGroup.children?.map((node) => node.label)).toEqual(["orders"]);
|
||||
|
||||
store.sidebarSearchQuery = "orders";
|
||||
await store.loadObjectGroupChildren(tablesGroup, { force: true });
|
||||
|
||||
expect(listTables).toHaveBeenLastCalledWith(connection.id, "basic", "basic", "orders", 200, undefined, ["TABLE"]);
|
||||
expect(tablesGroup.children?.map((node) => node.label)).toEqual(["orders"]);
|
||||
|
||||
let resolveAncestorLoad!: (tables: TableInfo[]) => void;
|
||||
listTables.mockImplementationOnce(
|
||||
() =>
|
||||
new Promise<TableInfo[]>((resolve) => {
|
||||
resolveAncestorLoad = resolve;
|
||||
}),
|
||||
);
|
||||
store.sidebarSearchQuery = "60307";
|
||||
const ancestorLoad = store.loadObjectGroupChildren(tablesGroup, {
|
||||
force: true,
|
||||
searchFilter: "",
|
||||
allowGlobalSearchMismatch: true,
|
||||
expectedSidebarSearchQuery: "60307",
|
||||
});
|
||||
await vi.waitFor(() => expect(listTables).toHaveBeenCalledTimes(3));
|
||||
|
||||
store.sidebarSearchQuery = "customers";
|
||||
resolveAncestorLoad([{ name: "stale_table", table_type: "TABLE", comment: null }]);
|
||||
await ancestorLoad;
|
||||
|
||||
expect(tablesGroup.children?.map((node) => node.label)).toEqual(["orders"]);
|
||||
});
|
||||
|
||||
it("merges load-more table pages onto the live group node after an in-tree replacement", async () => {
|
||||
const firstPage = Array.from({ length: 201 }, (_, index) => ({
|
||||
name: `t_${String(index + 1).padStart(4, "0")}`,
|
||||
|
||||
@@ -2176,8 +2176,9 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
|
||||
function isTreeLoadSearchChanged(searchFilter: string, options?: LoadTreeOptions): boolean {
|
||||
if (options?.sidebarTableSearchParentId) return isSidebarTableSearchQueryChanged(options);
|
||||
if (isSidebarSearchQueryChanged(options)) return true;
|
||||
if (options?.allowGlobalSearchMismatch) return false;
|
||||
return (sidebarSearchQuery.value || "") !== searchFilter || isSidebarSearchQueryChanged(options);
|
||||
return (sidebarSearchQuery.value || "") !== searchFilter;
|
||||
}
|
||||
|
||||
function isTreeNodeChildrenLoaded(nodeId: string): boolean {
|
||||
@@ -4476,7 +4477,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
nonTableObjectTypes,
|
||||
offset: 0,
|
||||
pageSize,
|
||||
searchFilter: searchFilter || undefined,
|
||||
searchFilter: options?.searchFilter === "" ? "" : searchFilter || undefined,
|
||||
force: options?.force,
|
||||
});
|
||||
children = page.hasMore && !searchFilter ? appendTableTreeLoadMoreNode(page.children, buildLoadMoreNode(node, page.nextOffset, pageSize), page.loadMoreParent) : page.children;
|
||||
@@ -4614,7 +4615,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
objectTypes,
|
||||
offset: 0,
|
||||
pageSize: sidebarObjectGroupPageSize(),
|
||||
searchFilter: searchFilter || undefined,
|
||||
searchFilter: options?.searchFilter === "" ? "" : searchFilter || undefined,
|
||||
force: options?.force,
|
||||
});
|
||||
children = page.hasMore && !searchFilter ? appendTableTreeLoadMoreNode(page.children, buildLoadMoreNode(node, page.nextOffset, sidebarObjectGroupPageSize()), page.loadMoreParent) : page.children;
|
||||
|
||||
Reference in new issue
Block a user