mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-12-12 14:35:28 +00:00
94879a98b7
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
238 lines
7.4 KiB
JavaScript
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();
|
|
}
|
|
} );
|