fix(completion-docs): hide the empty-search row when templates fail to load

This commit is contained in:
Alexandre Brandizzi 2026-09-25 17:00:23 -03:00
parent d281cbd663
commit d866cf1b87
3 changed files with 22 additions and 3 deletions

View file

@ -23,6 +23,8 @@ const BODY_CELL_SX = { fontSize: 13, padding: "8px 12px" } as const;
type CompletionTemplatesTableProps = { type CompletionTemplatesTableProps = {
templates: CompletionTemplate[]; templates: CompletionTemplate[];
isLoading: boolean; isLoading: boolean;
/** The load failed: the page shows the error, so there is no search result to explain. */
hasError: boolean;
canEdit: boolean; canEdit: boolean;
onView: (template: CompletionTemplate) => void; onView: (template: CompletionTemplate) => void;
onEdit: (template: CompletionTemplate) => void; onEdit: (template: CompletionTemplate) => void;
@ -79,7 +81,7 @@ function TemplateRow({
canEdit, canEdit,
onView, onView,
onEdit, onEdit,
}: Omit<CompletionTemplatesTableProps, "templates" | "isLoading"> & { }: Omit<CompletionTemplatesTableProps, "templates" | "isLoading" | "hasError"> & {
template: CompletionTemplate; template: CompletionTemplate;
}) { }) {
return ( return (
@ -120,6 +122,7 @@ function TemplateRow({
export function CompletionTemplatesTable({ export function CompletionTemplatesTable({
templates, templates,
isLoading, isLoading,
hasError,
canEdit, canEdit,
onView, onView,
onEdit, onEdit,
@ -143,7 +146,7 @@ export function CompletionTemplatesTable({
</TableHead> </TableHead>
<TableBody> <TableBody>
{isLoading && <TableLoadingRow colSpan={4} />} {isLoading && <TableLoadingRow colSpan={4} />}
{!isLoading && templates.length === 0 && <EmptyRow />} {!isLoading && !hasError && templates.length === 0 && <EmptyRow />}
{templates.map((template) => ( {templates.map((template) => (
<TemplateRow <TemplateRow
key={template.id} key={template.id}

View file

@ -72,6 +72,7 @@ export default function CompletionDocsPage() {
<CompletionTemplatesTable <CompletionTemplatesTable
templates={templates} templates={templates}
isLoading={filtered.isPending} isLoading={filtered.isPending}
hasError={filtered.error !== null}
canEdit={permissions.canEdit} canEdit={permissions.canEdit}
onView={(template) => setDialog({ template, mode: "view" })} onView={(template) => setDialog({ template, mode: "view" })}
onEdit={(template) => setDialog({ template, mode: "edit" })} onEdit={(template) => setDialog({ template, mode: "edit" })}

View file

@ -1,4 +1,4 @@
import { screen, within } from "@testing-library/react"; import { screen, waitFor, within } from "@testing-library/react";
import userEvent from "@testing-library/user-event"; import userEvent from "@testing-library/user-event";
import { beforeEach, describe, expect, it, vi } from "vitest"; import { beforeEach, describe, expect, it, vi } from "vitest";
import CompletionDocsPage from "@/app/(protected)/completion-docs/index"; import CompletionDocsPage from "@/app/(protected)/completion-docs/index";
@ -88,6 +88,21 @@ describe("Completion Docs page", { timeout: 15_000 }, () => {
expect(screen.queryByRole("row", { name: /Backflow Test Report/ })).not.toBeInTheDocument(); expect(screen.queryByRole("row", { name: /Backflow Test Report/ })).not.toBeInTheDocument();
}); });
it("reports a failed load without the empty-search message, including after a failed Retry", async () => {
api.apiGet.mockRejectedValue(new Error("Templates are unavailable"));
renderPage();
const retry = await screen.findByRole("button", { name: "Retry" });
expect(screen.getByText("Templates are unavailable")).toBeInTheDocument();
expect(screen.queryByText("No templates found")).not.toBeInTheDocument();
const callsBeforeRetry = api.apiGet.mock.calls.length;
await user.click(retry);
await waitFor(() => expect(api.apiGet.mock.calls.length).toBeGreaterThan(callsBeforeRetry));
expect(await screen.findByText("Templates are unavailable")).toBeInTheDocument();
expect(screen.queryByText("No templates found")).not.toBeInTheDocument();
});
it("opens a read-only detail panel from a row with every part of the template", async () => { it("opens a read-only detail panel from a row with every part of the template", async () => {
renderPage(); renderPage();
const dialog = await openTemplate("Backflow Test Report"); const dialog = await openTemplate("Backflow Test Report");