Separate out client code from screenshots runners

Change-Id: I92a588492169dafaf070477bef9fe22fa1fea5d3
This commit is contained in:
Ed Sanders 2020-04-17 22:55:45 +01:00
parent 651756c4fc
commit 3b9ba67889
8 changed files with 598 additions and 609 deletions

View file

@ -1,9 +1,11 @@
{ {
"root": true, "root": true,
"extends": [ "extends": [
"../.eslintrc.json",
"wikimedia/server" "wikimedia/server"
], ],
"globals": {
"langs": "readonly"
},
"rules": { "rules": {
"max-len": "off", "max-len": "off",
"mediawiki/valid-package-file-require": "off" "mediawiki/valid-package-file-require": "off"

View file

@ -0,0 +1,9 @@
{
"root": true,
"extends": [
"../../.eslintrc.json"
],
"globals": {
"seleniumUtils": "readonly"
}
}

View file

@ -0,0 +1,46 @@
module.exports = {
simple: function () {
var done = arguments[ arguments.length - 1 ];
seleniumUtils.runDiffTest(
'<h2>Lorem ipsum</h2>' +
'<p>Lorem ipsum dolor sit <b>amet</b>, consectetur adipiscing elit.</p>',
'<h2>Lorem ipsum</h2>' +
'<p>Lorem ipsum dolor sit <i>amet</i>, consectetur adipiscing elit.</p>',
done
);
},
moveAndChange: function () {
var done = arguments[ arguments.length - 1 ];
seleniumUtils.runDiffTest(
'<h2>Lorem ipsum</h2>' +
'<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>' +
'<p>Maecenas fringilla turpis et nunc bibendum mattis.</p>',
'<h2>Lorem ipsum</h2>' +
'<p>Maecenas fringilla turpis et nunc bibendum mattis.</p>' +
'<p>Lorem ipsum dolor sit amat, consectetur adipiscing elit.</p>',
done
);
},
linkChange: function () {
var done = arguments[ arguments.length - 1 ];
seleniumUtils.runDiffTest(
'<h2>Lorem ipsum</h2>' +
'<p><a rel="mw:WikiLink" href="./Lipsum">Lorem ipsum</a> dolor sit amet, consectetur adipiscing elit.</p>',
'<h2>Lorem ipsum</h2>' +
'<p><a rel="mw:WikiLink" href="./Lorem ipsum">Lorem ipsum</a> dolor sit amet, consectetur adipiscing elit.</p>',
done
);
},
listChange: function () {
var done = arguments[ arguments.length - 1 ];
seleniumUtils.runDiffTest(
'<ul><li>Lorem</li><li>ipsum</li><li>dolor</li><li>sit</li><li>amet</li></ul>',
'<ul><li>Lorem</li><li>ipsum</li><li>sit</li><li>amat</li></ul>',
done
);
}
};

View file

@ -0,0 +1,205 @@
/* eslint-disable no-jquery/no-global-selector */
module.exports = {
toolbar: function () {
var done = arguments[ arguments.length - 1 ];
// HACK: The test page is on the help namespace, so overwrite the
// read tab with the nstab-main message.
new mw.Api().loadMessagesIfMissing( [ 'nstab-main' ], { amenableparser: true } ).then( function () {
$( '#ca-nstab-help a' ).text( mw.msg( 'nstab-main' ) );
done(
seleniumUtils.getBoundingRect( [
ve.init.target.toolbar.$element[ 0 ],
$( '#p-namespaces' )[ 0 ]
] )
);
} );
},
toolbarActions: function () {
var done = arguments[ arguments.length - 1 ];
done(
seleniumUtils.getBoundingRect( [
ve.init.target.toolbar.$actions[ 0 ]
] )
);
},
citoidInspector: function () {
var done = arguments[ arguments.length - 1 ],
surface = ve.init.target.surface;
ve.init.target.toolbar.tools.citoid.onSelect();
setTimeout( function () {
done(
seleniumUtils.getBoundingRect( [
surface.$element.find( '.ve-ce-mwReferenceNode' )[ 0 ],
surface.context.inspectors.currentWindow.$element[ 0 ]
] )
);
}, 500 );
},
citoidInspectorManual: function () {
var done = arguments[ arguments.length - 1 ],
surface = ve.init.target.surface;
ve.init.target.surface.context.inspectors.currentWindow.setModePanel( 'manual' );
setTimeout( function () {
done(
seleniumUtils.getBoundingRect( [
surface.$element.find( '.ve-ce-mwReferenceNode' )[ 0 ],
surface.context.inspectors.currentWindow.$element[ 0 ]
] )
);
} );
},
citoidInspectorReuse: function () {
var done = arguments[ arguments.length - 1 ],
surface = ve.init.target.surface;
ve.init.target.surface.context.inspectors.currentWindow.setModePanel( 'reuse' );
setTimeout( function () {
done(
seleniumUtils.getBoundingRect( [
surface.$element.find( '.ve-ce-mwReferenceNode' )[ 0 ],
surface.context.inspectors.currentWindow.$element[ 0 ]
] )
);
} );
},
toolbarHeadings: function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.toolbar.tools.paragraph );
},
toolbarFormatting: function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.toolbar.tools.bold, true );
},
toolbarLists: function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.toolbar.tools.bullet );
},
toolbarInsert: function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.toolbar.tools.media, true );
},
toolbarMedia: function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.toolbar.tools.media, false, true );
},
toolbarTemplate: function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.toolbar.tools.transclusion, false, true );
},
toolbarTable: function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.toolbar.tools.insertTable, false, true );
},
toolbarFormula: function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.toolbar.tools.math, true, true );
},
toolbarReferences: function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.toolbar.tools.referencesList, true, true );
},
toolbarSettings: function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.actionsToolbar.tools.advancedSettings, false, false,
[ ve.init.target.toolbarSaveButton.$element[ 0 ] ]
);
},
toolbarPageSettings: function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.actionsToolbar.tools.settings, false, true );
},
toolbarCategory: function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.actionsToolbar.tools.categories, false, true );
},
save: function () {
var done = arguments[ arguments.length - 1 ];
ve.init.target.toolbarSaveButton.onSelect();
setTimeout( function () {
done(
seleniumUtils.getBoundingRect( [
ve.init.target.surface.dialogs.currentWindow.$frame[ 0 ]
] )
);
}, 500 );
},
specialCharacters: function () {
var done = arguments[ arguments.length - 1 ];
ve.init.target.toolbar.tools.specialCharacter.onSelect();
setTimeout( function () {
done(
seleniumUtils.getBoundingRect( [
ve.init.target.toolbar.tools.specialCharacter.$element[ 0 ],
ve.init.target.surface.toolbarDialogs.$element[ 0 ]
] )
);
}, 1000 );
},
formula: function () {
var done = arguments[ arguments.length - 1 ],
surface = ve.init.target.surface;
surface.dialogs.once( 'opening', function ( win, opening ) {
opening.then( function () {
win.previewElement.once( 'render', function () {
win.previewElement.$element.find( 'img' ).on( 'load', function () {
done(
seleniumUtils.getBoundingRect( [
win.$frame[ 0 ]
] )
);
} );
} );
win.input.setValue( 'E = mc^2' ).moveCursorToEnd();
} );
} );
surface.executeCommand( 'mathDialog' );
},
referenceList: function () {
var done = arguments[ arguments.length - 1 ],
surface = ve.init.target.surface;
surface.dialogs.once( 'opening', function ( win, opening ) {
opening.then( function () {
setTimeout( function () {
done(
seleniumUtils.getBoundingRect( [
win.$frame[ 0 ]
] )
);
}, 500 );
} );
} );
surface.executeCommand( 'referencesList' );
// The first command inserts a reference list instantly, so run again to open the window
surface.executeCommand( 'referencesList' );
},
toolbarCite: function () {
var done = arguments[ arguments.length - 1 ];
ve.init.target.$element.css( 'font-size', '250%' );
// Wait for re-paint
setTimeout( function () {
done(
seleniumUtils.getBoundingRect( [
ve.init.target.toolbar.tools.citoid.$element[ 0 ]
] )
);
}, 100 );
},
linkSearchResults: function () {
var done = arguments[ arguments.length - 1 ],
surface = ve.init.target.surface;
surface.getModel().getFragment()
// TODO: i18n this message, the linked word, and the API endpoint of the link inspector
.insertContent( 'World literature is literature that is read by many people all over' )
.collapseToStart().select();
surface.context.inspectors.once( 'opening', function ( win, opening ) {
opening.then( function () {
surface.context.inspectors.windows.link.annotationInput.input.requestRequest.then( function () {
// Wait a while for the images to load using a time guesstimate - as they're background
// images it's quite tricky to get load events.
setTimeout( function () {
done(
seleniumUtils.getBoundingRect( [
surface.$element.find( '.ve-ce-linkAnnotation' )[ 0 ],
surface.context.inspectors.currentWindow.$element[ 0 ]
] )
);
}, 2500 );
} );
} );
} );
ve.init.target.surface.executeCommand( 'link' );
}
};

View file

@ -0,0 +1,122 @@
module.exports = function () {
var done = arguments[ arguments.length - 1 ];
window.seleniumUtils = {
getBoundingRect: function ( elements ) {
var i, l, rect, boundingRect;
for ( i = 0, l = elements.length; i < l; i++ ) {
rect = elements[ i ].getBoundingClientRect();
if ( !boundingRect ) {
boundingRect = {
left: rect.left,
top: rect.top,
right: rect.right,
bottom: rect.bottom
};
} else {
boundingRect.left = Math.min( boundingRect.left, rect.left );
boundingRect.top = Math.min( boundingRect.top, rect.top );
boundingRect.right = Math.max( boundingRect.right, rect.right );
boundingRect.bottom = Math.max( boundingRect.bottom, rect.bottom );
}
}
if ( boundingRect ) {
boundingRect.width = boundingRect.right - boundingRect.left;
boundingRect.height = boundingRect.bottom - boundingRect.top;
}
return boundingRect;
},
collapseToolbar: function () {
ve.init.target.toolbar.items.forEach( function ( group ) {
if ( group.setActive ) {
group.setActive( false );
}
} );
ve.init.target.actionsToolbar.items.forEach( function ( group ) {
if ( group.setActive ) {
group.setActive( false );
}
} );
},
runMenuTask: function ( done, tool, expanded, highlight, extraElements ) {
var toolGroup = tool.toolGroup;
seleniumUtils.collapseToolbar();
toolGroup.setActive( true );
if ( toolGroup.updateCollapsibleState ) {
toolGroup.expanded = !!expanded;
toolGroup.updateCollapsibleState();
}
if ( highlight ) {
tool.$link[ 0 ].focus();
}
setTimeout( function () {
done(
seleniumUtils.getBoundingRect( [
toolGroup.$element[ 0 ],
toolGroup.$group[ 0 ]
].concat( extraElements || [] ) )
);
} );
},
runDiffTest: function ( oldHtml, newHtml, done ) {
var target = ve.init.target,
surface = target.surface;
if ( target.saveDialog ) {
target.saveDialog.clearDiff();
target.saveDialog.close();
while ( surface.getModel().canUndo() ) {
surface.getModel().undo();
}
}
target.originalDmDoc = target.constructor.static.createModelFromDom( target.constructor.static.parseDocument( oldHtml ), 'visual' );
surface.getModel().getDocument().getStore().merge( target.originalDmDoc.getStore() );
surface.getModel().getLinearFragment( new ve.Range( 0 ) ).insertDocument(
target.constructor.static.createModelFromDom( target.constructor.static.parseDocument( newHtml ), 'visual' )
).collapseToEnd().adjustLinearSelection( 0, 3 ).removeContent();
target.once( 'saveReview', function () {
setTimeout( function () {
var dialog = surface.dialogs.currentWindow;
dialog.reviewModeButtonSelect.selectItemByData( 'visual' );
// Fake parsed edit summary
dialog.$previewEditSummary.text( '(Lorem ipsum)' );
done(
seleniumUtils.getBoundingRect( [
dialog.$frame[ 0 ]
] )
);
}, 500 );
} );
surface.execute( 'mwSaveDialog', 'review' );
}
};
// Suppress welcome dialog
mw.storage.set( 've-beta-welcome-dialog', 1 );
// Suppress user education indicators
mw.storage.set( 've-hideusered', 1 );
mw.hook( 've.activationComplete' ).add( function () {
var target = ve.init.target,
surfaceView = target.getSurface().getView();
// Modify the document to make the save button blue
// Wait for focus
surfaceView.once( 'focus', function () {
target.surface.getModel().getFragment().insertContent( ' ' ).collapseToStart().select();
// Hide edit notices
target.actionsToolbar.tools.notices.getPopup().toggle( false );
// Wait for save button fade
setTimeout( function () {
done( { width: window.innerWidth, height: window.innerHeight } );
}, 100 );
} );
} );
};

View file

@ -1,121 +1,28 @@
/* global seleniumUtils, langs */ const createScreenshotEnvironment = require( './screenshots.js' ).createScreenshotEnvironment,
test = require( 'selenium-webdriver/testing' ),
runScreenshotTest = createScreenshotEnvironment( test );
( function () { function runTests( lang ) {
'use strict';
var runScreenshotTest,
createScreenshotEnvironment = require( './screenshots.js' ).createScreenshotEnvironment,
test = require( 'selenium-webdriver/testing' );
runScreenshotTest = createScreenshotEnvironment( test, function () { test.describe( 'Screenshots: ' + lang, function () {
var done = arguments[ arguments.length - 1 ]; this.lang = lang;
test.it( 'Simple diff', function () {
window.seleniumUtils.runDiffTest = function ( oldHtml, newHtml, done ) { runScreenshotTest( 'VisualEditor_diff_simple', lang,
var target = ve.init.target, require( './screenshots-client/diffs.js' ).simple
surface = target.surface; );
runScreenshotTest( 'VisualEditor_diff_move_and_change', lang,
if ( target.saveDialog ) { require( './screenshots-client/diffs.js' ).moveAndChange
target.saveDialog.clearDiff(); );
target.saveDialog.close(); runScreenshotTest( 'VisualEditor_diff_link_change', lang,
while ( surface.getModel().canUndo() ) { require( './screenshots-client/diffs.js' ).linkChange
surface.getModel().undo(); );
} runScreenshotTest( 'VisualEditor_diff_list_change', lang,
} require( './screenshots-client/diffs.js' ).listChange
);
target.originalDmDoc = target.constructor.static.createModelFromDom( target.constructor.static.parseDocument( oldHtml ), 'visual' );
surface.getModel().getDocument().getStore().merge( target.originalDmDoc.getStore() );
surface.getModel().getLinearFragment( new ve.Range( 0 ) ).insertDocument(
target.constructor.static.createModelFromDom( target.constructor.static.parseDocument( newHtml ), 'visual' )
).collapseToEnd().adjustLinearSelection( 0, 3 ).removeContent();
target.once( 'saveReview', function () {
setTimeout( function () {
var dialog = surface.dialogs.currentWindow;
dialog.reviewModeButtonSelect.selectItemByData( 'visual' );
// Fake parsed edit summary
dialog.$reviewEditSummary.text( '(Lorem ipsum)' );
done(
seleniumUtils.getBoundingRect( [
dialog.$frame[ 0 ]
] )
);
}, 500 );
} );
surface.execute( 'mwSaveDialog', 'review' );
};
done();
} );
function runTests( lang ) {
test.describe( 'Screenshots: ' + lang, function () {
this.lang = lang;
test.it( 'Simple diff', function () {
runScreenshotTest( 'VisualEditor_diff_simple', lang,
// This function is converted to a string and executed in the browser
function () {
var done = arguments[ arguments.length - 1 ];
seleniumUtils.runDiffTest(
'<h2>Lorem ipsum</h2>' +
'<p>Lorem ipsum dolor sit <b>amet</b>, consectetur adipiscing elit.</p>',
'<h2>Lorem ipsum</h2>' +
'<p>Lorem ipsum dolor sit <i>amet</i>, consectetur adipiscing elit.</p>',
done
);
}
);
runScreenshotTest( 'VisualEditor_diff_move_and_change', lang,
// This function is converted to a string and executed in the browser
function () {
var done = arguments[ arguments.length - 1 ];
seleniumUtils.runDiffTest(
'<h2>Lorem ipsum</h2>' +
'<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>' +
'<p>Maecenas fringilla turpis et nunc bibendum mattis.</p>',
'<h2>Lorem ipsum</h2>' +
'<p>Maecenas fringilla turpis et nunc bibendum mattis.</p>' +
'<p>Lorem ipsum dolor sit amat, consectetur adipiscing elit.</p>',
done
);
}
);
runScreenshotTest( 'VisualEditor_diff_link_change', lang,
// This function is converted to a string and executed in the browser
function () {
var done = arguments[ arguments.length - 1 ];
seleniumUtils.runDiffTest(
'<h2>Lorem ipsum</h2>' +
'<p><a rel="mw:WikiLink" href="./Lipsum">Lorem ipsum</a> dolor sit amet, consectetur adipiscing elit.</p>',
'<h2>Lorem ipsum</h2>' +
'<p><a rel="mw:WikiLink" href="./Lorem ipsum">Lorem ipsum</a> dolor sit amet, consectetur adipiscing elit.</p>',
done
);
}
);
runScreenshotTest( 'VisualEditor_diff_list_change', lang,
// This function is converted to a string and executed in the browser
function () {
var done = arguments[ arguments.length - 1 ];
seleniumUtils.runDiffTest(
'<ul><li>Lorem</li><li>ipsum</li><li>dolor</li><li>sit</li><li>amet</li></ul>',
'<ul><li>Lorem</li><li>ipsum</li><li>sit</li><li>amat</li></ul>',
done
);
}
);
} );
} ); } );
} } );
}
for ( let i = 0, l = langs.length; i < l; i++ ) { for ( let i = 0, l = langs.length; i < l; i++ ) {
runTests( langs[ i ] ); runTests( langs[ i ] );
} }
}() );

View file

@ -1,197 +1,102 @@
/* global seleniumUtils */ const accessKey = process.env.SAUCE_ONDEMAND_ACCESS_KEY,
Builder = require( 'selenium-webdriver' ).Builder,
fs = require( 'fs' ),
Jimp = require( 'jimp' ),
username = process.env.SAUCE_ONDEMAND_USERNAME,
webdriver = require( 'selenium-webdriver' ),
TIMEOUT = 40 * 1000;
/* eslint-disable no-console */ function createScreenshotEnvironment( test, beforeEach ) {
let clientSize, driver;
( function () { test.beforeEach( function () {
'use strict'; const lang = this.currentTest.parent.lang || 'en';
var accessKey = process.env.SAUCE_ONDEMAND_ACCESS_KEY,
Builder = require( 'selenium-webdriver' ).Builder,
fs = require( 'fs' ),
Jimp = require( 'jimp' ),
username = process.env.SAUCE_ONDEMAND_USERNAME,
webdriver = require( 'selenium-webdriver' ),
TIMEOUT = 40 * 1000;
function createScreenshotEnvironment( test, beforeEach ) { // Use Sauce Labs when running on Jenins
var clientSize, driver; if ( process.env.JENKINS_URL ) {
driver = new webdriver.Builder().withCapabilities( {
browserName: process.env.BROWSER,
platform: process.env.PLATFORM,
username: username,
accessKey: accessKey
} ).usingServer( 'http://' + username + ':' + accessKey +
'@ondemand.saucelabs.com:80/wd/hub' ).build();
} else {
// If not running on Jenkins, use local browser
driver = new Builder().forBrowser( 'chrome' ).build();
}
test.beforeEach( function () { driver.manage().timeouts().setScriptTimeout( TIMEOUT );
var lang = this.currentTest.parent.lang || 'en'; driver.manage().window().setSize( 1200, 1000 );
// Use Sauce Labs when running on Jenins
if ( process.env.JENKINS_URL ) {
driver = new webdriver.Builder().withCapabilities( {
browserName: process.env.BROWSER,
platform: process.env.PLATFORM,
username: username,
accessKey: accessKey
} ).usingServer( 'http://' + username + ':' + accessKey +
'@ondemand.saucelabs.com:80/wd/hub' ).build();
} else {
// If not running on Jenkins, use local browser
driver = new Builder().forBrowser( 'chrome' ).build();
}
driver.get( 'https://en.wikipedia.org/wiki/Help:Sample_page?veaction=edit&uselang=' + lang );
driver.wait(
driver.executeAsyncScript(
require( './screenshots-client/utils.js' )
).then( function ( cs ) {
clientSize = cs;
}, function ( e ) {
// Log error (timeout)
console.error( e.message );
} )
);
if ( beforeEach ) {
driver.manage().timeouts().setScriptTimeout( TIMEOUT ); driver.manage().timeouts().setScriptTimeout( TIMEOUT );
driver.manage().window().setSize( 1200, 1000 );
driver.get( 'https://en.wikipedia.org/wiki/Help:Sample_page?veaction=edit&uselang=' + lang );
driver.wait( driver.wait(
driver.executeAsyncScript( driver.executeAsyncScript( beforeEach ).then(
// This function is converted to a string and executed in the browser function () {},
function () { function ( e ) {
var done = arguments[ arguments.length - 1 ]; // Log error (timeout)
console.error( e.message );
window.seleniumUtils = {
getBoundingRect: function ( elements ) {
var i, l, rect, boundingRect;
for ( i = 0, l = elements.length; i < l; i++ ) {
rect = elements[ i ].getBoundingClientRect();
if ( !boundingRect ) {
boundingRect = {
left: rect.left,
top: rect.top,
right: rect.right,
bottom: rect.bottom
};
} else {
boundingRect.left = Math.min( boundingRect.left, rect.left );
boundingRect.top = Math.min( boundingRect.top, rect.top );
boundingRect.right = Math.max( boundingRect.right, rect.right );
boundingRect.bottom = Math.max( boundingRect.bottom, rect.bottom );
}
}
if ( boundingRect ) {
boundingRect.width = boundingRect.right - boundingRect.left;
boundingRect.height = boundingRect.bottom - boundingRect.top;
}
return boundingRect;
},
collapseToolbar: function () {
ve.init.target.toolbar.items.forEach( function ( group ) {
if ( group.setActive ) {
group.setActive( false );
}
} );
ve.init.target.actionsToolbar.items.forEach( function ( group ) {
if ( group.setActive ) {
group.setActive( false );
}
} );
},
runMenuTask: function ( done, tool, expanded, highlight, extraElements ) {
var toolGroup = tool.toolGroup;
seleniumUtils.collapseToolbar();
toolGroup.setActive( true );
if ( toolGroup.updateCollapsibleState ) {
toolGroup.expanded = !!expanded;
toolGroup.updateCollapsibleState();
}
if ( highlight ) {
tool.$link[ 0 ].focus();
}
setTimeout( function () {
done(
seleniumUtils.getBoundingRect( [
toolGroup.$element[ 0 ],
toolGroup.$group[ 0 ]
].concat( extraElements || [] ) )
);
} );
}
};
// Suppress welcome dialog
mw.storage.set( 've-beta-welcome-dialog', 1 );
// Suppress user education indicators
mw.storage.set( 've-hideusered', 1 );
mw.hook( 've.activationComplete' ).add( function () {
var target = ve.init.target,
surfaceView = target.getSurface().getView();
// Modify the document to make the save button blue
// Wait for focus
surfaceView.once( 'focus', function () {
target.surface.getModel().getFragment().insertContent( ' ' ).collapseToStart().select();
// Hide edit notices
target.actionsToolbar.tools.notices.getPopup().toggle( false );
// Wait for save button fade
setTimeout( function () {
done( { width: window.innerWidth, height: window.innerHeight } );
}, 100 );
} );
} );
} }
).then( function ( cs ) { )
clientSize = cs;
}, function ( e ) {
// Log error (timeout)
console.error( e.message );
} )
);
if ( beforeEach ) {
driver.manage().timeouts().setScriptTimeout( TIMEOUT );
driver.wait(
driver.executeAsyncScript( beforeEach ).then(
function () {},
function ( e ) {
// Log error (timeout)
console.error( e.message );
}
)
);
}
} );
test.afterEach( function () {
driver.quit();
} );
function cropScreenshot( filename, imageBuffer, rect, padding ) {
var left, top, right, bottom;
if ( padding === undefined ) {
padding = 5;
}
left = Math.max( 0, rect.left - padding );
top = Math.max( 0, rect.top - padding );
right = Math.min( clientSize.width, rect.left + rect.width + padding );
bottom = Math.min( clientSize.height, rect.top + rect.height + padding );
return Jimp.read( imageBuffer ).then( function ( jimpImage ) {
jimpImage
.crop( left, top, right - left, bottom - top )
.write( filename );
} );
}
function runScreenshotTest( name, lang, clientScript, padding ) {
var filename = './screenshots/' + name + '-' + lang + '.png';
driver.manage().timeouts().setScriptTimeout( TIMEOUT );
driver.wait(
driver.executeAsyncScript( clientScript ).then( function ( rect ) {
return driver.takeScreenshot().then( function ( base64Image ) {
var imageBuffer;
if ( rect ) {
imageBuffer = Buffer.from( base64Image, 'base64' );
return cropScreenshot( filename, imageBuffer, rect, padding );
} else {
fs.writeFile( filename, base64Image, 'base64' );
}
} );
}, function ( e ) {
// Log error (timeout)
console.error( e );
} )
); );
} }
} );
return runScreenshotTest; test.afterEach( function () {
driver.quit();
} );
function cropScreenshot( filename, imageBuffer, rect, padding ) {
if ( padding === undefined ) {
padding = 5;
}
const left = Math.max( 0, rect.left - padding );
const top = Math.max( 0, rect.top - padding );
const right = Math.min( clientSize.width, rect.left + rect.width + padding );
const bottom = Math.min( clientSize.height, rect.top + rect.height + padding );
return Jimp.read( imageBuffer ).then( function ( jimpImage ) {
jimpImage
.crop( left, top, right - left, bottom - top )
.write( filename );
} );
} }
module.exports.createScreenshotEnvironment = createScreenshotEnvironment; function runScreenshotTest( name, lang, clientScript, padding ) {
}() ); const filename = './screenshots/' + name + '-' + lang + '.png';
driver.manage().timeouts().setScriptTimeout( TIMEOUT );
driver.wait(
driver.executeAsyncScript( clientScript ).then( function ( rect ) {
return driver.takeScreenshot().then( function ( base64Image ) {
if ( rect ) {
const imageBuffer = Buffer.from( base64Image, 'base64' );
return cropScreenshot( filename, imageBuffer, rect, padding );
} else {
fs.writeFile( filename, base64Image, 'base64' );
}
} );
}, function ( e ) {
// Log error (timeout)
console.error( e );
} )
);
}
return runScreenshotTest;
}
module.exports.createScreenshotEnvironment = createScreenshotEnvironment;

View file

@ -1,311 +1,104 @@
/* global seleniumUtils, langs */ const createScreenshotEnvironment = require( './screenshots.js' ).createScreenshotEnvironment,
/* eslint-disable no-jquery/no-global-selector */ test = require( 'selenium-webdriver/testing' ),
runScreenshotTest = createScreenshotEnvironment( test );
( function () { function runTests( lang ) {
'use strict';
var createScreenshotEnvironment = require( './screenshots.js' ).createScreenshotEnvironment,
test = require( 'selenium-webdriver/testing' ),
runScreenshotTest = createScreenshotEnvironment( test );
function runTests( lang ) { test.describe( 'Screenshots: ' + lang, function () {
this.lang = lang;
test.describe( 'Screenshots: ' + lang, function () { test.it( 'Toolbar & action tools', function () {
this.lang = lang; runScreenshotTest( 'VisualEditor_toolbar', lang,
test.it( 'Toolbar & action tools', function () { require( './screenshots-client/userGuide.js' ).toolbar,
runScreenshotTest( 'VisualEditor_toolbar', lang, 0
// This function is converted to a string and executed in the browser );
function () { runScreenshotTest( 'VisualEditor_toolbar_actions', lang,
var done = arguments[ arguments.length - 1 ]; require( './screenshots-client/userGuide.js' ).toolbarActions,
// HACK: The test page is on the help namespace, so overwrite the 0
// read tab with the nstab-main message. );
new mw.Api().loadMessagesIfMissing( [ 'nstab-main' ], { amenableparser: true } ).then( function () {
$( '#ca-nstab-help a' ).text( mw.msg( 'nstab-main' ) );
done(
seleniumUtils.getBoundingRect( [
ve.init.target.toolbar.$element[ 0 ],
$( '#p-namespaces' )[ 0 ]
] )
);
} );
},
0
);
runScreenshotTest( 'VisualEditor_toolbar_actions', lang,
// This function is converted to a string and executed in the browser
function () {
var done = arguments[ arguments.length - 1 ];
done(
seleniumUtils.getBoundingRect( [
ve.init.target.toolbar.$actions[ 0 ]
] )
);
},
0
);
} );
test.it( 'Citoid inspector', function () {
runScreenshotTest( 'VisualEditor_Citoid_Inspector', lang,
// This function is converted to a string and executed in the browser
function () {
var done = arguments[ arguments.length - 1 ],
surface = ve.init.target.surface;
ve.init.target.toolbar.tools.citoid.onSelect();
setTimeout( function () {
done(
seleniumUtils.getBoundingRect( [
surface.$element.find( '.ve-ce-mwReferenceNode' )[ 0 ],
surface.context.inspectors.currentWindow.$element[ 0 ]
] )
);
}, 500 );
}
);
runScreenshotTest( 'VisualEditor_Citoid_Inspector_Manual', lang,
// This function is converted to a string and executed in the browser
function () {
var done = arguments[ arguments.length - 1 ],
surface = ve.init.target.surface;
ve.init.target.surface.context.inspectors.currentWindow.setModePanel( 'manual' );
setTimeout( function () {
done(
seleniumUtils.getBoundingRect( [
surface.$element.find( '.ve-ce-mwReferenceNode' )[ 0 ],
surface.context.inspectors.currentWindow.$element[ 0 ]
] )
);
} );
}
);
runScreenshotTest( 'VisualEditor_Citoid_Inspector_Reuse', lang,
// This function is converted to a string and executed in the browser
function () {
var done = arguments[ arguments.length - 1 ],
surface = ve.init.target.surface;
ve.init.target.surface.context.inspectors.currentWindow.setModePanel( 'reuse' );
setTimeout( function () {
done(
seleniumUtils.getBoundingRect( [
surface.$element.find( '.ve-ce-mwReferenceNode' )[ 0 ],
surface.context.inspectors.currentWindow.$element[ 0 ]
] )
);
} );
}
);
} );
test.it( 'Tool groups (headings/text style/indentation/insert/page settings)', function () {
runScreenshotTest( 'VisualEditor_Toolbar_Headings', lang,
// This function is converted to a string and executed in the browser
function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.toolbar.tools.paragraph );
}
);
runScreenshotTest( 'VisualEditor_Toolbar_Formatting', lang,
// This function is converted to a string and executed in the browser
function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.toolbar.tools.bold, true );
}
);
runScreenshotTest( 'VisualEditor_Toolbar_Lists_and_indentation', lang,
// This function is converted to a string and executed in the browser
function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.toolbar.tools.bullet );
}
);
runScreenshotTest( 'VisualEditor_Insert_Menu', lang,
// This function is converted to a string and executed in the browser
function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.toolbar.tools.media, true );
}
);
runScreenshotTest( 'VisualEditor_Media_Insert_Menu', lang,
// This function is converted to a string and executed in the browser
function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.toolbar.tools.media, false, true );
}
);
runScreenshotTest( 'VisualEditor_Template_Insert_Menu', lang,
// This function is converted to a string and executed in the browser
function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.toolbar.tools.transclusion, false, true );
}
);
runScreenshotTest( 'VisualEditor_insert_table', lang,
// This function is converted to a string and executed in the browser
function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.toolbar.tools.insertTable, false, true );
}
);
runScreenshotTest( 'VisualEditor_Formula_Insert_Menu', lang,
// This function is converted to a string and executed in the browser
function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.toolbar.tools.math, true, true );
}
);
runScreenshotTest( 'VisualEditor_References_List_Insert_Menu', lang,
// This function is converted to a string and executed in the browser
function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.toolbar.tools.referencesList, true, true );
}
);
runScreenshotTest( 'VisualEditor_More_Settings', lang,
// This function is converted to a string and executed in the browser
function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.actionsToolbar.tools.advancedSettings, false, false,
[ ve.init.target.toolbarSaveButton.$element[ 0 ] ]
);
}
);
runScreenshotTest( 'VisualEditor_page_settings_item', lang,
// This function is converted to a string and executed in the browser
function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.actionsToolbar.tools.settings, false, true );
}
);
runScreenshotTest( 'VisualEditor_category_item', lang,
// This function is converted to a string and executed in the browser
function () {
seleniumUtils.runMenuTask( arguments[ arguments.length - 1 ], ve.init.target.actionsToolbar.tools.categories, false, true );
}
);
} );
test.it( 'Save dialog', function () {
runScreenshotTest( 'VisualEditor_save_dialog', lang,
// This function is converted to a string and executed in the browser
function () {
var done = arguments[ arguments.length - 1 ];
ve.init.target.toolbarSaveButton.onSelect();
setTimeout( function () {
done(
seleniumUtils.getBoundingRect( [
ve.init.target.surface.dialogs.currentWindow.$frame[ 0 ]
] )
);
}, 500 );
}
);
} );
test.it( 'Special character inserter', function () {
runScreenshotTest( 'VisualEditor_Toolbar_SpecialCharacters', lang,
// This function is converted to a string and executed in the browser
function () {
var done = arguments[ arguments.length - 1 ];
ve.init.target.toolbar.tools.specialCharacter.onSelect();
setTimeout( function () {
done(
seleniumUtils.getBoundingRect( [
ve.init.target.toolbar.tools.specialCharacter.$element[ 0 ],
ve.init.target.surface.toolbarDialogs.$element[ 0 ]
] )
);
}, 1000 );
}
);
} );
test.it( 'Math dialog', function () {
runScreenshotTest( 'VisualEditor_formula', lang,
// This function is converted to a string and executed in the browser
function () {
var done = arguments[ arguments.length - 1 ],
surface = ve.init.target.surface;
surface.dialogs.once( 'opening', function ( win, opening ) {
opening.then( function () {
win.previewElement.once( 'render', function () {
win.previewElement.$element.find( 'img' ).on( 'load', function () {
done(
seleniumUtils.getBoundingRect( [
win.$frame[ 0 ]
] )
);
} );
} );
win.input.setValue( 'E = mc^2' ).moveCursorToEnd();
} );
} );
surface.executeCommand( 'mathDialog' );
}
);
} );
test.it( 'Reference list dialog', function () {
runScreenshotTest( 'VisualEditor_references_list', lang,
// This function is converted to a string and executed in the browser
function () {
var done = arguments[ arguments.length - 1 ],
surface = ve.init.target.surface;
surface.dialogs.once( 'opening', function ( win, opening ) {
opening.then( function () {
setTimeout( function () {
done(
seleniumUtils.getBoundingRect( [
win.$frame[ 0 ]
] )
);
}, 500 );
} );
} );
surface.executeCommand( 'referencesList' );
// The first command inserts a reference list instantly, so run again to open the window
surface.executeCommand( 'referencesList' );
}
);
} );
test.it( 'Cite button', function () {
runScreenshotTest( 'VisualEditor_citoid_Cite_button', lang,
// This function is converted to a string and executed in the browser
function () {
var done = arguments[ arguments.length - 1 ];
ve.init.target.$element.css( 'font-size', '250%' );
// Wait for re-paint
setTimeout( function () {
done(
seleniumUtils.getBoundingRect( [
ve.init.target.toolbar.tools.citoid.$element[ 0 ]
] )
);
}, 100 );
},
0
);
} );
test.it( 'Link inspector', function () {
runScreenshotTest( 'VisualEditor-link_tool-search_results', lang,
// This function is converted to a string and executed in the browser
function () {
var done = arguments[ arguments.length - 1 ],
surface = ve.init.target.surface;
surface.getModel().getFragment()
// TODO: i18n this message, the linked word, and the API endpoint of the link inspector
.insertContent( 'World literature is literature that is read by many people all over' )
.collapseToStart().select();
surface.context.inspectors.once( 'opening', function ( win, opening ) {
opening.then( function () {
surface.context.inspectors.windows.link.annotationInput.input.requestRequest.then( function () {
// Wait a while for the images to load using a time guesstimate - as they're background
// images it's quite tricky to get load events.
setTimeout( function () {
done(
seleniumUtils.getBoundingRect( [
surface.$element.find( '.ve-ce-linkAnnotation' )[ 0 ],
surface.context.inspectors.currentWindow.$element[ 0 ]
] )
);
}, 2500 );
} );
} );
} );
ve.init.target.surface.executeCommand( 'link' );
}
);
} );
} ); } );
} test.it( 'Citoid inspector', function () {
runScreenshotTest( 'VisualEditor_Citoid_Inspector', lang,
require( './screenshots-client/userGuide.js' ).citoidInspector
);
runScreenshotTest( 'VisualEditor_Citoid_Inspector_Manual', lang,
require( './screenshots-client/userGuide.js' ).citoidInspectorManual
);
runScreenshotTest( 'VisualEditor_Citoid_Inspector_Reuse', lang,
require( './screenshots-client/userGuide.js' ).citoidInspectorReuse
);
} );
test.it( 'Tool groups (headings/text style/indentation/insert/page settings)', function () {
runScreenshotTest( 'VisualEditor_Toolbar_Headings', lang,
require( './screenshots-client/userGuide.js' ).toolbarHeadings
);
runScreenshotTest( 'VisualEditor_Toolbar_Formatting', lang,
require( './screenshots-client/userGuide.js' ).toolbarFormatting
);
runScreenshotTest( 'VisualEditor_Toolbar_Lists_and_indentation', lang,
require( './screenshots-client/userGuide.js' ).toolbarLists
);
runScreenshotTest( 'VisualEditor_Insert_Menu', lang,
require( './screenshots-client/userGuide.js' ).toolbarInsert
);
runScreenshotTest( 'VisualEditor_Media_Insert_Menu', lang,
require( './screenshots-client/userGuide.js' ).toolbarMedia
);
runScreenshotTest( 'VisualEditor_Template_Insert_Menu', lang,
require( './screenshots-client/userGuide.js' ).toolbarTemplate
);
runScreenshotTest( 'VisualEditor_insert_table', lang,
require( './screenshots-client/userGuide.js' ).toolbarTable
);
runScreenshotTest( 'VisualEditor_Formula_Insert_Menu', lang,
require( './screenshots-client/userGuide.js' ).toolbarFormula
);
runScreenshotTest( 'VisualEditor_References_List_Insert_Menu', lang,
require( './screenshots-client/userGuide.js' ).toolbarReferences
);
runScreenshotTest( 'VisualEditor_More_Settings', lang,
require( './screenshots-client/userGuide.js' ).toolbarSettings
);
runScreenshotTest( 'VisualEditor_page_settings_item', lang,
require( './screenshots-client/userGuide.js' ).toolbarPageSettings
);
runScreenshotTest( 'VisualEditor_category_item', lang,
require( './screenshots-client/userGuide.js' ).toolbarCategory
);
} );
test.it( 'Save dialog', function () {
runScreenshotTest( 'VisualEditor_save_dialog', lang,
require( './screenshots-client/userGuide.js' ).save
);
} );
test.it( 'Special character inserter', function () {
runScreenshotTest( 'VisualEditor_Toolbar_SpecialCharacters', lang,
require( './screenshots-client/userGuide.js' ).specialCharacters
);
} );
test.it( 'Math dialog', function () {
runScreenshotTest( 'VisualEditor_formula', lang,
require( './screenshots-client/userGuide.js' ).formula
);
} );
test.it( 'Reference list dialog', function () {
runScreenshotTest( 'VisualEditor_references_list', lang,
require( './screenshots-client/userGuide.js' ).referenceList
);
} );
test.it( 'Cite button', function () {
runScreenshotTest( 'VisualEditor_citoid_Cite_button', lang,
require( './screenshots-client/userGuide.js' ).toolbarCite,
0
);
} );
test.it( 'Link inspector', function () {
runScreenshotTest( 'VisualEditor-link_tool-search_results', lang,
require( './screenshots-client/userGuide.js' ).linkSearchResults
);
} );
} );
}
for ( let i = 0, l = langs.length; i < l; i++ ) { for ( let i = 0, l = langs.length; i < l; i++ ) {
runTests( langs[ i ] ); runTests( langs[ i ] );
} }
}() );