fix(dashboard-tests): align remote-access mock store with FN-8491, ChatView mobile with FN-8502, and de-race planning claim tests
- remote-access-routes: FN-8491 made every project-context resolution call the
plugin-MCP binder; the mock store now satisfies the runtime-owned-store guard.
- ChatView.mobile: sendMessage gained the FN-8502 {onDelivered,onFailed} arg.
- PlanningModeModal.planning-flow: settle-then-requery before clicking Proceed
(detached-node race under CI load, same class 5a5796bca fixed for Stop/Refine)
and await the create-dispatch mock signal instead of the DOM alone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -881,7 +881,17 @@ describe("ChatView mobile behavior", () => {
|
||||
fireEvent.click(sendButton);
|
||||
|
||||
expect(sendMessage).toHaveBeenCalledTimes(1);
|
||||
expect(sendMessage).toHaveBeenCalledWith("Hello mobile", []);
|
||||
/*
|
||||
FNXC:ChatAttachments 2026-07-23-23:00:
|
||||
FN-8502 made ChatView pass attachment delivery callbacks as a third
|
||||
sendMessage argument ({ onDelivered, onFailed }); assert them
|
||||
structurally so the iOS first-tap send contract (text + empty
|
||||
attachments) stays the protected invariant.
|
||||
*/
|
||||
expect(sendMessage).toHaveBeenCalledWith("Hello mobile", [], expect.objectContaining({
|
||||
onDelivered: expect.any(Function),
|
||||
onFailed: expect.any(Function),
|
||||
}));
|
||||
expect(document.activeElement).toBe(input);
|
||||
} finally {
|
||||
isIOSSpy.mockRestore();
|
||||
@@ -911,7 +921,11 @@ describe("ChatView mobile behavior", () => {
|
||||
fireEvent.click(sendButton);
|
||||
|
||||
expect(sendMessage).toHaveBeenCalledTimes(1);
|
||||
expect(sendMessage).toHaveBeenCalledWith("Hello mobile", []);
|
||||
// FNXC:ChatAttachments 2026-07-23-23:00: FN-8502 delivery-callback third arg (see above).
|
||||
expect(sendMessage).toHaveBeenCalledWith("Hello mobile", [], expect.objectContaining({
|
||||
onDelivered: expect.any(Function),
|
||||
onFailed: expect.any(Function),
|
||||
}));
|
||||
expect(document.activeElement).toBe(input);
|
||||
} finally {
|
||||
restoreMatchMedia.mockRestore();
|
||||
|
||||
@@ -589,10 +589,19 @@ describe("PlanningModeModal sequential flow", () => {
|
||||
.mockResolvedValueOnce({ id: "FN-8442" });
|
||||
|
||||
renderSession();
|
||||
fireEvent.click(await screen.findByRole("button", { name: "Proceed with plan" }));
|
||||
/*
|
||||
FNXC:PlanningMode 2026-07-23-23:30:
|
||||
Settle pending hydration commits and click a freshly-queried node: clicking the button
|
||||
reference returned by findByRole raced late hydration re-renders on loaded CI shards
|
||||
(full-suite run 30069944059), dispatching on a detached node so the create never fired and
|
||||
the view stayed on plan review. Same detached-node class as the Stop/Refine race (5a5796bca).
|
||||
*/
|
||||
await screen.findByRole("button", { name: "Proceed with plan" });
|
||||
await act(async () => {});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Proceed with plan" }));
|
||||
|
||||
await waitFor(() => expect(mockCreateTaskFromPlanning).toHaveBeenCalledTimes(2));
|
||||
expect(await screen.findByTestId("planning-task-created")).toHaveTextContent("FN-8442");
|
||||
expect(mockCreateTaskFromPlanning).toHaveBeenCalledTimes(2);
|
||||
expect(screen.queryByTestId("planning-create-retry")).toBeNull();
|
||||
});
|
||||
|
||||
@@ -610,7 +619,10 @@ describe("PlanningModeModal sequential flow", () => {
|
||||
.mockResolvedValueOnce({ id: "FN-8442" });
|
||||
|
||||
const { rerender } = renderSession();
|
||||
fireEvent.click(await screen.findByRole("button", { name: "Proceed with plan" }));
|
||||
// FNXC:PlanningMode 2026-07-23-23:30: settle hydration then click a fresh node (see detached-node note above).
|
||||
await screen.findByRole("button", { name: "Proceed with plan" });
|
||||
await act(async () => {});
|
||||
fireEvent.click(screen.getByRole("button", { name: "Proceed with plan" }));
|
||||
vi.useFakeTimers();
|
||||
|
||||
await act(async () => {
|
||||
|
||||
@@ -87,6 +87,15 @@ function createMockStore(overrides: Partial<TaskStore> = {}): TaskStore {
|
||||
moveTask: vi.fn(),
|
||||
logEntry: vi.fn(),
|
||||
getAgentLogs: vi.fn().mockResolvedValue([]),
|
||||
/*
|
||||
FNXC:PluginMcpServers 2026-07-23-00:00:
|
||||
FN-8491 (3cd023fa4) made resolveProjectContext bind a project-scoped plugin
|
||||
MCP provider on every getProjectContext call. A store that already exposes
|
||||
getProjectScopedPluginMcpServers is treated as runtime-owned and skips the
|
||||
binder (which would otherwise call getPluginStore()); declare it here so the
|
||||
remote-access route contracts stay isolated from plugin-loader bootstrapping.
|
||||
*/
|
||||
getProjectScopedPluginMcpServers: vi.fn().mockResolvedValue([]),
|
||||
on: vi.fn(),
|
||||
off: vi.fn(),
|
||||
...overrides,
|
||||
|
||||
Reference in New Issue
Block a user