Skip to content

Commit ec7ee3f

Browse files
committed
fix: resolve e2e test failures across browsers
- Change Board from nested <main> to <section role="region"> to fix invalid HTML semantics (main elements shouldn't be nested) - Fix auth-flow tests that incorrectly expected Board visible after login when EmptyBoardWelcome is actually rendered - Fix race conditions in waitForResponse calls by using Promise.all pattern to start waiting before triggering the action - Update Board unit tests to use getByRole('region') instead of getByRole('main')
1 parent cf36bb9 commit ec7ee3f

File tree

5 files changed

+39
-29
lines changed

5 files changed

+39
-29
lines changed

src/components/Board/Board.test.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -446,24 +446,24 @@ describe('Board', () => {
446446
})
447447

448448
describe('accessibility', () => {
449-
it('should have main landmark role', () => {
449+
it('should have region landmark role', () => {
450450
render(<Board {...defaultProps} />)
451451

452-
expect(screen.getByRole('main')).toBeInTheDocument()
452+
expect(screen.getByRole('region', { name: 'Kanban Board' })).toBeInTheDocument()
453453
})
454454

455455
it('should have aria-label for the board', () => {
456456
render(<Board {...defaultProps} />)
457457

458-
const main = screen.getByRole('main')
459-
expect(main).toHaveAttribute('aria-label', expect.stringContaining('Kanban'))
458+
const board = screen.getByRole('region', { name: 'Kanban Board' })
459+
expect(board).toHaveAttribute('aria-label', expect.stringContaining('Kanban'))
460460
})
461461

462462
it('should have aria-busy when loading', () => {
463463
render(<Board {...defaultProps} isLoading={true} />)
464464

465-
const main = screen.getByRole('main')
466-
expect(main).toHaveAttribute('aria-busy', 'true')
465+
const board = screen.getByRole('region', { name: 'Kanban Board' })
466+
expect(board).toHaveAttribute('aria-busy', 'true')
467467
})
468468
})
469469

src/components/Board/Board.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -563,8 +563,8 @@ export function Board({
563563
onDragStart={handleDragStart}
564564
onDragEnd={handleDragEnd}
565565
>
566-
<main
567-
role="main"
566+
<section
567+
role="region"
568568
aria-label="Kanban Board"
569569
aria-busy={isLoading}
570570
className="min-h-screen bg-bg-primary py-6"
@@ -640,7 +640,7 @@ export function Board({
640640
isLoading={isLoading}
641641
hasActiveFilters={hasActiveFilters}
642642
/>
643-
</main>
643+
</section>
644644

645645
{/* Drag overlay - shows the card being dragged */}
646646
<DragOverlay>

tests/integration/auth-flow.spec.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,9 @@ test.describe('Auth Flow', () => {
8484

8585
// Modal should close
8686
await expect(page.getByRole('dialog')).not.toBeVisible({ timeout: 10000 })
87-
// Board should be visible
88-
await expect(page.getByRole('main', { name: 'Kanban Board' })).toBeVisible()
87+
// Main content should be visible (EmptyBoardWelcome is shown before filters are applied)
88+
await expect(page.getByRole('main')).toBeVisible()
89+
await expect(page.getByText('Get Started')).toBeVisible()
8990
})
9091

9192
// Skip: API key persistence relies on Web Crypto API encryption which may not
@@ -123,8 +124,9 @@ test.describe('Auth Flow', () => {
123124

124125
// Modal should NOT appear (key is persisted)
125126
await expect(page.getByRole('dialog')).not.toBeVisible({ timeout: 10000 })
126-
// Board should be visible
127-
await expect(page.getByRole('main', { name: 'Kanban Board' })).toBeVisible()
127+
// Main content should be visible
128+
await expect(page.getByRole('main')).toBeVisible()
129+
await expect(page.getByText('Get Started')).toBeVisible()
128130
})
129131

130132
test('should allow clearing API key and show modal again', async ({ page }) => {

tests/integration/filter-flow.spec.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -205,14 +205,16 @@ test.describe('Filter Flow', () => {
205205

206206
await whiteboardInput.fill('kanban')
207207
await componentInput.fill('Frontend')
208-
await page.getByRole('button', { name: 'Apply Filters' }).click()
209208

210-
// Wait for request with both filters
211-
await page.waitForResponse(
212-
(response) =>
213-
response.url().includes('whiteboard=kanban') &&
214-
response.url().includes('component=Frontend'),
215-
)
209+
// Wait for request with both filters (start waiting before clicking to avoid race condition)
210+
await Promise.all([
211+
page.waitForResponse(
212+
(response) =>
213+
response.url().includes('whiteboard=kanban') &&
214+
response.url().includes('component=Frontend'),
215+
),
216+
page.getByRole('button', { name: 'Apply Filters' }).click(),
217+
])
216218

217219
// Should show only the matching bug
218220
await expect(page.getByText('Frontend bug with kanban tag')).toBeVisible({ timeout: 10000 })
@@ -280,13 +282,17 @@ test.describe('Filter Flow', () => {
280282
// Apply filter
281283
const whiteboardInput = page.getByPlaceholder('e.g., [kanban] or bug-triage')
282284
await whiteboardInput.fill('kanban')
283-
await page.getByRole('button', { name: 'Apply Filters' }).click()
284-
await page.waitForResponse('**/api/bugzilla/**')
285+
await Promise.all([
286+
page.waitForResponse('**/api/bugzilla/**'),
287+
page.getByRole('button', { name: 'Apply Filters' }).click(),
288+
])
285289

286290
// Clear filter
287291
await page.getByRole('button', { name: 'Clear' }).click()
288-
await page.getByRole('button', { name: 'Apply Filters' }).click()
289-
await page.waitForResponse('**/api/bugzilla/**')
292+
await Promise.all([
293+
page.waitForResponse('**/api/bugzilla/**'),
294+
page.getByRole('button', { name: 'Apply Filters' }).click(),
295+
])
290296

291297
// Both types of requests should have been made
292298
expect(requestWithFilter).toBe(true)

tests/integration/kanban-flow.spec.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -246,12 +246,14 @@ test.describe('Kanban Flow', () => {
246246
// Click Apply Changes
247247
const applyButton = page.getByRole('button', { name: /Apply 1 change/i })
248248
await expect(applyButton).toBeVisible({ timeout: 5000 })
249-
await applyButton.click()
250249

251-
// Wait for the update request
252-
await page.waitForResponse(
253-
(response) => response.request().method() === 'PUT' && response.url().includes('/bug/'),
254-
)
250+
// Wait for the update request (start waiting before clicking to avoid race condition)
251+
await Promise.all([
252+
page.waitForResponse(
253+
(response) => response.request().method() === 'PUT' && response.url().includes('/bug/'),
254+
),
255+
applyButton.click(),
256+
])
255257

256258
// Verify the update request was made (backlog->todo adds sprint tag to whiteboard)
257259
expect(updateRequestMade).toBe(true)

0 commit comments

Comments
 (0)