diff --git a/apps/web/src/hooks/useThreadActions.permissions.test.ts b/apps/web/src/hooks/useThreadActions.permissions.test.ts index a1b39cdf47bd8..2fb45bf4045d3 100644 --- a/apps/web/src/hooks/useThreadActions.permissions.test.ts +++ b/apps/web/src/hooks/useThreadActions.permissions.test.ts @@ -43,7 +43,7 @@ vi.mock("react", () => ({ useRef: (current: unknown) => ({ current }), })); vi.mock("@tanstack/react-router", () => ({ - useRouter: () => ({ state: { matches: [] }, navigate: async () => {} }), + useRouter: () => ({ state: { location: { href: "/" }, matches: [] }, navigate: async () => {} }), })); vi.mock("../state/session", () => ({ environmentSession: { sessionStateAtom: "session" }, diff --git a/apps/web/src/hooks/useThreadActions.ts b/apps/web/src/hooks/useThreadActions.ts index 26adcfcd612fe..59a3d1e5beacf 100644 --- a/apps/web/src/hooks/useThreadActions.ts +++ b/apps/web/src/hooks/useThreadActions.ts @@ -356,6 +356,7 @@ export function useThreadActions() { ); } + const requestingRouteHref = router.state.location.href; const currentRouteThreadRef = getCurrentRouteThreadRef(); const shouldNavigateToDraft = currentRouteThreadRef?.threadId === threadRef.threadId && @@ -382,7 +383,7 @@ export function useThreadActions() { failureTitle: "Failed to undo archive", }); - if (shouldNavigateToDraft) { + if (shouldNavigateToDraft && router.state.location.href === requestingRouteHref) { const navigationResult = await settlePromise(() => handleNewThread(scopeProjectRef(thread.environmentId, thread.projectId)), ); diff --git a/apps/web/src/hooks/useThreadActions.undo.test.ts b/apps/web/src/hooks/useThreadActions.undo.test.ts index b31f657458e38..adf7e09b7e6f9 100644 --- a/apps/web/src/hooks/useThreadActions.undo.test.ts +++ b/apps/web/src/hooks/useThreadActions.undo.test.ts @@ -19,7 +19,7 @@ const commands = vi.hoisted(() => ({ })); const router = vi.hoisted(() => ({ navigate: vi.fn(async () => {}), - state: { matches: [{ params: {} as Record }] }, + state: { location: { href: "/" }, matches: [{ params: {} as Record }] }, })); vi.mock("../state/use-atom-query-runner", () => ({ useAtomQueryRunner: () => vi.fn() })); vi.mock("../state/session", async (original) => ({ @@ -34,7 +34,11 @@ vi.mock("react", async (original) => ({ })); vi.mock("@tanstack/react-router", () => ({ useRouter: () => router })); vi.mock("./useSettings", () => ({ useClientSettings: () => false })); -vi.mock("./useHandleNewThread", () => ({ useNewThreadHandler: () => vi.fn() })); +vi.mock("./useHandleNewThread", () => ({ + useNewThreadHandler: () => async () => { + router.state.location.href = "/draft/project"; + }, +})); vi.mock("../composerDraftStore", () => ({ useComposerDraftStore: () => vi.fn() })); vi.mock("../terminalUiStateStore", () => ({ useTerminalUiStateStore: () => vi.fn() })); vi.mock("../uiStateStore", () => ({ useUiStateStore: () => vi.fn() })); @@ -97,6 +101,7 @@ beforeEach(() => { command.mockReset().mockResolvedValue({ _tag: "Success", value: undefined }); } router.navigate.mockClear(); + router.state.location.href = "/"; router.state.matches[0]!.params = {}; threadShell.pinnedAt = null; threadShell.snoozedUntil = null; @@ -204,6 +209,32 @@ describe("archive Undo", () => { }); }); +describe("archive navigation", () => { + it.each([ + { destination: "/undo-env/thread", expected: "/draft/project" }, + { destination: "/undo-env/other-thread", expected: "/undo-env/other-thread" }, + { destination: "/settings", expected: "/settings" }, + ])("ends at $expected after opening $destination while archiving", async (route) => { + router.state.location.href = "/undo-env/thread"; + router.state.matches[0]!.params = { + environmentId: target.environmentId, + threadId: target.threadId, + }; + let finishArchive!: () => void; + commands.archive.mockReturnValue( + new Promise((resolve) => { + finishArchive = () => resolve({ _tag: "Success", value: undefined }); + }), + ); + const archived = useThreadActions().archiveThread(target); + router.state.location.href = route.destination; + finishArchive(); + expect((await archived)._tag).toBe("Success"); + expect(useThreadUndoNotice.getState().notice).toMatchObject({ action: "Archived" }); + expect(router.state.location.href).toBe(route.expected); + }); +}); + describe("settle and snooze Undo", () => { it("un-settles from the notice and expires the Undo after a manual un-settle", async () => { const add = vi.spyOn(toastManager, "add").mockReturnValue("toast");