From a52cb32045a3060b4913ad7146a36e8af672b35c Mon Sep 17 00:00:00 2001 From: Jeshika Date: Sat, 23 May 2026 09:01:34 +0530 Subject: [PATCH 1/5] Fix latest report export button behavior on Reports page --- frontend/src/pages/Reports.tsx | 15 ++++++++ frontend/testing/unit/pages/Reports.test.tsx | 40 ++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/frontend/src/pages/Reports.tsx b/frontend/src/pages/Reports.tsx index 047fffec..308eddf7 100644 --- a/frontend/src/pages/Reports.tsx +++ b/frontend/src/pages/Reports.tsx @@ -74,6 +74,9 @@ export default function Reports() { const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const { preferred, savePreference } = usePreferredExportFormat() + const latestReadyReport = [...reports] + .filter((report) => report.status === 'ready') + .sort((a, b) => new Date(b.generated_at).getTime() - new Date(a.generated_at).getTime())[0] const fetchReports = () => { setLoading(true) @@ -118,6 +121,18 @@ export default function Reports() {
+
-
+ - {[...exportFormats].sort((a, b) => - a === preferred ? -1 : b === preferred ? 1 : 0 - ).map((format) => ( + {exportFormats.map((format) => ( diff --git a/frontend/testing/unit/pages/Reports.test.tsx b/frontend/testing/unit/pages/Reports.test.tsx index 3da4ecd5..3b3ec230 100644 --- a/frontend/testing/unit/pages/Reports.test.tsx +++ b/frontend/testing/unit/pages/Reports.test.tsx @@ -22,6 +22,12 @@ const readyReport = { generated_at: '2026-05-14T10:00:00Z', status: 'ready', findings: 7, assets: 3, pages: 12, } +const newerReadyReport = { + id: 'report-4', task_id: 'task-jkl-012', + name: 'Security Scan — docs.example.com', type: 'technical', + generated_at: '2026-05-14T11:30:00Z', status: 'ready', + findings: 2, assets: 1, pages: 4, +} const generatingReport = { id: 'report-2', task_id: 'task-def-456', name: 'Security Scan — staging.example.com', type: 'executive', @@ -168,6 +174,39 @@ describe('Reports — export buttons on a ready report', () => { }) }) +describe('Reports — header export button', () => { + beforeEach(() => { + vi.mocked(getDashboardSummary).mockResolvedValue(emptySummary) + openSpy.mockClear() + }) + + it('opens the newest ready report PDF from the header button', async () => { + const user = userEvent.setup() + vi.mocked(getReports).mockResolvedValue({ reports: [readyReport, generatingReport, newerReadyReport, failedReport] }) + + renderReports() + + await user.click(await screen.findByRole('button', { name: /download latest ready report pdf/i })) + + expect(openSpy).toHaveBeenCalledWith( + expect.stringContaining('/task/' + newerReadyReport.task_id + '/report/pdf'), '_blank') + expect(openSpy).not.toHaveBeenCalledWith(expect.stringContaining('/task/latest/report/pdf'), expect.anything()) + }) + + it('disables the header export button when there is no ready report', async () => { + const user = userEvent.setup() + vi.mocked(getReports).mockResolvedValue({ reports: [generatingReport, failedReport] }) + + renderReports() + + const button = await screen.findByRole('button', { name: /download latest ready report pdf/i }) + expect(button).toBeDisabled() + + await user.click(button) + expect(openSpy).not.toHaveBeenCalled() + }) +}) + // ── Export buttons — generating report ──────────────────────────────────────────────────────────── describe('Reports — export buttons on a generating report', () => { From 56216d691bf3eacb4d77cc78b2ad8ec93e8a0364 Mon Sep 17 00:00:00 2001 From: Jeshika Date: Sat, 23 May 2026 09:53:31 +0530 Subject: [PATCH 5/5] FIX latest report export button behavior on Reports page --- frontend/src/pages/Reports.tsx | 47 ++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/frontend/src/pages/Reports.tsx b/frontend/src/pages/Reports.tsx index 17e29dd2..7464dbde 100644 --- a/frontend/src/pages/Reports.tsx +++ b/frontend/src/pages/Reports.tsx @@ -72,6 +72,7 @@ export default function Reports() { const [selectedDateRange, setSelectedDateRange] = useState('all') const [loading, setLoading] = useState(true) const [error, setError] = useState(null) + const [preferredFormat, setPreferredFormat] = useState(null) const latestReadyReport = [...reports] .filter((report) => report.status === 'ready') .sort((a, b) => new Date(b.generated_at).getTime() - new Date(a.generated_at).getTime())[0] @@ -94,6 +95,8 @@ export default function Reports() { useEffect(() => { fetchReports() + const pref = localStorage.getItem('secuscan:preferred-export-format') + if (pref) setPreferredFormat(pref) }, []) const filteredReports = reports.filter((report) => @@ -358,23 +361,35 @@ export default function Reports() { >