Skip to content

Commit

Permalink
Stop using targetcreated, see berstend/puppeteer-extra#6
Browse files Browse the repository at this point in the history
  • Loading branch information
notnownikki committed Jul 31, 2018
1 parent 384cf5e commit 5ce6245
Showing 1 changed file with 44 additions and 72 deletions.
116 changes: 44 additions & 72 deletions test/e2e/specs/preview.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,81 +13,45 @@ import {
} from '../support/utils';

describe( 'Preview', () => {

beforeEach( async () => {
await newPost();
} );

function sleep( time ) {
return new Promise( resolve => setTimeout( resolve, time ) );
}

/**
* Clicks the preview button and returns the generated preview window page,
* either the newly created tab or the redirected existing target. This is
* required because Chromium infuriatingly disregards same target name in
* specific undetermined circumstances, else our efforts to reuse the same
* popup have been fruitless and exhausting. It is worth exploring further,
* perhaps considering factors such as origin of the interstitial page (the
* about:blank placeholder screen), or whether the preview link default
* behavior is used / prevented by the display of the popup window of the
* same target name. Resolves only once the preview page has finished
* loading.
*
* @param {Promise} editorPage Editor's page.
* @param {Page} lastPreviewPage Last preview page.
*
* @return {Promise} Promise resolving with focused, loaded preview page.
* Waits for the number of open tabs to change. Listening for `targetcreated` is not reliable
* see: https://github.com/berstend/puppeteer-extra/issues/6
* The listeners sometimes get called too late, and the test has carried on without getting
* the target, and we end up with a crash.
*/
async function getOpenedPreviewPage( editorPage, lastPreviewPage ) {
const eventHandlers = [];

const race = [
new Promise( ( resolve ) => {
async function onBrowserTabOpened( target ) {
const targetPage = await target.page();
if ( targetPage.url() === 'about:blank' ) {
await targetPage.waitForNavigation();
}
if ( lastPreviewPage ) {
// If a new preview tab is opened and there was a previous one, close
// the previous tab.
await lastPreviewPage.close();
}
resolve( targetPage );
}
browser.once( 'targetcreated', onBrowserTabOpened );
eventHandlers.push( [ browser, 'targetcreated', onBrowserTabOpened ] );
} ),
];

if ( lastPreviewPage ) {
race.push(
new Promise( async ( resolve ) => {
async function onLastPreviewPageLoaded() {
await lastPreviewPage.reload();
resolve( lastPreviewPage );
}
lastPreviewPage.once( 'load', onLastPreviewPageLoaded );
eventHandlers.push( [ lastPreviewPage, 'load', onLastPreviewPageLoaded ] );
} )
);
async function waitForTab( numTabs ) {
let tabs = await browser.pages();
while ( tabs.length === numTabs ) {
await sleep(100);
tabs = await browser.pages();
}
}

editorPage.click( '.editor-post-preview' );

// The preview page is whichever of the two resolves first:
// - A new tab has opened.
// - An existing tab is reused and navigates.
const previewPage = await Promise.race( race );

// Since there may be lingering event handlers from whichever of the
// race candidates had lost, remove all handlers.
eventHandlers.forEach( ( [ target, event, handler ] ) => {
target.removeListener( event, handler );
} );
async function openPreviewPage( editorPage ) {
let openTabs = await browser.pages();
const numberOfTabs = openTabs.length;
expect( numberOfTabs ).toBe( 2 );

await previewPage.bringToFront();
editorPage.click( '.editor-post-preview' );
await waitForTab( numberOfTabs );

if ( lastPreviewPage ) {
expect( previewPage ).toBe( lastPreviewPage );
}
openTabs = await browser.pages();
expect( openTabs.length ).toBe( 3 );

const previewPage = openTabs[ openTabs.length - 1 ];
// Wait for the preview to load. We can't do interstitial detection here,
// because it might load too quickly for us to pick up, so we wait for
// the preview to load by waiting for the title to appear.
await previewPage.waitForSelector( '.entry-title' );
return previewPage;
}

Expand All @@ -104,7 +68,7 @@ describe( 'Preview', () => {

await editorPage.type( '.editor-post-title__input', 'Hello World' );

previewPage = await getOpenedPreviewPage( editorPage );
previewPage = await openPreviewPage( editorPage );

// When autosave completes for a new post, the URL of the editor should
// update to include the ID. Use this to assert on preview URL.
Expand All @@ -114,26 +78,29 @@ describe( 'Preview', () => {

let expectedPreviewURL = getUrl( '', `?p=${ postId }&preview=true` );
expect( previewPage.url() ).toBe( expectedPreviewURL );

// Title in preview should match input.
let previewTitle = await previewPage.$eval( '.entry-title', ( node ) => node.textContent );
expect( previewTitle ).toBe( 'Hello World' );

await previewPage.close();

// Return to editor to change title.
await editorPage.bringToFront();
await editorPage.type( '.editor-post-title__input', '!' );
previewPage = await getOpenedPreviewPage( editorPage, previewPage );
previewPage = await openPreviewPage( editorPage );

// Title in preview should match updated input.
previewTitle = await previewPage.$eval( '.entry-title', ( node ) => node.textContent );
expect( previewTitle ).toBe( 'Hello World!' );
await previewPage.close();

// Pressing preview without changes should bring same preview window to
// front and reload, but should not show interstitial.
await editorPage.bringToFront();
previewPage = await getOpenedPreviewPage( editorPage, previewPage );
previewPage = await openPreviewPage( editorPage );
previewTitle = await previewPage.$eval( '.entry-title', ( node ) => node.textContent );
expect( previewTitle ).toBe( 'Hello World!' );
await previewPage.close();

// Preview for published post (no unsaved changes) directs to canonical
// URL for post.
Expand All @@ -144,7 +111,7 @@ describe( 'Preview', () => {
editorPage.click( '.editor-post-publish-panel__header button' ),
] );
expectedPreviewURL = await editorPage.$eval( '.notice-success a', ( node ) => node.href );
previewPage = await getOpenedPreviewPage( editorPage, previewPage );
previewPage = await openPreviewPage( editorPage );
expect( previewPage.url() ).toBe( expectedPreviewURL );

// Return to editor to change title.
Expand All @@ -153,7 +120,9 @@ describe( 'Preview', () => {

// Published preview should reuse same popup frame.
// TODO: Fix an existing bug which opens a new tab.
previewPage = await getOpenedPreviewPage( editorPage );
let previewNav = previewPage.waitForNavigation();
editorPage.click( '.editor-post-preview' );
await previewNav;

// Title in preview should match updated input.
previewTitle = await previewPage.$eval( '.entry-title', ( node ) => node.textContent );
Expand All @@ -171,10 +140,13 @@ describe( 'Preview', () => {
//
// See: https://github.com/WordPress/gutenberg/issues/7561
await editorPage.bringToFront();
previewPage = await getOpenedPreviewPage( editorPage, previewPage );
previewNav = previewPage.waitForNavigation();
editorPage.click( '.editor-post-preview' );
await previewNav;

// Title in preview should match updated input.
previewTitle = await previewPage.$eval( '.entry-title', ( node ) => node.textContent );
expect( previewTitle ).toBe( 'Hello World! And more.' );
await previewPage.close();
} );
} );

0 comments on commit 5ce6245

Please sign in to comment.