fix(dashboard): index the FN-8348 Report row in settings search; re-green backfill test lane
Product fixes surfaced by the drift guards: - GeneralSection.search.ts: FN-8348 added the Report row (bug/feedback/idea/help) without a search-index entry, so settings search could not find it. - WorkflowNodeEditor.css: FN-8526 introduced the undefined deprecated alias --text-secondary; substitute the FN-8043 migration token --text-muted. Stale-test alignment (no assertions weakened): - settings-sections: builtin:coding-ideas is no longer deprecated post-#2378. - TaskDetailModal workflow/oversight suites: mocked workflows gain the columns array FN-8476 metadata resolution requires; rerender-refetch tests use persistent mocks since the board-workflows effect now keys on task identity. - ChatView.chat-commands: sendMessage gained the FN-8502 delivery-callback arg. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -143,7 +143,13 @@ describe("GeneralSection", () => {
|
||||
|
||||
await waitFor(() => expect(screen.getByLabelText("Coding")).toBeInTheDocument());
|
||||
expect(screen.queryByLabelText("Brainstorming")).not.toBeInTheDocument();
|
||||
expect(screen.queryByLabelText("Coding (Ideas)")).not.toBeInTheDocument();
|
||||
/*
|
||||
FNXC:SettingsWorkflowToggles 2026-07-23-22:05:
|
||||
PR #2378 restored builtin:coding-ideas (removed from DEPRECATED_BUILTIN_WORKFLOW_IDS),
|
||||
so Coding (Ideas) is a live selectable built-in again and must render a toggle.
|
||||
Brainstorming remains the deprecated built-in that must stay hidden.
|
||||
*/
|
||||
expect(screen.getByLabelText("Coding (Ideas)")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("emits the absolute file-browser path toggle via setForm", () => {
|
||||
|
||||
@@ -2072,10 +2072,18 @@ Fusion tokens so light/dark themes never show browser-default white controls.
|
||||
}
|
||||
|
||||
.wf-column-description-field {
|
||||
/*
|
||||
FNXC:DashboardTextTokens 2026-07-23-22:30:
|
||||
FN-8526 shipped this label with the undefined deprecated --text-secondary alias; per the FN-8043
|
||||
migration guarded by deprecated-text-secondary-token-migration.test.ts, secondary text uses the
|
||||
canonical --text-muted token, which resolves in both base and light themes.
|
||||
(Comment lives inside the block so WorkflowColumnPanel.test.tsx's brace-scanning selector parser
|
||||
still sees the bare selector.)
|
||||
*/
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-xs);
|
||||
color: var(--text-secondary);
|
||||
color: var(--text-muted);
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
|
||||
@@ -164,7 +164,17 @@ describe("ChatView slash-command dispatch (/steer)", () => {
|
||||
fireEvent.change(textarea, { target: { value: "hello there" } });
|
||||
fireEvent.keyDown(textarea, { key: "Enter" });
|
||||
|
||||
await waitFor(() => expect(sendMessage).toHaveBeenCalledWith("hello there", []));
|
||||
/*
|
||||
FNXC:ChatAttachments 2026-07-23-22:35:
|
||||
FN-8502 made ChatView pass attachment delivery callbacks as a third
|
||||
sendMessage argument ({ onDelivered, onFailed }); assert them structurally
|
||||
so the /steer dispatch contract (text + empty attachments, no steering
|
||||
comment) stays the protected invariant.
|
||||
*/
|
||||
await waitFor(() => expect(sendMessage).toHaveBeenCalledWith("hello there", [], expect.objectContaining({
|
||||
onDelivered: expect.any(Function),
|
||||
onFailed: expect.any(Function),
|
||||
})));
|
||||
expect(mockAddSteeringComment).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -181,7 +191,11 @@ describe("ChatView slash-command dispatch (/steer)", () => {
|
||||
fireEvent.change(textarea, { target: { value: "please /steer this" } });
|
||||
fireEvent.keyDown(textarea, { key: "Enter" });
|
||||
|
||||
await waitFor(() => expect(sendMessage).toHaveBeenCalledWith("please /steer this", []));
|
||||
// FNXC:ChatAttachments 2026-07-23-22:35: FN-8502 delivery-callback third arg (see above).
|
||||
await waitFor(() => expect(sendMessage).toHaveBeenCalledWith("please /steer this", [], expect.objectContaining({
|
||||
onDelivered: expect.any(Function),
|
||||
onFailed: expect.any(Function),
|
||||
})));
|
||||
expect(mockAddSteeringComment).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
@@ -1065,7 +1065,8 @@ describe("TaskDetailModal", () => {
|
||||
vi.mocked(fetchBoardWorkflows).mockResolvedValueOnce({
|
||||
flagEnabled: true,
|
||||
defaultWorkflowId: "wf-edit",
|
||||
workflows: [{ id: "wf-edit", name: "Edit Workflow" }],
|
||||
// FNXC:TaskDetailWorkflow 2026-07-23-22:10: FN-8476 (restore Ideas detail move action) made resolveTaskWorkflowMetadata derive move targets from workflow.columns, so mocked workflows must carry a columns array or metadata resolution throws and the edit-mode optional-steps picker never mounts.
|
||||
workflows: [{ id: "wf-edit", name: "Edit Workflow", columns: [] }],
|
||||
taskWorkflowIds: { "FN-099": "wf-edit" },
|
||||
} as any);
|
||||
vi.mocked(fetchWorkflowOptionalSteps).mockResolvedValueOnce([
|
||||
@@ -1108,7 +1109,8 @@ describe("TaskDetailModal", () => {
|
||||
vi.mocked(fetchBoardWorkflows).mockResolvedValueOnce({
|
||||
flagEnabled: true,
|
||||
defaultWorkflowId: "wf-edit",
|
||||
workflows: [{ id: "wf-edit", name: "Edit Workflow" }],
|
||||
// FNXC:TaskDetailWorkflow 2026-07-23-22:10: FN-8476 (restore Ideas detail move action) made resolveTaskWorkflowMetadata derive move targets from workflow.columns, so mocked workflows must carry a columns array or metadata resolution throws and the edit-mode optional-steps picker never mounts.
|
||||
workflows: [{ id: "wf-edit", name: "Edit Workflow", columns: [] }],
|
||||
taskWorkflowIds: { "FN-099": "wf-edit" },
|
||||
} as any);
|
||||
vi.mocked(fetchWorkflowOptionalSteps).mockResolvedValueOnce([
|
||||
|
||||
@@ -92,7 +92,7 @@ describe("TaskDetailModal oversight controls", () => {
|
||||
vi.mocked(api.fetchBoardWorkflows).mockResolvedValueOnce({
|
||||
flagEnabled: true,
|
||||
defaultWorkflowId: "WF-advisor",
|
||||
workflows: [{ id: "WF-advisor", name: "Advisor workflow" } as any],
|
||||
workflows: [{ id: "WF-advisor", name: "Advisor workflow", columns: [] } as any],
|
||||
taskWorkflowIds: { "FN-8247-workflow": "WF-advisor" },
|
||||
});
|
||||
vi.mocked(api.fetchWorkflowSettingValues).mockResolvedValueOnce({
|
||||
@@ -134,7 +134,7 @@ describe("TaskDetailModal oversight controls", () => {
|
||||
vi.mocked(api.fetchBoardWorkflows).mockResolvedValueOnce({
|
||||
flagEnabled: true,
|
||||
defaultWorkflowId: "WF-8263-project-default",
|
||||
workflows: [{ id: "WF-8263-project-default", name: "Project default workflow" } as any],
|
||||
workflows: [{ id: "WF-8263-project-default", name: "Project default workflow", columns: [] } as any],
|
||||
taskWorkflowIds: { "FN-8263-project-default": "WF-8263-project-default" },
|
||||
});
|
||||
vi.mocked(api.fetchWorkflowSettingValues).mockResolvedValueOnce({
|
||||
@@ -177,10 +177,18 @@ describe("TaskDetailModal oversight controls", () => {
|
||||
defaultPresetBySize: {},
|
||||
sessionAdvisorEnabledByDefault: true,
|
||||
} as any);
|
||||
vi.mocked(api.fetchBoardWorkflows).mockResolvedValueOnce({
|
||||
/*
|
||||
FNXC:PlannerOversight 2026-07-23-22:20:
|
||||
FN-8476 made the board-workflows lookup re-run whenever the task prop identity
|
||||
changes (it derives move metadata from the payload), so the onTaskUpdated
|
||||
rerender below refetches. A once-mock would leave the refetch on the
|
||||
flagEnabled:false default and silently drop the workflow tier mid-test —
|
||||
keep the payload persistent for every call in this test.
|
||||
*/
|
||||
vi.mocked(api.fetchBoardWorkflows).mockResolvedValue({
|
||||
flagEnabled: true,
|
||||
defaultWorkflowId: "WF-8263-pending-advisor",
|
||||
workflows: [{ id: "WF-8263-pending-advisor", name: "Pending advisor workflow" } as any],
|
||||
workflows: [{ id: "WF-8263-pending-advisor", name: "Pending advisor workflow", columns: [] } as any],
|
||||
taskWorkflowIds: { [currentTask.id]: "WF-8263-pending-advisor" },
|
||||
});
|
||||
vi.mocked(api.fetchWorkflowSettingValues).mockImplementationOnce(() => new Promise(() => {}));
|
||||
@@ -238,10 +246,12 @@ describe("TaskDetailModal oversight controls", () => {
|
||||
defaultPresetBySize: {},
|
||||
sessionAdvisorEnabledByDefault: false,
|
||||
} as any);
|
||||
vi.mocked(api.fetchBoardWorkflows).mockResolvedValueOnce({
|
||||
// FNXC:PlannerOversight 2026-07-23-22:20: persistent mock — FN-8476 refetches
|
||||
// board workflows on each task-prop identity change (see pending-advisor test).
|
||||
vi.mocked(api.fetchBoardWorkflows).mockResolvedValue({
|
||||
flagEnabled: true,
|
||||
defaultWorkflowId: "WF-advisor-explicit-off",
|
||||
workflows: [{ id: "WF-advisor-explicit-off", name: "Advisor workflow" } as any],
|
||||
workflows: [{ id: "WF-advisor-explicit-off", name: "Advisor workflow", columns: [] } as any],
|
||||
taskWorkflowIds: { [currentTask.id]: "WF-advisor-explicit-off" },
|
||||
});
|
||||
vi.mocked(api.fetchWorkflowSettingValues).mockResolvedValueOnce({
|
||||
|
||||
@@ -83,7 +83,7 @@ describe("TaskDetailModal oversight controls — mobile overflow menu", () => {
|
||||
vi.mocked(api.fetchBoardWorkflows).mockResolvedValueOnce({
|
||||
flagEnabled: true,
|
||||
defaultWorkflowId: "WF-8263-mobile-project-default",
|
||||
workflows: [{ id: "WF-8263-mobile-project-default", name: "Mobile project default workflow" } as any],
|
||||
workflows: [{ id: "WF-8263-mobile-project-default", name: "Mobile project default workflow", columns: [] } as any],
|
||||
taskWorkflowIds: { "FN-8263-mobile-project-default": "WF-8263-mobile-project-default" },
|
||||
});
|
||||
vi.mocked(api.fetchWorkflowSettingValues).mockResolvedValueOnce({
|
||||
@@ -129,7 +129,7 @@ describe("TaskDetailModal oversight controls — mobile overflow menu", () => {
|
||||
vi.mocked(api.fetchBoardWorkflows).mockResolvedValueOnce({
|
||||
flagEnabled: true,
|
||||
defaultWorkflowId: "WF-advisor-mobile",
|
||||
workflows: [{ id: "WF-advisor-mobile", name: "Advisor workflow" } as any],
|
||||
workflows: [{ id: "WF-advisor-mobile", name: "Advisor workflow", columns: [] } as any],
|
||||
taskWorkflowIds: { [currentTask.id]: "WF-advisor-mobile" },
|
||||
});
|
||||
vi.mocked(api.fetchWorkflowSettingValues).mockResolvedValueOnce({
|
||||
@@ -235,7 +235,7 @@ describe("TaskDetailModal oversight controls — mobile overflow menu", () => {
|
||||
vi.mocked(api.fetchBoardWorkflows).mockResolvedValue({
|
||||
flagEnabled: true,
|
||||
defaultWorkflowId: "WF-mobile-test",
|
||||
workflows: [{ id: "WF-mobile-test", name: "Mobile Test Workflow" } as any],
|
||||
workflows: [{ id: "WF-mobile-test", name: "Mobile Test Workflow", columns: [] } as any],
|
||||
taskWorkflowIds: { "FN-212": "WF-mobile-test" },
|
||||
});
|
||||
vi.mocked(api.fetchWorkflowSettingValues).mockImplementation(() => new Promise(() => {}));
|
||||
|
||||
@@ -8,6 +8,21 @@
|
||||
import type { SettingsSearchEntry } from "../search/types";
|
||||
|
||||
export const generalSearchEntries: SettingsSearchEntry[] = [
|
||||
{
|
||||
/*
|
||||
FNXC:SettingsSearch 2026-07-23-22:20:
|
||||
FN-8348 added the Report row (bug/feedback/idea/help entry point) to General
|
||||
without indexing it, so settings search could not find it; the search-index
|
||||
drift guard caught the gap. Labels/help mirror the section's t() copy verbatim.
|
||||
*/
|
||||
sectionId: "general",
|
||||
key: "report-action-menu",
|
||||
labelKey: "settings.general.report",
|
||||
labelFallback: "Report",
|
||||
helpKey: "settings.general.reportHelp",
|
||||
helpFallback: "Report a bug, send feedback, share an idea, or get help from Fusion.",
|
||||
keywords: ["bug", "feedback", "idea", "help", "support"],
|
||||
},
|
||||
{
|
||||
sectionId: "general",
|
||||
key: "taskPrefix",
|
||||
|
||||
Reference in New Issue
Block a user