diff --git a/build/.eslintrc.json b/build/.eslintrc.json
index 9f2c0a79f0..e5e4859af8 100644
--- a/build/.eslintrc.json
+++ b/build/.eslintrc.json
@@ -1,9 +1,11 @@
{
"root": true,
"extends": [
- "../.eslintrc.json",
"wikimedia/server"
],
+ "globals": {
+ "langs": "readonly"
+ },
"rules": {
"max-len": "off",
"mediawiki/valid-package-file-require": "off"
diff --git a/build/screenshots-client/.eslintrc.json b/build/screenshots-client/.eslintrc.json
new file mode 100644
index 0000000000..e027c09d61
--- /dev/null
+++ b/build/screenshots-client/.eslintrc.json
@@ -0,0 +1,9 @@
+{
+ "root": true,
+ "extends": [
+ "../../.eslintrc.json"
+ ],
+ "globals": {
+ "seleniumUtils": "readonly"
+ }
+}
diff --git a/build/screenshots-client/diffs.js b/build/screenshots-client/diffs.js
new file mode 100644
index 0000000000..775f672caa
--- /dev/null
+++ b/build/screenshots-client/diffs.js
@@ -0,0 +1,46 @@
+module.exports = {
+ simple: function () {
+ var done = arguments[ arguments.length - 1 ];
+
+ seleniumUtils.runDiffTest(
+ '
Lorem ipsum
' +
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.
',
+ 'Lorem ipsum
' +
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.
',
+ done
+ );
+ },
+ moveAndChange: function () {
+ var done = arguments[ arguments.length - 1 ];
+
+ seleniumUtils.runDiffTest(
+ 'Lorem ipsum
' +
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.
' +
+ 'Maecenas fringilla turpis et nunc bibendum mattis.
',
+ 'Lorem ipsum
' +
+ 'Maecenas fringilla turpis et nunc bibendum mattis.
' +
+ 'Lorem ipsum dolor sit amat, consectetur adipiscing elit.
',
+ done
+ );
+ },
+ linkChange: function () {
+ var done = arguments[ arguments.length - 1 ];
+
+ seleniumUtils.runDiffTest(
+ 'Lorem ipsum
' +
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.
',
+ 'Lorem ipsum
' +
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.
',
+ done
+ );
+ },
+ listChange: function () {
+ var done = arguments[ arguments.length - 1 ];
+
+ seleniumUtils.runDiffTest(
+ '',
+ '',
+ done
+ );
+ }
+};
diff --git a/build/screenshots-client/userGuide.js b/build/screenshots-client/userGuide.js
new file mode 100644
index 0000000000..0b1bffb5a7
--- /dev/null
+++ b/build/screenshots-client/userGuide.js
@@ -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' );
+ }
+};
diff --git a/build/screenshots-client/utils.js b/build/screenshots-client/utils.js
new file mode 100644
index 0000000000..31a83f67ba
--- /dev/null
+++ b/build/screenshots-client/utils.js
@@ -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 );
+ } );
+ } );
+};
diff --git a/build/screenshots.diffs.js b/build/screenshots.diffs.js
index 2aac6fc2d6..f568ab64c9 100644
--- a/build/screenshots.diffs.js
+++ b/build/screenshots.diffs.js
@@ -1,121 +1,28 @@
-/* global seleniumUtils, langs */
+const createScreenshotEnvironment = require( './screenshots.js' ).createScreenshotEnvironment,
+ test = require( 'selenium-webdriver/testing' ),
+ runScreenshotTest = createScreenshotEnvironment( test );
-( function () {
- 'use strict';
- var runScreenshotTest,
- createScreenshotEnvironment = require( './screenshots.js' ).createScreenshotEnvironment,
- test = require( 'selenium-webdriver/testing' );
+function runTests( lang ) {
- runScreenshotTest = createScreenshotEnvironment( test, function () {
- var done = arguments[ arguments.length - 1 ];
-
- window.seleniumUtils.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.$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(
- 'Lorem ipsum
' +
- 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.
',
- 'Lorem ipsum
' +
- 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.
',
- 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(
- 'Lorem ipsum
' +
- 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.
' +
- 'Maecenas fringilla turpis et nunc bibendum mattis.
',
- 'Lorem ipsum
' +
- 'Maecenas fringilla turpis et nunc bibendum mattis.
' +
- 'Lorem ipsum dolor sit amat, consectetur adipiscing elit.
',
- 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(
- 'Lorem ipsum
' +
- 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.
',
- 'Lorem ipsum
' +
- 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.
',
- 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(
- '',
- '',
- done
- );
- }
- );
- } );
+ test.describe( 'Screenshots: ' + lang, function () {
+ this.lang = lang;
+ test.it( 'Simple diff', function () {
+ runScreenshotTest( 'VisualEditor_diff_simple', lang,
+ require( './screenshots-client/diffs.js' ).simple
+ );
+ runScreenshotTest( 'VisualEditor_diff_move_and_change', lang,
+ require( './screenshots-client/diffs.js' ).moveAndChange
+ );
+ runScreenshotTest( 'VisualEditor_diff_link_change', lang,
+ require( './screenshots-client/diffs.js' ).linkChange
+ );
+ runScreenshotTest( 'VisualEditor_diff_list_change', lang,
+ require( './screenshots-client/diffs.js' ).listChange
+ );
} );
- }
+ } );
+}
- for ( let i = 0, l = langs.length; i < l; i++ ) {
- runTests( langs[ i ] );
- }
-}() );
+for ( let i = 0, l = langs.length; i < l; i++ ) {
+ runTests( langs[ i ] );
+}
diff --git a/build/screenshots.js b/build/screenshots.js
index 539fce7fa9..7b8e25e3f4 100644
--- a/build/screenshots.js
+++ b/build/screenshots.js
@@ -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 () {
- 'use strict';
- 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;
+ test.beforeEach( function () {
+ const lang = this.currentTest.parent.lang || 'en';
- function createScreenshotEnvironment( test, beforeEach ) {
- var clientSize, driver;
+ // 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();
+ }
- test.beforeEach( function () {
- var lang = this.currentTest.parent.lang || 'en';
-
- // 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.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.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().window().setSize( 1200, 1000 );
-
- driver.get( 'https://en.wikipedia.org/wiki/Help:Sample_page?veaction=edit&uselang=' + lang );
driver.wait(
- driver.executeAsyncScript(
- // This function is converted to a string and executed in the browser
- 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 || [] ) )
- );
- } );
- }
- };
-
- // 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 );
- } );
- } );
+ driver.executeAsyncScript( beforeEach ).then(
+ function () {},
+ function ( e ) {
+ // Log error (timeout)
+ console.error( e.message );
}
- ).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;
diff --git a/build/screenshots.userGuide.js b/build/screenshots.userGuide.js
index ac5185c984..76a79a0a0a 100644
--- a/build/screenshots.userGuide.js
+++ b/build/screenshots.userGuide.js
@@ -1,311 +1,104 @@
-/* global seleniumUtils, langs */
-/* eslint-disable no-jquery/no-global-selector */
+const createScreenshotEnvironment = require( './screenshots.js' ).createScreenshotEnvironment,
+ test = require( 'selenium-webdriver/testing' ),
+ runScreenshotTest = createScreenshotEnvironment( test );
-( function () {
- 'use strict';
- var createScreenshotEnvironment = require( './screenshots.js' ).createScreenshotEnvironment,
- test = require( 'selenium-webdriver/testing' ),
- runScreenshotTest = createScreenshotEnvironment( test );
+function runTests( lang ) {
- function runTests( lang ) {
-
- test.describe( 'Screenshots: ' + lang, function () {
- this.lang = lang;
- test.it( 'Toolbar & action tools', function () {
- runScreenshotTest( 'VisualEditor_toolbar', lang,
- // This function is converted to a string and executed in the browser
- 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 ]
- ] )
- );
- } );
- },
- 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.describe( 'Screenshots: ' + lang, function () {
+ this.lang = lang;
+ test.it( 'Toolbar & action tools', function () {
+ runScreenshotTest( 'VisualEditor_toolbar', lang,
+ require( './screenshots-client/userGuide.js' ).toolbar,
+ 0
+ );
+ runScreenshotTest( 'VisualEditor_toolbar_actions', lang,
+ require( './screenshots-client/userGuide.js' ).toolbarActions,
+ 0
+ );
} );
- }
+ 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++ ) {
- runTests( langs[ i ] );
- }
-}() );
+for ( let i = 0, l = langs.length; i < l; i++ ) {
+ runTests( langs[ i ] );
+}