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

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

Issue 2593933003: Revert of Get rid of verify-with-timeout in spellcheck_test (Closed)
Patch Set: Created 3 years, 12 months 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 | « no previous file | 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 //
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 */ 268 */
269 serializeInternal(node) { 269 serializeInternal(node) {
270 if (isElement(node)) 270 if (isElement(node))
271 return this.handleElementNode(node); 271 return this.handleElementNode(node);
272 if (isCharacterData(node)) 272 if (isCharacterData(node))
273 return this.handleCharacterData(node); 273 return this.handleCharacterData(node);
274 throw new Error(`Unexpected node ${node}`); 274 throw new Error(`Unexpected node ${node}`);
275 } 275 }
276 } 276 }
277 277
278 /**
279 * @param {!Document} document
280 * @return {boolean}
281 */
282 function hasPendingSpellCheckRequest(document) {
283 return internals.lastSpellCheckRequestSequence(document) !==
284 internals.lastSpellCheckProcessedSequence(document);
285 }
286
287 /** @type {string} */ 278 /** @type {string} */
288 const kTitle = 'title'; 279 const kTitle = 'title';
289 /** @type {string} */ 280 /** @type {string} */
290 const kCallback = 'callback'; 281 const kCallback = 'callback';
291 /** @type {string} */ 282 /** @type {string} */
292 const kIsSpellcheckTest = 'isSpellcheckTest'; 283 const kIsSpellcheckTest = 'isSpellcheckTest';
293 284
285 /**
286 * @param {!Test} testObject
287 * @param {!Sample} sample
288 * @param {string} expectedText
289 * @param {number} remainingRetry
290 * @param {number} retryInterval
291 */
292 function verifyMarkers(
293 testObject, sample, expectedText, remainingRetry, retryInterval) {
294 assert_not_equals(
295 window.internals, undefined,
296 'window.internals is required for running automated spellcheck tests.');
297
298 /** @type {!MarkerSerializer} */
299 const serializer = new MarkerSerializer({
300 spelling: '#',
301 grammar: '~'});
302
303 try {
304 assert_equals(serializer.serialize(sample.document), expectedText);
305 testObject.done();
306 } catch (error) {
307 if (remainingRetry <= 0)
308 throw error;
309
310 // Force invoking idle time spellchecker in case it has not been run yet.
311 if (window.testRunner)
312 window.testRunner.runIdleTasks(() => {});
313
314 // TODO(xiaochengh): We should make SpellCheckRequester::didCheck trigger
315 // something in JavaScript (e.g., a |Promise|), so that we can actively
316 // know the completion of spellchecking instead of passively waiting for
317 // markers to appear or disappear.
318 testObject.step_timeout(
319 () => verifyMarkers(testObject, sample, expectedText,
320 remainingRetry - 1, retryInterval),
321 retryInterval);
322 }
323 }
324
294 // Spellchecker gets triggered not only by text and selection change, but also 325 // Spellchecker gets triggered not only by text and selection change, but also
295 // by focus change. For example, misspelling markers in <INPUT> disappear when 326 // by focus change. For example, misspelling markers in <INPUT> disappear when
296 // the window loses focus, even though the selection does not change. 327 // the window loses focus, even though the selection does not change.
297 // Therefore, we disallow spellcheck tests from running simultaneously to 328 // Therefore, we disallow spellcheck tests from running simultaneously to
298 // prevent interference among them. If we call spellcheck_test while another 329 // prevent interference among them. If we call spellcheck_test while another
299 // test is running, the new test will be added into testQueue waiting for the 330 // test is running, the new test will be added into testQueue waiting for the
300 // completion of the previous test. 331 // completion of the previous test.
301 332
302 /** @type {boolean} */ 333 /** @type {boolean} */
303 var spellcheckTestRunning = false; 334 var spellcheckTestRunning = false;
304 /** @type {!Array<!Object>} */ 335 /** @type {!Array<!Object>} */
305 const testQueue = []; 336 const testQueue = [];
306 337
307 // We need to ensure correct usage of testRunner.runIdleTasks() that:
308 // 1. We don't call runIdleTasks if another runIdleTasks is called but the
309 // callback has not been invoked yet; Otherwise, the current call is ignored.
310 // 2. When the callback is invoked, we only verify test cases whose testers
311 // finished before calling runIdleTasks(); Otherwise, the idle time spell
312 // check may have not been invoked at the verification time.
313
314 /** @type {boolean} */
315 var runIdleTasksRequested = false;
316 /**
317 * @type {!Array<!Function>} Verification functions of test cases whose idle
318 * idle spell checkers are requested before the current call of runIdleTasks.
319 */
320 var idleVerificationReadyQueue = [];
321 /**
322 * @type {!Array<!Function>} Verification functions of test cases whose idle
323 * idle spell checkers are requested after the current call of runIdleTasks.
324 */
325 var idleVerificationWaitingQueue = [];
326
327 function batchIdleVerification() {
328 runIdleTasksRequested = false;
329 idleVerificationReadyQueue.forEach(func => func());
330 idleVerificationReadyQueue = idleVerificationWaitingQueue;
331 idleVerificationWaitingQueue = [];
332 if (idleVerificationReadyQueue.length) {
333 runIdleTasksRequested = true;
334 testRunner.runIdleTasks(batchIdleVerification);
335 }
336 }
337
338 /** 338 /**
339 * @param {!Test} testObject 339 * @param {!Test} testObject
340 * @param {!Sample|string} input 340 * @param {!Sample|string} input
341 * @param {function(!Document)|string} tester 341 * @param {function(!Document)|string} tester
342 * @param {string} expectedText 342 * @param {string} expectedText
343 */ 343 */
344 function invokeSpellcheckTest(testObject, input, tester, expectedText) { 344 function invokeSpellcheckTest(testObject, input, tester, expectedText) {
345 spellcheckTestRunning = true; 345 spellcheckTestRunning = true;
346 346
347 testObject.step(() => { 347 testObject.step(() => {
348 // TODO(xiaochengh): Merge the following part with |assert_selection|. 348 // TODO(xiaochengh): Merge the following part with |assert_selection|.
349 /** @type {!Sample} */ 349 /** @type {!Sample} */
350 const sample = typeof(input) === 'string' ? new Sample(input) : input; 350 const sample = typeof(input) === 'string' ? new Sample(input) : input;
351 testObject.sample = sample; 351 testObject.sample = sample;
352 352
353 if (typeof(tester) === 'function') { 353 if (typeof(tester) === 'function') {
354 tester.call(window, sample.document); 354 tester.call(window, sample.document);
355 } else if (typeof(tester) === 'string') { 355 } else if (typeof(tester) === 'string') {
356 const strings = tester.split(/ (.+)/); 356 const strings = tester.split(/ (.+)/);
357 sample.document.execCommand(strings[0], false, strings[1]); 357 sample.document.execCommand(strings[0], false, strings[1]);
358 } else { 358 } else {
359 assert_unreached(`Invalid tester: ${tester}`); 359 assert_unreached(`Invalid tester: ${tester}`);
360 } 360 }
361 361
362 assert_not_equals( 362 /** @type {number} */
363 window.testRunner, undefined, 363 const kMaxRetry = 10;
364 'window.testRunner is required for automated spellcheck tests.'); 364 /** @type {number} */
365 assert_not_equals( 365 const kRetryInterval = 50;
366 window.internals, undefined,
367 'window.internals is required for automated spellcheck tests.');
368 366
369 /** @type {!Function} */ 367 // TODO(xiaochengh): We should make SpellCheckRequester::didCheck trigger
370 const verification = () => { 368 // something in JavaScript (e.g., a |Promise|), so that we can actively know
371 testObject.step(() => { 369 // the completion of spellchecking instead of passively waiting for markers
372 if (hasPendingSpellCheckRequest(sample.document)) 370 // to appear or disappear.
373 return; 371 testObject.step_timeout(
374 372 () => verifyMarkers(testObject, sample, expectedText,
375 /** @type {!MarkerSerializer} */ 373 kMaxRetry, kRetryInterval),
376 const serializer = new MarkerSerializer({ 374 kRetryInterval);
377 spelling: '#',
378 grammar: '~'});
379
380 assert_equals(serializer.serialize(sample.document), expectedText);
381 testObject.done();
382 });
383 }
384
385 // Verify when all spell check requests are resolved.
386 testRunner.setSpellCheckResolvedCallback(verification);
387
388 // For tests that do not expect new markers, verify with runIdleTasks.
389 if (runIdleTasksRequested) {
390 idleVerificationWaitingQueue.push(verification);
391 return;
392 }
393
394 idleVerificationReadyQueue.push(verification);
395 runIdleTasksRequested = true;
396 testRunner.runIdleTasks(batchIdleVerification);
397 }); 375 });
398 } 376 }
399 377
400 add_result_callback(testObj => { 378 add_result_callback(testObj => {
401 if (!testObj.properties[kIsSpellcheckTest]) 379 if (!testObj.properties[kIsSpellcheckTest])
402 return; 380 return;
403 381
404 /** @type {boolean} */ 382 /** @type {boolean} */
405 var shouldRemoveSample = false; 383 var shouldRemoveSample = false;
406 if (testObj.status === testObj.PASS) { 384 if (testObj.status === testObj.PASS) {
407 if (testObj.properties[kCallback]) 385 if (testObj.properties[kCallback])
408 testObj.properties[kCallback](testObj.sample); 386 testObj.properties[kCallback](testObj.sample);
409 else 387 else
410 shouldRemoveSample = true; 388 shouldRemoveSample = true;
411 } else { 389 } else {
412 if (window.testRunner) 390 if (window.testRunner)
413 shouldRemoveSample = true; 391 shouldRemoveSample = true;
414 } 392 }
415 393
416 if (shouldRemoveSample) 394 if (shouldRemoveSample)
417 testObj.sample.remove(); 395 testObj.sample.remove();
418 396
419 // We may be in a spellCheckResolvedCallback here, so removing the callback 397 // This is the earliest timing when a new spellcheck_test can be started.
420 // (and hence, all remaining tasks) must be done asynchronously. 398 spellcheckTestRunning = false;
421 setTimeout(() => {
422 if (window.testRunner)
423 testRunner.removeSpellCheckResolvedCallback();
424 399
425 // This is the earliest timing when a new spellcheck_test can be started. 400 /** @type {Object} */
426 spellcheckTestRunning = false; 401 const next = testQueue.shift();
427 402 if (next === undefined)
428 /** @type {Object} */ 403 return;
429 const next = testQueue.shift(); 404 invokeSpellcheckTest(next.testObject, next.input,
430 if (next === undefined) 405 next.tester, next.expectedText);
431 return;
432 invokeSpellcheckTest(next.testObject, next.input,
433 next.tester, next.expectedText);
434 }, 0);
435 }); 406 });
436 407
437 /** 408 /**
438 * @param {Object=} passedArgs 409 * @param {Object=} passedArgs
439 * @return {!Object} 410 * @return {!Object}
440 */ 411 */
441 function getTestArguments(passedArgs) { 412 function getTestArguments(passedArgs) {
442 const args = {}; 413 const args = {};
443 args[kIsSpellcheckTest] = true; 414 args[kIsSpellcheckTest] = true;
444 [kTitle, kCallback].forEach(key => args[key] = undefined); 415 [kTitle, kCallback].forEach(key => args[key] = undefined);
(...skipping 30 matching lines...) Expand all
475 tester: tester, expectedText: expectedText}); 446 tester: tester, expectedText: expectedText});
476 return; 447 return;
477 } 448 }
478 449
479 invokeSpellcheckTest(testObject, input, tester, expectedText); 450 invokeSpellcheckTest(testObject, input, tester, expectedText);
480 } 451 }
481 452
482 // Export symbols 453 // Export symbols
483 window.spellcheck_test = spellcheckTest; 454 window.spellcheck_test = spellcheckTest;
484 })(); 455 })();
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698