Skip to content

Commit fd81fd5

Browse files
authored
test: trash e2e list view clicks timing out in CI (#15778)
## What Fixed 8 instances of flaky list view navigation in trash e2e tests that were timing out after 30 seconds in CI. <img width="1425" height="558" alt="Screenshot 2026-02-26 at 4 12 54 PM" src="https://github.com/user-attachments/assets/fef3ef66-9baf-4ad6-9304-1f28c8242383" /> ### Why Next.js 16 introduced hydration timing issues where Playwright detects elements as actionable before click handlers are fully attached in slow CI environments. Tests with CPU throttling were consistently failing when clicking list view cells to navigate to trashed document edit views. ### How Replaced `.click()` actions on list view cells with direct navigation by extracting the href attribute and using `page.goto()`. This bypasses hydration delays by navigating directly to the URL instead of waiting for click event handlers.
1 parent bda5d0d commit fd81fd5

1 file changed

Lines changed: 27 additions & 13 deletions

File tree

test/trash/e2e.spec.ts

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -791,8 +791,10 @@ describe('Trash', () => {
791791

792792
await expect(page.locator('.row-1 .cell-title')).toHaveText('Post 1')
793793

794-
// Click on the first row to go to the trashed doc edit view
795-
await page.locator('.row-1 .cell-title').click()
794+
// Navigate to the first row's trashed doc edit view
795+
const cellLink = page.locator('.row-1 .cell-title a')
796+
const linkURL = await cellLink.getAttribute('href')
797+
await page.goto(`${serverURL}${linkURL}`)
796798

797799
await page.waitForURL(/\/posts\/trash\//)
798800
await page.getByRole('link', { name: 'Versions' }).waitFor({ state: 'visible' })
@@ -840,8 +842,10 @@ describe('Trash', () => {
840842

841843
await expect(page.locator('.row-1 .cell-title')).toHaveText('Post 1')
842844

843-
// Click on the first row to go to the trashed doc edit view
844-
await page.locator('.row-1 .cell-title').click()
845+
// Navigate to the first row's trashed doc edit view
846+
const cellLinkVersions = page.locator('.row-1 .cell-title a')
847+
const linkURLVersions = await cellLinkVersions.getAttribute('href')
848+
await page.goto(`${serverURL}${linkURLVersions}`)
845849

846850
await page.waitForURL(/\/posts\/trash\//)
847851
await page.getByRole('link', { name: 'Versions' }).waitFor({ state: 'visible' })
@@ -895,8 +899,10 @@ describe('Trash', () => {
895899

896900
await expect(page.locator('.row-1 .cell-title')).toHaveText('Post 1')
897901

898-
// Click on the first row to go to the trashed doc edit view
899-
await page.locator('.row-1 .cell-title').click()
902+
// Navigate to the first row's trashed doc edit view
903+
const cellLinkVersionView = page.locator('.row-1 .cell-title a')
904+
const linkURLVersionView = await cellLinkVersionView.getAttribute('href')
905+
await page.goto(`${serverURL}${linkURLVersionView}`)
900906

901907
await page.waitForURL(/\/posts\/trash\//)
902908
await page.getByRole('link', { name: 'Versions' }).waitFor({ state: 'visible' })
@@ -950,8 +956,10 @@ describe('Trash', () => {
950956

951957
await expect(page.locator('.row-1 .cell-title')).toHaveText('Post 1')
952958

953-
// Click on the first row to go to the trashed doc edit view
954-
await page.locator('.row-1 .cell-title').click()
959+
// Navigate to the first row's trashed doc edit view
960+
const cellLinkAPI = page.locator('.row-1 .cell-title a')
961+
const linkURLAPI = await cellLinkAPI.getAttribute('href')
962+
await page.goto(`${serverURL}${linkURLAPI}`)
955963

956964
await page.waitForURL(/\/posts\/trash\//)
957965
await page.getByRole('link', { name: 'API' }).waitFor({ state: 'visible' })
@@ -999,8 +1007,10 @@ describe('Trash', () => {
9991007

10001008
await expect(page.locator('.row-1 .cell-title')).toHaveText('Post 1')
10011009

1002-
// Click on the first row to go to the trashed doc edit view
1003-
await page.locator('.row-1 .cell-title').click()
1010+
// Navigate to the first row's trashed doc edit view
1011+
const cellLinkAPIBreadcrumb = page.locator('.row-1 .cell-title a')
1012+
const linkURLAPIBreadcrumb = await cellLinkAPIBreadcrumb.getAttribute('href')
1013+
await page.goto(`${serverURL}${linkURLAPIBreadcrumb}`)
10041014

10051015
await page.waitForURL(/\/posts\/trash\//)
10061016
await page.getByRole('link', { name: 'API' }).waitFor({ state: 'visible' })
@@ -1096,7 +1106,8 @@ describe('Trash', () => {
10961106
await expect(page.locator('.row-1 .cell-name')).toHaveText('Dev')
10971107
const nameLink = page.locator('.row-1 .cell-name a')
10981108
await expect(nameLink).toBeVisible()
1099-
await nameLink.click()
1109+
const linkURL = await nameLink.getAttribute('href')
1110+
await page.goto(`${serverURL}${linkURL}`)
11001111

11011112
await page.waitForURL(/\/users\/trash\/[a-f0-9]{24}/)
11021113
await page.locator('input[name="email"]').waitFor({ state: 'visible' })
@@ -1110,7 +1121,9 @@ describe('Trash', () => {
11101121
await page.goto(usersUrl.trash)
11111122

11121123
await expect(page.locator('.row-1 .cell-name')).toHaveText('Dev')
1113-
await page.locator('.row-1 .cell-name').click()
1124+
const cellLink = page.locator('.row-1 .cell-name a')
1125+
const linkURL = await cellLink.getAttribute('href')
1126+
await page.goto(`${serverURL}${linkURL}`)
11141127

11151128
await page.waitForURL(/\/users\/trash\/[a-f0-9]{24}/)
11161129
await page.locator('input[name="email"]').waitFor({ state: 'visible' })
@@ -1132,7 +1145,8 @@ describe('Trash', () => {
11321145
await expect(page.locator('.row-1 .cell-name')).toHaveText('Dev')
11331146
const nameLink = page.locator('.row-1 .cell-name a')
11341147
await expect(nameLink).toBeVisible()
1135-
await nameLink.click()
1148+
const linkURLRestore = await nameLink.getAttribute('href')
1149+
await page.goto(`${serverURL}${linkURLRestore}`)
11361150

11371151
await page.waitForURL(/\/users\/trash\/[a-f0-9]{24}/)
11381152
await page.locator('.doc-controls__controls #action-restore').waitFor({ state: 'visible' })

0 commit comments

Comments
 (0)