Skip to content

Commit 6ee4a02

Browse files
committed
Fix flakiness for webkit
- Added code to ensure DOM is ready in webkit - Ensure page is not closed before interacting with elements
1 parent 5e26a31 commit 6ee4a02

File tree

3 files changed

+57
-21
lines changed

3 files changed

+57
-21
lines changed

tests/e2e/blocks/secondary-navigation.spec.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,19 @@ test('Test Secondary Navigation block', async ({page, admin, editor}) => {
3737
await searchAndInsertBlock({page}, 'Secondary Navigation Menu');
3838
await closeBlockInserter({page});
3939

40+
const blockRoot = page.locator('[data-type="planet4-blocks/secondary-navigation"]');
41+
await blockRoot.waitFor({state: 'attached'});
42+
4043
// Make sure it displays the empty message at first.
41-
await expect(page.locator('.EmptyMessage')).toBeVisible();
44+
const emptyMessage = blockRoot.locator('.EmptyMessage');
45+
await expect(emptyMessage).toBeVisible();
4246

4347
// Add content (headings and paragraphs).
44-
for (let index = 0; index < HEADINGS.length; index++) {
45-
await addHeadingOrParagraph({page}, 'Heading', 'h2', index, HEADINGS[index]);
46-
// For the paragraphs, we need to use index + 1 because there is a paragraph in the Page Header.
47-
await addHeadingOrParagraph({page}, 'Paragraph', 'p', index + 1, PARAGRAPH_CONTENT);
48-
};
48+
for (const heading of HEADINGS) {
49+
await addHeadingOrParagraph({page}, 'Heading', 'h2', heading);
50+
await page.waitForTimeout(20);
51+
await addHeadingOrParagraph({page}, 'Paragraph', 'p', PARAGRAPH_CONTENT);
52+
}
4953

5054
// Publish page.
5155
await publishPostAndVisit({page, editor});

tests/e2e/tools/lib/editor.js

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,19 @@ async function openComponentPanel({page, editor}, panelTitle) {
2727
* @param {{Page}} page
2828
*/
2929
const closeBlockInserter = async ({page}) => {
30-
const inserter = page.locator('.editor-inserter-sidebar');
30+
const getCloseButton = () => page.getByRole('button', {name: 'Close Block Inserter'});
3131

32-
if (await inserter.isVisible()) {
33-
await page.keyboard.press('Escape');
32+
try {
33+
await expect(getCloseButton()).toBeVisible({timeout: 1000});
34+
await getCloseButton().click();
35+
} catch (error) {
36+
if (process.env.CI) {
37+
// eslint-disable-next-line no-console
38+
console.warn(
39+
'[closeBlockInserter] skipped:',
40+
error?.message?.split('\n')[0]
41+
);
42+
}
3443
}
3544
};
3645

@@ -55,19 +64,17 @@ const searchAndInsertBlock = async ({page}, blockName, namespace = '') => {
5564
await searchInput.fill('');
5665
await searchInput.fill(blockName);
5766

58-
const blocksList = page.getByRole('listbox', {name: 'Blocks'});
59-
await expect(blocksList).toBeVisible();
60-
61-
let blockOption = blocksList.getByRole('option', {name: blockName});
67+
let blockOption = page.getByRole('option', {name: blockName});
6268

6369
if (namespace) {
64-
blockOption = blocksList.locator(
70+
blockOption = page.locator(
6571
`button.editor-block-list-item-${namespace.toLowerCase()}[role="option"]`
6672
);
6773
}
6874

69-
await expect(blockOption).toBeVisible();
70-
await blockOption.click();
75+
if (!page.isClosed()) {
76+
await page.evaluate(el => el.click(), await blockOption.elementHandle());
77+
}
7178
};
7279

7380
/**
@@ -86,14 +93,35 @@ const searchAndInsertPattern = async ({page}, id) => {
8693
* @param {{Page}} page
8794
* @param {string} blockName
8895
* @param {string} blockTag
89-
* @param {number} number
9096
* @param {string} text
9197
*/
92-
const addHeadingOrParagraph = async ({page}, blockName, blockTag, number, text) => {
98+
const addHeadingOrParagraph = async ({page}, blockName, blockTag, text) => {
9399
await searchAndInsertBlock({page}, blockName, blockName.toLowerCase());
94-
const newBlock = page.getByRole('region', {name: 'Editor content'}).locator(blockTag).nth(number);
95-
await expect(newBlock).toBeVisible();
100+
101+
const getNewBlock = () => page.getByRole('region', {name: 'Editor content'}).locator(`${blockTag}[contenteditable="true"]`).last();
102+
103+
// Wait for Gutenberg to finish inserting and the block to become editable
104+
await page.waitForFunction(
105+
newBlockTag => {
106+
const region = document.querySelector('[role="region"][aria-label="Editor content"]');
107+
if (!region) {return false;}
108+
const blocks = Array.from(region.querySelectorAll(newBlockTag));
109+
return blocks.some(b => b.isContentEditable && b.offsetParent !== null);
110+
},
111+
blockTag,
112+
{timeout: 5000}
113+
);
114+
96115
await closeBlockInserter({page});
116+
117+
// Webkit hack to allow re-render
118+
if (page.context().browser()?.browserType().name() === 'webkit') {
119+
if (!page.isClosed()) {
120+
await page.evaluate(() => new Promise(requestAnimationFrame));
121+
}
122+
}
123+
124+
const newBlock = getNewBlock();
97125
await newBlock.fill(text);
98126
};
99127

tests/e2e/tools/lib/post.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,11 @@ async function updatePost({page}) {
5151
async function publishPostAndVisit({page, editor}) {
5252
const urlString = await publishPost({page, editor});
5353

54-
await page.goto(urlString);
54+
if (page.isClosed()) {
55+
page = await page.context().newPage();
56+
}
57+
58+
await page.goto(urlString, {waitUntil: 'load'});
5559
}
5660

5761
/**

0 commit comments

Comments
 (0)