audionodeoptions.js (18338B)
1 // Test that constructor for the node with name |nodeName| handles the 2 // various possible values for channelCount, channelCountMode, and 3 // channelInterpretation. 4 5 // The |should| parameter is the test function from new |Audit|. 6 function testAudioNodeOptions(should, context, nodeName, expectedNodeOptions) { 7 if (expectedNodeOptions === undefined) 8 expectedNodeOptions = {}; 9 let node; 10 11 // Test that we can set channelCount and that errors are thrown for 12 // invalid values 13 let testChannelCount = 17; 14 if (expectedNodeOptions.channelCount) { 15 testChannelCount = expectedNodeOptions.channelCount.value; 16 } 17 should( 18 () => { 19 node = new window[nodeName]( 20 context, Object.assign({}, expectedNodeOptions.additionalOptions, { 21 channelCount: testChannelCount 22 })); 23 }, 24 'new ' + nodeName + '(c, {channelCount: ' + testChannelCount + '})') 25 .notThrow(); 26 should(node.channelCount, 'node.channelCount').beEqualTo(testChannelCount); 27 28 if (expectedNodeOptions.channelCount && 29 expectedNodeOptions.channelCount.isFixed) { 30 // The channel count is fixed. Verify that we throw an error if 31 // we try to change it. Arbitrarily set the count to be one more 32 // than the expected value. 33 testChannelCount = expectedNodeOptions.channelCount.value + 1; 34 should( 35 () => { 36 node = new window[nodeName]( 37 context, 38 Object.assign( 39 {}, expectedNodeOptions.additionalOptions, 40 {channelCount: testChannelCount})); 41 }, 42 'new ' + nodeName + '(c, {channelCount: ' + testChannelCount + '})') 43 .throw(DOMException, 44 expectedNodeOptions.channelCount.exceptionType); 45 // And test that setting it to the fixed value does not throw. 46 testChannelCount = expectedNodeOptions.channelCount.value; 47 should( 48 () => { 49 node = new window[nodeName]( 50 context, 51 Object.assign( 52 {}, expectedNodeOptions.additionalOptions, 53 {channelCount: testChannelCount})); 54 node.channelCount = testChannelCount; 55 }, 56 '(new ' + nodeName + '(c, {channelCount: ' + testChannelCount + '})).channelCount = ' + testChannelCount) 57 .notThrow(); 58 } else { 59 // The channel count is not fixed. Try to set the count to invalid 60 // values and make sure an error is thrown. 61 [0, 99].forEach(testValue => { 62 should(() => { 63 node = new window[nodeName]( 64 context, Object.assign({}, expectedNodeOptions.additionalOptions, { 65 channelCount: testValue 66 })); 67 }, `new ${nodeName}(c, {channelCount: ${testValue}})`) 68 .throw(DOMException, 'NotSupportedError'); 69 }); 70 } 71 72 // Test channelCountMode 73 let testChannelCountMode = 'max'; 74 if (expectedNodeOptions.channelCountMode) { 75 testChannelCountMode = expectedNodeOptions.channelCountMode.value; 76 } 77 should( 78 () => { 79 node = new window[nodeName]( 80 context, Object.assign({}, expectedNodeOptions.additionalOptions, { 81 channelCountMode: testChannelCountMode 82 })); 83 }, 84 'new ' + nodeName + '(c, {channelCountMode: "' + testChannelCountMode + 85 '"}') 86 .notThrow(); 87 should(node.channelCountMode, 'node.channelCountMode') 88 .beEqualTo(testChannelCountMode); 89 90 if (expectedNodeOptions.channelCountMode && 91 expectedNodeOptions.channelCountMode.isFixed) { 92 // Channel count mode is fixed. Test setting to something else throws. 93 ['max', 'clamped-max', 'explicit'].forEach(testValue => { 94 if (testValue !== expectedNodeOptions.channelCountMode.value) { 95 should( 96 () => { 97 node = new window[nodeName]( 98 context, 99 Object.assign( 100 {}, expectedNodeOptions.additionalOptions, 101 {channelCountMode: testValue})); 102 }, 103 `new ${nodeName}(c, {channelCountMode: "${testValue}"})`) 104 .throw(DOMException, 105 expectedNodeOptions.channelCountMode.exceptionType); 106 } else { 107 // Test that explicitly setting the fixed value is allowed. 108 should( 109 () => { 110 node = new window[nodeName]( 111 context, 112 Object.assign( 113 {}, expectedNodeOptions.additionalOptions, 114 {channelCountMode: testValue})); 115 node.channelCountMode = testValue; 116 }, 117 `(new ${nodeName}(c, {channelCountMode: "${testValue}"})).channelCountMode = "${testValue}"`) 118 .notThrow(); 119 } 120 }); 121 } else { 122 // Mode is not fixed. Verify that we can set the mode to all valid 123 // values, and that we throw for invalid values. 124 125 let testValues = ['max', 'clamped-max', 'explicit']; 126 127 testValues.forEach(testValue => { 128 should(() => { 129 node = new window[nodeName]( 130 context, Object.assign({}, expectedNodeOptions.additionalOptions, { 131 channelCountMode: testValue 132 })); 133 }, `new ${nodeName}(c, {channelCountMode: "${testValue}"})`).notThrow(); 134 should( 135 node.channelCountMode, 'node.channelCountMode after valid setter') 136 .beEqualTo(testValue); 137 138 }); 139 140 should( 141 () => { 142 node = new window[nodeName]( 143 context, 144 Object.assign( 145 {}, expectedNodeOptions.additionalOptions, 146 {channelCountMode: 'foobar'})); 147 }, 148 'new ' + nodeName + '(c, {channelCountMode: "foobar"}') 149 .throw(TypeError); 150 should(node.channelCountMode, 'node.channelCountMode after invalid setter') 151 .beEqualTo(testValues[testValues.length - 1]); 152 } 153 154 // Test channelInterpretation 155 if (expectedNodeOptions.channelInterpretation && 156 expectedNodeOptions.channelInterpretation.isFixed) { 157 // The channel interpretation is fixed. Verify that we throw an 158 // error if we try to change it. 159 ['speakers', 'discrete'].forEach(testValue => { 160 if (testValue !== expectedNodeOptions.channelInterpretation.value) { 161 should( 162 () => { 163 node = new window[nodeName]( 164 context, 165 Object.assign( 166 {}, expectedNodeOptions.additionOptions, 167 {channelInterpretation: testValue})); 168 }, 169 `new ${nodeName}(c, {channelInterpretation: "${testValue}"})`) 170 .throw(DOMException, 171 expectedNodeOptions.channelCountMode.exceptionType); 172 } else { 173 // Check that assigning the fixed value is OK. 174 should( 175 () => { 176 node = new window[nodeName]( 177 context, 178 Object.assign( 179 {}, expectedNodeOptions.additionOptions, 180 {channelInterpretation: testValue})); 181 node.channelInterpretation = testValue; 182 }, 183 `(new ${nodeName}(c, {channelInterpretation: "${testValue}"})).channelInterpretation = "${testValue}"`) 184 .notThrow(); 185 } 186 }); 187 } else { 188 // Channel interpretation is not fixed. Verify that we can set it 189 // to all possible values. 190 should( 191 () => { 192 node = new window[nodeName]( 193 context, 194 Object.assign( 195 {}, expectedNodeOptions.additionalOptions, 196 {channelInterpretation: 'speakers'})); 197 }, 198 'new ' + nodeName + '(c, {channelInterpretation: "speakers"})') 199 .notThrow(); 200 should(node.channelInterpretation, 'node.channelInterpretation') 201 .beEqualTo('speakers'); 202 203 should( 204 () => { 205 node = new window[nodeName]( 206 context, 207 Object.assign( 208 {}, expectedNodeOptions.additionalOptions, 209 {channelInterpretation: 'discrete'})); 210 }, 211 'new ' + nodeName + '(c, {channelInterpretation: "discrete"})') 212 .notThrow(); 213 should(node.channelInterpretation, 'node.channelInterpretation') 214 .beEqualTo('discrete'); 215 216 should( 217 () => { 218 node = new window[nodeName]( 219 context, 220 Object.assign( 221 {}, expectedNodeOptions.additionalOptions, 222 {channelInterpretation: 'foobar'})); 223 }, 224 'new ' + nodeName + '(c, {channelInterpretation: "foobar"})') 225 .throw(TypeError); 226 should( 227 node.channelInterpretation, 228 'node.channelInterpretation after invalid setter') 229 .beEqualTo('discrete'); 230 } 231 } 232 233 function initializeContext(should) { 234 let c; 235 should(() => { 236 c = new OfflineAudioContext(1, 1, 48000); 237 }, 'context = new OfflineAudioContext(...)').notThrow(); 238 239 return c; 240 } 241 242 function testInvalidConstructor(should, name, context) { 243 should(() => { 244 new window[name](); 245 }, 'new ' + name + '()').throw(TypeError); 246 should(() => { 247 new window[name](1); 248 }, 'new ' + name + '(1)').throw(TypeError); 249 should(() => { 250 new window[name](context, 42); 251 }, 'new ' + name + '(context, 42)').throw(TypeError); 252 } 253 254 function testDefaultConstructor(should, name, context, options) { 255 let node; 256 257 let message = options.prefix + ' = new ' + name + '(context'; 258 if (options.constructorOptions) 259 message += ', ' + JSON.stringify(options.constructorOptions); 260 message += ')' 261 262 should(() => { 263 node = new window[name](context, options.constructorOptions); 264 }, message).notThrow(); 265 266 should(node instanceof window[name], options.prefix + ' instanceof ' + name) 267 .beEqualTo(true); 268 should(node.numberOfInputs, options.prefix + '.numberOfInputs') 269 .beEqualTo(options.numberOfInputs); 270 should(node.numberOfOutputs, options.prefix + '.numberOfOutputs') 271 .beEqualTo(options.numberOfOutputs); 272 should(node.channelCount, options.prefix + '.channelCount') 273 .beEqualTo(options.channelCount); 274 should(node.channelCountMode, options.prefix + '.channelCountMode') 275 .beEqualTo(options.channelCountMode); 276 should(node.channelInterpretation, options.prefix + '.channelInterpretation') 277 .beEqualTo(options.channelInterpretation); 278 279 return node; 280 } 281 282 function testDefaultAttributes(should, node, prefix, items) { 283 items.forEach((item) => { 284 let attr = node[item.name]; 285 if (attr instanceof AudioParam) { 286 should(attr.value, prefix + '.' + item.name + '.value') 287 .beEqualTo(item.value); 288 } else { 289 should(attr, prefix + '.' + item.name).beEqualTo(item.value); 290 } 291 }); 292 } 293 294 // Test that constructor for the node with name |nodeName| handles the 295 // various possible values for channelCount, channelCountMode, and 296 // channelInterpretation. 297 298 // (Todo: Punith, Saqlain) Will be replaced with original function names 299 // after we are done with converting all the tests that require these functions 300 // from audit.js to testharness.js 301 302 function testAudioNodeOptions_W3CTH(context, nodeName, expectedNodeOptions) { 303 if (expectedNodeOptions === undefined) 304 expectedNodeOptions = {}; 305 let node; 306 307 // Test that we can set channelCount and that errors are thrown for 308 // invalid values 309 let testChannelCount = 17; 310 if (expectedNodeOptions.channelCount) { 311 testChannelCount = expectedNodeOptions.channelCount.value; 312 } 313 314 node = new window[nodeName]( 315 context, 316 Object.assign({}, expectedNodeOptions.additionalOptions, { 317 channelCount: testChannelCount 318 })); 319 assert_equals(node.channelCount, testChannelCount, 'node.channelCount'); 320 321 if (expectedNodeOptions.channelCount && 322 expectedNodeOptions.channelCount.isFixed) { 323 // The channel count is fixed. Verify that we throw an error if 324 // we try to change it. Arbitrarily set the count to be one more 325 // than the expected value. 326 const invalidCount = expectedNodeOptions.channelCount.value + 1; 327 assert_throws_dom( 328 expectedNodeOptions.channelCount.exceptionType, 329 () => new window[nodeName]( 330 context, 331 Object.assign({}, expectedNodeOptions.additionalOptions, { 332 channelCount: invalidCount 333 })), 334 `new ${nodeName}(context, {channelCount: ${invalidCount}})`); 335 336 // And test that setting it to the fixed value does not throw. 337 testChannelCount = expectedNodeOptions.channelCount.value; 338 node = new window[nodeName]( 339 context, 340 Object.assign({}, expectedNodeOptions.additionalOptions, { 341 channelCount: testChannelCount 342 })); 343 node.channelCount = testChannelCount; 344 } else { 345 // The channel count is not fixed. Try to set the count to invalid 346 // values and make sure an error is thrown. 347 [0, 99].forEach(testValue => { 348 assert_throws_dom( 349 'NotSupportedError', 350 () => new window[nodeName]( 351 context, 352 Object.assign({}, expectedNodeOptions.additionalOptions, { 353 channelCount: testValue 354 })), 355 `new ${nodeName}(context, {channelCount: ${testValue}})`); 356 }); 357 } 358 359 // Test channelCountMode 360 let testChannelCountMode = 'max'; 361 if (expectedNodeOptions.channelCountMode) { 362 testChannelCountMode = expectedNodeOptions.channelCountMode.value; 363 } 364 365 node = new window[nodeName]( 366 context, 367 Object.assign({}, expectedNodeOptions.additionalOptions, { 368 channelCountMode: testChannelCountMode 369 })); 370 assert_equals( 371 node.channelCountMode, 372 testChannelCountMode, 373 'node.channelCountMode'); 374 375 if (expectedNodeOptions.channelCountMode && 376 expectedNodeOptions.channelCountMode.isFixed) { 377 ['max', 'clamped-max', 'explicit'].forEach(testValue => { 378 if (testValue !== expectedNodeOptions.channelCountMode.value) { 379 assert_throws_dom( 380 expectedNodeOptions.channelCountMode.exceptionType, 381 () => new window[nodeName]( 382 context, 383 Object.assign({}, expectedNodeOptions.additionalOptions, { 384 channelCountMode: testValue 385 })), 386 `new ${nodeName}(context, {channelCountMode: "${testValue}"})`); 387 } else { 388 node = new window[nodeName]( 389 context, 390 Object.assign({}, expectedNodeOptions.additionalOptions, { 391 channelCountMode: testValue 392 })); 393 node.channelCountMode = testValue; 394 } 395 }); 396 } else { 397 ['max', 'clamped-max', 'explicit'].forEach(testValue => { 398 node = new window[nodeName]( 399 context, 400 Object.assign({}, expectedNodeOptions.additionalOptions, { 401 channelCountMode: testValue 402 })); 403 assert_equals( 404 node.channelCountMode, 405 testValue, 406 `node.channelCountMode after setting to ${testValue}`); 407 }); 408 409 assert_throws_js( 410 TypeError, 411 () => new window[nodeName]( 412 context, 413 Object.assign({}, expectedNodeOptions.additionalOptions, { 414 channelCountMode: 'foobar' 415 })), 416 'Invalid channelCountMode should throw'); 417 } 418 419 // Test channelInterpretation 420 if (expectedNodeOptions.channelInterpretation && 421 expectedNodeOptions.channelInterpretation.isFixed) { 422 ['speakers', 'discrete'].forEach(testValue => { 423 if (testValue !== expectedNodeOptions.channelInterpretation.value) { 424 assert_throws_dom( 425 expectedNodeOptions.channelCountMode.exceptionType, 426 () => new window[nodeName]( 427 context, 428 Object.assign({}, expectedNodeOptions.additionalOptions, { 429 channelInterpretation: testValue 430 })), 431 `new ${nodeName}(context, {channelInterpretation: "${testValue}"})`); 432 } else { 433 node = new window[nodeName]( 434 context, 435 Object.assign({}, expectedNodeOptions.additionalOptions, { 436 channelInterpretation: testValue 437 })); 438 node.channelInterpretation = testValue; 439 } 440 }); 441 } else { 442 node = new window[nodeName]( 443 context, 444 Object.assign({}, expectedNodeOptions.additionalOptions, { 445 channelInterpretation: 'speakers' 446 })); 447 assert_equals(node.channelInterpretation, 'speakers'); 448 449 node = new window[nodeName]( 450 context, 451 Object.assign({}, expectedNodeOptions.additionalOptions, { 452 channelInterpretation: 'discrete' 453 })); 454 assert_equals(node.channelInterpretation, 'discrete'); 455 456 assert_throws_js( 457 TypeError, 458 () => new window[nodeName]( 459 context, 460 Object.assign({}, expectedNodeOptions.additionalOptions, { 461 channelInterpretation: 'foobar' 462 })), 463 'Invalid channelInterpretation should throw'); 464 } 465 } 466 467 function testInvalidConstructor_W3CTH(name, context) { 468 assert_throws_js(TypeError, () => new window[name](), 'new ' + name + '()'); 469 assert_throws_js(TypeError, () => new window , 'new ' + name + '(1)'); 470 assert_throws_js( 471 TypeError, 472 () => new window[name](context, 42), 'new ' + name + '(context, 42)'); 473 } 474 475 function testDefaultConstructor_W3CTH(name, context, options) { 476 let node; 477 478 node = new window[name](context, options.constructorOptions); 479 480 assert_true( 481 node instanceof window[name], 482 `${options.prefix} instanceof ${name}`); 483 assert_equals( 484 node.numberOfInputs, options.numberOfInputs, 485 `${options.prefix}.numberOfInputs`); 486 assert_equals( 487 node.numberOfOutputs, options.numberOfOutputs, 488 `${options.prefix}.numberOfOutputs`); 489 assert_equals( 490 node.channelCount, options.channelCount, 491 `${options.prefix}.channelCount`); 492 assert_equals( 493 node.channelCountMode, options.channelCountMode, 494 `${options.prefix}.channelCountMode`); 495 assert_equals( 496 node.channelInterpretation, options.channelInterpretation, 497 `${options.prefix}.channelInterpretation`); 498 499 return node; 500 } 501 502 function testDefaultAttributes_W3CTH(node, prefix, items) { 503 items.forEach((item) => { 504 const attr = node[item.name]; 505 if (attr instanceof AudioParam) { 506 assert_equals(attr.value, item.value, `${prefix}.${item.name}.value`); 507 } else { 508 assert_equals(attr, item.value, `${prefix}.${item.name}`); 509 } 510 }); 511 }