diff --git a/client/src/pages/DashboardPage.test.tsx b/client/src/pages/DashboardPage.test.tsx
index 66936ead..20448828 100644
--- a/client/src/pages/DashboardPage.test.tsx
+++ b/client/src/pages/DashboardPage.test.tsx
@@ -86,10 +86,10 @@ describe('DashboardPage', () => {
render();
await waitFor(() => {
- expect(screen.getByRole('button', { name: /new trip/i })).toBeInTheDocument();
+ expect(screen.getAllByRole('button', { name: /new trip/i }).length).toBeGreaterThan(0);
});
- await user.click(screen.getByRole('button', { name: /new trip/i }));
+ await user.click(screen.getAllByRole('button', { name: /new trip/i })[0]);
// TripFormModal opens — "Create New Trip" appears in heading and submit button
await waitFor(() => {
@@ -322,17 +322,13 @@ describe('DashboardPage', () => {
render();
await waitFor(() => {
- expect(screen.getByText('Tokyo Trip')).toBeInTheDocument();
+ // Mobile + desktop may render the same trip twice
+ expect(screen.getAllByText('Tokyo Trip').length).toBeGreaterThan(0);
});
- // Click the trip title text (not an action button) on a non-spotlight card
- // Tokyo Trip appears as a TripCard (not SpotlightCard since Paris Adventure is spotlight)
- // Find the card by its title text — clicking it triggers navigate
- const tokyoTrip = screen.getByText('Tokyo Trip');
+ const tokyoTrip = screen.getAllByText('Tokyo Trip')[0];
await user.click(tokyoTrip);
- // After click, MemoryRouter won't actually navigate but we verify no errors occur
- // and the click was processed (the card was clickable)
expect(tokyoTrip).toBeInTheDocument();
});
});
@@ -343,7 +339,7 @@ describe('DashboardPage', () => {
render();
await waitFor(() => {
- expect(screen.getByText('Paris Adventure')).toBeInTheDocument();
+ expect(screen.getAllByText('Paris Adventure').length).toBeGreaterThan(0);
});
// Switch to list view
@@ -352,12 +348,12 @@ describe('DashboardPage', () => {
// Both trips should still be visible in list view
await waitFor(() => {
- expect(screen.getByText('Paris Adventure')).toBeInTheDocument();
- expect(screen.getByText('Tokyo Trip')).toBeInTheDocument();
+ expect(screen.getAllByText('Paris Adventure').length).toBeGreaterThan(0);
+ expect(screen.getAllByText('Tokyo Trip').length).toBeGreaterThan(0);
});
// In list view, clicking Tokyo Trip card should work
- const tokyoTrip = screen.getByText('Tokyo Trip');
+ const tokyoTrip = screen.getAllByText('Tokyo Trip')[0];
await user.click(tokyoTrip);
expect(tokyoTrip).toBeInTheDocument();
});
@@ -369,7 +365,7 @@ describe('DashboardPage', () => {
render();
await waitFor(() => {
- expect(screen.getByText('Paris Adventure')).toBeInTheDocument();
+ expect(screen.getAllByText('Paris Adventure').length).toBeGreaterThan(0);
});
// Switch to list view
@@ -378,16 +374,11 @@ describe('DashboardPage', () => {
// Both trips render in list view
await waitFor(() => {
- expect(screen.getByText('Paris Adventure')).toBeInTheDocument();
- expect(screen.getByText('Tokyo Trip')).toBeInTheDocument();
+ expect(screen.getAllByText('Paris Adventure').length).toBeGreaterThan(0);
+ expect(screen.getAllByText('Tokyo Trip').length).toBeGreaterThan(0);
});
- // In list view, CardAction buttons have no label/title — find by icon content
- // The delete buttons are CardAction with danger style; there are multiple action groups
- // Each trip row has: Edit, Copy, Archive, Delete buttons (4 per row)
const allButtons = screen.getAllByRole('button');
- // Find delete buttons — they are the 4th in each group, but simpler:
- // Just verify there are multiple action buttons rendered in list view
expect(allButtons.length).toBeGreaterThan(4);
});
});
@@ -425,20 +416,23 @@ describe('DashboardPage', () => {
render();
await waitFor(() => {
- expect(screen.getByText('Paris Adventure')).toBeInTheDocument();
+ expect(screen.getAllByText('Paris Adventure').length).toBeGreaterThan(0);
});
- // Header has 3 buttons: view-toggle (has title), settings gear (no title, no text), New Trip (has text)
- // Find settings button: no title attr, and text content doesn't include 'New Trip'
+ // Find settings button — it's the gear icon button without title or text
const allBtns = screen.getAllByRole('button');
const settingsButton = allBtns.find(
- btn => !btn.getAttribute('title') && !btn.textContent?.trim()
+ btn => {
+ const title = btn.getAttribute('title');
+ const text = btn.textContent?.trim() || '';
+ // Settings gear: no title, no meaningful text, not the notification bell
+ return !title && !text && btn.querySelector('.lucide-settings');
+ }
);
expect(settingsButton).toBeDefined();
if (settingsButton) {
await user.click(settingsButton);
- // Widget settings panel shows "Widgets:" label
await waitFor(() => {
expect(screen.getByText('Widgets:')).toBeInTheDocument();
});
@@ -507,10 +501,10 @@ describe('DashboardPage', () => {
render();
await waitFor(() => {
- expect(screen.getByRole('button', { name: /new trip/i })).toBeInTheDocument();
+ expect(screen.getAllByRole('button', { name: /new trip/i }).length).toBeGreaterThan(0);
});
- await user.click(screen.getByRole('button', { name: /new trip/i }));
+ await user.click(screen.getAllByRole('button', { name: /new trip/i })[0]);
await waitFor(() => {
expect(screen.getAllByText(/create new trip/i).length).toBeGreaterThan(0);