feat: establish unified administration and model context baseline
This commit is contained in:
@@ -14,6 +14,11 @@ import type {
|
||||
} from "../api/catalog-databases";
|
||||
import { Toaster } from "../components/ui/sonner";
|
||||
import { DatabaseManagementPage } from "./DatabaseManagementPage";
|
||||
import { workspacePreferences } from "../workspaces/preferences";
|
||||
import { ComposerFooter } from "./SteerInput";
|
||||
import { useSessionStore } from "../store/sessionStore";
|
||||
|
||||
beforeEach(() => { localStorage.clear(); });
|
||||
|
||||
const noSecrets = {
|
||||
password: false,
|
||||
@@ -142,7 +147,7 @@ function makeDescriptionGenerationRun(
|
||||
return {
|
||||
id: "77777777-7777-4777-8777-777777777777",
|
||||
databaseId: "11111111-1111-4111-8111-111111111111",
|
||||
modelId: "local-qwen",
|
||||
modelId: "local/qwen",
|
||||
scope: "selected_columns",
|
||||
language: "it",
|
||||
status: "queued",
|
||||
@@ -221,8 +226,8 @@ test("renders Fleet Ledger with real metrics, conceptual row tooltips, and persi
|
||||
updatedAt: "2026-08-31T09:00:00Z",
|
||||
})),
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
default: "local/qwen",
|
||||
})),
|
||||
);
|
||||
renderPage({ rows: [makeDatabase()], presentation: "fleet" });
|
||||
@@ -231,8 +236,8 @@ test("renders Fleet Ledger with real metrics, conceptual row tooltips, and persi
|
||||
expect(pageHeading).toBeVisible();
|
||||
const applicationBar = pageHeading.closest("header");
|
||||
expect(applicationBar).not.toBeNull();
|
||||
expect(within(applicationBar!).getByRole("region", { name: "Catalog status" })).toBeVisible();
|
||||
expect(within(applicationBar!).getByRole("group", { name: "Database management actions" })).toBeVisible();
|
||||
expect(screen.getByRole("region", { name: "Catalog status" })).toBeVisible();
|
||||
expect(screen.getByRole("group", { name: "Database management actions" })).toBeVisible();
|
||||
expect(screen.queryByText("Thoth catalog · Fleet ledger")).not.toBeInTheDocument();
|
||||
expect(screen.queryByText("Inspect physical metadata, curate descriptions and control catalog operations.")).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: "Back to workspace" })).not.toBeInTheDocument();
|
||||
@@ -241,8 +246,8 @@ test("renders Fleet Ledger with real metrics, conceptual row tooltips, and persi
|
||||
const summary = screen.getByRole("region", { name: "Fleet summary" });
|
||||
expect(await within(summary).findByText("2,275")).toBeVisible();
|
||||
expect(within(summary).getByText("75%")).toBeVisible();
|
||||
const modelSelector = await screen.findByRole("combobox", { name: "Metadata-generation LLM model" });
|
||||
expect(modelSelector).toHaveValue("local-qwen");
|
||||
const modelSelector = await screen.findByRole("combobox", { name: "Global LLM model" });
|
||||
expect(modelSelector).toHaveValue("local/qwen");
|
||||
|
||||
const databaseRow = await screen.findByRole("row", { name: /Policlinico San Donato/ });
|
||||
const tablesAction = within(databaseRow).getByRole("button", { name: "View tables for Policlinico San Donato" });
|
||||
@@ -253,10 +258,10 @@ test("renders Fleet Ledger with real metrics, conceptual row tooltips, and persi
|
||||
|
||||
const manager = screen.getByRole("main", { name: "Database management" });
|
||||
await user.click(within(databaseRow).getByRole("button", { name: "Edit Policlinico San Donato" }));
|
||||
const editDrawer = await screen.findByRole("dialog", { name: "Edit database" });
|
||||
const editDrawer = await screen.findByRole("region", { name: "Edit database form" });
|
||||
expect(manager).toContainElement(editDrawer);
|
||||
expect(editDrawer).toHaveAttribute("aria-modal", "false");
|
||||
await user.click(within(editDrawer).getByRole("button", { name: "Close database panel" }));
|
||||
expect(screen.queryByRole("dialog", { name: "Edit database" })).not.toBeInTheDocument();
|
||||
await user.click(within(editDrawer).getByRole("button", { name: "Back to list" }));
|
||||
|
||||
const restoredDatabaseRow = await screen.findByRole("row", { name: /Policlinico San Donato/ });
|
||||
await user.click(within(restoredDatabaseRow).getByRole("checkbox", { name: /toggle row selection/i }));
|
||||
@@ -264,8 +269,8 @@ test("renders Fleet Ledger with real metrics, conceptual row tooltips, and persi
|
||||
expect(within(actionPicker).getByRole("option", { name: /^Synchronize all(?:,|$)/ })).toBeVisible();
|
||||
expect(within(actionPicker).queryByRole("option", { name: "Synchronize all columns" })).not.toBeInTheDocument();
|
||||
await user.selectOptions(actionPicker, "generate-missing");
|
||||
expect(screen.getAllByRole("combobox", { name: "Metadata-generation LLM model" })).toHaveLength(1);
|
||||
expect(modelSelector).toHaveValue("local-qwen");
|
||||
expect(screen.getAllByRole("combobox", { name: "Global LLM model" })).toHaveLength(1);
|
||||
expect(modelSelector).toHaveValue("local/qwen");
|
||||
|
||||
});
|
||||
|
||||
@@ -471,7 +476,7 @@ test("offers catalog configuration directly on an unconfigured Fleet workspace",
|
||||
name: "Configure catalog for Research laboratory",
|
||||
}));
|
||||
|
||||
const drawer = await screen.findByRole("dialog", { name: "Configure catalog" });
|
||||
const drawer = await screen.findByRole("region", { name: "Configure catalog form" });
|
||||
expect(within(drawer).getByLabelText("Workspace")).toHaveAttribute("readonly");
|
||||
expect(within(drawer).getByLabelText("Workspace")).toHaveValue("Research laboratory");
|
||||
});
|
||||
@@ -555,7 +560,7 @@ test("reopens database synchronization history when no run is active", async ()
|
||||
await user.click(within(databaseRow).getByRole("button", {
|
||||
name: "View Policlinico San Donato",
|
||||
}));
|
||||
await user.click(screen.getByRole("button", { name: "Sync history" }));
|
||||
await user.click(screen.getByRole("button", { name: "View schema synchronization logs" }));
|
||||
|
||||
const drawer = await screen.findByRole("dialog", { name: "Schema synchronization" });
|
||||
expect(drawer).toBeVisible();
|
||||
@@ -567,22 +572,53 @@ test("reopens database synchronization history when no run is active", async ()
|
||||
test("selects the configured metadata-description model by default", async () => {
|
||||
server.use(http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [
|
||||
{ id: "openai-mini", label: "OpenAI Mini" },
|
||||
{ id: "local-qwen", label: "Local Qwen" },
|
||||
{ id: "openai/mini", label: "OpenAI Mini" },
|
||||
{ id: "local/qwen", label: "Local Qwen" },
|
||||
],
|
||||
default: "local-qwen",
|
||||
default: "local/qwen",
|
||||
})));
|
||||
renderPage();
|
||||
|
||||
const selector = await screen.findByRole("combobox", { name: "Metadata-generation LLM model" });
|
||||
await waitFor(() => expect(selector).toHaveValue("local-qwen"));
|
||||
const selector = await screen.findByRole("combobox", { name: "Global LLM model" });
|
||||
await waitFor(() => expect(selector).toHaveValue("local/qwen"));
|
||||
});
|
||||
|
||||
test("Core and Admin share one canonical selection, including models with the same short ID", async () => {
|
||||
const models = [{ id: "local/qwen", label: "Local Qwen" }, { id: "remote/qwen", label: "Remote Qwen" }];
|
||||
server.use(
|
||||
http.get("/api/catalog/databases", () => HttpResponse.json([makeDatabase()])),
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({ models, default: "local/qwen" })),
|
||||
http.get("/api/models", () => HttpResponse.json({ models: models.map((m) => ({
|
||||
provider: m.id.split("/")[0], id: "qwen", name: m.label, reasoning: false,
|
||||
})) })),
|
||||
http.get("/api/settings", () => HttpResponse.json({ provider: "local", model: "qwen" })),
|
||||
);
|
||||
const client = new QueryClient({ defaultOptions: { queries: { retry: false } } });
|
||||
render(<QueryClientProvider client={client}><ComposerFooter /><DatabaseManagementPage canManage canManageSecrets /></QueryClientProvider>);
|
||||
const admin = await screen.findByRole("combobox", { name: "Global LLM model" });
|
||||
const core = await screen.findByRole("combobox", { name: "Model" });
|
||||
await waitFor(() => expect(admin).toHaveValue("local/qwen"));
|
||||
act(() => useSessionStore.getState().setAgentActive(true));
|
||||
expect(core).toBeDisabled();
|
||||
expect(admin).toBeDisabled();
|
||||
act(() => useSessionStore.getState().setAgentActive(false));
|
||||
act(() => client.setQueryData(["description-generation-runs", 50], [makeDescriptionGenerationRun()]));
|
||||
await waitFor(() => expect(core).toBeDisabled());
|
||||
await waitFor(() => expect(admin).toBeDisabled());
|
||||
act(() => client.setQueryData(["description-generation-runs", 50], []));
|
||||
await waitFor(() => expect(core).toBeEnabled());
|
||||
await waitFor(() => expect(admin).toBeEnabled());
|
||||
await userEvent.selectOptions(admin, "remote/qwen");
|
||||
await waitFor(() => expect(core).toHaveValue("remote/qwen"));
|
||||
await userEvent.selectOptions(core, "local/qwen");
|
||||
await waitFor(() => expect(admin).toHaveValue("local/qwen"));
|
||||
});
|
||||
|
||||
test("keeps both run-history buttons visible beside the metadata-description selector", async () => {
|
||||
const user = userEvent.setup();
|
||||
renderPage();
|
||||
|
||||
const selector = await screen.findByRole("combobox", { name: "Metadata-generation LLM model" });
|
||||
const selector = await screen.findByRole("combobox", { name: "Global LLM model" });
|
||||
const toolbar = screen.getByRole("group", { name: "Database management controls" });
|
||||
const metadataControls = screen.getByRole("group", { name: "Metadata description controls" });
|
||||
const actions = screen.getByRole("group", { name: "Database management actions" });
|
||||
@@ -622,22 +658,23 @@ test("keeps both run-history buttons visible beside the metadata-description sel
|
||||
expect(within(suggestionDrawer).getByText("No sensitivity analysis runs yet.")).toBeVisible();
|
||||
});
|
||||
|
||||
test("changes the metadata-description model in page-local state", async () => {
|
||||
test("changes the global model shared with Core", async () => {
|
||||
const user = userEvent.setup();
|
||||
server.use(http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [
|
||||
{ id: "openai-mini", label: "OpenAI Mini" },
|
||||
{ id: "local-qwen", label: "Local Qwen" },
|
||||
{ id: "openai/mini", label: "OpenAI Mini" },
|
||||
{ id: "local/qwen", label: "Local Qwen" },
|
||||
],
|
||||
default: "local-qwen",
|
||||
default: "local/qwen",
|
||||
})));
|
||||
renderPage();
|
||||
|
||||
const selector = await screen.findByRole("combobox", { name: "Metadata-generation LLM model" });
|
||||
await waitFor(() => expect(selector).toHaveValue("local-qwen"));
|
||||
await user.selectOptions(selector, "openai-mini");
|
||||
const selector = await screen.findByRole("combobox", { name: "Global LLM model" });
|
||||
await waitFor(() => expect(selector).toHaveValue("local/qwen"));
|
||||
await user.selectOptions(selector, "openai/mini");
|
||||
|
||||
expect(selector).toHaveValue("openai-mini");
|
||||
expect(selector).toHaveValue("openai/mini");
|
||||
expect(workspacePreferences.load()).toMatchObject({ provider: "openai", model: "mini" });
|
||||
});
|
||||
|
||||
test("explains application setup when no metadata-description model is configured", async () => {
|
||||
@@ -647,7 +684,7 @@ test("explains application setup when no metadata-description model is configure
|
||||
})));
|
||||
renderPage();
|
||||
|
||||
const selector = await screen.findByRole("combobox", { name: "Metadata-generation LLM model" });
|
||||
const selector = await screen.findByRole("combobox", { name: "Global LLM model" });
|
||||
expect(selector).toBeDisabled();
|
||||
expect(await screen.findByText(
|
||||
"No metadata-generation LLM model is configured for this installation.",
|
||||
@@ -661,11 +698,11 @@ test("uses a safe disabled setup state when metadata-description models are unav
|
||||
}, { status: 503 })));
|
||||
renderPage();
|
||||
|
||||
const selector = await screen.findByRole("combobox", { name: "Metadata-generation LLM model" });
|
||||
const selector = await screen.findByRole("combobox", { name: "Global LLM model" });
|
||||
await waitFor(() => expect(selector).toHaveDisplayValue("Model choices unavailable"));
|
||||
expect(selector).toBeDisabled();
|
||||
expect(screen.getByText(
|
||||
"Metadata-generation LLM model choices are unavailable.",
|
||||
"Global LLM model choices are unavailable.",
|
||||
)).toBeVisible();
|
||||
expect(screen.queryByText("internal model registry details")).not.toBeInTheDocument();
|
||||
});
|
||||
@@ -674,12 +711,12 @@ test.each([null, "missing-model"])(
|
||||
"disables metadata-description selection when the public response has no usable default (%s)",
|
||||
async (configuredDefault) => {
|
||||
server.use(http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "openai-mini", label: "OpenAI Mini" }],
|
||||
models: [{ id: "openai/mini", label: "OpenAI Mini" }],
|
||||
default: configuredDefault,
|
||||
})));
|
||||
renderPage();
|
||||
|
||||
const selector = await screen.findByRole("combobox", { name: "Metadata-generation LLM model" });
|
||||
const selector = await screen.findByRole("combobox", { name: "Global LLM model" });
|
||||
await waitFor(() => expect(selector).toHaveDisplayValue("No usable model configured"));
|
||||
expect(selector).toBeDisabled();
|
||||
expect(screen.getByText(
|
||||
@@ -691,7 +728,7 @@ test.each([null, "missing-model"])(
|
||||
test("renders only the public metadata-generation model contract", async () => {
|
||||
server.use(http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{
|
||||
id: "approved-model",
|
||||
id: "approved/model",
|
||||
label: "Approved model",
|
||||
provider: "private-provider",
|
||||
model: "private/upstream-model",
|
||||
@@ -699,12 +736,12 @@ test("renders only the public metadata-generation model contract", async () => {
|
||||
apiKeyEnv: "PRIVATE_MODEL_API_KEY",
|
||||
credential: "raw-private-credential",
|
||||
}],
|
||||
default: "approved-model",
|
||||
default: "approved/model",
|
||||
})));
|
||||
renderPage();
|
||||
|
||||
const selector = await screen.findByRole("combobox", { name: "Metadata-generation LLM model" });
|
||||
await waitFor(() => expect(selector).toHaveValue("approved-model"));
|
||||
const selector = await screen.findByRole("combobox", { name: "Global LLM model" });
|
||||
await waitFor(() => expect(selector).toHaveValue("approved/model"));
|
||||
expect(within(selector).getAllByRole("option").map((option) => option.textContent))
|
||||
.toEqual(["Approved model"]);
|
||||
expect(document.body).not.toHaveTextContent(/private-provider|private\/upstream-model/);
|
||||
@@ -766,8 +803,8 @@ test("discloses source sampling before starting Generate missing descriptions",
|
||||
let startBody: unknown;
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
default: "local/qwen",
|
||||
})),
|
||||
http.post("/api/catalog/databases/:databaseId/description-generation-runs", async ({ request }) => {
|
||||
startBody = await request.json();
|
||||
@@ -793,7 +830,7 @@ test("discloses source sampling before starting Generate missing descriptions",
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "Generate missing descriptions" }));
|
||||
await waitFor(() => expect(startBody).toEqual({
|
||||
modelId: "local-qwen",
|
||||
modelId: "local/qwen",
|
||||
scope: "missing",
|
||||
}));
|
||||
expect(screen.queryByText(/replace existing generated descriptions/i)).not.toBeInTheDocument();
|
||||
@@ -805,8 +842,8 @@ test("keeps Fleet Generate missing descriptions behind the source-data disclosur
|
||||
let generationStarts = 0;
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
default: "local/qwen",
|
||||
})),
|
||||
http.post("/api/catalog/databases/:databaseId/description-generation-runs", () => {
|
||||
generationStarts += 1;
|
||||
@@ -822,8 +859,8 @@ test("keeps Fleet Generate missing descriptions behind the source-data disclosur
|
||||
"generate-missing",
|
||||
);
|
||||
await waitFor(() => expect(screen.getByRole("combobox", {
|
||||
name: "Metadata-generation LLM model",
|
||||
})).toHaveValue("local-qwen"));
|
||||
name: "Global LLM model",
|
||||
})).toHaveValue("local/qwen"));
|
||||
await user.click(screen.getByRole("button", { name: "Run action" }));
|
||||
|
||||
expect(screen.getByRole("note", {
|
||||
@@ -896,8 +933,8 @@ test("confirms generating all descriptions, supports cancel, and sends the datab
|
||||
let startBody: unknown;
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
default: "local/qwen",
|
||||
})),
|
||||
http.post("/api/catalog/databases/:databaseId/description-generation-runs", async ({ request }) => {
|
||||
startBody = await request.json();
|
||||
@@ -929,7 +966,7 @@ test("confirms generating all descriptions, supports cancel, and sends the datab
|
||||
await user.click(screen.getByRole("button", { name: "Generate all descriptions" }));
|
||||
|
||||
await waitFor(() => expect(startBody).toEqual({
|
||||
modelId: "local-qwen",
|
||||
modelId: "local/qwen",
|
||||
scope: "all",
|
||||
}));
|
||||
expect(await screen.findByRole("dialog", { name: "Description generation" })).toBeVisible();
|
||||
@@ -939,8 +976,8 @@ test("keeps the database selected and safely explains when no descriptions are e
|
||||
const user = userEvent.setup();
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
default: "local/qwen",
|
||||
})),
|
||||
http.post("/api/catalog/databases/:databaseId/description-generation-runs", () => HttpResponse.json({
|
||||
code: "description_generation_no_eligible_targets",
|
||||
@@ -985,8 +1022,8 @@ test.each([
|
||||
});
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
default: "local/qwen",
|
||||
})),
|
||||
http.post("/api/catalog/databases/:databaseId/description-generation-runs", () => (
|
||||
HttpResponse.json(queuedRun, { status: 202 })
|
||||
@@ -1036,8 +1073,8 @@ test.each([
|
||||
reason: "database.manage is absent",
|
||||
canManage: false,
|
||||
rows: [makeDatabase()],
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
configuredDefault: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
configuredDefault: "local/qwen",
|
||||
selectedRows: 1,
|
||||
},
|
||||
{
|
||||
@@ -1052,8 +1089,8 @@ test.each([
|
||||
reason: "the Workspace Database is not configured",
|
||||
canManage: true,
|
||||
rows: [unconfigured],
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
configuredDefault: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
configuredDefault: "local/qwen",
|
||||
selectedRows: 1,
|
||||
},
|
||||
{
|
||||
@@ -1067,8 +1104,8 @@ test.each([
|
||||
workspaceName: "Radiology",
|
||||
}),
|
||||
],
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
configuredDefault: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
configuredDefault: "local/qwen",
|
||||
selectedRows: 2,
|
||||
},
|
||||
])("disables database-wide generation when $reason", async ({
|
||||
@@ -1102,8 +1139,8 @@ test("disables database-wide generation while a description generation is active
|
||||
const queuedRun = makeDescriptionGenerationRun({ scope: "missing" });
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
default: "local/qwen",
|
||||
})),
|
||||
http.post("/api/catalog/databases/:databaseId/description-generation-runs", () => (
|
||||
HttpResponse.json(queuedRun, { status: 202 })
|
||||
@@ -1871,8 +1908,8 @@ test("starts description generation for multiple selected tables", async () => {
|
||||
let startBody: unknown;
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
default: "local/qwen",
|
||||
})),
|
||||
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([
|
||||
patientsTable,
|
||||
@@ -1903,7 +1940,7 @@ test("starts description generation for multiple selected tables", async () => {
|
||||
await user.click(generate);
|
||||
|
||||
await waitFor(() => expect(startBody).toEqual({
|
||||
modelId: "local-qwen",
|
||||
modelId: "local/qwen",
|
||||
scope: "selected_tables",
|
||||
targetIds: [patientsTable.id, visitsTable.id],
|
||||
}));
|
||||
@@ -1919,7 +1956,7 @@ test("generates descriptions for every column in selected tables", async () => {
|
||||
const queuedRun = makeDescriptionGenerationRun({ scope: "selected_columns", total: 1 });
|
||||
let startBody: unknown;
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({ models: [{ id: "local-qwen", label: "Local Qwen" }], default: "local-qwen" })),
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({ models: [{ id: "local/qwen", label: "Local Qwen" }], default: "local/qwen" })),
|
||||
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([patientsTable])),
|
||||
http.get(`/api/catalog/databases/:databaseId/tables/${patientsTable.id}/columns`, () => HttpResponse.json([patientIdColumn])),
|
||||
http.post("/api/catalog/databases/:databaseId/description-generation-runs", async ({ request }) => {
|
||||
@@ -1938,7 +1975,7 @@ test("generates descriptions for every column in selected tables", async () => {
|
||||
await user.click(await screen.findByRole("menuitem", { name: "Generate descriptions for all columns" }));
|
||||
|
||||
await waitFor(() => expect(startBody).toEqual({
|
||||
modelId: "local-qwen",
|
||||
modelId: "local/qwen",
|
||||
scope: "selected_columns",
|
||||
targetIds: [patientIdColumn.id],
|
||||
}));
|
||||
@@ -2059,8 +2096,8 @@ test("keeps selected tables when description generation cannot start", async ()
|
||||
};
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
default: "local/qwen",
|
||||
})),
|
||||
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([
|
||||
patientsTable,
|
||||
@@ -2113,8 +2150,8 @@ test("refreshes Catalog Tables and Catalog Columns after table generation comple
|
||||
let tableReads = 0;
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
default: "local/qwen",
|
||||
})),
|
||||
http.get("/api/catalog/databases/:databaseId/tables", () => {
|
||||
tableReads += 1;
|
||||
@@ -2320,10 +2357,10 @@ test("starts one selected column with the configured default model", async () =>
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [
|
||||
{ id: "openai-mini", label: "OpenAI Mini" },
|
||||
{ id: "local-qwen", label: "Local Qwen" },
|
||||
{ id: "openai/mini", label: "OpenAI Mini" },
|
||||
{ id: "local/qwen", label: "Local Qwen" },
|
||||
],
|
||||
default: "local-qwen",
|
||||
default: "local/qwen",
|
||||
})),
|
||||
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([patientsTable])),
|
||||
http.get("/api/catalog/databases/:databaseId/tables/:tableId/columns", () => HttpResponse.json([patientIdColumn])),
|
||||
@@ -2353,7 +2390,7 @@ test("starts one selected column with the configured default model", async () =>
|
||||
await user.click(await screen.findByRole("menuitem", { name: "Generate column description" }));
|
||||
|
||||
await waitFor(() => expect(startBody).toEqual({
|
||||
modelId: "local-qwen",
|
||||
modelId: "local/qwen",
|
||||
scope: "selected_columns",
|
||||
targetIds: [patientIdColumn.id],
|
||||
}));
|
||||
@@ -2373,8 +2410,8 @@ test("shows database sensitivity analysis only for a selection and rejects multi
|
||||
});
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
default: "local/qwen",
|
||||
})),
|
||||
http.post("/api/catalog/databases/:databaseId/sensitive-data-suggestions", () => {
|
||||
suggestionCalls += 1;
|
||||
@@ -2495,8 +2532,8 @@ test("requests database-level sensitivity analysis for the only selected databas
|
||||
const run = makeSensitivityAnalysisRun({ scope: "all", total: 1 });
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
default: "local/qwen",
|
||||
})),
|
||||
http.get("/api/catalog/sensitive-data-suggestion-runs", () => {
|
||||
historyCalls += 1;
|
||||
@@ -2539,8 +2576,8 @@ test("refetches sensitivity analysis history after a failed request", async () =
|
||||
let historyCalls = 0;
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
default: "local/qwen",
|
||||
})),
|
||||
http.get("/api/catalog/sensitive-data-suggestion-runs", () => {
|
||||
historyCalls += 1;
|
||||
@@ -2579,8 +2616,8 @@ test("requests sensitivity analysis only for selected tables", async () => {
|
||||
let suggestionBody: unknown;
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
default: "local/qwen",
|
||||
})),
|
||||
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([
|
||||
patientsTable,
|
||||
@@ -2650,8 +2687,8 @@ test("allows a human downgrade and saves only explicit sensitivity changes", asy
|
||||
const patches: Array<{ columnId: string; body: unknown }> = [];
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
default: "local/qwen",
|
||||
})),
|
||||
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([patientsTable])),
|
||||
http.get(
|
||||
@@ -2777,8 +2814,8 @@ test("polls a description run and renders its events in sequence order", async (
|
||||
const eventAfters: number[] = [];
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
default: "local/qwen",
|
||||
})),
|
||||
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([patientsTable])),
|
||||
http.get("/api/catalog/databases/:databaseId/tables/:tableId/columns", () => HttpResponse.json([patientIdColumn])),
|
||||
@@ -2814,7 +2851,7 @@ test("polls a description run and renders its events in sequence order", async (
|
||||
await user.click(await screen.findByRole("menuitem", { name: "Generate column description" }));
|
||||
|
||||
const drawer = await screen.findByRole("dialog", { name: "Description generation" });
|
||||
expect(within(drawer).getByText(/local-qwen/)).toBeVisible();
|
||||
expect(within(drawer).getByText(/local[/]qwen/)).toBeVisible();
|
||||
expect(within(drawer).getByText(/selected columns/)).toBeVisible();
|
||||
expect(await within(drawer).findByRole("heading", { name: "Completed" }, { timeout: 4_000 })).toBeVisible();
|
||||
expect(within(drawer).getByText("1", { selector: "[data-count='total']" })).toBeVisible();
|
||||
@@ -2852,8 +2889,8 @@ test("refreshes Catalog Tables and Catalog Columns after column generation compl
|
||||
let columns = [patientIdColumn];
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
default: "local/qwen",
|
||||
})),
|
||||
http.get("/api/catalog/databases/:databaseId/tables", () => {
|
||||
tableReads += 1;
|
||||
@@ -2907,8 +2944,8 @@ test("keeps the selected column and shows a safe message when generation cannot
|
||||
const user = userEvent.setup();
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
default: "local/qwen",
|
||||
})),
|
||||
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([patientsTable])),
|
||||
http.get("/api/catalog/databases/:databaseId/tables/:tableId/columns", () => HttpResponse.json([patientIdColumn])),
|
||||
@@ -2938,13 +2975,13 @@ test("shows a basic failed run without exposing private model or provider fields
|
||||
const user = userEvent.setup();
|
||||
let columnReads = 0;
|
||||
const queuedRun = {
|
||||
...makeDescriptionGenerationRun({ modelId: "approved-model" }),
|
||||
...makeDescriptionGenerationRun({ modelId: "approved/model" }),
|
||||
provider: "private-provider",
|
||||
apiKey: "sk-private-key",
|
||||
};
|
||||
const failedRun = {
|
||||
...makeDescriptionGenerationRun({
|
||||
modelId: "approved-model",
|
||||
modelId: "approved/model",
|
||||
status: "failed",
|
||||
processed: 1,
|
||||
failed: 1,
|
||||
@@ -2963,13 +3000,13 @@ test("shows a basic failed run without exposing private model or provider fields
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{
|
||||
id: "approved-model",
|
||||
id: "approved/model",
|
||||
label: "Approved model",
|
||||
provider: "private-provider",
|
||||
upstreamModel: "private/upstream-model",
|
||||
apiKeyEnv: "PRIVATE_MODEL_API_KEY",
|
||||
}],
|
||||
default: "approved-model",
|
||||
default: "approved/model",
|
||||
})),
|
||||
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([patientsTable])),
|
||||
http.get("/api/catalog/databases/:databaseId/tables/:tableId/columns", () => {
|
||||
@@ -3022,8 +3059,8 @@ test("offers generation and consolidation for multiple selected columns", async
|
||||
let startBody: unknown;
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
default: "local/qwen",
|
||||
})),
|
||||
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([patientsTable])),
|
||||
http.get("/api/catalog/databases/:databaseId/tables/:tableId/columns", () => (
|
||||
@@ -3063,7 +3100,7 @@ test("offers generation and consolidation for multiple selected columns", async
|
||||
await user.click(generate);
|
||||
|
||||
await waitFor(() => expect(startBody).toEqual({
|
||||
modelId: "local-qwen",
|
||||
modelId: "local/qwen",
|
||||
scope: "selected_columns",
|
||||
targetIds: [patientIdColumn.id, patientNameColumn.id],
|
||||
}));
|
||||
@@ -3072,7 +3109,7 @@ test("offers generation and consolidation for multiple selected columns", async
|
||||
});
|
||||
|
||||
test.each([
|
||||
{ name: "database.manage is absent", canManage: false, models: [{ id: "local-qwen", label: "Local Qwen" }], configuredDefault: "local-qwen" },
|
||||
{ name: "database.manage is absent", canManage: false, models: [{ id: "local/qwen", label: "Local Qwen" }], configuredDefault: "local/qwen" },
|
||||
{ name: "no usable model is configured", canManage: true, models: [], configuredDefault: null },
|
||||
])("disables selected table and column generation when $name", async ({ canManage, models, configuredDefault }) => {
|
||||
const user = userEvent.setup();
|
||||
@@ -3113,8 +3150,8 @@ test("disables another generation start while the selected-column run is active"
|
||||
const queuedRun = makeDescriptionGenerationRun();
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
models: [{ id: "local/qwen", label: "Local Qwen" }],
|
||||
default: "local/qwen",
|
||||
})),
|
||||
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([patientsTable])),
|
||||
http.get("/api/catalog/databases/:databaseId/tables/:tableId/columns", () => HttpResponse.json([patientIdColumn])),
|
||||
|
||||
Reference in New Issue
Block a user