Implement Garmin settings page with token management UI (P2.10)

- Add full Garmin connection management page at /settings/garmin
- Display connection status with colored indicators (green/red/gray)
- Show token expiry warnings (yellow 14 days, red 7 days)
- Token input form with JSON validation for bootstrap script output
- Disconnect functionality with confirmation
- Loading and error states throughout
- Add link from Settings page to Garmin settings
- 27 tests for Garmin settings page
- 3 additional tests for Settings page Garmin link

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-10 21:28:06 +00:00
parent be80c60253
commit 742f220be5
5 changed files with 1096 additions and 12 deletions

View File

@@ -100,6 +100,39 @@ describe("SettingsPage", () => {
expect(screen.getByText("test@example.com")).toBeInTheDocument();
});
});
it("renders Garmin connection section with manage link", async () => {
render(<SettingsPage />);
await waitFor(() => {
expect(screen.getByText(/garmin connection/i)).toBeInTheDocument();
expect(screen.getByRole("link", { name: /manage/i })).toHaveAttribute(
"href",
"/settings/garmin",
);
});
});
it("shows not connected when garminConnected is false", async () => {
render(<SettingsPage />);
await waitFor(() => {
expect(screen.getByText(/not connected/i)).toBeInTheDocument();
});
});
it("shows connected when garminConnected is true", async () => {
mockFetch.mockResolvedValueOnce({
ok: true,
json: () => Promise.resolve({ ...mockUser, garminConnected: true }),
});
render(<SettingsPage />);
await waitFor(() => {
expect(screen.getByText(/connected to garmin/i)).toBeInTheDocument();
});
});
});
describe("data loading", () => {