* feat: demo DB seed/regenerate, backup/restore/sync refinements, SSH/SSL polish - Demo SQLite DB: feature-rich seed (12 objects, 500-row audit log) + regenerate action in Settings - Backup/restore: headless-testable core logic, psql -f for plain dumps, sync passes --clean --if-exists - SSH/SSL runtime refinements and connection testing improvements - Data grid: DataTypeIcon component, FK popover, table tree polish - Docs: AGENTS.md/README updates, new screenshots, MIT LICENSE * chore: optimize README screenshots (4.7 MB → 916 KB via pngquant, quality 70-90) * v0.6.0: release workflow, constraint-aware cell editing, pending-cell styling - Bump version to 0.6.0 across package.json, Cargo.toml, tauri.conf.json - Add .github/workflows/release.yml: tag-triggered CI builds macOS (aarch64 + x64), Windows, and Linux installers into a draft GitHub Release - README: installer download table (unsigned note, per-platform files), "how releases are made" section - CellEditor: constraint-aware commit — empty input on nullable columns becomes NULL, NOT NULL text-like types fall back to empty string, all other types blocked with an inline error bubble; replace "Set NULL" checkbox with a NULL row in the FK dropdown / empty enum option - VirtualDataGrid: pending-edit dot → animated pending outline (ring) on staged cells; matching test updates - docs-coverage test: align with rewritten README comparison table
73 lines
2.2 KiB
TypeScript
73 lines
2.2 KiB
TypeScript
import { describe, it, expect, beforeEach } from "vitest";
|
|
import { render, screen } from "@testing-library/react";
|
|
import userEvent from "@testing-library/user-event";
|
|
import { TableTree } from "./TableTree";
|
|
import { useDbViewerStore } from "../../stores/dbViewerStore";
|
|
|
|
describe("TableTree", () => {
|
|
beforeEach(() => {
|
|
useDbViewerStore.getState().reset();
|
|
});
|
|
|
|
it("renders table names from store", () => {
|
|
useDbViewerStore.setState({
|
|
schemas: ["public"],
|
|
currentSchema: "public",
|
|
tables: [
|
|
{ name: "users", schema: "public", table_type: "TABLE" },
|
|
{ name: "orders", schema: "public", table_type: "TABLE" },
|
|
],
|
|
});
|
|
render(<TableTree />);
|
|
expect(screen.getByText("users")).toBeInTheDocument();
|
|
expect(screen.getByText("orders")).toBeInTheDocument();
|
|
});
|
|
|
|
it("shows a distinct icon and label for materialized views", () => {
|
|
useDbViewerStore.setState({
|
|
schemas: ["public"],
|
|
currentSchema: "public",
|
|
tables: [
|
|
{
|
|
name: "mv_products",
|
|
schema: "public",
|
|
table_type: "MATERIALIZED VIEW" as any,
|
|
},
|
|
],
|
|
});
|
|
render(<TableTree />);
|
|
expect(screen.getByText("mv_products")).toBeInTheDocument();
|
|
expect(screen.getByText("Materialized View")).toBeInTheDocument();
|
|
});
|
|
|
|
it("shows a distinct icon and label for views", () => {
|
|
useDbViewerStore.setState({
|
|
schemas: ["public"],
|
|
currentSchema: "public",
|
|
tables: [
|
|
{
|
|
name: "order_summary",
|
|
schema: "public",
|
|
table_type: "VIEW",
|
|
},
|
|
],
|
|
});
|
|
render(<TableTree />);
|
|
expect(screen.getByText("order_summary")).toBeInTheDocument();
|
|
expect(screen.getByText("View")).toBeInTheDocument();
|
|
});
|
|
|
|
it("opens a tab when table is clicked", async () => {
|
|
const user = userEvent.setup();
|
|
useDbViewerStore.setState({
|
|
schemas: ["public"],
|
|
currentSchema: "public",
|
|
tables: [{ name: "users", schema: "public", table_type: "TABLE" }],
|
|
});
|
|
render(<TableTree />);
|
|
await user.click(screen.getByText("users"));
|
|
const state = useDbViewerStore.getState();
|
|
expect(state.tabs).toHaveLength(1);
|
|
expect(state.tabs[0]).toMatchObject({ schema: "public", table: "users" });
|
|
});
|
|
}); |