/*! * VisualEditor UserInterface MWWikitextStringTransferHandler tests. * * @copyright See AUTHORS.txt */ QUnit.module( 've.ui.MWWikitextStringTransferHandler', ve.test.utils.newMwEnvironment( { beforeEach() { // Mock XHR for mw.Api() this.server = this.sandbox.useFakeServer(); // Random number, chosen by a fair dice roll. // Used to make #mwt ID deterministic this.randomStub = sinon.stub( Math, 'random' ).returns( 0.04 ); }, afterEach() { this.randomStub.restore(); } } ) ); ve.test.utils.runWikitextStringHandlerTest = ( assert, server, string, mimeType, expectedResponse, expectedData, annotations, assertDom, base, msg ) => { const done = assert.async(), item = ve.ui.DataTransferItem.static.newFromString( string, mimeType ), doc = ve.dm.Document.static.newBlankDocument(), mockSurface = { getModel: () => { return { getDocument: () => doc }; }, createProgress: () => ve.createDeferred().promise() }; ve.fixBase( doc.getHtmlDocument(), doc.getHtmlDocument(), base ); // Preprocess the expectedData array for ( let i = 0; i < expectedData.length; i++ ) { if ( Array.isArray( expectedData[ i ] ) ) { for ( let j = 0; j < expectedData[ i ][ 1 ].length; j++ ) { if ( typeof expectedData[ i ][ 1 ][ j ] === 'number' ) { expectedData[ i ][ 1 ][ j ] = annotations[ expectedData[ i ][ 1 ][ j ] ]; } } } } // Check we match the wikitext string handler const name = ve.ui.dataTransferHandlerFactory.getHandlerNameForItem( item ); assert.strictEqual( name, 'wikitextString', msg + ': triggers match function' ); // Invoke the handler const handler = ve.ui.dataTransferHandlerFactory.create( 'wikitextString', mockSurface, item ); handler.getInsertableData().done( ( docOrData ) => { let actualData, store; if ( docOrData instanceof ve.dm.Document ) { actualData = docOrData.getData(); store = docOrData.getStore(); } else { actualData = docOrData; store = new ve.dm.HashValueStore(); } ve.dm.example.postprocessAnnotations( actualData, store ); if ( assertDom ) { assert.equalLinearDataWithDom( store, actualData, expectedData, msg + ': data match (with DOM)' ); } else { assert.equalLinearData( actualData, expectedData, msg + ': data match' ); } done(); } ); if ( server && expectedResponse ) { server.respond( [ 200, { 'Content-Type': 'application/json' }, JSON.stringify( { visualeditor: { result: 'success', content: expectedResponse } } ) ] ); } }; QUnit.test.each( 'convert', [ { msg: 'Simple link', // Put link in the middle of text to verify that the // start-of-line and end-of-line anchors on the heading // identification pattern don't affect link identification pasteString: 'some [[Foo]] text', pasteType: 'text/plain', parsoidResponse: '

some Foo text

', annotations: [ { type: 'link/mwInternal', attributes: { lookupTitle: 'Foo', normalizedTitle: 'Foo', title: 'Foo' } } ], expectedData: [ { type: 'paragraph' }, ...'some ', [ 'F', [ 0 ] ], [ 'o', [ 0 ] ], [ 'o', [ 0 ] ], ...' text', { type: '/paragraph' }, { type: 'internalList' }, { type: '/internalList' } ] }, { msg: 'Simple link with no p-wrapping', pasteString: '*[[Foo]]', pasteType: 'text/plain', parsoidResponse: '', annotations: [ { type: 'link/mwInternal', attributes: { lookupTitle: 'Foo', normalizedTitle: 'Foo', title: 'Foo' } } ], expectedData: [ { type: 'list', attributes: { style: 'bullet' } }, { type: 'listItem' }, { type: 'paragraph', internal: { generated: 'wrapper' } }, [ 'F', [ 0 ] ], [ 'o', [ 0 ] ], [ 'o', [ 0 ] ], { type: '/paragraph' }, { type: '/listItem' }, { type: '/list' }, { type: 'internalList' }, { type: '/internalList' } ] }, { msg: 'Simple template', pasteString: '{{Template}}', pasteType: 'text/plain', parsoidResponse: '
Template
', assertDom: true, expectedData: [ { type: 'mwTransclusionBlock', attributes: { mw: {} }, originalDomElements: $.parseHTML( '
Template
' ) }, { type: '/mwTransclusionBlock' }, { type: 'internalList' }, { type: '/internalList' } ] }, { msg: 'Headings, only RESTBase IDs stripped', pasteString: '==heading==', pasteType: 'text/plain', parsoidResponse: '

foo

bar

', annotations: [], assertDom: true, expectedData: [ { type: 'mwHeading', attributes: { level: 2 }, originalDomElements: $.parseHTML( '

foo

' ) }, ...'foo', { type: '/mwHeading' }, { type: 'mwHeading', attributes: { level: 2 }, originalDomElements: $.parseHTML( '

bar

' ) }, ...'bar', { type: '/mwHeading' }, { type: 'internalList' }, { type: '/internalList' } ] }, { msg: 'Headings, parsoid fallback ids don\'t interfere with whitespace stripping', pasteString: '== Tudnivalók ==', pasteType: 'text/plain', parsoidResponse: '

Tudnivalók

', annotations: [], assertDom: true, expectedData: [ { type: 'mwHeading', attributes: { level: 2 }, originalDomElements: $.parseHTML( '

Tudnivalók

' ) }, ...'Tudnivalók', { type: '/mwHeading' }, { type: 'internalList' }, { type: '/internalList' } ] }, { msg: 'Magic link (RFC)', pasteString: 'RFC 1234', pasteType: 'text/plain', parsoidResponse: false, annotations: [], expectedData: [ { type: 'link/mwMagic', attributes: { content: 'RFC 1234' } }, { type: '/link/mwMagic' } ] }, { msg: 'Magic link (PMID)', pasteString: 'PMID 1234', pasteType: 'text/plain', parsoidResponse: false, annotations: [], expectedData: [ { type: 'link/mwMagic', attributes: { content: 'PMID 1234' } }, { type: '/link/mwMagic' } ] }, { msg: 'Magic link (ISBN)', pasteString: 'ISBN 123456789X', pasteType: 'text/plain', parsoidResponse: false, annotations: [], expectedData: [ { type: 'link/mwMagic', attributes: { content: 'ISBN 123456789X' } }, { type: '/link/mwMagic' } ] } ], function ( assert, caseItem ) { mw.config.set( { wgArticlePath: '/wiki/$1' } ); ve.test.utils.runWikitextStringHandlerTest( assert, this.server, caseItem.pasteString, caseItem.pasteType, caseItem.parsoidResponse, caseItem.expectedData, caseItem.annotations, caseItem.assertDom, ve.dm.mwExample.baseUri, caseItem.msg ); } );