test_bookmark_store.js (13620B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 const { Bookmark, BookmarkFolder, BookmarkQuery, PlacesItem } = 5 ChromeUtils.importESModule( 6 "resource://services-sync/engines/bookmarks.sys.mjs" 7 ); 8 // `Service` is used as a global in head_helpers.js. 9 // eslint-disable-next-line no-unused-vars 10 const { Service } = ChromeUtils.importESModule( 11 "resource://services-sync/service.sys.mjs" 12 ); 13 14 const BookmarksToolbarTitle = "toolbar"; 15 16 // apply some test records without going via a test server. 17 async function apply_records(engine, records) { 18 for (record of records) { 19 await engine._store.applyIncoming(record); 20 } 21 await engine._apply(); 22 } 23 24 add_bookmark_test(async function test_ignore_specials(engine) { 25 _("Ensure that we can't delete bookmark roots."); 26 let store = engine._store; 27 28 // Belt... 29 let record = new BookmarkFolder("bookmarks", "toolbar", "folder"); 30 record.deleted = true; 31 Assert.notEqual( 32 null, 33 await PlacesTestUtils.promiseItemId(PlacesUtils.bookmarks.toolbarGuid) 34 ); 35 36 await apply_records(engine, [record]); 37 38 // Ensure that the toolbar exists. 39 Assert.notEqual( 40 null, 41 await PlacesTestUtils.promiseItemId(PlacesUtils.bookmarks.toolbarGuid) 42 ); 43 44 await apply_records(engine, [record]); 45 46 Assert.notEqual( 47 null, 48 await PlacesTestUtils.promiseItemId(PlacesUtils.bookmarks.toolbarGuid) 49 ); 50 await store.wipe(); 51 }); 52 53 add_bookmark_test(async function test_bookmark_create(engine) { 54 let store = engine._store; 55 56 try { 57 _("Ensure the record isn't present yet."); 58 let item = await PlacesUtils.bookmarks.fetch({ 59 url: "http://getfirefox.com/", 60 }); 61 Assert.equal(null, item); 62 63 _("Let's create a new record."); 64 let fxrecord = new Bookmark("bookmarks", "get-firefox1"); 65 fxrecord.bmkUri = "http://getfirefox.com/"; 66 fxrecord.title = "Get Firefox!"; 67 fxrecord.tags = ["firefox", "awesome", "browser"]; 68 fxrecord.keyword = "awesome"; 69 fxrecord.parentName = BookmarksToolbarTitle; 70 fxrecord.parentid = "toolbar"; 71 await apply_records(engine, [fxrecord]); 72 73 _("Verify it has been created correctly."); 74 item = await PlacesUtils.bookmarks.fetch(fxrecord.id); 75 Assert.equal(item.type, PlacesUtils.bookmarks.TYPE_BOOKMARK); 76 Assert.equal(item.url.href, "http://getfirefox.com/"); 77 Assert.equal(item.title, fxrecord.title); 78 Assert.equal(item.parentGuid, PlacesUtils.bookmarks.toolbarGuid); 79 let keyword = await PlacesUtils.keywords.fetch(fxrecord.keyword); 80 Assert.equal(keyword.url.href, "http://getfirefox.com/"); 81 82 _( 83 "Have the store create a new record object. Verify that it has the same data." 84 ); 85 let newrecord = await store.createRecord(fxrecord.id); 86 Assert.ok(newrecord instanceof Bookmark); 87 for (let property of [ 88 "type", 89 "bmkUri", 90 "title", 91 "keyword", 92 "parentName", 93 "parentid", 94 ]) { 95 Assert.equal(newrecord[property], fxrecord[property]); 96 } 97 Assert.ok(Utils.deepEquals(newrecord.tags.sort(), fxrecord.tags.sort())); 98 99 _("The calculated sort index is based on frecency data."); 100 Assert.greaterOrEqual(newrecord.sortindex, 150); 101 102 _("Create a record with some values missing."); 103 let tbrecord = new Bookmark("bookmarks", "thunderbird1"); 104 tbrecord.bmkUri = "http://getthunderbird.com/"; 105 tbrecord.parentName = BookmarksToolbarTitle; 106 tbrecord.parentid = "toolbar"; 107 await apply_records(engine, [tbrecord]); 108 109 _("Verify it has been created correctly."); 110 item = await PlacesUtils.bookmarks.fetch(tbrecord.id); 111 Assert.equal(item.type, PlacesUtils.bookmarks.TYPE_BOOKMARK); 112 Assert.equal(item.url.href, "http://getthunderbird.com/"); 113 Assert.equal(item.title, ""); 114 Assert.equal(item.parentGuid, PlacesUtils.bookmarks.toolbarGuid); 115 keyword = await PlacesUtils.keywords.fetch({ 116 url: "http://getthunderbird.com/", 117 }); 118 Assert.equal(null, keyword); 119 } finally { 120 _("Clean up."); 121 await store.wipe(); 122 } 123 }); 124 125 add_bookmark_test(async function test_bookmark_update(engine) { 126 let store = engine._store; 127 128 try { 129 _("Create a bookmark whose values we'll change."); 130 let bmk1 = await PlacesUtils.bookmarks.insert({ 131 parentGuid: PlacesUtils.bookmarks.toolbarGuid, 132 url: "http://getfirefox.com/", 133 title: "Get Firefox!", 134 }); 135 await PlacesUtils.keywords.insert({ 136 url: "http://getfirefox.com/", 137 keyword: "firefox", 138 }); 139 140 _("Update the record with some null values."); 141 let record = await store.createRecord(bmk1.guid); 142 record.title = null; 143 record.keyword = null; 144 record.tags = null; 145 await apply_records(engine, [record]); 146 147 _("Verify that the values have been cleared."); 148 let item = await PlacesUtils.bookmarks.fetch(bmk1.guid); 149 Assert.equal(item.title, ""); 150 let keyword = await PlacesUtils.keywords.fetch({ 151 url: "http://getfirefox.com/", 152 }); 153 Assert.equal(null, keyword); 154 } finally { 155 _("Clean up."); 156 await store.wipe(); 157 } 158 }); 159 160 add_bookmark_test(async function test_bookmark_createRecord(engine) { 161 let store = engine._store; 162 163 try { 164 _("Create a bookmark without a title."); 165 let bmk1 = await PlacesUtils.bookmarks.insert({ 166 parentGuid: PlacesUtils.bookmarks.toolbarGuid, 167 url: "http://getfirefox.com/", 168 }); 169 170 _("Verify that the record is created accordingly."); 171 let record = await store.createRecord(bmk1.guid); 172 Assert.equal(record.title, ""); 173 Assert.equal(record.keyword, null); 174 } finally { 175 _("Clean up."); 176 await store.wipe(); 177 } 178 }); 179 180 add_bookmark_test(async function test_folder_create(engine) { 181 let store = engine._store; 182 183 try { 184 _("Create a folder."); 185 let folder = new BookmarkFolder("bookmarks", "testfolder-1"); 186 folder.parentName = BookmarksToolbarTitle; 187 folder.parentid = "toolbar"; 188 folder.title = "Test Folder"; 189 await apply_records(engine, [folder]); 190 191 _("Verify it has been created correctly."); 192 let item = await PlacesUtils.bookmarks.fetch(folder.id); 193 Assert.equal(item.type, PlacesUtils.bookmarks.TYPE_FOLDER); 194 Assert.equal(item.title, folder.title); 195 Assert.equal(item.parentGuid, PlacesUtils.bookmarks.toolbarGuid); 196 197 _( 198 "Have the store create a new record object. Verify that it has the same data." 199 ); 200 let newrecord = await store.createRecord(folder.id); 201 Assert.ok(newrecord instanceof BookmarkFolder); 202 for (let property of ["title", "parentName", "parentid"]) { 203 Assert.equal(newrecord[property], folder[property]); 204 } 205 206 _("Folders have high sort index to ensure they're synced first."); 207 Assert.equal(newrecord.sortindex, 1000000); 208 } finally { 209 _("Clean up."); 210 await store.wipe(); 211 } 212 }); 213 214 add_bookmark_test(async function test_folder_createRecord(engine) { 215 let store = engine._store; 216 217 try { 218 _("Create a folder."); 219 let folder1 = await PlacesUtils.bookmarks.insert({ 220 parentGuid: PlacesUtils.bookmarks.toolbarGuid, 221 type: PlacesUtils.bookmarks.TYPE_FOLDER, 222 title: "Folder1", 223 }); 224 225 _("Create two bookmarks in that folder without assigning them GUIDs."); 226 let bmk1 = await PlacesUtils.bookmarks.insert({ 227 parentGuid: folder1.guid, 228 url: "http://getfirefox.com/", 229 title: "Get Firefox!", 230 }); 231 let bmk2 = await PlacesUtils.bookmarks.insert({ 232 parentGuid: folder1.guid, 233 url: "http://getthunderbird.com/", 234 title: "Get Thunderbird!", 235 }); 236 237 _("Create a record for the folder and verify basic properties."); 238 let record = await store.createRecord(folder1.guid); 239 Assert.ok(record instanceof BookmarkFolder); 240 Assert.equal(record.title, "Folder1"); 241 Assert.equal(record.parentid, "toolbar"); 242 Assert.equal(record.parentName, BookmarksToolbarTitle); 243 244 _( 245 "Verify the folder's children. Ensures that the bookmarks were given GUIDs." 246 ); 247 Assert.deepEqual(record.children, [bmk1.guid, bmk2.guid]); 248 } finally { 249 _("Clean up."); 250 await store.wipe(); 251 } 252 }); 253 254 add_bookmark_test(async function test_deleted(engine) { 255 let store = engine._store; 256 257 try { 258 _("Create a bookmark that will be deleted."); 259 let bmk1 = await PlacesUtils.bookmarks.insert({ 260 parentGuid: PlacesUtils.bookmarks.toolbarGuid, 261 url: "http://getfirefox.com/", 262 title: "Get Firefox!", 263 }); 264 // The engine needs to think we've previously synced it. 265 await PlacesTestUtils.markBookmarksAsSynced(); 266 267 _("Delete the bookmark through the store."); 268 let record = new PlacesItem("bookmarks", bmk1.guid); 269 record.deleted = true; 270 await apply_records(engine, [record]); 271 _("Ensure it has been deleted."); 272 let item = await PlacesUtils.bookmarks.fetch(bmk1.guid); 273 let newrec = await store.createRecord(bmk1.guid); 274 Assert.equal(null, item); 275 Assert.equal(newrec.deleted, true); 276 _("Verify that the keyword has been cleared."); 277 let keyword = await PlacesUtils.keywords.fetch({ 278 url: "http://getfirefox.com/", 279 }); 280 Assert.equal(null, keyword); 281 } finally { 282 _("Clean up."); 283 await store.wipe(); 284 } 285 }); 286 287 add_bookmark_test(async function test_move_folder(engine) { 288 let store = engine._store; 289 store._childrenToOrder = {}; // *sob* - only needed for legacy. 290 291 try { 292 _("Create two folders and a bookmark in one of them."); 293 let folder1 = await PlacesUtils.bookmarks.insert({ 294 parentGuid: PlacesUtils.bookmarks.toolbarGuid, 295 type: PlacesUtils.bookmarks.TYPE_FOLDER, 296 title: "Folder1", 297 }); 298 let folder2 = await PlacesUtils.bookmarks.insert({ 299 parentGuid: PlacesUtils.bookmarks.toolbarGuid, 300 type: PlacesUtils.bookmarks.TYPE_FOLDER, 301 title: "Folder2", 302 }); 303 let bmk = await PlacesUtils.bookmarks.insert({ 304 parentGuid: folder1.guid, 305 url: "http://getfirefox.com/", 306 title: "Get Firefox!", 307 }); 308 // add records to the store that represent the current state. 309 await apply_records(engine, [ 310 await store.createRecord(folder1.guid), 311 await store.createRecord(folder2.guid), 312 await store.createRecord(bmk.guid), 313 ]); 314 315 _("Now simulate incoming records reparenting it."); 316 let bmkRecord = await store.createRecord(bmk.guid); 317 Assert.equal(bmkRecord.parentid, folder1.guid); 318 bmkRecord.parentid = folder2.guid; 319 320 let folder1Record = await store.createRecord(folder1.guid); 321 Assert.deepEqual(folder1Record.children, [bmk.guid]); 322 folder1Record.children = []; 323 let folder2Record = await store.createRecord(folder2.guid); 324 Assert.deepEqual(folder2Record.children, []); 325 folder2Record.children = [bmk.guid]; 326 327 await apply_records(engine, [bmkRecord, folder1Record, folder2Record]); 328 329 _("Verify the new parent."); 330 let movedBmk = await PlacesUtils.bookmarks.fetch(bmk.guid); 331 Assert.equal(movedBmk.parentGuid, folder2.guid); 332 } finally { 333 _("Clean up."); 334 await store.wipe(); 335 } 336 }); 337 338 add_bookmark_test(async function test_move_order(engine) { 339 let store = engine._store; 340 let tracker = engine._tracker; 341 342 // Make sure the tracker is turned on. 343 tracker.start(); 344 try { 345 _("Create two bookmarks"); 346 let bmk1 = await PlacesUtils.bookmarks.insert({ 347 parentGuid: PlacesUtils.bookmarks.toolbarGuid, 348 url: "http://getfirefox.com/", 349 title: "Get Firefox!", 350 }); 351 let bmk2 = await PlacesUtils.bookmarks.insert({ 352 parentGuid: PlacesUtils.bookmarks.toolbarGuid, 353 url: "http://getthunderbird.com/", 354 title: "Get Thunderbird!", 355 }); 356 357 _("Verify order."); 358 let childIds = 359 await PlacesSyncUtils.bookmarks.fetchChildRecordIds("toolbar"); 360 Assert.deepEqual(childIds, [bmk1.guid, bmk2.guid]); 361 let toolbar = await store.createRecord("toolbar"); 362 Assert.deepEqual(toolbar.children, [bmk1.guid, bmk2.guid]); 363 364 _("Move bookmarks around."); 365 store._childrenToOrder = {}; 366 toolbar.children = [bmk2.guid, bmk1.guid]; 367 await apply_records(engine, [ 368 toolbar, 369 await store.createRecord(bmk1.guid), 370 await store.createRecord(bmk2.guid), 371 ]); 372 delete store._childrenToOrder; 373 374 _("Verify new order."); 375 let newChildIds = 376 await PlacesSyncUtils.bookmarks.fetchChildRecordIds("toolbar"); 377 Assert.deepEqual(newChildIds, [bmk2.guid, bmk1.guid]); 378 } finally { 379 await tracker.stop(); 380 _("Clean up."); 381 await store.wipe(); 382 } 383 }); 384 385 // Tests Bug 806460, in which query records arrive with empty folder 386 // names and missing bookmark URIs. 387 add_bookmark_test(async function test_empty_query_doesnt_die(engine) { 388 let record = new BookmarkQuery("bookmarks", "8xoDGqKrXf1P"); 389 record.folderName = ""; 390 record.queryId = ""; 391 record.parentName = "Toolbar"; 392 record.parentid = "toolbar"; 393 394 // These should not throw. 395 await apply_records(engine, [record]); 396 397 delete record.folderName; 398 await apply_records(engine, [record]); 399 }); 400 401 add_bookmark_test(async function test_calculateIndex_for_invalid_url(engine) { 402 let store = engine._store; 403 404 let folderIndex = await store._calculateIndex({ 405 type: "folder", 406 }); 407 equal(folderIndex, 1000000, "Should use high sort index for folders"); 408 409 let toolbarIndex = await store._calculateIndex({ 410 parentid: "toolbar", 411 }); 412 equal(toolbarIndex, 150, "Should bump sort index for toolbar bookmarks"); 413 414 let validURLIndex = await store._calculateIndex({ 415 bmkUri: "http://example.com/a", 416 }); 417 greaterOrEqual(validURLIndex, 0, "Should use frecency for index"); 418 419 let invalidURLIndex = await store._calculateIndex({ 420 bmkUri: "!@#$%", 421 }); 422 equal(invalidURLIndex, 0, "Should not throw for invalid URLs"); 423 });