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

Site editor: add typing performance test #32553

Merged
merged 1 commit into from
Jun 10, 2021
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
5 changes: 3 additions & 2 deletions packages/e2e-tests/experimental-features.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,10 @@ export const navigationPanel = {
};

export const siteEditor = {
async visit() {
const query = addQueryArgs( '', {
async visit( query ) {
query = addQueryArgs( '', {
page: 'gutenberg-edit-site',
...query,
} ).slice( 1 );
await visitAdminPage( 'admin.php', query );
await page.waitForSelector( '.edit-site-visual-editor iframe' );
Expand Down
91 changes: 12 additions & 79 deletions packages/e2e-tests/specs/performance/post-editor.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* External dependencies
*/
import { basename, join } from 'path';
import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'fs';
import { writeFileSync } from 'fs';

/**
* WordPress dependencies
Expand All @@ -15,84 +15,17 @@ import {
closeGlobalBlockInserter,
} from '@wordpress/e2e-test-utils';

function readFile( filePath ) {
return existsSync( filePath )
? readFileSync( filePath, 'utf8' ).trim()
: '';
}

function deleteFile( filePath ) {
if ( existsSync( filePath ) ) {
unlinkSync( filePath );
}
}

function isKeyEvent( item ) {
return (
item.cat === 'devtools.timeline' &&
item.name === 'EventDispatch' &&
item.dur &&
item.args &&
item.args.data
);
}

function isKeyDownEvent( item ) {
return isKeyEvent( item ) && item.args.data.type === 'keydown';
}

function isKeyPressEvent( item ) {
return isKeyEvent( item ) && item.args.data.type === 'keypress';
}

function isKeyUpEvent( item ) {
return isKeyEvent( item ) && item.args.data.type === 'keyup';
}

function isFocusEvent( item ) {
return isKeyEvent( item ) && item.args.data.type === 'focus';
}

function isClickEvent( item ) {
return isKeyEvent( item ) && item.args.data.type === 'click';
}

function isMouseOverEvent( item ) {
return isKeyEvent( item ) && item.args.data.type === 'mouseover';
}

function isMouseOutEvent( item ) {
return isKeyEvent( item ) && item.args.data.type === 'mouseout';
}

function getEventDurationsForType( trace, filterFunction ) {
return trace.traceEvents
.filter( filterFunction )
.map( ( item ) => item.dur / 1000 );
}

function getTypingEventDurations( trace ) {
return [
getEventDurationsForType( trace, isKeyDownEvent ),
getEventDurationsForType( trace, isKeyPressEvent ),
getEventDurationsForType( trace, isKeyUpEvent ),
];
}

function getSelectionEventDurations( trace ) {
return [ getEventDurationsForType( trace, isFocusEvent ) ];
}

function getClickEventDurations( trace ) {
return [ getEventDurationsForType( trace, isClickEvent ) ];
}

function getHoverEventDurations( trace ) {
return [
getEventDurationsForType( trace, isMouseOverEvent ),
getEventDurationsForType( trace, isMouseOutEvent ),
];
}
/**
* Internal dependencies
*/
import {
readFile,
deleteFile,
getTypingEventDurations,
getClickEventDurations,
getHoverEventDurations,
getSelectionEventDurations,
} from './utils';

jest.setTimeout( 1000000 );

Expand Down
77 changes: 76 additions & 1 deletion packages/e2e-tests/specs/performance/site-editor.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ import {
trashAllPosts,
activateTheme,
canvas,
createNewPost,
saveDraft,
insertBlock,
} from '@wordpress/e2e-test-utils';

/**
* Internal dependencies
*/
import { siteEditor } from '../../experimental-features';
import { readFile, deleteFile, getTypingEventDurations } from './utils';

jest.setTimeout( 1000000 );

Expand All @@ -42,7 +46,32 @@ describe( 'Site Editor Performance', () => {
inserterHover: [],
};

await siteEditor.visit();
const html = readFile(
join( __dirname, '../../assets/large-post.html' )
);

await createNewPost( { postType: 'page' } );
await page.evaluate( ( _html ) => {
const { parse } = window.wp.blocks;
const { dispatch } = window.wp.data;
const blocks = parse( _html );

blocks.forEach( ( block ) => {
if ( block.name === 'core/image' ) {
delete block.attributes.id;
delete block.attributes.url;
}
} );

dispatch( 'core/block-editor' ).resetBlocks( blocks );
}, html );
await saveDraft();

const id = await page.evaluate( () =>
new URL( document.location ).searchParams.get( 'post' )
);

await siteEditor.visit( { postId: id, postType: 'page' } );

let i = 3;

Expand All @@ -58,13 +87,59 @@ describe( 'Site Editor Performance', () => {
results.load.push( new Date() - startTime );
}

// Measuring typing performance inside the post content.
await canvas().click(
'[data-type="core/post-content"] [data-type="core/paragraph"]'
);
await insertBlock( 'Paragraph' );
i = 200;
const traceFile = __dirname + '/trace.json';
await page.tracing.start( {
path: traceFile,
screenshots: false,
categories: [ 'devtools.timeline' ],
} );
while ( i-- ) {
await page.keyboard.type( 'x' );
}
await page.tracing.stop();
const traceResults = JSON.parse( readFile( traceFile ) );
const [
keyDownEvents,
keyPressEvents,
keyUpEvents,
] = getTypingEventDurations( traceResults );

// Both keydown and keypress events are bubbled from the iframe to the
// main frame, which must be ignored. These will be the odd values in
// the array.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be able to remove this soon when we remove the event bubbling from the iframe.

const _keyDownEvents = keyDownEvents.filter(
( v, ii ) => ii % 2 === 0
);
const _keyPressEvents = keyPressEvents.filter(
( v, ii ) => ii % 2 === 0
);

expect(
_keyDownEvents.length === _keyPressEvents.length &&
_keyPressEvents.length === keyUpEvents.length
).toBe( true );

for ( let j = 0; j < _keyDownEvents.length; j++ ) {
results.type.push(
_keyDownEvents[ j ] + _keyPressEvents[ j ] + keyUpEvents[ j ]
);
}

const resultsFilename = basename( __filename, '.js' ) + '.results.json';

writeFileSync(
join( __dirname, resultsFilename ),
JSON.stringify( results, null, 2 )
);

deleteFile( traceFile );

expect( true ).toBe( true );
} );
} );
83 changes: 83 additions & 0 deletions packages/e2e-tests/specs/performance/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/**
* External dependencies
*/
import { existsSync, readFileSync, unlinkSync } from 'fs';

export function readFile( filePath ) {
return existsSync( filePath )
? readFileSync( filePath, 'utf8' ).trim()
: '';
}

export function deleteFile( filePath ) {
if ( existsSync( filePath ) ) {
unlinkSync( filePath );
}
}

function isEvent( item ) {
return (
item.cat === 'devtools.timeline' &&
item.name === 'EventDispatch' &&
item.dur &&
item.args &&
item.args.data
);
}

function isKeyDownEvent( item ) {
return isEvent( item ) && item.args.data.type === 'keydown';
}

function isKeyPressEvent( item ) {
return isEvent( item ) && item.args.data.type === 'keypress';
}

function isKeyUpEvent( item ) {
return isEvent( item ) && item.args.data.type === 'keyup';
}

function isFocusEvent( item ) {
return isEvent( item ) && item.args.data.type === 'focus';
}

function isClickEvent( item ) {
return isEvent( item ) && item.args.data.type === 'click';
}

function isMouseOverEvent( item ) {
return isEvent( item ) && item.args.data.type === 'mouseover';
}

function isMouseOutEvent( item ) {
return isEvent( item ) && item.args.data.type === 'mouseout';
}

function getEventDurationsForType( trace, filterFunction ) {
return trace.traceEvents
.filter( filterFunction )
.map( ( item ) => item.dur / 1000 );
}

export function getTypingEventDurations( trace ) {
return [
getEventDurationsForType( trace, isKeyDownEvent ),
getEventDurationsForType( trace, isKeyPressEvent ),
getEventDurationsForType( trace, isKeyUpEvent ),
];
}

export function getSelectionEventDurations( trace ) {
return [ getEventDurationsForType( trace, isFocusEvent ) ];
}

export function getClickEventDurations( trace ) {
return [ getEventDurationsForType( trace, isClickEvent ) ];
}

export function getHoverEventDurations( trace ) {
return [
getEventDurationsForType( trace, isMouseOverEvent ),
getEventDurationsForType( trace, isMouseOutEvent ),
];
}