Index: trunk/extensions/VisualEditor/tests/es/es.DocumentNode.test.js |
— | — | @@ -114,7 +114,7 @@ |
115 | 115 | } |
116 | 116 | } ); |
117 | 117 | |
118 | | -test( 'es.DocumentBranchNode.selectNodes', 21, function() { |
| 118 | +test( 'es.DocumentBranchNode.selectNodes', 75, function() { |
119 | 119 | |
120 | 120 | // selectNodes tests |
121 | 121 | |
— | — | @@ -125,11 +125,8 @@ |
126 | 126 | var f = new DocumentBranchNodeStub( [], 'f', 8 ), |
127 | 127 | g = new DocumentBranchNodeStub( [], 'g', 8 ), |
128 | 128 | h = new DocumentBranchNodeStub( [], 'h', 8 ), |
129 | | - root2 = new DocumentBranchNodeStub( [f, g, h], 'root2', 30 ); |
130 | | - // FIXME: QUnit thinks f == g because both are empty arrays. Rawr. |
131 | | - // TODO make sure there is a test case for everything that is special-cased in the code |
132 | | - // TODO also nest with a more complicated nested structure, like the one from |
133 | | - // es.DocumentModel.test.js |
| 129 | + root2 = new DocumentBranchNodeStub( [f, g, h], 'root2', 30 ), |
| 130 | + big = es.DocumentModel.newFromPlainObject( esTest.obj ); |
134 | 131 | |
135 | 132 | // Tests 1 ... 22 |
136 | 133 | // Possible positions are: |
— | — | @@ -236,59 +233,558 @@ |
237 | 234 | 'output': [], |
238 | 235 | 'desc': 'Zero-length range past the end of a node' |
239 | 236 | }, |
240 | | - // TODO add a complete set of combinations for cross-node ranges |
241 | 237 | { |
242 | 238 | 'node': root2, |
243 | | - 'input': new es.Range( 5, 25 ), |
| 239 | + 'input': new es.Range( 20, 20 ), |
| 240 | + 'output': [], |
| 241 | + 'desc': 'Zero-length range between two nodes' |
| 242 | + }, |
| 243 | + // Complete set of combinations for cross-node selections. Generated with help of a script |
| 244 | + { |
| 245 | + 'node': root2, |
| 246 | + 'input': new es.Range( 0, 11 ), |
244 | 247 | 'output': [ |
245 | | - { 'node': f, 'range': new es.Range( 4, 8 ) }, |
| 248 | + { 'node': f }, |
| 249 | + { 'node': g, 'range': new es.Range( 0, 0 ) } |
| 250 | + ], |
| 251 | + 'desc': 'Range starting before the beginning of the first node and ending at the beginning of the second node' |
| 252 | + }, |
| 253 | + { |
| 254 | + 'node': root2, |
| 255 | + 'input': new es.Range( 0, 14 ), |
| 256 | + 'output': [ |
| 257 | + { 'node': f }, |
| 258 | + { 'node': g, 'range': new es.Range( 0, 3 ) } |
| 259 | + ], |
| 260 | + 'desc': 'Range starting before the beginning of the first node and ending in the middle of the second node' |
| 261 | + }, |
| 262 | + { |
| 263 | + 'node': root2, |
| 264 | + 'input': new es.Range( 0, 19 ), |
| 265 | + 'output': [ |
| 266 | + { 'node': f }, |
| 267 | + { 'node': g, 'range': new es.Range( 0, 8 ) } |
| 268 | + ], |
| 269 | + 'desc': 'Range starting before the beginning of the first node and ending at the end of the second node' |
| 270 | + }, |
| 271 | + { |
| 272 | + 'node': root2, |
| 273 | + 'input': new es.Range( 0, 20 ), |
| 274 | + 'output': [ |
| 275 | + { 'node': f }, |
| 276 | + { 'node': g } |
| 277 | + ], |
| 278 | + 'desc': 'Range starting before the beginning of the first node and ending between the second and the third node' |
| 279 | + }, |
| 280 | + { |
| 281 | + 'node': root2, |
| 282 | + 'input': new es.Range( 0, 21 ), |
| 283 | + 'output': [ |
| 284 | + { 'node': f }, |
246 | 285 | { 'node': g }, |
247 | | - { 'node': h, 'range': new es.Range( 0, 4 ) } |
| 286 | + { 'node': h, 'range': new es.Range( 0, 0 ) } |
248 | 287 | ], |
249 | | - 'desc': 'Range from the middle of the first node to the middle of the third' |
| 288 | + 'desc': 'Range starting before the beginning of the first node and ending at the beginning of the third node' |
250 | 289 | }, |
251 | 290 | { |
252 | 291 | 'node': root2, |
| 292 | + 'input': new es.Range( 0, 27 ), |
| 293 | + 'output': [ |
| 294 | + { 'node': f }, |
| 295 | + { 'node': g }, |
| 296 | + { 'node': h, 'range': new es.Range( 0, 6 ) } |
| 297 | + ], |
| 298 | + 'desc': 'Range starting before the beginning of the first node and ending in the middle of the third node' |
| 299 | + }, |
| 300 | + { |
| 301 | + 'node': root2, |
| 302 | + 'input': new es.Range( 0, 29 ), |
| 303 | + 'output': [ |
| 304 | + { 'node': f }, |
| 305 | + { 'node': g }, |
| 306 | + { 'node': h, 'range': new es.Range( 0, 8 ) } |
| 307 | + ], |
| 308 | + 'desc': 'Range starting before the beginning of the first node and ending at the end of the third node' |
| 309 | + }, |
| 310 | + { |
| 311 | + 'node': root2, |
| 312 | + 'input': new es.Range( 0, 30 ), |
| 313 | + 'output': [ |
| 314 | + { 'node': f }, |
| 315 | + { 'node': g }, |
| 316 | + { 'node': h } |
| 317 | + ], |
| 318 | + 'desc': 'Range starting before the beginning of the first node and ending past the end of the third node' |
| 319 | + }, |
| 320 | + { |
| 321 | + 'node': root2, |
| 322 | + 'input': new es.Range( 1, 11 ), |
| 323 | + 'output': [ |
| 324 | + { 'node': f, 'range': new es.Range( 0, 8 ) }, |
| 325 | + { 'node': g, 'range': new es.Range( 0, 0 ) } |
| 326 | + ], |
| 327 | + 'desc': 'Range starting at the beginning of the first node and ending at the beginning of the second node' |
| 328 | + }, |
| 329 | + { |
| 330 | + 'node': root2, |
| 331 | + 'input': new es.Range( 1, 14 ), |
| 332 | + 'output': [ |
| 333 | + { 'node': f, 'range': new es.Range( 0, 8 ) }, |
| 334 | + { 'node': g, 'range': new es.Range( 0, 3 ) } |
| 335 | + ], |
| 336 | + 'desc': 'Range starting at the beginning of the first node and ending in the middle of the second node' |
| 337 | + }, |
| 338 | + { |
| 339 | + 'node': root2, |
| 340 | + 'input': new es.Range( 1, 19 ), |
| 341 | + 'output': [ |
| 342 | + { 'node': f, 'range': new es.Range( 0, 8 ) }, |
| 343 | + { 'node': g, 'range': new es.Range( 0, 8 ) } |
| 344 | + ], |
| 345 | + 'desc': 'Range starting at the beginning of the first node and ending at the end of the second node' |
| 346 | + }, |
| 347 | + { |
| 348 | + 'node': root2, |
| 349 | + 'input': new es.Range( 1, 20 ), |
| 350 | + 'output': [ |
| 351 | + { 'node': f, 'range': new es.Range( 0, 8 ) }, |
| 352 | + { 'node': g } |
| 353 | + ], |
| 354 | + 'desc': 'Range starting at the beginning of the first node and ending between the second and the third node' |
| 355 | + }, |
| 356 | + { |
| 357 | + 'node': root2, |
| 358 | + 'input': new es.Range( 1, 21 ), |
| 359 | + 'output': [ |
| 360 | + { 'node': f, 'range': new es.Range( 0, 8 ) }, |
| 361 | + { 'node': g }, |
| 362 | + { 'node': h, 'range': new es.Range( 0, 0 ) } |
| 363 | + ], |
| 364 | + 'desc': 'Range starting at the beginning of the first node and ending at the beginning of the third node' |
| 365 | + }, |
| 366 | + { |
| 367 | + 'node': root2, |
| 368 | + 'input': new es.Range( 1, 27 ), |
| 369 | + 'output': [ |
| 370 | + { 'node': f, 'range': new es.Range( 0, 8 ) }, |
| 371 | + { 'node': g }, |
| 372 | + { 'node': h, 'range': new es.Range( 0, 6 ) } |
| 373 | + ], |
| 374 | + 'desc': 'Range starting at the beginning of the first node and ending in the middle of the third node' |
| 375 | + }, |
| 376 | + { |
| 377 | + 'node': root2, |
| 378 | + 'input': new es.Range( 1, 29 ), |
| 379 | + 'output': [ |
| 380 | + { 'node': f, 'range': new es.Range( 0, 8 ) }, |
| 381 | + { 'node': g }, |
| 382 | + { 'node': h, 'range': new es.Range( 0, 8 ) } |
| 383 | + ], |
| 384 | + 'desc': 'Range starting at the beginning of the first node and ending at the end of the third node' |
| 385 | + }, |
| 386 | + { |
| 387 | + 'node': root2, |
| 388 | + 'input': new es.Range( 1, 30 ), |
| 389 | + 'output': [ |
| 390 | + { 'node': f, 'range': new es.Range( 0, 8 ) }, |
| 391 | + { 'node': g }, |
| 392 | + { 'node': h } |
| 393 | + ], |
| 394 | + 'desc': 'Range starting at the beginning of the first node and ending past the end of the third node' |
| 395 | + }, |
| 396 | + { |
| 397 | + 'node': root2, |
253 | 398 | 'input': new es.Range( 5, 11 ), |
254 | 399 | 'output': [ |
255 | 400 | { 'node': f, 'range': new es.Range( 4, 8 ) }, |
256 | 401 | { 'node': g, 'range': new es.Range( 0, 0 ) } |
257 | 402 | ], |
258 | | - 'desc': 'Range from the middle of a node to the beginning of the second' |
| 403 | + 'desc': 'Range starting in the middle of the first node and ending at the beginning of the second node' |
259 | 404 | }, |
260 | 405 | { |
261 | 406 | 'node': root2, |
262 | | - 'input': new es.Range( 5, 12 ), |
| 407 | + 'input': new es.Range( 5, 14 ), |
263 | 408 | 'output': [ |
264 | 409 | { 'node': f, 'range': new es.Range( 4, 8 ) }, |
265 | | - { 'node': g, 'range': new es.Range( 0, 1 ) } |
| 410 | + { 'node': g, 'range': new es.Range( 0, 3 ) } |
266 | 411 | ], |
267 | | - 'desc': 'Range from in the middle of a node to the first character of the second' |
| 412 | + 'desc': 'Range starting in the middle of the first node and ending in the middle of the second node' |
268 | 413 | }, |
269 | 414 | { |
270 | 415 | 'node': root2, |
271 | | - 'input': new es.Range( 8, 16 ), |
| 416 | + 'input': new es.Range( 5, 19 ), |
272 | 417 | 'output': [ |
273 | | - { 'node': f, 'range': new es.Range( 7, 8 ) }, |
274 | | - { 'node': g, 'range': new es.Range( 0, 5 ) } |
| 418 | + { 'node': f, 'range': new es.Range( 4, 8 ) }, |
| 419 | + { 'node': g, 'range': new es.Range( 0, 8 ) } |
275 | 420 | ], |
276 | | - 'desc': 'Range from before the last character of a node to the middle of the next node' |
| 421 | + 'desc': 'Range starting in the middle of the first node and ending at the end of the second node' |
277 | 422 | }, |
278 | 423 | { |
279 | 424 | 'node': root2, |
280 | | - 'input': new es.Range( 9, 16 ), |
| 425 | + 'input': new es.Range( 5, 20 ), |
281 | 426 | 'output': [ |
| 427 | + { 'node': f, 'range': new es.Range( 4, 8 ) }, |
| 428 | + { 'node': g } |
| 429 | + ], |
| 430 | + 'desc': 'Range starting in the middle of the first node and ending between the second and the third node' |
| 431 | + }, |
| 432 | + { |
| 433 | + 'node': root2, |
| 434 | + 'input': new es.Range( 5, 21 ), |
| 435 | + 'output': [ |
| 436 | + { 'node': f, 'range': new es.Range( 4, 8 ) }, |
| 437 | + { 'node': g }, |
| 438 | + { 'node': h, 'range': new es.Range( 0, 0 ) } |
| 439 | + ], |
| 440 | + 'desc': 'Range starting in the middle of the first node and ending at the beginning of the third node' |
| 441 | + }, |
| 442 | + { |
| 443 | + 'node': root2, |
| 444 | + 'input': new es.Range( 5, 27 ), |
| 445 | + 'output': [ |
| 446 | + { 'node': f, 'range': new es.Range( 4, 8 ) }, |
| 447 | + { 'node': g }, |
| 448 | + { 'node': h, 'range': new es.Range( 0, 6 ) } |
| 449 | + ], |
| 450 | + 'desc': 'Range starting in the middle of the first node and ending in the middle of the third node' |
| 451 | + }, |
| 452 | + { |
| 453 | + 'node': root2, |
| 454 | + 'input': new es.Range( 5, 29 ), |
| 455 | + 'output': [ |
| 456 | + { 'node': f, 'range': new es.Range( 4, 8 ) }, |
| 457 | + { 'node': g }, |
| 458 | + { 'node': h, 'range': new es.Range( 0, 8 ) } |
| 459 | + ], |
| 460 | + 'desc': 'Range starting in the middle of the first node and ending at the end of the third node' |
| 461 | + }, |
| 462 | + { |
| 463 | + 'node': root2, |
| 464 | + 'input': new es.Range( 5, 30 ), |
| 465 | + 'output': [ |
| 466 | + { 'node': f, 'range': new es.Range( 4, 8 ) }, |
| 467 | + { 'node': g }, |
| 468 | + { 'node': h } |
| 469 | + ], |
| 470 | + 'desc': 'Range starting in the middle of the first node and ending past the end of the third node' |
| 471 | + }, |
| 472 | + { |
| 473 | + 'node': root2, |
| 474 | + 'input': new es.Range( 9, 11 ), |
| 475 | + 'output': [ |
282 | 476 | { 'node': f, 'range': new es.Range( 8, 8 ) }, |
283 | | - { 'node': g, 'range': new es.Range( 0, 5 ) } |
| 477 | + { 'node': g, 'range': new es.Range( 0, 0 ) } |
284 | 478 | ], |
285 | | - 'desc': 'Range from at the end of a node to the middle of the next node' |
| 479 | + 'desc': 'Range starting at the end of the first node and ending at the beginning of the second node' |
| 480 | + }, |
| 481 | + { |
| 482 | + 'node': root2, |
| 483 | + 'input': new es.Range( 9, 14 ), |
| 484 | + 'output': [ |
| 485 | + { 'node': f, 'range': new es.Range( 8, 8 ) }, |
| 486 | + { 'node': g, 'range': new es.Range( 0, 3 ) } |
| 487 | + ], |
| 488 | + 'desc': 'Range starting at the end of the first node and ending in the middle of the second node' |
| 489 | + }, |
| 490 | + { |
| 491 | + 'node': root2, |
| 492 | + 'input': new es.Range( 9, 19 ), |
| 493 | + 'output': [ |
| 494 | + { 'node': f, 'range': new es.Range( 8, 8 ) }, |
| 495 | + { 'node': g, 'range': new es.Range( 0, 8 ) } |
| 496 | + ], |
| 497 | + 'desc': 'Range starting at the end of the first node and ending at the end of the second node' |
| 498 | + }, |
| 499 | + { |
| 500 | + 'node': root2, |
| 501 | + 'input': new es.Range( 9, 20 ), |
| 502 | + 'output': [ |
| 503 | + { 'node': f, 'range': new es.Range( 8, 8 ) }, |
| 504 | + { 'node': g } |
| 505 | + ], |
| 506 | + 'desc': 'Range starting at the end of the first node and ending between the second and the third node' |
| 507 | + }, |
| 508 | + { |
| 509 | + 'node': root2, |
| 510 | + 'input': new es.Range( 9, 21 ), |
| 511 | + 'output': [ |
| 512 | + { 'node': f, 'range': new es.Range( 8, 8 ) }, |
| 513 | + { 'node': g }, |
| 514 | + { 'node': h, 'range': new es.Range( 0, 0 ) } |
| 515 | + ], |
| 516 | + 'desc': 'Range starting at the end of the first node and ending at the beginning of the third node' |
| 517 | + }, |
| 518 | + { |
| 519 | + 'node': root2, |
| 520 | + 'input': new es.Range( 9, 27 ), |
| 521 | + 'output': [ |
| 522 | + { 'node': f, 'range': new es.Range( 8, 8 ) }, |
| 523 | + { 'node': g }, |
| 524 | + { 'node': h, 'range': new es.Range( 0, 6 ) } |
| 525 | + ], |
| 526 | + 'desc': 'Range starting at the end of the first node and ending in the middle of the third node' |
| 527 | + }, |
| 528 | + { |
| 529 | + 'node': root2, |
| 530 | + 'input': new es.Range( 9, 29 ), |
| 531 | + 'output': [ |
| 532 | + { 'node': f, 'range': new es.Range( 8, 8 ) }, |
| 533 | + { 'node': g }, |
| 534 | + { 'node': h, 'range': new es.Range( 0, 8 ) } |
| 535 | + ], |
| 536 | + 'desc': 'Range starting at the end of the first node and ending at the end of the third node' |
| 537 | + }, |
| 538 | + { |
| 539 | + 'node': root2, |
| 540 | + 'input': new es.Range( 9, 30 ), |
| 541 | + 'output': [ |
| 542 | + { 'node': f, 'range': new es.Range( 8, 8 ) }, |
| 543 | + { 'node': g }, |
| 544 | + { 'node': h } |
| 545 | + ], |
| 546 | + 'desc': 'Range starting at the end of the first node and ending past the end of the third node' |
| 547 | + }, |
| 548 | + { |
| 549 | + 'node': root2, |
| 550 | + 'input': new es.Range( 10, 21 ), |
| 551 | + 'output': [ |
| 552 | + { 'node': g }, |
| 553 | + { 'node': h, 'range': new es.Range( 0, 0 ) } |
| 554 | + ], |
| 555 | + 'desc': 'Range starting between the first and the second node and ending at the beginning of the third node' |
| 556 | + }, |
| 557 | + { |
| 558 | + 'node': root2, |
| 559 | + 'input': new es.Range( 10, 27 ), |
| 560 | + 'output': [ |
| 561 | + { 'node': g }, |
| 562 | + { 'node': h, 'range': new es.Range( 0, 6 ) } |
| 563 | + ], |
| 564 | + 'desc': 'Range starting between the first and the second node and ending in the middle of the third node' |
| 565 | + }, |
| 566 | + { |
| 567 | + 'node': root2, |
| 568 | + 'input': new es.Range( 10, 29 ), |
| 569 | + 'output': [ |
| 570 | + { 'node': g }, |
| 571 | + { 'node': h, 'range': new es.Range( 0, 8 ) } |
| 572 | + ], |
| 573 | + 'desc': 'Range starting between the first and the second node and ending at the end of the third node' |
| 574 | + }, |
| 575 | + { |
| 576 | + 'node': root2, |
| 577 | + 'input': new es.Range( 10, 30 ), |
| 578 | + 'output': [ |
| 579 | + { 'node': g }, |
| 580 | + { 'node': h } |
| 581 | + ], |
| 582 | + 'desc': 'Range starting between the first and the second node and ending past the end of the third node' |
| 583 | + }, |
| 584 | + { |
| 585 | + 'node': root2, |
| 586 | + 'input': new es.Range( 11, 21 ), |
| 587 | + 'output': [ |
| 588 | + { 'node': g, 'range': new es.Range( 0, 8 ) }, |
| 589 | + { 'node': h, 'range': new es.Range( 0, 0 ) } |
| 590 | + ], |
| 591 | + 'desc': 'Range starting at the beginning of the second node and ending at the beginning of the third node' |
| 592 | + }, |
| 593 | + { |
| 594 | + 'node': root2, |
| 595 | + 'input': new es.Range( 11, 27 ), |
| 596 | + 'output': [ |
| 597 | + { 'node': g, 'range': new es.Range( 0, 8 ) }, |
| 598 | + { 'node': h, 'range': new es.Range( 0, 6 ) } |
| 599 | + ], |
| 600 | + 'desc': 'Range starting at the beginning of the second node and ending in the middle of the third node' |
| 601 | + }, |
| 602 | + { |
| 603 | + 'node': root2, |
| 604 | + 'input': new es.Range( 11, 29 ), |
| 605 | + 'output': [ |
| 606 | + { 'node': g, 'range': new es.Range( 0, 8 ) }, |
| 607 | + { 'node': h, 'range': new es.Range( 0, 8 ) } |
| 608 | + ], |
| 609 | + 'desc': 'Range starting at the beginning of the second node and ending at the end of the third node' |
| 610 | + }, |
| 611 | + { |
| 612 | + 'node': root2, |
| 613 | + 'input': new es.Range( 11, 30 ), |
| 614 | + 'output': [ |
| 615 | + { 'node': g, 'range': new es.Range( 0, 8 ) }, |
| 616 | + { 'node': h } |
| 617 | + ], |
| 618 | + 'desc': 'Range starting at the beginning of the second node and ending past the end of the third node' |
| 619 | + }, |
| 620 | + { |
| 621 | + 'node': root2, |
| 622 | + 'input': new es.Range( 14, 21 ), |
| 623 | + 'output': [ |
| 624 | + { 'node': g, 'range': new es.Range( 3, 8 ) }, |
| 625 | + { 'node': h, 'range': new es.Range( 0, 0 ) } |
| 626 | + ], |
| 627 | + 'desc': 'Range starting in the middle of the second node and ending at the beginning of the third node' |
| 628 | + }, |
| 629 | + { |
| 630 | + 'node': root2, |
| 631 | + 'input': new es.Range( 14, 27 ), |
| 632 | + 'output': [ |
| 633 | + { 'node': g, 'range': new es.Range( 3, 8 ) }, |
| 634 | + { 'node': h, 'range': new es.Range( 0, 6 ) } |
| 635 | + ], |
| 636 | + 'desc': 'Range starting in the middle of the second node and ending in the middle of the third node' |
| 637 | + }, |
| 638 | + { |
| 639 | + 'node': root2, |
| 640 | + 'input': new es.Range( 14, 29 ), |
| 641 | + 'output': [ |
| 642 | + { 'node': g, 'range': new es.Range( 3, 8 ) }, |
| 643 | + { 'node': h, 'range': new es.Range( 0, 8 ) } |
| 644 | + ], |
| 645 | + 'desc': 'Range starting in the middle of the second node and ending at the end of the third node' |
| 646 | + }, |
| 647 | + { |
| 648 | + 'node': root2, |
| 649 | + 'input': new es.Range( 14, 30 ), |
| 650 | + 'output': [ |
| 651 | + { 'node': g, 'range': new es.Range( 3, 8 ) }, |
| 652 | + { 'node': h } |
| 653 | + ], |
| 654 | + 'desc': 'Range starting in the middle of the second node and ending past the end of the third node' |
| 655 | + }, |
| 656 | + { |
| 657 | + 'node': root2, |
| 658 | + 'input': new es.Range( 19, 21 ), |
| 659 | + 'output': [ |
| 660 | + { 'node': g, 'range': new es.Range( 8, 8 ) }, |
| 661 | + { 'node': h, 'range': new es.Range( 0, 0 ) } |
| 662 | + ], |
| 663 | + 'desc': 'Range starting at the end of the second node and ending at the beginning of the third node' |
| 664 | + }, |
| 665 | + { |
| 666 | + 'node': root2, |
| 667 | + 'input': new es.Range( 19, 27 ), |
| 668 | + 'output': [ |
| 669 | + { 'node': g, 'range': new es.Range( 8, 8 ) }, |
| 670 | + { 'node': h, 'range': new es.Range( 0, 6 ) } |
| 671 | + ], |
| 672 | + 'desc': 'Range starting at the end of the second node and ending in the middle of the third node' |
| 673 | + }, |
| 674 | + { |
| 675 | + 'node': root2, |
| 676 | + 'input': new es.Range( 19, 29 ), |
| 677 | + 'output': [ |
| 678 | + { 'node': g, 'range': new es.Range( 8, 8 ) }, |
| 679 | + { 'node': h, 'range': new es.Range( 0, 8 ) } |
| 680 | + ], |
| 681 | + 'desc': 'Range starting at the end of the second node and ending at the end of the third node' |
| 682 | + }, |
| 683 | + { |
| 684 | + 'node': root2, |
| 685 | + 'input': new es.Range( 19, 30 ), |
| 686 | + 'output': [ |
| 687 | + { 'node': g, 'range': new es.Range( 8, 8 ) }, |
| 688 | + { 'node': h } |
| 689 | + ], |
| 690 | + 'desc': 'Range starting at the end of the second node and ending past the end of the third node' |
| 691 | + }, |
| 692 | + // Tests for childless nodes |
| 693 | + { |
| 694 | + 'node': g, |
| 695 | + 'input': new es.Range( 1, 3 ), |
| 696 | + 'output': [ |
| 697 | + { 'node': g, 'range': new es.Range( 1, 3 ) } |
| 698 | + ], |
| 699 | + 'desc': 'Childless node given, range not out of bounds' |
| 700 | + }, |
| 701 | + { |
| 702 | + 'node': g, |
| 703 | + 'input': new es.Range( 0, 8 ), |
| 704 | + 'output': [ |
| 705 | + { 'node': g, 'range': new es.Range( 0, 8 ) } |
| 706 | + ], |
| 707 | + 'desc': 'Childless node given, range covers entire node' |
| 708 | + }, |
| 709 | + // Tests for out-of-bounds cases |
| 710 | + { |
| 711 | + 'node': g, |
| 712 | + 'input': new es.Range( -1, 3 ), |
| 713 | + 'exception': /^The start offset of the range is negative$/, |
| 714 | + 'desc': 'Childless node given, range start out of bounds' |
| 715 | + }, |
| 716 | + { |
| 717 | + 'node': g, |
| 718 | + 'input': new es.Range( 1, 9 ), |
| 719 | + 'exception': /^The end offset of the range is past the end of the node$/, |
| 720 | + 'desc': 'Childless node given, range end out of bounds' |
| 721 | + }, |
| 722 | + { |
| 723 | + 'node': root2, |
| 724 | + 'input': new es.Range( 31, 35 ), |
| 725 | + 'exception': /^The start offset of the range is past the end of the node$/, |
| 726 | + 'desc': 'Node with children given, range start out of bounds' |
| 727 | + }, |
| 728 | + { |
| 729 | + 'node': root2, |
| 730 | + 'input': new es.Range( 30, 35 ), |
| 731 | + 'exception': /^The end offset of the range is past the end of the node$/, |
| 732 | + 'desc': 'Node with children given, range end out of bounds' |
| 733 | + }, |
| 734 | + // Tests for recursion cases |
| 735 | + { |
| 736 | + 'node': big, |
| 737 | + 'input': new es.Range( 2, 10 ), |
| 738 | + 'output': [ |
| 739 | + { 'node': big.children[0], 'range': new es.Range( 1, 3 ) }, |
| 740 | + { 'node': big.children[1], 'range': new es.Range( 0, 4 ) } |
| 741 | + ], |
| 742 | + 'desc': 'Select from before the b to after the d' |
| 743 | + }, |
| 744 | + { |
| 745 | + 'node': big, |
| 746 | + 'input': new es.Range( 3, 27 ), |
| 747 | + 'output': [ |
| 748 | + { 'node': big.children[0], 'range': new es.Range( 2, 3 ) }, |
| 749 | + { 'node': big.children[1] }, |
| 750 | + { 'node': big.children[2], 'range': new es.Range( 0, 1 ) } |
| 751 | + ], |
| 752 | + 'desc': 'Select from before the c to after the h' |
| 753 | + }, |
| 754 | + { |
| 755 | + 'node': big, |
| 756 | + 'input': new es.Range( 9, 17 ), |
| 757 | + 'output': [ |
| 758 | + { 'node': big.children[1].children[0].children[0].children[0], 'range': new es.Range( 0, 1 ) }, |
| 759 | + { 'node': big.children[1].children[0].children[0].children[1], 'range': new es.Range( 0, 5 ) } |
| 760 | + ], |
| 761 | + 'desc': 'Select from before the d to after the f, with recursion' |
| 762 | + }, |
| 763 | + { |
| 764 | + 'node': big, |
| 765 | + 'input': new es.Range( 9, 17 ), |
| 766 | + 'shallow': true, |
| 767 | + 'output': [ |
| 768 | + { 'node': big.children[1], 'range': new es.Range( 3, 11 ) } |
| 769 | + ], |
| 770 | + 'desc': 'Select from before the d to after the f, without recursion' |
286 | 771 | } |
287 | 772 | ]; |
| 773 | + |
288 | 774 | for ( var i = 0; i < selectNodesTests.length; i++ ) { |
289 | | - deepEqual( |
290 | | - root2.selectNodes( selectNodesTests[i].input ), |
291 | | - selectNodesTests[i].output, |
292 | | - selectNodesTests[i].desc |
293 | | - ); |
| 775 | + if ( 'output' in selectNodesTests[i] ) { |
| 776 | + deepEqual( |
| 777 | + selectNodesTests[i].node.selectNodes( selectNodesTests[i].input, selectNodesTests[i].shallow ), |
| 778 | + selectNodesTests[i].output, |
| 779 | + selectNodesTests[i].desc |
| 780 | + ); |
| 781 | + } else if ( 'exception' in selectNodesTests[i] ) { |
| 782 | + raises( |
| 783 | + function() { |
| 784 | + selectNodesTests[i].node.selectNodes( selectNodesTests[i].input, selectNodesTests[i].shallow ); |
| 785 | + }, |
| 786 | + selectNodesTests[i].exception, |
| 787 | + selectNodesTests[i].desc |
| 788 | + ); |
| 789 | + } |
294 | 790 | } |
295 | 791 | } ); |
Index: trunk/extensions/VisualEditor/modules/es/bases/es.DocumentBranchNode.js |
— | — | @@ -168,24 +168,6 @@ |
169 | 169 | // Empty range outside of any node |
170 | 170 | return []; |
171 | 171 | } |
172 | | - if ( start == left - 1 && end == right + 1 ) { |
173 | | - // The range covers the entire node, including its opening and closing elements |
174 | | - return [ { 'node': this.children[i] } ]; |
175 | | - } |
176 | | - if ( start == left - 1 ) { |
177 | | - // start is between this.children[i-1] and this.children[i], move it to left for |
178 | | - // convenience |
179 | | - // We don't need to check for start < end here because we already have start != end and |
180 | | - // start <= end |
181 | | - start = left; |
182 | | - } |
183 | | - if ( end == right + 1 ) { |
184 | | - // end is between this.children[i] and this.children[i+1], move it to right for |
185 | | - // convenience |
186 | | - // We don't need to check for start < end here because we already have start != end and |
187 | | - // start <= end |
188 | | - end = right; |
189 | | - } |
190 | 172 | |
191 | 173 | startInside = start >= left && start <= right; // is the start inside this.children[i]? |
192 | 174 | endInside = end >= left && end <= right; // is the end inside this.children[i]? |
— | — | @@ -215,6 +197,18 @@ |
216 | 198 | nodes.push( { 'node': this.children[i], 'range': new es.Range( 0, end - left ) } ); |
217 | 199 | // We've found the end, so we're done |
218 | 200 | return nodes; |
| 201 | + } else if ( end == right + 1 ) { |
| 202 | + // end is between this.children[i] and this.children[i+1] |
| 203 | + // start is not inside this.children[i], so the selection covers |
| 204 | + // all of this.children[i], then ends |
| 205 | + nodes.push( { 'node': this.children[i] } ); |
| 206 | + // We've reached the end so we're done |
| 207 | + return nodes; |
| 208 | + } else if ( start == left - 1 ) { |
| 209 | + // start is between this.children[i-1] and this.children[i] |
| 210 | + // end is not inside this.children[i], so the selection covers |
| 211 | + // all of this.children[i] and more |
| 212 | + nodes.push( { 'node': this.children[i] } ); |
219 | 213 | } else if ( nodes.length > 0 ) { |
220 | 214 | // Neither the start nor the end is inside this.children[i], but nodes is non-empty, |
221 | 215 | // so this.children[i] must be between the start and the end |
— | — | @@ -226,11 +220,15 @@ |
227 | 221 | // We use +2 because we need to jump over the offset between this.children[i] and |
228 | 222 | // this.children[i+1] |
229 | 223 | left = right + 2; |
| 224 | + if ( end < left ) { |
| 225 | + // We've skipped over the end, so we're done |
| 226 | + return nodes; |
| 227 | + } |
230 | 228 | } |
231 | 229 | |
232 | 230 | // If we got here, that means that at least some part of the range is out of bounds |
233 | 231 | // This is an error |
234 | | - if ( nodes.length === 0 ) { |
| 232 | + if ( start > right + 1 ) { |
235 | 233 | throw 'The start offset of the range is past the end of the node'; |
236 | 234 | } else { |
237 | 235 | // Apparently the start was inside this node, but the end wasn't |