-
Notifications
You must be signed in to change notification settings - Fork 39
Fix flaky e2e tests, focus on Webkit and making sure the DOM is ready so events fire properly #2841
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,10 +27,19 @@ async function openComponentPanel({page, editor}, panelTitle) { | |
| * @param {{Page}} page | ||
| */ | ||
| const closeBlockInserter = async ({page}) => { | ||
| const inserter = page.locator('.editor-inserter-sidebar'); | ||
| const getCloseButton = () => page.getByRole('button', {name: 'Close Block Inserter'}); | ||
|
|
||
| if (await inserter.isVisible()) { | ||
| await page.keyboard.press('Escape'); | ||
| try { | ||
| await expect(getCloseButton()).toBeVisible({timeout: 1000}); | ||
| await getCloseButton().click(); | ||
| } catch (error) { | ||
| if (process.env.CI) { | ||
| // eslint-disable-next-line no-console | ||
| console.warn( | ||
| '[closeBlockInserter] skipped:', | ||
| error?.message?.split('\n')[0] | ||
| ); | ||
| } | ||
| } | ||
| }; | ||
|
|
||
|
|
@@ -46,29 +55,26 @@ const closeBlockInserter = async ({page}) => { | |
| const searchAndInsertBlock = async ({page}, blockName, namespace = '') => { | ||
| const openSidebar = await page.getByRole('button', {name: 'Block Inserter', exact: true}); | ||
| const searchInput = page.getByPlaceholder('Search'); | ||
|
|
||
| if (await openSidebar.getAttribute('aria-expanded') === 'false') { | ||
| await openSidebar.dispatchEvent('click'); | ||
| await openSidebar.click(); | ||
| await expect(searchInput).toBeVisible(); | ||
| } | ||
|
|
||
| await searchInput.fill(''); | ||
| await searchInput.fill(blockName); | ||
|
|
||
| const blocksList = page.getByRole('listbox', {name: 'Blocks'}); | ||
| await expect(blocksList).toBeVisible(); | ||
|
|
||
| let blockOption; | ||
| let blockOption = page.getByRole('option', {name: blockName}); | ||
|
|
||
| if (namespace) { | ||
| blockOption = blocksList.locator( | ||
| blockOption = page.locator( | ||
| `button.editor-block-list-item-${namespace.toLowerCase()}[role="option"]` | ||
| ); | ||
| } else { | ||
| blockOption = blocksList.getByRole('option', {name: blockName}); | ||
| } | ||
|
|
||
| await expect(blockOption).toBeVisible(); | ||
| await blockOption.click(); | ||
| if (!page.isClosed()) { | ||
| await page.evaluate(el => el.click(), await blockOption.elementHandle()); | ||
| } | ||
| }; | ||
|
|
||
| /** | ||
|
|
@@ -87,14 +93,35 @@ const searchAndInsertPattern = async ({page}, id) => { | |
| * @param {{Page}} page | ||
| * @param {string} blockName | ||
| * @param {string} blockTag | ||
| * @param {number} number | ||
| * @param {string} text | ||
| */ | ||
| const addHeadingOrParagraph = async ({page}, blockName, blockTag, number, text) => { | ||
| const addHeadingOrParagraph = async ({page}, blockName, blockTag, text) => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With the new changes, this function looks pretty generic to me, and it could be used for other blocks, not only headings or paragraphs.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We already have a generic function to add blocks to pages, I am not sure but this is also pretty reusable if there is a use case, as for the changes, those are just hacks to ensure there is enough time to allow DOM update and stability before certain actions take place, different browsers render differently hence the reason for flakiness in some of our tests |
||
| await searchAndInsertBlock({page}, blockName, blockName.toLowerCase()); | ||
| const newBlock = page.getByRole('region', {name: 'Editor content'}).locator(blockTag).nth(number); | ||
| await expect(newBlock).toBeVisible(); | ||
|
|
||
| const getNewBlock = () => page.getByRole('region', {name: 'Editor content'}).locator(`${blockTag}[contenteditable="true"]`).last(); | ||
|
|
||
| // Wait for Gutenberg to finish inserting and the block to become editable | ||
| await page.waitForFunction( | ||
| newBlockTag => { | ||
| const region = document.querySelector('[role="region"][aria-label="Editor content"]'); | ||
| if (!region) {return false;} | ||
| const blocks = Array.from(region.querySelectorAll(newBlockTag)); | ||
| return blocks.some(b => b.isContentEditable && b.offsetParent !== null); | ||
| }, | ||
| blockTag, | ||
| {timeout: 5000} | ||
| ); | ||
|
|
||
| await closeBlockInserter({page}); | ||
|
|
||
| // Webkit hack to allow re-render | ||
| if (page.context().browser()?.browserType().name() === 'webkit') { | ||
| if (!page.isClosed()) { | ||
| await page.evaluate(() => new Promise(requestAnimationFrame)); | ||
| } | ||
| } | ||
|
|
||
| const newBlock = getNewBlock(); | ||
| await newBlock.fill(text); | ||
| }; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need the
catchblock?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to have some kind of way to see why the try block didn't run