forked from mirrors/gecko-dev
1245 lines
40 KiB
JavaScript
1245 lines
40 KiB
JavaScript
import {
|
|
actionCreators as ac,
|
|
actionTypes as at,
|
|
} from "common/Actions.sys.mjs";
|
|
import { GlobalOverrider } from "test/unit/utils";
|
|
import injector from "inject!lib/PlacesFeed.jsm";
|
|
|
|
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;
|
|
|
|
const TOP_SITES_BLOCKED_SPONSORS_PREF = "browser.topsites.blockedSponsors";
|
|
const POCKET_SITE_PREF = "extensions.pocket.site";
|
|
|
|
describe("PlacesFeed", () => {
|
|
let PlacesFeed;
|
|
let PlacesObserver;
|
|
let globals;
|
|
let sandbox;
|
|
let feed;
|
|
let shortURLStub;
|
|
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()),
|
|
},
|
|
});
|
|
globals.set("pktApi", {
|
|
isUserLoggedIn: sandbox.spy(),
|
|
});
|
|
globals.set("ExperimentAPI", {
|
|
getExperiment: sandbox.spy(),
|
|
});
|
|
globals.set("NimbusFeatures", {
|
|
pocketNewtab: {
|
|
getVariable: sandbox.spy(),
|
|
},
|
|
});
|
|
globals.set("PartnerLinkAttribution", {
|
|
makeRequest: sandbox.spy(),
|
|
});
|
|
sandbox
|
|
.stub(global.PlacesUtils.bookmarks, "TYPE_BOOKMARK")
|
|
.value(TYPE_BOOKMARK);
|
|
sandbox.stub(global.PlacesUtils.bookmarks, "SOURCES").value(SOURCES);
|
|
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.console, "error");
|
|
shortURLStub = sandbox
|
|
.stub()
|
|
.callsFake(site =>
|
|
site.url.replace(/(.com|.ca)/, "").replace("https://", "")
|
|
);
|
|
|
|
global.Services.io.newURI = spec => ({
|
|
mutate: () => ({
|
|
setRef: ref => ({
|
|
finalize: () => ({
|
|
ref,
|
|
spec,
|
|
}),
|
|
}),
|
|
}),
|
|
spec,
|
|
scheme: "https",
|
|
});
|
|
|
|
global.Cc["@mozilla.org/timer;1"] = {
|
|
createInstance() {
|
|
return {
|
|
initWithCallback: sinon.stub().callsFake(callback => callback()),
|
|
cancel: sinon.spy(),
|
|
};
|
|
},
|
|
};
|
|
({ PlacesFeed } = injector({
|
|
"lib/ShortURL.jsm": { shortURL: shortURLStub },
|
|
}));
|
|
PlacesObserver = PlacesFeed.PlacesObserver;
|
|
feed = new PlacesFeed();
|
|
feed.store = { dispatch: sinon.spy() };
|
|
globals.set("AboutNewTab", {
|
|
activityStream: { store: { feeds: { get() {} } } },
|
|
});
|
|
});
|
|
afterEach(() => {
|
|
globals.restore();
|
|
sandbox.restore();
|
|
});
|
|
|
|
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("#addToBlockedTopSitesSponsors", () => {
|
|
let spy;
|
|
beforeEach(() => {
|
|
sandbox
|
|
.stub(global.Services.prefs, "getStringPref")
|
|
.withArgs(TOP_SITES_BLOCKED_SPONSORS_PREF)
|
|
.returns(`["foo","bar"]`);
|
|
spy = sandbox.spy(global.Services.prefs, "setStringPref");
|
|
});
|
|
|
|
it("should add the blocked sponsors to the blocklist", () => {
|
|
feed.addToBlockedTopSitesSponsors([
|
|
{ url: "test.com" },
|
|
{ url: "test1.com" },
|
|
]);
|
|
|
|
assert.calledOnce(spy);
|
|
const [, sponsors] = spy.firstCall.args;
|
|
assert.deepEqual(
|
|
new Set(["foo", "bar", "test", "test1"]),
|
|
new Set(JSON.parse(sponsors))
|
|
);
|
|
});
|
|
|
|
it("should not add duplicate sponsors to the blocklist", () => {
|
|
feed.addToBlockedTopSitesSponsors([
|
|
{ url: "foo.com" },
|
|
{ url: "bar.com" },
|
|
{ url: "test.com" },
|
|
]);
|
|
|
|
assert.calledOnce(spy);
|
|
const [, sponsors] = spy.firstCall.args;
|
|
assert.deepEqual(
|
|
new Set(["foo", "bar", "test"]),
|
|
new Set(JSON.parse(sponsors))
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("#onAction", () => {
|
|
it("should add bookmark, history, places, blocked observers on INIT", () => {
|
|
feed.onAction({ type: at.INIT });
|
|
|
|
assert.calledWith(
|
|
global.PlacesUtils.observers.addListener,
|
|
[
|
|
"bookmark-added",
|
|
"bookmark-removed",
|
|
"history-cleared",
|
|
"page-removed",
|
|
],
|
|
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.observers.removeListener,
|
|
[
|
|
"bookmark-added",
|
|
"bookmark-removed",
|
|
"history-cleared",
|
|
"page-removed",
|
|
],
|
|
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 update the blocked top sites sponsors", () => {
|
|
sandbox.stub(feed, "addToBlockedTopSitesSponsors");
|
|
feed.onAction({
|
|
type: at.BLOCK_URL,
|
|
data: [{ url: "foo.com", pocket_id: 1234, isSponsoredTopSite: 1 }],
|
|
});
|
|
assert.calledWith(feed.addToBlockedTopSitesSponsors, [
|
|
{ url: "foo.com" },
|
|
]);
|
|
});
|
|
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 openTrustedLinkIn with the correct url, where and params on OPEN_NEW_WINDOW", () => {
|
|
const openTrustedLinkIn = sinon.stub();
|
|
const openWindowAction = {
|
|
type: at.OPEN_NEW_WINDOW,
|
|
data: { url: "https://foo.com" },
|
|
_target: { browser: { ownerGlobal: { openTrustedLinkIn } } },
|
|
};
|
|
|
|
feed.onAction(openWindowAction);
|
|
|
|
assert.calledOnce(openTrustedLinkIn);
|
|
const [url, where, params] = openTrustedLinkIn.firstCall.args;
|
|
assert.equal(url, "https://foo.com");
|
|
assert.equal(where, "window");
|
|
assert.propertyVal(params, "private", false);
|
|
assert.propertyVal(params, "forceForeground", false);
|
|
});
|
|
it("should call openTrustedLinkIn with the correct url, where, params and privacy args on OPEN_PRIVATE_WINDOW", () => {
|
|
const openTrustedLinkIn = sinon.stub();
|
|
const openWindowAction = {
|
|
type: at.OPEN_PRIVATE_WINDOW,
|
|
data: { url: "https://foo.com" },
|
|
_target: { browser: { ownerGlobal: { openTrustedLinkIn } } },
|
|
};
|
|
|
|
feed.onAction(openWindowAction);
|
|
|
|
assert.calledOnce(openTrustedLinkIn);
|
|
const [url, where, params] = openTrustedLinkIn.firstCall.args;
|
|
assert.equal(url, "https://foo.com");
|
|
assert.equal(where, "window");
|
|
assert.propertyVal(params, "private", true);
|
|
assert.propertyVal(params, "forceForeground", false);
|
|
});
|
|
it("should call openTrustedLinkIn with the correct url, where and params on OPEN_LINK", () => {
|
|
const openTrustedLinkIn = sinon.stub();
|
|
const openLinkAction = {
|
|
type: at.OPEN_LINK,
|
|
data: { url: "https://foo.com" },
|
|
_target: {
|
|
browser: {
|
|
ownerGlobal: { openTrustedLinkIn, whereToOpenLink: e => "current" },
|
|
},
|
|
},
|
|
};
|
|
|
|
feed.onAction(openLinkAction);
|
|
|
|
assert.calledOnce(openTrustedLinkIn);
|
|
const [url, where, params] = openTrustedLinkIn.firstCall.args;
|
|
assert.equal(url, "https://foo.com");
|
|
assert.equal(where, "current");
|
|
assert.propertyVal(params, "private", false);
|
|
assert.propertyVal(params, "forceForeground", false);
|
|
});
|
|
it("should open link with referrer on OPEN_LINK", () => {
|
|
const openTrustedLinkIn = sinon.stub();
|
|
const openLinkAction = {
|
|
type: at.OPEN_LINK,
|
|
data: { url: "https://foo.com", referrer: "https://foo.com/ref" },
|
|
_target: {
|
|
browser: {
|
|
ownerGlobal: { openTrustedLinkIn, whereToOpenLink: e => "tab" },
|
|
},
|
|
},
|
|
};
|
|
|
|
feed.onAction(openLinkAction);
|
|
|
|
const [, , params] = openTrustedLinkIn.firstCall.args;
|
|
assert.nestedPropertyVal(params, "referrerInfo.referrerPolicy", 5);
|
|
assert.nestedPropertyVal(
|
|
params,
|
|
"referrerInfo.originalReferrer.spec",
|
|
"https://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 openTrustedLinkIn = sinon.stub().callsFake(() => {
|
|
callOrder.push("openTrustedLinkIn");
|
|
});
|
|
const openLinkAction = {
|
|
type: at.OPEN_LINK,
|
|
data: {
|
|
typedBonus: true,
|
|
url: "https://foo.com",
|
|
},
|
|
_target: {
|
|
browser: {
|
|
ownerGlobal: { openTrustedLinkIn, whereToOpenLink: e => "tab" },
|
|
},
|
|
},
|
|
};
|
|
|
|
feed.onAction(openLinkAction);
|
|
|
|
assert.sameOrderedMembers(callOrder, [
|
|
"markPageAsTyped",
|
|
"openTrustedLinkIn",
|
|
]);
|
|
});
|
|
it("should open the pocket link if it's a pocket story on OPEN_LINK", () => {
|
|
const openTrustedLinkIn = sinon.stub();
|
|
const openLinkAction = {
|
|
type: at.OPEN_LINK,
|
|
data: {
|
|
url: "https://foo.com",
|
|
open_url: "getpocket.com/foo",
|
|
type: "pocket",
|
|
},
|
|
_target: {
|
|
browser: {
|
|
ownerGlobal: { openTrustedLinkIn, whereToOpenLink: e => "current" },
|
|
},
|
|
},
|
|
};
|
|
|
|
feed.onAction(openLinkAction);
|
|
|
|
assert.calledOnce(openTrustedLinkIn);
|
|
const [url, where, params] = openTrustedLinkIn.firstCall.args;
|
|
assert.equal(url, "getpocket.com/foo");
|
|
assert.equal(where, "current");
|
|
assert.propertyVal(params, "private", false);
|
|
});
|
|
it("should not open link if not http", () => {
|
|
const openTrustedLinkIn = sinon.stub();
|
|
global.Services.io.newURI = spec => ({
|
|
mutate: () => ({
|
|
setRef: ref => ({
|
|
finalize: () => ({
|
|
ref,
|
|
spec,
|
|
}),
|
|
}),
|
|
}),
|
|
spec,
|
|
scheme: "file",
|
|
});
|
|
const openLinkAction = {
|
|
type: at.OPEN_LINK,
|
|
data: { url: "file:///foo.com" },
|
|
_target: {
|
|
browser: {
|
|
ownerGlobal: { openTrustedLinkIn, whereToOpenLink: e => "current" },
|
|
},
|
|
},
|
|
};
|
|
|
|
feed.onAction(openLinkAction);
|
|
const [e] = global.console.error.firstCall.args;
|
|
assert.equal(
|
|
e.message,
|
|
"Can't open link using file protocol from the new tab page."
|
|
);
|
|
});
|
|
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 call openTrustedLinkIn with the correct SUMO url on ABOUT_SPONSORED_TOP_SITES", () => {
|
|
const openTrustedLinkIn = sinon.stub();
|
|
const openLinkAction = {
|
|
type: at.ABOUT_SPONSORED_TOP_SITES,
|
|
_target: {
|
|
browser: {
|
|
ownerGlobal: { openTrustedLinkIn },
|
|
},
|
|
},
|
|
};
|
|
|
|
feed.onAction(openLinkAction);
|
|
|
|
assert.calledOnce(openTrustedLinkIn);
|
|
const [url, where] = openTrustedLinkIn.firstCall.args;
|
|
assert.equal(url.endsWith("sponsor-privacy"), true);
|
|
assert.equal(where, "tab");
|
|
});
|
|
it("should set the URL bar value to the label value", async () => {
|
|
const locationBar = { search: sandbox.stub() };
|
|
const action = {
|
|
type: at.FILL_SEARCH_TERM,
|
|
data: { label: "@Foo" },
|
|
_target: { browser: { ownerGlobal: { gURLBar: locationBar } } },
|
|
};
|
|
|
|
await feed.fillSearchTopSiteTerm(action);
|
|
|
|
assert.calledOnce(locationBar.search);
|
|
assert.calledWithExactly(locationBar.search, "@Foo", {
|
|
searchEngine: null,
|
|
searchModeEntry: "topsites_newtab",
|
|
});
|
|
});
|
|
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 openTrustedLinkIn with sendToPocket if not logged in", () => {
|
|
const openTrustedLinkIn = sinon.stub();
|
|
global.NimbusFeatures.pocketNewtab.getVariable = sandbox
|
|
.stub()
|
|
.returns(true);
|
|
global.pktApi.isUserLoggedIn = sandbox.stub().returns(false);
|
|
global.ExperimentAPI.getExperiment = sandbox.stub().returns({
|
|
slug: "slug",
|
|
branch: { slug: "branch-slug" },
|
|
});
|
|
sandbox
|
|
.stub(global.Services.prefs, "getStringPref")
|
|
.withArgs(POCKET_SITE_PREF)
|
|
.returns("getpocket.com");
|
|
const action = {
|
|
type: at.SAVE_TO_POCKET,
|
|
data: { site: { url: "raspberry.com", title: "raspberry" } },
|
|
_target: {
|
|
browser: {
|
|
ownerGlobal: {
|
|
openTrustedLinkIn,
|
|
},
|
|
},
|
|
},
|
|
};
|
|
feed.onAction(action);
|
|
assert.calledOnce(openTrustedLinkIn);
|
|
const [url, where] = openTrustedLinkIn.firstCall.args;
|
|
assert.equal(
|
|
url,
|
|
"https://getpocket.com/signup?utm_source=firefox_newtab_save_button&utm_campaign=slug&utm_content=branch-slug"
|
|
);
|
|
assert.equal(where, "tab");
|
|
});
|
|
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.console.error, 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.console.error, 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.console.error, 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);
|
|
});
|
|
it("should call makeAttributionRequest on PARTNER_LINK_ATTRIBUTION", () => {
|
|
sinon.stub(feed, "makeAttributionRequest");
|
|
let data = { targetURL: "https://partnersite.com", source: "topsites" };
|
|
feed.onAction({
|
|
type: at.PARTNER_LINK_ATTRIBUTION,
|
|
data,
|
|
});
|
|
|
|
assert.calledOnce(feed.makeAttributionRequest);
|
|
assert.calledWithExactly(feed.makeAttributionRequest, data);
|
|
});
|
|
it("should call PartnerLinkAttribution.makeRequest when calling makeAttributionRequest", () => {
|
|
let data = { targetURL: "https://partnersite.com", source: "topsites" };
|
|
feed.makeAttributionRequest(data);
|
|
assert.calledOnce(global.PartnerLinkAttribution.makeRequest);
|
|
});
|
|
});
|
|
|
|
describe("handoffSearchToAwesomebar", () => {
|
|
let fakeUrlBar;
|
|
let listeners;
|
|
|
|
beforeEach(() => {
|
|
fakeUrlBar = {
|
|
focus: sinon.spy(),
|
|
handoff: 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.handoff);
|
|
assert.notCalled(feed.store.dispatch);
|
|
|
|
// Now type a character.
|
|
listeners.keydown({ key: "f" });
|
|
assert.calledOnce(fakeUrlBar.handoff);
|
|
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: "DISABLE_SEARCH",
|
|
});
|
|
});
|
|
it("should properly handle handoff with text data passed in", () => {
|
|
const sessionId = "decafc0ffee";
|
|
sandbox
|
|
.stub(global.AboutNewTab.activityStream.store.feeds, "get")
|
|
.returns({
|
|
sessions: {
|
|
get: () => {
|
|
return { session_id: sessionId };
|
|
},
|
|
},
|
|
});
|
|
feed.handoffSearchToAwesomebar({
|
|
_target: { browser: { ownerGlobal: { gURLBar: fakeUrlBar } } },
|
|
data: { text: "foo" },
|
|
meta: { fromTarget: {} },
|
|
});
|
|
assert.calledOnce(fakeUrlBar.handoff);
|
|
assert.calledWithExactly(
|
|
fakeUrlBar.handoff,
|
|
"foo",
|
|
global.Services.search.defaultEngine,
|
|
sessionId
|
|
);
|
|
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 properly handle handoff with text data passed in, in private browsing mode", () => {
|
|
global.PrivateBrowsingUtils.isBrowserPrivate = () => true;
|
|
feed.handoffSearchToAwesomebar({
|
|
_target: { browser: { ownerGlobal: { gURLBar: fakeUrlBar } } },
|
|
data: { text: "foo" },
|
|
meta: { fromTarget: {} },
|
|
});
|
|
assert.calledOnce(fakeUrlBar.handoff);
|
|
assert.calledWithExactly(
|
|
fakeUrlBar.handoff,
|
|
"foo",
|
|
global.Services.search.defaultPrivateEngine,
|
|
undefined
|
|
);
|
|
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",
|
|
});
|
|
global.PrivateBrowsingUtils.isBrowserPrivate = () => false;
|
|
});
|
|
it("should SHOW_SEARCH on ESC keydown", () => {
|
|
feed.handoffSearchToAwesomebar({
|
|
_target: { browser: { ownerGlobal: { gURLBar: fakeUrlBar } } },
|
|
data: { text: "foo" },
|
|
meta: { fromTarget: {} },
|
|
});
|
|
assert.calledOnce(fakeUrlBar.handoff);
|
|
assert.calledWithExactly(
|
|
fakeUrlBar.handoff,
|
|
"foo",
|
|
global.Services.search.defaultEngine,
|
|
undefined
|
|
);
|
|
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 handoff a newtab session id with no text passed in", () => {
|
|
const sessionId = "decafc0ffee";
|
|
sandbox
|
|
.stub(global.AboutNewTab.activityStream.store.feeds, "get")
|
|
.returns({
|
|
sessions: {
|
|
get: () => {
|
|
return { session_id: sessionId };
|
|
},
|
|
},
|
|
});
|
|
feed.handoffSearchToAwesomebar({
|
|
_target: { browser: { ownerGlobal: { gURLBar: fakeUrlBar } } },
|
|
data: {},
|
|
meta: { fromTarget: {} },
|
|
});
|
|
assert.calledOnce(fakeUrlBar.setHiddenFocus);
|
|
assert.notCalled(fakeUrlBar.handoff);
|
|
assert.notCalled(feed.store.dispatch);
|
|
|
|
// Now type a character.
|
|
listeners.keydown({ key: "f" });
|
|
assert.calledOnce(fakeUrlBar.handoff);
|
|
assert.calledWithExactly(
|
|
fakeUrlBar.handoff,
|
|
"",
|
|
global.Services.search.defaultEngine,
|
|
sessionId
|
|
);
|
|
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: "DISABLE_SEARCH",
|
|
});
|
|
});
|
|
});
|
|
|
|
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("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,
|
|
type: "bookmark-added",
|
|
},
|
|
];
|
|
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 = [
|
|
{
|
|
id: null,
|
|
parentId: null,
|
|
index: null,
|
|
itemType: TYPE_BOOKMARK,
|
|
url: "foo.com",
|
|
guid: "123foo",
|
|
parentGuid: "",
|
|
source: SOURCES.DEFAULT,
|
|
type: "bookmark-removed",
|
|
},
|
|
];
|
|
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 any page-removed notifications happened at once", async () => {
|
|
await feed.placesObserver.handlePlacesEvent([
|
|
{ type: "page-removed", url: "foo.com", isRemovedFromStore: true },
|
|
]);
|
|
await feed.placesObserver.handlePlacesEvent([
|
|
{ type: "page-removed", url: "foo1.com", isRemovedFromStore: true },
|
|
]);
|
|
await feed.placesObserver.handlePlacesEvent([
|
|
{ type: "page-removed", url: "foo2.com", isRemovedFromStore: true },
|
|
]);
|
|
|
|
assert.calledOnce(
|
|
feed.store.dispatch.withArgs(
|
|
ac.OnlyToMain({ type: at.PLACES_LINKS_CHANGED })
|
|
)
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("PlacesObserver", () => {
|
|
let dispatch;
|
|
let observer;
|
|
beforeEach(() => {
|
|
dispatch = sandbox.spy();
|
|
observer = new PlacesObserver(dispatch);
|
|
});
|
|
|
|
describe("#history-cleared", () => {
|
|
it("should dispatch a PLACES_HISTORY_CLEARED action", async () => {
|
|
const args = [{ type: "history-cleared" }];
|
|
await observer.handlePlacesEvent(args);
|
|
assert.calledWith(dispatch, { type: at.PLACES_HISTORY_CLEARED });
|
|
});
|
|
});
|
|
|
|
describe("#page-removed", () => {
|
|
it("should dispatch a PLACES_LINKS_DELETED action with the right url", async () => {
|
|
const args = [
|
|
{
|
|
type: "page-removed",
|
|
url: "foo.com",
|
|
isRemovedFromStore: true,
|
|
},
|
|
];
|
|
await observer.handlePlacesEvent(args);
|
|
assert.calledWith(dispatch, {
|
|
type: at.PLACES_LINKS_DELETED,
|
|
data: { urls: ["foo.com"] },
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("#bookmark-added", () => {
|
|
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,
|
|
type: "bookmark-added",
|
|
},
|
|
];
|
|
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,
|
|
type: "bookmark-added",
|
|
},
|
|
];
|
|
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,
|
|
type: "bookmark-added",
|
|
},
|
|
];
|
|
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,
|
|
type: "bookmark-added",
|
|
},
|
|
];
|
|
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,
|
|
type: "bookmark-added",
|
|
},
|
|
];
|
|
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,
|
|
type: "bookmark-added",
|
|
},
|
|
];
|
|
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,
|
|
type: "bookmark-added",
|
|
},
|
|
];
|
|
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,
|
|
type: "bookmark-added",
|
|
},
|
|
];
|
|
await observer.handlePlacesEvent(args);
|
|
|
|
assert.notCalled(dispatch);
|
|
});
|
|
});
|
|
describe("#bookmark-removed", () => {
|
|
it("should ignore events that are not of TYPE_BOOKMARK", async () => {
|
|
const args = [
|
|
{
|
|
id: null,
|
|
parentId: null,
|
|
index: null,
|
|
itemType: "nottypebookmark",
|
|
url: null,
|
|
guid: "123foo",
|
|
parentGuid: "",
|
|
source: SOURCES.DEFAULT,
|
|
type: "bookmark-removed",
|
|
},
|
|
];
|
|
await observer.handlePlacesEvent(args);
|
|
assert.notCalled(dispatch);
|
|
});
|
|
it("should not dispatch a PLACES_BOOKMARKS_REMOVED action - has SYNC source", async () => {
|
|
const args = [
|
|
{
|
|
id: null,
|
|
parentId: null,
|
|
index: null,
|
|
itemType: TYPE_BOOKMARK,
|
|
url: "foo.com",
|
|
guid: "123foo",
|
|
parentGuid: "",
|
|
source: SOURCES.SYNC,
|
|
type: "bookmark-removed",
|
|
},
|
|
];
|
|
await observer.handlePlacesEvent(args);
|
|
|
|
assert.notCalled(dispatch);
|
|
});
|
|
it("should not dispatch a PLACES_BOOKMARKS_REMOVED action - has IMPORT source", async () => {
|
|
const args = [
|
|
{
|
|
id: null,
|
|
parentId: null,
|
|
index: null,
|
|
itemType: TYPE_BOOKMARK,
|
|
url: "foo.com",
|
|
guid: "123foo",
|
|
parentGuid: "",
|
|
source: SOURCES.IMPORT,
|
|
type: "bookmark-removed",
|
|
},
|
|
];
|
|
await observer.handlePlacesEvent(args);
|
|
|
|
assert.notCalled(dispatch);
|
|
});
|
|
it("should not dispatch a PLACES_BOOKMARKS_REMOVED action - has RESTORE source", async () => {
|
|
const args = [
|
|
{
|
|
id: null,
|
|
parentId: null,
|
|
index: null,
|
|
itemType: TYPE_BOOKMARK,
|
|
url: "foo.com",
|
|
guid: "123foo",
|
|
parentGuid: "",
|
|
source: SOURCES.RESTORE,
|
|
type: "bookmark-removed",
|
|
},
|
|
];
|
|
await observer.handlePlacesEvent(args);
|
|
|
|
assert.notCalled(dispatch);
|
|
});
|
|
it("should not dispatch a PLACES_BOOKMARKS_REMOVED action - has RESTORE_ON_STARTUP source", async () => {
|
|
const args = [
|
|
{
|
|
id: null,
|
|
parentId: null,
|
|
index: null,
|
|
itemType: TYPE_BOOKMARK,
|
|
url: "foo.com",
|
|
guid: "123foo",
|
|
parentGuid: "",
|
|
source: SOURCES.RESTORE_ON_STARTUP,
|
|
type: "bookmark-removed",
|
|
},
|
|
];
|
|
await observer.handlePlacesEvent(args);
|
|
|
|
assert.notCalled(dispatch);
|
|
});
|
|
it("should dispatch a PLACES_BOOKMARKS_REMOVED action with the right URL and bookmarkGuid", async () => {
|
|
const args = [
|
|
{
|
|
id: null,
|
|
parentId: null,
|
|
index: null,
|
|
itemType: TYPE_BOOKMARK,
|
|
url: "foo.com",
|
|
guid: "123foo",
|
|
parentGuid: "",
|
|
source: SOURCES.DEFAULT,
|
|
type: "bookmark-removed",
|
|
},
|
|
];
|
|
await observer.handlePlacesEvent(args);
|
|
assert.calledWith(dispatch, {
|
|
type: at.PLACES_BOOKMARKS_REMOVED,
|
|
data: { urls: ["foo.com"] },
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|