| OLD | NEW |
| 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 | 5 |
| 6 /** | 6 /** |
| 7 * @fileOverview WebAudio layout test utility library. Built around W3C's | 7 * @fileOverview WebAudio layout test utility library. Built around W3C's |
| 8 * testharness.js. Includes asynchronous test task manager, | 8 * testharness.js. Includes asynchronous test task manager, |
| 9 * assertion utilities. | 9 * assertion utilities. |
| 10 * @dependency testharness.js | 10 * @dependency testharness.js |
| 11 * @seealso webaudio/unit-tests/audit.html for actual examples. | |
| 12 */ | 11 */ |
| 13 | 12 |
| 14 | 13 |
| 15 (function () { | 14 (function () { |
| 16 | 15 |
| 17 'use strict'; | 16 'use strict'; |
| 18 | 17 |
| 19 // Selected properties from testharness.js | 18 // Selected properties from testharness.js |
| 20 let testharnessProperties = [ | 19 let testharnessProperties = [ |
| 21 'test', 'async_test', 'promise_test', 'promise_rejects', | 20 'test', 'async_test', 'promise_test', 'promise_rejects', |
| 22 'generate_tests', 'setup', 'done', 'assert_true', 'assert_false' | 21 'generate_tests', 'setup', 'done', 'assert_true', 'assert_false' |
| 23 ]; | 22 ]; |
| 24 | 23 |
| 25 // Check if testharness.js is properly loaded. Throw otherwise. | 24 // Check if testharness.js is properly loaded. Throw otherwise. |
| 26 for (let name in testharnessProperties) { | 25 for (let name in testharnessProperties) { |
| 27 if (!self.hasOwnProperty(testharnessProperties[name])) { | 26 if (!self.hasOwnProperty(testharnessProperties[name])) |
| 28 throw new Error('Cannot proceed. testharness.js is not loaded.'); | 27 throw new Error('Cannot proceed. testharness.js is not loaded.'); |
| 29 break; | |
| 30 } | |
| 31 } | 28 } |
| 32 })(); | 29 })(); |
| 33 | 30 |
| 34 | 31 |
| 35 /** | |
| 36 * @class Audit | |
| 37 * @description A WebAudio layout test task manager. | |
| 38 * @example | |
| 39 * let audit = Audit.createTaskRunner(); | |
| 40 * audit.define('first-task', function (task, should) { | |
| 41 * task.describe('the first task'); | |
| 42 * should(someValue).beEqualTo(someValue); | |
| 43 * task.done(); | |
| 44 * }); | |
| 45 * audit.run(); | |
| 46 */ | |
| 47 window.Audit = (function () { | 32 window.Audit = (function () { |
| 48 | 33 |
| 49 'use strict'; | 34 'use strict'; |
| 50 | 35 |
| 36 // NOTE: Moving this method (or any other code above) will change the location |
| 37 // of 'CONSOLE ERROR...' message in the expected text files. |
| 38 function _logError (message) { |
| 39 console.error('[audit.js] ' + message); |
| 40 } |
| 41 |
| 51 function _logPassed (message) { | 42 function _logPassed (message) { |
| 52 test(function (arg) { | 43 test(function (arg) { |
| 53 assert_true(true); | 44 assert_true(true); |
| 54 }, message); | 45 }, message); |
| 55 } | 46 } |
| 56 | 47 |
| 57 function _logFailed (message, detail) { | 48 function _logFailed (message, detail) { |
| 58 test(function () { | 49 test(function () { |
| 59 assert_true(false, detail); | 50 assert_true(false, detail); |
| 60 }, message); | 51 }, message); |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 * | 223 * |
| 233 * @example | 224 * @example |
| 234 * should({}, 'An empty object').exist(); | 225 * should({}, 'An empty object').exist(); |
| 235 * @result | 226 * @result |
| 236 * "PASS An empty object does exist." | 227 * "PASS An empty object does exist." |
| 237 */ | 228 */ |
| 238 exist () { | 229 exist () { |
| 239 return this._assert( | 230 return this._assert( |
| 240 this._actual !== null && this._actual !== undefined, | 231 this._actual !== null && this._actual !== undefined, |
| 241 '${actual} does exist.', | 232 '${actual} does exist.', |
| 242 '${actual} does *NOT* exist.'); | 233 '${actual} does not exist.'); |
| 243 } | 234 } |
| 244 | 235 |
| 245 /** | 236 /** |
| 246 * Check if |actual| operation wrapped in a function throws an exception | 237 * Check if |actual| operation wrapped in a function throws an exception |
| 247 * with a expected error type correctly. |expected| is optional. | 238 * with a expected error type correctly. |expected| is optional. |
| 248 * | 239 * |
| 249 * @example | 240 * @example |
| 250 * should(() => { let a = b; }, 'A bad code').throw(); | 241 * should(() => { let a = b; }, 'A bad code').throw(); |
| 251 * should(() => { let c = d; }, 'Assigning d to c.') | 242 * should(() => { let c = d; }, 'Assigning d to c.') |
| 252 * .throw('ReferenceError'); | 243 * .throw('ReferenceError'); |
| 253 * | 244 * |
| 254 * @result | 245 * @result |
| 255 * "PASS A bad code threw an exception of ReferenceError." | 246 * "PASS A bad code threw an exception of ReferenceError." |
| 256 * "PASS Assigning d to c threw ReferenceError." | 247 * "PASS Assigning d to c threw ReferenceError." |
| 257 */ | 248 */ |
| 258 throw () { | 249 throw () { |
| 259 this._processArguments(arguments); | 250 this._processArguments(arguments); |
| 260 | 251 |
| 261 let didThrowCorrectly = false; | 252 let didThrowCorrectly = false; |
| 262 let passDetail, failDetail; | 253 let passDetail, failDetail; |
| 263 | 254 |
| 264 try { | 255 try { |
| 265 // This should throw. | 256 // This should throw. |
| 266 this._actual(); | 257 this._actual(); |
| 267 // Catch did not happen, so the test is failed. | 258 // Catch did not happen, so the test is failed. |
| 268 failDetail = '${actual} did *NOT* throw an exception.'; | 259 failDetail = '${actual} did not throw an exception.'; |
| 269 } catch (error) { | 260 } catch (error) { |
| 270 if (this._expected === undefined) { | 261 if (this._expected === undefined) { |
| 271 didThrowCorrectly = true; | 262 didThrowCorrectly = true; |
| 272 passDetail = '${actual} threw an exception of ' + error.name + '.'; | 263 passDetail = '${actual} threw an exception of ' + error.name + '.'; |
| 273 } else if (error.name === this._expected) { | 264 } else if (error.name === this._expected) { |
| 274 didThrowCorrectly = true; | 265 didThrowCorrectly = true; |
| 275 passDetail = '${actual} threw ${expected} : "' + error.message + '".'; | 266 passDetail = '${actual} threw ${expected} : "' + error.message + '".'; |
| 276 } else { | 267 } else { |
| 277 didThrowCorrectly = false; | 268 didThrowCorrectly = false; |
| 278 failDetail = '${actual} threw "' + error.name | 269 failDetail = '${actual} threw "' + error.name |
| (...skipping 16 matching lines...) Expand all Loading... |
| 295 */ | 286 */ |
| 296 notThrow () { | 287 notThrow () { |
| 297 let didThrowCorrectly = false; | 288 let didThrowCorrectly = false; |
| 298 let passDetail, failDetail; | 289 let passDetail, failDetail; |
| 299 | 290 |
| 300 try { | 291 try { |
| 301 this._actual(); | 292 this._actual(); |
| 302 passDetail = '${actual} did not throw an exception.'; | 293 passDetail = '${actual} did not throw an exception.'; |
| 303 } catch (error) { | 294 } catch (error) { |
| 304 didThrowCorrectly = true; | 295 didThrowCorrectly = true; |
| 305 failDetail = '${actual} threw ' + error.name + ': ' | 296 failDetail = '${actual} incorrectly threw ' + error.name + ': "' |
| 306 + error.message + '.'; | 297 + error.message + '".'; |
| 307 } | 298 } |
| 308 | 299 |
| 309 return this._assert(!didThrowCorrectly, passDetail, failDetail); | 300 return this._assert(!didThrowCorrectly, passDetail, failDetail); |
| 310 } | 301 } |
| 311 | 302 |
| 312 /** | 303 /** |
| 313 * Check if |actual| promise is resolved correctly. | 304 * Check if |actual| promise is resolved correctly. |
| 314 * | 305 * |
| 315 * @example | 306 * @example |
| 316 * should('My promise', promise).beResolve().then(nextStuff); | 307 * should('My promise', promise).beResolve().then(nextStuff); |
| 317 * | 308 * |
| 318 * @result | 309 * @result |
| 319 * "PASS My promise resolved correctly." | 310 * "PASS My promise resolved correctly." |
| 320 * "FAIL X My promise rejected *INCORRECTLY* with _ERROR_." | 311 * "FAIL X My promise rejected *INCORRECTLY* with _ERROR_." |
| 321 */ | 312 */ |
| 322 beResolved () { | 313 beResolved () { |
| 323 return this._actual.then(function () { | 314 return this._actual.then(function () { |
| 324 this._assert(true, '${actual} resolved correctly.', null); | 315 this._assert(true, '${actual} resolved correctly.', null); |
| 325 }.bind(this), function (error) { | 316 }.bind(this), function (error) { |
| 326 this._assert(false, null, | 317 this._assert(false, null, |
| 327 '${actual} rejected *INCORRECTLY* with ' + error + '.'); | 318 '${actual} rejected incorrectly with ' + error + '.'); |
| 328 }.bind(this)); | 319 }.bind(this)); |
| 329 } | 320 } |
| 330 | 321 |
| 331 /** | 322 /** |
| 332 * Check if |actual| promise is rejected correctly. | 323 * Check if |actual| promise is rejected correctly. |
| 333 * | 324 * |
| 334 * @example | 325 * @example |
| 335 * should('My promise', promise).beRejected().then(nextStuff); | 326 * should('My promise', promise).beRejected().then(nextStuff); |
| 336 * | 327 * |
| 337 * @result | 328 * @result |
| 338 * "PASS My promise rejected correctly (with _ERROR_)." | 329 * "PASS My promise rejected correctly (with _ERROR_)." |
| 339 * "FAIL X My promise resolved *INCORRECTLY*." | 330 * "FAIL X My promise resolved *INCORRECTLY*." |
| 340 */ | 331 */ |
| 341 beRejected () { | 332 beRejected () { |
| 342 return this._actual.then(function () { | 333 return this._actual.then(function () { |
| 343 this._assert(false, null, '${actual} resolved *INCORRECTLY*.'); | 334 this._assert(false, null, '${actual} resolved incorrectly.'); |
| 344 }.bind(this), function (error) { | 335 }.bind(this), function (error) { |
| 345 this._assert(true, | 336 this._assert(true, |
| 346 '${actual} rejected correctly with ' + error + '.', null); | 337 '${actual} rejected correctly with ' + error + '.', null); |
| 347 }.bind(this)); | 338 }.bind(this)); |
| 348 } | 339 } |
| 349 | 340 |
| 350 /** | 341 /** |
| 351 * Check if |actual| is a boolean true. | 342 * Check if |actual| is a boolean true. |
| 352 * | 343 * |
| 353 * @example | 344 * @example |
| 354 * should(3 < 5, '3 < 5').beTrue(); | 345 * should(3 < 5, '3 < 5').beTrue(); |
| 355 * | 346 * |
| 356 * @result | 347 * @result |
| 357 * "PASS 3 < 5 is true." | 348 * "PASS 3 < 5 is true." |
| 358 */ | 349 */ |
| 359 beTrue () { | 350 beTrue () { |
| 360 return this._assert( | 351 return this._assert( |
| 361 this._actual === true, | 352 this._actual === true, |
| 362 '${actual} is true.', | 353 '${actual} is true.', |
| 363 '${actual} is *NOT* true.'); | 354 '${actual} is not true.'); |
| 364 } | 355 } |
| 365 | 356 |
| 366 /** | 357 /** |
| 367 * Check if |actual| is a boolean false. | 358 * Check if |actual| is a boolean false. |
| 368 * | 359 * |
| 369 * @example | 360 * @example |
| 370 * should(3 > 5, '3 > 5').beFalse(); | 361 * should(3 > 5, '3 > 5').beFalse(); |
| 371 * | 362 * |
| 372 * @result | 363 * @result |
| 373 * "PASS 3 > 5 is false." | 364 * "PASS 3 > 5 is false." |
| 374 */ | 365 */ |
| 375 beFalse () { | 366 beFalse () { |
| 376 return this._assert( | 367 return this._assert( |
| 377 this._actual === false, | 368 this._actual === false, |
| 378 '${actual} is false.', | 369 '${actual} is false.', |
| 379 '${actual} is *NOT* false.'); | 370 '${actual} is not false.'); |
| 380 } | 371 } |
| 381 | 372 |
| 382 /** | 373 /** |
| 383 * Check if |actual| is strictly equal to |expected|. (no type coercion) | 374 * Check if |actual| is strictly equal to |expected|. (no type coercion) |
| 384 * | 375 * |
| 385 * @example | 376 * @example |
| 386 * should(1).beEqualTo(1); | 377 * should(1).beEqualTo(1); |
| 387 * | 378 * |
| 388 * @result | 379 * @result |
| 389 * "PASS 1 is equal to 1." | 380 * "PASS 1 is equal to 1." |
| 390 */ | 381 */ |
| 391 beEqualTo () { | 382 beEqualTo () { |
| 392 this._processArguments(arguments); | 383 this._processArguments(arguments); |
| 393 return this._assert( | 384 return this._assert( |
| 394 this._actual === this._expected, | 385 this._actual === this._expected, |
| 395 '${actual} is equal to ${expected}.', | 386 '${actual} is equal to ${expected}.', |
| 396 '${actual} is *NOT* equal to ${expected}.'); | 387 '${actual} is not equal to ${expected}.'); |
| 397 } | 388 } |
| 398 | 389 |
| 399 /** | 390 /** |
| 400 * Check if |actual| is not equal to |expected|. | 391 * Check if |actual| is not equal to |expected|. |
| 401 * | 392 * |
| 402 * @example | 393 * @example |
| 403 * should(1).notBeEqualTo(2); | 394 * should(1).notBeEqualTo(2); |
| 404 * | 395 * |
| 405 * @result | 396 * @result |
| 406 * "PASS 1 is *NOT* equal to 2." | 397 * "PASS 1 is not equal to 2." |
| 407 */ | 398 */ |
| 408 notBeEqualTo () { | 399 notBeEqualTo () { |
| 409 this._processArguments(arguments); | 400 this._processArguments(arguments); |
| 410 return this._assert( | 401 return this._assert( |
| 411 this._actual !== this._expected, | 402 this._actual !== this._expected, |
| 412 '${actual} is not equal to ${expected}.', | 403 '${actual} is not equal to ${expected}.', |
| 413 '${actual} should *NOT* be equal to ${expected}.'); | 404 '${actual} should not be equal to ${expected}.'); |
| 414 } | 405 } |
| 415 | 406 |
| 416 /** | 407 /** |
| 417 * Check if |actual| is greater than |expected|. | 408 * Check if |actual| is greater than |expected|. |
| 418 * | 409 * |
| 419 * @example | 410 * @example |
| 420 * should(2).beGreaterThanOrEqualTo(2); | 411 * should(2).beGreaterThanOrEqualTo(2); |
| 421 * | 412 * |
| 422 * @result | 413 * @result |
| 423 * "PASS 2 is greater than or equal to 2." | 414 * "PASS 2 is greater than or equal to 2." |
| 424 */ | 415 */ |
| 425 beGreaterThan () { | 416 beGreaterThan () { |
| 426 this._processArguments(arguments); | 417 this._processArguments(arguments); |
| 427 return this._assert( | 418 return this._assert( |
| 428 this._actual > this._expected, | 419 this._actual > this._expected, |
| 429 '${actual} is greater than ${expected}.', | 420 '${actual} is greater than ${expected}.', |
| 430 '${actual} is *NOT* greater than ${expected}.' | 421 '${actual} is not greater than ${expected}.' |
| 431 ); | 422 ); |
| 432 } | 423 } |
| 433 | 424 |
| 434 /** | 425 /** |
| 435 * Check if |actual| is greater than or equal to |expected|. | 426 * Check if |actual| is greater than or equal to |expected|. |
| 436 * | 427 * |
| 437 * @example | 428 * @example |
| 438 * should(2).beGreaterThan(1); | 429 * should(2).beGreaterThan(1); |
| 439 * | 430 * |
| 440 * @result | 431 * @result |
| 441 * "PASS 2 is greater than 1." | 432 * "PASS 2 is greater than 1." |
| 442 */ | 433 */ |
| 443 beGreaterThanOrEqualTo () { | 434 beGreaterThanOrEqualTo () { |
| 444 this._processArguments(arguments); | 435 this._processArguments(arguments); |
| 445 return this._assert( | 436 return this._assert( |
| 446 this._actual >= this._expected, | 437 this._actual >= this._expected, |
| 447 '${actual} is greater than or equal to ${expected}.', | 438 '${actual} is greater than or equal to ${expected}.', |
| 448 '${actual} is *NOT* greater than or equal to ${expected}.' | 439 '${actual} is not greater than or equal to ${expected}.' |
| 449 ); | 440 ); |
| 450 } | 441 } |
| 451 | 442 |
| 452 /** | 443 /** |
| 453 * Check if |actual| is less than |expected|. | 444 * Check if |actual| is less than |expected|. |
| 454 * | 445 * |
| 455 * @example | 446 * @example |
| 456 * should(1).beLessThan(2); | 447 * should(1).beLessThan(2); |
| 457 * | 448 * |
| 458 * @result | 449 * @result |
| 459 * "PASS 1 is less than 2." | 450 * "PASS 1 is less than 2." |
| 460 */ | 451 */ |
| 461 beLessThan () { | 452 beLessThan () { |
| 462 this._processArguments(arguments); | 453 this._processArguments(arguments); |
| 463 return this._assert( | 454 return this._assert( |
| 464 this._actual < this._expected, | 455 this._actual < this._expected, |
| 465 '${actual} is less than ${expected}.', | 456 '${actual} is less than ${expected}.', |
| 466 '${actual} is *NOT* less than ${expected}.' | 457 '${actual} is not less than ${expected}.' |
| 467 ); | 458 ); |
| 468 } | 459 } |
| 469 | 460 |
| 470 /** | 461 /** |
| 471 * Check if |actual| is less than or equal to |expected|. | 462 * Check if |actual| is less than or equal to |expected|. |
| 472 * | 463 * |
| 473 * @example | 464 * @example |
| 474 * should(1).beLessThanOrEqualTo(1); | 465 * should(1).beLessThanOrEqualTo(1); |
| 475 * | 466 * |
| 476 * @result | 467 * @result |
| 477 * "PASS 1 is less than or equal to 1." | 468 * "PASS 1 is less than or equal to 1." |
| 478 */ | 469 */ |
| 479 beLessThanOrEqualTo () { | 470 beLessThanOrEqualTo () { |
| 480 this._processArguments(arguments); | 471 this._processArguments(arguments); |
| 481 return this._assert( | 472 return this._assert( |
| 482 this._actual <= this._expected, | 473 this._actual <= this._expected, |
| 483 '${actual} is less than or equal to ${expected}.', | 474 '${actual} is less than or equal to ${expected}.', |
| 484 '${actual} is *NOT* less than or equal to ${expected}.' | 475 '${actual} is not less than or equal to ${expected}.' |
| 485 ); | 476 ); |
| 486 } | 477 } |
| 487 | 478 |
| 488 /** | 479 /** |
| 489 * Check if |actual| array is filled with a constant |expected| value. | 480 * Check if |actual| array is filled with a constant |expected| value. |
| 490 * | 481 * |
| 491 * @example | 482 * @example |
| 492 * should([1, 1, 1]).beConstantValueOf(1); | 483 * should([1, 1, 1]).beConstantValueOf(1); |
| 493 * | 484 * |
| 494 * @result | 485 * @result |
| (...skipping 11 matching lines...) Expand all Loading... |
| 506 errors[index] = this._actual[index]; | 497 errors[index] = this._actual[index]; |
| 507 } | 498 } |
| 508 | 499 |
| 509 let numberOfErrors = Object.keys(errors).length; | 500 let numberOfErrors = Object.keys(errors).length; |
| 510 passed = numberOfErrors === 0; | 501 passed = numberOfErrors === 0; |
| 511 | 502 |
| 512 if (passed) { | 503 if (passed) { |
| 513 passDetail = '${actual} contains only the constant ${expected}.'; | 504 passDetail = '${actual} contains only the constant ${expected}.'; |
| 514 } else { | 505 } else { |
| 515 let counter = 0; | 506 let counter = 0; |
| 516 failDetail = '${actual} contains ' + numberOfErrors | 507 failDetail = 'Expected ${expected} for all values but found ' |
| 517 + ' values that are *NOT* equal to ${expected}: '; | 508 + numberOfErrors + ' unexpected values. : '; |
| 518 failDetail += '\n\tIndex\tActual'; | 509 failDetail += '\n\tIndex\tActual'; |
| 519 for (let errorIndex in errors) { | 510 for (let errorIndex in errors) { |
| 520 failDetail += '\n\t[' + errorIndex + ']' | 511 failDetail += '\n\t[' + errorIndex + ']' |
| 521 + '\t' + errors[errorIndex]; | 512 + '\t' + errors[errorIndex]; |
| 522 if (++counter >= this._options.numberOfErrors) { | 513 if (++counter >= this._options.numberOfErrors) { |
| 523 failDetail += '\n\t...and ' + (numberOfErrors - counter) | 514 failDetail += '\n\t...and ' + (numberOfErrors - counter) |
| 524 + ' more errors.'; | 515 + ' more errors.'; |
| 525 break; | 516 break; |
| 526 } | 517 } |
| 527 } | 518 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 541 */ | 532 */ |
| 542 beEqualToArray () { | 533 beEqualToArray () { |
| 543 this._processArguments(arguments); | 534 this._processArguments(arguments); |
| 544 | 535 |
| 545 let passed = true; | 536 let passed = true; |
| 546 let passDetail, failDetail; | 537 let passDetail, failDetail; |
| 547 let errorIndices = []; | 538 let errorIndices = []; |
| 548 | 539 |
| 549 if (this._actual.length !== this._expected.length) { | 540 if (this._actual.length !== this._expected.length) { |
| 550 passed = false; | 541 passed = false; |
| 551 failDetail = 'The array length does *NOT* match.'; | 542 failDetail = 'The array length does not match.'; |
| 552 return this._assert(passed, passDetail, failDetail); | 543 return this._assert(passed, passDetail, failDetail); |
| 553 } | 544 } |
| 554 | 545 |
| 555 for (let index in this._actual) { | 546 for (let index in this._actual) { |
| 556 if (this._actual[index] !== this._expected[index]) | 547 if (this._actual[index] !== this._expected[index]) |
| 557 errorIndices.push(index); | 548 errorIndices.push(index); |
| 558 } | 549 } |
| 559 | 550 |
| 560 passed = errorIndices.length === 0; | 551 passed = errorIndices.length === 0; |
| 561 | 552 |
| 562 if (passed) { | 553 if (passed) { |
| 563 passDetail = '${actual} is identical to the array ${expected}.'; | 554 passDetail = '${actual} is identical to the array ${expected}.'; |
| 564 } else { | 555 } else { |
| 565 let counter = 0; | 556 let counter = 0; |
| 566 failDetail = '${actual} contains ' + errorIndices.length | 557 failDetail = '${actual} expected to be equal to the array ${expected} ' |
| 567 + ' values that are *NOT* equal to ${expected}: '; | 558 + 'but differs in ' + errorIndices.length + ' places:' |
| 568 failDetail += '\n\tIndex\tActual\t\t\tExpected'; | 559 + '\n\tIndex\tActual\t\t\tExpected'; |
| 569 for (let index of errorIndices) { | 560 for (let index of errorIndices) { |
| 570 failDetail += '\n\t[' + index + ']' | 561 failDetail += '\n\t[' + index + ']' |
| 571 + '\t' + this._actual[index].toExponential(16) | 562 + '\t' + this._actual[index].toExponential(16) |
| 572 + '\t' + this._expected[index].toExponential(16); | 563 + '\t' + this._expected[index].toExponential(16); |
| 573 if (++counter >= this._options.numberOfErrors) { | 564 if (++counter >= this._options.numberOfErrors) { |
| 574 failDetail += '\n\t...and ' + (numberOfErrors - counter) | 565 failDetail += '\n\t...and ' + (numberOfErrors - counter) |
| 575 + ' more errors.'; | 566 + ' more errors.'; |
| 576 break; | 567 break; |
| 577 } | 568 } |
| 578 } | 569 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 589 * Should([1, 1, 3, 3, 2], 'My random array').containValues([1, 3, 2]); | 580 * Should([1, 1, 3, 3, 2], 'My random array').containValues([1, 3, 2]); |
| 590 * | 581 * |
| 591 * @result | 582 * @result |
| 592 * "PASS [1,1,3,3,2] contains all the expected values in the correct | 583 * "PASS [1,1,3,3,2] contains all the expected values in the correct |
| 593 * order: [1,3,2]. | 584 * order: [1,3,2]. |
| 594 */ | 585 */ |
| 595 containValues () { | 586 containValues () { |
| 596 this._processArguments(arguments); | 587 this._processArguments(arguments); |
| 597 | 588 |
| 598 let passed = true; | 589 let passed = true; |
| 599 let indexActual = 0, indexExpected = 0; | 590 let indexedActual = []; |
| 591 let firstErrorIndex = null; |
| 600 | 592 |
| 601 while (indexActual < this._actual.length | 593 // Collect the unique value sequence from the actual. |
| 602 && indexExpected < this._expected.length) { | 594 for (let i = 0, prev = null; i < this._actual.length; i++) { |
| 603 if (this._actual[indexActual] === this._expected[indexExpected]) { | 595 if (this._actual[i] !== prev) { |
| 604 indexActual++; | 596 indexedActual.push({ |
| 605 } else { | 597 index: i, |
| 606 indexExpected++; | 598 value: this._actual[i] |
| 599 }); |
| 600 prev = this._actual[i]; |
| 607 } | 601 } |
| 608 } | 602 } |
| 609 | 603 |
| 610 passed = !(indexActual < this._actual.length - 1 | 604 // Compare against the expected sequence. |
| 611 || indexExpected < this._expected.length - 1); | 605 for (let j = 0; j < this._expected.length; j++) { |
| 606 if (this._expected[j] !== indexedActual[j].value) { |
| 607 firstErrorIndex = indexedActual[j].index; |
| 608 passed = false; |
| 609 break; |
| 610 } |
| 611 } |
| 612 | 612 |
| 613 return this._assert( | 613 return this._assert( |
| 614 passed, | 614 passed, |
| 615 '${actual} contains all the expected values in the correct order: ' | 615 '${actual} contains all the expected values in the correct order: ' |
| 616 + '${expected}.', | 616 + '${expected}.', |
| 617 '${actual} contains an unexpected value of ' | 617 '${actual} expected to have the value sequence of ${expected} but ' |
| 618 + this._actual[indexActual] + ' at index ' + indexActual + '.'); | 618 + 'got ' + this._actual[firstErrorIndex] + ' at index ' |
| 619 + firstErrorIndex + '.'); |
| 619 } | 620 } |
| 620 | 621 |
| 621 /** | 622 /** |
| 622 * Check if |actual| array does not have any glitches. Note that |threshold| | 623 * Check if |actual| array does not have any glitches. Note that |threshold| |
| 623 * is not optional and is to define the desired threshold value. | 624 * is not optional and is to define the desired threshold value. |
| 624 * | 625 * |
| 625 * @example | 626 * @example |
| 626 * should([0.5, 0.5, 0.55, 0.5, 0.45, 0.5]).notGlitch(0.06); | 627 * should([0.5, 0.5, 0.55, 0.5, 0.45, 0.5]).notGlitch(0.06); |
| 627 * | 628 * |
| 628 * @result | 629 * @result |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 */ | 666 */ |
| 666 beCloseTo () { | 667 beCloseTo () { |
| 667 this._processArguments(arguments); | 668 this._processArguments(arguments); |
| 668 | 669 |
| 669 // The threshold is relative except when |expected| is zero, in which case | 670 // The threshold is relative except when |expected| is zero, in which case |
| 670 // it is absolute. | 671 // it is absolute. |
| 671 let absExpected = this._expected ? Math.abs(this._expected) : 1; | 672 let absExpected = this._expected ? Math.abs(this._expected) : 1; |
| 672 let error = Math.abs(this._actual - this._expected) / absExpected; | 673 let error = Math.abs(this._actual - this._expected) / absExpected; |
| 673 | 674 |
| 674 return this._assert( | 675 return this._assert( |
| 675 error <= this._options.threshold, | 676 error <= this._options.threshold, |
| 676 '${actual} is ${expected} within an error of ${threshold}.', | 677 '${actual} is ${expected} within an error of ${threshold}.', |
| 677 '${actual} is not ${expected} within an error of ${threshold}: ' + | 678 '${actual} is not close to ${expected} within an error of ' + |
| 678 '${actual} with error of ${threshold}.'); | 679 '${threshold}'); |
| 679 } | 680 } |
| 680 | 681 |
| 681 /** | 682 /** |
| 682 * Check if |target| array is close to |expected| array element-wise within | 683 * Check if |target| array is close to |expected| array element-wise within |
| 683 * a certain error bound given by the |options|. | 684 * a certain error bound given by the |options|. |
| 684 * | 685 * |
| 685 * The error criterion is: | 686 * The error criterion is: |
| 686 * abs(actual[k] - expected[k]) < max(absErr, relErr * abs(expected)) | 687 * abs(actual[k] - expected[k]) < max(absErr, relErr * abs(expected)) |
| 687 * | 688 * |
| 688 * If nothing is given for |options|, then absErr = relErr = 0. If | 689 * If nothing is given for |options|, then absErr = relErr = 0. If |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 970 } | 971 } |
| 971 | 972 |
| 972 // Start the first task. | 973 // Start the first task. |
| 973 this._currentTaskIndex = 0; | 974 this._currentTaskIndex = 0; |
| 974 this._runNextTask(); | 975 this._runNextTask(); |
| 975 } | 976 } |
| 976 | 977 |
| 977 } | 978 } |
| 978 | 979 |
| 979 | 980 |
| 981 /** |
| 982 * @class Audit |
| 983 * @description A WebAudio layout test task manager. |
| 984 * @example |
| 985 * let audit = Audit.createTaskRunner(); |
| 986 * audit.define('first-task', function (task, should) { |
| 987 * task.describe('the first task'); |
| 988 * should(someValue).beEqualTo(someValue); |
| 989 * task.done(); |
| 990 * }); |
| 991 * audit.run(); |
| 992 */ |
| 980 return { | 993 return { |
| 981 | 994 |
| 982 /** | 995 /** |
| 983 * Creates an instance of Audit task runner. | 996 * Creates an instance of Audit task runner. |
| 997 * @param {Object} options Options for task runner. |
| 998 * @param {Boolean} options.requireResultFile True if the test suite |
| 999 * requires explicit text |
| 1000 * comparison with the expected |
| 1001 * result file. |
| 984 */ | 1002 */ |
| 985 createTaskRunner: function () { | 1003 createTaskRunner: function (options) { |
| 1004 if (options && options.requireResultFile == true) { |
| 1005 _logError('this test requires the explicit comparison with the ' |
| 1006 + 'expected result when it runs with run-webkit-tests.'); |
| 1007 } |
| 1008 |
| 986 return new TaskRunner(); | 1009 return new TaskRunner(); |
| 987 } | 1010 } |
| 988 | 1011 |
| 989 }; | 1012 }; |
| 990 | 1013 |
| 991 })(); | 1014 })(); |
| OLD | NEW |