test(tabs): align cache assertions with bounded keepalive

This commit is contained in:
t8y2 committed 2026-09-11 11:47:40 +08:00
1 parent 1c9846dc57
commit ead906477f
2 files changed
+48 -34

No files matched your search

@@ -5,8 +5,8 @@ import { createI18n } from "vue-i18n";
import { beforeEach, describe, expect, it, vi } from "vitest";
const lifecycle = vi.hoisted(() => ({
queryCreated: 0,
queryUnmounted: 0,
surfaceCreated: 0,
surfaceUnmounted: 0,
}));
vi.mock("@/components/layout/EditorGroupTabBar.vue", () => ({
@@ -29,10 +29,10 @@ vi.mock("@/components/layout/QueryEditorSurface.vue", () => ({
name: "QueryEditorSurfaceStub",
props: ["activeTab", "autoFocus"],
created() {
lifecycle.queryCreated += 1;
lifecycle.surfaceCreated += 1;
},
unmounted() {
lifecycle.queryUnmounted += 1;
lifecycle.surfaceUnmounted += 1;
},
template: `<div data-test="query-editor">{{ activeTab.id }}</div>`,
},
@@ -41,6 +41,12 @@ vi.mock("@/components/layout/QueryEditorSurface.vue", () => ({
vi.mock("@/components/layout/ContentArea.vue", () => ({
default: {
name: "ContentAreaStub",
created() {
lifecycle.surfaceCreated += 1;
},
unmounted() {
lifecycle.surfaceUnmounted += 1;
},
template: `<div data-test="content-area" />`,
},
}));
@@ -54,14 +60,14 @@ import EditorGroup from "../EditorGroup.vue";
import { createNoopEditorToolbarActions, EDITOR_TOOLBAR_ACTIONS, type EditorToolbarActions } from "../editorToolbarActions";
import { useQueryStore } from "@/stores/queryStore";
function tab(id: string) {
function tab(id: string, mode: "query" | "data" = "query") {
return {
id,
title: id,
connectionId: "conn-1",
database: "db",
sql: "SELECT 1",
mode: "query",
mode,
} as const;
}
@@ -77,8 +83,8 @@ describe("EditorGroup mount contract", () => {
beforeEach(() => {
document.body.innerHTML = "";
lifecycle.queryCreated = 0;
lifecycle.queryUnmounted = 0;
lifecycle.surfaceCreated = 0;
lifecycle.surfaceUnmounted = 0;
pinia = createPinia();
setActivePinia(pinia);
i18n = createI18n({
@@ -88,9 +94,10 @@ describe("EditorGroup mount contract", () => {
});
});
it("keeps a bounded hot surface cache while switching query tabs", async () => {
it.each(["query", "data"] as const)("reuses hot %s tabs and remounts evicted surfaces", async (mode) => {
const store = useQueryStore();
store.tabs = [tab("tab-a"), tab("tab-b")];
const tabIds = ["tab-a", "tab-b", "tab-c", "tab-d"];
store.tabs = tabIds.map((tabId) => tab(tabId, mode));
const activeTabId = ref("tab-a");
const host = createHost();
const root = defineComponent({
@@ -98,9 +105,9 @@ describe("EditorGroup mount contract", () => {
return () =>
h(EditorGroup, {
groupId: "group-1",
tabIds: ["tab-a", "tab-b"],
tabIds,
activeTabId: activeTabId.value,
activeTab: tab(activeTabId.value),
activeTab: tab(activeTabId.value, mode),
activeConnection: undefined,
executableSql: "SELECT 1",
activeOutputView: "result",
@@ -123,11 +130,31 @@ describe("EditorGroup mount contract", () => {
activeTabId.value = "tab-a";
await nextTick();
expect(lifecycle.queryCreated).toBe(2);
expect(lifecycle.queryUnmounted).toBe(0);
expect(lifecycle.surfaceCreated).toBe(2);
expect(lifecycle.surfaceUnmounted).toBe(0);
activeTabId.value = "tab-c";
await nextTick();
expect(lifecycle.surfaceCreated).toBe(3);
expect(lifecycle.surfaceUnmounted).toBe(0);
activeTabId.value = "tab-d";
await nextTick();
expect(lifecycle.surfaceCreated).toBe(4);
expect(lifecycle.surfaceUnmounted).toBe(1);
activeTabId.value = "tab-a";
await nextTick();
expect(lifecycle.surfaceCreated).toBe(4);
expect(lifecycle.surfaceUnmounted).toBe(1);
activeTabId.value = "tab-b";
await nextTick();
expect(lifecycle.surfaceCreated).toBe(5);
expect(lifecycle.surfaceUnmounted).toBe(2);
app.unmount();
expect(lifecycle.queryUnmounted).toBe(2);
expect(lifecycle.surfaceUnmounted).toBe(5);
host.remove();
});