fix: update Dashboard tests for dual mobile+desktop rendering in jsdom

- Use getAllBy* instead of getBy* where mobile + desktop render same content
- Settings button finder uses .lucide-settings selector
This commit is contained in:
Maurice
2026-04-11 19:25:30 +02:00
parent a6a12acad7
commit 42c12ea26d
+22 -28
View File
@@ -86,10 +86,10 @@ describe('DashboardPage', () => {
render(<DashboardPage />);
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(<DashboardPage />);
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(<DashboardPage />);
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(<DashboardPage />);
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(<DashboardPage />);
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(<DashboardPage />);
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);