-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Try to rewrite e2e tests using jest-puppeter preset #8301
Conversation
0683a23
to
249807f
Compare
test/e2e/specs/preview.test.js
Outdated
expect( previewPage.url() ).toBe( expectedPreviewURL ); | ||
|
||
// Return to editor to change title. | ||
await editorPage.bringToFront(); | ||
await editorPage.type( '.editor-post-title__input', ' And more.' ); | ||
|
||
// Published preview should reuse same popup frame. | ||
previewPage = await getOpenedPreviewPage(); | ||
// TODO: Fix code to reuse the same frame! | ||
previewPage = await getOpenedPreviewPage( editorPage ); |
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.
This is the only place where we don't reuse the same frame. Very surprising given given that there is code comment which states it 😃
2e26a08
to
8d46c2f
Compare
Travis run for e2e tests is back to 7 minutes! This is what I see locally:
|
a95eae1
to
69126e1
Compare
|
||
afterEach( async () => { | ||
// Clear localStorage tips so they aren't persisted for the next test. | ||
await clearLocalStorage(); |
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.
Is this not needed anymore?
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.
We clear localStorage
after every test suite. In addition, when opening the editor and enableTips
flag is passed we clean all disabled tips and reload the page.
@@ -17,7 +15,7 @@ describe( 'Multi-block selection', () => { | |||
const multiSelectedCssClass = 'is-multi-selected'; | |||
|
|||
// Creating test blocks | |||
await page.click( '.editor-default-block-appender' ); | |||
await page.click( '.editor-default-block-appender__content' ); |
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.
Just curious why this change?
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.
For consistency, we probably should wrap it with a utility method. Initially, I suspected that it might be the reason why undo test fails sometimes.
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.
This updated class is the one which has the events bound, so it's more "correct".
newPost, | ||
pressWithModifier, | ||
searchForBlock, | ||
} from '../support/utils'; | ||
|
||
function waitForAndAcceptDialog() { | ||
return new Promise( ( resolve ) => { | ||
page.once( 'dialog', async ( dialog ) => { | ||
await dialog.accept(); |
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.
Why are we removing this?
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.
We have global handler so you don't need to accept it twice.
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.
Can we remove the entire waitForAndAcceptDialog
function, then?
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.
We use this Promise
, so not quite sure 🤷♂️
@@ -66,8 +61,7 @@ describe( 'Publishing', () => { | |||
|
|||
it( 'Should reopen sidebar the sidebar when resizing from mobile to desktop if the sidebar was closed automatically', async () => { | |||
await setViewport( 'large' ); | |||
await newPost(); | |||
await setViewport( 'small' ); | |||
await newPost( { viewport: 'small' } ); |
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.
I think it's weird to have an option to set the viewport size as part of the newPost
helper, I prefer a separate helper for that.
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.
I can revert those changes. Previously, we were setting large
viewport using newDesktopBrowserPage
helper.
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.
Reverted 👍
headless: PUPPETEER_HEADLESS !== 'false', | ||
slowMo: parseInt( PUPPETEER_SLOWMO, 10 ) || 0, | ||
} ); | ||
enablePageDialogAccept(); |
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.
I don't like that we're accepting dialogs globally, I prefer the explicitness we had before, because sometimes we want to test these dialogs
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.
We need for the majority of test suites as far as I discovered today. There is disablePageDialogAccept
method which would be useful in case when you want to handle it yourself. I'm happy to refactor, but then we would have to put it for every test which types something.
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.
Ok 👍 It's fine
I'd appreciate if we extend our testing docs with steps to:
Just trying to think of alternative workflows (other than CI) needed to debug and build tests. |
I brought back explicit calls for I also added a change which ensures |
@youknowriad I opened a follow-up issue for your comment about documentation - #8319. |
Added another small tweak which improves the trigger which wraps up after tests cleanup: 384cf5e. |
Pushed up some code in 5ce6245 that makes the preview test pass consistently everywhere I try it. Looked at this, and there's a problem with using the Because we can't reliably get the created target, I've introduced a I also changed the test to only reuse the preview page in tests that we explicitly check for reuse behaviour. There are also assertions that we have the expected number of tabs open at all times. The test passes consistently for me now, both with the browser and in headless mode (both of which resulted in different race conditions in the original test - it used to be possible for the test to fail because it thought the preview page had reloaded with updated content, but it hadn't yet even though it was in the process of doing so). |
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.
Left a few minor comments. Would love to get this in very soon—it's hard to review PRs when they're all 🔴! 😅
test/e2e/specs/preview.test.js
Outdated
} | ||
function sleep( time ) { | ||
return new Promise( ( resolve ) => setTimeout( resolve, time ) ); | ||
} |
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.
Puppeteer already provides this function in the form of page.waitFor
.
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.
Also, I think we discussed this previously and the conclusion is to prefer waitForSelector
over waitFor
/sleep
, since it's more reliable.
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.
You can't wait for a selector on a page that doesn't exist yet though, you have to have the page instance, and that's what this is for.
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.
Ok, that's fine, can we add an inline comment with this explanation?
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.
Sure, in fact I've already changed this code locally and used the editor page to call waitFor
, with an inline comment :)
test/e2e/specs/preview.test.js
Outdated
expect( previewPage.url() ).toBe( expectedPreviewURL ); | ||
|
||
// Return to editor to change title. | ||
await editorPage.bringToFront(); | ||
await editorPage.type( '.editor-post-title__input', ' And more.' ); | ||
|
||
// Published preview should reuse same popup frame. | ||
previewPage = await getOpenedPreviewPage(); | ||
// TODO: Fix an existing bug which opens a new tab. |
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.
Can we create an issue to track this work?
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.
newPost, | ||
pressWithModifier, | ||
searchForBlock, | ||
} from '../support/utils'; | ||
|
||
function waitForAndAcceptDialog() { | ||
return new Promise( ( resolve ) => { | ||
page.once( 'dialog', async ( dialog ) => { | ||
await dialog.accept(); |
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.
Can we remove the entire waitForAndAcceptDialog
function, then?
Heads up that #8330 contains a fix for the |
6e7f7de
to
6687d0a
Compare
It passed 2 times after recent tweaks. We should merge as soon as someone confirms I didn't break anything else 😅 |
🚢 Works well on my poor little laptop even when it's under load! This is a huge improvement. Thank you! |
Thank you all for commits, reviews, and testing. Let's iterate on this as it is still not perfect 🚀 |
Description
Closes #8619.
Improves #6956. See known issues to find out what is still necessary to make it bulletproof.
Tries to fix intermittent e2e test failures. In particular an error with
preview
test:This is try to use
jest-puppeteer
preset recommended in Jest docs:https://jestjs.io/docs/en/puppeteer#use-puppeteer-preset
The biggest difference is that we no longer use isolated browser instance per test suite but share one browser to speed up tests execution.
It also enables some new methods to
expect
API. See:https://github.com/smooth-code/jest-puppeteer/tree/master/packages/expect-puppeteer#api
How has this been tested?
npm run test-e2e
Knows issues
We should open a follow up tasks for two issues.
Preview opens new tab after publish
Steps to reproduce:
Too many undo levels
It happens only in the headless mode when running e2e tests. Sometimes it creates two undo levels for the first paragraph. When you modify test and add snapshots after each undo action you might see the following:
This isn't expected behavior. It uncovers some edge case happening inside the logic which creates undo levels.