fix: scope and batch sensitive suggestions
This commit is contained in:
@@ -1571,6 +1571,125 @@ test("starts one selected column with the configured default model", async () =>
|
||||
expect(await screen.findByText("Description generation started for 1 column")).toBeVisible();
|
||||
});
|
||||
|
||||
test("shows database sensitive suggestions only for a selection and rejects multiple databases clearly", async () => {
|
||||
const user = userEvent.setup();
|
||||
let suggestionCalls = 0;
|
||||
const radiology = makeDatabase({
|
||||
id: "44444444-4444-4444-8444-444444444444",
|
||||
workspaceId: "radiology",
|
||||
workspaceName: "Radiology",
|
||||
});
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
})),
|
||||
http.post("/api/catalog/databases/:databaseId/sensitive-data-suggestions", () => {
|
||||
suggestionCalls += 1;
|
||||
return HttpResponse.json({ suggestions: [] });
|
||||
}),
|
||||
);
|
||||
renderPage({ rows: [makeDatabase(), radiology] });
|
||||
|
||||
expect(screen.queryByRole("button", { name: "Suggest sensitive fields" })).not.toBeInTheDocument();
|
||||
const psdRow = await screen.findByRole("row", { name: /Policlinico San Donato/ });
|
||||
const radiologyRow = await screen.findByRole("row", { name: /Radiology/ });
|
||||
await user.click(within(psdRow).getByRole("checkbox", { name: /toggle row selection/i }));
|
||||
expect(screen.getByRole("button", { name: "Suggest sensitive fields" })).toBeVisible();
|
||||
await user.click(within(radiologyRow).getByRole("checkbox", { name: /toggle row selection/i }));
|
||||
await user.click(screen.getByRole("button", { name: "Suggest sensitive fields" }));
|
||||
|
||||
expect(await screen.findByText("Sensitive-field suggestions can be requested for only one database at a time. Select one database and try again.")).toBeVisible();
|
||||
expect(suggestionCalls).toBe(0);
|
||||
});
|
||||
|
||||
test("requests database-level sensitive suggestions for the only selected database", async () => {
|
||||
const user = userEvent.setup();
|
||||
let suggestionBody: unknown;
|
||||
server.use(
|
||||
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
|
||||
models: [{ id: "local-qwen", label: "Local Qwen" }],
|
||||
default: "local-qwen",
|
||||
})),
|
||||
http.post("/api/catalog/databases/:databaseId/sensitive-data-suggestions", async ({ request }) => {
|
||||
suggestionBody = await request.json();
|
||||
return HttpResponse.json({
|
||||
suggestions: [{
|
||||
columnId: patientIdColumn.id,
|
||||
tableId: patientsTable.id,
|
||||
tableName: patientsTable.name,
|
||||
columnName: patientIdColumn.name,
|
||||
version: patientIdColumn.version,
|
||||
currentSensitive: false,
|
||||
sensitive: true,
|
||||
}],
|
||||
});
|
||||
}),
|
||||
);
|
||||
renderPage({ rows: [makeDatabase()] });
|
||||
|
||||
const databaseRow = await screen.findByRole("row", { name: /Policlinico San Donato/ });
|
||||
await user.click(within(databaseRow).getByRole("checkbox", { name: /toggle row selection/i }));
|
||||
await user.click(screen.getByRole("button", { name: "Suggest sensitive fields" }));
|
||||
|
||||
await waitFor(() => expect(suggestionBody).toEqual({ modelId: "local-qwen", scope: "all" }));
|
||||
expect(await screen.findByRole("complementary", { name: "Sensitive field review" })).toBeVisible();
|
||||
});
|
||||
|
||||
test("requests sensitive suggestions only for selected tables", async () => {
|
||||
const user = userEvent.setup();
|
||||
const visitsTable: CatalogTable = {
|
||||
...patientsTable,
|
||||
id: "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
|
||||
name: "visits",
|
||||
};
|
||||
const visitColumn = {
|
||||
...patientIdColumn,
|
||||
id: "eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee",
|
||||
tableId: visitsTable.id,
|
||||
name: "clinical_note",
|
||||
};
|
||||
let suggestionBody: 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/databases/:databaseId/tables", () => HttpResponse.json([
|
||||
patientsTable,
|
||||
visitsTable,
|
||||
])),
|
||||
http.post("/api/catalog/databases/:databaseId/sensitive-data-suggestions", async ({ request }) => {
|
||||
suggestionBody = await request.json();
|
||||
return HttpResponse.json({
|
||||
suggestions: [{
|
||||
columnId: visitColumn.id,
|
||||
tableId: visitsTable.id,
|
||||
tableName: visitsTable.name,
|
||||
columnName: visitColumn.name,
|
||||
version: visitColumn.version,
|
||||
currentSensitive: false,
|
||||
sensitive: true,
|
||||
}],
|
||||
});
|
||||
}),
|
||||
);
|
||||
renderPage({ rows: [makeDatabase({ connectionStatus: "reachable", testedVersion: 3 })] });
|
||||
|
||||
await user.click(await screen.findByRole("button", { name: "View Policlinico San Donato" }));
|
||||
await user.click(screen.getByRole("tab", { name: "Tables" }));
|
||||
const visitsRow = await screen.findByRole("row", { name: /visits/ });
|
||||
await user.click(within(visitsRow).getByRole("checkbox", { name: /toggle row selection/i }));
|
||||
await user.click(screen.getByRole("button", { name: "Suggest sensitive fields" }));
|
||||
|
||||
await waitFor(() => expect(suggestionBody).toEqual({
|
||||
modelId: "local-qwen",
|
||||
scope: "selected_tables",
|
||||
targetIds: [visitsTable.id],
|
||||
}));
|
||||
expect(await screen.findByRole("complementary", { name: "Sensitive field review" })).toBeVisible();
|
||||
});
|
||||
|
||||
test("reviews AI-sensitive-field suggestions as an editable draft and saves only changed columns", async () => {
|
||||
const user = userEvent.setup();
|
||||
const idColumn = { ...patientIdColumn, sensitive: false };
|
||||
@@ -1585,7 +1704,18 @@ test("reviews AI-sensitive-field suggestions as an editable draft and saves only
|
||||
generatedDescription: "Name of the patient",
|
||||
sensitive: false,
|
||||
};
|
||||
let columns = [idColumn, nameColumn];
|
||||
const unselectedColumn = {
|
||||
...patientIdColumn,
|
||||
id: "ffffffff-ffff-4fff-8fff-ffffffffffff",
|
||||
name: "address",
|
||||
ordinalPosition: 3,
|
||||
primaryKeyPosition: null,
|
||||
isPrimaryKey: false,
|
||||
description: "Patient address",
|
||||
generatedDescription: "Address of the patient",
|
||||
sensitive: false,
|
||||
};
|
||||
let columns = [idColumn, nameColumn, unselectedColumn];
|
||||
let suggestionBody: unknown;
|
||||
const patches: Array<{ columnId: string; body: unknown }> = [];
|
||||
server.use(
|
||||
@@ -1604,9 +1734,24 @@ test("reviews AI-sensitive-field suggestions as an editable draft and saves only
|
||||
suggestionBody = await request.json();
|
||||
return HttpResponse.json({
|
||||
suggestions: [
|
||||
{ columnId: idColumn.id, sensitive: true },
|
||||
{ columnId: nameColumn.id, sensitive: true },
|
||||
{ columnId: "ffffffff-ffff-4fff-8fff-ffffffffffff", sensitive: true },
|
||||
{
|
||||
columnId: idColumn.id,
|
||||
tableId: patientsTable.id,
|
||||
tableName: patientsTable.name,
|
||||
columnName: idColumn.name,
|
||||
version: idColumn.version,
|
||||
currentSensitive: false,
|
||||
sensitive: true,
|
||||
},
|
||||
{
|
||||
columnId: nameColumn.id,
|
||||
tableId: patientsTable.id,
|
||||
tableName: patientsTable.name,
|
||||
columnName: nameColumn.name,
|
||||
version: nameColumn.version,
|
||||
currentSensitive: false,
|
||||
sensitive: true,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
@@ -1616,8 +1761,6 @@ test("reviews AI-sensitive-field suggestions as an editable draft and saves only
|
||||
async ({ params, request }) => {
|
||||
const body = await request.json() as {
|
||||
version: number;
|
||||
description: string | null;
|
||||
generatedDescription: string | null;
|
||||
sensitive: boolean;
|
||||
};
|
||||
patches.push({ columnId: String(params.columnId), body });
|
||||
@@ -1638,31 +1781,41 @@ test("reviews AI-sensitive-field suggestions as an editable draft and saves only
|
||||
const nameSensitive = await screen.findByRole("checkbox", { name: "Sensitive data for name" });
|
||||
expect(idSensitive).not.toBeChecked();
|
||||
expect(nameSensitive).not.toBeChecked();
|
||||
expect(screen.queryByRole("button", { name: "Suggest sensitive fields" })).not.toBeInTheDocument();
|
||||
|
||||
const selectableRow = async (name: RegExp) => {
|
||||
const rows = await screen.findAllByRole("row", { name });
|
||||
return rows.find((row) => within(row).queryByRole("checkbox", { name: /toggle row selection/i }))!;
|
||||
};
|
||||
await user.click(within(await selectableRow(/Patient identifier/))
|
||||
.getByRole("checkbox", { name: /toggle row selection/i }));
|
||||
await user.click(within(await selectableRow(/Patient name/))
|
||||
.getByRole("checkbox", { name: /toggle row selection/i }));
|
||||
await user.click(screen.getByRole("button", { name: "Suggest sensitive fields" }));
|
||||
|
||||
await waitFor(() => expect(suggestionBody).toEqual({ modelId: "local-qwen" }));
|
||||
await waitFor(() => {
|
||||
expect(screen.getByRole("checkbox", { name: "Sensitive data for id" })).toBeChecked();
|
||||
expect(screen.getByRole("checkbox", { name: "Sensitive data for name" })).toBeChecked();
|
||||
});
|
||||
await waitFor(() => expect(suggestionBody).toEqual({
|
||||
modelId: "local-qwen",
|
||||
scope: "selected_columns",
|
||||
targetIds: [idColumn.id, nameColumn.id],
|
||||
}));
|
||||
const review = await screen.findByRole("complementary", { name: "Sensitive field review" });
|
||||
expect(within(review).getByRole("checkbox", { name: "Protect patients.id" })).toBeChecked();
|
||||
expect(within(review).getByRole("checkbox", { name: "Protect patients.name" })).toBeChecked();
|
||||
expect(patches).toHaveLength(0);
|
||||
|
||||
await user.click(screen.getByRole("checkbox", { name: "Sensitive data for name" }));
|
||||
expect(screen.getByRole("checkbox", { name: "Sensitive data for name" })).not.toBeChecked();
|
||||
await user.click(screen.getByRole("button", { name: "Save sensitive fields" }));
|
||||
await user.click(within(review).getByRole("checkbox", { name: "Protect patients.name" }));
|
||||
await user.click(within(review).getByRole("button", { name: "Save 1" }));
|
||||
|
||||
await waitFor(() => expect(patches).toEqual([{
|
||||
columnId: idColumn.id,
|
||||
body: {
|
||||
version: idColumn.version,
|
||||
description: idColumn.description,
|
||||
generatedDescription: idColumn.generatedDescription,
|
||||
sensitive: true,
|
||||
},
|
||||
}]));
|
||||
expect(await screen.findByText("Sensitive fields saved")).toBeVisible();
|
||||
expect(screen.getByRole("checkbox", { name: "Sensitive data for id" })).toBeChecked();
|
||||
expect(await screen.findByText("Saved 1 sensitive flag")).toBeVisible();
|
||||
await waitFor(() => expect(screen.queryByRole("complementary", { name: "Sensitive field review" })).not.toBeInTheDocument());
|
||||
await waitFor(() => expect(screen.getByRole("checkbox", { name: "Sensitive data for id" })).toBeChecked());
|
||||
expect(screen.getByRole("checkbox", { name: "Sensitive data for name" })).not.toBeChecked();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user