mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-19 16:16:45 +00:00
feat(tabs): default to compact tab titles via migration
This commit is contained in:
@@ -54,6 +54,9 @@ beforeEach(() => {
|
||||
removeItem: vi.fn((key: string) => values.delete(key)),
|
||||
});
|
||||
setActivePinia(createPinia());
|
||||
// Compact titles are the shipped default now (#12310); pin the flag so these
|
||||
// assertions keep describing full titles and compact cases opt in themselves.
|
||||
useSettingsStore().editorSettings.compactTabTitle = false;
|
||||
});
|
||||
|
||||
function queryTab(overrides: Partial<QueryTab>): QueryTab {
|
||||
|
||||
@@ -24,12 +24,21 @@ import {
|
||||
type RightSidebarPanelState,
|
||||
transitionRightSidebarPanels,
|
||||
WELCOME_PAGE_DEFAULT_VERSION,
|
||||
COMPACT_TAB_TITLE_DEFAULT_VERSION,
|
||||
} from "@/stores/settingsStore";
|
||||
import type { AiConfigItem } from "@/types/ai";
|
||||
import { DATA_GRID_EXTRACTOR_OPTIONS_MIGRATION_VERSION } from "@/lib/dataGrid/dataGridCopyExtractor";
|
||||
import { DEFAULT_MONO_FONT_FAMILY } from "@/lib/app/appFonts";
|
||||
|
||||
describe("normalizeEditorSettings", () => {
|
||||
it("defaults tab titles to the compact presentation while preserving an explicit opt-out", () => {
|
||||
expect(DEFAULT_EDITOR_SETTINGS.compactTabTitle).toBe(true);
|
||||
expect(normalizeEditorSettings({}).compactTabTitle).toBe(true);
|
||||
expect(normalizeEditorSettings({ compactTabTitle: false }).compactTabTitle).toBe(true);
|
||||
expect(normalizeEditorSettings({ compactTabTitle: false, compactTabTitleDefaultVersion: COMPACT_TAB_TITLE_DEFAULT_VERSION }).compactTabTitle).toBe(false);
|
||||
expect(normalizeEditorSettings({ compactTabTitle: "false" } as any).compactTabTitle).toBe(true);
|
||||
});
|
||||
|
||||
it("keeps empty-column hiding opt-in and independent from NULL-only hiding", () => {
|
||||
expect(normalizeEditorSettings({})).toMatchObject({ dataGridHideNullColumns: false, dataGridHideEmptyColumns: false });
|
||||
expect(normalizeEditorSettings({ dataGridHideNullColumns: true })).toMatchObject({ dataGridHideNullColumns: true, dataGridHideEmptyColumns: false });
|
||||
@@ -70,6 +79,19 @@ describe("normalizeEditorSettings", () => {
|
||||
expect(normalizeEditorSettings({ welcomePageMode: "workspace", welcomePageModeDefaultVersion: WELCOME_PAGE_DEFAULT_VERSION }).welcomePageMode).toBe("workspace");
|
||||
});
|
||||
|
||||
it("defaults compact tab titles on and keeps an explicit choice packed with its version marker", () => {
|
||||
expect(DEFAULT_EDITOR_SETTINGS.compactTabTitle).toBe(true);
|
||||
// Fresh blobs never saw the old unwrapped default, so they take the marker and the new default.
|
||||
expect(normalizeEditorSettings({})).toMatchObject({ compactTabTitle: true, compactTabTitleDefaultVersion: COMPACT_TAB_TITLE_DEFAULT_VERSION });
|
||||
// A persisted `false` from the unwrapped-title builds carries no marker and migrates on.
|
||||
expect(normalizeEditorSettings({ compactTabTitle: false }).compactTabTitle).toBe(true);
|
||||
expect(normalizeEditorSettings({ compactTabTitle: false }).compactTabTitleDefaultVersion).toBe(COMPACT_TAB_TITLE_DEFAULT_VERSION);
|
||||
// With the marker the value is the user's own and must survive untouched, including `false`.
|
||||
expect(normalizeEditorSettings({ compactTabTitle: false, compactTabTitleDefaultVersion: COMPACT_TAB_TITLE_DEFAULT_VERSION }).compactTabTitle).toBe(false);
|
||||
expect(normalizeEditorSettings({ compactTabTitle: true, compactTabTitleDefaultVersion: COMPACT_TAB_TITLE_DEFAULT_VERSION }).compactTabTitle).toBe(true);
|
||||
expect(normalizeEditorSettings({ compactTabTitle: "yes" as any, compactTabTitleDefaultVersion: COMPACT_TAB_TITLE_DEFAULT_VERSION }).compactTabTitle).toBe(false);
|
||||
});
|
||||
|
||||
it("defaults and sanitizes AI conversation typography independently", () => {
|
||||
expect(normalizeEditorSettings({})).toMatchObject({ aiFontFamily: "", aiFontSize: 12 });
|
||||
expect(
|
||||
@@ -1629,6 +1651,57 @@ describe("settingsStore persisted settings initialization", () => {
|
||||
expect(saveEditorSettings).toHaveBeenLastCalledWith(expect.objectContaining({ welcomePageMode: "intro", welcomePageModeDefaultVersion: WELCOME_PAGE_DEFAULT_VERSION }));
|
||||
});
|
||||
|
||||
it("migrates a persisted off compact tab title to the new default and keeps later explicit choices", async () => {
|
||||
const loadEditorSettings = vi.fn().mockResolvedValueOnce({
|
||||
compactTabTitle: false,
|
||||
executeModeDefaultVersion: EXECUTE_MODE_CURRENT_DEFAULT_VERSION,
|
||||
sidebarBrowseObjectsOnDatabaseActivationMigrationVersion: SIDEBAR_BROWSE_OBJECTS_MIGRATION_VERSION,
|
||||
dataGridExtractorOptionsMigrationVersion: DATA_GRID_EXTRACTOR_OPTIONS_MIGRATION_VERSION,
|
||||
});
|
||||
const saveEditorSettings = vi.fn().mockResolvedValue(undefined);
|
||||
vi.doMock("@/lib/backend/api", () => ({ loadEditorSettings, saveEditorSettings }));
|
||||
|
||||
const { useSettingsStore } = await import("@/stores/settingsStore");
|
||||
const store = useSettingsStore();
|
||||
await store.initEditorSettings();
|
||||
|
||||
// The marker is absent, so `false` is the old default rather than a choice.
|
||||
expect(store.editorSettings.compactTabTitle).toBe(true);
|
||||
expect(store.editorSettings.compactTabTitleDefaultVersion).toBe(COMPACT_TAB_TITLE_DEFAULT_VERSION);
|
||||
await vi.waitFor(() => expect(saveEditorSettings).toHaveBeenCalledOnce());
|
||||
expect(saveEditorSettings).toHaveBeenLastCalledWith(expect.objectContaining({ compactTabTitle: true, compactTabTitleDefaultVersion: COMPACT_TAB_TITLE_DEFAULT_VERSION }));
|
||||
|
||||
// Turning it back off must stick now that the marker is stamped.
|
||||
store.updateEditorSettings({ compactTabTitle: false });
|
||||
expect(store.editorSettings.compactTabTitle).toBe(false);
|
||||
await vi.waitFor(() => expect(saveEditorSettings).toHaveBeenCalledTimes(2));
|
||||
expect(saveEditorSettings).toHaveBeenLastCalledWith(expect.objectContaining({ compactTabTitle: false, compactTabTitleDefaultVersion: COMPACT_TAB_TITLE_DEFAULT_VERSION }));
|
||||
});
|
||||
|
||||
it("does not re-migrate an already stamped compact tab title", async () => {
|
||||
const loadEditorSettings = vi.fn().mockResolvedValueOnce({
|
||||
compactTabTitle: false,
|
||||
compactTabTitleDefaultVersion: COMPACT_TAB_TITLE_DEFAULT_VERSION,
|
||||
executeModeDefaultVersion: EXECUTE_MODE_CURRENT_DEFAULT_VERSION,
|
||||
sidebarBrowseObjectsOnDatabaseActivationMigrationVersion: SIDEBAR_BROWSE_OBJECTS_MIGRATION_VERSION,
|
||||
dataGridExtractorOptionsMigrationVersion: DATA_GRID_EXTRACTOR_OPTIONS_MIGRATION_VERSION,
|
||||
});
|
||||
const saveEditorSettings = vi.fn().mockResolvedValue(undefined);
|
||||
vi.doMock("@/lib/backend/api", () => ({ loadEditorSettings, saveEditorSettings }));
|
||||
|
||||
const { useSettingsStore } = await import("@/stores/settingsStore");
|
||||
const store = useSettingsStore();
|
||||
await store.initEditorSettings();
|
||||
|
||||
expect(store.editorSettings.compactTabTitle).toBe(false);
|
||||
await vi.waitFor(() => expect(store.isEditorSettingsLoaded).toBe(true));
|
||||
// Other migration flags in this stub may still trigger an eager save; the
|
||||
// point is that the compact title is never flipped on a stamped value.
|
||||
if (saveEditorSettings.mock.calls.length) {
|
||||
expect(saveEditorSettings).toHaveBeenLastCalledWith(expect.objectContaining({ compactTabTitle: false, compactTabTitleDefaultVersion: COMPACT_TAB_TITLE_DEFAULT_VERSION }));
|
||||
}
|
||||
});
|
||||
|
||||
it("persists table completion schema qualification updates", async () => {
|
||||
const loadEditorSettings = vi.fn().mockResolvedValue({});
|
||||
const saveEditorSettings = vi.fn().mockResolvedValue(undefined);
|
||||
@@ -2041,6 +2114,7 @@ describe("settingsStore editor settings persistence", () => {
|
||||
executeModeDefaultVersion: EXECUTE_MODE_CURRENT_DEFAULT_VERSION,
|
||||
sidebarBrowseObjectsOnDatabaseActivationMigrationVersion: SIDEBAR_BROWSE_OBJECTS_MIGRATION_VERSION,
|
||||
welcomePageModeDefaultVersion: WELCOME_PAGE_DEFAULT_VERSION,
|
||||
compactTabTitleDefaultVersion: COMPACT_TAB_TITLE_DEFAULT_VERSION,
|
||||
});
|
||||
const saveEditorSettings = vi.fn().mockRejectedValueOnce(new Error("save failed")).mockResolvedValueOnce(undefined);
|
||||
vi.doMock("@/lib/backend/api", () => ({ loadEditorSettings, saveEditorSettings }));
|
||||
@@ -2089,6 +2163,7 @@ describe("settingsStore editor settings persistence", () => {
|
||||
executeModeDefaultVersion: EXECUTE_MODE_CURRENT_DEFAULT_VERSION,
|
||||
sidebarBrowseObjectsOnDatabaseActivationMigrationVersion: SIDEBAR_BROWSE_OBJECTS_MIGRATION_VERSION,
|
||||
welcomePageModeDefaultVersion: WELCOME_PAGE_DEFAULT_VERSION,
|
||||
compactTabTitleDefaultVersion: COMPACT_TAB_TITLE_DEFAULT_VERSION,
|
||||
});
|
||||
const saveEditorSettings = vi.fn().mockImplementationOnce(
|
||||
() =>
|
||||
@@ -2126,6 +2201,7 @@ describe("settingsStore editor settings persistence", () => {
|
||||
executeModeDefaultVersion: EXECUTE_MODE_CURRENT_DEFAULT_VERSION,
|
||||
sidebarBrowseObjectsOnDatabaseActivationMigrationVersion: SIDEBAR_BROWSE_OBJECTS_MIGRATION_VERSION,
|
||||
welcomePageModeDefaultVersion: WELCOME_PAGE_DEFAULT_VERSION,
|
||||
compactTabTitleDefaultVersion: COMPACT_TAB_TITLE_DEFAULT_VERSION,
|
||||
});
|
||||
const saveEditorSettings = vi.fn().mockImplementationOnce(
|
||||
() =>
|
||||
|
||||
@@ -1003,6 +1003,7 @@ export interface EditorSettings {
|
||||
welcomePageMode: WelcomePageMode;
|
||||
welcomePageModeDefaultVersion: number;
|
||||
compactTabTitle: boolean;
|
||||
compactTabTitleDefaultVersion: number;
|
||||
tabLayout: TabLayoutMode;
|
||||
tabPlacement: TabPlacement;
|
||||
colorizeConnectionTabs: boolean;
|
||||
@@ -1311,6 +1312,11 @@ export const SIDEBAR_BROWSE_OBJECTS_MIGRATION_VERSION = 1;
|
||||
// v1: the welcome page default moved from "intro" back to "workspace"; persisted
|
||||
// blobs from the intro-default builds lack this marker and are migrated.
|
||||
export const WELCOME_PAGE_DEFAULT_VERSION = 1;
|
||||
// v1: compact tab titles became the default. A stored `compactTabTitle: false`
|
||||
// cannot be told apart from the old default, so this marker separates the two:
|
||||
// blobs written by the unwrapped-title builds lack it and migrate to the new
|
||||
// default, while an explicit toggle afterwards stamps the marker and wins.
|
||||
export const COMPACT_TAB_TITLE_DEFAULT_VERSION = 1;
|
||||
|
||||
export const DEFAULT_EDITOR_SETTINGS: EditorSettings = {
|
||||
fontFamily: DEFAULT_MONO_FONT_FAMILY,
|
||||
@@ -1366,7 +1372,8 @@ export const DEFAULT_EDITOR_SETTINGS: EditorSettings = {
|
||||
savedSqlOpenTargetMode: "saved",
|
||||
welcomePageMode: "workspace",
|
||||
welcomePageModeDefaultVersion: WELCOME_PAGE_DEFAULT_VERSION,
|
||||
compactTabTitle: false,
|
||||
compactTabTitle: true,
|
||||
compactTabTitleDefaultVersion: COMPACT_TAB_TITLE_DEFAULT_VERSION,
|
||||
tabLayout: "scroll",
|
||||
tabPlacement: "top",
|
||||
colorizeConnectionTabs: true,
|
||||
@@ -1903,6 +1910,9 @@ export function normalizeEditorSettings(settings: Partial<EditorSettings>, exist
|
||||
const savedWelcomePageDefaultVersion = settings.welcomePageModeDefaultVersion;
|
||||
const welcomePageModeDefaultVersion = typeof savedWelcomePageDefaultVersion === "number" && savedWelcomePageDefaultVersion >= WELCOME_PAGE_DEFAULT_VERSION ? savedWelcomePageDefaultVersion : WELCOME_PAGE_DEFAULT_VERSION;
|
||||
const hasCurrentWelcomePageDefault = welcomePageModeDefaultVersion === savedWelcomePageDefaultVersion;
|
||||
const savedCompactTabTitleDefaultVersion = settings.compactTabTitleDefaultVersion;
|
||||
const compactTabTitleDefaultVersion = typeof savedCompactTabTitleDefaultVersion === "number" && savedCompactTabTitleDefaultVersion >= COMPACT_TAB_TITLE_DEFAULT_VERSION ? savedCompactTabTitleDefaultVersion : COMPACT_TAB_TITLE_DEFAULT_VERSION;
|
||||
const hasCurrentCompactTabTitleDefault = compactTabTitleDefaultVersion === savedCompactTabTitleDefaultVersion;
|
||||
// The active id can only be validated once the scheme list it points into is known.
|
||||
const dataGridTypeColorSchemes = normalizeDataGridTypeColorSchemes(settings.dataGridTypeColorSchemes);
|
||||
const savedExtractorMigrationVersion = settings.dataGridExtractorOptionsMigrationVersion;
|
||||
@@ -2018,7 +2028,8 @@ export function normalizeEditorSettings(settings: Partial<EditorSettings>, exist
|
||||
savedSqlOpenTargetMode: settings.savedSqlOpenTargetMode === "current" ? "current" : DEFAULT_EDITOR_SETTINGS.savedSqlOpenTargetMode,
|
||||
welcomePageMode: hasCurrentWelcomePageDefault && (settings.welcomePageMode === "intro" || settings.welcomePageMode === "workspace") ? settings.welcomePageMode : DEFAULT_EDITOR_SETTINGS.welcomePageMode,
|
||||
welcomePageModeDefaultVersion,
|
||||
compactTabTitle: settings.compactTabTitle ?? DEFAULT_EDITOR_SETTINGS.compactTabTitle,
|
||||
compactTabTitle: hasCurrentCompactTabTitleDefault ? settings.compactTabTitle === true : DEFAULT_EDITOR_SETTINGS.compactTabTitle,
|
||||
compactTabTitleDefaultVersion,
|
||||
tabLayout: normalizeTabLayout(settings.tabLayout),
|
||||
tabPlacement: normalizeTabPlacement(settings.tabPlacement),
|
||||
colorizeConnectionTabs: typeof settings.colorizeConnectionTabs === "boolean" ? settings.colorizeConnectionTabs : DEFAULT_EDITOR_SETTINGS.colorizeConnectionTabs,
|
||||
@@ -2446,6 +2457,7 @@ export const useSettingsStore = defineStore("settings", () => {
|
||||
};
|
||||
const needsExecuteModeDefaultMigration = typeof savedSettings.executeModeDefaultVersion !== "number" || savedSettings.executeModeDefaultVersion < EXECUTE_MODE_CURRENT_DEFAULT_VERSION;
|
||||
const needsWelcomePageDefaultMigration = typeof savedSettings.welcomePageModeDefaultVersion !== "number" || savedSettings.welcomePageModeDefaultVersion < WELCOME_PAGE_DEFAULT_VERSION;
|
||||
const needsCompactTabTitleDefaultMigration = typeof savedSettings.compactTabTitleDefaultVersion !== "number" || savedSettings.compactTabTitleDefaultVersion < COMPACT_TAB_TITLE_DEFAULT_VERSION;
|
||||
const needsTabNavigationShortcutMigration = needsTabNavigationHistoryShortcutMigration(savedSettings.shortcuts);
|
||||
const savedNullText = (savedSettings.dataGridExtractorOptions as Partial<DataGridExtractorOptions> | undefined)?.dsv?.nullText;
|
||||
// v2 also resets a historically persisted includeDatabaseName=true, so
|
||||
@@ -2455,7 +2467,7 @@ export const useSettingsStore = defineStore("settings", () => {
|
||||
const needsDataGridExtractorOptionsMigration =
|
||||
(typeof savedSettings.dataGridExtractorOptionsMigrationVersion !== "number" || savedSettings.dataGridExtractorOptionsMigrationVersion < DATA_GRID_EXTRACTOR_OPTIONS_MIGRATION_VERSION) && (savedNullText === "NULL" || savedSqlIncludeDatabaseName === true);
|
||||
const savedUpdateDownloadSource = (saved as { updateDownloadSource?: unknown }).updateDownloadSource;
|
||||
if (savedUpdateDownloadSource === "atomgit" || needsExecuteModeDefaultMigration || needsWelcomePageDefaultMigration || needsTabNavigationShortcutMigration || needsSidebarBrowseObjectsMigration || needsDataGridExtractorOptionsMigration) {
|
||||
if (savedUpdateDownloadSource === "atomgit" || needsExecuteModeDefaultMigration || needsWelcomePageDefaultMigration || needsCompactTabTitleDefaultMigration || needsTabNavigationShortcutMigration || needsSidebarBrowseObjectsMigration || needsDataGridExtractorOptionsMigration) {
|
||||
// Persist one-time migrations so removed or unsafe defaults cannot reappear.
|
||||
await enqueueEditorSettingsSave().catch(() => {});
|
||||
}
|
||||
@@ -2903,7 +2915,12 @@ export const useSettingsStore = defineStore("settings", () => {
|
||||
if (partial.appCloseUnsavedTabsMode !== undefined) editorSettings.value.appCloseUnsavedTabsMode = normalizeAppCloseUnsavedTabsMode(partial.appCloseUnsavedTabsMode);
|
||||
if (partial.savedSqlOpenTargetMode !== undefined) editorSettings.value.savedSqlOpenTargetMode = partial.savedSqlOpenTargetMode === "current" ? "current" : "saved";
|
||||
if (partial.welcomePageMode !== undefined) editorSettings.value.welcomePageMode = partial.welcomePageMode === "intro" || partial.welcomePageMode === "workspace" ? partial.welcomePageMode : DEFAULT_EDITOR_SETTINGS.welcomePageMode;
|
||||
if (partial.compactTabTitle !== undefined) editorSettings.value.compactTabTitle = partial.compactTabTitle;
|
||||
if (partial.compactTabTitle !== undefined) {
|
||||
editorSettings.value.compactTabTitle = partial.compactTabTitle;
|
||||
// Stamping the current version marks this as a deliberate choice, so a
|
||||
// later default change must not overwrite it (see normalizeEditorSettings).
|
||||
editorSettings.value.compactTabTitleDefaultVersion = COMPACT_TAB_TITLE_DEFAULT_VERSION;
|
||||
}
|
||||
if (partial.tabLayout !== undefined) editorSettings.value.tabLayout = normalizeTabLayout(partial.tabLayout);
|
||||
if (partial.tabPlacement !== undefined) editorSettings.value.tabPlacement = normalizeTabPlacement(partial.tabPlacement);
|
||||
if (partial.colorizeConnectionTabs !== undefined) editorSettings.value.colorizeConnectionTabs = partial.colorizeConnectionTabs === true;
|
||||
|
||||
+13
-6
@@ -19,8 +19,15 @@ import {
|
||||
import i18n, { setLocale } from "../../apps/desktop/src/i18n/index.ts";
|
||||
import { restoreOpenTabsState } from "../../apps/desktop/src/lib/app/openTabsPersistence.ts";
|
||||
import { useConnectionStore } from "../../apps/desktop/src/stores/connectionStore.ts";
|
||||
import { useSettingsStore } from "../../apps/desktop/src/stores/settingsStore.ts";
|
||||
import type { ConnectionConfig, QueryResult, QueryTab } from "../../apps/desktop/src/types/database.ts";
|
||||
|
||||
function activateTestPinia() {
|
||||
setActivePinia(createPinia());
|
||||
// Keep legacy title assertions explicit now that compact titles are the default.
|
||||
useSettingsStore().editorSettings.compactTabTitle = false;
|
||||
}
|
||||
|
||||
function installMemoryStorage() {
|
||||
const values = new Map<string, string>();
|
||||
const original = Object.getOwnPropertyDescriptor(globalThis, "localStorage");
|
||||
@@ -76,7 +83,7 @@ function result(columns: string[], overrides: Partial<QueryResult> = {}): QueryR
|
||||
|
||||
test("query tab display title uses custom title when present", () => {
|
||||
const restoreStorage = installMemoryStorage();
|
||||
setActivePinia(createPinia());
|
||||
activateTestPinia();
|
||||
useConnectionStore().addEphemeralConnection(conn("conn-1"));
|
||||
const t = (key: string) => key;
|
||||
|
||||
@@ -90,7 +97,7 @@ test("query tab display title uses custom title when present", () => {
|
||||
|
||||
test("restored MQTT tab titles ignore legacy persisted text and follow the current locale", async () => {
|
||||
const restoreStorage = installMemoryStorage();
|
||||
setActivePinia(createPinia());
|
||||
activateTestPinia();
|
||||
useConnectionStore().addEphemeralConnection({
|
||||
...conn("conn-1"),
|
||||
name: "test-mqtt",
|
||||
@@ -125,7 +132,7 @@ test("restored MQTT tab titles ignore legacy persisted text and follow the curre
|
||||
|
||||
test("jdbc tabs use the connection target when database is empty", () => {
|
||||
const restoreStorage = installMemoryStorage();
|
||||
setActivePinia(createPinia());
|
||||
activateTestPinia();
|
||||
useConnectionStore().addEphemeralConnection({
|
||||
...conn("conn-1"),
|
||||
db_type: "jdbc",
|
||||
@@ -158,7 +165,7 @@ test("jdbc tabs use the connection target when database is empty", () => {
|
||||
|
||||
test("zookeeper tabs use key browser labels", () => {
|
||||
const restoreStorage = installMemoryStorage();
|
||||
setActivePinia(createPinia());
|
||||
activateTestPinia();
|
||||
useConnectionStore().addEphemeralConnection({
|
||||
...conn("conn-1"),
|
||||
name: "ZK Prod",
|
||||
@@ -178,7 +185,7 @@ test("zookeeper tabs use key browser labels", () => {
|
||||
|
||||
test("HBase tabs identify the table and namespace", () => {
|
||||
const restoreStorage = installMemoryStorage();
|
||||
setActivePinia(createPinia());
|
||||
activateTestPinia();
|
||||
useConnectionStore().addEphemeralConnection({
|
||||
...conn("conn-1"),
|
||||
name: "HBase Dev",
|
||||
@@ -198,7 +205,7 @@ test("HBase tabs identify the table and namespace", () => {
|
||||
|
||||
test("GridFS tabs use dedicated titles and labels", () => {
|
||||
const restoreStorage = installMemoryStorage();
|
||||
setActivePinia(createPinia());
|
||||
activateTestPinia();
|
||||
useConnectionStore().addEphemeralConnection({
|
||||
...conn("conn-1"),
|
||||
name: "uat-mongo",
|
||||
|
||||
Reference in New Issue
Block a user