diff --git a/ui/src/components/IssueProperties.test.tsx b/ui/src/components/IssueProperties.test.tsx index 81da9782871..d3a582327da 100644 --- a/ui/src/components/IssueProperties.test.tsx +++ b/ui/src/components/IssueProperties.test.tsx @@ -766,6 +766,7 @@ describe("IssueProperties", () => { expect(container.textContent).toContain("BLOCK-6"); expect(container.textContent).toContain("BLOCK-7"); expect(container.textContent).not.toContain("SUB-6"); + expect(container.textContent).toContain("show less"); const expandSubTasks = Array.from(container.querySelectorAll("button")).find((button) => button.textContent?.trim() === "and 2 more...", @@ -782,6 +783,84 @@ describe("IssueProperties", () => { button.textContent?.trim() === "and 2 more...", ), ).toHaveLength(0); + expect( + Array.from(container.querySelectorAll("button")).filter((button) => + button.textContent?.trim() === "show less", + ), + ).toHaveLength(2); + + const collapseBlockedBy = Array.from(container.querySelectorAll("button")).find((button) => + button.textContent?.trim() === "show less", + ); + expect(collapseBlockedBy).not.toBeUndefined(); + await act(async () => { + collapseBlockedBy!.dispatchEvent(new MouseEvent("click", { bubbles: true })); + }); + + expect(container.textContent).not.toContain("BLOCK-6"); + expect(container.textContent).toContain("SUB-6"); + expect(container.textContent).toContain("and 2 more..."); + + act(() => root.unmount()); + }); + + it("resets expanded relation previews when the issue changes", async () => { + const blockedBy = Array.from({ length: 7 }, (_, index) => ({ + id: `blocker-${index + 1}`, + identifier: `BLOCK-${index + 1}`, + title: `Blocker ${index + 1}`, + status: "todo", + priority: "medium", + assigneeAgentId: null, + assigneeUserId: null, + })) as NonNullable; + const queryClient = new QueryClient({ + defaultOptions: { + queries: { retry: false }, + }, + }); + const root = createRoot(container); + + act(() => { + root.render( + + + , + ); + }); + await flush(); + + const expandBlockedBy = Array.from(container.querySelectorAll("button")).find((button) => + button.textContent?.trim() === "and 2 more...", + ); + expect(expandBlockedBy).not.toBeUndefined(); + await act(async () => { + expandBlockedBy!.dispatchEvent(new MouseEvent("click", { bubbles: true })); + }); + + expect(container.textContent).toContain("BLOCK-6"); + + act(() => { + root.render( + + + , + ); + }); + await flush(); + + expect(container.textContent).not.toContain("BLOCK-6"); + expect(container.textContent).toContain("and 2 more..."); act(() => root.unmount()); }); diff --git a/ui/src/components/IssueProperties.tsx b/ui/src/components/IssueProperties.tsx index b610c5289f0..83412e8c1ed 100644 --- a/ui/src/components/IssueProperties.tsx +++ b/ui/src/components/IssueProperties.tsx @@ -324,19 +324,21 @@ function RemovableIssueReferencePill({ function ExpandRelationListButton({ hiddenCount, + expanded, onClick, }: { hiddenCount: number; + expanded: boolean; onClick: () => void; }) { - if (hiddenCount <= 0) return null; + if (!expanded && hiddenCount <= 0) return null; return ( ); } @@ -448,6 +450,11 @@ export function IssueProperties({ const [monitorServiceInput, setMonitorServiceInput] = useState(issue.executionPolicy?.monitor?.serviceName ?? ""); const normalizedBlockedBySearch = blockedBySearch.trim(); + useEffect(() => { + setBlockedByExpanded(false); + setSubTasksExpanded(false); + }, [issue.id]); + const { data: session } = useQuery({ queryKey: queryKeys.auth.session, queryFn: () => authApi.getSession(), @@ -2021,7 +2028,8 @@ export function IssueProperties({ ))} setBlockedByExpanded(true)} + expanded={blockedByExpanded} + onClick={() => setBlockedByExpanded((expanded) => !expanded)} /> {renderAddBlockedByButton(() => setBlockedByOpen((open) => !open))} @@ -2038,7 +2046,8 @@ export function IssueProperties({ ))} setBlockedByExpanded(true)} + expanded={blockedByExpanded} + onClick={() => setBlockedByExpanded((expanded) => !expanded)} /> setSubTasksExpanded(true)} + expanded={subTasksExpanded} + onClick={() => setSubTasksExpanded((expanded) => !expanded)} /> {onAddSubIssue ? (