/* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ /* globals ChromeUtils, Assert, add_task */ "use strict"; // Ensure we initialize places: do_get_profile(); ChromeUtils.defineModuleGetter( this, "PlacesUIUtils", "resource:///modules/PlacesUIUtils.jsm" ); // Needed because we rely on the app name for the OPML file name and title. ChromeUtils.import("resource://testing-common/AppInfo.jsm", this); updateAppInfo({ name: "LiveBookmarkMigratorTest", ID: "{230de50e-4cd1-11dc-8314-0800200c9a66}", version: "1", platformVersion: "", }); const { PlacesUtils } = ChromeUtils.import( "resource://gre/modules/PlacesUtils.jsm" ); const { LiveBookmarkMigrator } = ChromeUtils.import( "resource:///modules/LiveBookmarkMigrator.jsm" ); const kTestData = { guid: PlacesUtils.bookmarks.toolbarGuid, children: [ { type: PlacesUtils.bookmarks.TYPE_BOOKMARK, title: "BM 1", url: new URL("https://example.com/1"), }, { type: PlacesUtils.bookmarks.TYPE_FOLDER, title: "LB 1" }, { type: PlacesUtils.bookmarks.TYPE_BOOKMARK, title: "BM 2", url: new URL("https://example.com/2"), }, { type: PlacesUtils.bookmarks.TYPE_FOLDER, title: "Regular old folder", children: [ { type: PlacesUtils.bookmarks.TYPE_FOLDER, title: "LB child 1" }, { type: PlacesUtils.bookmarks.TYPE_BOOKMARK, title: "BM child 1", url: new URL("https://example.com/1/1"), }, { type: PlacesUtils.bookmarks.TYPE_FOLDER, title: "LB child 2" }, { type: PlacesUtils.bookmarks.TYPE_BOOKMARK, title: "BM child 2", url: new URL("https://example.com/1/2"), }, ], }, { type: PlacesUtils.bookmarks.TYPE_FOLDER, title: "LB 2" }, { type: PlacesUtils.bookmarks.TYPE_BOOKMARK, title: "BM 3", url: new URL("https://example.com/3"), }, { type: PlacesUtils.bookmarks.TYPE_FOLDER, title: "LB 3" }, // The next two will be skipped because we ignore the feeds we used to ship by default: { type: PlacesUtils.bookmarks.TYPE_FOLDER, title: "Default live bookmark 4", }, { type: PlacesUtils.bookmarks.TYPE_FOLDER, title: "Default live bookmark 5", }, ], }; const kDefaultFeedURLsToTest = [ "http://en-US.fxfeeds.mozilla.com/", "http://fxfeeds.mozilla.org/", ]; registerCleanupFunction(async () => { await PlacesUtils.bookmarks.eraseEverything(); }); add_task(async function setup() { let insertedItems = await PlacesUtils.bookmarks.insertTree(kTestData); for (let item of insertedItems) { if (item.title.includes("LB")) { let id = await PlacesUtils.promiseItemId(item.guid); let feedID = item.title.replace(/[^0-9]/g, ""); PlacesUtils.annotations.setItemAnnotation( id, PlacesUtils.LMANNO_FEEDURI, "https://example.com/feed/" + feedID, 0, PlacesUtils.annotations.EXPIRE_NEVER, PlacesUtils.bookmarks.SOURCES.DEFAULT, true ); // For half the feeds, set a site URI as well. if (parseInt(feedID) % 2) { PlacesUtils.annotations.setItemAnnotation( id, PlacesUtils.LMANNO_SITEURI, "https://example.com/feedpage/" + feedID, 0, PlacesUtils.annotations.EXPIRE_NEVER, PlacesUtils.bookmarks.SOURCES.DEFAULT, true ); } } else if (item.title.includes("Default live bookmark")) { let id = await PlacesUtils.promiseItemId(item.guid); PlacesUtils.annotations.setItemAnnotation( id, PlacesUtils.LMANNO_FEEDURI, kDefaultFeedURLsToTest.pop(), 0, PlacesUtils.annotations.EXPIRE_NEVER, PlacesUtils.bookmarks.SOURCES.DEFAULT, true ); } } }); // Test fetching LB with and without siteURIs works. Check ordering is last-positioned-first. add_task(async function check_fetches_livemarks_correctly() { let detectedLiveBookmarks = await LiveBookmarkMigrator._fetch(); Assert.equal(detectedLiveBookmarks.length, 7, "Should have 7 live bookmarks"); Assert.notEqual( detectedLiveBookmarks.filter(lb => lb.siteURI).length, 0, "Should have more than 0 items with a siteURI" ); Assert.notEqual( detectedLiveBookmarks.filter(lb => !lb.siteURI).length, 0, "Should have more than 0 items without a siteURI" ); Assert.equal( detectedLiveBookmarks.filter(lb => lb.feedURI).length, 7, "All of them should have a feed URI" ); info(JSON.stringify(detectedLiveBookmarks)); Assert.deepEqual( detectedLiveBookmarks.map(bm => bm.index), [8, 7, 6, 4, 2, 1, 0], "Should have sorted the items correctly." ); }); // Test that we write sane OPML for some live bookmarks. add_task(async function check_opml_writing() { let bsPass = ChromeUtils.import( "resource:///modules/LiveBookmarkMigrator.jsm", null ); let oldFile = bsPass.OS.File; registerCleanupFunction(() => { bsPass.OS.File = oldFile; }); let lastWriteArgs = null; bsPass.OS.File = { writeAtomic() { lastWriteArgs = Array.from(arguments); }, openUnique() { return { file: { close() {} }, path: "foopy.opml" }; }, }; let livemarks = [ { feedURI: new URL("https://example.com/feed"), siteURI: new URL("https://example.com/"), title: "My funky feed", }, { feedURI: new URL("https://example.com/otherfeed"), title: "My other feed", }, ]; await LiveBookmarkMigrator._writeOPML(livemarks); let expectedOPML = ` LiveBookmarkMigratorTest Live Bookmarks `; Assert.deepEqual( lastWriteArgs, ["foopy.opml", expectedOPML, { encoding: "utf-8" }], "Should have tried to write the right thing." ); }); // Check all the live bookmarks have been removed, and where they have site URIs, replaced: add_task(async function check_replace_bookmarks_correctly() { let oldLiveBookmarks = await LiveBookmarkMigrator._fetch(); await LiveBookmarkMigrator._transformBookmarks(oldLiveBookmarks); // Check all the remaining bookmarks are not live bookmarks anymore: let newBookmarkState = await PlacesUtils.promiseBookmarksTree( PlacesUtils.bookmarks.toolbarGuid ); function checkNotALiveBookmark(bm) { Assert.ok( !bm.annos, "Bookmark " + bm.title + " shouldn't be a live bookmark" ); } function iterate(node, fn) { fn(node); if (node.children) { node.children.forEach(fn); } } iterate(newBookmarkState, checkNotALiveBookmark); Assert.equal( (await LiveBookmarkMigrator._fetch()).length, 0, "Migrator should no longer find live bookmarks" ); info(JSON.stringify(newBookmarkState)); // Check that all the old live bookmarks have been removed, and where appropriate, replaced: for (let bm of oldLiveBookmarks) { let replacements = await PlacesUtils.bookmarks.search({ title: bm.title }); let replacement = replacements && replacements[0]; if (!bm.title.includes("Default live bookmark")) { if (replacement) { Assert.equal( bm.title, replacement.title, "Found item should have same title" ); Assert.equal( bm.siteURI || bm.feedURI, replacement.url.href, "Found item should have matching URL" ); Assert.equal( bm.index, replacement.index, "Found item should have same position" ); Assert.equal( bm.parentGuid, replacement.parentGuid, "Found item should have same parent" ); } else { Assert.ok( false, "Oy! No replacement for `" + bm.title + "` but we expected one!" ); } } else { Assert.ok(!replacement, "Shouldn't have kept the default bookmark items"); } } });