mediawiki-extensions-Visual.../modules/ve/test/ce/ve.ce.test.js
Roan Kattouw 94879a98b7 Use jquery.i18n for standalone i18n
VisualEditor.php:
* Make jquery.i18n a dependency of ext.visualEditor.standalone

makeStaticLoader.php:
* Remove ve.init.platform.addMessages() call with PHP-generated messages
* Add fake module for jquery.i18n
** Needed because the module might come from MW core
** Also add special treatment for fallbacks.js and language scripts

ve.init.sa.Platform.js:
* Remove basic message system, replace with jquery.i18n
* Add initialize method that loads messages for current language and
  fallbacks

ve.init.sa.Target.js:
* Wait for the platform to initialize before actually doing things
* Add .setup() method to allow callers to short-circuit this process
** This is convenient for callers of ve.init.sa.Target in the test suite

ve.ce.test.js:
* Use existing ve.test.utils function for creating a surface

ve.test.utils.js:
* Call .setup() on the target so we can get a surface synchronously

ve.init.Platform.test.js:
* Make these tests async, wait for the platform to initialize
* Allow for missing messages to be output either as <foo> (MW)
  or foo (jquery.i18n)
* Get rid of message clearing code, namespace test messages instead

Change-Id: Iac7dfd327eadf9b503a61510574d35d748faac92
2013-12-17 21:16:26 +01:00

238 lines
7.4 KiB
JavaScript

/*!
* VisualEditor ContentEditable tests.
*
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
QUnit.module( 've.ce' );
/* Tests */
QUnit.test( 'whitespacePattern', 4, function ( assert ) {
assert.equal( 'a b'.match( ve.ce.whitespacePattern ), ' ', 'matches spaces' );
assert.equal( 'a\u00A0b'.match( ve.ce.whitespacePattern ), '\u00A0', 'matches non-breaking spaces' );
assert.equal( 'a\tb'.match( ve.ce.whitespacePattern ), null, 'does not match tab' );
assert.equal( 'ab'.match( ve.ce.whitespacePattern ), null, 'does not match non-whitespace' );
} );
QUnit.test( 'getDomText', 1, function ( assert ) {
assert.equal( ve.ce.getDomText(
$( '<span>a<b><a href="#">b</a></b><span></span><i>c</i>d</span>' )[0] ),
'abcd'
);
} );
QUnit.test( 'getDomHash', 1, function ( assert ) {
assert.equal(
ve.ce.getDomHash( $( '<span>a<b><a href="#">b</a></b><span></span><i>c</i>d</span>' )[0] ),
'<SPAN>#<B><A>#</A></B><SPAN></SPAN><I>#</I>#</SPAN>'
);
} );
QUnit.test( 'getOffsetFrom(Element|Text)Node', function ( assert ) {
var i, surface, documentModel, documentView,
expected = 0,
testCases = [
{
'msg': 'Annotated alien',
'html': '<p>Foo<b><cite>Bar</cite></b>Baz</p>',
// CE html summary;
// <p>Foo<b><span [protectedNode]><cite>Bar</cite><img [shield]></span></b>Baz</p>
'expected': [
0,
1, 1,
2,
3,
4, 4, 4,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7,
8,
9, 9,
10
]
}
];
for ( i = 0; i < testCases.length; i++ ) {
expected += testCases[i].expected.length;
}
QUnit.expect( expected );
function testOffsets( parent, testCase, expectedIndex ) {
var i;
switch ( parent.nodeType ) {
case Node.ELEMENT_NODE:
for ( i = 0; i <= parent.childNodes.length; i++ ) {
expectedIndex++;
assert.equal(
ve.ce.getOffsetFromElementNode( parent, i ),
testCase.expected[expectedIndex],
testCase.msg + ': offset ' + i + ' in <' + parent.nodeName.toLowerCase() + '>'
);
if ( parent.childNodes[i] ) {
expectedIndex = testOffsets( parent.childNodes[i], testCase, expectedIndex );
}
}
break;
case Node.TEXT_NODE:
for ( i = 0; i <= parent.data.length; i++ ) {
expectedIndex++;
assert.equal(
ve.ce.getOffsetFromTextNode( parent, i ),
testCase.expected[expectedIndex],
testCase.msg + ': offset ' + i + ' in "' + parent.data + '"'
);
}
break;
}
return expectedIndex;
}
for ( i = 0; i < testCases.length; i++ ) {
surface = ve.test.utils.createSurfaceFromHtml( testCases[i].html );
documentModel = surface.getModel().getDocument();
documentView = surface.getView().getDocument();
testOffsets( documentView.getDocumentNode().$element[0], testCases[i], -1 );
surface.destroy();
}
} );
// TODO: ve.ce.getOffset
// TODO: ve.ce.getOffsetOfSlug
QUnit.test( 'isLeftOrRightArrowKey', 4, function ( assert ) {
assert.equal( ve.ce.isLeftOrRightArrowKey( OO.ui.Keys.LEFT ), true, 'Left' );
assert.equal( ve.ce.isLeftOrRightArrowKey( OO.ui.Keys.RIGHT ), true, 'Right' );
assert.equal( ve.ce.isLeftOrRightArrowKey( OO.ui.Keys.UP ), false, 'Up' );
assert.equal( ve.ce.isLeftOrRightArrowKey( OO.ui.Keys.DOWN ), false, 'Down' );
} );
QUnit.test( 'isUpOrDownArrowKey', 4, function ( assert ) {
assert.equal( ve.ce.isUpOrDownArrowKey( OO.ui.Keys.LEFT ), false, 'Left' );
assert.equal( ve.ce.isUpOrDownArrowKey( OO.ui.Keys.RIGHT ), false, 'Right' );
assert.equal( ve.ce.isUpOrDownArrowKey( OO.ui.Keys.UP ), true, 'Up' );
assert.equal( ve.ce.isUpOrDownArrowKey( OO.ui.Keys.DOWN ), true, 'Down' );
} );
QUnit.test( 'isArrowKey', 5, function ( assert ) {
assert.equal( ve.ce.isArrowKey( OO.ui.Keys.LEFT ), true, 'Left' );
assert.equal( ve.ce.isArrowKey( OO.ui.Keys.RIGHT ), true, 'Right' );
assert.equal( ve.ce.isArrowKey( OO.ui.Keys.UP ), true, 'Up' );
assert.equal( ve.ce.isArrowKey( OO.ui.Keys.DOWN ), true, 'Down' );
assert.equal( ve.ce.isArrowKey( OO.ui.Keys.ENTER ), false, 'Enter' );
} );
QUnit.test( 'isShortcutKey', 3, function ( assert ) {
assert.equal( ve.ce.isShortcutKey( { 'ctrlKey': true } ), true, 'ctrlKey' );
assert.equal( ve.ce.isShortcutKey( { 'metaKey': true } ), true, 'metaKey' );
assert.equal( ve.ce.isShortcutKey( {} ), false, 'Not set' );
} );
QUnit.test( 'resolveTestOffset', function ( assert ) {
var i, ilen, j, jlen, tests, test, testOffset, elt, pre, post, count, dom;
tests = [
['o', 'k'],
// TODO: doesn't handle tags correctly yet!
// ['w', '<b>', 'x', 'y', '</b>', 'z'],
// ['q', '<b>', 'r', '<b>', 's', 't', '</b>', 'u', '</b>', 'v']
['h', 'e', 'l', 'l', 'o']
];
count = 0;
for ( i = 0, ilen = tests.length; i < ilen; i++ ) {
count += tests[i].length + 1;
}
QUnit.expect( 2 * count );
dom = ve.createDocumentFromHtml( '' );
elt = dom.createElement( 'div' );
for ( i = 0, ilen = tests.length; i < ilen; i++ ) {
test = tests[i];
elt.innerHTML = test.join( '' );
for ( j = 0, jlen = test.length; j < jlen + 1; j++ ) {
testOffset = new ve.ce.TestOffset( 'forward', j );
pre = test.slice( 0, j ).join( '' );
post = test.slice( j ).join( '' );
assert.equal(
testOffset.resolve( elt ).slice,
pre + '|' + post
);
testOffset = new ve.ce.TestOffset( 'backward', j );
pre = test.slice( 0, jlen - j ).join( '' );
post = test.slice( jlen - j ).join( '' );
assert.equal(
testOffset.resolve( elt ).slice,
pre + '|' + post
);
}
}
} );
QUnit.test( 'fakeImes', function ( assert ) {
var i, ilen, j, jlen, surface, testRunner, testName, testActions, seq, testInfo,
action, args, count, foundEndLoop, fakePreventDefault;
// count tests
count = 0;
for ( i = 0, ilen = ve.ce.imetests.length; i < ilen; i++ ) {
testName = ve.ce.imetests[i][0];
if ( ve.ce.imetestsBroken[testName] ) {
// Skip broken test for now
continue;
}
testActions = ve.ce.imetests[i][1];
// For the test that there is at least one endLoop
count++;
for ( j = 1, jlen = testActions.length; j < jlen; j++ ) {
action = testActions[j].action;
if ( action === 'endLoop' ) {
// For the test that the model and CE surface are in sync
count++;
}
}
}
if ( !count ) {
throw new Error( 'No IME tests found' );
}
QUnit.expect( count );
// TODO: make this function actually affect the events triggered
fakePreventDefault = function () {};
for ( i = 0, ilen = ve.ce.imetests.length; i < ilen; i++ ) {
testName = ve.ce.imetests[i][0];
if ( ve.ce.imetestsBroken[testName] ) {
// Skip broken test for now
continue;
}
testActions = ve.ce.imetests[i][1];
foundEndLoop = false;
// First element is the testInfo
testInfo = testActions[0];
surface = ve.test.utils.createSurfaceFromHtml( testInfo.startDom || '' );
testRunner = new ve.ce.TestRunner( surface );
// start at 1 to omit the testInfo
for ( j = 1, jlen = testActions.length; j < jlen; j++ ) {
action = testActions[j].action;
args = testActions[j].args;
seq = testActions[j].seq;
if ( action === 'sendEvent' ) {
// TODO: make preventDefault work
args[1].preventDefault = fakePreventDefault;
}
testRunner[action].apply( testRunner, args );
// Check synchronized at the end of each event loop
if ( action === 'endLoop' ) {
// Test that the model and CE surface are in sync
testRunner.testEqual( assert, testName, seq );
foundEndLoop = true;
}
}
// Test that there is at least one endLoop
assert.equal( foundEndLoop, true, testName + ' found at least one endLoop' );
surface.destroy();
}
} );