browser_textleafpoint.js (13738B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 /* import-globals-from ../../mochitest/text.js */ 8 9 addAccessibleTask( 10 ` 11 <p id="p" style="white-space: pre-line;">A bug 12 h<a href="#">id i</a>n 13 the <strong>big</strong> rug.</p> 14 `, 15 function (browser, docAcc) { 16 const container = findAccessibleChildByID(docAcc, "p"); 17 const firstPoint = createTextLeafPoint(container, 0); 18 const lastPoint = createTextLeafPoint(container, kTextEndOffset); 19 20 let charSequence = [ 21 ...textBoundaryGenerator(firstPoint, BOUNDARY_CHAR, DIRECTION_NEXT), 22 ]; 23 24 testPointEqual( 25 firstPoint, 26 charSequence[0], 27 "Point constructed via container and offset 0 is first character point." 28 ); 29 testPointEqual( 30 lastPoint, 31 charSequence[charSequence.length - 1], 32 "Point constructed via container and kTextEndOffset is last character point." 33 ); 34 35 const expectedCharSequence = [ 36 ["A bug\nh", 0], 37 ["A bug\nh", 1], 38 ["A bug\nh", 2], 39 ["A bug\nh", 3], 40 ["A bug\nh", 4], 41 ["A bug\nh", 5], 42 ["A bug\nh", 6], 43 ["id i", 0], 44 ["id i", 1], 45 ["id i", 2], 46 ["id i", 3], 47 ["n\nthe ", 0], 48 ["n\nthe ", 1], 49 ["n\nthe ", 2], 50 ["n\nthe ", 3], 51 ["n\nthe ", 4], 52 ["n\nthe ", 5], 53 ["big", 0], 54 ["big", 1], 55 ["big", 2], 56 [" rug.", 0], 57 [" rug.", 1], 58 [" rug.", 2], 59 [" rug.", 3], 60 [" rug.", 4], 61 [" rug.", 5], 62 ]; 63 64 testBoundarySequence( 65 firstPoint, 66 BOUNDARY_CHAR, 67 DIRECTION_NEXT, 68 expectedCharSequence, 69 "Forward BOUNDARY_CHAR sequence is correct" 70 ); 71 72 testBoundarySequence( 73 lastPoint, 74 BOUNDARY_CHAR, 75 DIRECTION_PREVIOUS, 76 [...expectedCharSequence].reverse(), 77 "Backward BOUNDARY_CHAR sequence is correct" 78 ); 79 80 const expectedWordStartSequence = [ 81 ["A bug\nh", 0], 82 ["A bug\nh", 2], 83 ["A bug\nh", 6], 84 ["id i", 3], 85 ["n\nthe ", 2], 86 ["big", 0], 87 [" rug.", 1], 88 ]; 89 testBoundarySequence( 90 firstPoint, 91 BOUNDARY_WORD_START, 92 DIRECTION_NEXT, 93 // Add last point in doc 94 [...expectedWordStartSequence, readablePoint(lastPoint)], 95 "Forward BOUNDARY_WORD_START sequence is correct" 96 ); 97 98 testBoundarySequence( 99 lastPoint, 100 BOUNDARY_WORD_START, 101 DIRECTION_PREVIOUS, 102 [...expectedWordStartSequence].reverse(), 103 "Backward BOUNDARY_WORD_START sequence is correct" 104 ); 105 106 const expectedWordEndSequence = [ 107 ["A bug\nh", 1], 108 ["A bug\nh", 5], 109 ["id i", 2], 110 ["n\nthe ", 1], 111 ["n\nthe ", 5], 112 [" rug.", 0], 113 [" rug.", 5], 114 ]; 115 testBoundarySequence( 116 firstPoint, 117 BOUNDARY_WORD_END, 118 DIRECTION_NEXT, 119 expectedWordEndSequence, 120 "Forward BOUNDARY_WORD_END sequence is correct" 121 ); 122 123 testBoundarySequence( 124 lastPoint, 125 BOUNDARY_WORD_END, 126 DIRECTION_PREVIOUS, 127 [readablePoint(firstPoint), ...expectedWordEndSequence].reverse(), 128 "Backward BOUNDARY_WORD_END sequence is correct" 129 ); 130 131 const expectedLineStartSequence = [ 132 ["A bug\nh", 0], 133 ["A bug\nh", 6], 134 ["n\nthe ", 2], 135 ]; 136 testBoundarySequence( 137 firstPoint, 138 BOUNDARY_LINE_START, 139 DIRECTION_NEXT, 140 // Add last point in doc 141 [...expectedLineStartSequence, readablePoint(lastPoint)], 142 "Forward BOUNDARY_LINE_START sequence is correct" 143 ); 144 145 testBoundarySequence( 146 lastPoint, 147 BOUNDARY_LINE_START, 148 DIRECTION_PREVIOUS, 149 [...expectedLineStartSequence].reverse(), 150 "Backward BOUNDARY_LINE_START sequence is correct" 151 ); 152 153 const expectedLineEndSequence = [ 154 ["A bug\nh", 5], 155 ["n\nthe ", 1], 156 ]; 157 testBoundarySequence( 158 firstPoint, 159 BOUNDARY_LINE_END, 160 DIRECTION_NEXT, 161 // Add last point in doc 162 [...expectedLineEndSequence, readablePoint(lastPoint)], 163 "Forward BOUNDARY_LINE_END sequence is correct", 164 { todo: true } 165 ); 166 167 testBoundarySequence( 168 lastPoint, 169 BOUNDARY_LINE_END, 170 DIRECTION_PREVIOUS, 171 [readablePoint(firstPoint), ...expectedLineEndSequence].reverse(), 172 "Backward BOUNDARY_LINE_END sequence is correct" 173 ); 174 }, 175 { chrome: true, topLevel: true, iframe: false, remoteIframe: false } 176 ); 177 178 addAccessibleTask( 179 `<p id="p"> 180 Rob ca<input id="i1" value="n m">op up. 181 </p>`, 182 function (browser, docAcc) { 183 const container = findAccessibleChildByID(docAcc, "p"); 184 const firstPoint = createTextLeafPoint(container, 0); 185 const lastPoint = createTextLeafPoint(container, kTextEndOffset); 186 187 testBoundarySequence( 188 firstPoint, 189 BOUNDARY_CHAR, 190 DIRECTION_NEXT, 191 [ 192 ["Rob ca", 0], 193 ["Rob ca", 1], 194 ["Rob ca", 2], 195 ["Rob ca", 3], 196 ["Rob ca", 4], 197 ["Rob ca", 5], 198 ["n m", 0], 199 ["n m", 1], 200 ["n m", 2], 201 ["n m", 3], 202 ], 203 "Forward BOUNDARY_CHAR sequence when stopping in editable is correct", 204 { flags: BOUNDARY_FLAG_STOP_IN_EDITABLE } 205 ); 206 207 testBoundarySequence( 208 lastPoint, 209 BOUNDARY_CHAR, 210 DIRECTION_PREVIOUS, 211 [ 212 ["op up. ", 7], 213 ["op up. ", 6], 214 ["op up. ", 5], 215 ["op up. ", 4], 216 ["op up. ", 3], 217 ["op up. ", 2], 218 ["op up. ", 1], 219 ["op up. ", 0], 220 ["n m", 2], 221 ["n m", 1], 222 ["n m", 0], 223 ], 224 "Backward BOUNDARY_CHAR sequence when stopping in editable is correct", 225 { flags: BOUNDARY_FLAG_STOP_IN_EDITABLE } 226 ); 227 228 testBoundarySequence( 229 firstPoint, 230 BOUNDARY_WORD_START, 231 DIRECTION_NEXT, 232 [ 233 ["Rob ca", 0], 234 ["Rob ca", 4], 235 ["n m", 2], 236 ], 237 "Forward BOUNDARY_WORD_START sequence when stopping in editable is correct", 238 { 239 flags: BOUNDARY_FLAG_STOP_IN_EDITABLE, 240 todo: true, // Shouldn't consider end of input a word start 241 } 242 ); 243 }, 244 { chrome: true, topLevel: true, iframe: false, remoteIframe: false } 245 ); 246 247 addAccessibleTask( 248 ` 249 <p id="p" style="white-space: pre-line;">A bug 250 on a <span style="display: block;">rug</span></p> 251 <p id="p2"> 252 Numbers: 253 </p> 254 <ul> 255 <li>One</li> 256 <li>Two</li> 257 <li>Three</li> 258 </ul>`, 259 function (browser, docAcc) { 260 const firstPoint = createTextLeafPoint(docAcc, 0); 261 const lastPoint = createTextLeafPoint(docAcc, kTextEndOffset); 262 263 const expectedParagraphStart = [ 264 ["A bug\non a ", 0], 265 ["A bug\non a ", 6], 266 ["rug", 0], 267 ["Numbers: ", 0], 268 ["• ", 0], 269 ["• ", 0], 270 ["• ", 0], 271 ]; 272 testBoundarySequence( 273 firstPoint, 274 BOUNDARY_PARAGRAPH, 275 DIRECTION_NEXT, 276 [...expectedParagraphStart, readablePoint(lastPoint)], 277 "Forward BOUNDARY_PARAGRAPH sequence is correct" 278 ); 279 280 const paragraphStart = createTextLeafPoint( 281 findAccessibleChildByID(docAcc, "p2").firstChild, 282 0 283 ); 284 const wordEnd = paragraphStart.findBoundary( 285 BOUNDARY_WORD_END, 286 DIRECTION_NEXT, 287 BOUNDARY_FLAG_INCLUDE_ORIGIN 288 ); 289 testPointEqual( 290 wordEnd, 291 paragraphStart, 292 "The word end from the previous block is the first point in this block" 293 ); 294 }, 295 { chrome: true, topLevel: true, iframe: false, remoteIframe: false } 296 ); 297 298 // Test for skipping list item bullets. 299 addAccessibleTask( 300 `<ul> 301 <li>One</li> 302 <li>Two</li> 303 <li style="white-space: pre-line;">Three 304 Four</li> 305 </ul>`, 306 function (browser, docAcc) { 307 const firstPoint = createTextLeafPoint(docAcc, 0); 308 const lastPoint = createTextLeafPoint(docAcc, kTextEndOffset); 309 310 const firstNonMarkerPoint = firstPoint.findBoundary( 311 BOUNDARY_CHAR, 312 DIRECTION_NEXT, 313 BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER | BOUNDARY_FLAG_INCLUDE_ORIGIN 314 ); 315 Assert.deepEqual( 316 readablePoint(firstNonMarkerPoint), 317 ["One", 0], 318 "First non-marker point is correct" 319 ); 320 321 const expectedParagraphStart = [ 322 ["One", 0], 323 ["Two", 0], 324 ["Three\nFour", 0], 325 ["Three\nFour", 6], 326 ]; 327 328 testBoundarySequence( 329 firstPoint, 330 BOUNDARY_PARAGRAPH, 331 DIRECTION_NEXT, 332 [...expectedParagraphStart, readablePoint(lastPoint)], 333 "Forward BOUNDARY_PARAGRAPH skipping list item markers sequence is correct", 334 { flags: BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER } 335 ); 336 337 testBoundarySequence( 338 lastPoint, 339 BOUNDARY_PARAGRAPH, 340 DIRECTION_PREVIOUS, 341 [...expectedParagraphStart].reverse(), 342 "Backward BOUNDARY_PARAGRAPH skipping list item markers sequence is correct", 343 { flags: BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER } 344 ); 345 346 const expectedCharSequence = [ 347 ["One", 0], 348 ["One", 1], 349 ["One", 2], 350 ["Two", 0], 351 ["Two", 1], 352 ["Two", 2], 353 ["Three\nFour", 0], 354 ["Three\nFour", 1], 355 ["Three\nFour", 2], 356 ["Three\nFour", 3], 357 ["Three\nFour", 4], 358 ["Three\nFour", 5], 359 ["Three\nFour", 6], 360 ["Three\nFour", 7], 361 ["Three\nFour", 8], 362 ["Three\nFour", 9], 363 ["Three\nFour", 10], 364 ]; 365 testBoundarySequence( 366 firstPoint, 367 BOUNDARY_CHAR, 368 DIRECTION_NEXT, 369 expectedCharSequence, 370 "Forward BOUNDARY_CHAR skipping list item markers sequence is correct", 371 { flags: BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER } 372 ); 373 374 testBoundarySequence( 375 lastPoint, 376 BOUNDARY_CHAR, 377 DIRECTION_PREVIOUS, 378 [...expectedCharSequence].reverse(), 379 "Backward BOUNDARY_CHAR skipping list item markers sequence is correct", 380 { flags: BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER } 381 ); 382 383 const expectedWordStartSequence = [ 384 ["One", 0], 385 ["Two", 0], 386 ["Three\nFour", 0], 387 ["Three\nFour", 6], 388 ]; 389 testBoundarySequence( 390 firstPoint, 391 BOUNDARY_WORD_START, 392 DIRECTION_NEXT, 393 [...expectedWordStartSequence, readablePoint(lastPoint)], 394 "Forward BOUNDARY_WORD_START skipping list item markers sequence is correct", 395 { flags: BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER } 396 ); 397 398 testBoundarySequence( 399 lastPoint, 400 BOUNDARY_WORD_START, 401 DIRECTION_PREVIOUS, 402 [...expectedWordStartSequence].reverse(), 403 "Backward BOUNDARY_WORD_START skipping list item markers sequence is correct", 404 { flags: BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER } 405 ); 406 407 const expectedWordEndSequence = [ 408 ["Two", 0], 409 ["Three\nFour", 0], 410 ["Three\nFour", 5], 411 ["Three\nFour", 10], 412 ]; 413 testBoundarySequence( 414 firstPoint, 415 BOUNDARY_WORD_END, 416 DIRECTION_NEXT, 417 expectedWordEndSequence, 418 "Forward BOUNDARY_WORD_END skipping list item markers sequence is correct", 419 { flags: BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER } 420 ); 421 422 testBoundarySequence( 423 lastPoint, 424 BOUNDARY_WORD_END, 425 DIRECTION_PREVIOUS, 426 [ 427 readablePoint(firstNonMarkerPoint), 428 ...expectedWordEndSequence, 429 ].reverse(), 430 "Backward BOUNDARY_WORD_END skipping list item markers sequence is correct", 431 { flags: BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER } 432 ); 433 434 const expectedLineStartSequence = [ 435 ["One", 0], 436 ["Two", 0], 437 ["Three\nFour", 0], 438 ["Three\nFour", 6], 439 ]; 440 testBoundarySequence( 441 firstPoint, 442 BOUNDARY_LINE_START, 443 DIRECTION_NEXT, 444 // Add last point in doc 445 [...expectedLineStartSequence, readablePoint(lastPoint)], 446 "Forward BOUNDARY_LINE_START skipping list item markers sequence is correct", 447 { flags: BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER } 448 ); 449 450 testBoundarySequence( 451 lastPoint, 452 BOUNDARY_LINE_START, 453 DIRECTION_PREVIOUS, 454 // Add last point in doc 455 [...expectedLineStartSequence].reverse(), 456 "Backward BOUNDARY_LINE_START skipping list item markers sequence is correct", 457 { flags: BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER } 458 ); 459 }, 460 { chrome: true, topLevel: true, iframe: false, remoteIframe: false } 461 ); 462 463 /** 464 * Test the paragraph boundary on tables. 465 */ 466 addAccessibleTask( 467 ` 468 <table id="table"> 469 <tr><th>a</th><td>b</td></tr> 470 <tr><td>c</td><td>d</td></tr> 471 </table> 472 `, 473 async function (browser, docAcc) { 474 const firstPoint = createTextLeafPoint(docAcc, 0); 475 const lastPoint = createTextLeafPoint(docAcc, kTextEndOffset); 476 testBoundarySequence( 477 firstPoint, 478 BOUNDARY_PARAGRAPH, 479 DIRECTION_NEXT, 480 [["a", 0], ["b", 0], ["c", 0], ["d", 0], readablePoint(lastPoint)], 481 "Forward BOUNDARY_PARAGRAPH sequence is correct" 482 ); 483 }, 484 { chrome: true, topLevel: true, iframe: false, remoteIframe: false } 485 ); 486 487 /* 488 * Test the word boundary with punctuation character 489 */ 490 addAccessibleTask( 491 ` 492 <p>ab'cd</p> 493 `, 494 async function (browser, docAcc) { 495 const firstPoint = createTextLeafPoint(docAcc, 0); 496 const lastPoint = createTextLeafPoint(docAcc, kTextEndOffset); 497 498 const expectedWordStartSequence = [ 499 ["ab'cd", 0], 500 ["ab'cd", 3], 501 ["ab'cd", 5], 502 ]; 503 testBoundarySequence( 504 firstPoint, 505 BOUNDARY_WORD_START, 506 DIRECTION_NEXT, 507 expectedWordStartSequence, 508 "Forward BOUNDARY_WORD_START sequence is correct" 509 ); 510 const expectedWordEndSequence = [ 511 ["ab'cd", 5], 512 ["ab'cd", 3], 513 ["ab'cd", 0], 514 ]; 515 testBoundarySequence( 516 lastPoint, 517 BOUNDARY_WORD_END, 518 DIRECTION_PREVIOUS, 519 expectedWordEndSequence, 520 "Backward BOUNDARY_WORD_END sequence is correct" 521 ); 522 }, 523 { chrome: true, topLevel: true, iframe: false, remoteIframe: false } 524 );