123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749 |
- import {actionCreators as ac, actionTypes as at} from "common/Actions.jsm";
- import {GlobalOverrider} from "test/unit/utils";
- import {PlacesFeed} from "lib/PlacesFeed.jsm";
- const {HistoryObserver, BookmarksObserver, PlacesObserver} = PlacesFeed;
- const FAKE_BOOKMARK = {bookmarkGuid: "xi31", bookmarkTitle: "Foo", dateAdded: 123214232, url: "foo.com"};
- const TYPE_BOOKMARK = 0; // This is fake, for testing
- const SOURCES = {
- DEFAULT: 0,
- SYNC: 1,
- IMPORT: 2,
- RESTORE: 5,
- RESTORE_ON_STARTUP: 6,
- };
- const BLOCKED_EVENT = "newtab-linkBlocked"; // The event dispatched in NewTabUtils when a link is blocked;
- describe("PlacesFeed", () => {
- let globals;
- let sandbox;
- let feed;
- beforeEach(() => {
- globals = new GlobalOverrider();
- sandbox = globals.sandbox;
- globals.set("NewTabUtils", {
- activityStreamProvider: {getBookmark() {}},
- activityStreamLinks: {
- addBookmark: sandbox.spy(),
- deleteBookmark: sandbox.spy(),
- deleteHistoryEntry: sandbox.spy(),
- blockURL: sandbox.spy(),
- addPocketEntry: sandbox.spy(() => Promise.resolve()),
- deletePocketEntry: sandbox.spy(() => Promise.resolve()),
- archivePocketEntry: sandbox.spy(() => Promise.resolve()),
- },
- });
- sandbox.stub(global.PlacesUtils.bookmarks, "TYPE_BOOKMARK").value(TYPE_BOOKMARK);
- sandbox.stub(global.PlacesUtils.bookmarks, "SOURCES").value(SOURCES);
- sandbox.spy(global.PlacesUtils.bookmarks, "addObserver");
- sandbox.spy(global.PlacesUtils.bookmarks, "removeObserver");
- sandbox.spy(global.PlacesUtils.history, "addObserver");
- sandbox.spy(global.PlacesUtils.history, "removeObserver");
- sandbox.spy(global.PlacesUtils.observers, "addListener");
- sandbox.spy(global.PlacesUtils.observers, "removeListener");
- sandbox.spy(global.Services.obs, "addObserver");
- sandbox.spy(global.Services.obs, "removeObserver");
- sandbox.spy(global.Cu, "reportError");
- global.Cc["@mozilla.org/timer;1"] = {
- createInstance() {
- return {
- initWithCallback: sinon.stub().callsFake(callback => callback()),
- cancel: sinon.spy(),
- };
- },
- };
- feed = new PlacesFeed();
- feed.store = {dispatch: sinon.spy()};
- });
- afterEach(() => globals.restore());
- it("should have a HistoryObserver that dispatches to the store", () => {
- assert.instanceOf(feed.historyObserver, HistoryObserver);
- const action = {type: "FOO"};
- feed.historyObserver.dispatch(action);
- assert.calledOnce(feed.store.dispatch);
- assert.equal(feed.store.dispatch.firstCall.args[0].type, action.type);
- });
- it("should have a BookmarksObserver that dispatch to the store", () => {
- assert.instanceOf(feed.bookmarksObserver, BookmarksObserver);
- const action = {type: "FOO"};
- feed.bookmarksObserver.dispatch(action);
- assert.calledOnce(feed.store.dispatch);
- assert.equal(feed.store.dispatch.firstCall.args[0].type, action.type);
- });
- it("should have a PlacesObserver that dispatches to the store", () => {
- assert.instanceOf(feed.placesObserver, PlacesObserver);
- const action = {type: "FOO"};
- feed.placesObserver.dispatch(action);
- assert.calledOnce(feed.store.dispatch);
- assert.equal(feed.store.dispatch.firstCall.args[0].type, action.type);
- });
- describe("#onAction", () => {
- it("should add bookmark, history, places, blocked observers on INIT", () => {
- feed.onAction({type: at.INIT});
- assert.calledWith(global.PlacesUtils.history.addObserver, feed.historyObserver, true);
- assert.calledWith(global.PlacesUtils.bookmarks.addObserver, feed.bookmarksObserver, true);
- assert.calledWith(global.PlacesUtils.observers.addListener, ["bookmark-added"], feed.placesObserver.handlePlacesEvent);
- assert.calledWith(global.Services.obs.addObserver, feed, BLOCKED_EVENT);
- });
- it("should remove bookmark, history, places, blocked observers, and timers on UNINIT", () => {
- feed.placesChangedTimer = global.Cc["@mozilla.org/timer;1"].createInstance();
- let spy = feed.placesChangedTimer.cancel;
- feed.onAction({type: at.UNINIT});
- assert.calledWith(global.PlacesUtils.history.removeObserver, feed.historyObserver);
- assert.calledWith(global.PlacesUtils.bookmarks.removeObserver, feed.bookmarksObserver);
- assert.calledWith(global.PlacesUtils.observers.removeListener, ["bookmark-added"], feed.placesObserver.handlePlacesEvent);
- assert.calledWith(global.Services.obs.removeObserver, feed, BLOCKED_EVENT);
- assert.equal(feed.placesChangedTimer, null);
- assert.calledOnce(spy);
- });
- it("should block a url on BLOCK_URL", () => {
- feed.onAction({type: at.BLOCK_URL, data: {url: "apple.com", pocket_id: 1234}});
- assert.calledWith(global.NewTabUtils.activityStreamLinks.blockURL, {url: "apple.com", pocket_id: 1234});
- });
- it("should bookmark a url on BOOKMARK_URL", () => {
- const data = {url: "pear.com", title: "A pear"};
- const _target = {browser: {ownerGlobal() {}}};
- feed.onAction({type: at.BOOKMARK_URL, data, _target});
- assert.calledWith(global.NewTabUtils.activityStreamLinks.addBookmark, data, _target.browser.ownerGlobal);
- });
- it("should delete a bookmark on DELETE_BOOKMARK_BY_ID", () => {
- feed.onAction({type: at.DELETE_BOOKMARK_BY_ID, data: "g123kd"});
- assert.calledWith(global.NewTabUtils.activityStreamLinks.deleteBookmark, "g123kd");
- });
- it("should delete a history entry on DELETE_HISTORY_URL", () => {
- feed.onAction({type: at.DELETE_HISTORY_URL, data: {url: "guava.com", forceBlock: null}});
- assert.calledWith(global.NewTabUtils.activityStreamLinks.deleteHistoryEntry, "guava.com");
- assert.notCalled(global.NewTabUtils.activityStreamLinks.blockURL);
- });
- it("should delete a history entry on DELETE_HISTORY_URL and force a site to be blocked if specified", () => {
- feed.onAction({type: at.DELETE_HISTORY_URL, data: {url: "guava.com", forceBlock: "g123kd"}});
- assert.calledWith(global.NewTabUtils.activityStreamLinks.deleteHistoryEntry, "guava.com");
- assert.calledWith(global.NewTabUtils.activityStreamLinks.blockURL, {url: "guava.com", pocket_id: undefined});
- });
- it("should call openLinkIn with the correct url and where on OPEN_NEW_WINDOW", () => {
- const openLinkIn = sinon.stub();
- const openWindowAction = {
- type: at.OPEN_NEW_WINDOW,
- data: {url: "foo.com"},
- _target: {browser: {ownerGlobal: {openLinkIn}}},
- };
- feed.onAction(openWindowAction);
- assert.calledOnce(openLinkIn);
- const [url, where, params] = openLinkIn.firstCall.args;
- assert.equal(url, "foo.com");
- assert.equal(where, "window");
- assert.propertyVal(params, "private", false);
- });
- it("should call openLinkIn with the correct url, where and privacy args on OPEN_PRIVATE_WINDOW", () => {
- const openLinkIn = sinon.stub();
- const openWindowAction = {
- type: at.OPEN_PRIVATE_WINDOW,
- data: {url: "foo.com"},
- _target: {browser: {ownerGlobal: {openLinkIn}}},
- };
- feed.onAction(openWindowAction);
- assert.calledOnce(openLinkIn);
- const [url, where, params] = openLinkIn.firstCall.args;
- assert.equal(url, "foo.com");
- assert.equal(where, "window");
- assert.propertyVal(params, "private", true);
- });
- it("should open link on OPEN_LINK", () => {
- const openLinkIn = sinon.stub();
- const openLinkAction = {
- type: at.OPEN_LINK,
- data: {url: "foo.com"},
- _target: {browser: {ownerGlobal: {openLinkIn, whereToOpenLink: e => "current"}}},
- };
- feed.onAction(openLinkAction);
- assert.calledOnce(openLinkIn);
- const [url, where, params] = openLinkIn.firstCall.args;
- assert.equal(url, "foo.com");
- assert.equal(where, "current");
- assert.propertyVal(params, "private", false);
- assert.propertyVal(params, "triggeringPrincipal", undefined);
- });
- it("should open link with referrer on OPEN_LINK", () => {
- const openLinkIn = sinon.stub();
- const openLinkAction = {
- type: at.OPEN_LINK,
- data: {url: "foo.com", referrer: "foo.com/ref"},
- _target: {browser: {ownerGlobal: {openLinkIn, whereToOpenLink: e => "tab"}}},
- };
- feed.onAction(openLinkAction);
- const [, , params] = openLinkIn.firstCall.args;
- assert.propertyVal(params, "referrerPolicy", 5);
- assert.propertyVal(params.referrerURI, "spec", "foo.com/ref");
- });
- it("should mark link with typed bonus as typed before opening OPEN_LINK", () => {
- const callOrder = [];
- sinon.stub(global.PlacesUtils.history, "markPageAsTyped").callsFake(() => {
- callOrder.push("markPageAsTyped");
- });
- const openLinkIn = sinon.stub().callsFake(() => {
- callOrder.push("openLinkIn");
- });
- const openLinkAction = {
- type: at.OPEN_LINK,
- data: {
- typedBonus: true,
- url: "foo.com",
- },
- _target: {browser: {ownerGlobal: {openLinkIn, whereToOpenLink: e => "tab"}}},
- };
- feed.onAction(openLinkAction);
- assert.sameOrderedMembers(callOrder, ["markPageAsTyped", "openLinkIn"]);
- });
- it("should open the pocket link if it's a pocket story on OPEN_LINK", () => {
- const openLinkIn = sinon.stub();
- const openLinkAction = {
- type: at.OPEN_LINK,
- data: {url: "foo.com", open_url: "getpocket.com/foo", type: "pocket"},
- _target: {browser: {ownerGlobal: {openLinkIn, whereToOpenLink: e => "current"}}},
- };
- feed.onAction(openLinkAction);
- assert.calledOnce(openLinkIn);
- const [url, where, params] = openLinkIn.firstCall.args;
- assert.equal(url, "getpocket.com/foo");
- assert.equal(where, "current");
- assert.propertyVal(params, "private", false);
- assert.propertyVal(params, "triggeringPrincipal", undefined);
- });
- it("should call fillSearchTopSiteTerm on FILL_SEARCH_TERM", () => {
- sinon.stub(feed, "fillSearchTopSiteTerm");
- feed.onAction({type: at.FILL_SEARCH_TERM});
- assert.calledOnce(feed.fillSearchTopSiteTerm);
- });
- it("should set the URL bar value to the label value", () => {
- const locationBar = {search: sandbox.stub()};
- const action = {
- type: at.FILL_SEARCH_TERM,
- data: {label: "@Foo"},
- _target: {browser: {ownerGlobal: {gURLBar: locationBar}}},
- };
- feed.fillSearchTopSiteTerm(action);
- assert.calledOnce(locationBar.search);
- assert.calledWithExactly(locationBar.search, "@Foo ");
- });
- it("should call saveToPocket on SAVE_TO_POCKET", () => {
- const action = {
- type: at.SAVE_TO_POCKET,
- data: {site: {url: "raspberry.com", title: "raspberry"}},
- _target: {browser: {}},
- };
- sinon.stub(feed, "saveToPocket");
- feed.onAction(action);
- assert.calledWithExactly(feed.saveToPocket, action.data.site, action._target.browser);
- });
- it("should call NewTabUtils.activityStreamLinks.addPocketEntry if we are saving a pocket story", async () => {
- const action = {
- data: {site: {url: "raspberry.com", title: "raspberry"}},
- _target: {browser: {}},
- };
- await feed.saveToPocket(action.data.site, action._target.browser);
- assert.calledOnce(global.NewTabUtils.activityStreamLinks.addPocketEntry);
- assert.calledWithExactly(global.NewTabUtils.activityStreamLinks.addPocketEntry, action.data.site.url, action.data.site.title, action._target.browser);
- });
- it("should reject the promise if NewTabUtils.activityStreamLinks.addPocketEntry rejects", async () => {
- const e = new Error("Error");
- const action = {
- data: {site: {url: "raspberry.com", title: "raspberry"}},
- _target: {browser: {}},
- };
- global.NewTabUtils.activityStreamLinks.addPocketEntry = sandbox.stub().rejects(e);
- await feed.saveToPocket(action.data.site, action._target.browser);
- assert.calledWith(global.Cu.reportError, e);
- });
- it("should broadcast to content if we successfully added a link to Pocket", async () => {
- // test in the form that the API returns data based on: https://getpocket.com/developer/docs/v3/add
- global.NewTabUtils.activityStreamLinks.addPocketEntry = sandbox.stub().resolves({item: {open_url: "pocket.com/itemID", item_id: 1234}});
- const action = {
- data: {site: {url: "raspberry.com", title: "raspberry"}},
- _target: {browser: {}},
- };
- await feed.saveToPocket(action.data.site, action._target.browser);
- assert.equal(feed.store.dispatch.firstCall.args[0].type, at.PLACES_SAVED_TO_POCKET);
- assert.deepEqual(feed.store.dispatch.firstCall.args[0].data, {
- url: "raspberry.com",
- title: "raspberry",
- pocket_id: 1234,
- open_url: "pocket.com/itemID",
- });
- });
- it("should only broadcast if we got some data back from addPocketEntry", async () => {
- global.NewTabUtils.activityStreamLinks.addPocketEntry = sandbox.stub().resolves(null);
- const action = {
- data: {site: {url: "raspberry.com", title: "raspberry"}},
- _target: {browser: {}},
- };
- await feed.saveToPocket(action.data.site, action._target.browser);
- assert.notCalled(feed.store.dispatch);
- });
- it("should call deleteFromPocket on DELETE_FROM_POCKET", () => {
- sandbox.stub(feed, "deleteFromPocket");
- feed.onAction({type: at.DELETE_FROM_POCKET, data: {pocket_id: 12345}});
- assert.calledOnce(feed.deleteFromPocket);
- assert.calledWithExactly(feed.deleteFromPocket, 12345);
- });
- it("should catch if deletePocketEntry throws", async () => {
- const e = new Error("Error");
- global.NewTabUtils.activityStreamLinks.deletePocketEntry = sandbox.stub().rejects(e);
- await feed.deleteFromPocket(12345);
- assert.calledWith(global.Cu.reportError, e);
- });
- it("should call NewTabUtils.deletePocketEntry and dispatch POCKET_LINK_DELETED_OR_ARCHIVED when deleting from Pocket", async () => {
- await feed.deleteFromPocket(12345);
- assert.calledOnce(global.NewTabUtils.activityStreamLinks.deletePocketEntry);
- assert.calledWith(global.NewTabUtils.activityStreamLinks.deletePocketEntry, 12345);
- assert.calledOnce(feed.store.dispatch);
- assert.calledWith(feed.store.dispatch, {type: at.POCKET_LINK_DELETED_OR_ARCHIVED});
- });
- it("should call archiveFromPocket on ARCHIVE_FROM_POCKET", async () => {
- sandbox.stub(feed, "archiveFromPocket");
- await feed.onAction({type: at.ARCHIVE_FROM_POCKET, data: {pocket_id: 12345}});
- assert.calledOnce(feed.archiveFromPocket);
- assert.calledWithExactly(feed.archiveFromPocket, 12345);
- });
- it("should catch if archiveFromPocket throws", async () => {
- const e = new Error("Error");
- global.NewTabUtils.activityStreamLinks.archivePocketEntry = sandbox.stub().rejects(e);
- await feed.archiveFromPocket(12345);
- assert.calledWith(global.Cu.reportError, e);
- });
- it("should call NewTabUtils.archivePocketEntry and dispatch POCKET_LINK_DELETED_OR_ARCHIVED when archiving from Pocket", async () => {
- await feed.archiveFromPocket(12345);
- assert.calledOnce(global.NewTabUtils.activityStreamLinks.archivePocketEntry);
- assert.calledWith(global.NewTabUtils.activityStreamLinks.archivePocketEntry, 12345);
- assert.calledOnce(feed.store.dispatch);
- assert.calledWith(feed.store.dispatch, {type: at.POCKET_LINK_DELETED_OR_ARCHIVED});
- });
- it("should call handoffSearchToAwesomebar on HANDOFF_SEARCH_TO_AWESOMEBAR", () => {
- const action = {
- type: at.HANDOFF_SEARCH_TO_AWESOMEBAR,
- data: {text: "f"},
- meta: {fromTarget: {}},
- _target: {browser: {ownerGlobal: {gURLBar: {focus: () => {}}}}},
- };
- sinon.stub(feed, "handoffSearchToAwesomebar");
- feed.onAction(action);
- assert.calledWith(feed.handoffSearchToAwesomebar, action);
- });
- });
- describe("handoffSearchToAwesomebar", () => {
- let fakeUrlBar;
- let listeners;
- beforeEach(() => {
- fakeUrlBar = {
- focus: sinon.spy(),
- search: sinon.spy(),
- setHiddenFocus: sinon.spy(),
- removeHiddenFocus: sinon.spy(),
- addEventListener: (ev, cb) => {
- listeners[ev] = cb;
- },
- removeEventListener: sinon.spy(),
- };
- listeners = {};
- });
- it("should properly handle handoff with no text passed in", () => {
- feed.handoffSearchToAwesomebar({
- _target: {browser: {ownerGlobal: {gURLBar: fakeUrlBar}}},
- data: {},
- meta: {fromTarget: {}},
- });
- assert.calledOnce(fakeUrlBar.setHiddenFocus);
- assert.notCalled(fakeUrlBar.search);
- assert.notCalled(feed.store.dispatch);
- // Now type a character.
- listeners.keydown({key: "f"});
- assert.calledOnce(fakeUrlBar.search);
- assert.calledOnce(fakeUrlBar.removeHiddenFocus);
- assert.calledOnce(feed.store.dispatch);
- assert.calledWith(feed.store.dispatch, {
- meta: {
- from: "ActivityStream:Main",
- skipMain: true,
- to: "ActivityStream:Content",
- toTarget: {},
- },
- type: "HIDE_SEARCH",
- });
- });
- it("should properly handle handoff with text data passed in", () => {
- feed.handoffSearchToAwesomebar({
- _target: {browser: {ownerGlobal: {gURLBar: fakeUrlBar}}},
- data: {text: "foo"},
- meta: {fromTarget: {}},
- });
- assert.calledOnce(fakeUrlBar.search);
- assert.calledWith(fakeUrlBar.search, "@google foo");
- assert.notCalled(fakeUrlBar.focus);
- assert.notCalled(fakeUrlBar.setHiddenFocus);
- // Now call blur listener.
- listeners.blur();
- assert.calledOnce(feed.store.dispatch);
- assert.calledWith(feed.store.dispatch, {
- meta: {
- from: "ActivityStream:Main",
- skipMain: true,
- to: "ActivityStream:Content",
- toTarget: {},
- },
- type: "SHOW_SEARCH",
- });
- });
- it("should SHOW_SEARCH on ESC keydown", () => {
- feed.handoffSearchToAwesomebar({
- _target: {browser: {ownerGlobal: {gURLBar: fakeUrlBar}}},
- data: {text: "foo"},
- meta: {fromTarget: {}},
- });
- assert.calledOnce(fakeUrlBar.search);
- assert.calledWith(fakeUrlBar.search, "@google foo");
- assert.notCalled(fakeUrlBar.focus);
- // Now call ESC keydown.
- listeners.keydown({key: "Escape"});
- assert.calledOnce(feed.store.dispatch);
- assert.calledWith(feed.store.dispatch, {
- meta: {
- from: "ActivityStream:Main",
- skipMain: true,
- to: "ActivityStream:Content",
- toTarget: {},
- },
- type: "SHOW_SEARCH",
- });
- });
- it("should properly handle no defined search alias", () => {
- global.Services.search.defaultEngine.wrappedJSObject.__internalAliases = [];
- feed.handoffSearchToAwesomebar({
- _target: {browser: {ownerGlobal: {gURLBar: fakeUrlBar}}},
- data: {text: "foo"},
- meta: {fromTarget: {}},
- });
- assert.calledOnce(fakeUrlBar.search);
- assert.calledWith(fakeUrlBar.search, "foo");
- });
- });
- describe("#observe", () => {
- it("should dispatch a PLACES_LINK_BLOCKED action with the url of the blocked link", () => {
- feed.observe(null, BLOCKED_EVENT, "foo123.com");
- assert.equal(feed.store.dispatch.firstCall.args[0].type, at.PLACES_LINK_BLOCKED);
- assert.deepEqual(feed.store.dispatch.firstCall.args[0].data, {url: "foo123.com"});
- });
- it("should not call dispatch if the topic is something other than BLOCKED_EVENT", () => {
- feed.observe(null, "someotherevent");
- assert.notCalled(feed.store.dispatch);
- });
- });
- describe("HistoryObserver", () => {
- let dispatch;
- let observer;
- beforeEach(() => {
- dispatch = sandbox.spy();
- observer = new HistoryObserver(dispatch);
- });
- it("should have a QueryInterface property", () => {
- assert.property(observer, "QueryInterface");
- });
- describe("#onDeleteURI", () => {
- it("should dispatch a PLACES_LINK_DELETED action with the right url", async () => {
- await observer.onDeleteURI({spec: "foo.com"});
- assert.calledWith(dispatch, {type: at.PLACES_LINK_DELETED, data: {url: "foo.com"}});
- });
- });
- describe("#onClearHistory", () => {
- it("should dispatch a PLACES_HISTORY_CLEARED action", () => {
- observer.onClearHistory();
- assert.calledWith(dispatch, {type: at.PLACES_HISTORY_CLEARED});
- });
- });
- describe("Other empty methods (to keep code coverage happy)", () => {
- it("should have a various empty functions for xpconnect happiness", () => {
- observer.onBeginUpdateBatch();
- observer.onEndUpdateBatch();
- observer.onTitleChanged();
- observer.onFrecencyChanged();
- observer.onManyFrecenciesChanged();
- observer.onPageChanged();
- observer.onDeleteVisits();
- });
- });
- });
- describe("Custom dispatch", () => {
- it("should only dispatch 1 PLACES_LINKS_CHANGED action if many bookmark-added notifications happened at once", async () => {
- // Yes, onItemAdded has at least 8 arguments. See function definition for docs.
- const args = [{
- itemType: TYPE_BOOKMARK,
- source: SOURCES.DEFAULT,
- dateAdded: FAKE_BOOKMARK.dateAdded,
- guid: FAKE_BOOKMARK.bookmarkGuid,
- title: FAKE_BOOKMARK.bookmarkTitle,
- url: "https://www.foo.com",
- isTagging: false,
- }];
- await feed.placesObserver.handlePlacesEvent(args);
- await feed.placesObserver.handlePlacesEvent(args);
- await feed.placesObserver.handlePlacesEvent(args);
- await feed.placesObserver.handlePlacesEvent(args);
- assert.calledOnce(feed.store.dispatch.withArgs(ac.OnlyToMain({type: at.PLACES_LINKS_CHANGED})));
- });
- it("should only dispatch 1 PLACES_LINKS_CHANGED action if many onItemRemoved notifications happened at once", async () => {
- const args = [null, null, null, TYPE_BOOKMARK, {spec: "foo.com"}, "123foo", "", SOURCES.DEFAULT];
- await feed.bookmarksObserver.onItemRemoved(...args);
- await feed.bookmarksObserver.onItemRemoved(...args);
- await feed.bookmarksObserver.onItemRemoved(...args);
- await feed.bookmarksObserver.onItemRemoved(...args);
- assert.calledOnce(feed.store.dispatch.withArgs(ac.OnlyToMain({type: at.PLACES_LINKS_CHANGED})));
- });
- it("should only dispatch 1 PLACES_LINKS_CHANGED action if any onDeleteURI notifications happened at once", async () => {
- await feed.historyObserver.onDeleteURI({spec: "foo.com"});
- await feed.historyObserver.onDeleteURI({spec: "foo1.com"});
- await feed.historyObserver.onDeleteURI({spec: "foo2.com"});
- assert.calledOnce(feed.store.dispatch.withArgs(ac.OnlyToMain({type: at.PLACES_LINKS_CHANGED})));
- });
- });
- describe("PlacesObserver", () => {
- describe("#bookmark-added", () => {
- let dispatch;
- let observer;
- beforeEach(() => {
- dispatch = sandbox.spy();
- observer = new PlacesObserver(dispatch);
- });
- it("should dispatch a PLACES_BOOKMARK_ADDED action with the bookmark data - http", async () => {
- const args = [{
- itemType: TYPE_BOOKMARK,
- source: SOURCES.DEFAULT,
- dateAdded: FAKE_BOOKMARK.dateAdded,
- guid: FAKE_BOOKMARK.bookmarkGuid,
- title: FAKE_BOOKMARK.bookmarkTitle,
- url: "http://www.foo.com",
- isTagging: false,
- }];
- await observer.handlePlacesEvent(args);
- assert.calledWith(dispatch.secondCall, {
- type: at.PLACES_BOOKMARK_ADDED,
- data: {
- bookmarkGuid: FAKE_BOOKMARK.bookmarkGuid,
- bookmarkTitle: FAKE_BOOKMARK.bookmarkTitle,
- dateAdded: FAKE_BOOKMARK.dateAdded * 1000,
- url: "http://www.foo.com",
- },
- });
- });
- it("should dispatch a PLACES_BOOKMARK_ADDED action with the bookmark data - https", async () => {
- const args = [{
- itemType: TYPE_BOOKMARK,
- source: SOURCES.DEFAULT,
- dateAdded: FAKE_BOOKMARK.dateAdded,
- guid: FAKE_BOOKMARK.bookmarkGuid,
- title: FAKE_BOOKMARK.bookmarkTitle,
- url: "https://www.foo.com",
- isTagging: false,
- }];
- await observer.handlePlacesEvent(args);
- assert.calledWith(dispatch.secondCall, {
- type: at.PLACES_BOOKMARK_ADDED,
- data: {
- bookmarkGuid: FAKE_BOOKMARK.bookmarkGuid,
- bookmarkTitle: FAKE_BOOKMARK.bookmarkTitle,
- dateAdded: FAKE_BOOKMARK.dateAdded * 1000,
- url: "https://www.foo.com",
- },
- });
- });
- it("should not dispatch a PLACES_BOOKMARK_ADDED action - not http/https", async () => {
- const args = [{
- itemType: TYPE_BOOKMARK,
- source: SOURCES.DEFAULT,
- dateAdded: FAKE_BOOKMARK.dateAdded,
- guid: FAKE_BOOKMARK.bookmarkGuid,
- title: FAKE_BOOKMARK.bookmarkTitle,
- url: "foo.com",
- isTagging: false,
- }];
- await observer.handlePlacesEvent(args);
- assert.notCalled(dispatch);
- });
- it("should not dispatch a PLACES_BOOKMARK_ADDED action - has IMPORT source", async () => {
- const args = [{
- itemType: TYPE_BOOKMARK,
- source: SOURCES.IMPORT,
- dateAdded: FAKE_BOOKMARK.dateAdded,
- guid: FAKE_BOOKMARK.bookmarkGuid,
- title: FAKE_BOOKMARK.bookmarkTitle,
- url: "foo.com",
- isTagging: false,
- }];
- await observer.handlePlacesEvent(args);
- assert.notCalled(dispatch);
- });
- it("should not dispatch a PLACES_BOOKMARK_ADDED action - has RESTORE source", async () => {
- const args = [{
- itemType: TYPE_BOOKMARK,
- source: SOURCES.RESTORE,
- dateAdded: FAKE_BOOKMARK.dateAdded,
- guid: FAKE_BOOKMARK.bookmarkGuid,
- title: FAKE_BOOKMARK.bookmarkTitle,
- url: "foo.com",
- isTagging: false,
- }];
- await observer.handlePlacesEvent(args);
- assert.notCalled(dispatch);
- });
- it("should not dispatch a PLACES_BOOKMARK_ADDED action - has RESTORE_ON_STARTUP source", async () => {
- const args = [{
- itemType: TYPE_BOOKMARK,
- source: SOURCES.RESTORE_ON_STARTUP,
- dateAdded: FAKE_BOOKMARK.dateAdded,
- guid: FAKE_BOOKMARK.bookmarkGuid,
- title: FAKE_BOOKMARK.bookmarkTitle,
- url: "foo.com",
- isTagging: false,
- }];
- await observer.handlePlacesEvent(args);
- assert.notCalled(dispatch);
- });
- it("should not dispatch a PLACES_BOOKMARK_ADDED action - has SYNC source", async () => {
- const args = [{
- itemType: TYPE_BOOKMARK,
- source: SOURCES.SYNC,
- dateAdded: FAKE_BOOKMARK.dateAdded,
- guid: FAKE_BOOKMARK.bookmarkGuid,
- title: FAKE_BOOKMARK.bookmarkTitle,
- url: "foo.com",
- isTagging: false,
- }];
- await observer.handlePlacesEvent(args);
- assert.notCalled(dispatch);
- });
- it("should ignore events that are not of TYPE_BOOKMARK", async () => {
- const args = [{
- itemType: "nottypebookmark",
- source: SOURCES.DEFAULT,
- dateAdded: FAKE_BOOKMARK.dateAdded,
- guid: FAKE_BOOKMARK.bookmarkGuid,
- title: FAKE_BOOKMARK.bookmarkTitle,
- url: "https://www.foo.com",
- isTagging: false,
- }];
- await observer.handlePlacesEvent(args);
- assert.notCalled(dispatch);
- });
- });
- });
- describe("BookmarksObserver", () => {
- let dispatch;
- let observer;
- beforeEach(() => {
- dispatch = sandbox.spy();
- observer = new BookmarksObserver(dispatch);
- });
- it("should have a QueryInterface property", () => {
- assert.property(observer, "QueryInterface");
- });
- describe("#onItemRemoved", () => {
- it("should ignore events that are not of TYPE_BOOKMARK", async () => {
- await observer.onItemRemoved(null, null, null, "nottypebookmark", null, "123foo", "", SOURCES.DEFAULT);
- assert.notCalled(dispatch);
- });
- it("should not dispatch a PLACES_BOOKMARK_REMOVED action - has SYNC source", async () => {
- const args = [null, null, null, TYPE_BOOKMARK, {spec: "foo.com"}, "123foo", "", SOURCES.SYNC];
- await observer.onItemRemoved(...args);
- assert.notCalled(dispatch);
- });
- it("should not dispatch a PLACES_BOOKMARK_REMOVED action - has IMPORT source", async () => {
- const args = [null, null, null, TYPE_BOOKMARK, {spec: "foo.com"}, "123foo", "", SOURCES.IMPORT];
- await observer.onItemRemoved(...args);
- assert.notCalled(dispatch);
- });
- it("should not dispatch a PLACES_BOOKMARK_REMOVED action - has RESTORE source", async () => {
- const args = [null, null, null, TYPE_BOOKMARK, {spec: "foo.com"}, "123foo", "", SOURCES.RESTORE];
- await observer.onItemRemoved(...args);
- assert.notCalled(dispatch);
- });
- it("should not dispatch a PLACES_BOOKMARK_REMOVED action - has RESTORE_ON_STARTUP source", async () => {
- const args = [null, null, null, TYPE_BOOKMARK, {spec: "foo.com"}, "123foo", "", SOURCES.RESTORE_ON_STARTUP];
- await observer.onItemRemoved(...args);
- assert.notCalled(dispatch);
- });
- it("should dispatch a PLACES_BOOKMARK_REMOVED action with the right URL and bookmarkGuid", () => {
- observer.onItemRemoved(null, null, null, TYPE_BOOKMARK, {spec: "foo.com"}, "123foo", "", SOURCES.DEFAULT);
- assert.calledWith(dispatch, {type: at.PLACES_BOOKMARK_REMOVED, data: {bookmarkGuid: "123foo", url: "foo.com"}});
- });
- });
- describe("Other empty methods (to keep code coverage happy)", () => {
- it("should have a various empty functions for xpconnect happiness", () => {
- observer.onBeginUpdateBatch();
- observer.onEndUpdateBatch();
- observer.onItemVisited();
- observer.onItemMoved();
- observer.onItemChanged();
- });
- });
- });
- });
|