test_ext_bookmarks.js (49487B)
1 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ 2 /* vim: set sts=2 sw=2 et tw=80: */ 3 "use strict"; 4 5 const { AddonTestUtils } = ChromeUtils.importESModule( 6 "resource://testing-common/AddonTestUtils.sys.mjs" 7 ); 8 9 ChromeUtils.defineESModuleGetters(this, { 10 PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs", 11 }); 12 13 AddonTestUtils.init(this); 14 AddonTestUtils.overrideCertDB(); 15 AddonTestUtils.createAppInfo( 16 "xpcshell@tests.mozilla.org", 17 "XPCShell", 18 "1", 19 "43" 20 ); 21 22 add_task(async function test_bookmarks() { 23 async function background() { 24 let unsortedId, ourId; 25 let initialBookmarkCount = 0; 26 let createdBookmarks = new Set(); 27 let createdFolderId; 28 let createdSeparatorId; 29 let collectedEvents = []; 30 const nonExistentId = "000000000000"; 31 const bookmarkGuids = { 32 menuGuid: "menu________", 33 toolbarGuid: "toolbar_____", 34 unfiledGuid: "unfiled_____", 35 rootGuid: "root________", 36 }; 37 38 function checkOurBookmark(bookmark) { 39 browser.test.assertEq(ourId, bookmark.id, "Bookmark has the expected Id"); 40 browser.test.assertTrue( 41 "parentId" in bookmark, 42 "Bookmark has a parentId" 43 ); 44 browser.test.assertEq( 45 0, 46 bookmark.index, 47 "Bookmark has the expected index" 48 ); // We assume there are no other bookmarks. 49 browser.test.assertEq( 50 "http://example.org/", 51 bookmark.url, 52 "Bookmark has the expected url" 53 ); 54 browser.test.assertEq( 55 "test bookmark", 56 bookmark.title, 57 "Bookmark has the expected title" 58 ); 59 browser.test.assertTrue( 60 "dateAdded" in bookmark, 61 "Bookmark has a dateAdded" 62 ); 63 browser.test.assertFalse( 64 "dateGroupModified" in bookmark, 65 "Bookmark does not have a dateGroupModified" 66 ); 67 browser.test.assertFalse( 68 "unmodifiable" in bookmark, 69 "Bookmark is not unmodifiable" 70 ); 71 browser.test.assertEq( 72 "bookmark", 73 bookmark.type, 74 "Bookmark is of type bookmark" 75 ); 76 } 77 78 function checkBookmark(expected, bookmark) { 79 browser.test.assertEq( 80 expected.url, 81 bookmark.url, 82 "Bookmark has the expected url" 83 ); 84 browser.test.assertEq( 85 expected.title, 86 bookmark.title, 87 "Bookmark has the expected title" 88 ); 89 browser.test.assertEq( 90 expected.index, 91 bookmark.index, 92 "Bookmark has expected index" 93 ); 94 browser.test.assertEq( 95 "bookmark", 96 bookmark.type, 97 "Bookmark is of type bookmark" 98 ); 99 if ("parentId" in expected) { 100 browser.test.assertEq( 101 expected.parentId, 102 bookmark.parentId, 103 "Bookmark has the expected parentId" 104 ); 105 } 106 } 107 108 function checkOnCreated( 109 id, 110 parentId, 111 index, 112 title, 113 url, 114 dateAdded, 115 type = "bookmark" 116 ) { 117 let createdData = collectedEvents.pop(); 118 browser.test.assertEq( 119 "onCreated", 120 createdData.event, 121 "onCreated was the last event received" 122 ); 123 browser.test.assertEq( 124 id, 125 createdData.id, 126 "onCreated event received the expected id" 127 ); 128 let bookmark = createdData.bookmark; 129 browser.test.assertEq( 130 id, 131 bookmark.id, 132 "onCreated event received the expected bookmark id" 133 ); 134 browser.test.assertEq( 135 parentId, 136 bookmark.parentId, 137 "onCreated event received the expected bookmark parentId" 138 ); 139 browser.test.assertEq( 140 index, 141 bookmark.index, 142 "onCreated event received the expected bookmark index" 143 ); 144 browser.test.assertEq( 145 title, 146 bookmark.title, 147 "onCreated event received the expected bookmark title" 148 ); 149 browser.test.assertEq( 150 url, 151 bookmark.url, 152 "onCreated event received the expected bookmark url" 153 ); 154 browser.test.assertEq( 155 dateAdded, 156 bookmark.dateAdded, 157 "onCreated event received the expected bookmark dateAdded" 158 ); 159 browser.test.assertEq( 160 type, 161 bookmark.type, 162 "onCreated event received the expected bookmark type" 163 ); 164 } 165 166 function checkOnChanged(id, url, title) { 167 // If both url and title are changed, then url is fired last. 168 let changedData = collectedEvents.pop(); 169 browser.test.assertEq( 170 "onChanged", 171 changedData.event, 172 "onChanged was the last event received" 173 ); 174 browser.test.assertEq( 175 id, 176 changedData.id, 177 "onChanged event received the expected id" 178 ); 179 browser.test.assertEq( 180 url, 181 changedData.info.url, 182 "onChanged event received the expected url" 183 ); 184 // title is fired first. 185 changedData = collectedEvents.pop(); 186 browser.test.assertEq( 187 "onChanged", 188 changedData.event, 189 "onChanged was the last event received" 190 ); 191 browser.test.assertEq( 192 id, 193 changedData.id, 194 "onChanged event received the expected id" 195 ); 196 browser.test.assertEq( 197 title, 198 changedData.info.title, 199 "onChanged event received the expected title" 200 ); 201 } 202 203 function checkOnMoved(id, parentId, oldParentId, index, oldIndex) { 204 let movedData = collectedEvents.pop(); 205 browser.test.assertEq( 206 "onMoved", 207 movedData.event, 208 "onMoved was the last event received" 209 ); 210 browser.test.assertEq( 211 id, 212 movedData.id, 213 "onMoved event received the expected id" 214 ); 215 let info = movedData.info; 216 browser.test.assertEq( 217 parentId, 218 info.parentId, 219 "onMoved event received the expected parentId" 220 ); 221 browser.test.assertEq( 222 oldParentId, 223 info.oldParentId, 224 "onMoved event received the expected oldParentId" 225 ); 226 browser.test.assertEq( 227 index, 228 info.index, 229 "onMoved event received the expected index" 230 ); 231 browser.test.assertEq( 232 oldIndex, 233 info.oldIndex, 234 "onMoved event received the expected oldIndex" 235 ); 236 } 237 238 function checkOnRemoved(id, parentId, index, title, url, type = "folder") { 239 let removedData = collectedEvents.pop(); 240 browser.test.assertEq( 241 "onRemoved", 242 removedData.event, 243 "onRemoved was the last event received" 244 ); 245 browser.test.assertEq( 246 id, 247 removedData.id, 248 "onRemoved event received the expected id" 249 ); 250 let info = removedData.info; 251 browser.test.assertEq( 252 parentId, 253 removedData.info.parentId, 254 "onRemoved event received the expected parentId" 255 ); 256 browser.test.assertEq( 257 index, 258 removedData.info.index, 259 "onRemoved event received the expected index" 260 ); 261 let node = info.node; 262 browser.test.assertEq( 263 id, 264 node.id, 265 "onRemoved event received the expected node id" 266 ); 267 browser.test.assertEq( 268 parentId, 269 node.parentId, 270 "onRemoved event received the expected node parentId" 271 ); 272 browser.test.assertEq( 273 index, 274 node.index, 275 "onRemoved event received the expected node index" 276 ); 277 browser.test.assertEq( 278 url, 279 node.url, 280 "onRemoved event received the expected node url" 281 ); 282 browser.test.assertEq( 283 title, 284 node.title, 285 "onRemoved event received the expected node title" 286 ); 287 browser.test.assertEq( 288 type, 289 node.type, 290 "onRemoved event received the expected node type" 291 ); 292 } 293 294 browser.bookmarks.onChanged.addListener((id, info) => { 295 collectedEvents.push({ event: "onChanged", id, info }); 296 }); 297 298 browser.bookmarks.onCreated.addListener((id, bookmark) => { 299 collectedEvents.push({ event: "onCreated", id, bookmark }); 300 }); 301 302 browser.bookmarks.onMoved.addListener((id, info) => { 303 collectedEvents.push({ event: "onMoved", id, info }); 304 }); 305 306 browser.bookmarks.onRemoved.addListener((id, info) => { 307 collectedEvents.push({ event: "onRemoved", id, info }); 308 }); 309 310 await browser.test.assertRejects( 311 browser.bookmarks.get(["not-a-bookmark-guid"]), 312 /Invalid value for property 'guid': "not-a-bookmark-guid"/, 313 "Expected error thrown when trying to get a bookmark using an invalid guid" 314 ); 315 316 await browser.test 317 .assertRejects( 318 browser.bookmarks.get([nonExistentId]), 319 /Bookmark not found/, 320 "Expected error thrown when trying to get a bookmark using a non-existent Id" 321 ) 322 .then(() => { 323 return browser.bookmarks.search({}); 324 }) 325 .then(results => { 326 initialBookmarkCount = results.length; 327 return browser.bookmarks.create({ 328 title: "test bookmark", 329 url: "http://example.org", 330 type: "bookmark", 331 }); 332 }) 333 .then(result => { 334 ourId = result.id; 335 checkOurBookmark(result); 336 browser.test.assertEq( 337 1, 338 collectedEvents.length, 339 "1 expected event received" 340 ); 341 checkOnCreated( 342 ourId, 343 bookmarkGuids.unfiledGuid, 344 0, 345 "test bookmark", 346 "http://example.org/", 347 result.dateAdded 348 ); 349 350 return browser.bookmarks.get(ourId); 351 }) 352 .then(results => { 353 browser.test.assertEq(results.length, 1); 354 checkOurBookmark(results[0]); 355 356 unsortedId = results[0].parentId; 357 return browser.bookmarks.get(unsortedId); 358 }) 359 .then(results => { 360 let folder = results[0]; 361 browser.test.assertEq(1, results.length, "1 bookmark was returned"); 362 363 browser.test.assertEq( 364 unsortedId, 365 folder.id, 366 "Folder has the expected id" 367 ); 368 browser.test.assertTrue("parentId" in folder, "Folder has a parentId"); 369 browser.test.assertTrue("index" in folder, "Folder has an index"); 370 browser.test.assertEq( 371 undefined, 372 folder.url, 373 "Folder does not have a url" 374 ); 375 browser.test.assertEq( 376 "Other Bookmarks", 377 folder.title, 378 "Folder has the expected title" 379 ); 380 browser.test.assertTrue( 381 "dateAdded" in folder, 382 "Folder has a dateAdded" 383 ); 384 browser.test.assertTrue( 385 "dateGroupModified" in folder, 386 "Folder has a dateGroupModified" 387 ); 388 browser.test.assertFalse( 389 "unmodifiable" in folder, 390 "Folder is not unmodifiable" 391 ); // TODO: Do we want to enable this? 392 browser.test.assertEq( 393 "folder", 394 folder.type, 395 "Folder has a type of folder" 396 ); 397 398 return browser.bookmarks.getChildren(unsortedId); 399 }) 400 .then(async results => { 401 browser.test.assertEq(1, results.length, "The folder has one child"); 402 checkOurBookmark(results[0]); 403 404 await browser.test.assertRejects( 405 browser.bookmarks.update(nonExistentId, { title: "new test title" }), 406 /No bookmarks found for the provided GUID/, 407 "Expected error thrown when trying to update a non-existent bookmark" 408 ); 409 return browser.bookmarks.update(ourId, { 410 title: "new test title", 411 url: "http://example.com/", 412 }); 413 }) 414 .then(async result => { 415 browser.test.assertEq( 416 "new test title", 417 result.title, 418 "Updated bookmark has the expected title" 419 ); 420 browser.test.assertEq( 421 "http://example.com/", 422 result.url, 423 "Updated bookmark has the expected URL" 424 ); 425 browser.test.assertEq( 426 ourId, 427 result.id, 428 "Updated bookmark has the expected id" 429 ); 430 browser.test.assertEq( 431 "bookmark", 432 result.type, 433 "Updated bookmark has a type of bookmark" 434 ); 435 436 browser.test.assertEq( 437 2, 438 collectedEvents.length, 439 "2 expected events received" 440 ); 441 checkOnChanged(ourId, "http://example.com/", "new test title"); 442 443 await browser.test.assertRejects( 444 browser.bookmarks.update(ourId, { url: "this is not a valid url" }), 445 /Invalid bookmark:/, 446 "Expected error thrown when trying update with an invalid url" 447 ); 448 return browser.bookmarks.getTree(); 449 }) 450 .then(results => { 451 browser.test.assertEq(1, results.length, "getTree returns one result"); 452 let bookmark = results[0].children.find( 453 bookmarkItem => bookmarkItem.id == unsortedId 454 ); 455 browser.test.assertEq( 456 "Other Bookmarks", 457 bookmark.title, 458 "Folder returned from getTree has the expected title" 459 ); 460 browser.test.assertEq( 461 "folder", 462 bookmark.type, 463 "Folder returned from getTree has the expected type" 464 ); 465 466 return browser.test.assertRejects( 467 browser.bookmarks.create({ parentId: "invalid" }), 468 error => 469 error.message.includes("Invalid bookmark") && 470 error.message.includes(`"parentGuid":"invalid"`), 471 "Expected error thrown when trying to create a bookmark with an invalid parentId" 472 ); 473 }) 474 .then(() => { 475 return browser.bookmarks.remove(ourId); 476 }) 477 .then(result => { 478 browser.test.assertEq( 479 undefined, 480 result, 481 "Removing a bookmark returns undefined" 482 ); 483 484 browser.test.assertEq( 485 1, 486 collectedEvents.length, 487 "1 expected events received" 488 ); 489 checkOnRemoved( 490 ourId, 491 bookmarkGuids.unfiledGuid, 492 0, 493 "new test title", 494 "http://example.com/", 495 "bookmark" 496 ); 497 498 return browser.test.assertRejects( 499 browser.bookmarks.get(ourId), 500 /Bookmark not found/, 501 "Expected error thrown when trying to get a removed bookmark" 502 ); 503 }) 504 .then(() => { 505 return browser.test.assertRejects( 506 browser.bookmarks.remove(nonExistentId), 507 /No bookmarks found for the provided GUID/, 508 "Expected error thrown when trying removed a non-existent bookmark" 509 ); 510 }) 511 .then(() => { 512 // test bookmarks.search 513 return Promise.all([ 514 browser.bookmarks.create({ 515 title: "Μοζιλλας", 516 url: "http://møzîllä.örg/", 517 }), 518 browser.bookmarks.create({ 519 title: "Example", 520 url: "http://example.org/", 521 }), 522 browser.bookmarks.create({ title: "Mozilla Folder", type: "folder" }), 523 browser.bookmarks.create({ title: "EFF", url: "http://eff.org/" }), 524 browser.bookmarks.create({ 525 title: "Menu Item", 526 url: "http://menu.org/", 527 parentId: bookmarkGuids.menuGuid, 528 }), 529 browser.bookmarks.create({ 530 title: "Toolbar Item", 531 url: "http://toolbar.org/", 532 parentId: bookmarkGuids.toolbarGuid, 533 }), 534 ]); 535 }) 536 .then(results => { 537 browser.test.assertEq( 538 6, 539 collectedEvents.length, 540 "6 expected events received" 541 ); 542 checkOnCreated( 543 results[5].id, 544 bookmarkGuids.toolbarGuid, 545 0, 546 "Toolbar Item", 547 "http://toolbar.org/", 548 results[5].dateAdded 549 ); 550 checkOnCreated( 551 results[4].id, 552 bookmarkGuids.menuGuid, 553 0, 554 "Menu Item", 555 "http://menu.org/", 556 results[4].dateAdded 557 ); 558 checkOnCreated( 559 results[3].id, 560 bookmarkGuids.unfiledGuid, 561 0, 562 "EFF", 563 "http://eff.org/", 564 results[3].dateAdded 565 ); 566 checkOnCreated( 567 results[2].id, 568 bookmarkGuids.unfiledGuid, 569 0, 570 "Mozilla Folder", 571 undefined, 572 results[2].dateAdded, 573 "folder" 574 ); 575 checkOnCreated( 576 results[1].id, 577 bookmarkGuids.unfiledGuid, 578 0, 579 "Example", 580 "http://example.org/", 581 results[1].dateAdded 582 ); 583 checkOnCreated( 584 results[0].id, 585 bookmarkGuids.unfiledGuid, 586 0, 587 "Μοζιλλας", 588 "http://xn--mzll-ooa1dud.xn--rg-eka/", 589 results[0].dateAdded 590 ); 591 592 for (let result of results) { 593 if (result.title !== "Mozilla Folder") { 594 createdBookmarks.add(result.id); 595 } 596 } 597 let folderResult = results[2]; 598 createdFolderId = folderResult.id; 599 return Promise.all([ 600 browser.bookmarks.create({ 601 title: "Mozilla", 602 url: "http://allizom.org/", 603 parentId: createdFolderId, 604 }), 605 browser.bookmarks.create({ 606 parentId: createdFolderId, 607 type: "separator", 608 }), 609 browser.bookmarks.create({ 610 title: "Mozilla Corporation", 611 url: "http://allizom.com/", 612 parentId: createdFolderId, 613 }), 614 browser.bookmarks.create({ 615 title: "Firefox", 616 url: "http://allizom.org/firefox/", 617 parentId: createdFolderId, 618 }), 619 ]) 620 .then(newBookmarks => { 621 browser.test.assertEq( 622 4, 623 collectedEvents.length, 624 "4 expected events received" 625 ); 626 checkOnCreated( 627 newBookmarks[3].id, 628 createdFolderId, 629 0, 630 "Firefox", 631 "http://allizom.org/firefox/", 632 newBookmarks[3].dateAdded 633 ); 634 checkOnCreated( 635 newBookmarks[2].id, 636 createdFolderId, 637 0, 638 "Mozilla Corporation", 639 "http://allizom.com/", 640 newBookmarks[2].dateAdded 641 ); 642 checkOnCreated( 643 newBookmarks[1].id, 644 createdFolderId, 645 0, 646 "", 647 "data:", 648 newBookmarks[1].dateAdded, 649 "separator" 650 ); 651 checkOnCreated( 652 newBookmarks[0].id, 653 createdFolderId, 654 0, 655 "Mozilla", 656 "http://allizom.org/", 657 newBookmarks[0].dateAdded 658 ); 659 660 return browser.bookmarks.create({ 661 title: "About Mozilla", 662 url: "http://allizom.org/about/", 663 parentId: createdFolderId, 664 index: 1, 665 }); 666 }) 667 .then(result => { 668 browser.test.assertEq( 669 1, 670 collectedEvents.length, 671 "1 expected events received" 672 ); 673 checkOnCreated( 674 result.id, 675 createdFolderId, 676 1, 677 "About Mozilla", 678 "http://allizom.org/about/", 679 result.dateAdded 680 ); 681 682 // returns all items on empty object 683 return browser.bookmarks.search({}); 684 }) 685 .then(async bookmarksSearchResults => { 686 browser.test.assertTrue( 687 bookmarksSearchResults.length >= 10, 688 "At least as many bookmarks as added were returned by search({})" 689 ); 690 691 await browser.test.assertRejects( 692 browser.bookmarks.remove(createdFolderId), 693 /Cannot remove a non-empty folder/, 694 "Expected error thrown when trying to remove a non-empty folder" 695 ); 696 return browser.bookmarks.getSubTree(createdFolderId); 697 }); 698 }) 699 .then(results => { 700 browser.test.assertEq( 701 1, 702 results.length, 703 "Expected number of nodes returned by getSubTree" 704 ); 705 browser.test.assertEq( 706 "Mozilla Folder", 707 results[0].title, 708 "Folder has the expected title" 709 ); 710 browser.test.assertEq( 711 bookmarkGuids.unfiledGuid, 712 results[0].parentId, 713 "Folder has the expected parentId" 714 ); 715 browser.test.assertEq( 716 "folder", 717 results[0].type, 718 "Folder has the expected type" 719 ); 720 let children = results[0].children; 721 browser.test.assertEq( 722 5, 723 children.length, 724 "Expected number of bookmarks returned by getSubTree" 725 ); 726 browser.test.assertEq( 727 "Firefox", 728 children[0].title, 729 "Bookmark has the expected title" 730 ); 731 browser.test.assertEq( 732 "bookmark", 733 children[0].type, 734 "Bookmark has the expected type" 735 ); 736 browser.test.assertEq( 737 "About Mozilla", 738 children[1].title, 739 "Bookmark has the expected title" 740 ); 741 browser.test.assertEq( 742 "bookmark", 743 children[1].type, 744 "Bookmark has the expected type" 745 ); 746 browser.test.assertEq( 747 1, 748 children[1].index, 749 "Bookmark has the expected index" 750 ); 751 browser.test.assertEq( 752 "Mozilla Corporation", 753 children[2].title, 754 "Bookmark has the expected title" 755 ); 756 browser.test.assertEq( 757 "", 758 children[3].title, 759 "Separator has the expected title" 760 ); 761 browser.test.assertEq( 762 "data:", 763 children[3].url, 764 "Separator has the expected url" 765 ); 766 browser.test.assertEq( 767 "separator", 768 children[3].type, 769 "Separator has the expected type" 770 ); 771 browser.test.assertEq( 772 "Mozilla", 773 children[4].title, 774 "Bookmark has the expected title" 775 ); 776 777 // throws an error for invalid query objects 778 browser.test.assertThrows( 779 () => browser.bookmarks.search(), 780 /Incorrect argument types for bookmarks.search/, 781 "Expected error thrown when trying to search with no arguments" 782 ); 783 784 browser.test.assertThrows( 785 () => browser.bookmarks.search(null), 786 /Incorrect argument types for bookmarks.search/, 787 "Expected error thrown when trying to search with null as an argument" 788 ); 789 790 browser.test.assertThrows( 791 () => browser.bookmarks.search(() => {}), 792 /Incorrect argument types for bookmarks.search/, 793 "Expected error thrown when trying to search with a function as an argument" 794 ); 795 796 browser.test.assertThrows( 797 () => browser.bookmarks.search({ banana: "banana" }), 798 /an unexpected "banana" property/, 799 "Expected error thrown when trying to search with a banana as an argument" 800 ); 801 802 browser.test.assertThrows( 803 () => browser.bookmarks.search({ url: "spider-man vs. batman" }), 804 /must match the format "url"/, 805 "Expected error thrown when trying to search with a illegally formatted URL" 806 ); 807 // queries the full url 808 return browser.bookmarks.search("http://example.org/"); 809 }) 810 .then(results => { 811 browser.test.assertEq( 812 1, 813 results.length, 814 "Expected number of results returned for url search" 815 ); 816 checkBookmark( 817 { title: "Example", url: "http://example.org/", index: 2 }, 818 results[0] 819 ); 820 821 // queries a partial url 822 return browser.bookmarks.search("example.org"); 823 }) 824 .then(results => { 825 browser.test.assertEq( 826 1, 827 results.length, 828 "Expected number of results returned for url search" 829 ); 830 checkBookmark( 831 { title: "Example", url: "http://example.org/", index: 2 }, 832 results[0] 833 ); 834 835 // queries the title 836 return browser.bookmarks.search("EFF"); 837 }) 838 .then(results => { 839 browser.test.assertEq( 840 1, 841 results.length, 842 "Expected number of results returned for title search" 843 ); 844 checkBookmark( 845 { 846 title: "EFF", 847 url: "http://eff.org/", 848 index: 0, 849 parentId: bookmarkGuids.unfiledGuid, 850 }, 851 results[0] 852 ); 853 854 // finds menu items 855 return browser.bookmarks.search("Menu Item"); 856 }) 857 .then(results => { 858 browser.test.assertEq( 859 1, 860 results.length, 861 "Expected number of results returned for menu item search" 862 ); 863 checkBookmark( 864 { 865 title: "Menu Item", 866 url: "http://menu.org/", 867 index: 0, 868 parentId: bookmarkGuids.menuGuid, 869 }, 870 results[0] 871 ); 872 873 // finds toolbar items 874 return browser.bookmarks.search("Toolbar Item"); 875 }) 876 .then(results => { 877 browser.test.assertEq( 878 1, 879 results.length, 880 "Expected number of results returned for toolbar item search" 881 ); 882 checkBookmark( 883 { 884 title: "Toolbar Item", 885 url: "http://toolbar.org/", 886 index: 0, 887 parentId: bookmarkGuids.toolbarGuid, 888 }, 889 results[0] 890 ); 891 892 // finds folders 893 return browser.bookmarks.search("Mozilla Folder"); 894 }) 895 .then(results => { 896 browser.test.assertEq( 897 1, 898 results.length, 899 "Expected number of folders returned" 900 ); 901 browser.test.assertEq( 902 "Mozilla Folder", 903 results[0].title, 904 "Folder has the expected title" 905 ); 906 browser.test.assertEq( 907 "folder", 908 results[0].type, 909 "Folder has the expected type" 910 ); 911 912 // is case-insensitive 913 return browser.bookmarks.search("corporation"); 914 }) 915 .then(results => { 916 browser.test.assertEq( 917 1, 918 results.length, 919 "Expected number of results returnedfor case-insensitive search" 920 ); 921 browser.test.assertEq( 922 "Mozilla Corporation", 923 results[0].title, 924 "Bookmark has the expected title" 925 ); 926 927 // is case-insensitive for non-ascii 928 return browser.bookmarks.search("ΜοΖΙΛΛΑς"); 929 }) 930 .then(results => { 931 browser.test.assertEq( 932 1, 933 results.length, 934 "Expected number of results returned for non-ascii search" 935 ); 936 browser.test.assertEq( 937 "Μοζιλλας", 938 results[0].title, 939 "Bookmark has the expected title" 940 ); 941 942 // returns multiple results 943 return browser.bookmarks.search("allizom"); 944 }) 945 .then(results => { 946 browser.test.assertEq( 947 4, 948 results.length, 949 "Expected number of multiple results returned" 950 ); 951 browser.test.assertEq( 952 "Mozilla", 953 results[0].title, 954 "Bookmark has the expected title" 955 ); 956 browser.test.assertEq( 957 "Mozilla Corporation", 958 results[1].title, 959 "Bookmark has the expected title" 960 ); 961 browser.test.assertEq( 962 "Firefox", 963 results[2].title, 964 "Bookmark has the expected title" 965 ); 966 browser.test.assertEq( 967 "About Mozilla", 968 results[3].title, 969 "Bookmark has the expected title" 970 ); 971 972 // accepts a url field 973 return browser.bookmarks.search({ url: "http://allizom.com/" }); 974 }) 975 .then(results => { 976 browser.test.assertEq( 977 1, 978 results.length, 979 "Expected number of results returned for url field" 980 ); 981 checkBookmark( 982 { 983 title: "Mozilla Corporation", 984 url: "http://allizom.com/", 985 index: 2, 986 }, 987 results[0] 988 ); 989 990 // normalizes urls 991 return browser.bookmarks.search({ url: "http://allizom.com" }); 992 }) 993 .then(results => { 994 browser.test.assertEq( 995 results.length, 996 1, 997 "Expected number of results returned for normalized url field" 998 ); 999 checkBookmark( 1000 { 1001 title: "Mozilla Corporation", 1002 url: "http://allizom.com/", 1003 index: 2, 1004 }, 1005 results[0] 1006 ); 1007 1008 // normalizes urls even more 1009 return browser.bookmarks.search({ url: "http:allizom.com" }); 1010 }) 1011 .then(results => { 1012 browser.test.assertEq( 1013 results.length, 1014 1, 1015 "Expected number of results returned for normalized url field" 1016 ); 1017 checkBookmark( 1018 { 1019 title: "Mozilla Corporation", 1020 url: "http://allizom.com/", 1021 index: 2, 1022 }, 1023 results[0] 1024 ); 1025 1026 // accepts a title field 1027 return browser.bookmarks.search({ title: "Mozilla" }); 1028 }) 1029 .then(results => { 1030 browser.test.assertEq( 1031 results.length, 1032 1, 1033 "Expected number of results returned for title field" 1034 ); 1035 checkBookmark( 1036 { title: "Mozilla", url: "http://allizom.org/", index: 4 }, 1037 results[0] 1038 ); 1039 1040 // can combine title and query 1041 return browser.bookmarks.search({ title: "Mozilla", query: "allizom" }); 1042 }) 1043 .then(results => { 1044 browser.test.assertEq( 1045 1, 1046 results.length, 1047 "Expected number of results returned for title and query fields" 1048 ); 1049 checkBookmark( 1050 { title: "Mozilla", url: "http://allizom.org/", index: 4 }, 1051 results[0] 1052 ); 1053 1054 // uses AND conditions 1055 return browser.bookmarks.search({ title: "EFF", query: "allizom" }); 1056 }) 1057 .then(results => { 1058 browser.test.assertEq( 1059 0, 1060 results.length, 1061 "Expected number of results returned for non-matching title and query fields" 1062 ); 1063 1064 // returns an empty array on item not found 1065 return browser.bookmarks.search("microsoft"); 1066 }) 1067 .then(results => { 1068 browser.test.assertEq( 1069 0, 1070 results.length, 1071 "Expected number of results returned for non-matching search" 1072 ); 1073 1074 browser.test.assertThrows( 1075 () => browser.bookmarks.getRecent(""), 1076 /Incorrect argument types for bookmarks.getRecent/, 1077 "Expected error thrown when calling getRecent with an empty string" 1078 ); 1079 }) 1080 .then(() => { 1081 browser.test.assertThrows( 1082 () => browser.bookmarks.getRecent(1.234), 1083 /Incorrect argument types for bookmarks.getRecent/, 1084 "Expected error thrown when calling getRecent with a decimal number" 1085 ); 1086 }) 1087 .then(() => { 1088 return Promise.all([ 1089 browser.bookmarks.search("corporation"), 1090 browser.bookmarks.getChildren(bookmarkGuids.menuGuid), 1091 ]); 1092 }) 1093 .then(results => { 1094 let corporationBookmark = results[0][0]; 1095 let childCount = results[1].length; 1096 1097 browser.test.assertEq( 1098 2, 1099 corporationBookmark.index, 1100 "Bookmark has the expected index" 1101 ); 1102 1103 return browser.bookmarks 1104 .move(corporationBookmark.id, { index: 0 }) 1105 .then(result => { 1106 browser.test.assertEq( 1107 0, 1108 result.index, 1109 "Bookmark has the expected index" 1110 ); 1111 1112 browser.test.assertEq( 1113 1, 1114 collectedEvents.length, 1115 "1 expected events received" 1116 ); 1117 checkOnMoved( 1118 corporationBookmark.id, 1119 createdFolderId, 1120 createdFolderId, 1121 0, 1122 2 1123 ); 1124 1125 return browser.bookmarks.move(corporationBookmark.id, { 1126 parentId: bookmarkGuids.menuGuid, 1127 }); 1128 }) 1129 .then(result => { 1130 browser.test.assertEq( 1131 bookmarkGuids.menuGuid, 1132 result.parentId, 1133 "Bookmark has the expected parent" 1134 ); 1135 browser.test.assertEq( 1136 childCount, 1137 result.index, 1138 "Bookmark has the expected index" 1139 ); 1140 1141 browser.test.assertEq( 1142 1, 1143 collectedEvents.length, 1144 "1 expected events received" 1145 ); 1146 checkOnMoved( 1147 corporationBookmark.id, 1148 bookmarkGuids.menuGuid, 1149 createdFolderId, 1150 1, 1151 0 1152 ); 1153 1154 return browser.bookmarks.move(corporationBookmark.id, { index: 0 }); 1155 }) 1156 .then(result => { 1157 browser.test.assertEq( 1158 bookmarkGuids.menuGuid, 1159 result.parentId, 1160 "Bookmark has the expected parent" 1161 ); 1162 browser.test.assertEq( 1163 0, 1164 result.index, 1165 "Bookmark has the expected index" 1166 ); 1167 1168 browser.test.assertEq( 1169 1, 1170 collectedEvents.length, 1171 "1 expected events received" 1172 ); 1173 checkOnMoved( 1174 corporationBookmark.id, 1175 bookmarkGuids.menuGuid, 1176 bookmarkGuids.menuGuid, 1177 0, 1178 1 1179 ); 1180 1181 return browser.bookmarks.move(corporationBookmark.id, { 1182 parentId: bookmarkGuids.toolbarGuid, 1183 index: 1, 1184 }); 1185 }) 1186 .then(result => { 1187 browser.test.assertEq( 1188 bookmarkGuids.toolbarGuid, 1189 result.parentId, 1190 "Bookmark has the expected parent" 1191 ); 1192 browser.test.assertEq( 1193 1, 1194 result.index, 1195 "Bookmark has the expected index" 1196 ); 1197 1198 browser.test.assertEq( 1199 1, 1200 collectedEvents.length, 1201 "1 expected events received" 1202 ); 1203 checkOnMoved( 1204 corporationBookmark.id, 1205 bookmarkGuids.toolbarGuid, 1206 bookmarkGuids.menuGuid, 1207 1, 1208 0 1209 ); 1210 1211 createdBookmarks.add(corporationBookmark.id); 1212 }); 1213 }) 1214 .then(() => { 1215 return browser.bookmarks.getRecent(4); 1216 }) 1217 .then(results => { 1218 browser.test.assertEq( 1219 4, 1220 results.length, 1221 "Expected number of results returned by getRecent" 1222 ); 1223 let prevDate = results[0].dateAdded; 1224 for (let bookmark of results) { 1225 browser.test.assertTrue( 1226 bookmark.dateAdded <= prevDate, 1227 "The recent bookmarks are sorted by dateAdded" 1228 ); 1229 prevDate = bookmark.dateAdded; 1230 } 1231 let bookmarksByTitle = results.sort((a, b) => { 1232 return a.title.localeCompare(b.title); 1233 }); 1234 browser.test.assertEq( 1235 "About Mozilla", 1236 bookmarksByTitle[0].title, 1237 "Bookmark has the expected title" 1238 ); 1239 browser.test.assertEq( 1240 "Firefox", 1241 bookmarksByTitle[1].title, 1242 "Bookmark has the expected title" 1243 ); 1244 browser.test.assertEq( 1245 "Mozilla", 1246 bookmarksByTitle[2].title, 1247 "Bookmark has the expected title" 1248 ); 1249 browser.test.assertEq( 1250 "Mozilla Corporation", 1251 bookmarksByTitle[3].title, 1252 "Bookmark has the expected title" 1253 ); 1254 1255 return browser.bookmarks.search({}); 1256 }) 1257 .then(results => { 1258 let startBookmarkCount = results.length; 1259 1260 return browser.bookmarks 1261 .search({ title: "Mozilla Folder" }) 1262 .then(result => { 1263 return browser.bookmarks.removeTree(result[0].id); 1264 }) 1265 .then(() => { 1266 browser.test.assertEq( 1267 1, 1268 collectedEvents.length, 1269 "1 expected events received" 1270 ); 1271 checkOnRemoved( 1272 createdFolderId, 1273 bookmarkGuids.unfiledGuid, 1274 1, 1275 "Mozilla Folder" 1276 ); 1277 1278 return browser.bookmarks.search({}).then(searchResults => { 1279 browser.test.assertEq( 1280 startBookmarkCount - 5, 1281 searchResults.length, 1282 "Expected number of results returned after removeTree" 1283 ); 1284 }); 1285 }); 1286 }) 1287 .then(() => { 1288 return browser.bookmarks.create({ title: "Empty Folder" }); 1289 }) 1290 .then(result => { 1291 createdFolderId = result.id; 1292 1293 browser.test.assertEq( 1294 1, 1295 collectedEvents.length, 1296 "1 expected events received" 1297 ); 1298 checkOnCreated( 1299 createdFolderId, 1300 bookmarkGuids.unfiledGuid, 1301 3, 1302 "Empty Folder", 1303 undefined, 1304 result.dateAdded, 1305 "folder" 1306 ); 1307 1308 browser.test.assertEq( 1309 "Empty Folder", 1310 result.title, 1311 "Folder has the expected title" 1312 ); 1313 browser.test.assertEq( 1314 "folder", 1315 result.type, 1316 "Folder has the expected type" 1317 ); 1318 1319 return browser.bookmarks.create({ 1320 parentId: createdFolderId, 1321 type: "separator", 1322 }); 1323 }) 1324 .then(result => { 1325 createdSeparatorId = result.id; 1326 browser.test.assertEq( 1327 1, 1328 collectedEvents.length, 1329 "1 expected events received" 1330 ); 1331 checkOnCreated( 1332 createdSeparatorId, 1333 createdFolderId, 1334 0, 1335 "", 1336 "data:", 1337 result.dateAdded, 1338 "separator" 1339 ); 1340 return browser.bookmarks.remove(createdSeparatorId); 1341 }) 1342 .then(() => { 1343 browser.test.assertEq( 1344 1, 1345 collectedEvents.length, 1346 "1 expected events received" 1347 ); 1348 checkOnRemoved( 1349 createdSeparatorId, 1350 createdFolderId, 1351 0, 1352 "", 1353 "data:", 1354 "separator" 1355 ); 1356 1357 return browser.bookmarks.remove(createdFolderId); 1358 }) 1359 .then(() => { 1360 browser.test.assertEq( 1361 1, 1362 collectedEvents.length, 1363 "1 expected events received" 1364 ); 1365 checkOnRemoved( 1366 createdFolderId, 1367 bookmarkGuids.unfiledGuid, 1368 3, 1369 "Empty Folder" 1370 ); 1371 1372 return browser.test.assertRejects( 1373 browser.bookmarks.get(createdFolderId), 1374 /Bookmark not found/, 1375 "Expected error thrown when trying to get a removed folder" 1376 ); 1377 }) 1378 .then(() => { 1379 return browser.test.assertRejects( 1380 browser.bookmarks.getChildren(nonExistentId), 1381 /root is null/, 1382 "Expected error thrown when trying to getChildren for a non-existent folder" 1383 ); 1384 }) 1385 .then(() => { 1386 return browser.test.assertRejects( 1387 browser.bookmarks.move(nonExistentId, {}), 1388 /No bookmarks found for the provided GUID/, 1389 "Expected error thrown when calling move with a non-existent bookmark" 1390 ); 1391 }) 1392 .then(() => { 1393 return browser.test.assertRejects( 1394 browser.bookmarks.create({ 1395 title: "test root folder", 1396 parentId: bookmarkGuids.rootGuid, 1397 }), 1398 "The bookmark root cannot be modified", 1399 "Expected error thrown when creating bookmark folder at the root" 1400 ); 1401 }) 1402 .then(() => { 1403 return browser.test.assertRejects( 1404 browser.bookmarks.update(bookmarkGuids.rootGuid, { 1405 title: "test update title", 1406 }), 1407 "The bookmark root cannot be modified", 1408 "Expected error thrown when updating root" 1409 ); 1410 }) 1411 .then(() => { 1412 return browser.test.assertRejects( 1413 browser.bookmarks.remove(bookmarkGuids.rootGuid), 1414 "The bookmark root cannot be modified", 1415 "Expected error thrown when removing root" 1416 ); 1417 }) 1418 .then(() => { 1419 return browser.test.assertRejects( 1420 browser.bookmarks.removeTree(bookmarkGuids.rootGuid), 1421 "The bookmark root cannot be modified", 1422 "Expected error thrown when removing root tree" 1423 ); 1424 }) 1425 .then(() => { 1426 return browser.bookmarks.create({ title: "Empty Folder" }); 1427 }) 1428 .then(async result => { 1429 createdFolderId = result.id; 1430 1431 browser.test.assertEq( 1432 1, 1433 collectedEvents.length, 1434 "1 expected events received" 1435 ); 1436 checkOnCreated( 1437 createdFolderId, 1438 bookmarkGuids.unfiledGuid, 1439 3, 1440 "Empty Folder", 1441 undefined, 1442 result.dateAdded, 1443 "folder" 1444 ); 1445 1446 await browser.test.assertRejects( 1447 browser.bookmarks.move(createdFolderId, { 1448 parentId: bookmarkGuids.rootGuid, 1449 }), 1450 "The bookmark root cannot be modified", 1451 "Expected error thrown when moving bookmark folder to the root" 1452 ); 1453 1454 return browser.bookmarks.remove(createdFolderId); 1455 }) 1456 .then(() => { 1457 browser.test.assertEq( 1458 1, 1459 collectedEvents.length, 1460 "1 expected events received" 1461 ); 1462 checkOnRemoved( 1463 createdFolderId, 1464 bookmarkGuids.unfiledGuid, 1465 3, 1466 "Empty Folder", 1467 undefined, 1468 "folder" 1469 ); 1470 1471 return browser.test.assertRejects( 1472 browser.bookmarks.get(createdFolderId), 1473 "Bookmark not found", 1474 "Expected error thrown when trying to get a removed folder" 1475 ); 1476 }) 1477 .then(() => { 1478 return browser.test.assertRejects( 1479 browser.bookmarks.move(bookmarkGuids.rootGuid, { 1480 parentId: bookmarkGuids.unfiledGuid, 1481 }), 1482 "The bookmark root cannot be modified", 1483 "Expected error thrown when moving root" 1484 ); 1485 }) 1486 .then(() => { 1487 // remove all created bookmarks 1488 let promises = Array.from(createdBookmarks, guid => 1489 browser.bookmarks.remove(guid) 1490 ); 1491 return Promise.all(promises); 1492 }) 1493 .then(() => { 1494 browser.test.assertEq( 1495 createdBookmarks.size, 1496 collectedEvents.length, 1497 "expected number of events received" 1498 ); 1499 1500 return browser.bookmarks.search({}); 1501 }) 1502 .then(results => { 1503 browser.test.assertEq( 1504 initialBookmarkCount, 1505 results.length, 1506 "All created bookmarks have been removed" 1507 ); 1508 1509 return browser.test.notifyPass("bookmarks"); 1510 }) 1511 .catch(error => { 1512 browser.test.fail(`Error: ${String(error)} :: ${error.stack}`); 1513 browser.test.notifyFail("bookmarks"); 1514 }); 1515 } 1516 1517 let extension = ExtensionTestUtils.loadExtension({ 1518 background, 1519 manifest: { 1520 permissions: ["bookmarks"], 1521 }, 1522 }); 1523 1524 await extension.startup(); 1525 await extension.awaitFinish("bookmarks"); 1526 await extension.unload(); 1527 }); 1528 1529 add_task(async function test_get_recent_with_tag_and_query() { 1530 function background() { 1531 browser.bookmarks.getRecent(100).then(bookmarks => { 1532 browser.test.sendMessage("bookmarks", bookmarks); 1533 }); 1534 } 1535 1536 let extension = ExtensionTestUtils.loadExtension({ 1537 background, 1538 manifest: { 1539 permissions: ["bookmarks"], 1540 }, 1541 }); 1542 1543 // Start with an empty bookmarks database. 1544 await PlacesUtils.bookmarks.eraseEverything(); 1545 1546 let createdBookmarks = []; 1547 for (let i = 0; i < 3; i++) { 1548 let bookmark = { 1549 type: PlacesUtils.bookmarks.TYPE_BOOKMARK, 1550 url: `http://example.com/${i}`, 1551 title: `My bookmark ${i}`, 1552 parentGuid: PlacesUtils.bookmarks.unfiledGuid, 1553 }; 1554 createdBookmarks.unshift(bookmark); 1555 await PlacesUtils.bookmarks.insert(bookmark); 1556 } 1557 1558 // Add a tag to the most recent url to prove it doesn't get returned. 1559 PlacesUtils.tagging.tagURI(NetUtil.newURI("http://example.com/${i}"), [ 1560 "Test Tag", 1561 ]); 1562 1563 // Add a query bookmark. 1564 let queryURL = `place:parent=${PlacesUtils.bookmarks.menuGuid}&queryType=1`; 1565 await PlacesUtils.bookmarks.insert({ 1566 parentGuid: PlacesUtils.bookmarks.unfiledGuid, 1567 url: queryURL, 1568 title: "a test query", 1569 }); 1570 1571 await extension.startup(); 1572 let receivedBookmarks = await extension.awaitMessage("bookmarks"); 1573 1574 equal( 1575 receivedBookmarks.length, 1576 3, 1577 "The expected number of bookmarks was returned." 1578 ); 1579 for (let i = 0; i < 3; i++) { 1580 let actual = receivedBookmarks[i]; 1581 let expected = createdBookmarks[i]; 1582 equal(actual.url, expected.url, "Bookmark has the expected url."); 1583 equal(actual.title, expected.title, "Bookmark has the expected title."); 1584 equal( 1585 actual.parentId, 1586 expected.parentGuid, 1587 "Bookmark has the expected parentId." 1588 ); 1589 } 1590 1591 await extension.unload(); 1592 }); 1593 1594 add_task(async function test_tree_with_empty_folder() { 1595 async function background() { 1596 await browser.bookmarks.create({ title: "Empty Folder" }); 1597 let nonEmptyFolder = await browser.bookmarks.create({ 1598 title: "Non-Empty Folder", 1599 }); 1600 await browser.bookmarks.create({ 1601 title: "A bookmark", 1602 url: "http://example.com", 1603 parentId: nonEmptyFolder.id, 1604 }); 1605 1606 let tree = await browser.bookmarks.getSubTree(nonEmptyFolder.parentId); 1607 browser.test.assertEq( 1608 0, 1609 tree[0].children[0].children.length, 1610 "The empty folder returns an empty array for children." 1611 ); 1612 browser.test.assertEq( 1613 1, 1614 tree[0].children[1].children.length, 1615 "The non-empty folder returns a single item array for children." 1616 ); 1617 1618 let children = await browser.bookmarks.getChildren(nonEmptyFolder.parentId); 1619 // getChildren should only return immediate children. This is not tested in the 1620 // monster test above. 1621 for (let child of children) { 1622 browser.test.assertEq( 1623 undefined, 1624 child.children, 1625 "Child from getChildren does not contain any children." 1626 ); 1627 } 1628 1629 browser.test.sendMessage("done"); 1630 } 1631 1632 let extension = ExtensionTestUtils.loadExtension({ 1633 background, 1634 manifest: { 1635 permissions: ["bookmarks"], 1636 }, 1637 }); 1638 1639 // Start with an empty bookmarks database. 1640 await PlacesUtils.bookmarks.eraseEverything(); 1641 1642 await extension.startup(); 1643 await extension.awaitMessage("done"); 1644 1645 await extension.unload(); 1646 }); 1647 1648 add_task( 1649 { 1650 pref_set: [["extensions.eventPages.enabled", true]], 1651 }, 1652 async function test_bookmarks_event_page() { 1653 await AddonTestUtils.promiseStartupManager(); 1654 let extension = ExtensionTestUtils.loadExtension({ 1655 useAddonManager: "permanent", 1656 manifest: { 1657 browser_specific_settings: { gecko: { id: "eventpage@bookmarks" } }, 1658 permissions: ["bookmarks"], 1659 background: { persistent: false }, 1660 }, 1661 background() { 1662 browser.bookmarks.onCreated.addListener(() => { 1663 browser.test.sendMessage("onCreated"); 1664 }); 1665 browser.bookmarks.onRemoved.addListener(() => { 1666 browser.test.sendMessage("onRemoved"); 1667 }); 1668 browser.bookmarks.onChanged.addListener(() => {}); 1669 browser.bookmarks.onMoved.addListener(() => {}); 1670 browser.test.sendMessage("ready"); 1671 }, 1672 }); 1673 1674 const EVENTS = ["onCreated", "onRemoved", "onChanged", "onMoved"]; 1675 await PlacesUtils.bookmarks.eraseEverything(); 1676 1677 await extension.startup(); 1678 await extension.awaitMessage("ready"); 1679 for (let event of EVENTS) { 1680 assertPersistentListeners(extension, "bookmarks", event, { 1681 primed: false, 1682 }); 1683 } 1684 1685 // test events waken background 1686 await extension.terminateBackground(); 1687 for (let event of EVENTS) { 1688 assertPersistentListeners(extension, "bookmarks", event, { 1689 primed: true, 1690 }); 1691 } 1692 1693 let bookmark = { 1694 type: PlacesUtils.bookmarks.TYPE_BOOKMARK, 1695 url: `http://example.com/12345`, 1696 title: `My bookmark 12345`, 1697 parentGuid: PlacesUtils.bookmarks.unfiledGuid, 1698 }; 1699 await PlacesUtils.bookmarks.insert(bookmark); 1700 1701 await extension.awaitMessage("ready"); 1702 await extension.awaitMessage("onCreated"); 1703 for (let event of EVENTS) { 1704 assertPersistentListeners(extension, "bookmarks", event, { 1705 primed: false, 1706 }); 1707 } 1708 1709 await AddonTestUtils.promiseRestartManager(); 1710 await extension.awaitStartup(); 1711 1712 for (let event of EVENTS) { 1713 assertPersistentListeners(extension, "bookmarks", event, { 1714 primed: true, 1715 }); 1716 } 1717 1718 await PlacesUtils.bookmarks.eraseEverything(); 1719 await extension.awaitMessage("ready"); 1720 await extension.awaitMessage("onRemoved"); 1721 1722 await extension.unload(); 1723 await AddonTestUtils.promiseShutdownManager(); 1724 } 1725 );