Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: third_party/WebKit/LayoutTests/editing/spelling/spellcheck_test.js

Issue 2445323005: Allow spellcheck_test to run custom callback at completion (Closed)
Patch Set: Wed Oct 26 16:59:50 JST 2016 Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/LayoutTests/editing/spelling/spellcheck_test.html ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 'use strict'; 5 'use strict';
6 6
7 // This file provides 7 // This file provides
8 // |spellcheck_test(sample, tester, expectedText, opt_title)| asynchronous test 8 // |spellcheck_test(sample, tester, expectedText, opt_title)| asynchronous test
9 // to W3C test harness for easier writing of spellchecker test cases. 9 // to W3C test harness for easier writing of spellchecker test cases.
10 // 10 //
11 // |sample| is an HTML fragment text which is inserted as |innerHTML|. It should 11 // |sample| is
12 // have at least one focus boundary point marker "|" and at most one anchor 12 // - Either an HTML fragment text which is inserted as |innerHTML|, in which
13 // boundary point marker "^" indicating the initial selection. 13 // case It should have at least one focus boundary point marker "|" and at
14 // TODO(editing-dev): Make initial selection work with TEXTAREA and INPUT. 14 // most one anchor boundary point marker "^" indicating the initial selection.
15 // TODO(editing-dev): Make initial selection work with TEXTAREA and INPUT.
16 // - Or a |Sample| object created by some previous test.
15 // 17 //
16 // |tester| is either name with parameter of execCommand or function taking 18 // |tester| is either name with parameter of execCommand or function taking
17 // one parameter |Document|. 19 // one parameter |Document|.
18 // 20 //
19 // |expectedText| is an HTML fragment indicating the expected result, where text 21 // |expectedText| is an HTML fragment indicating the expected result, where text
20 // with spelling marker is surrounded by '_', and text with grammar marker is 22 // with spelling marker is surrounded by '_', and text with grammar marker is
21 // surrounded by '~'. 23 // surrounded by '~'.
22 // 24 //
23 // |opt_title| is an optional string giving the title of the test case. 25 // |opt_args| is an optional object with the following optional fields:
26 // - title: the title of the test case.
27 // - callback: a callback function to be run after the test passes, which takes
28 // one parameter -- the |Sample| at the end of the test
29 // It is allowed to pass a string as |arg_args| to indicate the title only.
24 // 30 //
25 // See spellcheck_test.html for sample usage. 31 // See spellcheck_test.html for sample usage.
26 32
27 (function() { 33 (function() {
28 const Sample = window.Sample; 34 const Sample = window.Sample;
29 35
30 // TODO(editing-dev): Once we can import JavaScript file from scripts, we should 36 // TODO(editing-dev): Once we can import JavaScript file from scripts, we should
31 // import "imported/wpt/html/resources/common.js", since |HTML5_VOID_ELEMENTS| 37 // import "imported/wpt/html/resources/common.js", since |HTML5_VOID_ELEMENTS|
32 // is defined in there. 38 // is defined in there.
33 /** 39 /**
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 */ 256 */
251 serializeInternal(node) { 257 serializeInternal(node) {
252 if (isElement(node)) 258 if (isElement(node))
253 return this.handleElementNode(node); 259 return this.handleElementNode(node);
254 if (isCharacterData(node)) 260 if (isCharacterData(node))
255 return this.handleCharacterData(node); 261 return this.handleCharacterData(node);
256 throw new Error(`Unexpected node ${node}`); 262 throw new Error(`Unexpected node ${node}`);
257 } 263 }
258 } 264 }
259 265
266 /** @type {string} */
267 const kTitle = 'title';
268 /** @type {string} */
269 const kCallback = 'callback';
270 /** @type {string} */
271 const kIsSpellcheckTest = 'isSpellcheckTest';
272
260 /** 273 /**
261 * @param {!Test} testObject 274 * @param {!Test} testObject
262 * @param {!Sample} sample 275 * @param {!Sample} sample
263 * @param {string} expectedText 276 * @param {string} expectedText
264 * @param {number} remainingRetry 277 * @param {number} remainingRetry
265 * @param {number} retryInterval 278 * @param {number} retryInterval
266 */ 279 */
267 function verifyMarkers( 280 function verifyMarkers(
268 testObject, sample, expectedText, remainingRetry, retryInterval) { 281 testObject, sample, expectedText, remainingRetry, retryInterval) {
269 assert_not_equals( 282 assert_not_equals(
270 window.internals, undefined, 283 window.internals, undefined,
271 'window.internals is required for running automated spellcheck tests.'); 284 'window.internals is required for running automated spellcheck tests.');
272 285
273 /** @type {!MarkerSerializer} */ 286 /** @type {!MarkerSerializer} */
274 const serializer = new MarkerSerializer({ 287 const serializer = new MarkerSerializer({
275 spelling: '_', 288 spelling: '_',
276 grammar: '~'}); 289 grammar: '~'});
277 290
278 try { 291 try {
279 assert_equals(serializer.serialize(sample.document), expectedText); 292 assert_equals(serializer.serialize(sample.document), expectedText);
280 testObject.done(); 293 testObject.done();
281 sample.remove();
282 } catch (error) { 294 } catch (error) {
283 if (remainingRetry <= 0) 295 if (remainingRetry <= 0)
284 throw error; 296 throw error;
285 297
286 // Force invoking idle time spellchecker in case it has not been run yet. 298 // Force invoking idle time spellchecker in case it has not been run yet.
287 if (window.testRunner) 299 if (window.testRunner)
288 window.testRunner.runIdleTasks(() => {}); 300 window.testRunner.runIdleTasks(() => {});
289 301
290 // TODO(xiaochengh): We should make SpellCheckRequester::didCheck trigger 302 // TODO(xiaochengh): We should make SpellCheckRequester::didCheck trigger
291 // something in JavaScript (e.g., a |Promise|), so that we can actively 303 // something in JavaScript (e.g., a |Promise|), so that we can actively
(...skipping 13 matching lines...) Expand all
305 // prevent interference among them. If we call spellcheck_test while another 317 // prevent interference among them. If we call spellcheck_test while another
306 // test is running, the new test will be added into testQueue waiting for the 318 // test is running, the new test will be added into testQueue waiting for the
307 // completion of the previous test. 319 // completion of the previous test.
308 320
309 /** @type {boolean} */ 321 /** @type {boolean} */
310 var spellcheckTestRunning = false; 322 var spellcheckTestRunning = false;
311 /** @type {!Array<!Object>} */ 323 /** @type {!Array<!Object>} */
312 const testQueue = []; 324 const testQueue = [];
313 325
314 /** 326 /**
315 * @param {string} inputText 327 * @param {!Sample|string} input
316 * @param {function(!Document)|string} tester 328 * @param {function(!Document)|string} tester
317 * @param {string} expectedText 329 * @param {string} expectedText
318 * @param {string=} opt_title 330 * @param {Object} args
319 */ 331 */
320 function invokeSpellcheckTest(inputText, tester, expectedText, opt_title) { 332 function invokeSpellcheckTest(input, tester, expectedText, args) {
321 spellcheckTestRunning = true; 333 spellcheckTestRunning = true;
322 334
323 async_test(testObject => { 335 async_test(testObject => {
324 // TODO(xiaochengh): Merge the following part with |assert_selection|. 336 // TODO(xiaochengh): Merge the following part with |assert_selection|.
325 /** @type {!Sample} */ 337 /** @type {!Sample} */
326 const sample = new Sample(inputText); 338 const sample = typeof(input) === 'string' ? new Sample(input) : input;
339 testObject.sample = sample;
340
327 if (typeof(tester) === 'function') { 341 if (typeof(tester) === 'function') {
328 tester.call(window, sample.document); 342 tester.call(window, sample.document);
329 } else if (typeof(tester) === 'string') { 343 } else if (typeof(tester) === 'string') {
330 const strings = tester.split(/ (.+)/); 344 const strings = tester.split(/ (.+)/);
331 sample.document.execCommand(strings[0], false, strings[1]); 345 sample.document.execCommand(strings[0], false, strings[1]);
332 } else { 346 } else {
333 assert_unreached(`Invalid tester: ${tester}`); 347 assert_unreached(`Invalid tester: ${tester}`);
334 } 348 }
335 349
336 /** @type {number} */ 350 /** @type {number} */
337 const kMaxRetry = 10; 351 const kMaxRetry = 10;
338 /** @type {number} */ 352 /** @type {number} */
339 const kRetryInterval = 50; 353 const kRetryInterval = 50;
340 354
341 // TODO(xiaochengh): We should make SpellCheckRequester::didCheck trigger 355 // TODO(xiaochengh): We should make SpellCheckRequester::didCheck trigger
342 // something in JavaScript (e.g., a |Promise|), so that we can actively know 356 // something in JavaScript (e.g., a |Promise|), so that we can actively know
343 // the completion of spellchecking instead of passively waiting for markers 357 // the completion of spellchecking instead of passively waiting for markers
344 // to appear or disappear. 358 // to appear or disappear.
345 testObject.step_timeout( 359 testObject.step_timeout(
346 () => verifyMarkers(testObject, sample, expectedText, 360 () => verifyMarkers(testObject, sample, expectedText,
347 kMaxRetry, kRetryInterval), 361 kMaxRetry, kRetryInterval),
348 kRetryInterval); 362 kRetryInterval);
349 }, opt_title, {isSpellcheckTest: true}); 363 }, args[kTitle], args);
350 } 364 }
351 365
352 add_result_callback(testObj => { 366 add_result_callback(testObj => {
353 if (!testObj.properties.isSpellcheckTest) 367 if (!testObj.properties[kIsSpellcheckTest])
354 return; 368 return;
355 spellcheckTestRunning = false; 369 spellcheckTestRunning = false;
370
371 if (testObj.status === testObj.PASS) {
372 if (testObj.properties[kCallback]) {
373 testObj.properties[kCallback](testObj.sample);
374 } else {
375 testObj.sample.remove();
376 }
377 }
378
356 /** @type {Object} */ 379 /** @type {Object} */
357 const args = testQueue.shift(); 380 const next = testQueue.shift();
358 if (args === undefined) 381 if (next === undefined)
359 return; 382 return;
360 invokeSpellcheckTest(args.inputText, args.tester, 383 invokeSpellcheckTest(next.input, next.tester,
361 args.expectedText, args.opt_title); 384 next.expectedText, next.args);
362 }); 385 });
363 386
364 /** 387 /**
365 * @param {string} inputText 388 * @param {Object=} passedArgs
389 * @return {!Object}
390 */
391 function getTestArguments(passedArgs) {
392 const args = {};
393 args[kIsSpellcheckTest] = true;
394 [kTitle, kCallback].forEach(key => args[key] = undefined);
395 if (!passedArgs)
396 return args;
397
398 if (typeof(passedArgs) === 'string') {
399 args[kTitle] = passedArgs;
400 return args;
401 }
402
403 [kTitle, kCallback].forEach(key => args[key] = passedArgs[key]);
404 return args;
405 }
406
407 /**
408 * @param {!Sample|string} input
366 * @param {function(!Document)|string} tester 409 * @param {function(!Document)|string} tester
367 * @param {string} expectedText 410 * @param {string} expectedText
368 * @param {string=} opt_title 411 * @param {Object=} opt_args
369 */ 412 */
370 function spellcheckTest(inputText, tester, expectedText, opt_title) { 413 function spellcheckTest(input, tester, expectedText, opt_args) {
371 if (window.testRunner) 414 if (window.testRunner)
372 window.testRunner.setMockSpellCheckerEnabled(true); 415 window.testRunner.setMockSpellCheckerEnabled(true);
373 416
417 /** @type {!Object} */
418 const args = getTestArguments(opt_args);
419
374 if (spellcheckTestRunning) { 420 if (spellcheckTestRunning) {
375 testQueue.push({ 421 testQueue.push({
376 inputText: inputText, tester: tester, 422 input: input, tester: tester,
377 expectedText: expectedText, opt_title: opt_title}); 423 expectedText: expectedText, args: args});
378 return; 424 return;
379 } 425 }
380 426
381 invokeSpellcheckTest(inputText, tester, expectedText, opt_title); 427 invokeSpellcheckTest(input, tester, expectedText, args);
382 } 428 }
383 429
384 // Export symbols 430 // Export symbols
385 window.spellcheck_test = spellcheckTest; 431 window.spellcheck_test = spellcheckTest;
386 })(); 432 })();
OLDNEW
« no previous file with comments | « third_party/WebKit/LayoutTests/editing/spelling/spellcheck_test.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698