1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// Include test fixture. 6GEN_INCLUDE(['../testing/chromevox_unittest_base.js']); 7 8/** 9 * Test fixture. 10 * @constructor 11 * @extends {ChromeVoxUnitTestBase} 12 */ 13function CvoxDomUtilUnitTest() {} 14 15CvoxDomUtilUnitTest.prototype = { 16 __proto__: ChromeVoxUnitTestBase.prototype, 17 18 /** @override */ 19 closureModuleDeps: [ 20 'cvox.ChromeVox', 21 'cvox.DescriptionUtil', 22 'cvox.DomUtil', 23 'cvox.TestMsgs', 24 ], 25 26 /** @override */ 27 setUp: function() { 28 cvox.ChromeVox.msgs = new cvox.TestMsgs(); 29 }, 30 31 asText_: function(node) { 32 var temp = document.createElement('div'); 33 temp.appendChild(node); 34 return temp.innerHTML; 35 }, 36 37 assertEqualsAsText_: function(node1, node2) { 38 assertEquals(this.asText_(node1), this.asText_(node2)); 39 }, 40 41 loadDomUtilTestDoc_: function() { 42 this.loadDoc(function() {/*! 43 <style type="text/css"> 44 #display_none { display: none; } 45 #visibility_hidden { visibility: hidden; } 46 #forced_visible { visibility: hidden; } 47 #visibility_collapse { visibility: collapse; } 48 #opacity_zero { opacity: 0; } 49 #opacity_partial { opacity: 0.5; } 50 #opacity_undefined { } 51 #nested_visibility_hide { visibility: hidden; } 52 #nested_visibility_show { visibility: visible; } 53 #nested_display_none { display: none; } 54 #nested_display_block { display: block; } 55 </style> 56 <form action=""> 57 58 <div id="normal_node">1</div> 59 <div id="display_none">2</div> 60 <div id="visibility_hidden">3</div> 61 <div id="visibility_collapse">3b</div> 62 <div id="opacity_zero">4</div> 63 <div id="opacity_partial">4b</div> 64 <div id="opacity_undefined">5</div> 65 <select id="select_node"><option>5</option></select> 66 <textarea id="textarea">6</textarea> 67 <div id="forced_visible" aria-hidden="false">7</div> 68 <p id="normal_para">----</p> 69 <p id="presentation" role="presentation">----</p> 70 <p id="aria_hidden" aria-hidden="true">----</p> 71 <p id="only_spaces"> </p> 72 <p id="only_tabs"> </p> 73 <p id="only_newlines"> 74 75 </p> 76 <p id="only_nbsp"> </p> 77 <p id="other_entity">&</p> 78 <img id="img"> 79 <img id="img_alt" alt="tree"> 80 <img id="img_blankalt" alt=""> 81 82 <input id="check" type="checkbox"> 83 <input id="check_checked" type="checkbox" checked> 84 85 <span><p id="a">a</p></span> 86 <span><p id="b">b</p><p id="c">c</p></span> 87 </form> 88 89 <a id="special_link1" href="http://google.com"><span id="empty_span"></span> 90 </a> 91 <a id="special_link2" href="http://google.com"><span>Text content</span></a> 92 <a id="special_link3"><span></span></a> 93 94 <div id="nested_visibility_hide"> 95 hide<div id="nested_visibility_show">show</div>me 96 </div> 97 <div id="nested_display_none"> 98 nothing<div id="nested_display_block">will</div>show 99 </div> 100 */}); 101 }, 102}; 103 104TEST_F('CvoxDomUtilUnitTest', 'IsVisible', function() { 105 this.loadDomUtilTestDoc_(); 106 107 // Simple tests. 108 var node = $('normal_node'); 109 assertEquals(true, cvox.DomUtil.isVisible(node)); 110 node = $('display_none'); 111 assertEquals(false, cvox.DomUtil.isVisible(node)); 112 node = $('visibility_hidden'); 113 assertEquals(false, cvox.DomUtil.isVisible(node)); 114 node = $('visibility_collapse'); 115 assertEquals(false, cvox.DomUtil.isVisible(node)); 116 node = $('opacity_zero'); 117 assertEquals(false, cvox.DomUtil.isVisible(node)); 118 node = $('opacity_partial'); 119 assertEquals(true, cvox.DomUtil.isVisible(node)); 120 node = $('opacity_undefined'); 121 assertEquals(true, cvox.DomUtil.isVisible(node)); 122 node = $('forced_visible'); 123 assertEquals(true, cvox.DomUtil.isVisible(node)); 124 125 // Nested visibility tests. 126 node = $('nested_visibility_hide'); 127 assertEquals(true, cvox.DomUtil.isVisible(node)); // Has visible child. 128 node = $('nested_visibility_hide').childNodes[0]; 129 assertEquals(false, cvox.DomUtil.isVisible(node)); // TextNode is invisible. 130 node = $('nested_visibility_show'); 131 assertEquals(true, cvox.DomUtil.isVisible(node)); 132 node = $('nested_visibility_show').childNodes[0]; 133 assertEquals(true, cvox.DomUtil.isVisible(node)); // TextNode is visible. 134 node = $('nested_display_block'); 135 assertEquals(false, cvox.DomUtil.isVisible(node)); 136 137 // Options tests (for performance). 138 node = $('nested_display_block'); 139 assertEquals(true, 140 cvox.DomUtil.isVisible(node, {checkAncestors: false})); 141 node = $('nested_visibility_hide'); 142 assertEquals(false, 143 cvox.DomUtil.isVisible(node, {checkDescendants: false})); 144 145 // Test that an element not part of the DOM is treated as invisible. 146 var div = document.createElement('div'); 147 assertEquals(false, cvox.DomUtil.isVisible(div)); 148 document.body.appendChild(div); 149 assertEquals(true, cvox.DomUtil.isVisible(div)); 150}); 151 152/** Test determining if a node is a leaf node or not. @export */ 153TEST_F('CvoxDomUtilUnitTest', 'IsLeafNode', function() { 154 this.loadDomUtilTestDoc_(); 155 156 var node = $('normal_node'); 157 assertEquals(false, cvox.DomUtil.isLeafNode(node)); 158 node = $('display_none'); 159 assertEquals(true, cvox.DomUtil.isLeafNode(node)); 160 node = $('visibility_hidden'); 161 assertEquals(true, cvox.DomUtil.isLeafNode(node)); 162 node = $('opacity_zero'); 163 assertEquals(true, cvox.DomUtil.isLeafNode(node)); 164 node = $('select_node'); 165 assertEquals(true, cvox.DomUtil.isLeafNode(node)); 166 node = $('textarea'); 167 assertEquals(true, cvox.DomUtil.isLeafNode(node)); 168 node = $('normal_para'); 169 assertEquals(false, cvox.DomUtil.isLeafNode(node)); 170 node = $('aria_hidden'); 171 assertEquals(true, cvox.DomUtil.isLeafNode(node)); 172 node = $('special_link1'); 173 assertEquals(true, cvox.DomUtil.isLeafNode(node)); 174 node = $('special_link2'); 175 assertEquals(true, cvox.DomUtil.isLeafNode(node)); 176 node = $('special_link3'); 177 assertEquals(false, cvox.DomUtil.isLeafNode(node)); 178 node = $('nested_visibility_hide'); 179 assertEquals(false, cvox.DomUtil.isLeafNode(node)); 180}); 181 182/** Test determining if a node has content or not. @export */ 183TEST_F('CvoxDomUtilUnitTest', 'HasContent', function() { 184 this.loadDomUtilTestDoc_(); 185 186 var node = $('normal_node'); 187 cvox.DomUtil.hasContent(node); 188 assertEquals(true, cvox.DomUtil.hasContent(node)); 189 node = $('display_none'); 190 assertEquals(false, cvox.DomUtil.hasContent(node)); 191 node = $('visibility_hidden'); 192 assertEquals(false, cvox.DomUtil.hasContent(node)); 193 node = $('opacity_zero'); 194 assertEquals(false, cvox.DomUtil.hasContent(node)); 195 node = $('select_node'); 196 assertEquals(true, cvox.DomUtil.hasContent(node)); 197 node = $('textarea'); 198 assertEquals(true, cvox.DomUtil.hasContent(node)); 199 node = $('normal_para'); 200 assertEquals(true, cvox.DomUtil.hasContent(node)); 201 // TODO (adu): This test fails. Will inspect. 202 // node = $('presentation'); 203 // assertEquals(false, cvox.DomUtil.hasContent(node)); 204 node = $('aria_hidden'); 205 assertEquals(false, cvox.DomUtil.hasContent(node)); 206 node = $('only_spaces'); 207 assertEquals(false, cvox.DomUtil.hasContent(node)); 208 node = $('only_tabs'); 209 assertEquals(false, cvox.DomUtil.hasContent(node)); 210 node = $('only_newlines'); 211 assertEquals(false, cvox.DomUtil.hasContent(node)); 212 node = $('other_entity'); 213 assertEquals(true, cvox.DomUtil.hasContent(node)); 214 node = $('img'); 215 assertEquals(true, cvox.DomUtil.hasContent(node)); 216 node = $('img_alt'); 217 assertEquals(true, cvox.DomUtil.hasContent(node)); 218 node = $('img_blankalt'); 219 assertEquals(false, cvox.DomUtil.hasContent(node)); 220}); 221 222/** Test getting a node's state. @export */ 223TEST_F('CvoxDomUtilUnitTest', 'NodeState', function() { 224 this.loadDomUtilTestDoc_(); 225 this.appendDoc(function() {/*! 226 <input id="state1_enabled"> 227 <input id="state1_disabled" disabled> 228 <button id="state2_enabled">Button</button> 229 <button id="state2_disabled" disabled>Button</button> 230 <textarea id="state3_enabled">Textarea</textarea> 231 <textarea id="state3_disabled" disabled>Textarea</textarea> 232 <select id="state4_enabled"><option>Select</option></select> 233 <select id="state4_disabled" disabled><option>Select</option></select> 234 <div role="button" id="state5_enabled" tabindex="0">ARIAButton</div> 235 <div role="button" id="state5_disabled" tabindex="0" disabled>ARIAButton</div> 236 <fieldset> 237 <input id="state6_enabled"> 238 </fieldset> 239 <fieldset disabled> 240 <input id="state6_disabled"> 241 </fieldset> 242 */}); 243 var node = $('check'); 244 assertEquals('not checked', cvox.DomUtil.getState(node, true)); 245 node = $('check_checked'); 246 assertEquals('checked', cvox.DomUtil.getState(node, true)); 247 node = $('state1_enabled'); 248 assertEquals('', cvox.DomUtil.getState(node, true)); 249 node = $('state1_disabled'); 250 assertEquals('Disabled', cvox.DomUtil.getState(node, true)); 251 node = $('state2_enabled'); 252 assertEquals('', cvox.DomUtil.getState(node, true)); 253 node = $('state2_disabled'); 254 assertEquals('Disabled', cvox.DomUtil.getState(node, true)); 255 node = $('state3_enabled'); 256 assertEquals('', cvox.DomUtil.getState(node, true)); 257 node = $('state3_disabled'); 258 assertEquals('Disabled', cvox.DomUtil.getState(node, true)); 259 node = $('state4_enabled'); 260 assertEquals('1 of 1', cvox.DomUtil.getState(node, true)); 261 node = $('state4_disabled'); 262 assertEquals('1 of 1 Disabled', cvox.DomUtil.getState(node, true)); 263 node = $('state5_enabled'); 264 assertEquals('', cvox.DomUtil.getState(node, true)); 265 node = $('state5_disabled'); 266 assertEquals('', cvox.DomUtil.getState(node, true)); 267 node = $('state6_enabled'); 268 assertEquals('', cvox.DomUtil.getState(node, true)); 269 node = $('state6_disabled'); 270 assertEquals('Disabled', cvox.DomUtil.getState(node, true)); 271}); 272 273/** Test finding the next/previous leaf node. @export */ 274TEST_F('CvoxDomUtilUnitTest', 'LeafNodeTraversal', function() { 275 this.loadDomUtilTestDoc_(); 276 277 var node = $('a'); 278 node = cvox.DomUtil.directedNextLeafNode(node); 279 assertEquals('\n ', node.textContent); 280 node = cvox.DomUtil.directedNextLeafNode(node); 281 assertEquals('b', node.textContent); 282 node = cvox.DomUtil.directedNextLeafNode(node); 283 assertEquals('c', node.textContent); 284 node = cvox.DomUtil.previousLeafNode(node); 285 assertEquals('b', node.textContent); 286 node = cvox.DomUtil.previousLeafNode(node); 287 assertEquals('\n ', node.textContent); 288 node = cvox.DomUtil.previousLeafNode(node); 289 assertEquals('a', node.textContent); 290}); 291 292/** Test finding the label for controls. @export */ 293TEST_F('CvoxDomUtilUnitTest', 'GetLabel', function() { 294 this.loadDoc(function() {/*! 295 <fieldset id="Fieldset"> 296 <legend>This is a legend inside a fieldset</legend> 297 <div align="right"> 298 <span> 299 Username: 300 </span> 301 </div> 302 <input name="Email" id="Email" size="18" value="" type="text"> 303 <span> 304 Password: 305 </span> 306 <input name="Passwd" id="Passwd" size="18" type="password"> 307 <input name="PersistentCookie" id="PersistentCookie" type="checkbox"> 308 <label for="PersistentCookie" id="PersistentCookieLabel"> 309 Stay signed in 310 </label> 311 <input name="signIn" id="signIn" value="Sign in" type="submit"> 312 <input id="dummyA" size="18" value="" type="text" title=""> 313 <input id="dummyB" size="18" value="" type="text" aria-label=""> 314 </fieldset> 315 */}); 316 317 function getControlText(control) { 318 var description = cvox.DescriptionUtil.getControlDescription(control); 319 return cvox.DomUtil.collapseWhitespace( 320 description.context + ' ' + 321 description.text + ' ' + 322 description.userValue + ' ' + 323 description.annotation); 324 } 325 326 var fieldsetElement = $('Fieldset'); 327 assertEquals('This is a legend inside a fieldset', 328 cvox.DomUtil.getName(fieldsetElement, false, false)); 329 330 var usernameField = $('Email'); 331 assertEquals('', cvox.DomUtil.getValue(usernameField)); 332 assertEquals('Username:', 333 cvox.DomUtil.getControlLabelHeuristics(usernameField)); 334 assertEquals('Username: Edit text', getControlText(usernameField)); 335 var passwordField = $('Passwd'); 336 assertEquals('', cvox.DomUtil.getValue(passwordField)); 337 assertEquals('Password:', 338 cvox.DomUtil.getControlLabelHeuristics(passwordField)); 339 assertEquals('Password: Password edit text', getControlText(passwordField)); 340 var cookieCheckbox = $('PersistentCookie'); 341 assertEquals('Stay signed in', cvox.DomUtil.getName(cookieCheckbox)); 342 assertEquals('Stay signed in Check box not checked', 343 getControlText(cookieCheckbox)); 344 var signinButton = $('signIn'); 345 assertEquals('Sign in', cvox.DomUtil.getName(signinButton)); 346 assertEquals('Sign in Button', getControlText(signinButton)); 347 var dummyInputA = $('dummyA'); 348 assertEquals('', cvox.DomUtil.getName(dummyInputA)); 349 var dummyInputB = $('dummyB'); 350 assertEquals('', cvox.DomUtil.getName(dummyInputB)); 351 352 // The heuristic no longer returns 'Stay signed in' as the label for 353 // the signIn button because 'Stay signed in' is in a label that's 354 // explicitly associated with another control. 355 //assertEquals('Stay signed in ', 356 // cvox.DomUtil.getControlLabelHeuristics(signinButton)); 357}); 358 359/** Test finding the label for controls with a more complex setup. @export */ 360TEST_F('CvoxDomUtilUnitTest', 'GetLabelComplex', function() { 361 this.loadDoc(function() {/*! 362 <table class="bug-report-table"> 363 <tbody><tr> 364 <td class="bug-report-fieldlabel"> 365 <input id="page-url-checkbox" type="checkbox"> 366 <span id="page-url-label" i18n-content="page-url">Include this URL:</span> 367 </td> 368 <td> 369 <input id="page-url-text" class="bug-report-field" maxlength="200"> 370 </td> 371 </tr> 372 </tbody></table> 373 <table id="user-email-table" class="bug-report-table"> 374 <tbody><tr> 375 <td class="bug-report-fieldlabel"> 376 <input id="user-email-checkbox" checked="checked" type="checkbox"> 377 <span id="user-email-label">Include this email:</span> 378 </td> 379 <td> 380 <label id="user-email-text" class="bug-report-field"></label> 381 </td> 382 </tr> 383 </tbody></table> 384 <table class="bug-report-table"> 385 <tbody><tr> 386 <td class="bug-report-fieldlabel"> 387 <input id="sys-info-checkbox" checked="checked" type="checkbox"> 388 <span id="sysinfo-label"> 389 <a id="sysinfo-url" href="#">Send system information</a> 390 </span> 391 </td> 392 </tr> 393 </tbody></table> 394 <table class="bug-report-table"> 395 <tbody><tr> 396 <td class="bug-report-fieldlabel"> 397 <input id="screenshot-checkbox" type="checkbox"> 398 <span id="screenshot-label-current">Include the current screenshot:</span> 399 </td> 400 </tr> 401 </tbody></table> 402 */}); 403 var urlCheckbox = $('page-url-checkbox'); 404 assertEquals('Include this URL:', 405 cvox.DomUtil.getControlLabelHeuristics(urlCheckbox)); 406 var emailCheckbox = $('user-email-checkbox'); 407 assertEquals('Include this email:', 408 cvox.DomUtil.getControlLabelHeuristics(emailCheckbox)); 409 var sysCheckbox = $('sys-info-checkbox'); 410 assertEquals('Send system information', 411 cvox.DomUtil.getControlLabelHeuristics(sysCheckbox)); 412}); 413 414/**************************************************************/ 415 416TEST_F('CvoxDomUtilUnitTest', 'EscapedNames', function() { 417 this.loadDoc(function() {/*! 418 <p id="en-title" title="<>"></p> 419 <p id="en-arialabel" aria-label="<>"></p> 420 <img id="en-img" title="<>"></img> 421 <p id="en-double" title="&lt;&gt;"></p> 422 */}); 423 assertEquals('<>', cvox.DomUtil.getName( 424 $('en-title'))); 425 assertEquals('<>', cvox.DomUtil.getName( 426 $('en-arialabel'))); 427 assertEquals('<>', cvox.DomUtil.getName( 428 $('en-img'))); 429 assertEquals('<>', cvox.DomUtil.getName( 430 $('en-double'))); 431}); 432 433/** Test a paragraph with plain text. @export */ 434TEST_F('CvoxDomUtilUnitTest', 'SimplePara', function() { 435 this.loadDoc(function() {/*! 436 <p id="simplepara">This is a simple paragraph.</p> 437 */}); 438 var node = $('simplepara'); 439 var text = cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(node)); 440 assertEquals('This is a simple paragraph.', text); 441}); 442 443/** Test a paragraph with nested tags. @export */ 444TEST_F('CvoxDomUtilUnitTest', 'NestedPara', function() { 445 this.loadDoc(function() {/*! 446 <p id="nestedpara">This is a <b>paragraph</b> with <i>nested</i> tags.</p> 447 */}); 448 var node = $('nestedpara'); 449 var text = cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(node)); 450 assertEquals('This is a paragraph with nested tags.', text); 451}); 452 453/** 454 * Test a paragraph with nested tags and varying visibility. 455 * @export 456 */ 457TEST_F('CvoxDomUtilUnitTest', 'NestedVisibilityPara', function() { 458 this.loadDoc(function() {/*! 459 <style type="text/css"> 460 #nested_visibility_paragraph { } 461 #nested_visibility_paragraph .hide { visibility: hidden; } 462 #nested_visibility_paragraph .show { visibility: visible; } 463 </style> 464 <p id="nested_visibility_paragraph"> 465 This is 466 <span class="hide"> 467 not 468 <span class="show"> a sentence.</span> 469 </span> 470 </p> 471 */}); 472 var node = $('nested_visibility_paragraph'); 473 var text = cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(node)); 474 assertEquals('This is a sentence.', text); 475}); 476 477/** Test getting text from an IMG node. @export */ 478TEST_F('CvoxDomUtilUnitTest', 'Image', function() { 479 this.loadDoc(function() {/*! 480 <img id="img"> 481 <img id="img_noalt" src="rose.png"> 482 <img id="img_alt" alt="flower" src="rose.png"> 483 <img id="img_title" title="a Flower" src="rose.png"> 484 <img id="img_noalt_long" 485 src="777777777777777777777777777777777.png"> 486 */}); 487 488 var node = $('img'); 489 assertEquals('Image', cvox.DomUtil.getName(node)); 490 node = $('img_noalt'); 491 assertEquals('rose Image', cvox.DomUtil.getName(node)); 492 node = $('img_alt'); 493 assertEquals('flower', cvox.DomUtil.getName(node)); 494 node = $('img_title'); 495 assertEquals('a Flower', cvox.DomUtil.getName(node)); 496 node = $('img_noalt_long'); 497 assertEquals('Image', cvox.DomUtil.getName(node)); 498}); 499 500/** Test getting text from a select box. @export */ 501TEST_F('CvoxDomUtilUnitTest', 'Select', function() { 502 this.loadDoc(function() {/*! 503 <select id="select_noneselected"> 504 <option>Apple</option> 505 <option>Banana</option> 506 <option>Pear</option> 507 </select> 508 <select id="select_bananaselected"> 509 <option>Apple</option> 510 <option selected>Banana</option> 511 <option>Pear</option> 512 </select> 513 */}); 514 515 $('select_noneselected').selectedIndex = -1; 516 var node = $('select_noneselected'); 517 assertEquals('', cvox.DomUtil.getValue(node)); 518 node = $('select_bananaselected'); 519 assertEquals('Banana', cvox.DomUtil.getValue(node)); 520}); 521 522/** Test whether funky html causes getName to go into infinite loop. */ 523TEST_F('CvoxDomUtilUnitTest', 'GetNameInfiniteLoop', function() { 524 this.loadDoc(function() {/*! 525 <div> 526 <label for="a"> 527 <p id="a">asdf</p> 528 </label> 529 </div> 530 */}); 531 // intentionally no asserts; if there is an infinite (recursive) loop, 532 // the stack will blow up 533 var node = $('a'); 534 var label = cvox.DomUtil.getName(node); 535}); 536 537/** Test getting text from an INPUT control. @export */ 538TEST_F('CvoxDomUtilUnitTest', 'Input', function() { 539 this.loadDoc(function() {/*! 540 <form action=""> 541 <input id="hidden" type="hidden" value="hidden1"> 542 <input id="input_img" type="image" src="rose.png"> 543 <input id="input_img_alt" type="image" alt="flower" src="rose.png"> 544 <input id="submit" type="submit"> 545 <input id="submit_withvalue" type="submit" value="Go"> 546 <input id="reset" type="reset"> 547 <input id="reset_withvalue" type="reset" value="Stop"> 548 <input id="button" type="button" value="Button"> 549 <input id="checkbox" type="checkbox" value="ignore1"> 550 <input id="checkbox_title" type="checkbox" value="ignore1" title="toggle"> 551 <input id="radio" type="radio" value="ignore2"> 552 <input id="password" type="password" value="dragon"> 553 <input id="text" value="my text"> 554 <input id="placeholder0" placeholder="Phone number"> 555 <input id="placeholder1" title="Phone number"> 556 <input id="placeholder2" title="Phone number" placeholder="xxx-yyy-zzzz"> 557 <input id="placeholder3" title="Phone number" placeholder="xxx-yyy-zzzz" 558 value="310-555-1212"> 559 </form> 560 */}); 561 562 var node = $('hidden'); 563 assertEquals('', cvox.DomUtil.getName(node)); 564 node = $('input_img'); 565 assertEquals('rose Image', cvox.DomUtil.getName(node)); 566 node = $('input_img_alt'); 567 assertEquals('flower', cvox.DomUtil.getName(node)); 568 node = $('submit'); 569 assertEquals('Submit', cvox.DomUtil.getName(node)); 570 node = $('submit_withvalue'); 571 assertEquals('Go', cvox.DomUtil.getName(node)); 572 node = $('reset'); 573 assertEquals('Reset', cvox.DomUtil.getName(node)); 574 node = $('reset_withvalue'); 575 assertEquals('Stop', cvox.DomUtil.getName(node)); 576 node = $('button'); 577 assertEquals('Button', cvox.DomUtil.getName(node)); 578 node = $('checkbox'); 579 assertEquals('', cvox.DomUtil.getName(node)); 580 node = $('checkbox_title'); 581 assertEquals('toggle', cvox.DomUtil.getName(node)); 582 node = $('radio'); 583 assertEquals('', cvox.DomUtil.getName(node)); 584 node = $('password'); 585 assertEquals('dot dot dot dot dot dot ', cvox.DomUtil.getValue(node)); 586 node = $('text'); 587 assertEquals('my text', cvox.DomUtil.getValue(node)); 588 node = $('placeholder0'); 589 assertEquals('Phone number', cvox.DomUtil.getName(node)); 590 node = $('placeholder1'); 591 assertEquals('Phone number', cvox.DomUtil.getName(node)); 592 node = $('placeholder2'); 593 assertEquals('xxx-yyy-zzzz', 594 cvox.DomUtil.getName(node)); 595 node = $('placeholder3'); 596 assertEquals('310-555-1212 xxx-yyy-zzzz', 597 cvox.DomUtil.getValue(node) + ' ' + cvox.DomUtil.getName(node)); 598}); 599 600 601/** Test checking if something is a control. @export */ 602TEST_F('CvoxDomUtilUnitTest', 'IsControl', function() { 603 this.loadDoc(function() {/*! 604 <table width="100%" border="0" cellpadding="0" cellspacing="0"> 605 <tbody> 606 <tr> 607 <td> </td> 608 609 <td nowrap="nowrap"> 610 <table width="100%" border="0" cellpadding="0" cellspacing="0"> 611 <tbody> 612 <tr> 613 <td bgcolor="#3366CC"><img alt="" width="1" height="1"></td> 614 </tr> 615 </tbody> 616 </table> 617 618 <table width="100%" border="0" cellpadding="0" cellspacing="0"> 619 <tbody> 620 <tr> 621 <td bgcolor="#E5ECF9" nowrap="nowrap"><font color="#000000" 622 face="arial,sans-serif" size="+1"><b> Preferences</b> 623 </font></td> 624 625 <td align="right" bgcolor="#E5ECF9" nowrap="nowrap"> 626 <font color="#000000" face="arial,sans-serif" size="-1"> 627 <a href="http://www.google.com/accounts/ManageAccount">Google 628 Account settings</a> | <a href="http://www.google.com/"> 629 Preferences Help</a> | <a href="/about.html">About 630 Google</a> </font></td> 631 </tr> 632 </tbody> 633 </table> 634 </td> 635 </tr> 636 </tbody> 637 </table> 638 639 <table width="100%" border="0" cellpadding="2" cellspacing="0"> 640 <tbody> 641 <tr bgcolor="#E5ECF9"> 642 <td><font face="arial,sans-serif" size="-1"><b>Save</b> your 643 preferences when finished and <b>return to search</b>.</font></td> 644 645 <td align="right"><font face="arial,sans-serif" size="-1"> 646 <input value="Save Preferences " name="submit2" type="submit"> 647 </font></td> 648 </tr> 649 </tbody> 650 </table> 651 652 <h1>Global Preferences</h1><font size="-1">(changes apply to all Google 653 services)</font><br> 654 655 <table width="100%" border="0" cellpadding="0" cellspacing="0"> 656 <tbody> 657 <tr> 658 <td bgcolor="#CBDCED"><img alt="" width="1" height="2"></td> 659 </tr> 660 </tbody> 661 </table> 662 663 <table width="100%" border="0" cellpadding="0" cellspacing="0"> 664 <tbody> 665 <tr> 666 <td width="1" bgcolor="#CBDCED"><img alt="" width="2" height="1"></td> 667 668 <td valign="top" width="175" nowrap="nowrap"> 669 <br> 670 671 672 <h2>Interface Language</h2> 673 </td> 674 675 <td colspan="2"><br> 676 <font face="arial,sans-serif" size="-1">Display Google tips and 677 messages in: <select name="hl"> 678 <option value="af"> 679 Afrikaans 680 </option> 681 682 <option value="ak"> 683 Akan 684 </option> 685 686 <option value="sq"> 687 Albanian 688 </option> 689 690 <option value="am"> 691 Amharic 692 </option> 693 694 <option value="ar"> 695 Arabic 696 </option> 697 </select><br> 698 If you do not find your native language in the pulldown above, you 699 can<br> 700 help Google create it through our 701 <a href="http://services.google.com/">Google in Your Language 702 program</a>.<br> 703 </font></td> 704 </tr> 705 </tbody> 706 </table> 707 708 <table width="100%" border="0" cellpadding="0" cellspacing="0"> 709 <tbody> 710 <tr> 711 <td colspan="4" bgcolor="#CBDCED"><img alt="" width="1" height="1"></td> 712 </tr> 713 714 <tr> 715 <td width="1" bgcolor="#CBDCED"><img alt="" width="2" height="1"></td> 716 717 <td valign="top" width="175" nowrap="nowrap"> 718 <br> 719 720 721 <h2>Search Language</h2> 722 </td> 723 724 <td> 725 <br> 726 <font face="arial,sans-serif" size="-1">Prefer pages written in these 727 language(s):</font><br> 728 729 <table border="0" cellpadding="5" cellspacing="10"> 730 <tbody> 731 <tr> 732 <td valign="top" nowrap="nowrap"><font face="arial,sans-serif" 733 size="-1"><label><input name="lr" value="lang_af" 734 onclick="tick()" id="paf" type="checkbox"> 735 <span id="taf">Afrikaans</span></label><br> 736 <label><input name="lr" value="lang_ar" onclick="tick()" 737 id="par" type="checkbox"> <span id="tar">Arabic</span></label> 738 <br> 739 <label><input name="lr" value="lang_hy" onclick="tick()" 740 id="phy" type="checkbox"> <span id="thy">Armenian</span> 741 </label><br> 742 <label><input name="lr" value="lang_be" onclick="tick()" 743 id="pbe" type="checkbox"> <span id="tbe">Belarusian</span> 744 </label><br> 745 <label><input name="lr" value="lang_bg" onclick="tick()" 746 id="pbg" type="checkbox"> <span id="tbg">Bulgarian</span> 747 </label><br> 748 <label><input name="lr" value="lang_ca" onclick="tick()" 749 id="pca" type="checkbox"> <span id="tca">Catalan</span> 750 </label><br> 751 <label><input name="lr" value="lang_zh-CN" onclick="tick()" 752 id="pzh-CN" type="checkbox"> <span id="tzh-CN"> 753 Chinese (Simplified)</span></label><br> 754 <label><input name="lr" value="lang_zh-TW" onclick="tick()" 755 id="pzh-TW" type="checkbox"> <span id="tzh-TW"> 756 Chinese (Traditional)</span></label><br> 757 <label><input name="lr" value="lang_hr" onclick="tick()" 758 id="phr" type="checkbox"> <span id="thr">Croatian</span> 759 </label><br> 760 <label><input name="lr" value="lang_cs" onclick="tick()" 761 id="pcs" type="checkbox"> <span id="tcs">Czech</span> 762 </label><br> 763 <label><input name="lr" value="lang_da" onclick="tick()" 764 id="pda" type="checkbox"> <span id="tda">Danish</span> 765 </label><br> 766 <label><input name="lr" value="lang_nl" onclick="tick()" 767 id="pnl" type="checkbox"> <span id="tnl">Dutch</span> 768 </label></font></td> 769 </tr> 770 </tbody> 771 </table> 772 </td> 773 </tr> 774 </tbody> 775 </table><a name="loc" id="loc"></a> 776 777 <table width="100%" border="0" cellpadding="0" cellspacing="0"> 778 <tbody> 779 <tr> 780 <td colspan="4" bgcolor="#CBDCED"><img alt="" width="1" height="1"></td> 781 </tr> 782 783 <tr> 784 <td width="1" bgcolor="#CBDCED"><img alt="" width="2" height="1"></td> 785 786 <td valign="top" width="175" nowrap="nowrap"> 787 <br> 788 789 790 <h2>Location</h2> 791 </td> 792 793 <td> 794 <br> 795 796 <div style="color: rgb(204, 0, 0); display: none;" id="locerr"> 797 <span id="lem"><font face="arial,sans-serif" size="-1">The location 798 <b>X</b> was not recognized.</font></span> 799 <font face="arial,sans-serif" size="-1"><br> 800 <br> 801 Suggestions:<br></font> 802 803 <ul> 804 <li><font face="arial,sans-serif" size="-1">Make sure all street 805 and city names are spelled correctly.</font></li> 806 807 <li><font face="arial,sans-serif" size="-1">Make sure the address 808 included a city and state.</font></li> 809 810 <li><font face="arial,sans-serif" size="-1">Try entering a Zip 811 code.</font></li> 812 </ul> 813 </div> 814 815 <div style="color: rgb(204, 0, 0); display: none;" id="locterr"> 816 <font face="arial,sans-serif" size="-1">Please enter a valid US 817 city or zip code<br> 818 <br></font> 819 </div> 820 821 <div style="color: rgb(204, 0, 0); display: none;" id="locserr"> 822 <font face="arial,sans-serif" size="-1">Server error. Please try 823 again.<br> 824 <br></font> 825 </div><font face="arial,sans-serif" size="-1">Use as the default 826 location in Google Maps, customized search results, and other Google 827 products:<br> 828 <input name="uulo" value="1" type="hidden"><input name="muul" 829 value="4_20" type="hidden"><input name="luul" size="60" value="" 830 type="text"><br> 831 This location is saved on this computer. 832 <a href="/support/websearch/bin/answer.py?answer=35892&hl=en"> 833 Learn more</a><br> 834 <br></font> 835 </td> 836 </tr> 837 </tbody> 838 </table> 839 840 <table width="100%" border="0" cellpadding="0" cellspacing="0"> 841 <tbody> 842 <tr> 843 <td colspan="4" bgcolor="#CBDCED"><img alt="" width="1" height="1"></td> 844 </tr> 845 846 <tr> 847 <td rowspan="2" width="1" bgcolor="#CBDCED"> 848 <img alt="" width="2" height="1"></td> 849 850 <td width="175" nowrap="nowrap"> 851 <br> 852 853 <h2>SafeSearch Filtering</h2> 854 </td> 855 <td><br> 856 <font face="arial,sans-serif" size="-1"> 857 <a href="http://www.google.com/"> 858 Google's SafeSearch</a> blocks web pages containing explicit sexual 859 content from appearing in search results.</font></td> 860 </tr> 861 <tr valign="top"> 862 <td width="175" nowrap="nowrap"> </td> 863 <td> 864 <div style="margin-bottom: 1.2em; font: smaller arial,sans-serif;"> 865 <input id="stf" name="safeui" value="on" type="radio"> 866 <label for="stf">Use strict filtering (Filter both explicit 867 text and explicit images)</label><br> 868 <input id="modf" name="safeui" value="images" checked="checked" 869 type="radio"><label for="modf">Use moderate 870 filtering (Filter explicit images only - default 871 behavior)</label><br> 872 <input id="nof" name="safeui" value="off" type="radio"> 873 <label for="nof">Do not filter my search results</label> 874 </div> 875 <p style="margin-bottom: 1.2em; font-size: smaller;">This will apply 876 strict filtering to all searches from this computer using Firefox. 877 <a href="http://www.google.com/">Learn more</a></p> 878 </td> 879 </tr> 880 </tbody> 881 </table> 882 <table width="100%" border="0" cellpadding="0" cellspacing="0"> 883 <tbody> 884 <tr> 885 <td colspan="4" bgcolor="#CBDCED"><img alt="" width="1" height="1"></td> 886 </tr> 887 888 <tr> 889 <td width="1" bgcolor="#CBDCED"><img alt="" width="2" height="1"></td> 890 891 <td valign="top" width="175" nowrap="nowrap"> 892 <br> 893 894 895 <h2>Number of Results</h2> 896 </td> 897 898 <td> <br> 899 <font face="arial,sans-serif" size="-1">Google's default (10 results) 900 provides the fastest results.<br> 901 Display <select name="num"> 902 <option value="10" selected="selected"> 903 10 904 </option> 905 906 <option value="20"> 907 20 908 </option> 909 910 <option value="30"> 911 30 912 </option> 913 914 <option value="50"> 915 50 916 </option> 917 918 <option value="100"> 919 100 920 </option> 921 </select> results per page.<br> 922 </font></td> 923 </tr> 924 </tbody> 925 </table> 926 927 <table width="100%" border="0" cellpadding="0" cellspacing="0"> 928 <tbody> 929 <tr> 930 <td colspan="4" bgcolor="#CBDCED"><img alt="" width="1" height="1"></td> 931 </tr> 932 933 <tr> 934 <td width="1" bgcolor="#CBDCED"><img alt="" width="2" height="1"></td> 935 936 <td valign="top" width="175" nowrap="nowrap"> 937 <br> 938 939 940 <h2>Results Window</h2><a name="safeui" id="safeui"> </a> 941 </td> 942 943 <td> <br> 944 <font face="arial,sans-serif" size="-1"><input id="nwc" name="newwindow" 945 value="1" type="checkbox"> <label for="nwc">Open 946 search results in a new browser window.</label></font><br> 947 </td> 948 </tr> 949 </tbody> 950 </table> 951 952 <table width="100%" border="0" cellpadding="0" cellspacing="0"> 953 <tbody> 954 <tr> 955 <td colspan="4" bgcolor="#CBDCED"><img alt="" width="1" height="1"></td> 956 </tr> 957 958 <tr> 959 <td width="1" bgcolor="#CBDCED"><img alt="" width="2" height="1"></td> 960 961 <td valign="top" width="175" nowrap="nowrap"> 962 <br> 963 964 965 <h2>Google Instant</h2> 966 </td> 967 968 <td> <br> 969 <font face="arial,sans-serif" size="-1"><input id="suggon" name="suggon" 970 value="1" checked="checked" type="radio"><label for="suggon">Use Google 971 Instant predictions and results appear while typing</label><br> 972 <input id="suggmid" name="suggon" value="2" type="radio"> 973 <label for="suggmid">Do not use Google Instant</label><br> 974 <br> 975 Signed-in users can remove personalized predictions from their 976 <a href="/history">Web History</a>. <a href="http://www.google.com/"> 977 Learn more</a><br> 978 <br> 979 </font></td> 980 </tr> 981 982 <tr> 983 <td colspan="4" bgcolor="#CBDCED"><img alt="" width="1" height="2"></td> 984 </tr> 985 </tbody> 986 </table><br> 987 */}); 988 var submitButton = document.getElementsByName('submit2')[0]; 989 assertEquals(true, cvox.DomUtil.isControl(submitButton)); 990 var selectControl = document.getElementsByName('hl')[0]; 991 assertEquals(true, cvox.DomUtil.isControl(selectControl)); 992 var checkbox = $('paf'); 993 assertEquals(true, cvox.DomUtil.isControl(checkbox)); 994 var textInput = document.getElementsByName('luul')[0]; 995 assertEquals(true, cvox.DomUtil.isControl(textInput)); 996 var radioButton = $('suggmid'); 997 assertEquals(true, cvox.DomUtil.isControl(radioButton)); 998 var h1Elem = document.getElementsByTagName('h1'); 999 assertEquals(false, cvox.DomUtil.isControl(h1Elem)); 1000}); 1001 1002/** Test if something is an ARIA control. @export */ 1003TEST_F('CvoxDomUtilUnitTest', 'IsAriaControl', function() { 1004 this.loadDoc(function() {/*! 1005 <li id="cb1" role="checkbox" tabindex="0" aria-checked="false" 1006 aria-describedby="cond desc1"> 1007 Lettuce 1008 </li> 1009 <li id="larger1" role="button" tabindex="0" aria-pressed="false" 1010 aria-labelledby="larger_label">+</li> 1011 <li id="r1" role="radio" tabindex="-1" aria-checked="false">Thai</li> 1012 <li id="treeitem1" role="treeitem" tabindex="-1">Oranges</li> 1013 */}); 1014 var checkbox = $('cb1'); 1015 assertEquals(true, cvox.DomUtil.isControl(checkbox)); 1016 var button = $('larger1'); 1017 assertEquals(true, cvox.DomUtil.isControl(button)); 1018 var radio = $('r1'); 1019 assertEquals(true, cvox.DomUtil.isControl(radio)); 1020 var treeitem = $('treeitem1'); 1021 assertEquals(false, cvox.DomUtil.isControl(treeitem)); 1022}); 1023 1024/** Test if something is an focusable. @export */ 1025TEST_F('CvoxDomUtilUnitTest', 'IsFocusable', function() { 1026 this.loadDoc(function() {/*! 1027 <a id="focus_link" href="#">Link</a> 1028 <a id="focus_anchor">Unfocusable anchor</a> 1029 <input id="focus_input" value="Input" /> 1030 <select id="focus_select"><option>Select</option></select> 1031 <button id="focus_button1">Button</button> 1032 <button id="focus_button2" tabindex="-1">Button 2</button> 1033 <button id="focus_button3" tabindex="0">Button 3</button> 1034 <button id="focus_button4" tabindex="1">Button 4</button> 1035 <div id="focus_div1">Div</div> 1036 <div id="focus_div2" tabindex="-1">Div 2</div> 1037 <div id="focus_div3" tabindex="0">Div 3</div> 1038 <div id="focus_div4" tabindex="1">Div 4</div> 1039 */}); 1040 var node; 1041 node = $('focus_link'); 1042 assertEquals(true, cvox.DomUtil.isFocusable(node)); 1043 node = $('focus_anchor'); 1044 assertEquals(false, cvox.DomUtil.isFocusable(node)); 1045 node = $('focus_input'); 1046 assertEquals(true, cvox.DomUtil.isFocusable(node)); 1047 node = $('focus_select'); 1048 assertEquals(true, cvox.DomUtil.isFocusable(node)); 1049 node = $('focus_button1'); 1050 assertEquals(true, cvox.DomUtil.isFocusable(node)); 1051 node = $('focus_button2'); 1052 assertEquals(true, cvox.DomUtil.isFocusable(node)); 1053 node = $('focus_button3'); 1054 assertEquals(true, cvox.DomUtil.isFocusable(node)); 1055 node = $('focus_button4'); 1056 assertEquals(true, cvox.DomUtil.isFocusable(node)); 1057 node = $('focus_div1'); 1058 assertEquals(false, cvox.DomUtil.isFocusable(node)); 1059 node = $('focus_div2'); 1060 assertEquals(true, cvox.DomUtil.isFocusable(node)); 1061 node = $('focus_div3'); 1062 assertEquals(true, cvox.DomUtil.isFocusable(node)); 1063 node = $('focus_div4'); 1064 assertEquals(true, cvox.DomUtil.isFocusable(node)); 1065 1066 // Test it with null. 1067 assertEquals(false, cvox.DomUtil.isFocusable(null)); 1068 1069 // Test it with something that's not an element. 1070 assertEquals(false, cvox.DomUtil.isFocusable(new Object())); 1071 1072 // Test it with a Text node. 1073 node = $('focus_button1').firstChild; 1074 assertEquals(false, cvox.DomUtil.isFocusable(node)); 1075}); 1076 1077/** Some additional tests for getName function. */ 1078TEST_F('CvoxDomUtilUnitTest', 'GetName', function() { 1079 this.loadDoc(function() {/*! 1080 <span id="test-span" aria-labelledby="fake-id">Some text</span> 1081 <label id="label1">One</label> 1082 <label id="label3">Label</label> 1083 <div id="test-div" aria-labelledby="label1 label2 label3"></div> 1084 */}); 1085 var node = $('test-span'); 1086 // Makes sure we can deal with invalid ids in aria-labelledby. 1087 var text = cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(node)); 1088 assertEquals('Some text', text); 1089 node = $('test-div'); 1090 text = cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(node)); 1091 assertEquals('One Label', cvox.DomUtil.getName(node)); 1092}); 1093 1094/** Test for getLinkURL. */ 1095TEST_F('CvoxDomUtilUnitTest', 'GetLinkURL', function() { 1096 this.loadDoc(function() {/*! 1097 <a id="l1" name="nohref">Anchor</a> 1098 <a id="l2" href="">Empty link</a> 1099 <a id="l3" href="#">Link to self</a> 1100 <a id="l4" href="http://google.com">Google</a> 1101 <span id="l5" role="link" onClick="javascript:alert('?')">Something</span> 1102 <div id="l6" role="link">Div with link role</a> 1103 */}); 1104 var node = $('l1'); 1105 assertEquals('', cvox.DomUtil.getLinkURL(node)); 1106 node = $('l2'); 1107 assertEquals('', cvox.DomUtil.getLinkURL(node)); 1108 node = $('l3'); 1109 assertEquals('Internal link', cvox.DomUtil.getLinkURL(node)); 1110 node = $('l4'); 1111 assertEquals('http://google.com', cvox.DomUtil.getLinkURL(node)); 1112 node = $('l5'); 1113 assertEquals('Unknown link', cvox.DomUtil.getLinkURL(node)); 1114 node = $('l6'); 1115 assertEquals('Unknown link', cvox.DomUtil.getLinkURL(node)); 1116}); 1117 1118/** Test for isDisabled. */ 1119TEST_F('CvoxDomUtilUnitTest', 'IsDisabled', function() { 1120 this.loadDoc(function() {/*! 1121 <input id="button1" type="button" value="Press me!"/> 1122 <input id="button2" type="button" value="Don't touch me!" disabled/> 1123 */}); 1124 var node = $('button1'); 1125 assertEquals(false, cvox.DomUtil.isDisabled(node)); 1126 node = $('button2'); 1127 assertEquals(true, cvox.DomUtil.isDisabled(node)); 1128}); 1129 1130/** Test for a tree with aria-expanded attribute. */ 1131TEST_F('CvoxDomUtilUnitTest', 'Tree', function() { 1132 this.loadDoc(function() {/*! 1133 <div id=":0" role="tree" aria-selected="false" aria-expanded="true" 1134 aria-level="0" aria-labelledby=":0.label" tabindex="0" 1135 aria-activedescendant=":1"> 1136 <span id=":0.label">Countries</span> 1137 <div class="goog-tree-item" id=":1" role="treeitem" aria-selected="true" 1138 aria-expanded="false" aria-labelledby=":1.label" aria-level="1"> 1139 <span id=":1.label">A</span> 1140 </div> 1141 <div class="goog-tree-item" id=":2" role="treeitem" aria-selected="false" 1142 aria-expanded="false" aria-labelledby=":2.label" aria-level="1"> 1143 <span id=":2.label">B<span> 1144 </div> 1145 <div class="goog-tree-item" id=":3" role="treeitem" aria-selected="false" 1146 aria-expanded="true" aria-labelledby=":3.label" aria-level="1"> 1147 <span id=":3.label">C</span> 1148 <div class="goog-tree-children" role="group"> 1149 <div class="goog-tree-item" id=":3a" role="treeitem" 1150 aria-selected="false" aria-expanded="false" 1151 aria-labelledby=":3a.label" aria-level="2"> 1152 <span id=":3a.label">Chile</span> 1153 </div> 1154 <div class="goog-tree-item" id=":3b" role="treeitem" 1155 aria-selected="false" aria-expanded="false" 1156 aria-labelledby=":3b.label" aria-level="2"> 1157 <span id=":3b.label">China</span> 1158 </div> 1159 <div class="goog-tree-item" id=":3c" role="treeitem" 1160 aria-selected="false" aria-expanded="false" 1161 aria-labelledby=":3c.label" aria-level="2"> 1162 <span id=":3c.label">Christmas Island</span> 1163 </div> 1164 <div class="goog-tree-item" id=":3d" role="treeitem" 1165 aria-selected="false" aria-expanded="false" 1166 aria-labelledby=":3d.label" aria-level="2"> 1167 <span id=":3d.label">Cocos (Keeling) Islands</span> 1168 </div> 1169 </div> 1170 </div> 1171 </div> 1172 */}); 1173 var node = $(':0'); 1174 assertEquals('A Collapsed Selected 1 of 3', 1175 cvox.DomUtil.getControlValueAndStateString(node)); 1176 node = $(':1'); 1177 assertEquals('A Collapsed Selected 1 of 3', 1178 cvox.DomUtil.getControlValueAndStateString(node)); 1179 node = $(':2'); 1180 assertEquals('B Collapsed Not selected 2 of 3', 1181 cvox.DomUtil.getControlValueAndStateString(node)); 1182 node = $(':3'); 1183 assertEquals('C Expanded Not selected 3 of 3', 1184 cvox.DomUtil.getControlValueAndStateString(node)); 1185 node = $(':3b'); 1186 assertEquals('China Collapsed Not selected 2 of 4', 1187 cvox.DomUtil.getControlValueAndStateString(node)); 1188}); 1189 1190/** Test for tables with different border specifications */ 1191TEST_F('CvoxDomUtilUnitTest', 'TableBorders', function() { 1192 this.loadDoc(function() {/*! 1193 <table id=":0" border="1"> 1194 <tr> 1195 <td>A</td> 1196 </tr> 1197 </table> 1198 <table id=":1" border="0"> 1199 <tr> 1200 <td>A</td> 1201 </tr> 1202 </table> 1203 <table id=":2" border="0px"> 1204 <tr> 1205 <td>A</td> 1206 </tr> 1207 </table> 1208 <table id=":3" frame="box"> 1209 <tr> 1210 <td>A</td> 1211 </tr> 1212 </table> 1213 <table id=":4" frame="void"> 1214 <tr> 1215 <td>A</td> 1216 </tr> 1217 </table> 1218 <table id=":5" style="border-width: medium"> 1219 <tr> 1220 <td>A</td> 1221 </tr> 1222 </table> 1223 <table id=":6" style="border-width: medium; border-style: none"> 1224 <tr> 1225 <td>A</td> 1226 </tr> 1227 </table> 1228 <table id=":7" style="border-color: red"> 1229 <tr> 1230 <td>A</td> 1231 </tr> 1232 </table> 1233 <table id=":8" style="border-style: dotted; border-width: 0px"> 1234 <tr> 1235 <td>A</td> 1236 </tr> 1237 </table> 1238 <table id=":9" style="border-width: 0px"> 1239 <tr> 1240 <td>A</td> 1241 </tr> 1242 </table> 1243 <table id=":10" style="border: 0px"> 1244 <tr> 1245 <td>A</td> 1246 </tr> 1247 </table> 1248 <table id=":11" style="border: 0"> 1249 <tr> 1250 <td>A</td> 1251 </tr> 1252 </table> 1253 */}); 1254 var node = $(':0'); 1255 assertTrue(cvox.DomUtil.hasBorder(node)); 1256 1257 node = $(':1'); 1258 assertFalse(cvox.DomUtil.hasBorder(node)); 1259 1260 node = $(':2'); 1261 assertFalse(cvox.DomUtil.hasBorder(node)); 1262 1263 node = $(':3'); 1264 assertTrue(cvox.DomUtil.hasBorder(node)); 1265 1266 node = $(':4'); 1267 assertFalse(cvox.DomUtil.hasBorder(node)); 1268 1269 node = $(':5'); 1270 assertTrue(cvox.DomUtil.hasBorder(node)); 1271 1272 node = $(':6'); 1273 assertFalse(cvox.DomUtil.hasBorder(node)); 1274 1275 node = $(':7'); 1276 assertTrue(cvox.DomUtil.hasBorder(node)); 1277 1278 node = $(':8'); 1279 assertFalse(cvox.DomUtil.hasBorder(node)); 1280 1281 node = $(':9'); 1282 assertFalse(cvox.DomUtil.hasBorder(node)); 1283 1284 node = $(':10'); 1285 assertFalse(cvox.DomUtil.hasBorder(node)); 1286 1287 node = $(':11'); 1288 assertFalse(cvox.DomUtil.hasBorder(node)); 1289}); 1290 1291/** Tests for shallowChildlessClone */ 1292TEST_F('CvoxDomUtilUnitTest', 'ShallowChildlessClone', function() { 1293 this.loadDoc(function() {/*! 1294 <div id='simple'>asdf</div> 1295 <div id='expectedSimpleClone'>asdf</div> 1296 <div id='oneLevel'><div>asdf</div></div> 1297 <div id='expectedOneLevelClone'><div></div></div> 1298 <div id='withAttrs'><div class="asdf">asdf</div></div> 1299 <div id='expectedWithAttrsClone'><div class="asdf"></div></div> 1300 */}); 1301 1302 var simple = $('simple').firstChild; 1303 var expectedSimpleClone = $('expectedSimpleClone').firstChild; 1304 var oneLevel = $('oneLevel').firstChild; 1305 var expectedOneLevelClone = $('expectedOneLevelClone').firstChild; 1306 var withAttrs = $('withAttrs').firstChild; 1307 var expectedWithAttrsClone = $('expectedWithAttrsClone').firstChild; 1308 1309 var simpleClone = cvox.DomUtil.shallowChildlessClone(simple); 1310 this.assertEqualsAsText_(simpleClone, expectedSimpleClone); 1311 1312 var oneLevelClone = cvox.DomUtil.shallowChildlessClone(oneLevel); 1313 this.assertEqualsAsText_(oneLevelClone, expectedOneLevelClone); 1314 1315 var withAttrsClone = cvox.DomUtil.shallowChildlessClone(withAttrs); 1316 this.assertEqualsAsText_(withAttrsClone, expectedWithAttrsClone); 1317}); 1318 1319/** Tests for deepClone */ 1320TEST_F('CvoxDomUtilUnitTest', 'DeepClone', function() { 1321 this.loadDoc(function() {/*! 1322 <div id='simple'>asdf</div> 1323 */}); 1324 var simpleClone = cvox.DomUtil.deepClone($('simple')); 1325 this.assertEqualsAsText_(simpleClone, $('simple')); 1326 1327 this.loadDoc(function() {/*! 1328 <div id="withAttrs" class="asdf">asdf</div> 1329 */}); 1330 var withAttrsClone = cvox.DomUtil.deepClone($('withAttrs')); 1331 this.assertEqualsAsText_(withAttrsClone, $('withAttrs')); 1332}); 1333 1334/** Tests for findNode */ 1335TEST_F('CvoxDomUtilUnitTest', 'FindNode', function() { 1336 this.loadDoc(function() {/*! 1337 <div id="root"> 1338 <p id="a">a</p> 1339 <a href="#" id="b">b</a> 1340 </div> 1341 */}); 1342 var f = cvox.DomUtil.findNode; 1343 var node = f($('root'), function(n) {return n.id == 'b';}); 1344 assertEquals('b', node.id); 1345}); 1346 1347/** Tests for getState for a list */ 1348TEST_F('CvoxDomUtilUnitTest', 'ListLength', function() { 1349 this.loadDoc(function() {/*! 1350 <ul id="ul1"> 1351 <li>A 1352 <li>B 1353 <li>C 1354 </ul> 1355 <ul id="ul2"> 1356 <li aria-setsize="10">A 1357 <li aria-setsize="10">B 1358 <li aria-setsize="10">C 1359 </ul> 1360 */}); 1361 var ul1 = $('ul1'); 1362 assertEquals('with 3 items', 1363 cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getState(ul1))); 1364 1365 var ul2 = $('ul2'); 1366 assertEquals('with 10 items', 1367 cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getState(ul2))); 1368}); 1369 1370/** Tests for hasLongDesc */ 1371TEST_F('CvoxDomUtilUnitTest', 'HasLongDesc', function() { 1372 this.loadDoc(function() {/*! 1373 <img id="img0" longdesc="desc.html" src="img0.jpg"></img> 1374 <img id="img1" src="img1.jpg"></img> 1375 */}); 1376 var img0 = $('img0'); 1377 assertEquals(true, cvox.DomUtil.hasLongDesc(img0)); 1378 1379 var img1 = $('img1'); 1380 assertEquals(false, cvox.DomUtil.hasLongDesc(img1)); 1381}); 1382 1383/** Tests for various link leaf types. */ 1384TEST_F('CvoxDomUtilUnitTest', 'LinkLeaf', function() { 1385 this.loadDoc(function() {/*! 1386 <a id='leaf' href='google.com'><strong>Click</strong><div>here</div></a> 1387 <a id='non-leaf' href='google.com'>Click <h2>here</h2></a> 1388 */}); 1389 var leaf = $('leaf'); 1390 var nonLeaf = $('non-leaf'); 1391 assertTrue(cvox.DomUtil.isLeafNode(leaf)); 1392 assertFalse(cvox.DomUtil.isLeafNode(nonLeaf)); 1393}); 1394 1395 1396/** Test the value and state of a multiple select. */ 1397TEST_F('CvoxDomUtilUnitTest', 'MultipleSelectValue', function() { 1398 this.loadDoc(function() {/*! 1399 <select id='cars' multiple> 1400 <option value="volvo">Volvo</option> 1401 <option value="saab">Saab</option> 1402 <option value="opel" selected>Opel</option> 1403 <option value="audi" selected>Audi</option> 1404 </select> 1405 */}); 1406 var cars = $('cars'); 1407 assertEquals('Opel to Audi', cvox.DomUtil.getValue(cars)); 1408 assertEquals('selected 2 items', cvox.DomUtil.getState(cars)); 1409}); 1410 1411 1412/** 1413 * Test correctness of elementToPoint. 1414 * 1415 * Absolute positioning of the container is used to avoid the window of the 1416 * browser being too small to contain the test elements. 1417 */ 1418TEST_F('CvoxDomUtilUnitTest', 'ElementToPoint', function() { 1419 this.loadDoc(function() {/*! 1420 <div style="position: absolute; top: 0; left: 0"> 1421 <a id='one' href='#a'>First</a> 1422 <p id='two'>Some text</p> 1423 <ul><li id='three'>LI</li><li>LI2</li></ul> 1424 </div> 1425 */}); 1426 var one = $('one'); 1427 var two = $('two'); 1428 var three = $('three'); 1429 1430 var oneHitPoint = cvox.DomUtil.elementToPoint(one); 1431 var twoHitPoint = cvox.DomUtil.elementToPoint(two); 1432 var threeHitPoint = cvox.DomUtil.elementToPoint(three); 1433 1434 assertEquals(one, document.elementFromPoint(oneHitPoint.x, oneHitPoint.y)); 1435 assertEquals(two, document.elementFromPoint(twoHitPoint.x, twoHitPoint.y)); 1436 assertEquals(three, 1437 document.elementFromPoint(threeHitPoint.x, threeHitPoint.y)); 1438}); 1439 1440/** Tests we compute the correct name for hidden aria labelledby nodes. */ 1441TEST_F('CvoxDomUtilUnitTest', 'HiddenAriaLabelledby', function() { 1442 this.loadDoc(function() {/*! 1443 <span id="acc_name" style="display: none"> 1444 hello world! 1445 </span> 1446 <button id="button" aria-labelledby="acc_name"> 1447 */}); 1448 assertEquals('hello world!', 1449 cvox.DomUtil.getName($('button'))); 1450}); 1451 1452/** Tests that we compute the correct state for accesskeys. */ 1453TEST_F('CvoxDomUtilUnitTest', 'AccessKey', function() { 1454 this.loadDoc(function() {/*! 1455 <a id='accessKey' href="#f" title="Next page" accesskey="n">Next page</a> 1456 */}); 1457 var a = $('accessKey'); 1458 assertEquals('has access key, n', cvox.DomUtil.getState(a)); 1459}); 1460 1461 1462/** Tests that we compute the correct name for ordered listitems. */ 1463TEST_F('CvoxDomUtilUnitTest', 'OrderedListitem', function() { 1464 this.loadDoc(function() {/*! 1465 <ol id="fruits_ol"> 1466 <li id='ol_li1'>apple 1467 <li id='ol_li2'>orange 1468 <li id='ol_li3'>strawberry 1469 <li id='ol_li4'>banana 1470 </ol> 1471 */}); 1472 var li1 = $('ol_li1'); 1473 var li2 = $('ol_li2'); 1474 var li3 = $('ol_li3'); 1475 var li4 = $('ol_li4'); 1476 // Note that whitespace processing happens at a higher layer 1477 // (DescriptionUtil). 1478 assertEquals('1. apple', 1479 cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(li1))); 1480 assertEquals('2. orange', 1481 cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(li2))); 1482 assertEquals('3. strawberry', 1483 cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(li3))); 1484 assertEquals('4. banana', 1485 cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(li4))); 1486 1487 $('fruits_ol').style.listStyleType = 'lower-latin'; 1488 1489 assertEquals('A. apple', 1490 cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(li1))); 1491 assertEquals('B. orange', 1492 cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(li2))); 1493 assertEquals('C. strawberry', 1494 cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(li3))); 1495 assertEquals('D. banana', 1496 cvox.DomUtil.collapseWhitespace(cvox.DomUtil.getName(li4))); 1497}); 1498 1499/** Tests a node with title, and textContent containing only whitespace. */ 1500TEST_F('CvoxDomUtilUnitTest', 'TitleOverridesInnerWhitespace', function() { 1501 this.loadDoc(function() {/*! 1502 <button id="btn1" title="Remove from Chrome"> 1503 <span class="lid"></span> 1504 <span class="can"></span> 1505 </button> 1506 */}); 1507 var btn1 = $('btn1'); 1508 assertEquals('Remove from Chrome', cvox.DomUtil.getName(btn1)); 1509}); 1510 1511/** Test memoization. **/ 1512TEST_F('CvoxDomUtilUnitTest', 'Memoization', function() { 1513 this.loadDoc(function() {/*! 1514 <div id="container"> 1515 </div> 1516 */}); 1517 1518 // Nest divs 100 levels deep. 1519 var container = $('container'); 1520 var outer = container; 1521 for (var i = 0; i < 100; i++) { 1522 var inner = document.createElement('div'); 1523 outer.appendChild(inner); 1524 outer = inner; 1525 } 1526 var target = document.createElement('p'); 1527 target.innerHTML = 'Text'; 1528 outer.appendChild(target); 1529 1530 var iterations = 200; 1531 1532 function logTime(msg, fn) { 1533 var t0 = new Date(); 1534 fn(); 1535 console.log(msg + ' elapsed time: ' + (new Date() - t0) + ' ms'); 1536 } 1537 1538 // First, test without memoization. 1539 logTime('No memoization', function() { 1540 container.style.visibility = 'hidden'; 1541 for (var i = 0; i < iterations; i++) { 1542 assertFalse(cvox.DomUtil.isVisible(target)); 1543 } 1544 container.style.visibility = 'visible'; 1545 for (var i = 0; i < iterations; i++) { 1546 assertTrue(cvox.DomUtil.isVisible(target)); 1547 } 1548 }); 1549 1550 // Now test with memoization enabled. 1551 logTime('With memoization', function() { 1552 cvox.Memoize.scope(function() { 1553 container.style.visibility = 'hidden'; 1554 for (var i = 0; i < iterations; i++) { 1555 assertFalse(cvox.DomUtil.isVisible(target)); 1556 } 1557 }); 1558 cvox.Memoize.scope(function() { 1559 container.style.visibility = 'visible'; 1560 for (var i = 0; i < iterations; i++) { 1561 assertTrue(cvox.DomUtil.isVisible(target)); 1562 } 1563 }); 1564 }); 1565 1566 // Finally as a sanity check that things are being memoized, turn on 1567 // memoization and show that we get the wrong result if we change the 1568 // DOM and call isVisible again. 1569 cvox.Memoize.scope(function() { 1570 container.style.visibility = 'hidden'; 1571 assertFalse(cvox.DomUtil.isVisible(target)); 1572 1573 container.style.visibility = 'visible'; 1574 // This should be true! It will return the wrong answer because 1575 // we're deliberately leaving memoization on while modifying the DOM. 1576 assertFalse(cvox.DomUtil.isVisible(target)); 1577 }); 1578}); 1579