From 50bec367cae1acbe1a4cd529940c8db7d43d85e8 Mon Sep 17 00:00:00 2001 From: Ed Sanders Date: Tue, 17 Dec 2013 19:12:00 +0000 Subject: [PATCH] Fix paste tests to work in phantomJS PhantomJS doesn't play nicely with document.execCommand and complex HTML. For testing the attribute stripping, use the clipboardData path. Add in a special clipboard key value that allows us to manually trigger this from the tests ('useClipboardData-0'). Change-Id: I0de842095a6a9a766f0f9a2249064ca7707283c8 --- modules/ve/ce/ve.ce.Surface.js | 7 +- modules/ve/test/ce/ve.ce.Surface.test.js | 81 +++++++++++++++++------- 2 files changed, 64 insertions(+), 24 deletions(-) diff --git a/modules/ve/ce/ve.ce.Surface.js b/modules/ve/ce/ve.ce.Surface.js index fc1220da4a..4f1e38c0f2 100644 --- a/modules/ve/ce/ve.ce.Surface.js +++ b/modules/ve/ce/ve.ce.Surface.js @@ -985,8 +985,11 @@ ve.ce.Surface.prototype.afterPaste = function () { $elements = this.$( $.parseHTML( beforePasteData.html ) ); } if ( - $elements.filter( 'span[id],span[typeof],span[rel]' ).length > 0 && - this.$pasteTarget.filter('span[id],span[typeof],span[rel]').length === 0 + // HACK: Allow the test runner to force the use of clipboardData + clipboardKey === 'useClipboardData-0' || ( + $elements.filter( 'span[id],span[typeof],span[rel]' ).length > 0 && + this.$pasteTarget.filter('span[id],span[typeof],span[rel]').length === 0 + ) ) { // CE destroyed an important span, so revert to using clipboard data htmlDoc = ve.createDocumentFromHtml( beforePasteData.html ); diff --git a/modules/ve/test/ce/ve.ce.Surface.test.js b/modules/ve/test/ce/ve.ce.Surface.test.js index 9e49a558fd..a887f8e4c7 100644 --- a/modules/ve/test/ce/ve.ce.Surface.test.js +++ b/modules/ve/test/ce/ve.ce.Surface.test.js @@ -553,7 +553,7 @@ QUnit.test( 'beforePaste/afterPaste', function ( assert ) { cases = [ { 'range': new ve.Range( 1 ), - 'pasteTargetHtml': 'Foo', + 'pasteHtml': 'Foo', 'expectedRange': new ve.Range( 4 ), 'expectedOps': [ [ @@ -572,7 +572,7 @@ QUnit.test( 'beforePaste/afterPaste', function ( assert ) { }, { 'range': new ve.Range( 4 ), - 'pasteTargetHtml': 'Bar', + 'pasteHtml': 'Bar', 'expectedRange': new ve.Range( 7 ), 'expectedOps': [ [ @@ -589,7 +589,7 @@ QUnit.test( 'beforePaste/afterPaste', function ( assert ) { }, { 'range': new ve.Range( 4 ), - 'pasteTargetHtml': 'FooBar', + 'pasteHtml': 'FooBar', 'expectedRange': new ve.Range( 7 ), 'expectedOps': [ [ @@ -606,7 +606,7 @@ QUnit.test( 'beforePaste/afterPaste', function ( assert ) { }, { 'range': new ve.Range( 4 ), - 'pasteTargetHtml': 'FooBar', + 'pasteHtml': 'FooBar', 'pasteSpecial': true, 'expectedRange': new ve.Range( 7 ), 'expectedOps': [ @@ -624,7 +624,7 @@ QUnit.test( 'beforePaste/afterPaste', function ( assert ) { }, { 'range': new ve.Range( 4 ), - 'pasteTargetHtml': '

Bar

', + 'pasteHtml': '

Bar

', 'expectedRange': new ve.Range( 7 ), 'expectedOps': [ [ @@ -641,7 +641,7 @@ QUnit.test( 'beforePaste/afterPaste', function ( assert ) { }, { 'range': new ve.Range( 6 ), - 'pasteTargetHtml': '

Bar

', + 'pasteHtml': '

Bar

', 'expectedRange': new ve.Range( 9 ), 'expectedOps': [ [ @@ -658,7 +658,7 @@ QUnit.test( 'beforePaste/afterPaste', function ( assert ) { }, { 'range': new ve.Range( 3 ), - 'pasteTargetHtml': '

Bar

', + 'pasteHtml': '

Bar

', 'expectedRange': new ve.Range( 6 ), 'expectedOps': [ [ @@ -675,7 +675,7 @@ QUnit.test( 'beforePaste/afterPaste', function ( assert ) { }, { 'range': new ve.Range( 4 ), - 'pasteTargetHtml': '☂foo☀', + 'pasteHtml': '☂foo☀', 'expectedRange': new ve.Range( 9 ), 'expectedOps': [ [ @@ -692,7 +692,7 @@ QUnit.test( 'beforePaste/afterPaste', function ( assert ) { }, { 'range': new ve.Range( 6 ), - 'pasteTargetHtml': '', + 'pasteHtml': '', 'expectedRange': new ve.Range( 6 ), 'expectedOps': [ [ @@ -717,7 +717,7 @@ QUnit.test( 'beforePaste/afterPaste', function ( assert ) { }, { 'range': new ve.Range( 4 ), - 'pasteTargetHtml': '
Foo
Bar
', + 'pasteHtml': '
Foo
Bar
', 'expectedRange': new ve.Range( 26 ), 'expectedOps': [ [ @@ -753,28 +753,63 @@ QUnit.test( 'beforePaste/afterPaste', function ( assert ) { }, { 'range': new ve.Range( 4 ), - 'pasteTargetHtml': 'Foo', - 'clipboardKey': true, - 'expectedRange': new ve.Range( 7 ), + 'pasteHtml': 'Foo', + // Test this in clipboard data mode as document.execCommand + // doesn't work reliably with complex attributes + 'useClipboardData': true, + 'expectedRange': new ve.Range( 11 ), 'expectedOps': [ [ { 'type': 'retain', 'length': 4 }, { 'type': 'replace', - 'insert': [ 'F', 'o', 'o' ], + 'insert': [ + { 'type': '/paragraph' }, + { 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } }, + 'F', 'o', 'o', + { 'type': '/paragraph' }, + { 'type': 'paragraph' } + ], 'remove': [] }, { 'type': 'retain', 'length': 5 } ] ], - 'msg': 'Span empty after stlyle attributes removed is ignored' + 'msg': 'Span empty after style attribute removed is ignored' + }, + { + 'range': new ve.Range( 4 ), + 'pasteHtml': 'Foo', + // Test this in clipboard data mode as document.execCommand + // doesn't work reliably with complex attributes + 'useClipboardData': true, + 'expectedRange': new ve.Range( 11 ), + 'expectedOps': [ + [ + { 'type': 'retain', 'length': 4 }, + { + 'type': 'replace', + 'insert': [ + { 'type': '/paragraph' }, + { 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } }, + ['F',[0]], ['o',[0]], ['o',[0]], + { 'type': '/paragraph' }, + { 'type': 'paragraph' } + ], + 'remove': [] + }, + { 'type': 'retain', 'length': 5 } + ] + ], + 'msg': 'Span not empty after style attribute removed is kept' } ]; QUnit.expect( cases.length * 2 ); - function testRunner( documentHtml, pasteTargetHtml, clipboardKey, range, expectedOps, pasteSpecial, expectedRange, msg ) { + function testRunner( documentHtml, pasteHtml, fromVe, useClipboardData, range, expectedOps, pasteSpecial, expectedRange, msg ) { var i, txs, ops, + e = {}, surface = ve.test.utils.createSurfaceFromHtml( documentHtml || exampleDoc ), view = surface.getView(), model = surface.getModel(); @@ -782,12 +817,14 @@ QUnit.test( 'beforePaste/afterPaste', function ( assert ) { // Paste sequence model.setSelection( range ); view.pasteSpecial = pasteSpecial; - if ( clipboardKey ) { - view.beforePaste( new TestEvent( { 'text/xcustom': '0.123-0' } ) ); - } else { - view.beforePaste( { 'originalEvent': {} } ); + if ( useClipboardData ) { + e['text/html'] = pasteHtml; + e['text/xcustom'] = 'useClipboardData-0'; + } else if ( fromVe ) { + e['text/xcustom'] = '0.123-0'; } - document.execCommand( 'insertHTML', false, pasteTargetHtml ) ; + view.beforePaste( new TestEvent( e ) ); + document.execCommand( 'insertHTML', false, pasteHtml ); view.afterPaste(); txs = model.getHistory()[0].transactions; @@ -803,7 +840,7 @@ QUnit.test( 'beforePaste/afterPaste', function ( assert ) { for ( i = 0; i < cases.length; i++ ) { testRunner( - cases[i].documentHtml, cases[i].pasteTargetHtml, cases[i].clipboardKey, + cases[i].documentHtml, cases[i].pasteHtml, cases[i].fromVe, cases[i].useClipboardData, cases[i].range, cases[i].expectedOps, cases[i].pasteSpecial, cases[i].expectedRange, cases[i].msg ); }