diff options
Diffstat (limited to 'www/wiki/extensions/Cite/modules/ve-cite/tests')
6 files changed, 1286 insertions, 0 deletions
diff --git a/www/wiki/extensions/Cite/modules/ve-cite/tests/ve.dm.Converter.test.js b/www/wiki/extensions/Cite/modules/ve-cite/tests/ve.dm.Converter.test.js new file mode 100644 index 00000000..a3410e8f --- /dev/null +++ b/www/wiki/extensions/Cite/modules/ve-cite/tests/ve.dm.Converter.test.js @@ -0,0 +1,36 @@ +/*! + * VisualEditor DataModel Cite-specific Converter tests. + * + * @copyright 2011-2018 VisualEditor Team's Cite sub-team and others; see AUTHORS.txt + * @license MIT + */ + +QUnit.module( 've.dm.Converter (Cite)', ve.test.utils.mwEnvironment ); + +QUnit.test( 'getModelFromDom', function ( assert ) { + var msg, caseItem, + cases = ve.dm.citeExample.domToDataCases; + + for ( msg in cases ) { + caseItem = ve.copy( cases[ msg ] ); + if ( caseItem.mwConfig ) { + mw.config.set( caseItem.mwConfig ); + } + + ve.test.utils.runGetModelFromDomTest( assert, caseItem, msg ); + } +} ); + +QUnit.test( 'getDomFromModel', function ( assert ) { + var msg, caseItem, + cases = ve.dm.citeExample.domToDataCases; + + for ( msg in cases ) { + caseItem = ve.copy( cases[ msg ] ); + if ( caseItem.mwConfig ) { + mw.config.set( caseItem.mwConfig ); + } + + ve.test.utils.runGetDomFromModelTest( assert, caseItem, msg ); + } +} ); diff --git a/www/wiki/extensions/Cite/modules/ve-cite/tests/ve.dm.InternalList.test.js b/www/wiki/extensions/Cite/modules/ve-cite/tests/ve.dm.InternalList.test.js new file mode 100644 index 00000000..78d3d10f --- /dev/null +++ b/www/wiki/extensions/Cite/modules/ve-cite/tests/ve.dm.InternalList.test.js @@ -0,0 +1,237 @@ +/*! + * VisualEditor DataModel Cite-specific InternalList tests. + * + * @copyright 2011-2018 VisualEditor Team's Cite sub-team and others; see AUTHORS.txt + * @license MIT + */ + +QUnit.module( 've.dm.InternalList (Cite)', ve.test.utils.mwEnvironment ); + +/* Tests */ + +QUnit.test( 'addNode/removeNode', function ( assert ) { + var doc = ve.dm.citeExample.createExampleDocument( 'references' ), + newInternalList = new ve.dm.InternalList( doc ), + referenceNodes = [ + doc.getDocumentNode().children[ 0 ].children[ 0 ], + doc.getDocumentNode().children[ 1 ].children[ 1 ], + doc.getDocumentNode().children[ 1 ].children[ 3 ], + doc.getDocumentNode().children[ 1 ].children[ 5 ], + doc.getDocumentNode().children[ 2 ].children[ 0 ], + doc.getDocumentNode().children[ 2 ].children[ 1 ] + ], + expectedNodes = { + 'mwReference/': { + keyedNodes: { + 'auto/0': [ referenceNodes[ 0 ] ], + 'literal/bar': [ referenceNodes[ 1 ], referenceNodes[ 3 ] ], + 'literal/:3': [ referenceNodes[ 2 ] ], + 'auto/1': [ referenceNodes[ 4 ] ] + }, + firstNodes: [ + referenceNodes[ 0 ], + referenceNodes[ 1 ], + referenceNodes[ 2 ], + referenceNodes[ 4 ] + ], + indexOrder: [ 0, 1, 2, 3 ], + uniqueListKeys: {}, + uniqueListKeysInUse: {} + }, + 'mwReference/foo': { + keyedNodes: { + 'auto/2': [ referenceNodes[ 5 ] ] + }, + firstNodes: [ undefined, undefined, undefined, undefined, referenceNodes[ 5 ] ], + indexOrder: [ 4 ], + uniqueListKeys: {}, + uniqueListKeysInUse: {} + } + }; + + assert.deepEqualWithNodeTree( + doc.internalList.nodes, + expectedNodes, + 'Document construction populates internal list correctly' + ); + + newInternalList.addNode( 'mwReference/', 'auto/0', 0, referenceNodes[ 0 ] ); + newInternalList.addNode( 'mwReference/', 'literal/bar', 1, referenceNodes[ 1 ] ); + newInternalList.addNode( 'mwReference/', 'literal/:3', 2, referenceNodes[ 2 ] ); + newInternalList.addNode( 'mwReference/', 'literal/bar', 1, referenceNodes[ 3 ] ); + newInternalList.addNode( 'mwReference/', 'auto/1', 3, referenceNodes[ 4 ] ); + newInternalList.addNode( 'mwReference/foo', 'auto/2', 4, referenceNodes[ 5 ] ); + newInternalList.onTransact(); + + assert.deepEqualWithNodeTree( + newInternalList.nodes, + expectedNodes, + 'Nodes added in order' + ); + + newInternalList = new ve.dm.InternalList( doc ); + + newInternalList.addNode( 'mwReference/foo', 'auto/2', 4, referenceNodes[ 5 ] ); + newInternalList.addNode( 'mwReference/', 'auto/1', 3, referenceNodes[ 4 ] ); + newInternalList.addNode( 'mwReference/', 'literal/bar', 1, referenceNodes[ 3 ] ); + newInternalList.addNode( 'mwReference/', 'literal/:3', 2, referenceNodes[ 2 ] ); + newInternalList.addNode( 'mwReference/', 'literal/bar', 1, referenceNodes[ 1 ] ); + newInternalList.addNode( 'mwReference/', 'auto/0', 0, referenceNodes[ 0 ] ); + newInternalList.onTransact(); + + assert.deepEqualWithNodeTree( + newInternalList.nodes, + expectedNodes, + 'Nodes added in reverse order' + ); + + newInternalList.removeNode( 'mwReference/', 'literal/bar', 1, referenceNodes[ 1 ] ); + newInternalList.onTransact(); + + assert.deepEqualWithNodeTree( + newInternalList.nodes, + { + 'mwReference/': { + keyedNodes: { + 'auto/0': [ referenceNodes[ 0 ] ], + 'literal/bar': [ referenceNodes[ 3 ] ], + 'literal/:3': [ referenceNodes[ 2 ] ], + 'auto/1': [ referenceNodes[ 4 ] ] + }, + firstNodes: [ + referenceNodes[ 0 ], + referenceNodes[ 3 ], + referenceNodes[ 2 ], + referenceNodes[ 4 ] + ], + indexOrder: [ 0, 2, 1, 3 ], + uniqueListKeys: {}, + uniqueListKeysInUse: {} + }, + 'mwReference/foo': { + keyedNodes: { + 'auto/2': [ referenceNodes[ 5 ] ] + }, + firstNodes: [ undefined, undefined, undefined, undefined, referenceNodes[ 5 ] ], + indexOrder: [ 4 ], + uniqueListKeys: {}, + uniqueListKeysInUse: {} + } + }, + 'Keys re-ordered after one item of key removed' + ); + + newInternalList.removeNode( 'mwReference/', 'literal/bar', 1, referenceNodes[ 3 ] ); + newInternalList.onTransact(); + + assert.deepEqualWithNodeTree( + newInternalList.nodes, + { + 'mwReference/': { + keyedNodes: { + 'auto/0': [ referenceNodes[ 0 ] ], + 'literal/:3': [ referenceNodes[ 2 ] ], + 'auto/1': [ referenceNodes[ 4 ] ] + }, + firstNodes: [ + referenceNodes[ 0 ], + undefined, + referenceNodes[ 2 ], + referenceNodes[ 4 ] + ], + indexOrder: [ 0, 2, 3 ], + uniqueListKeys: {}, + uniqueListKeysInUse: {} + }, + 'mwReference/foo': { + keyedNodes: { + 'auto/2': [ referenceNodes[ 5 ] ] + }, + firstNodes: [ undefined, undefined, undefined, undefined, referenceNodes[ 5 ] ], + indexOrder: [ 4 ], + uniqueListKeys: {}, + uniqueListKeysInUse: {} + } + }, + 'Keys truncated after last item of key removed' + ); + + newInternalList.removeNode( 'mwReference/', 'auto/0', 0, referenceNodes[ 0 ] ); + newInternalList.removeNode( 'mwReference/foo', 'auto/2', 4, referenceNodes[ 5 ] ); + newInternalList.removeNode( 'mwReference/', 'auto/1', 3, referenceNodes[ 4 ] ); + newInternalList.removeNode( 'mwReference/', 'literal/:3', 2, referenceNodes[ 2 ] ); + newInternalList.onTransact(); + + assert.deepEqualWithNodeTree( + newInternalList.nodes, + { + 'mwReference/': { + keyedNodes: {}, + firstNodes: new Array( 4 ), + indexOrder: [], + uniqueListKeys: {}, + uniqueListKeysInUse: {} + }, + 'mwReference/foo': { + keyedNodes: {}, + firstNodes: new Array( 5 ), + indexOrder: [], + uniqueListKeys: {}, + uniqueListKeysInUse: {} + } + }, + 'All nodes removed' + ); +} ); + +QUnit.test( 'getItemInsertion', function ( assert ) { + var insertion, index, + doc = ve.dm.citeExample.createExampleDocument( 'references' ), + internalList = doc.getInternalList(); + + insertion = internalList.getItemInsertion( 'mwReference/', 'literal/foo', [] ); + index = internalList.getItemNodeCount(); + assert.strictEqual( insertion.index, index, 'Insertion creates a new reference' ); + assert.deepEqual( + insertion.transaction.getOperations(), + [ + { type: 'retain', length: 91 }, + { + type: 'replace', + remove: [], + insert: [ + { type: 'internalItem' }, + { type: '/internalItem' } + ] + }, + { type: 'retain', length: 1 } + ], + 'New reference operations match' ); + + insertion = internalList.getItemInsertion( 'mwReference/', 'literal/foo', [] ); + assert.strictEqual( insertion.index, index, 'Insertion with duplicate key reuses old index' ); + assert.strictEqual( insertion.transaction, null, 'Insertion with duplicate key has null transaction' ); +} ); + +QUnit.test( 'getUniqueListKey', function ( assert ) { + var generatedName, + doc = ve.dm.citeExample.createExampleDocument( 'references' ), + internalList = doc.getInternalList(); + + generatedName = internalList.getUniqueListKey( 'mwReference/', 'auto/0', 'literal/:' ); + assert.strictEqual( generatedName, 'literal/:0', '0 maps to 0' ); + generatedName = internalList.getUniqueListKey( 'mwReference/', 'auto/1', 'literal/:' ); + assert.strictEqual( generatedName, 'literal/:1', '1 maps to 1' ); + generatedName = internalList.getUniqueListKey( 'mwReference/', 'auto/2', 'literal/:' ); + assert.strictEqual( generatedName, 'literal/:2', '2 maps to 2' ); + generatedName = internalList.getUniqueListKey( 'mwReference/', 'auto/3', 'literal/:' ); + assert.strictEqual( generatedName, 'literal/:4', '3 maps to 4 (because a literal :3 is present)' ); + generatedName = internalList.getUniqueListKey( 'mwReference/', 'auto/4', 'literal/:' ); + assert.strictEqual( generatedName, 'literal/:5', '4 maps to 5' ); + + generatedName = internalList.getUniqueListKey( 'mwReference/', 'auto/0', 'literal/:' ); + assert.strictEqual( generatedName, 'literal/:0', 'Reusing a key reuses the name' ); + + generatedName = internalList.getUniqueListKey( 'mwReference/foo', 'auto/4', 'literal/:' ); + assert.strictEqual( generatedName, 'literal/:0', 'Different groups are treated separately' ); +} ); diff --git a/www/wiki/extensions/Cite/modules/ve-cite/tests/ve.dm.Transaction.test.js b/www/wiki/extensions/Cite/modules/ve-cite/tests/ve.dm.Transaction.test.js new file mode 100644 index 00000000..bf9f30bc --- /dev/null +++ b/www/wiki/extensions/Cite/modules/ve-cite/tests/ve.dm.Transaction.test.js @@ -0,0 +1,97 @@ +/*! + * VisualEditor DataModel Cite-specific Transaction tests. + * + * @copyright 2011-2018 VisualEditor Team's Cite sub-team and others; see AUTHORS.txt + * @license MIT + */ + +QUnit.module( 've.dm.Transaction (Cite)', ve.test.utils.mwEnvironment ); + +// FIXME: Duplicates test runner; should be using a data provider +QUnit.test( 'newFromDocumentInsertion with references', function ( assert ) { + var i, j, doc2, tx, actualStoreItems, expectedStoreItems, removalOps, doc, + complexDoc = ve.dm.citeExample.createExampleDocument( 'complexInternalData' ), + withReference = [ + { type: 'paragraph' }, + 'B', 'a', 'r', + { type: 'mwReference', attributes: { + mw: {}, + about: '#mwt4', + listIndex: 0, + listGroup: 'mwReference/', + listKey: 'auto/0', + refGroup: '', + contentsUsed: true + } }, + { type: '/mwReference' }, + { type: '/paragraph' }, + { type: 'internalList' }, + { type: 'internalItem' }, + { type: 'paragraph', internal: { generated: 'wrapper' } }, + 'B', + 'a', + 'z', + { type: '/paragraph' }, + { type: '/internalItem' }, + { type: '/internalList' } + ], + cases = [ + { + msg: 'inserting a brand new document; internal lists are merged and items renumbered', + doc: 'complexInternalData', + offset: 7, + newDocData: withReference, + removalOps: [], + expectedOps: [ + { type: 'retain', length: 7 }, + { + type: 'replace', + remove: [], + insert: withReference.slice( 0, 4 ) + // Renumber listIndex from 0 to 2 + // Renumber listKey from auto/0 to auto/1 + .concat( [ + ve.extendObject( true, {}, withReference[ 4 ], + { attributes: { listIndex: 2, listKey: 'auto/1' } } + ) + ] ) + .concat( withReference.slice( 5, 7 ) ) + }, + { type: 'retain', length: 1 }, + { + type: 'replace', + remove: complexDoc.getData( new ve.Range( 8, 32 ) ), + insert: complexDoc.getData( new ve.Range( 8, 32 ) ) + .concat( withReference.slice( 8, 15 ) ) + }, + { type: 'retain', length: 1 } + ] + } + ]; + + for ( i = 0; i < cases.length; i++ ) { + doc = ve.dm.citeExample.createExampleDocument( cases[ i ].doc ); + if ( cases[ i ].newDocData ) { + doc2 = new ve.dm.Document( cases[ i ].newDocData ); + removalOps = []; + } else if ( cases[ i ].range ) { + doc2 = doc.cloneFromRange( cases[ i ].range ); + cases[ i ].modify( doc2 ); + tx = ve.dm.TransactionBuilder.static.newFromRemoval( doc, cases[ i ].range, true ); + doc.commit( tx ); + removalOps = tx.getOperations(); + } + + assert.deepEqualWithDomElements( removalOps, cases[ i ].removalOps, cases[ i ].msg + ': removal' ); + + tx = ve.dm.TransactionBuilder.static.newFromDocumentInsertion( doc, cases[ i ].offset, doc2 ); + assert.deepEqualWithDomElements( tx.getOperations(), cases[ i ].expectedOps, cases[ i ].msg + ': transaction' ); + + actualStoreItems = []; + expectedStoreItems = cases[ i ].expectedStoreItems || []; + for ( j = 0; j < expectedStoreItems.length; j++ ) { + actualStoreItems[ j ] = doc.store.value( OO.getHash( expectedStoreItems[ j ] ) ); + } + assert.deepEqual( actualStoreItems, expectedStoreItems, cases[ i ].msg + ': store items' ); + } +} ); diff --git a/www/wiki/extensions/Cite/modules/ve-cite/tests/ve.dm.citeExample.js b/www/wiki/extensions/Cite/modules/ve-cite/tests/ve.dm.citeExample.js new file mode 100644 index 00000000..2fd8c7f4 --- /dev/null +++ b/www/wiki/extensions/Cite/modules/ve-cite/tests/ve.dm.citeExample.js @@ -0,0 +1,754 @@ +/*! + * VisualEditor DataModel Cite-specific example data sets. + * + * @copyright 2011-2018 VisualEditor Team's Cite sub-team and others; see AUTHORS.txt + * @license MIT + */ + +ve.dm.citeExample = {}; + +ve.dm.citeExample.createExampleDocument = function ( name, store ) { + return ve.dm.example.createExampleDocumentFromObject( name, store, ve.dm.citeExample ); +}; + +ve.dm.citeExample.domToDataCases = { + 'mw:Reference': { + // Wikitext: + // Foo<ref name="bar" /> Baz<ref group="g1" name=":0">Quux</ref> Whee<ref name="bar">[[Bar]]</ref> Yay<ref group="g1">No name</ref> Quux<ref name="bar">Different content</ref> Foo<ref group="g1" name="foo" /> + // <references group="g1"><ref group="g1" name="foo">Ref in refs</ref></references> + body: + '<p>Foo' + + '<sup about="#mwt1" class="reference" data-mw="{"name":"ref","attrs":{"name":"bar"}}" id="cite_ref-bar-1-0" rel="dc:references" typeof="mw:Extension/ref">' + + '<a href="#cite_note-bar-1">[1]</a>' + + '</sup>' + + ' Baz' + + '<sup about="#mwt2" class="reference" data-mw="{"name":"ref","body":{"html":"Quux"},"attrs":{"group":"g1","name":":0"}}" id="cite_ref-quux-2-0" rel="dc:references" typeof="mw:Extension/ref">' + + '<a href="#cite_note-.3A0-2">[g1 1]</a>' + + '</sup>' + + ' Whee' + + '<sup about="#mwt3" class="reference" data-mw="{"name":"ref","body":{"html":"' + + '<a rel=\\"mw:WikiLink\\" href=\\"./Bar\\">Bar' + + '</a>"},"attrs":{"name":"bar"}}" id="cite_ref-bar-1-1" rel="dc:references" typeof="mw:Extension/ref">' + + '<a href="#cite_note-bar-1">[1]</a>' + + '</sup>' + + ' Yay' + + // This reference has .body.id instead of .body.html + '<sup about="#mwt4" class="reference" data-mw="{"name":"ref","body":{"id":"mw-cite-3"},"attrs":{"group":"g1"}}" id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref">' + + '<a href="#cite_note-3">[g1 2]</a>' + + '</sup>' + + ' Quux' + + '<sup about="#mwt5" class="reference" data-mw="{"name":"ref","body":{"html":"Different content"},"attrs":{"name":"bar"}}" id="cite_ref-bar-1-2" rel="dc:references" typeof="mw:Extension/ref">' + + '<a href="#cite_note-bar-1">[1]</a>' + + '</sup>' + + ' Foo' + + '<sup about="#mwt6" class="reference" data-mw="{"name":"ref","attrs":{"group":"g1","name":"foo"}}" ' + + 'id="cite_ref-foo-4" rel="dc:references" typeof="mw:Extension/ref">' + + '<a href="#cite_ref-foo-4">[g1 3]</a>' + + '</sup>' + + '</p>' + + // The HTML below is enriched to wrap reference contents in <span id="mw-cite-[...]"> + // which Parsoid doesn't do yet, but T88290 asks for + '<ol class="references" typeof="mw:Extension/references" about="#mwt7"' + + 'data-mw="{"name":"references","body":{' + + '"html":"<sup about=\\"#mwt8\\" class=\\"reference\\" ' + + 'data-mw=\\"{&quot;name&quot;:&quot;ref&quot;,&quot;body&quot;:{&quot;html&quot;:&quot;Ref in refs&quot;},' + + '&quot;attrs&quot;:{&quot;group&quot;:&quot;g1&quot;,&quot;name&quot;:&quot;foo&quot;}}\\" ' + + 'rel=\\"dc:references\\" typeof=\\"mw:Extension/ref\\">' + + '<a href=\\"#cite_note-foo-3\\">[3]</a></sup>"},"attrs":{"group":"g1"}}">' + + '<li about="#cite_note-.3A0-2" id="cite_note-.3A0-2"><span rel="mw:referencedBy"><a href="#cite_ref-.3A0_2-0">↑</a></span> <span id="mw-cite-:0">Quux</span></li>' + + '<li about="#cite_note-3" id="cite_note-3"><span rel="mw:referencedBy"><a href="#cite_ref-3">↑</a></span> <span id="mw-cite-3">No name</span></li>' + + '<li about="#cite_note-foo-4" id="cite_note-foo-4"><span rel="mw:referencedBy"><a href="#cite_ref-foo_4-0">↑</a></span> <span id="mw-cite-foo">Ref in refs</span></li>' + + '</ol>', + fromDataBody: + '<p>Foo' + + '<sup data-mw="{"name":"ref","attrs":{"name":"bar"}}" typeof="mw:Extension/ref">' + + '</sup>' + + ' Baz' + + '<sup data-mw="{"name":"ref","body":{"html":"Quux"},"attrs":{"group":"g1","name":":0"}}" typeof="mw:Extension/ref">' + + '</sup>' + + ' Whee' + + '<sup data-mw="{"name":"ref","body":{"html":"' + + '<a rel=\\"mw:WikiLink\\" href=\\"./Bar\\">Bar' + + '</a>"},"attrs":{"name":"bar"}}" typeof="mw:Extension/ref">' + + '</sup>' + + ' Yay' + + '<sup data-mw="{"name":"ref","body":{"id":"mw-cite-3"},"attrs":{"group":"g1"}}" typeof="mw:Extension/ref">' + + '</sup>' + + ' Quux' + + '<sup data-mw="{"name":"ref","body":{"html":"Different content"},"attrs":{"name":"bar"}}" typeof="mw:Extension/ref">' + + '</sup>' + + ' Foo' + + '<sup data-mw="{"name":"ref","attrs":{"group":"g1","name":"foo"}}" ' + + 'typeof="mw:Extension/ref">' + + '</sup>' + + '</p>' + + '<div typeof="mw:Extension/references" ' + + 'data-mw="{"name":"references","attrs":{"group":"g1"},"body":{' + + '"html":"<sup typeof=\\"mw:Extension/ref\\" ' + + 'data-mw=\\"{&quot;name&quot;:&quot;ref&quot;,&quot;body&quot;:{&quot;html&quot;:&quot;Ref in refs&quot;},' + + '&quot;attrs&quot;:{&quot;group&quot;:&quot;g1&quot;,&quot;name&quot;:&quot;foo&quot;}}\\">' + + '</sup>"}}">' + + '</div>', + clipboardBody: + '<p>Foo' + + '<sup typeof="mw:Extension/ref" data-mw="{"name":"ref","attrs":{"name":"bar"}}" class="mw-ref">' + + '<a style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a>' + + '</sup>' + + ' Baz' + + '<sup typeof="mw:Extension/ref" data-mw="{"name":"ref","body":{"html":"Quux"},"attrs":{"group":"g1","name":":0"}}" class="mw-ref">' + + '<a data-mw-group="g1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[g1 1]</span></a>' + + '</sup>' + + ' Whee' + + '<sup typeof="mw:Extension/ref" data-mw="{"name":"ref","body":{"html":"' + + '<a href=\\"./Bar\\" rel=\\"mw:WikiLink\\">Bar' + + '</a>"},"attrs":{"name":"bar"}}" class="mw-ref">' + + '<a style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a>' + + '</sup>' + + ' Yay' + + // This reference has .body.id instead of .body.html + '<sup typeof="mw:Extension/ref" data-mw="{"name":"ref","body":{"id":"mw-cite-3","html":"No name"},"attrs":{"group":"g1"}}" class="mw-ref">' + + '<a data-mw-group="g1" style="counter-reset: mw-Ref 2;"><span class="mw-reflink-text">[g1 2]</span></a>' + + '</sup>' + + ' Quux' + + '<sup typeof="mw:Extension/ref" data-mw="{"name":"ref","body":{"html":"Different content"},"attrs":{"name":"bar"}}" class="mw-ref">' + + '<a style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a>' + + '</sup>' + + ' Foo' + + '<sup typeof="mw:Extension/ref" data-mw="{"name":"ref","attrs":{"group":"g1","name":"foo"}}" class="mw-ref">' + + '<a data-mw-group="g1" style="counter-reset: mw-Ref 3;"><span class="mw-reflink-text">[g1 3]</span></a>' + + '</sup>' + + '</p>' + + // The HTML below is enriched to wrap reference contents in <span id="mw-cite-[...]"> + // which Parsoid doesn't do yet, but T88290 asks for + '<div typeof="mw:Extension/references" ' + + 'data-mw="{"name":"references","attrs":{"group":"g1"},"body":{' + + '"html":"<sup typeof=\\"mw:Extension/ref\\" ' + + 'data-mw=\\"{&quot;name&quot;:&quot;ref&quot;,&quot;attrs&quot;:{&quot;group&quot;:&quot;g1&quot;,&quot;name&quot;:&quot;foo&quot;},&quot;body&quot;:{&quot;html&quot;:&quot;Ref in refs&quot;}}' + + '\\" class=\\"mw-ref\\"><a data-mw-group=\\"g1\\" style=\\"counter-reset: mw-Ref 3;\\"><span class=\\"mw-reflink-text\\">[g1 3]</span></a></sup>"}}">' + + '<ol class="mw-references references" data-mw-group="g1">' + + '<li>' + + '<a rel="mw:referencedBy" data-mw-group="g1"><span class="mw-linkback-text">↑ </span></a>' + + '<span class="reference-text"><span class="ve-ce-branchNode ve-ce-internalItemNode">Quux</span></span>' + + '</li>' + + '<li>' + + '<a rel="mw:referencedBy" data-mw-group="g1"><span class="mw-linkback-text">↑ </span></a>' + + '<span class="reference-text"><span class="ve-ce-branchNode ve-ce-internalItemNode">No name</span></span>' + + '</li>' + + '<li>' + + '<a rel="mw:referencedBy" data-mw-group="g1"><span class="mw-linkback-text">↑ </span></a>' + + '<span class="reference-text"><span class="ve-ce-branchNode ve-ce-internalItemNode">Ref in refs</span></span>' + + '</li>' + + '</ol>' + + '</div>', + head: '<base href="http://example.com" />', + data: [ + { type: 'paragraph' }, + 'F', 'o', 'o', + { + type: 'mwReference', + attributes: { + listIndex: 0, + listGroup: 'mwReference/', + listKey: 'literal/bar', + refGroup: '', + mw: { name: 'ref', attrs: { name: 'bar' } }, + originalMw: '{"name":"ref","attrs":{"name":"bar"}}', + contentsUsed: false + } + }, + { type: '/mwReference' }, + ' ', 'B', 'a', 'z', + { + type: 'mwReference', + attributes: { + listIndex: 1, + listGroup: 'mwReference/g1', + listKey: 'literal/:0', + refGroup: 'g1', + mw: { name: 'ref', body: { html: 'Quux' }, attrs: { group: 'g1', name: ':0' } }, + originalMw: '{"name":"ref","body":{"html":"Quux"},"attrs":{"group":"g1","name":":0"}}', + contentsUsed: true + } + }, + { type: '/mwReference' }, + ' ', 'W', 'h', 'e', 'e', + { + type: 'mwReference', + attributes: { + listIndex: 0, + listGroup: 'mwReference/', + listKey: 'literal/bar', + refGroup: '', + mw: { name: 'ref', body: { html: '<a rel="mw:WikiLink" href="./Bar">Bar</a>' }, attrs: { name: 'bar' } }, + originalMw: '{"name":"ref","body":{"html":"<a rel=\\"mw:WikiLink\\" href=\\"./Bar\\">Bar</a>"},"attrs":{"name":"bar"}}', + contentsUsed: true + } + }, + { type: '/mwReference' }, + ' ', 'Y', 'a', 'y', + { + type: 'mwReference', + attributes: { + listIndex: 2, + listGroup: 'mwReference/g1', + listKey: 'auto/0', + refGroup: 'g1', + mw: { name: 'ref', body: { id: 'mw-cite-3' }, attrs: { group: 'g1' } }, + originalMw: '{"name":"ref","body":{"id":"mw-cite-3"},"attrs":{"group":"g1"}}', + contentsUsed: true, + refListItemId: 'mw-cite-3' + } + }, + { type: '/mwReference' }, + ' ', 'Q', 'u', 'u', 'x', + { + type: 'mwReference', + attributes: { + listIndex: 0, + listGroup: 'mwReference/', + listKey: 'literal/bar', + refGroup: '', + mw: { name: 'ref', body: { html: 'Different content' }, attrs: { name: 'bar' } }, + originalMw: '{"name":"ref","body":{"html":"Different content"},"attrs":{"name":"bar"}}', + contentsUsed: false + } + }, + { type: '/mwReference' }, + ' ', 'F', 'o', 'o', + { + type: 'mwReference', + attributes: { + listGroup: 'mwReference/g1', + listIndex: 3, + listKey: 'literal/foo', + refGroup: 'g1', + mw: { name: 'ref', attrs: { group: 'g1', name: 'foo' } }, + originalMw: '{"name":"ref","attrs":{"group":"g1","name":"foo"}}', + contentsUsed: false + } + }, + { type: '/mwReference' }, + { type: '/paragraph' }, + { + type: 'mwReferencesList', + attributes: { + mw: { + name: 'references', + attrs: { group: 'g1' }, + body: { + html: '<sup about="#mwt8" class="reference" data-mw="{"name":"ref","body":{"html":"Ref in refs"},"attrs":{"group":"g1","name":"foo"}}" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-foo-3">[3]</a></sup>' + } + }, + originalMw: '{"name":"references","body":{"html":"<sup about=\\"#mwt8\\" class=\\"reference\\" data-mw=\\"{"name":"ref","body":{"html":"Ref in refs"},"attrs":{"group":"g1","name":"foo"}}\\" rel=\\"dc:references\\" typeof=\\"mw:Extension/ref\\"><a href=\\"#cite_note-foo-3\\">[3]</a></sup>"},"attrs":{"group":"g1"}}', + listGroup: 'mwReference/g1', + refGroup: 'g1', + isResponsive: true, + templateGenerated: false + } + }, + { type: 'paragraph', internal: { generated: 'wrapper' } }, + { + type: 'mwReference', + attributes: { + contentsUsed: true, + listGroup: 'mwReference/g1', + listIndex: 3, + listKey: 'literal/foo', + mw: { name: 'ref', attrs: { group: 'g1', name: 'foo' }, body: { html: 'Ref in refs' } }, + originalMw: '{"name":"ref","body":{"html":"Ref in refs"},"attrs":{"group":"g1","name":"foo"}}', + refGroup: 'g1' + } + }, + { type: '/mwReference' }, + { type: '/paragraph' }, + { type: '/mwReferencesList' }, + { type: 'internalList' }, + { type: 'internalItem', attributes: { originalHtml: '<a rel="mw:WikiLink" href="./Bar">Bar</a>' } }, + { type: 'paragraph', internal: { generated: 'wrapper' } }, + [ + 'B', + [ { + type: 'link/mwInternal', + attributes: { + title: 'Bar', + origTitle: 'Bar', + normalizedTitle: 'Bar', + lookupTitle: 'Bar', + hrefPrefix: './' + } + } ] + ], + [ + 'a', + [ { + type: 'link/mwInternal', + attributes: { + title: 'Bar', + origTitle: 'Bar', + normalizedTitle: 'Bar', + lookupTitle: 'Bar', + hrefPrefix: './' + } + } ] + ], + [ + 'r', + [ { + type: 'link/mwInternal', + attributes: { + title: 'Bar', + origTitle: 'Bar', + normalizedTitle: 'Bar', + lookupTitle: 'Bar', + hrefPrefix: './' + } + } ] + ], + { type: '/paragraph' }, + { type: '/internalItem' }, + { type: 'internalItem', attributes: { originalHtml: 'Quux' } }, + { type: 'paragraph', internal: { generated: 'wrapper' } }, + 'Q', 'u', 'u', 'x', + { type: '/paragraph' }, + { type: '/internalItem' }, + { type: 'internalItem', attributes: { originalHtml: 'No name' } }, + { type: 'paragraph', internal: { generated: 'wrapper' } }, + 'N', 'o', ' ', 'n', 'a', 'm', 'e', + { type: '/paragraph' }, + { type: '/internalItem' }, + { type: 'internalItem', attributes: { originalHtml: 'Ref in refs' } }, + { type: 'paragraph', internal: { generated: 'wrapper' } }, + 'R', 'e', 'f', ' ', 'i', 'n', ' ', 'r', 'e', 'f', 's', + { type: '/paragraph' }, + { type: '/internalItem' }, + { type: '/internalList' } + ] + }, + 'mw:Reference with comment': { + body: '<p><sup about="#mwt2" class="reference" ' + + 'data-mw="{"name":"ref","body":' + + '{"html":"Foo<!-- bar -->"},"attrs":{}}" ' + + 'id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref">' + + '<a href="#cite_note-bar-1">[1]</a></sup></p>', + fromDataBody: '<p><sup ' + + 'data-mw="{"name":"ref","body":' + + '{"html":"Foo<!-- bar -->"},"attrs":{}}" ' + + 'typeof="mw:Extension/ref"></sup></p>', + clipboardBody: '<p><sup typeof="mw:Extension/ref" ' + + 'data-mw="{"attrs":{},"body":' + + '{"html":"Foo<span rel=\\"ve:Comment\\" data-ve-comment=\\" bar \\">&nbsp;</span>"},"name":"ref"}" ' + + ' class="mw-ref">' + + '<a style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></sup></p>', + head: '<base href="http://example.com" />', + data: [ + { type: 'paragraph' }, + { + type: 'mwReference', + attributes: { + contentsUsed: true, + listGroup: 'mwReference/', + listIndex: 0, + listKey: 'auto/0', + mw: { + attrs: {}, + body: { + html: 'Foo<!-- bar -->' + }, + name: 'ref' + }, + originalMw: '{"name":"ref","body":{"html":"Foo<!-- bar -->"},"attrs":{}}', + refGroup: '' + } + }, + { type: '/mwReference' }, + { type: '/paragraph' }, + { type: 'internalList' }, + { type: 'internalItem', attributes: { originalHtml: 'Foo<!-- bar -->' } }, + { + internal: { + generated: 'wrapper' + }, + type: 'paragraph' + }, + 'F', 'o', 'o', + { + type: 'comment', + attributes: { + text: ' bar ' + } + }, + { type: '/comment' }, + { type: '/paragraph' }, + { type: '/internalItem' }, + { type: '/internalList' } + ] + }, + 'Template generated reflist': { + body: '<p><sup about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw="{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{"group":"notes"}}"><a href="./Main_Page#cite_note-1" style="counter-reset: mw-Ref 1;" data-mw-group="notes"><span class="mw-reflink-text">[notes 1]</span></a></sup></p>' + + '<div class="mw-references-wrap" typeof="mw:Extension/references mw:Transclusion" about="#mwt4" data-mw="{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<references group=\\"notes\\" />"}},"i":0}}]}">' + + '<ol class="mw-references references" data-mw-group="notes">' + + '<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" data-mw-group="notes" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">Foo</span></li>' + + '</ol>' + + '</div>', + fromDataBody: '<p><sup typeof="mw:Extension/ref" data-mw="{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{"group":"notes"}}"></sup></p>' + + '<span typeof="mw:Transclusion" data-mw="{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<references group=\\"notes\\" />"}},"i":0}}]}"></span>', + clipboardBody: '<p><sup typeof="mw:Extension/ref" data-mw="{"attrs":{"group":"notes"},"body":{"id":"mw-reference-text-cite_note-1","html":"Foo"},"name":"ref"}" class="mw-ref"><a data-mw-group="notes" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[notes 1]</span></a></sup></p>' + + '<div typeof="mw:Extension/references" data-mw="{"parts":[{"template":{"params":{"1":{"wt":"<references group=\\"notes\\" />"}},"target":{"wt":"echo","href":"./Template:Echo"},"i":0}}],"name":"references"}">' + + // TODO: This should list should get populated on copy + '<ol class="mw-references references"></ol>' + + '</div>', + data: [ + { type: 'paragraph' }, + { + type: 'mwReference', + attributes: { + contentsUsed: true, + listGroup: 'mwReference/notes', + listIndex: 0, + listKey: 'auto/0', + mw: { + attrs: { + group: 'notes' + }, + body: { + id: 'mw-reference-text-cite_note-1' + }, + name: 'ref' + }, + originalMw: '{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{"group":"notes"}}', + refGroup: 'notes', + refListItemId: 'mw-reference-text-cite_note-1' + } + }, + { type: '/mwReference' }, + { type: '/paragraph' }, + { + type: 'mwReferencesList', + attributes: { + mw: { + parts: [ { + template: { + params: { + 1: { wt: '<references group="notes" />' } + }, + target: { wt: 'echo', href: './Template:Echo' }, + i: 0 + } + } ] + }, + originalMw: '{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<references group=\\"notes\\" />"}},"i":0}}]}', + refGroup: '', + listGroup: 'mwReference/', + isResponsive: true, + templateGenerated: true + } + }, + { type: '/mwReferencesList' }, + { type: 'internalList' }, + { type: 'internalItem', attributes: { originalHtml: 'Foo' } }, + { + internal: { + generated: 'wrapper' + }, + type: 'paragraph' + }, + 'F', 'o', 'o', + { type: '/paragraph' }, + { type: '/internalItem' }, + { type: '/internalList' } + ] + }, + 'Template generated reflist (div wrapped)': { + body: '<p><sup about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw="{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}"><a href="./Main_Page#cite_note-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></sup></p>' + + '<div about="#mwt3" typeof="mw:Transclusion" data-mw="{"parts":[{"template":{"target":{"wt":"reflist","href":"./Template:Reflist"},"params":{},"i":0}}]}">' + + '<div typeof="mw:Extension/references" about="#mwt5" data-mw="{"name":"references","attrs":{}}">' + + '<ol class="mw-references references">' + + '<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">Foo</span></li>' + + '</ol>' + + '</div>' + + '</div>', + fromDataBody: '<p><sup typeof="mw:Extension/ref" data-mw="{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}"></sup></p>' + + '<span typeof="mw:Transclusion" data-mw="{"name":"references","attrs":{}}"></span>', + clipboardBody: '<p><sup typeof="mw:Extension/ref" data-mw="{"attrs":{},"body":{"id":"mw-reference-text-cite_note-1","html":"Foo"},"name":"ref"}" class="mw-ref"><a style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></sup></p>' + + '<div typeof="mw:Extension/references" data-mw="{"name":"references","attrs":{}}">' + + '<ol class="mw-references references">' + + '<li><a rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a><span class="reference-text"><span class="ve-ce-branchNode ve-ce-internalItemNode">Foo</span></span></li>' + + '</ol>' + + '</div>', + data: [ + { type: 'paragraph' }, + { + type: 'mwReference', + attributes: { + contentsUsed: true, + listGroup: 'mwReference/', + listIndex: 0, + listKey: 'auto/0', + mw: { + attrs: {}, + body: { + id: 'mw-reference-text-cite_note-1' + }, + name: 'ref' + }, + originalMw: '{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}', + refGroup: '', + refListItemId: 'mw-reference-text-cite_note-1' + } + }, + { type: '/mwReference' }, + { type: '/paragraph' }, + { + type: 'mwReferencesList', + attributes: { + mw: { + name: 'references', + attrs: {} + }, + originalMw: '{"name":"references","attrs":{}}', + refGroup: '', + listGroup: 'mwReference/', + isResponsive: true, + templateGenerated: true + } + }, + { type: '/mwReferencesList' }, + { type: 'internalList' }, + { type: 'internalItem', attributes: { originalHtml: 'Foo' } }, + { + internal: { + generated: 'wrapper' + }, + type: 'paragraph' + }, + 'F', 'o', 'o', + { type: '/paragraph' }, + { type: '/internalItem' }, + { type: '/internalList' } + ] + } +}; + +ve.dm.citeExample.references = [ + { type: 'paragraph' }, + { + type: 'mwReference', + attributes: { + contentsUsed: true, + listGroup: 'mwReference/', + listIndex: 0, + listKey: 'auto/0', + mw: { + attrs: {}, + body: { html: 'No name 1' }, + name: 'ref' + }, + originalMw: '{"name":"ref","body":{"html":"No name 1"},"attrs":{}}', + refGroup: '' + } + }, + { type: '/mwReference' }, + { type: '/paragraph' }, + { type: 'paragraph' }, + 'F', 'o', 'o', + { + type: 'mwReference', + attributes: { + contentsUsed: true, + listGroup: 'mwReference/', + listIndex: 1, + listKey: 'literal/bar', + mw: { + attrs: { name: 'bar' }, + body: { html: 'Bar' }, + name: 'ref' + }, + originalMw: '{"body":{"html":""},"attrs":{"name":"bar"}}', + refGroup: '' + } + }, + { type: '/mwReference' }, + ' ', 'B', 'a', 'z', + { + type: 'mwReference', + attributes: { + contentsUsed: true, + listGroup: 'mwReference/', + listIndex: 2, + listKey: 'literal/:3', + mw: { + attrs: { name: ':3' }, + body: { html: 'Quux' }, + name: 'ref' + }, + originalMw: '{"name":"ref","body":{"html":"Quux"},"attrs":{"name":":3"}}', + refGroup: '' + } + }, + { type: '/mwReference' }, + ' ', 'W', 'h', 'e', 'e', + { + type: 'mwReference', + attributes: { + contentsUsed: false, + listGroup: 'mwReference/', + listIndex: 1, + listKey: 'literal/bar', + mw: { + attrs: { name: 'bar' }, + name: 'ref' + }, + originalMw: '{"body":{"html":""},"attrs":{"name":"bar"}}', + refGroup: '' + } + }, + { type: '/mwReference' }, + ' ', 'Y', 'a', 'y', + { type: '/paragraph' }, + { type: 'paragraph' }, + { + type: 'mwReference', + attributes: { + contentsUsed: true, + listGroup: 'mwReference/', + listIndex: 3, + listKey: 'auto/1', + mw: { + attrs: {}, + body: { html: 'No name 2' }, + name: 'ref' + }, + originalMw: '{"name":"ref","body":{"html":"No name 2"},"attrs":{}}', + refGroup: '' + } + }, + { type: '/mwReference' }, + { + type: 'mwReference', + attributes: { + contentsUsed: true, + listGroup: 'mwReference/foo', + listIndex: 4, + listKey: 'auto/2', + mw: { + attrs: { group: 'foo' }, + body: { html: 'No name 3' }, + name: 'ref' + }, + originalMw: '{"name":"ref","body":{"html":"No name 3"},"attrs":{"group":"foo"}}', + refGroup: 'foo' + } + }, + { type: '/mwReference' }, + { type: '/paragraph' }, + { + type: 'mwReferencesList', + // originalDomElements: HTML, + attributes: { + mw: { + name: 'references', + attrs: { group: 'g1' } + }, + originalMw: '{"name":"references","attrs":{"group":"g1"}"}', + listGroup: 'mwReference/', + refGroup: '', + isResponsive: true, + templateGenerated: false + } + }, + { type: '/mwReferencesList' }, + { type: 'internalList' }, + { type: 'internalItem' }, + { type: 'paragraph' }, + 'N', 'o', ' ', 'n', 'a', 'm', 'e', ' ', '1', + { type: '/paragraph' }, + { type: '/internalItem' }, + { type: 'internalItem' }, + { type: 'paragraph' }, + 'B', 'a', 'r', + { type: '/paragraph' }, + { type: '/internalItem' }, + { type: 'internalItem' }, + { type: 'paragraph' }, + 'Q', 'u', 'u', 'x', + { type: '/paragraph' }, + { type: '/internalItem' }, + { type: 'internalItem' }, + { type: 'paragraph' }, + 'N', 'o', ' ', 'n', 'a', 'm', 'e', ' ', '2', + { type: '/paragraph' }, + { type: '/internalItem' }, + { type: 'internalItem' }, + { type: 'paragraph' }, + 'N', 'o', ' ', 'n', 'a', 'm', 'e', ' ', '3', + { type: '/paragraph' }, + { type: '/internalItem' }, + { type: '/internalList' } +]; + +ve.dm.citeExample.complexInternalData = [ + // 0 + { type: 'paragraph' }, + 'F', [ 'o', [ ve.dm.example.bold ] ], [ 'o', [ ve.dm.example.italic ] ], + // 4 + { type: 'mwReference', attributes: { + about: '#mwt1', + listIndex: 0, + listGroup: 'mwReference/', + listKey: 'auto/0', + refGroup: '' + } }, + // 5 + { type: '/mwReference' }, + // 6 + { type: '/paragraph' }, + // 7 + { type: 'internalList' }, + // 8 + { type: 'internalItem' }, + // 9 + { type: 'paragraph', internal: { generated: 'wrapper' } }, + 'R', [ 'e', [ ve.dm.example.bold ] ], 'f', + // 13 + 'e', [ 'r', [ ve.dm.example.italic ] ], [ 'e', [ ve.dm.example.italic ] ], + // 16 + { type: 'mwReference', attributes: { + mw: {}, + about: '#mwt2', + listIndex: 1, + listGroup: 'mwReference/', + listKey: 'foo', + refGroup: '', + contentsUsed: true + } }, + // 17 + { type: '/mwReference' }, + 'n', 'c', 'e', + // 21 + { type: '/paragraph' }, + // 22 + { type: '/internalItem' }, + // 23 + { type: 'internalItem' }, + // 24 + { type: 'preformatted' }, + // 25 + { type: 'mwEntity', attributes: { character: '€' } }, + // 26 + { type: '/mwEntity' }, + '2', '5', '0', + // 30 + { type: '/preformatted' }, + // 31 + { type: '/internalItem' }, + // 32 + { type: '/internalList' } + // 33 +]; + +ve.dm.citeExample.complexInternalData.internalItems = [ + { group: 'mwReference', key: null, body: 'First reference' }, + { group: 'mwReference', key: 'foo', body: 'Table in ref: <table><tr><td>because I can</td></tr></table>' } +]; + +ve.dm.citeExample.complexInternalData.internalListNextUniqueNumber = 1; diff --git a/www/wiki/extensions/Cite/modules/ve-cite/tests/ve.ui.DiffElement.test.js b/www/wiki/extensions/Cite/modules/ve-cite/tests/ve.ui.DiffElement.test.js new file mode 100644 index 00000000..79b4497b --- /dev/null +++ b/www/wiki/extensions/Cite/modules/ve-cite/tests/ve.ui.DiffElement.test.js @@ -0,0 +1,67 @@ +/*! + * VisualEditor Cite-specific DiffElement tests. + * + * @copyright 2011-2018 VisualEditor Team and others; see http://ve.mit-license.org + */ + +QUnit.module( 've.ui.DiffElement (Cite)' ); + +QUnit.test( 'Diffing', function ( assert ) { + var i, len, + // spacer = '<div class="ve-ui-diffElement-spacer">⋮</div>', + ref = function ( text, num, name ) { + var dataMw = { + name: 'ref', + body: { html: text } + }; + if ( name ) { + dataMw.attrs = { name: name }; + } + return '<sup typeof="mw:Extension/ref" data-mw="' + JSON.stringify( dataMw ).replace( /"/g, '"' ) + '" class="mw-ref">' + + '<a style="counter-reset: mw-Ref ' + num + ';"><span class="mw-reflink-text">[' + num + ']</span></a>' + + '</sup>'; + }, + cases = [ + { + msg: 'Simple ref change', + oldDoc: + '<p>' + ref( 'Foo' ) + ref( 'Bar' ) + ref( 'Baz' ) + '</p>' + + '<h2>Notes</h2>' + + '<div typeof="mw:Extension/references" data-mw="{"name":"references"}"></div>', + newDoc: + '<p>' + ref( 'Foo' ) + ref( 'Bar ish' ) + ref( 'Baz' ) + '</p>' + + '<h2>Notes</h2>' + + '<div typeof="mw:Extension/references" data-mw="{"name":"references"}"></div>', + expected: + '<div class="ve-ui-diffElement-doc-child-change">' + + '<p>' + + ref( 'Foo', '1' ) + + '<span data-diff-action="change-remove">' + + ref( 'Bar', '2', ':0' ) + + '</span>' + + '<span data-diff-action="change-insert">' + + ref( 'Bar ish', '2', ':0' ) + + '</span>' + + ref( 'Baz', '3' ) + + '</p>' + + '</div>' + + '<h2 data-diff-action="none">Notes</h2>' + + '<div class="ve-ui-diffElement-doc-child-change" data-diff-move="undefined">' + + '<ol start="1">' + + '<li><p data-diff-action="none">Foo</p></li>' + + '</ol>' + + '<ol start="2">' + + '<li><div class="ve-ui-diffElement-doc-child-change">Bar<ins data-diff-action="insert"> ish</ins></div></li>' + + '</ol>' + + '<ol start="3">' + + '<li><p data-diff-action="none">Baz</p></li>' + + '</ol>' + + '</div>' + } + ]; + + for ( i = 0, len = cases.length; i < len; i++ ) { + ve.test.utils.runDiffElementTest( assert, cases[ i ] ); + } + +} ); diff --git a/www/wiki/extensions/Cite/modules/ve-cite/tests/ve.ui.MWWikitextStringTransferHandler.test.js b/www/wiki/extensions/Cite/modules/ve-cite/tests/ve.ui.MWWikitextStringTransferHandler.test.js new file mode 100644 index 00000000..210dd49c --- /dev/null +++ b/www/wiki/extensions/Cite/modules/ve-cite/tests/ve.ui.MWWikitextStringTransferHandler.test.js @@ -0,0 +1,95 @@ +/*! + * VisualEditor UserInterface MWWikitextStringTransferHandler tests. + * + * @copyright 2011-2018 VisualEditor Team's Cite sub-team and others; see AUTHORS.txt + * @license MIT + */ + +window.MWWIKITEXT_MOCK_API = true; + +QUnit.module( 've.ui.MWWikitextStringTransferHandler (Cite)', QUnit.newMwEnvironment( { + beforeEach: function () { + // Mock XHR for mw.Api() + this.server = window.MWWIKITEXT_MOCK_API ? this.sandbox.useFakeServer() : null; + ve.test.utils.mwEnvironment.setup.call( this ); + }, + afterEach: ve.test.utils.mwEnvironment.teardown +} ) ); + +/* Tests */ + +QUnit.test( 'convert', function ( assert ) { + var i, + cases = [ + { + msg: 'Simple reference', + pasteString: '<ref>Foo</ref>', + pasteType: 'text/plain', + parsoidResponse: '<p><span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw=\'{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}\'>[1]</span></p>' + + '<ol class="mw-references" typeof="mw:Extension/references" about="#mwt3" data-mw=\'{"name":"references","attrs":{},"autoGenerated":true}\'>' + + '<li about="#cite_note-1" id="cite_note-1">↑ <span id="mw-reference-text-cite_note-1" class="mw-reference-text">Foo</span></li>' + + '</ol>', + annotations: [], + expectedData: [ + { + type: 'mwReference', + attributes: { + mw: { + attrs: {}, + body: { + id: 'mw-reference-text-cite_note-1' + }, + name: 'ref' + }, + contentsUsed: true, + listGroup: 'mwReference/', + listIndex: 0, + listKey: 'auto/0', + originalMw: '{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}', + refGroup: '', + refListItemId: 'mw-reference-text-cite_note-1' + } + }, + { type: '/mwReference' }, + { type: 'internalList' }, + { type: 'internalItem' }, + { type: 'paragraph', internal: { generated: 'wrapper' } }, + 'F', 'o', 'o', + { type: '/paragraph' }, + { type: '/internalItem' }, + { type: '/internalList' } + ] + }, + { + msg: 'Reference template with autoGenerated content', + pasteString: '{{reference}}', + pasteType: 'text/plain', + parsoidResponse: '<p><span typeof="mw:Transclusion">[1]</span></p>' + + '<ol class="mw-references" typeof="mw:Extension/references" about="#mwt3" data-mw=\'{"name":"references","attrs":{},"autoGenerated":true}\'>' + + '<li>Reference list</li>' + + '</ol>', + annotations: [], + expectedData: [ + { + type: 'mwTransclusionInline', + attributes: { + mw: {}, + originalMw: null + } + }, + { + type: '/mwTransclusionInline' + }, + { type: 'internalList' }, + { type: '/internalList' } + ] + } + ]; + + for ( i = 0; i < cases.length; i++ ) { + ve.test.utils.runWikitextStringHandlerTest( + assert, this.server, cases[ i ].pasteString, cases[ i ].pasteType, cases[ i ].parsoidResponse, + cases[ i ].expectedData, cases[ i ].annotations, cases[ i ].assertDom, cases[ i ].msg + ); + } +} ); |