Catrope has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/68603


Change subject: Refactor selectNodes tests
......................................................................

Refactor selectNodes tests

* Move them from ve.example.js to ve.dm.example.js
** Also move lookupNode() and createDomElement() there
** Delete ve.example.js because there's nothing left in it
* Make main example document implicit, but allow override
* Specify nodes as arrays and do the lookup later
* Specify range and mode separately rather than calling selectNodes()
  during construction
* Construct statically rather than in a function
* Use expect( cases.length );

Change-Id: I620e949c5e612b32eaa57c5d9b60cc91f9ddbf02
---
M VisualEditor.hooks.php
M modules/ve/test/ce/ve.ce.Document.test.js
M modules/ve/test/dm/ve.dm.Document.test.js
M modules/ve/test/dm/ve.dm.example.js
M modules/ve/test/index.php
D modules/ve/test/ve.example.js
6 files changed, 546 insertions(+), 541 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor 
refs/changes/03/68603/1

diff --git a/VisualEditor.hooks.php b/VisualEditor.hooks.php
index 29d94dd..5994d6a 100644
--- a/VisualEditor.hooks.php
+++ b/VisualEditor.hooks.php
@@ -128,7 +128,6 @@
                                've.qunit.js',
                                // VisualEditor Tests
                                've.test.js',
-                               've.example.js',
                                've.Document.test.js',
                                've.Element.test.js',
                                've.Node.test.js',
diff --git a/modules/ve/test/ce/ve.ce.Document.test.js 
b/modules/ve/test/ce/ve.ce.Document.test.js
index 85cefe5..7828858 100644
--- a/modules/ve/test/ce/ve.ce.Document.test.js
+++ b/modules/ve/test/ce/ve.ce.Document.test.js
@@ -9,15 +9,6 @@
 
 /* Tests */
 
-QUnit.test( 'selectNodes', 21, function ( assert ) {
-       var i, len,
-               doc = ve.dm.example.createExampleDocument(),
-               cases = ve.example.getSelectNodesCases( doc );
-       for ( i = 0, len = cases.length; i < len; i++ ) {
-               assert.equalNodeSelection( cases[i].actual, cases[i].expected, 
cases[i].msg );
-       }
-} );
-
 QUnit.test( 'getRelativeOffset', function ( assert ) {
        var documentModel = ve.dm.example.createExampleDocument( 'alienData' ),
                documentView = new ve.ce.Document( documentModel ),
diff --git a/modules/ve/test/dm/ve.dm.Document.test.js 
b/modules/ve/test/dm/ve.dm.Document.test.js
index 32808f0..78ee137 100644
--- a/modules/ve/test/dm/ve.dm.Document.test.js
+++ b/modules/ve/test/dm/ve.dm.Document.test.js
@@ -274,13 +274,26 @@
        );
 } );
 
-QUnit.test( 'selectNodes', 21, function ( assert ) {
-       var i,
-               doc = ve.dm.example.createExampleDocument(),
-               cases = ve.example.getSelectNodesCases( doc );
+QUnit.test( 'selectNodes', function ( assert ) {
+       var i, doc, expectedSelection,
+               mainDoc = ve.dm.example.createExampleDocument(),
+               cases = ve.dm.example.selectNodesCases;
 
+       function resolveNode( item ) {
+               var newItem = ve.extendObject( {}, item );
+               newItem.node = ve.dm.example.lookupNode.apply(
+                       ve.dm.example, [ doc.getDocumentNode() ].concat( 
item.node )
+               );
+               return newItem;
+       }
+
+       QUnit.expect( cases.length );
        for ( i = 0; i < cases.length; i++ ) {
-               assert.equalNodeSelection( cases[i].actual, cases[i].expected, 
cases[i].msg );
+               doc = cases[i].doc ? ve.dm.example.createExampleDocument( 
cases[i].doc ) : mainDoc;
+               expectedSelection = cases[i].expected.map( resolveNode );
+               assert.equalNodeSelection(
+                       doc.selectNodes( cases[i].range, cases[i].mode ), 
expectedSelection, cases[i].msg
+               );
        }
 } );
 
diff --git a/modules/ve/test/dm/ve.dm.example.js 
b/modules/ve/test/dm/ve.dm.example.js
index d046c36..4af8941 100644
--- a/modules/ve/test/dm/ve.dm.example.js
+++ b/modules/ve/test/dm/ve.dm.example.js
@@ -118,6 +118,33 @@
        return doc;
 };
 
+/**
+ * Looks up a value in a node tree.
+ *
+ * @method
+ * @param {ve.Node} root Root node to lookup from
+ * @param {number...} [paths] Index path
+ * @return {ve.Node} Node at given path
+ */
+ve.dm.example.lookupNode = function ( root ) {
+       var i,
+               node = root;
+       for ( i = 1; i < arguments.length; i++ ) {
+               node = node.children[arguments[i]];
+       }
+       return node;
+};
+
+ve.dm.example.createDomElement = function ( type, attributes ) {
+       var key,
+               element = document.createElement( type );
+       for ( key in attributes ) {
+               element.setAttribute( key, attributes[key] );
+       }
+       return element;
+};
+
+
 ve.dm.example.testDir = window.mw ?
        ( window.mw.config.get( 'wgExtensionAssetsPath' ) + 
'/VisualEditor/modules/ve/test' ) :
        '.';
@@ -750,79 +777,79 @@
 
 ve.dm.example.conversions = {
        'definitionListItem term': {
-               'domElement': ve.example.createDomElement( 'dt' ),
+               'domElement': ve.dm.example.createDomElement( 'dt' ),
                'dataElement': { 'type': 'definitionListItem', 'attributes': { 
'style': 'term' } }
        },
        'definitionListItem definition': {
-               'domElement': ve.example.createDomElement( 'dd' ),
+               'domElement': ve.dm.example.createDomElement( 'dd' ),
                'dataElement': { 'type': 'definitionListItem', 'attributes': { 
'style': 'definition' } }
        },
        'definitionList definition': {
-               'domElement': ve.example.createDomElement( 'dl' ),
+               'domElement': ve.dm.example.createDomElement( 'dl' ),
                'dataElement': { 'type': 'definitionList' }
        },
        'heading level 1': {
-               'domElement': ve.example.createDomElement( 'h1' ),
+               'domElement': ve.dm.example.createDomElement( 'h1' ),
                'dataElement': { 'type': 'heading', 'attributes': { 'level': 1 
} }
        },
        'heading level 2': {
-               'domElement': ve.example.createDomElement( 'h2' ),
+               'domElement': ve.dm.example.createDomElement( 'h2' ),
                'dataElement': { 'type': 'heading', 'attributes': { 'level': 2 
} }
        },
        'heading level 3': {
-               'domElement': ve.example.createDomElement( 'h3' ),
+               'domElement': ve.dm.example.createDomElement( 'h3' ),
                'dataElement': { 'type': 'heading', 'attributes': { 'level': 3 
} }
        },
        'heading level 4': {
-               'domElement': ve.example.createDomElement( 'h4' ),
+               'domElement': ve.dm.example.createDomElement( 'h4' ),
                'dataElement': { 'type': 'heading', 'attributes': { 'level': 4 
} }
        },
        'heading level 5': {
-               'domElement': ve.example.createDomElement( 'h5' ),
+               'domElement': ve.dm.example.createDomElement( 'h5' ),
                'dataElement': { 'type': 'heading', 'attributes': { 'level': 5 
} }
        },
        'heading level 6': {
-               'domElement': ve.example.createDomElement( 'h6' ),
+               'domElement': ve.dm.example.createDomElement( 'h6' ),
                'dataElement': { 'type': 'heading', 'attributes': { 'level': 6 
} }
        },
        'image': {
-               'domElement': ve.example.createDomElement( 'img' ),
+               'domElement': ve.dm.example.createDomElement( 'img' ),
                'dataElement': { 'type': 'image' }
        },
        'listItem': {
-               'domElement': ve.example.createDomElement( 'li' ),
+               'domElement': ve.dm.example.createDomElement( 'li' ),
                'dataElement': { 'type': 'listItem' }
        },
        'list bullet': {
-               'domElement': ve.example.createDomElement( 'ul' ),
+               'domElement': ve.dm.example.createDomElement( 'ul' ),
                'dataElement': { 'type': 'list', 'attributes': { 'style': 
'bullet' } }
        },
        'list number': {
-               'domElement': ve.example.createDomElement( 'ol' ),
+               'domElement': ve.dm.example.createDomElement( 'ol' ),
                'dataElement': { 'type': 'list', 'attributes': { 'style': 
'number' } }
        },
        'paragraph': {
-               'domElement': ve.example.createDomElement( 'p' ),
+               'domElement': ve.dm.example.createDomElement( 'p' ),
                'dataElement': { 'type': 'paragraph' }
        },
        'preformatted': {
-               'domElement': ve.example.createDomElement( 'pre' ),
+               'domElement': ve.dm.example.createDomElement( 'pre' ),
                'dataElement': { 'type': 'preformatted' }
        },
        'tableCell': {
-               'domElement': ve.example.createDomElement( 'td' ),
+               'domElement': ve.dm.example.createDomElement( 'td' ),
                'dataElement': { 'type': 'tableCell', 'attributes': { 'style': 
'data' } }
        },
        'table': {
-               'domElement': ve.example.createDomElement( 'table' ),
+               'domElement': ve.dm.example.createDomElement( 'table' ),
                'dataElement': { 'type': 'table' }
        },
        'tableRow': {
-               'domElement': ve.example.createDomElement( 'tr' ),
+               'domElement': ve.dm.example.createDomElement( 'tr' ),
                'dataElement': { 'type': 'tableRow' }
        },
        'paragraph with data-mw attribute': {
-               'domElement': ve.example.createDomElement( 'p', { 'data-mw': 
'{"test":1234}' } ),
+               'domElement': ve.dm.example.createDomElement( 'p', { 'data-mw': 
'{"test":1234}' } ),
                'dataElement': {
                        'type': 'paragraph',
                        'htmlAttributes': [
@@ -834,7 +861,7 @@
                }
        },
        'paragraph with style attribute': {
-               'domElement': ve.example.createDomElement( 'p', { 'style': 
'color:blue' } ),
+               'domElement': ve.dm.example.createDomElement( 'p', { 'style': 
'color:blue' } ),
                'dataElement': {
                        'type': 'paragraph',
                        'htmlAttributes': [
@@ -3597,4 +3624,484 @@
        { 'type': '/paragraph' },
        { 'type': '/internalItem' },
        { 'type': '/internalList' }
-];
\ No newline at end of file
+];
+
+ve.dm.example.selectNodesCases = [
+       {
+               'range': new ve.Range( 1 ),
+               'mode': 'branches',
+               'expected': [
+                       // heading
+                       {
+                               'node': [ 0 ],
+                               'range': new ve.Range( 1 ),
+                               'index': 0,
+                               'nodeRange': new ve.Range( 1, 4 ),
+                               'nodeOuterRange': new ve.Range( 0, 5 ),
+                               'parentOuterRange': new ve.Range( 0, 61 )
+                       }
+               ]
+       },
+       {
+               'range': new ve.Range( 10 ),
+               'mode': 'branches',
+               'expected': [
+                       // table/tableSection/tableRow/tableCell/paragraph
+                       {
+                               'node': [ 1, 0, 0, 0, 0 ],
+                               'range': new ve.Range( 10 ),
+                               'index': 0,
+                               'nodeRange': new ve.Range( 10, 11 ),
+                               'nodeOuterRange': new ve.Range( 9, 12 ),
+                               'parentOuterRange': new ve.Range( 8, 34 )
+                       }
+               ]
+       },
+       {
+               'range': new ve.Range( 20 ),
+               'mode': 'branches',
+               'expected': [
+                       // 
table/tableSection/tableRow/tableCell/list/listItem/list/listItem/paragraph
+                       {
+                               'node': [ 1, 0, 0, 0, 1, 0, 1, 0, 0 ],
+                               'range': new ve.Range( 20 ),
+                               'index': 0,
+                               'nodeRange': new ve.Range( 20, 21 ),
+                               'nodeOuterRange': new ve.Range( 19, 22 ),
+                               'parentOuterRange': new ve.Range( 18, 23 )
+                       }
+               ]
+       },
+       {
+               'range': new ve.Range( 1, 20 ),
+               'mode': 'branches',
+               'expected': [
+                       // heading
+                       {
+                               'node': [ 0 ],
+                               'range': new ve.Range( 1, 4 ),
+                               'index': 0,
+                               'nodeRange': new ve.Range( 1, 4 ),
+                               'nodeOuterRange': new ve.Range( 0, 5 ),
+                               'parentOuterRange': new ve.Range( 0, 61 )
+                       },
+
+                       // table/tableSection/tableRow/tableCell/paragraph
+                       {
+                               'node': [ 1, 0, 0, 0, 0 ],
+                               'index': 0,
+                               'nodeRange': new ve.Range( 10, 11 ),
+                               'nodeOuterRange': new ve.Range( 9, 12 ),
+                               'parentOuterRange': new ve.Range( 8, 34 )
+                       },
+
+                       // 
table/tableSection/tableRow/tableCell/list/listItem/paragraph
+                       {
+                               'node': [ 1, 0, 0, 0, 1, 0, 0 ],
+                               'index': 0,
+                               'nodeRange': new ve.Range( 15, 16 ),
+                               'nodeOuterRange': new ve.Range( 14, 17 ),
+                               'parentOuterRange': new ve.Range( 13, 25 )
+                       },
+
+                       // 
table/tableSection/tableRow/tableCell/list/listItem/list/listItem/paragraph
+                       {
+                               'node': [ 1, 0, 0, 0, 1, 0, 1, 0, 0 ],
+                               'range': new ve.Range( 20 ),
+                               'index': 0,
+                               'nodeRange': new ve.Range( 20, 21 ),
+                               'nodeOuterRange': new ve.Range( 19, 22 ),
+                               'parentOuterRange': new ve.Range( 18, 23 )
+                       }
+               ]
+       },
+       {
+               'range': new ve.Range( 1 ),
+               'mode': 'branches',
+               'expected': [
+                       // heading
+                       {
+                               'node': [ 0 ],
+                               'range': new ve.Range( 1 ),
+                               'index': 0,
+                               'nodeRange': new ve.Range( 1, 4 ),
+                               'nodeOuterRange': new ve.Range( 0, 5 ),
+                               'parentOuterRange': new ve.Range( 0, 61 )
+                       }
+               ]
+       },
+       {
+               'range': new ve.Range( 0, 3 ),
+               'mode': 'leaves',
+               'expected': [
+                       // heading/text
+                       {
+                               'node': [ 0, 0 ],
+                               'range': new ve.Range( 1, 3 ),
+                               'index': 0,
+                               'nodeRange': new ve.Range( 1, 4 ),
+                               'nodeOuterRange': new ve.Range( 1, 4 ),
+                               'parentOuterRange': new ve.Range( 0, 5 )
+                       }
+               ],
+               'msg': 'partial leaf results have ranges with global offsets'
+       },
+       {
+               'range': new ve.Range( 0, 11 ),
+               'mode': 'leaves',
+               'expected': [
+                       // heading/text
+                       {
+                               'node': [ 0, 0 ],
+                               'index': 0,
+                               'nodeRange': new ve.Range( 1, 4 ),
+                               'nodeOuterRange': new ve.Range( 1, 4 ),
+                               'parentOuterRange': new ve.Range( 0, 5 )
+                       },
+                       // table/tableSection/tableRow/tableCell/paragraph/text
+                       {
+                               'node': [ 1, 0, 0, 0, 0, 0 ],
+                               'index': 0,
+                               'nodeRange': new ve.Range( 10, 11 ),
+                               'nodeOuterRange': new ve.Range( 10, 11 ),
+                               'parentOuterRange': new ve.Range( 9, 12 )
+                       }
+               ],
+               'msg': 'leaf nodes do not have ranges, leaf nodes from 
different levels'
+       },
+       {
+               'range': new ve.Range( 29, 43 ),
+               'mode': 'leaves',
+               'expected': [
+                       // 
table/tableSection/tableRow/tableCell/list/listItem/paragraph/text
+                       {
+                               'node': [ 1, 0, 0, 0, 2, 0, 0, 0 ],
+                               'index': 0,
+                               'nodeRange': new ve.Range( 29, 30 ),
+                               'nodeOuterRange': new ve.Range( 29, 30 ),
+                               'parentOuterRange': new ve.Range( 28, 31 )
+                       },
+                       // preformatted/text
+                       {
+                               'node': [ 2, 0 ],
+                               'index': 0,
+                               'nodeRange': new ve.Range( 38, 39 ),
+                               'nodeOuterRange': new ve.Range( 38, 39 ),
+                               'parentOuterRange': new ve.Range( 37, 43 )
+                       },
+                       // preformatted/image
+                       {
+                               'node': [ 2, 1 ],
+                               'index': 1,
+                               'nodeRange': new ve.Range( 40, 40 ),
+                               'nodeOuterRange': new ve.Range( 39, 41 ),
+                               'parentOuterRange': new ve.Range( 37, 43 )
+                       },
+                       // preformatted/text
+                       {
+                               'node': [ 2, 2 ],
+                               'index': 2,
+                               'nodeRange': new ve.Range( 41, 42 ),
+                               'nodeOuterRange': new ve.Range( 41, 42 ),
+                               'parentOuterRange': new ve.Range( 37, 43 )
+                       }
+               ],
+               'msg': 'leaf nodes that are not text nodes'
+       },
+       {
+               'range': new ve.Range( 2, 16 ),
+               'mode': 'siblings',
+               'expected': [
+                       // heading
+                       {
+                               'node': [ 0 ],
+                               'range': new ve.Range( 2, 4 ),
+                               'index': 0,
+                               'nodeRange': new ve.Range( 1, 4 ),
+                               'nodeOuterRange': new ve.Range( 0, 5 ),
+                               'parentOuterRange': new ve.Range( 0, 61 )
+                       },
+                       // table
+                       {
+                               'node': [ 1 ],
+                               'range': new ve.Range( 6, 16 ),
+                               'index': 1,
+                               'nodeRange': new ve.Range( 6, 36 ),
+                               'nodeOuterRange': new ve.Range( 5, 37 ),
+                               'parentOuterRange': new ve.Range( 0, 61 )
+                       }
+               ],
+               'msg': 'siblings at the document level'
+       },
+       {
+               'range': new ve.Range( 2, 51 ),
+               'mode': 'siblings',
+               'expected': [
+                       // heading
+                       {
+                               'node': [ 0 ],
+                               'range': new ve.Range( 2, 4 ),
+                               'index': 0,
+                               'nodeRange': new ve.Range( 1, 4 ),
+                               'nodeOuterRange': new ve.Range( 0, 5 ),
+                               'parentOuterRange': new ve.Range( 0, 61 )
+                       },
+                       // table
+                       {
+                               'node': [ 1 ],
+                               'index': 1,
+                               'nodeRange': new ve.Range( 6, 36 ),
+                               'nodeOuterRange': new ve.Range( 5, 37 ),
+                               'parentOuterRange': new ve.Range( 0, 61 )
+                       },
+                       // preformatted
+                       {
+                               'node': [ 2 ],
+                               'index': 2,
+                               'nodeRange': new ve.Range( 38, 42 ),
+                               'nodeOuterRange': new ve.Range( 37, 43 ),
+                               'parentOuterRange': new ve.Range( 0, 61 )
+                       },
+                       // definitionList
+                       {
+                               'node': [ 3 ],
+                               'range': new ve.Range( 44, 51 ),
+                               'index': 3,
+                               'nodeRange': new ve.Range( 44, 54 ),
+                               'nodeOuterRange': new ve.Range( 43, 55 ),
+                               'parentOuterRange': new ve.Range( 0, 61 )
+                       }
+               ],
+               'msg': 'more than 2 siblings at the document level'
+       },
+       {
+               'range': new ve.Range( 1, 1 ),
+               'mode': 'leaves',
+               'expected': [
+                       // heading/text
+                       {
+                               'node': [ 0, 0 ],
+                               'range': new ve.Range( 1, 1 ),
+                               'index': 0,
+                               'nodeRange': new ve.Range( 1, 4 ),
+                               'nodeOuterRange': new ve.Range( 1, 4 ),
+                               'parentOuterRange': new ve.Range( 0, 5 )
+                       }
+               ],
+               'msg': 'zero-length range at the start of a text node returns 
text node rather than parent'
+       },
+       {
+               'range': new ve.Range( 4, 4 ),
+               'mode': 'leaves',
+               'expected': [
+                       // heading/text
+                       {
+                               'node': [ 0, 0 ],
+                               'range': new ve.Range( 4, 4 ),
+                               'index': 0,
+                               'nodeRange': new ve.Range( 1, 4 ),
+                               'nodeOuterRange': new ve.Range( 1, 4 ),
+                               'parentOuterRange': new ve.Range( 0, 5 )
+                       }
+               ],
+               'msg': 'zero-length range at the end of a text node returns 
text node rather than parent'
+       },
+       {
+               'range': new ve.Range( 2, 3 ),
+               'mode': 'leaves',
+               'expected': [
+                       // heading/text
+                       {
+                               'node': [ 0, 0 ],
+                               'range': new ve.Range( 2, 3 ),
+                               'index': 0,
+                               'nodeRange': new ve.Range( 1, 4 ),
+                               'nodeOuterRange': new ve.Range( 1, 4 ),
+                               'parentOuterRange': new ve.Range( 0, 5 )
+                       }
+               ],
+               'msg': 'range entirely within one leaf node'
+       },
+       {
+               'range': new ve.Range( 5, 5 ),
+               'mode': 'leaves',
+               'expected': [
+                       // document
+                       {
+                               'node': [],
+                               'range': new ve.Range( 5, 5 ),
+                               // no 'index' because documentNode has no parent
+                               'indexInNode': 1,
+                               'nodeRange': new ve.Range( 0, 61 ),
+                               'nodeOuterRange': new ve.Range( 0, 61 )
+                       }
+               ],
+               'msg': 'zero-length range between two children of the document'
+       },
+       {
+               'range': new ve.Range( 0, 0 ),
+               'mode': 'leaves',
+               'expected': [
+                       // document
+                       {
+                               'node': [],
+                               'range': new ve.Range( 0, 0 ),
+                               // no 'index' because documentNode has no parent
+                               'indexInNode': 0,
+                               'nodeRange': new ve.Range( 0, 61 ),
+                               'nodeOuterRange': new ve.Range( 0, 61 )
+                       }
+               ],
+               'msg': 'zero-length range at the start of the document'
+       },
+       {
+               'range': new ve.Range( 32, 39 ),
+               'mode': 'leaves',
+               'expected': [
+                       // table/tableSection/tableRow/tableCell/list
+                       {
+                               'node': [ 1, 0, 0, 0, 2 ],
+                               'range': new ve.Range( 32, 32 ),
+                               'index': 2,
+                               'indexInNode': 1,
+                               'nodeRange': new ve.Range( 27, 32 ),
+                               'nodeOuterRange': new ve.Range( 26, 33 )
+                       },
+                       // preformatted/text
+                       {
+                               'node': [ 2, 0 ],
+                               // no 'range' because the text node is covered 
completely
+                               'index': 0,
+                               'nodeRange': new ve.Range( 38, 39 ),
+                               'nodeOuterRange': new ve.Range( 38, 39 ),
+                               'parentOuterRange': new ve.Range( 37, 43 )
+                       }
+               ],
+               'msg': 'range with 5 closings and a text node'
+       },
+       {
+               'range': new ve.Range( 2, 57 ),
+               'mode': 'covered',
+               'expected': [
+                       // heading/text
+                       {
+                               'node': [ 0, 0 ],
+                               'range': new ve.Range( 2, 4 ),
+                               'index': 0,
+                               'nodeRange': new ve.Range( 1, 4 ),
+                               'nodeOuterRange': new ve.Range( 1, 4 ),
+                               'parentOuterRange': new ve.Range( 0, 5 )
+                       },
+                       // table
+                       {
+                               'node': [ 1 ],
+                               // no 'range' because the table is covered 
completely
+                               'index': 1,
+                               'nodeRange': new ve.Range( 6, 36 ),
+                               'nodeOuterRange': new ve.Range( 5, 37 ),
+                               'parentOuterRange': new ve.Range( 0, 61 )
+                       },
+                       // preformatted
+                       {
+                               'node': [ 2 ],
+                               // no 'range' because the node is covered 
completely
+                               'index': 2,
+                               'nodeRange': new ve.Range( 38, 42 ),
+                               'nodeOuterRange': new ve.Range( 37, 43 ),
+                               'parentOuterRange': new ve.Range( 0, 61 )
+                       },
+                       // definitionList
+                       {
+                               'node': [ 3 ],
+                               // no 'range' because the node is covered 
completely
+                               'index': 3,
+                               'nodeRange': new ve.Range( 44, 54 ),
+                               'nodeOuterRange': new ve.Range( 43, 55 ),
+                               'parentOuterRange': new ve.Range( 0, 61 )
+                       },
+                       // paragraph/text
+                       {
+                               'node': [ 4, 0 ],
+                               // no 'range' because the text node is covered 
completely
+                               'index': 0,
+                               'nodeRange': new ve.Range( 56, 57 ),
+                               'nodeOuterRange': new ve.Range( 56, 57 ),
+                               'parentOuterRange': new ve.Range( 55, 58 )
+                       }
+               ],
+               'msg': 'range from the first heading into the second-to-last 
paragraph, in covered mode'
+       },
+       {
+               'range': new ve.Range( 14, 14 ),
+               'mode': 'siblings',
+               'expected': [
+                       // table/tableSection/tableRow/tableCell/list/listItem
+                       {
+                               'node': [ 1, 0, 0, 0, 1, 0 ],
+                               'range': new ve.Range( 14, 14 ),
+                               'index': 0,
+                               'indexInNode': 0,
+                               'nodeRange': new ve.Range( 14, 24 ),
+                               'nodeOuterRange': new ve.Range( 13, 25 )
+                       }
+               ],
+               'msg': 'zero-length range at the beginning of a listItem, in 
siblings mode'
+       },
+       {
+               'range': new ve.Range( 25, 27 ),
+               'mode': 'covered',
+               'expected': [
+                       // table/tableSection/tableRow/tableCell/list
+                       {
+                               'node': [ 1, 0, 0, 0, 1 ],
+                               'range': new ve.Range( 25, 25 ),
+                               'index': 1,
+                               'indexInNode': 1,
+                               'nodeRange': new ve.Range( 13, 25 ),
+                               'nodeOuterRange': new ve.Range( 12, 26 )
+                       },
+                       // table/tableSection/tableRow/tableCell/list
+                       {
+                               'node': [ 1, 0, 0, 0, 2 ],
+                               'range': new ve.Range( 27, 27 ),
+                               'index': 2,
+                               'indexInNode': 0,
+                               'nodeRange': new ve.Range( 27, 32 ),
+                               'nodeOuterRange': new ve.Range( 26, 33 )
+                       }
+               ],
+               'msg': 'range covering a list closing and a list opening'
+       },
+       {
+               'range': new ve.Range( 39, 39 ),
+               'mode': 'leaves',
+               'expected': [
+                       // preformatted/text
+                       {
+                               'node': [ 2, 0 ],
+                               'range': new ve.Range( 39, 39 ),
+                               'index': 0,
+                               'nodeRange': new ve.Range( 38, 39 ),
+                               'nodeOuterRange': new ve.Range( 38, 39 ),
+                               'parentOuterRange': new ve.Range( 37, 43 )
+                       }
+               ],
+               'msg': 'zero-length range in text node before inline node'
+       },
+       {
+               'range': new ve.Range( 41, 41 ),
+               'mode': 'leaves',
+               'expected': [
+                       // preformatted/text
+                       {
+                               'node': [ 2, 2 ],
+                               'range': new ve.Range( 41, 41 ),
+                               'index': 2,
+                               'nodeRange': new ve.Range( 41, 42 ),
+                               'nodeOuterRange': new ve.Range( 41, 42 ),
+                               'parentOuterRange': new ve.Range( 37, 43 )
+                       }
+               ],
+               'msg': 'zero-length range in text node after inline node'
+       }
+];
diff --git a/modules/ve/test/index.php b/modules/ve/test/index.php
index 3ce587d..b82318f 100644
--- a/modules/ve/test/index.php
+++ b/modules/ve/test/index.php
@@ -277,7 +277,6 @@
 
                <!-- Load test suites -->
                <script src="ve.test.js"></script>
-               <script src="ve.example.js"></script>
                <script src="ve.Range.test.js"></script>
                <script src="ve.Document.test.js"></script>
                <script src="ve.Element.test.js"></script>
diff --git a/modules/ve/test/ve.example.js b/modules/ve/test/ve.example.js
deleted file mode 100644
index ae643e5..0000000
--- a/modules/ve/test/ve.example.js
+++ /dev/null
@@ -1,504 +0,0 @@
-/*!
- * VisualEditor example data sets and helper functions.
- *
- * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
- * @license The MIT License (MIT); see LICENSE.txt
- */
-
-/**
- * @class
- * @singleton
- * @ignore
- */
-ve.example = {};
-
-/* Methods */
-
-ve.example.getSelectNodesCases = function ( doc ) {
-       var lookup = ve.example.lookupNode,
-               documentNode = doc.getDocumentNode();
-       return [
-               {
-                       'actual': doc.selectNodes( new ve.Range( 1 ), 
'branches' ),
-                       'expected': [
-                               // heading
-                               {
-                                       'node': lookup( documentNode, 0 ),
-                                       'range': new ve.Range( 1 ),
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 1, 4 ),
-                                       'nodeOuterRange': new ve.Range( 0, 5 ),
-                                       'parentOuterRange': new ve.Range( 0, 61 
)
-                               }
-                       ]
-               },
-               {
-                       'actual': doc.selectNodes( new ve.Range( 10 ), 
'branches' ),
-                       'expected': [
-                               // 
table/tableSection/tableRow/tableCell/paragraph
-                               {
-                                       'node': lookup( documentNode, 1, 0, 0, 
0, 0 ),
-                                       'range': new ve.Range( 10 ),
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 10, 11 ),
-                                       'nodeOuterRange': new ve.Range( 9, 12 ),
-                                       'parentOuterRange': new ve.Range( 8, 34 
)
-                               }
-                       ]
-               },
-               {
-                       'actual': doc.selectNodes( new ve.Range( 20 ), 
'branches' ),
-                       'expected': [
-                               // 
table/tableSection/tableRow/tableCell/list/listItem/list/listItem/paragraph
-                               {
-                                       'node': lookup( documentNode, 1, 0, 0, 
0, 1, 0, 1, 0, 0 ),
-                                       'range': new ve.Range( 20 ),
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 20, 21 ),
-                                       'nodeOuterRange': new ve.Range( 19, 22 
),
-                                       'parentOuterRange': new ve.Range( 18, 
23 )
-                               }
-                       ]
-               },
-               {
-                       'actual': doc.selectNodes( new ve.Range( 1, 20 ), 
'branches' ),
-                       'expected': [
-                               // heading
-                               {
-                                       'node': lookup( documentNode, 0 ),
-                                       'range': new ve.Range( 1, 4 ),
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 1, 4 ),
-                                       'nodeOuterRange': new ve.Range( 0, 5 ),
-                                       'parentOuterRange': new ve.Range( 0, 61 
)
-                               },
-
-                               // 
table/tableSection/tableRow/tableCell/paragraph
-                               {
-                                       'node': lookup( documentNode, 1, 0, 0, 
0, 0 ),
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 10, 11 ),
-                                       'nodeOuterRange': new ve.Range( 9, 12 ),
-                                       'parentOuterRange': new ve.Range( 8, 34 
)
-                               },
-
-                               // 
table/tableSection/tableRow/tableCell/list/listItem/paragraph
-                               {
-                                       'node': lookup( documentNode, 1, 0, 0, 
0, 1, 0, 0 ),
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 15, 16 ),
-                                       'nodeOuterRange': new ve.Range( 14, 17 
),
-                                       'parentOuterRange': new ve.Range( 13, 
25 )
-                               },
-
-                               // 
table/tableSection/tableRow/tableCell/list/listItem/list/listItem/paragraph
-                               {
-                                       'node': lookup( documentNode, 1, 0, 0, 
0, 1, 0, 1, 0, 0 ),
-                                       'range': new ve.Range( 20 ),
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 20, 21 ),
-                                       'nodeOuterRange': new ve.Range( 19, 22 
),
-                                       'parentOuterRange': new ve.Range( 18, 
23 )
-                               }
-                       ]
-               },
-               {
-                       'actual': doc.selectNodes( new ve.Range( 1 ), 
'branches' ),
-                       'expected': [
-                               // heading
-                               {
-                                       'node': lookup( documentNode, 0 ),
-                                       'range': new ve.Range( 1 ),
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 1, 4 ),
-                                       'nodeOuterRange': new ve.Range( 0, 5 ),
-                                       'parentOuterRange': new ve.Range( 0, 61 
)
-                               }
-                       ]
-               },
-               {
-                       'actual': doc.selectNodes( new ve.Range( 0, 3 ), 
'leaves' ),
-                       'expected': [
-                               // heading/text
-                               {
-                                       'node': lookup( documentNode, 0, 0 ),
-                                       'range': new ve.Range( 1, 3 ),
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 1, 4 ),
-                                       'nodeOuterRange': new ve.Range( 1, 4 ),
-                                       'parentOuterRange': new ve.Range( 0, 5 )
-                               }
-                       ],
-                       'msg': 'partial leaf results have ranges with global 
offsets'
-               },
-               {
-                       'actual': doc.selectNodes( new ve.Range( 0, 11 ), 
'leaves' ),
-                       'expected': [
-                               // heading/text
-                               {
-                                       'node': lookup( documentNode, 0, 0 ),
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 1, 4 ),
-                                       'nodeOuterRange': new ve.Range( 1, 4 ),
-                                       'parentOuterRange': new ve.Range( 0, 5 )
-                               },
-                               // 
table/tableSection/tableRow/tableCell/paragraph/text
-                               {
-                                       'node': lookup( documentNode, 1, 0, 0, 
0, 0, 0 ),
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 10, 11 ),
-                                       'nodeOuterRange': new ve.Range( 10, 11 
),
-                                       'parentOuterRange': new ve.Range( 9, 12 
)
-                               }
-                       ],
-                       'msg': 'leaf nodes do not have ranges, leaf nodes from 
different levels'
-               },
-               {
-                       'actual': doc.selectNodes( new ve.Range( 29, 43 ), 
'leaves' ),
-                       'expected': [
-                               // 
table/tableSection/tableRow/tableCell/list/listItem/paragraph/text
-                               {
-                                       'node': lookup( documentNode, 1, 0, 0, 
0, 2, 0, 0, 0 ),
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 29, 30 ),
-                                       'nodeOuterRange': new ve.Range( 29, 30 
),
-                                       'parentOuterRange': new ve.Range( 28, 
31 )
-                               },
-                               // preformatted/text
-                               {
-                                       'node': lookup( documentNode, 2, 0 ),
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 38, 39 ),
-                                       'nodeOuterRange': new ve.Range( 38, 39 
),
-                                       'parentOuterRange': new ve.Range( 37, 
43 )
-                               },
-                               // preformatted/image
-                               {
-                                       'node': lookup( documentNode, 2, 1 ),
-                                       'index': 1,
-                                       'nodeRange': new ve.Range( 40, 40 ),
-                                       'nodeOuterRange': new ve.Range( 39, 41 
),
-                                       'parentOuterRange': new ve.Range( 37, 
43 )
-                               },
-                               // preformatted/text
-                               {
-                                       'node': lookup( documentNode, 2, 2 ),
-                                       'index': 2,
-                                       'nodeRange': new ve.Range( 41, 42 ),
-                                       'nodeOuterRange': new ve.Range( 41, 42 
),
-                                       'parentOuterRange': new ve.Range( 37, 
43 )
-                               }
-                       ],
-                       'msg': 'leaf nodes that are not text nodes'
-               },
-               {
-                       'actual': doc.selectNodes( new ve.Range( 2, 16 ), 
'siblings' ),
-                       'expected': [
-                               // heading
-                               {
-                                       'node': lookup( documentNode, 0 ),
-                                       'range': new ve.Range( 2, 4 ),
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 1, 4 ),
-                                       'nodeOuterRange': new ve.Range( 0, 5 ),
-                                       'parentOuterRange': new ve.Range( 0, 61 
)
-                               },
-                               // table
-                               {
-                                       'node': lookup( documentNode, 1 ),
-                                       'range': new ve.Range( 6, 16 ),
-                                       'index': 1,
-                                       'nodeRange': new ve.Range( 6, 36 ),
-                                       'nodeOuterRange': new ve.Range( 5, 37 ),
-                                       'parentOuterRange': new ve.Range( 0, 61 
)
-                               }
-                       ],
-                       'msg': 'siblings at the document level'
-               },
-               {
-                       'actual': doc.selectNodes( new ve.Range( 2, 51 ), 
'siblings' ),
-                       'expected': [
-                               // heading
-                               {
-                                       'node': lookup( documentNode, 0 ),
-                                       'range': new ve.Range( 2, 4 ),
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 1, 4 ),
-                                       'nodeOuterRange': new ve.Range( 0, 5 ),
-                                       'parentOuterRange': new ve.Range( 0, 61 
)
-                               },
-                               // table
-                               {
-                                       'node': lookup( documentNode, 1 ),
-                                       'index': 1,
-                                       'nodeRange': new ve.Range( 6, 36 ),
-                                       'nodeOuterRange': new ve.Range( 5, 37 ),
-                                       'parentOuterRange': new ve.Range( 0, 61 
)
-                               },
-                               // preformatted
-                               {
-                                       'node': lookup( documentNode, 2 ),
-                                       'index': 2,
-                                       'nodeRange': new ve.Range( 38, 42 ),
-                                       'nodeOuterRange': new ve.Range( 37, 43 
),
-                                       'parentOuterRange': new ve.Range( 0, 61 
)
-                               },
-                               // definitionList
-                               {
-                                       'node': lookup( documentNode, 3 ),
-                                       'range': new ve.Range( 44, 51 ),
-                                       'index': 3,
-                                       'nodeRange': new ve.Range( 44, 54 ),
-                                       'nodeOuterRange': new ve.Range( 43, 55 
),
-                                       'parentOuterRange': new ve.Range( 0, 61 
)
-                               }
-                       ],
-                       'msg': 'more than 2 siblings at the document level'
-               },
-               {
-                       'actual': doc.selectNodes( new ve.Range( 1, 1 ), 
'leaves' ),
-                       'expected': [
-                               // heading/text
-                               {
-                                       'node': lookup( documentNode, 0, 0 ),
-                                       'range': new ve.Range( 1, 1 ),
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 1, 4 ),
-                                       'nodeOuterRange': new ve.Range( 1, 4 ),
-                                       'parentOuterRange': new ve.Range( 0, 5 )
-                               }
-                       ],
-                       'msg': 'zero-length range at the start of a text node 
returns text node rather than parent'
-               },
-               {
-                       'actual': doc.selectNodes( new ve.Range( 4, 4 ), 
'leaves' ),
-                       'expected': [
-                               // heading/text
-                               {
-                                       'node': lookup( documentNode, 0, 0 ),
-                                       'range': new ve.Range( 4, 4 ),
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 1, 4 ),
-                                       'nodeOuterRange': new ve.Range( 1, 4 ),
-                                       'parentOuterRange': new ve.Range( 0, 5 )
-                               }
-                       ],
-                       'msg': 'zero-length range at the end of a text node 
returns text node rather than parent'
-               },
-               {
-                       'actual': doc.selectNodes( new ve.Range( 2, 3 ), 
'leaves' ),
-                       'expected': [
-                               // heading/text
-                               {
-                                       'node': lookup( documentNode, 0, 0 ),
-                                       'range': new ve.Range( 2, 3 ),
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 1, 4 ),
-                                       'nodeOuterRange': new ve.Range( 1, 4 ),
-                                       'parentOuterRange': new ve.Range( 0, 5 )
-                               }
-                       ],
-                       'msg': 'range entirely within one leaf node'
-               },
-               {
-                       'actual': doc.selectNodes( new ve.Range( 5, 5 ), 
'leaves' ),
-                       'expected': [
-                               // document
-                               {
-                                       'node': documentNode,
-                                       'range': new ve.Range( 5, 5 ),
-                                       // no 'index' because documentNode has 
no parent
-                                       'indexInNode': 1,
-                                       'nodeRange': new ve.Range( 0, 61 ),
-                                       'nodeOuterRange': new ve.Range( 0, 61 )
-                               }
-                       ],
-                       'msg': 'zero-length range between two children of the 
document'
-               },
-               {
-                       'actual': doc.selectNodes( new ve.Range( 0, 0 ), 
'leaves' ),
-                       'expected': [
-                               // document
-                               {
-                                       'node': documentNode,
-                                       'range': new ve.Range( 0, 0 ),
-                                       // no 'index' because documentNode has 
no parent
-                                       'indexInNode': 0,
-                                       'nodeRange': new ve.Range( 0, 61 ),
-                                       'nodeOuterRange': new ve.Range( 0, 61 )
-                               }
-                       ],
-                       'msg': 'zero-length range at the start of the document'
-               },
-               {
-                       'actual': doc.selectNodes( new ve.Range( 32, 39 ), 
'leaves' ),
-                       'expected': [
-                               // table/tableSection/tableRow/tableCell/list
-                               {
-                                       'node': lookup( documentNode, 1, 0, 0, 
0, 2 ),
-                                       'range': new ve.Range( 32, 32 ),
-                                       'index': 2,
-                                       'indexInNode': 1,
-                                       'nodeRange': new ve.Range( 27, 32 ),
-                                       'nodeOuterRange': new ve.Range( 26, 33 )
-                               },
-                               // preformatted/text
-                               {
-                                       'node': lookup( documentNode, 2, 0 ),
-                                       // no 'range' because the text node is 
covered completely
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 38, 39 ),
-                                       'nodeOuterRange': new ve.Range( 38, 39 
),
-                                       'parentOuterRange': new ve.Range( 37, 
43 )
-                               }
-                       ],
-                       'msg': 'range with 5 closings and a text node'
-               },
-               {
-                       'actual': doc.selectNodes( new ve.Range( 2, 57 ), 
'covered' ),
-                       'expected': [
-                               // heading/text
-                               {
-                                       'node': lookup( documentNode, 0, 0 ),
-                                       'range': new ve.Range( 2, 4 ),
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 1, 4 ),
-                                       'nodeOuterRange': new ve.Range( 1, 4 ),
-                                       'parentOuterRange': new ve.Range( 0, 5 )
-                               },
-                               // table
-                               {
-                                       'node': lookup( documentNode, 1 ),
-                                       // no 'range' because the table is 
covered completely
-                                       'index': 1,
-                                       'nodeRange': new ve.Range( 6, 36 ),
-                                       'nodeOuterRange': new ve.Range( 5, 37 ),
-                                       'parentOuterRange': new ve.Range( 0, 61 
)
-                               },
-                               // preformatted
-                               {
-                                       'node': lookup( documentNode, 2 ),
-                                       // no 'range' because the node is 
covered completely
-                                       'index': 2,
-                                       'nodeRange': new ve.Range( 38, 42 ),
-                                       'nodeOuterRange': new ve.Range( 37, 43 
),
-                                       'parentOuterRange': new ve.Range( 0, 61 
)
-                               },
-                               // definitionList
-                               {
-                                       'node': lookup( documentNode, 3 ),
-                                       // no 'range' because the node is 
covered completely
-                                       'index': 3,
-                                       'nodeRange': new ve.Range( 44, 54 ),
-                                       'nodeOuterRange': new ve.Range( 43, 55 
),
-                                       'parentOuterRange': new ve.Range( 0, 61 
)
-                               },
-                               // paragraph/text
-                               {
-                                       'node': lookup( documentNode, 4, 0 ),
-                                       // no 'range' because the text node is 
covered completely
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 56, 57 ),
-                                       'nodeOuterRange': new ve.Range( 56, 57 
),
-                                       'parentOuterRange': new ve.Range( 55, 
58 )
-                               }
-                       ],
-                       'msg': 'range from the first heading into the 
second-to-last paragraph, in covered mode'
-               },
-               {
-                       'actual': doc.selectNodes( new ve.Range( 14, 14 ), 
'siblings' ),
-                       'expected': [
-                               // 
table/tableSection/tableRow/tableCell/list/listItem
-                               {
-                                       'node': lookup( documentNode, 1, 0, 0, 
0, 1, 0 ),
-                                       'range': new ve.Range( 14, 14 ),
-                                       'index': 0,
-                                       'indexInNode': 0,
-                                       'nodeRange': new ve.Range( 14, 24 ),
-                                       'nodeOuterRange': new ve.Range( 13, 25 )
-                               }
-                       ],
-                       'msg': 'zero-length range at the beginning of a 
listItem, in siblings mode'
-               },
-               {
-                       'actual': doc.selectNodes( new ve.Range( 25, 27 ), 
'covered' ),
-                       'expected': [
-                               // table/tableSection/tableRow/tableCell/list
-                               {
-                                       'node': lookup( documentNode, 1, 0, 0, 
0, 1 ),
-                                       'range': new ve.Range( 25, 25 ),
-                                       'index': 1,
-                                       'indexInNode': 1,
-                                       'nodeRange': new ve.Range( 13, 25 ),
-                                       'nodeOuterRange': new ve.Range( 12, 26 )
-                               },
-                               // table/tableSection/tableRow/tableCell/list
-                               {
-                                       'node': lookup( documentNode, 1, 0, 0, 
0, 2 ),
-                                       'range': new ve.Range( 27, 27 ),
-                                       'index': 2,
-                                       'indexInNode': 0,
-                                       'nodeRange': new ve.Range( 27, 32 ),
-                                       'nodeOuterRange': new ve.Range( 26, 33 )
-                               }
-                       ],
-                       'msg': 'range covering a list closing and a list 
opening'
-               },
-               {
-                       'actual': doc.selectNodes( new ve.Range( 39, 39 ), 
'leaves' ),
-                       'expected': [
-                               // preformatted/text
-                               {
-                                       'node': lookup( documentNode, 2, 0 ),
-                                       'range': new ve.Range( 39, 39 ),
-                                       'index': 0,
-                                       'nodeRange': new ve.Range( 38, 39 ),
-                                       'nodeOuterRange': new ve.Range( 38, 39 
),
-                                       'parentOuterRange': new ve.Range( 37, 
43 )
-                               }
-                       ],
-                       'msg': 'zero-length range in text node before inline 
node'
-               },
-               {
-                       'actual': doc.selectNodes( new ve.Range( 41, 41 ), 
'leaves' ),
-                       'expected': [
-                               // preformatted/text
-                               {
-                                       'node': lookup( documentNode, 2, 2 ),
-                                       'range': new ve.Range( 41, 41 ),
-                                       'index': 2,
-                                       'nodeRange': new ve.Range( 41, 42 ),
-                                       'nodeOuterRange': new ve.Range( 41, 42 
),
-                                       'parentOuterRange': new ve.Range( 37, 
43 )
-                               }
-                       ],
-                       'msg': 'zero-length range in text node after inline 
node'
-               }
-       ];
-};
-
-/**
- * Looks up a value in a node tree.
- *
- * @method
- * @param {ve.Node} root Root node to lookup from
- * @param {number...} [paths] Index path
- * @return {ve.Node} Node at given path
- */
-ve.example.lookupNode = function ( root ) {
-       var i,
-               node = root;
-       for ( i = 1; i < arguments.length; i++ ) {
-               node = node.children[arguments[i]];
-       }
-       return node;
-};
-
-ve.example.createDomElement = function ( type, attributes ) {
-       var key,
-               element = document.createElement( type );
-       for ( key in attributes ) {
-               element.setAttribute( key, attributes[key] );
-       }
-       return element;
-};

-- 
To view, visit https://gerrit.wikimedia.org/r/68603
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I620e949c5e612b32eaa57c5d9b60cc91f9ddbf02
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Catrope <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to