diff --git a/frontend/src/v2/__tests__/V2DevicesPanel.test.tsx b/frontend/src/v2/__tests__/V2DevicesPanel.test.tsx index 24cafe5936..ecdb4b7a48 100644 --- a/frontend/src/v2/__tests__/V2DevicesPanel.test.tsx +++ b/frontend/src/v2/__tests__/V2DevicesPanel.test.tsx @@ -25,5 +25,14 @@ test('lists a device without exposing its bearer and revokes it in place', async expect(screen.queryByText(/cm_[a-f0-9]/)).not.toBeInTheDocument(); fireEvent.click(screen.getByRole('button', { name: 'Revoke' })); await waitFor(() => expect(axios.delete).toHaveBeenCalledWith('/api/auth/devices/d1')); - expect(await screen.findByText('Revoked')).toBeInTheDocument(); + expect(await screen.findByText(/^Revoked/)).toBeInTheDocument(); +}); + +test('a revoked device shows its revoked date and no Revoke button', async () => { + axios.get.mockResolvedValue({ data: { devices: [{ id: 'd2', label: 'old-laptop · commonly-cli', createdAt: '2026-08-31T00:00:00.000Z', lastUsedAt: null, revokedAt: '2026-10-20T09:30:00.000Z' }] } }); + render(); + + expect(await screen.findByText('old-laptop · commonly-cli')).toBeInTheDocument(); + expect(screen.queryByRole('button', { name: 'Revoke' })).not.toBeInTheDocument(); + expect(screen.getByText(/^Revoked/)).toHaveTextContent(new Date('2026-10-20T09:30:00.000Z').toLocaleString()); }); diff --git a/frontend/src/v2/components/V2DevicesPanel.tsx b/frontend/src/v2/components/V2DevicesPanel.tsx index a2338df3ae..4938860219 100644 --- a/frontend/src/v2/components/V2DevicesPanel.tsx +++ b/frontend/src/v2/components/V2DevicesPanel.tsx @@ -55,7 +55,7 @@ const V2DevicesPanel: React.FC = ({ showHeading = true }) = {!loading && devices.length > 0 &&
{devices.map((device) =>
{device.label}Created {dateLabel(device.createdAt)} · Last used {dateLabel(device.lastUsedAt)}
- {device.revokedAt ? Revoked : } + {device.revokedAt ? Revoked {dateLabel(device.revokedAt)} : }
)}
}