| @@ -2818,6 +2818,55 @@ describe("ChatView timeline estimator parity (full app)", () => { · 2817 unmodified lines |
| 2818 | 2818 | } |
| 2819 | 2819 | }); |
| 2820 | 2820 | |
| 2821 | + it("uses the active worktree path when saving a proposed plan to the workspace", async () => { |
| 2822 | + const snapshot = createSnapshotWithLongProposedPlan(); |
| 2823 | + const threads = snapshot.threads.slice(); |
| 2824 | + const targetThreadIndex = threads.findIndex((thread) => thread.id === THREAD_ID); |
| 2825 | + const targetThread = targetThreadIndex >= 0 ? threads[targetThreadIndex] : undefined; |
| 2826 | + if (targetThread) { |
| 2827 | + threads[targetThreadIndex] = { |
| 2828 | + ...targetThread, |
| 2829 | + worktreePath: "/repo/worktrees/plan-thread", |
| 2830 | + }; |
| 2831 | + } |
| 2832 | + |
| 2833 | + const mounted = await mountChatView({ |
| 2834 | + viewport: DEFAULT_VIEWPORT, |
| 2835 | + snapshot: { |
| 2836 | + ...snapshot, |
| 2837 | + threads, |
| 2838 | + }, |
| 2839 | + }); |
| 2840 | + |
| 2841 | + try { |
| 2842 | + const planActionsButton = await waitForElement( |
| 2843 | + () => document.querySelector<HTMLButtonElement>('button[aria-label="Plan actions"]'), |
| 2844 | + "Unable to find proposed plan actions button.", |
| 2845 | + ); |
| 2846 | + planActionsButton.click(); |
| 2847 | + |
| 2848 | + const saveToWorkspaceItem = await waitForElement( |
| 2849 | + () => |
| 2850 | + (Array.from(document.querySelectorAll('[data-slot="menu-item"]')).find( |
| 2851 | + (item) => item.textContent?.trim() === "Save to workspace", |
| 2852 | + ) ?? null) as HTMLElement | null, |
| 2853 | + 'Unable to find "Save to workspace" menu item.', |
| 2854 | + ); |
| 2855 | + saveToWorkspaceItem.click(); |
| 2856 | + |
| 2857 | + await vi.waitFor( |
| 2858 | + () => { |
| 2859 | + expect(document.body.textContent).toContain( |
| 2860 | + "Enter a path relative to /repo/worktrees/plan-thread.", |
| 2861 | + ); |
| 2862 | + }, |
| 2863 | + { timeout: 8_000, interval: 16 }, |
| 2864 | + ); |
| 2865 | + } finally { |
| 2866 | + await mounted.cleanup(); |
| 2867 | + } |
| 2868 | + }); |
| 2869 | + |
| 2821 | 2870 | it("keeps pending-question footer actions inside the composer after a real resize", async () => { |
| 2822 | 2871 | const mounted = await mountChatView({ |
| 2823 | 2872 | viewport: WIDE_FOOTER_VIEWPORT, |