Skip to content
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

Testing: Trigger E2E test failure on console logging #8721

Merged
merged 3 commits into from
Aug 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions test/e2e/specs/change-detection.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ describe( 'Change detection', () => {
await page.setOfflineMode( false );

await assertIsDirty( true );

expect( console ).toHaveErroredWith( 'Failed to load resource: net::ERR_INTERNET_DISCONNECTED' );
} );

it( 'Should prompt if changes and save is in-flight', async () => {
Expand Down
125 changes: 106 additions & 19 deletions test/e2e/support/setup-test-framework.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
*/
import 'expect-puppeteer';

/**
* WordPress dependencies
*/
import '@wordpress/jest-console';

/**
* Internal dependencies
*/
import {
clearLocalStorage,
disablePageDialogAccept,
enablePageDialogAccept,
setViewport,
visitAdmin,
Expand All @@ -19,6 +23,26 @@ import {
*/
const { PUPPETEER_TIMEOUT } = process.env;

/**
* Set of console logging types observed to protect against unexpected yet
* handled (i.e. not catastrophic) errors or warnings. Each key corresponds
* to the Puppeteer ConsoleMessage type, its value the corresponding function
* on the console global object.
*
* @type {Object<string,string>}
*/
const OBSERVED_CONSOLE_MESSAGE_TYPES = {
warning: 'warn',
error: 'error',
};

/**
* Array of page event tuples of [ eventName, handler ].
*
* @type {Array}
*/
const pageEvents = [];

// The Jest timeout is increased because these tests are a bit slow
jest.setTimeout( PUPPETEER_TIMEOUT || 100000 );

Expand All @@ -27,29 +51,92 @@ async function setupBrowser() {
await setViewport( 'large' );
}

// Before every test suite run, delete all content created by the test. This ensures
// other posts/comments/etc. aren't dirtying tests and tests don't depend on
// each other's side-effects.
beforeAll( async () => {
enablePageDialogAccept();

/**
* Navigates to the post listing screen and bulk-trashes any posts which exist.
*
* @return {Promise} Promise resolving once posts have been trashed.
*/
async function trashExistingPosts() {
// Visit `/wp-admin/edit.php` so we can see a list of posts and delete them.
await visitAdmin( 'edit.php' );

// If this selector doesn't exist there are no posts for us to delete.
const bulkSelector = await page.$( '#bulk-action-selector-top' );
if ( bulkSelector ) {
// Select all posts.
await page.waitForSelector( '#cb-select-all-1' );
await page.click( '#cb-select-all-1' );
// Select the "bulk actions" > "trash" option.
await page.select( '#bulk-action-selector-top', 'trash' );
// Submit the form to send all draft/scheduled/published posts to the trash.
await page.click( '#doaction' );
await page.waitForXPath(
'//*[contains(@class, "updated notice")]/p[contains(text(), "moved to the Trash.")]'
);
if ( ! bulkSelector ) {
return;
}

// Select all posts.
await page.waitForSelector( '#cb-select-all-1' );
await page.click( '#cb-select-all-1' );
// Select the "bulk actions" > "trash" option.
await page.select( '#bulk-action-selector-top', 'trash' );
// Submit the form to send all draft/scheduled/published posts to the trash.
await page.click( '#doaction' );
return page.waitForXPath(
'//*[contains(@class, "updated notice")]/p[contains(text(), "moved to the Trash.")]'
);
}

/**
* Adds an event listener to the page to handle additions of page event
* handlers, to assure that they are removed at test teardown.
*/
function capturePageEventsForTearDown() {
page.on( 'newListener', ( eventName, listener ) => {
pageEvents.push( [ eventName, listener ] );
} );
}

/**
* Removes all bound page event handlers.
*/
function removePageEvents() {
pageEvents.forEach( ( [ eventName, handler ] ) => {
page.removeListener( eventName, handler );
} );
}

/**
* Adds a page event handler to emit uncaught exception to process if one of
* the observed console logging types is encountered.
*/
function observeConsoleLogging() {
page.on( 'console', ( message ) => {
const type = message.type();
if ( ! OBSERVED_CONSOLE_MESSAGE_TYPES.hasOwnProperty( type ) ) {
return;
}

const text = message.text();

// An exception is made for _blanket_ deprecation warnings: Those
// which log regardless of whether a deprecated feature is in use.
if ( text.includes( 'This is a global warning' ) ) {
return;
}

const logFunction = OBSERVED_CONSOLE_MESSAGE_TYPES[ type ];

// Disable reason: We intentionally bubble up the console message
// which, unless the test explicitly anticipates the logging via
// @wordpress/jest-console matchers, will cause the intended test
// failure.

// eslint-disable-next-line no-console
console[ logFunction ]( text );
} );
}

// Before every test suite run, delete all content created by the test. This ensures
// other posts/comments/etc. aren't dirtying tests and tests don't depend on
// each other's side-effects.
beforeAll( async () => {
capturePageEventsForTearDown();
enablePageDialogAccept();
observeConsoleLogging();

await trashExistingPosts();
await setupBrowser();
} );

Expand All @@ -58,5 +145,5 @@ afterEach( async () => {
} );

afterAll( () => {
disablePageDialogAccept();
removePageEvents();
} );
8 changes: 0 additions & 8 deletions test/e2e/support/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,11 +307,3 @@ async function acceptPageDialog( dialog ) {
export function enablePageDialogAccept() {
page.on( 'dialog', acceptPageDialog );
}

/**
* Disables even listener which accepts a page dialog which
* may appear when navigating away from Gutenberg.
*/
export function disablePageDialogAccept() {
page.removeListener( 'dialog', acceptPageDialog );
}