feat: Query history + saved queries (#5)
* fix: restore frontend test baseline (vitest jsdom env + tsc + mock fixes) * feat: v6 migration — favorite column + queries table (Task 1) * feat: extend TS types for favorites + saved queries (Task 2) * feat: dedup consecutive + prune to 500 in insert_query_history (Task 3) * feat: favorite column threading + set_history_favorite command (Task 4) * feat: saved queries store CRUD (Task 5) * feat: saved query commands + registration (Task 6) * feat: queryStore — Zustand cache for history + saved queries (Task 7) * feat: QueryHistoryDropdown — toolbar history dropdown (Task 8) * feat: SaveQueryDialog — save query modal (Task 9) * feat: QueryToolbar — add History + Save icons (Task 10) * feat: QueriesPanel — History + Saved tabs (Task 11) * feat: wire Queries view + toolbar to panel (Task 12) * fix: global scope wrappers, empty/spinner states, cache invalidation (Task 13) * feat: Queries view — history sidebar + tabbed query workspace (PR feedback) * fix: toolbar action order + view-specific empty state (PR feedback) * fix: view-specific empty state icon (PR feedback) * fix: portal Tooltip to body so it is never clipped by overflow containers (PR feedback) * feat: Queries sidebar — Explorer-style header + per-connection scoping (PR feedback) * fix: move History/Saved dropdown to right side of Queries header (PR feedback) * fix: History/Saved dropdown on its own row in Queries header (PR feedback) * fix: Queries header order (search above dropdown) + sidebar width matches Explorer (PR feedback) * fix: Queries header spacing — tight rows, pb-3 on container (PR feedback) * fix: Queries header spacing — space-y-2 on container, no mb on title row (PR feedback) * feat: history/saved rows click-to-load, remove sub-buttons (PR feedback) * feat: merge Functions/Triggers/Sequences/Enums/Extensions into single Objects view (PR feedback) * fix: Schema Visualizer nav icon — node graph glyph (PR feedback) * fix: Objects view — type dropdown replaces static header label (PR feedback) * fix: Objects empty state — remove bg circle, larger icon (PR feedback) * fix: center icon in Objects empty state (PR feedback) * feat: merge Backup/Restore/DB Sync into single Tools view (PR feedback) * docs: update AGENTS.md + README for query history/saved queries, merged Objects + Tools views
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
// Bun test runner DOM setup: `bun test` uses Bun's native runner, which does
|
||||
// not read vite.config.ts and provides no DOM. Register jsdom globals (plus the
|
||||
// ResizeObserver polyfill used by @xyflow/react) so the vitest-authored suite
|
||||
// runs under `bun test` too. This MUST load before any module that imports
|
||||
// @testing-library/react, because bun caches modules process-wide and
|
||||
// testing-library's `screen` binds `document.body` at module-evaluation time.
|
||||
import { JSDOM } from "jsdom";
|
||||
|
||||
if (typeof globalThis.document === "undefined") {
|
||||
const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>", {
|
||||
url: "http://localhost/",
|
||||
pretendToBeVisual: true,
|
||||
});
|
||||
|
||||
const { window } = dom;
|
||||
for (const key of Object.getOwnPropertyNames(window)) {
|
||||
if (
|
||||
key !== "window" &&
|
||||
key !== "self" &&
|
||||
key !== "top" &&
|
||||
!(key in globalThis)
|
||||
) {
|
||||
(globalThis as Record<string, unknown>)[key] = (
|
||||
window as unknown as Record<string, unknown>
|
||||
)[key];
|
||||
}
|
||||
}
|
||||
globalThis.window = window as unknown as Window & typeof globalThis;
|
||||
globalThis.document = window.document;
|
||||
globalThis.navigator = window.navigator;
|
||||
globalThis.HTMLElement = window.HTMLElement;
|
||||
globalThis.Element = window.Element;
|
||||
globalThis.Node = window.Node;
|
||||
globalThis.getComputedStyle = window.getComputedStyle.bind(window);
|
||||
globalThis.requestAnimationFrame = (cb: FrameRequestCallback) =>
|
||||
setTimeout(() => cb(Date.now()), 0) as unknown as number;
|
||||
globalThis.cancelAnimationFrame = (id: number) => clearTimeout(id);
|
||||
globalThis.matchMedia =
|
||||
globalThis.matchMedia ||
|
||||
((query: string) => ({
|
||||
matches: false,
|
||||
media: query,
|
||||
onchange: null,
|
||||
addListener: () => {},
|
||||
removeListener: () => {},
|
||||
addEventListener: () => {},
|
||||
removeEventListener: () => {},
|
||||
dispatchEvent: () => false,
|
||||
}));
|
||||
}
|
||||
|
||||
// Polyfill ResizeObserver for jsdom (required by @xyflow/react)
|
||||
if (typeof globalThis.ResizeObserver === "undefined") {
|
||||
globalThis.ResizeObserver = class ResizeObserver {
|
||||
observe() {}
|
||||
unobserve() {}
|
||||
disconnect() {}
|
||||
};
|
||||
}
|
||||
|
||||
// jsdom does not implement the execCommand family; monaco-editor probes
|
||||
// document.queryCommandSupported at import time and crashes without it.
|
||||
if (typeof globalThis.document.queryCommandSupported !== "function") {
|
||||
globalThis.document.queryCommandSupported = () => false;
|
||||
globalThis.document.queryCommandEnabled = () => false;
|
||||
globalThis.document.execCommand = () => false;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Bun test runner setup: register testing-library cleanup (bun does not inject
|
||||
// a global `afterEach`, so RTL's auto-cleanup never hooks in) and minimal
|
||||
// vitest-compat shims for `vi.mocked`/`vi.hoisted` (bun's compat `vi` omits
|
||||
// them). Loaded via bunfig.toml [test].preload — bun-dom.ts must run first so
|
||||
// `document` exists before @testing-library/react evaluates.
|
||||
import { afterEach, vi } from "vitest";
|
||||
import { cleanup } from "@testing-library/react";
|
||||
import "@testing-library/jest-dom";
|
||||
|
||||
// NOTE: under `bun test`, importing from "vitest" resolves to bun's built-in
|
||||
// vitest-compat module (which provides afterEach and a limited vi), while under
|
||||
// `tsc` it resolves to the real vitest types.
|
||||
|
||||
// @testing-library/react auto-cleanup relies on a global `afterEach`, which
|
||||
// bun does not inject; register it explicitly so DOM doesn't leak between tests.
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
});
|
||||
|
||||
// Minimal vi shims matching vitest semantics used by the suite.
|
||||
(vi as unknown as { mocked: unknown }).mocked = (m: unknown) => m;
|
||||
(vi as unknown as { hoisted: unknown }).hoisted = <T>(factory: () => T): T =>
|
||||
factory();
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
// jsdom ships no type declarations and @types/jsdom is not installed; this
|
||||
// ambient declaration keeps `src/test/bun-dom.ts` (used only by `bun test`)
|
||||
// type-clean. The JSDOM API is consumed through `any`.
|
||||
declare module "jsdom";
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import "@testing-library/jest-dom";
|
||||
|
||||
// Polyfill ResizeObserver for jsdom (required by @xyflow/react)
|
||||
global.ResizeObserver = class ResizeObserver {
|
||||
globalThis.ResizeObserver = class ResizeObserver {
|
||||
observe() {}
|
||||
unobserve() {}
|
||||
disconnect() {}
|
||||
|
||||
Reference in New Issue
Block a user