Skip to content

Commit 02da3fd

Browse files
authored
test: fix flaky versions tests timing out on link clicks before hydration (#15790)
### What Fix flaky versions e2e tests that timeout when clicking table row and version links. ### Why Since Next.js 16, clicking links before page hydration completes doesn't trigger navigation sometimes. The test finds the link and clicks it, but nothing happens, causing timeouts waiting for the page to load. ### How Extract href attributes and navigate directly with `page.goto()` instead of clicking. Also reduced typing delay in autosave test to complete within timeout under CPU throttling.
1 parent ee298f5 commit 02da3fd

File tree

2 files changed

+72
-52
lines changed

2 files changed

+72
-52
lines changed

test/versions/e2e.spec.ts

Lines changed: 33 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,9 @@ describe('Versions', () => {
196196

197197
test('collection — has versions tab', async () => {
198198
await page.goto(url.list)
199-
// Wait for hydration
200-
await wait(1000)
201-
await page.locator('tbody tr .cell-title a').first().click()
199+
const firstRowLink = page.locator('tbody tr .cell-title a').first()
200+
const docHref = await firstRowLink.getAttribute('href')
201+
await page.goto(`${serverURL}${docHref}`)
202202

203203
const versionsTab = page.locator('.doc-tab:has-text("Versions")')
204204
await versionsTab.waitFor({ state: 'visible' })
@@ -217,14 +217,14 @@ describe('Versions', () => {
217217
test('collection — tab displays proper number of versions', async () => {
218218
await page.goto(url.list)
219219
// Wait for hydration
220-
await wait(1000)
221220
const linkToDoc = page
222221
.locator('tbody tr .cell-title a', {
223222
hasText: exactText('Title With Many Versions 11'),
224223
})
225224
.first()
226225
expect(linkToDoc).toBeTruthy()
227-
await linkToDoc.click()
226+
const linkHref = await linkToDoc.getAttribute('href')
227+
await page.goto(`${serverURL}${linkHref}`)
228228
const versionsTab = page.locator('.doc-tab', {
229229
hasText: 'Versions',
230230
})
@@ -237,11 +237,9 @@ describe('Versions', () => {
237237

238238
test('collection — has versions route', async () => {
239239
await page.goto(url.list)
240-
// Wait for hydration
241-
await wait(1000)
242-
await page.locator('tbody tr .cell-title a').first().click()
243-
await page.waitForSelector('.doc-header__title', { state: 'visible' })
244-
await page.goto(`${page.url()}/versions`)
240+
const firstRowLink = page.locator('tbody tr .cell-title a').first()
241+
const docHref = await firstRowLink.getAttribute('href')
242+
await page.goto(`${serverURL}${docHref}/versions`)
245243
await expect(() => {
246244
expect(page.url()).toMatch(/\/versions/)
247245
}).toPass({ timeout: 10000, intervals: [100] })
@@ -270,9 +268,9 @@ describe('Versions', () => {
270268

271269
test('should show collection versions view level action in collection versions view', async () => {
272270
await page.goto(url.list)
273-
// Wait for hydration
274-
await wait(1000)
275-
await page.locator('tbody tr .cell-title a').first().click()
271+
const firstRowLink = page.locator('tbody tr .cell-title a').first()
272+
const docHref = await firstRowLink.getAttribute('href')
273+
await page.goto(`${serverURL}${docHref}`)
276274

277275
// Wait for the document to load
278276
const versionsTab = page.locator('.doc-tab', {
@@ -725,8 +723,7 @@ describe('Versions', () => {
725723
await page.goto(autosaveURL.list)
726724
const secondRowLink = page.locator('tbody tr:nth-child(2) .cell-title a')
727725
const docURL = await secondRowLink.getAttribute('href')
728-
await secondRowLink.click()
729-
await page.waitForURL(`**${docURL}`)
726+
await page.goto(`${serverURL}${docURL}`)
730727
await expect(page.locator('#field-title')).toHaveValue('first post title')
731728
await expect(page.locator('#field-description')).toHaveValue('first post description')
732729
})
@@ -739,9 +736,9 @@ describe('Versions', () => {
739736
await saveDocAndAssert(page)
740737

741738
await page.goto(customIDURL.list)
742-
// Wait for hydration
743-
await wait(1000)
744-
await page.locator('tbody tr .cell-id a').click()
739+
const customIDLink = page.locator('tbody tr .cell-id a')
740+
const docURL = await customIDLink.getAttribute('href')
741+
await page.goto(`${serverURL}${docURL}`)
745742

746743
await expect(page.locator('div.id-label')).toHaveText(/custom/)
747744
await expect(page.locator('#field-title')).toHaveValue('title')
@@ -972,11 +969,9 @@ describe('Versions', () => {
972969
describe('A11y', () => {
973970
test('Versions list view should have no accessibility violations', async ({}, testInfo) => {
974971
await page.goto(url.list)
975-
// Wait for hydration
976-
await wait(1000)
977-
await page.locator('tbody tr .cell-title a').first().click()
978-
await page.waitForSelector('.doc-header__title', { state: 'visible' })
979-
await page.goto(`${page.url()}/versions`)
972+
const firstRowLink = page.locator('tbody tr .cell-title a').first()
973+
const docHref = await firstRowLink.getAttribute('href')
974+
await page.goto(`${serverURL}${docHref}/versions`)
980975
await expect(() => {
981976
expect(page.url()).toMatch(/\/versions/)
982977
}).toPass({ timeout: 10000, intervals: [100] })
@@ -992,11 +987,9 @@ describe('Versions', () => {
992987

993988
test('Versions list view elements have focus indicators', async ({}, testInfo) => {
994989
await page.goto(url.list)
995-
// Wait for hydration
996-
await wait(1000)
997-
await page.locator('tbody tr .cell-title a').first().click()
998-
await page.waitForSelector('.doc-header__title', { state: 'visible' })
999-
await page.goto(`${page.url()}/versions`)
990+
const firstRowLink = page.locator('tbody tr .cell-title a').first()
991+
const docHref = await firstRowLink.getAttribute('href')
992+
await page.goto(`${serverURL}${docHref}/versions`)
1000993
await expect(() => {
1001994
expect(page.url()).toMatch(/\/versions/)
1002995
}).toPass({ timeout: 10000, intervals: [100] })
@@ -1013,16 +1006,16 @@ describe('Versions', () => {
10131006

10141007
test.fixme('Version view should have no accessibility violations', async ({}, testInfo) => {
10151008
await page.goto(url.list)
1016-
// Wait for hydration
1017-
await wait(1000)
1018-
await page.locator('tbody tr .cell-title a').first().click()
1019-
await page.waitForSelector('.doc-header__title', { state: 'visible' })
1020-
await page.goto(`${page.url()}/versions`)
1009+
const firstRowLink = page.locator('tbody tr .cell-title a').first()
1010+
const docHref = await firstRowLink.getAttribute('href')
1011+
await page.goto(`${serverURL}${docHref}/versions`)
10211012
await expect(() => {
10221013
expect(page.url()).toMatch(/\/versions/)
10231014
}).toPass({ timeout: 10000, intervals: [100] })
10241015

1025-
await page.locator('.cell-updatedAt a').first().click()
1016+
const versionLink = page.locator('.cell-updatedAt a').first()
1017+
const versionHref = await versionLink.getAttribute('href')
1018+
await page.goto(`${serverURL}${versionHref}`)
10261019

10271020
await page.locator('.view-version').waitFor()
10281021

@@ -1037,11 +1030,9 @@ describe('Versions', () => {
10371030

10381031
test('Version view elements have focus indicators', async ({}, testInfo) => {
10391032
await page.goto(url.list)
1040-
// Wait for hydration
1041-
await wait(1000)
1042-
await page.locator('tbody tr .cell-title a').first().click()
1043-
await page.waitForSelector('.doc-header__title', { state: 'visible' })
1044-
await page.goto(`${page.url()}/versions`)
1033+
const firstRowLink = page.locator('tbody tr .cell-title a').first()
1034+
const docHref = await firstRowLink.getAttribute('href')
1035+
await page.goto(`${serverURL}${docHref}/versions`)
10451036
await expect(() => {
10461037
expect(page.url()).toMatch(/\/versions/)
10471038
}).toPass({ timeout: 10000, intervals: [100] })
@@ -1265,7 +1256,8 @@ describe('Versions', () => {
12651256

12661257
const versionAnchor = versionsTable.locator('tbody tr.row-1 td.cell-updatedAt a')
12671258
await expect(versionAnchor).toBeVisible()
1268-
await versionAnchor.click()
1259+
const versionHref = await versionAnchor.getAttribute('href')
1260+
await page.goto(`${serverURL}${versionHref}`)
12691261

12701262
const compareFromContainer = page.locator(
12711263
'.view-version__version-from .field-type.compare-version',
@@ -1865,7 +1857,7 @@ describe('Versions', () => {
18651857

18661858
// press slower than the autosave interval, but not faster than the response and processing
18671859
await titleField.pressSequentially('Initial', {
1868-
delay: 150,
1860+
delay: 100,
18691861
})
18701862

18711863
const drawer = page.locator('[id^=doc-drawer_autosave-posts_1_]')

test/versions/payload-types.ts

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ export interface Config {
148148
'draft-unlimited-global': DraftUnlimitedGlobalSelect<false> | DraftUnlimitedGlobalSelect<true>;
149149
};
150150
locale: 'en' | 'es' | 'de';
151+
widgets: {
152+
collections: CollectionsWidget;
153+
};
151154
user: User;
152155
jobs: {
153156
tasks: {
@@ -405,17 +408,25 @@ export interface LocalizedPost {
405408
text?: string | null;
406409
description?: string | null;
407410
blocks?:
408-
| {
409-
array?:
410-
| {
411-
relationship?: (string | null) | Post;
412-
id?: string | null;
413-
}[]
414-
| null;
415-
id?: string | null;
416-
blockName?: string | null;
417-
blockType: 'block';
418-
}[]
411+
| (
412+
| {
413+
array?:
414+
| {
415+
relationship?: (string | null) | Post;
416+
id?: string | null;
417+
}[]
418+
| null;
419+
id?: string | null;
420+
blockName?: string | null;
421+
blockType: 'block';
422+
}
423+
| {
424+
blockText?: string | null;
425+
id?: string | null;
426+
blockName?: string | null;
427+
blockType: 'localizedTextBlock';
428+
}
429+
)[]
419430
| null;
420431
updatedAt: string;
421432
createdAt: string;
@@ -1123,6 +1134,13 @@ export interface LocalizedPostsSelect<T extends boolean = true> {
11231134
id?: T;
11241135
blockName?: T;
11251136
};
1137+
localizedTextBlock?:
1138+
| T
1139+
| {
1140+
blockText?: T;
1141+
id?: T;
1142+
blockName?: T;
1143+
};
11261144
};
11271145
updatedAt?: T;
11281146
createdAt?: T;
@@ -1573,6 +1591,16 @@ export interface DraftUnlimitedGlobalSelect<T extends boolean = true> {
15731591
createdAt?: T;
15741592
globalType?: T;
15751593
}
1594+
/**
1595+
* This interface was referenced by `Config`'s JSON-Schema
1596+
* via the `definition` "collections_widget".
1597+
*/
1598+
export interface CollectionsWidget {
1599+
data?: {
1600+
[k: string]: unknown;
1601+
};
1602+
width: 'full';
1603+
}
15761604
/**
15771605
* This interface was referenced by `Config`'s JSON-Schema
15781606
* via the `definition` "TaskSchedulePublish".

0 commit comments

Comments
 (0)