diff options
Diffstat (limited to 'browser/components/syncedtabs')
12 files changed, 0 insertions, 1224 deletions
diff --git a/browser/components/syncedtabs/test/browser/.eslintrc.js b/browser/components/syncedtabs/test/browser/.eslintrc.js deleted file mode 100644 index 7c8021192..000000000 --- a/browser/components/syncedtabs/test/browser/.eslintrc.js +++ /dev/null @@ -1,7 +0,0 @@ -"use strict"; - -module.exports = { - "extends": [ - "../../../../../testing/mochitest/browser.eslintrc.js" - ] -}; diff --git a/browser/components/syncedtabs/test/browser/browser.ini b/browser/components/syncedtabs/test/browser/browser.ini deleted file mode 100644 index 02fa364f1..000000000 --- a/browser/components/syncedtabs/test/browser/browser.ini +++ /dev/null @@ -1,4 +0,0 @@ -[DEFAULT] -support-files = head.js - -[browser_sidebar_syncedtabslist.js] diff --git a/browser/components/syncedtabs/test/browser/browser_sidebar_syncedtabslist.js b/browser/components/syncedtabs/test/browser/browser_sidebar_syncedtabslist.js deleted file mode 100644 index afbc00282..000000000 --- a/browser/components/syncedtabs/test/browser/browser_sidebar_syncedtabslist.js +++ /dev/null @@ -1,410 +0,0 @@ -"use strict"; - -const FIXTURE = [ - { - "id": "7cqCr77ptzX3", - "type": "client", - "name": "zcarter's Nightly on MacBook-Pro-25", - "isMobile": false, - "tabs": [ - { - "type": "tab", - "title": "Firefox for Android — Mobile Web browser — More ways to customize and protect your privacy — Mozilla", - "url": "https://www.mozilla.org/en-US/firefox/android/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=synced-tabs-sidebar", - "icon": "chrome://mozapps/skin/places/defaultFavicon.png", - "client": "7cqCr77ptzX3", - "lastUsed": 1452124677 - } - ] - }, - { - "id": "2xU5h-4bkWqA", - "type": "client", - "name": "laptop", - "isMobile": false, - "tabs": [ - { - "type": "tab", - "title": "Firefox for iOS — Mobile Web browser for your iPhone, iPad and iPod touch — Mozilla", - "url": "https://www.mozilla.org/en-US/firefox/ios/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=synced-tabs-sidebar", - "icon": "moz-anno:favicon:https://www.mozilla.org/media/img/firefox/favicon.dc6635050bf5.ico", - "client": "2xU5h-4bkWqA", - "lastUsed": 1451519425 - }, - { - "type": "tab", - "title": "Firefox Nightly First Run Page", - "url": "https://www.mozilla.org/en-US/firefox/nightly/firstrun/?oldversion=45.0a1", - "icon": "moz-anno:favicon:https://www.mozilla.org/media/img/firefox/favicon-nightly.560395bbb2e1.png", - "client": "2xU5h-4bkWqA", - "lastUsed": 1451519420 - }, - { - // Should appear first for this client. - "type": "tab", - "title": "Mozilla Developer Network", - "url": "https://developer.mozilla.org/en-US/", - "icon": "moz-anno:favicon:https://developer.cdn.mozilla.net/static/img/favicon32.e02854fdcf73.png", - "client": "2xU5h-4bkWqA", - "lastUsed": 1451519725 - } - ] - }, - { - "id": "OL3EJCsdb2JD", - "type": "client", - "name": "desktop", - "isMobile": false, - "tabs": [] - } -]; - -let originalSyncedTabsInternal = null; - -function* testClean() { - let syncedTabsDeckComponent = window.SidebarUI.browser.contentWindow.syncedTabsDeckComponent; - let SyncedTabs = window.SidebarUI.browser.contentWindow.SyncedTabs; - syncedTabsDeckComponent._accountStatus.restore(); - SyncedTabs._internal.getTabClients.restore(); - SyncedTabs._internal = originalSyncedTabsInternal; - - yield new Promise(resolve => { - window.SidebarUI.browser.contentWindow.addEventListener("unload", function listener() { - window.SidebarUI.browser.contentWindow.removeEventListener("unload", listener); - resolve(); - }); - SidebarUI.hide(); - }); -} - -add_task(function* testSyncedTabsSidebarList() { - yield SidebarUI.show('viewTabsSidebar'); - - Assert.equal(SidebarUI.currentID, "viewTabsSidebar", "Sidebar should have SyncedTabs loaded"); - - let syncedTabsDeckComponent = SidebarUI.browser.contentWindow.syncedTabsDeckComponent; - let SyncedTabs = SidebarUI.browser.contentWindow.SyncedTabs; - - Assert.ok(syncedTabsDeckComponent, "component exists"); - - originalSyncedTabsInternal = SyncedTabs._internal; - SyncedTabs._internal = { - isConfiguredToSyncTabs: true, - hasSyncedThisSession: true, - getTabClients() { return Promise.resolve([]) }, - syncTabs() { return Promise.resolve(); }, - }; - - sinon.stub(syncedTabsDeckComponent, "_accountStatus", () => Promise.resolve(true)); - sinon.stub(SyncedTabs._internal, "getTabClients", () => Promise.resolve(Cu.cloneInto(FIXTURE, {}))); - - yield syncedTabsDeckComponent.updatePanel(); - // This is a hacky way of waiting for the view to render. The view renders - // after the following promise (a different instance of which is triggered - // in updatePanel) resolves, so we wait for it here as well - yield syncedTabsDeckComponent.tabListComponent._store.getData(); - - Assert.ok(SyncedTabs._internal.getTabClients.called, "get clients called"); - - let selectedPanel = syncedTabsDeckComponent.container.querySelector(".sync-state.selected"); - - - Assert.ok(selectedPanel.classList.contains("tabs-container"), - "tabs panel is selected"); - - Assert.equal(selectedPanel.querySelectorAll(".tab").length, 4, - "four tabs listed"); - Assert.equal(selectedPanel.querySelectorAll(".client").length, 3, - "three clients listed"); - Assert.equal(selectedPanel.querySelectorAll(".client")[2].querySelectorAll(".empty").length, 1, - "third client is empty"); - - // Verify that the tabs are sorted by last used time. - var expectedTabIndices = [[0], [2, 0, 1]]; - Array.prototype.forEach.call(selectedPanel.querySelectorAll(".client"), (clientNode, i) => { - checkItem(clientNode, FIXTURE[i]); - Array.prototype.forEach.call(clientNode.querySelectorAll(".tab"), (tabNode, j) => { - let tabIndex = expectedTabIndices[i][j]; - checkItem(tabNode, FIXTURE[i].tabs[tabIndex]); - }); - }); - -}); - -add_task(testClean); - -add_task(function* testSyncedTabsSidebarFilteredList() { - yield SidebarUI.show('viewTabsSidebar'); - let syncedTabsDeckComponent = window.SidebarUI.browser.contentWindow.syncedTabsDeckComponent; - let SyncedTabs = window.SidebarUI.browser.contentWindow.SyncedTabs; - - Assert.ok(syncedTabsDeckComponent, "component exists"); - - originalSyncedTabsInternal = SyncedTabs._internal; - SyncedTabs._internal = { - isConfiguredToSyncTabs: true, - hasSyncedThisSession: true, - getTabClients() { return Promise.resolve([]) }, - syncTabs() { return Promise.resolve(); }, - }; - - sinon.stub(syncedTabsDeckComponent, "_accountStatus", () => Promise.resolve(true)); - sinon.stub(SyncedTabs._internal, "getTabClients", () => Promise.resolve(Cu.cloneInto(FIXTURE, {}))); - - yield syncedTabsDeckComponent.updatePanel(); - // This is a hacky way of waiting for the view to render. The view renders - // after the following promise (a different instance of which is triggered - // in updatePanel) resolves, so we wait for it here as well - yield syncedTabsDeckComponent.tabListComponent._store.getData(); - - let filterInput = syncedTabsDeckComponent._window.document.querySelector(".tabsFilter"); - filterInput.value = "filter text"; - filterInput.blur(); - - yield syncedTabsDeckComponent.tabListComponent._store.getData("filter text"); - - let selectedPanel = syncedTabsDeckComponent.container.querySelector(".sync-state.selected"); - Assert.ok(selectedPanel.classList.contains("tabs-container"), - "tabs panel is selected"); - - Assert.equal(selectedPanel.querySelectorAll(".tab").length, 4, - "four tabs listed"); - Assert.equal(selectedPanel.querySelectorAll(".client").length, 0, - "no clients are listed"); - - Assert.equal(filterInput.value, "filter text", - "filter text box has correct value"); - - // Tabs should not be sorted when filter is active. - let FIXTURE_TABS = FIXTURE.reduce((prev, client) => prev.concat(client.tabs), []); - - Array.prototype.forEach.call(selectedPanel.querySelectorAll(".tab"), (tabNode, i) => { - checkItem(tabNode, FIXTURE_TABS[i]); - }); - - // Removing the filter should resort tabs. - FIXTURE_TABS.sort((a, b) => b.lastUsed - a.lastUsed); - yield syncedTabsDeckComponent.tabListComponent._store.getData(); - Array.prototype.forEach.call(selectedPanel.querySelectorAll(".tab"), (tabNode, i) => { - checkItem(tabNode, FIXTURE_TABS[i]); - }); -}); - -add_task(testClean); - -add_task(function* testSyncedTabsSidebarStatus() { - let accountExists = false; - - yield SidebarUI.show('viewTabsSidebar'); - let syncedTabsDeckComponent = window.SidebarUI.browser.contentWindow.syncedTabsDeckComponent; - let SyncedTabs = window.SidebarUI.browser.contentWindow.SyncedTabs; - - originalSyncedTabsInternal = SyncedTabs._internal; - SyncedTabs._internal = { - isConfiguredToSyncTabs: false, - hasSyncedThisSession: false, - getTabClients() {}, - syncTabs() { return Promise.resolve(); }, - }; - - Assert.ok(syncedTabsDeckComponent, "component exists"); - - sinon.spy(syncedTabsDeckComponent, "updatePanel"); - sinon.spy(syncedTabsDeckComponent, "observe"); - - sinon.stub(syncedTabsDeckComponent, "_accountStatus", () => Promise.reject("Test error")); - yield syncedTabsDeckComponent.updatePanel(); - - let selectedPanel = syncedTabsDeckComponent.container.querySelector(".sync-state.selected"); - Assert.ok(selectedPanel.classList.contains("notAuthedInfo"), - "not-authed panel is selected on auth error"); - - syncedTabsDeckComponent._accountStatus.restore(); - sinon.stub(syncedTabsDeckComponent, "_accountStatus", () => Promise.resolve(accountExists)); - yield syncedTabsDeckComponent.updatePanel(); - selectedPanel = syncedTabsDeckComponent.container.querySelector(".sync-state.selected"); - Assert.ok(selectedPanel.classList.contains("notAuthedInfo"), - "not-authed panel is selected"); - - accountExists = true; - yield syncedTabsDeckComponent.updatePanel(); - selectedPanel = syncedTabsDeckComponent.container.querySelector(".sync-state.selected"); - Assert.ok(selectedPanel.classList.contains("tabs-disabled"), - "tabs disabled panel is selected"); - - SyncedTabs._internal.isConfiguredToSyncTabs = true; - yield syncedTabsDeckComponent.updatePanel(); - selectedPanel = syncedTabsDeckComponent.container.querySelector(".sync-state.selected"); - Assert.ok(selectedPanel.classList.contains("tabs-fetching"), - "tabs fetch panel is selected"); - - SyncedTabs._internal.hasSyncedThisSession = true; - sinon.stub(SyncedTabs._internal, "getTabClients", () => Promise.resolve([])); - yield syncedTabsDeckComponent.updatePanel(); - selectedPanel = syncedTabsDeckComponent.container.querySelector(".sync-state.selected"); - Assert.ok(selectedPanel.classList.contains("singleDeviceInfo"), - "tabs fetch panel is selected"); - - SyncedTabs._internal.getTabClients.restore(); - sinon.stub(SyncedTabs._internal, "getTabClients", () => Promise.resolve([{id: "mock"}])); - yield syncedTabsDeckComponent.updatePanel(); - selectedPanel = syncedTabsDeckComponent.container.querySelector(".sync-state.selected"); - Assert.ok(selectedPanel.classList.contains("tabs-container"), - "tabs panel is selected"); -}); - -add_task(testClean); - -add_task(function* testSyncedTabsSidebarContextMenu() { - yield SidebarUI.show('viewTabsSidebar'); - let syncedTabsDeckComponent = window.SidebarUI.browser.contentWindow.syncedTabsDeckComponent; - let SyncedTabs = window.SidebarUI.browser.contentWindow.SyncedTabs; - - Assert.ok(syncedTabsDeckComponent, "component exists"); - - originalSyncedTabsInternal = SyncedTabs._internal; - SyncedTabs._internal = { - isConfiguredToSyncTabs: true, - hasSyncedThisSession: true, - getTabClients() { return Promise.resolve([]) }, - syncTabs() { return Promise.resolve(); }, - }; - - sinon.stub(syncedTabsDeckComponent, "_accountStatus", () => Promise.resolve(true)); - sinon.stub(SyncedTabs._internal, "getTabClients", () => Promise.resolve(Cu.cloneInto(FIXTURE, {}))); - - yield syncedTabsDeckComponent.updatePanel(); - // This is a hacky way of waiting for the view to render. The view renders - // after the following promise (a different instance of which is triggered - // in updatePanel) resolves, so we wait for it here as well - yield syncedTabsDeckComponent.tabListComponent._store.getData(); - - info("Right-clicking the search box should show text-related actions"); - let filterMenuItems = [ - "menuitem[cmd=cmd_undo]", - "menuseparator", - // We don't check whether the commands are enabled due to platform - // differences. On OS X and Windows, "cut" and "copy" are always enabled - // for HTML inputs; on Linux, they're only enabled if text is selected. - "menuitem[cmd=cmd_cut]", - "menuitem[cmd=cmd_copy]", - "menuitem[cmd=cmd_paste]", - "menuitem[cmd=cmd_delete]", - "menuseparator", - "menuitem[cmd=cmd_selectAll]", - "menuseparator", - "menuitem#syncedTabsRefreshFilter", - ]; - yield* testContextMenu(syncedTabsDeckComponent, - "#SyncedTabsSidebarTabsFilterContext", - ".tabsFilter", - filterMenuItems); - - info("Right-clicking a tab should show additional actions"); - let tabMenuItems = [ - ["menuitem#syncedTabsOpenSelected", { hidden: false }], - ["menuitem#syncedTabsOpenSelectedInTab", { hidden: false }], - ["menuitem#syncedTabsOpenSelectedInWindow", { hidden: false }], - ["menuitem#syncedTabsOpenSelectedInPrivateWindow", { hidden: false }], - ["menuseparator", { hidden: false }], - ["menuitem#syncedTabsBookmarkSelected", { hidden: false }], - ["menuitem#syncedTabsCopySelected", { hidden: false }], - ["menuseparator", { hidden: false }], - ["menuitem#syncedTabsRefresh", { hidden: false }], - ]; - yield* testContextMenu(syncedTabsDeckComponent, - "#SyncedTabsSidebarContext", - "#tab-7cqCr77ptzX3-0", - tabMenuItems); - - info("Right-clicking a client shouldn't show any actions"); - let sidebarMenuItems = [ - ["menuitem#syncedTabsOpenSelected", { hidden: true }], - ["menuitem#syncedTabsOpenSelectedInTab", { hidden: true }], - ["menuitem#syncedTabsOpenSelectedInWindow", { hidden: true }], - ["menuitem#syncedTabsOpenSelectedInPrivateWindow", { hidden: true }], - ["menuseparator", { hidden: true }], - ["menuitem#syncedTabsBookmarkSelected", { hidden: true }], - ["menuitem#syncedTabsCopySelected", { hidden: true }], - ["menuseparator", { hidden: true }], - ["menuitem#syncedTabsRefresh", { hidden: false }], - ]; - yield* testContextMenu(syncedTabsDeckComponent, - "#SyncedTabsSidebarContext", - "#item-OL3EJCsdb2JD", - sidebarMenuItems); -}); - -add_task(testClean); - -function checkItem(node, item) { - Assert.ok(node.classList.contains("item"), - "Node should have .item class"); - if (item.client) { - // tab items - Assert.equal(node.querySelector(".item-title").textContent, item.title, - "Node's title element's text should match item title"); - Assert.ok(node.classList.contains("tab"), - "Node should have .tab class"); - Assert.equal(node.dataset.url, item.url, - "Node's URL should match item URL"); - Assert.equal(node.getAttribute("title"), item.title + "\n" + item.url, - "Tab node should have correct title attribute"); - } else { - // client items - Assert.equal(node.querySelector(".item-title").textContent, item.name, - "Node's title element's text should match client name"); - Assert.ok(node.classList.contains("client"), - "Node should have .client class"); - Assert.equal(node.dataset.id, item.id, - "Node's ID should match item ID"); - } -} - -function* testContextMenu(syncedTabsDeckComponent, contextSelector, triggerSelector, menuSelectors) { - let contextMenu = document.querySelector(contextSelector); - let triggerElement = syncedTabsDeckComponent._window.document.querySelector(triggerSelector); - let isClosed = triggerElement.classList.contains("closed"); - - let promisePopupShown = BrowserTestUtils.waitForEvent(contextMenu, "popupshown"); - - let chromeWindow = triggerElement.ownerGlobal.top; - let rect = triggerElement.getBoundingClientRect(); - let contentRect = chromeWindow.SidebarUI.browser.getBoundingClientRect(); - // The offsets in `rect` are relative to the content window, but - // `synthesizeMouseAtPoint` calls `nsIDOMWindowUtils.sendMouseEvent`, - // which interprets the offsets relative to the containing *chrome* window. - // This means we need to account for the width and height of any elements - // outside the `browser` element, like `sidebarheader`. - let offsetX = contentRect.x + rect.x + (rect.width / 2); - let offsetY = contentRect.y + rect.y + (rect.height / 4); - - yield EventUtils.synthesizeMouseAtPoint(offsetX, offsetY, { - type: "contextmenu", - button: 2, - }, chromeWindow); - yield promisePopupShown; - is(triggerElement.classList.contains("closed"), isClosed, - "Showing the context menu shouldn't toggle the tab list"); - checkChildren(contextMenu, menuSelectors); - - let promisePopupHidden = BrowserTestUtils.waitForEvent(contextMenu, "popuphidden"); - contextMenu.hidePopup(); - yield promisePopupHidden; -} - -function checkChildren(node, selectors) { - is(node.children.length, selectors.length, "Menu item count doesn't match"); - for (let index = 0; index < node.children.length; index++) { - let child = node.children[index]; - let [selector, props] = [].concat(selectors[index]); - ok(selector, `Node at ${index} should have selector`); - ok(child.matches(selector), `Node ${ - index} should match ${selector}`); - if (props) { - Object.keys(props).forEach(prop => { - is(child[prop], props[prop], `${prop} value at ${index} should match`); - }); - } - } -} diff --git a/browser/components/syncedtabs/test/browser/head.js b/browser/components/syncedtabs/test/browser/head.js deleted file mode 100644 index 40e36123e..000000000 --- a/browser/components/syncedtabs/test/browser/head.js +++ /dev/null @@ -1,19 +0,0 @@ -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/Promise.jsm"); - - -// Load mocking/stubbing library, sinon -// docs: http://sinonjs.org/docs/ -/* global sinon */ -let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader); -loader.loadSubScript("resource://testing-common/sinon-1.16.1.js"); - -registerCleanupFunction(function*() { - // Cleanup window or the test runner will throw an error - delete window.sinon; - delete window.setImmediate; - delete window.clearImmediate; -}); diff --git a/browser/components/syncedtabs/test/xpcshell/.eslintrc.js b/browser/components/syncedtabs/test/xpcshell/.eslintrc.js deleted file mode 100644 index d35787cd2..000000000 --- a/browser/components/syncedtabs/test/xpcshell/.eslintrc.js +++ /dev/null @@ -1,7 +0,0 @@ -"use strict"; - -module.exports = { - "extends": [ - "../../../../../testing/xpcshell/xpcshell.eslintrc.js" - ] -}; diff --git a/browser/components/syncedtabs/test/xpcshell/head.js b/browser/components/syncedtabs/test/xpcshell/head.js deleted file mode 100644 index 00055231c..000000000 --- a/browser/components/syncedtabs/test/xpcshell/head.js +++ /dev/null @@ -1,29 +0,0 @@ -const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); - -XPCOMUtils.defineLazyGetter(this, "FxAccountsCommon", function () { - return Components.utils.import("resource://gre/modules/FxAccountsCommon.js", {}); -}); - -Cu.import("resource://gre/modules/Timer.jsm"); - -do_get_profile(); // fxa needs a profile directory for storage. - -// Create a window polyfill so sinon can load -let window = { - document: {}, - location: {}, - setTimeout: setTimeout, - setInterval: setInterval, - clearTimeout: clearTimeout, - clearinterval: clearInterval -}; -let self = window; - -// Load mocking/stubbing library, sinon -// docs: http://sinonjs.org/docs/ -/* global sinon */ -let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader); -loader.loadSubScript("resource://testing-common/sinon-1.16.1.js"); diff --git a/browser/components/syncedtabs/test/xpcshell/test_EventEmitter.js b/browser/components/syncedtabs/test/xpcshell/test_EventEmitter.js deleted file mode 100644 index bc73ac621..000000000 --- a/browser/components/syncedtabs/test/xpcshell/test_EventEmitter.js +++ /dev/null @@ -1,35 +0,0 @@ -"use strict"; - -let { EventEmitter } = Cu.import("resource:///modules/syncedtabs/EventEmitter.jsm", {}); - -add_task(function* testSingleListener() { - let eventEmitter = new EventEmitter(); - let spy = sinon.spy(); - - eventEmitter.on("click", spy); - eventEmitter.emit("click", "foo", "bar"); - Assert.ok(spy.calledOnce); - Assert.ok(spy.calledWith("foo", "bar")); - - eventEmitter.off("click", spy); - eventEmitter.emit("click"); - Assert.ok(spy.calledOnce); -}); - -add_task(function* testMultipleListeners() { - let eventEmitter = new EventEmitter(); - let spy1 = sinon.spy(); - let spy2 = sinon.spy(); - - eventEmitter.on("some_event", spy1); - eventEmitter.on("some_event", spy2); - eventEmitter.emit("some_event"); - Assert.ok(spy1.calledOnce); - Assert.ok(spy2.calledOnce); - - eventEmitter.off("some_event", spy1); - eventEmitter.emit("some_event"); - Assert.ok(spy1.calledOnce); - Assert.ok(spy2.calledTwice); -}); - diff --git a/browser/components/syncedtabs/test/xpcshell/test_SyncedTabsDeckComponent.js b/browser/components/syncedtabs/test/xpcshell/test_SyncedTabsDeckComponent.js deleted file mode 100644 index 3d748b33c..000000000 --- a/browser/components/syncedtabs/test/xpcshell/test_SyncedTabsDeckComponent.js +++ /dev/null @@ -1,218 +0,0 @@ -"use strict"; - -let { SyncedTabs } = Cu.import("resource://services-sync/SyncedTabs.jsm", {}); -let { SyncedTabsDeckComponent } = Cu.import("resource:///modules/syncedtabs/SyncedTabsDeckComponent.js", {}); -let { TabListComponent } = Cu.import("resource:///modules/syncedtabs/TabListComponent.js", {}); -let { SyncedTabsListStore } = Cu.import("resource:///modules/syncedtabs/SyncedTabsListStore.js", {}); -let { SyncedTabsDeckStore } = Cu.import("resource:///modules/syncedtabs/SyncedTabsDeckStore.js", {}); -let { TabListView } = Cu.import("resource:///modules/syncedtabs/TabListView.js", {}); -let { DeckView } = Cu.import("resource:///modules/syncedtabs/SyncedTabsDeckView.js", {}); - - -add_task(function* testInitUninit() { - let deckStore = new SyncedTabsDeckStore(); - let listComponent = {}; - - let ViewMock = sinon.stub(); - let view = {render: sinon.spy(), destroy: sinon.spy(), container: {}}; - ViewMock.returns(view); - - sinon.stub(SyncedTabs, "syncTabs", () => Promise.resolve()); - - sinon.spy(deckStore, "on"); - sinon.stub(deckStore, "setPanels"); - - let component = new SyncedTabsDeckComponent({ - window, - deckStore, - listComponent, - SyncedTabs, - DeckView: ViewMock, - }); - - sinon.stub(component, "updatePanel"); - - component.init(); - - Assert.ok(SyncedTabs.syncTabs.called); - SyncedTabs.syncTabs.restore(); - - Assert.ok(ViewMock.calledWithNew(), "view is instantiated"); - Assert.equal(ViewMock.args[0][0], window); - Assert.equal(ViewMock.args[0][1], listComponent); - Assert.ok(ViewMock.args[0][2].onAndroidClick, - "view is passed onAndroidClick prop"); - Assert.ok(ViewMock.args[0][2].oniOSClick, - "view is passed oniOSClick prop"); - Assert.ok(ViewMock.args[0][2].onSyncPrefClick, - "view is passed onSyncPrefClick prop"); - - Assert.equal(component.container, view.container, - "component returns view's container"); - - Assert.ok(deckStore.on.calledOnce, "listener is added to store"); - Assert.equal(deckStore.on.args[0][0], "change"); - // Object.values only in nightly - let values = Object.keys(component.PANELS).map(k => component.PANELS[k]); - Assert.ok(deckStore.setPanels.calledWith(values), - "panels are set on deck store"); - - Assert.ok(component.updatePanel.called); - - deckStore.emit("change", "mock state"); - Assert.ok(view.render.calledWith("mock state"), - "view.render is called on state change"); - - component.uninit(); - - Assert.ok(view.destroy.calledOnce, "view is destroyed on uninit"); -}); - - -function waitForObserver() { - return new Promise((resolve, reject) => { - Services.obs.addObserver((subject, topic) => { - resolve(); - }, SyncedTabs.TOPIC_TABS_CHANGED, false); - }); -} - -add_task(function* testObserver() { - let deckStore = new SyncedTabsDeckStore(); - let listStore = new SyncedTabsListStore(SyncedTabs); - let listComponent = {}; - - let ViewMock = sinon.stub(); - let view = {render: sinon.spy(), destroy: sinon.spy(), container: {}}; - ViewMock.returns(view); - - sinon.stub(SyncedTabs, "syncTabs", () => Promise.resolve()); - - sinon.spy(deckStore, "on"); - sinon.stub(deckStore, "setPanels"); - - sinon.stub(listStore, "getData"); - - let component = new SyncedTabsDeckComponent({ - window, - deckStore, - listStore, - listComponent, - SyncedTabs, - DeckView: ViewMock, - }); - - sinon.spy(component, "observe"); - sinon.stub(component, "updatePanel"); - - component.init(); - SyncedTabs.syncTabs.restore(); - Assert.ok(component.updatePanel.called, "triggers panel update during init"); - - Services.obs.notifyObservers(null, SyncedTabs.TOPIC_TABS_CHANGED, ""); - - Assert.ok(component.observe.calledWith(null, SyncedTabs.TOPIC_TABS_CHANGED, ""), - "component is notified"); - - Assert.ok(listStore.getData.called, "gets list data"); - Assert.ok(component.updatePanel.calledTwice, "triggers panel update"); - - Services.obs.notifyObservers(null, FxAccountsCommon.ONLOGIN_NOTIFICATION, ""); - - Assert.ok(component.observe.calledWith(null, FxAccountsCommon.ONLOGIN_NOTIFICATION, ""), - "component is notified of login"); - Assert.equal(component.updatePanel.callCount, 3, "triggers panel update again"); -}); - -add_task(function* testPanelStatus() { - let deckStore = new SyncedTabsDeckStore(); - let listStore = new SyncedTabsListStore(); - let listComponent = {}; - let fxAccounts = { - accountStatus() {} - }; - let SyncedTabsMock = { - getTabClients() {} - }; - - sinon.stub(listStore, "getData"); - - - let component = new SyncedTabsDeckComponent({ - fxAccounts, - deckStore, - listComponent, - SyncedTabs: SyncedTabsMock, - }); - - let isAuthed = false; - sinon.stub(fxAccounts, "accountStatus", () => Promise.resolve(isAuthed)); - let result = yield component.getPanelStatus(); - Assert.equal(result, component.PANELS.NOT_AUTHED_INFO); - - isAuthed = true; - - SyncedTabsMock.isConfiguredToSyncTabs = false; - result = yield component.getPanelStatus(); - Assert.equal(result, component.PANELS.TABS_DISABLED); - - SyncedTabsMock.isConfiguredToSyncTabs = true; - - SyncedTabsMock.hasSyncedThisSession = false; - result = yield component.getPanelStatus(); - Assert.equal(result, component.PANELS.TABS_FETCHING); - - SyncedTabsMock.hasSyncedThisSession = true; - - let clients = []; - sinon.stub(SyncedTabsMock, "getTabClients", () => Promise.resolve(clients)); - result = yield component.getPanelStatus(); - Assert.equal(result, component.PANELS.SINGLE_DEVICE_INFO); - - clients = ["mock-client"]; - result = yield component.getPanelStatus(); - Assert.equal(result, component.PANELS.TABS_CONTAINER); - - fxAccounts.accountStatus.restore(); - sinon.stub(fxAccounts, "accountStatus", () => Promise.reject("err")); - result = yield component.getPanelStatus(); - Assert.equal(result, component.PANELS.NOT_AUTHED_INFO); - - sinon.stub(component, "getPanelStatus", () => Promise.resolve("mock-panelId")); - sinon.spy(deckStore, "selectPanel"); - yield component.updatePanel(); - Assert.ok(deckStore.selectPanel.calledWith("mock-panelId")); -}); - -add_task(function* testActions() { - let windowMock = { - openUILink() {}, - }; - let chromeWindowMock = { - gSyncUI: { - openSetup() {} - } - }; - sinon.spy(windowMock, "openUILink"); - sinon.spy(chromeWindowMock.gSyncUI, "openSetup"); - - let getChromeWindowMock = sinon.stub(); - getChromeWindowMock.returns(chromeWindowMock); - - let component = new SyncedTabsDeckComponent({ - window: windowMock, - getChromeWindowMock - }); - - let href = Services.prefs.getCharPref("identity.mobilepromo.android") + "synced-tabs-sidebar"; - component.openAndroidLink("mock-event"); - Assert.ok(windowMock.openUILink.calledWith(href, "mock-event")); - - href = Services.prefs.getCharPref("identity.mobilepromo.ios") + "synced-tabs-sidebar"; - component.openiOSLink("mock-event"); - Assert.ok(windowMock.openUILink.calledWith(href, "mock-event")); - - component.openSyncPrefs(); - Assert.ok(getChromeWindowMock.calledWith(windowMock)); - Assert.ok(chromeWindowMock.gSyncUI.openSetup.called); -}); diff --git a/browser/components/syncedtabs/test/xpcshell/test_SyncedTabsDeckStore.js b/browser/components/syncedtabs/test/xpcshell/test_SyncedTabsDeckStore.js deleted file mode 100644 index 69abb4024..000000000 --- a/browser/components/syncedtabs/test/xpcshell/test_SyncedTabsDeckStore.js +++ /dev/null @@ -1,64 +0,0 @@ -"use strict"; - -let { SyncedTabsDeckStore } = Cu.import("resource:///modules/syncedtabs/SyncedTabsDeckStore.js", {}); - -add_task(function* testSelectUnkownPanel() { - let deckStore = new SyncedTabsDeckStore(); - let spy = sinon.spy(); - - deckStore.on("change", spy); - deckStore.selectPanel("foo"); - - Assert.ok(!spy.called); -}); - -add_task(function* testSetPanels() { - let deckStore = new SyncedTabsDeckStore(); - let spy = sinon.spy(); - - deckStore.on("change", spy); - deckStore.setPanels(["panel1", "panel2"]); - - Assert.ok(spy.calledWith({ - panels: [ - { id: "panel1", selected: false }, - { id: "panel2", selected: false }, - ], - isUpdatable: false - })); -}); - -add_task(function* testSelectPanel() { - let deckStore = new SyncedTabsDeckStore(); - let spy = sinon.spy(); - - deckStore.setPanels(["panel1", "panel2"]); - - deckStore.on("change", spy); - deckStore.selectPanel("panel2"); - - Assert.ok(spy.calledWith({ - panels: [ - { id: "panel1", selected: false }, - { id: "panel2", selected: true }, - ], - isUpdatable: true - })); - - deckStore.selectPanel("panel2"); - Assert.ok(spy.calledOnce, "doesn't trigger unless panel changes"); -}); - -add_task(function* testSetPanelsSameArray() { - let deckStore = new SyncedTabsDeckStore(); - let spy = sinon.spy(); - deckStore.on("change", spy); - - let panels = ["panel1", "panel2"]; - - deckStore.setPanels(panels); - deckStore.setPanels(panels); - - Assert.ok(spy.calledOnce, "doesn't trigger unless set of panels changes"); -}); - diff --git a/browser/components/syncedtabs/test/xpcshell/test_SyncedTabsListStore.js b/browser/components/syncedtabs/test/xpcshell/test_SyncedTabsListStore.js deleted file mode 100644 index 51580235f..000000000 --- a/browser/components/syncedtabs/test/xpcshell/test_SyncedTabsListStore.js +++ /dev/null @@ -1,266 +0,0 @@ -"use strict"; - -let { SyncedTabs } = Cu.import("resource://services-sync/SyncedTabs.jsm", {}); -let { SyncedTabsListStore } = Cu.import("resource:///modules/syncedtabs/SyncedTabsListStore.js", {}); - -const FIXTURE = [ - { - "id": "2xU5h-4bkWqA", - "type": "client", - "name": "laptop", - "isMobile": false, - "tabs": [ - { - "type": "tab", - "title": "Firefox for iOS — Mobile Web browser for your iPhone, iPad and iPod touch — Mozilla", - "url": "https://www.mozilla.org/en-US/firefox/ios/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=synced-tabs-sidebar", - "icon": "moz-anno:favicon:https://www.mozilla.org/media/img/firefox/favicon.dc6635050bf5.ico", - "client": "2xU5h-4bkWqA", - "lastUsed": 1451519425 - }, - { - "type": "tab", - "title": "Firefox Nightly First Run Page", - "url": "https://www.mozilla.org/en-US/firefox/nightly/firstrun/?oldversion=45.0a1", - "icon": "moz-anno:favicon:https://www.mozilla.org/media/img/firefox/favicon-nightly.560395bbb2e1.png", - "client": "2xU5h-4bkWqA", - "lastUsed": 1451519420 - } - ] - }, - { - "id": "OL3EJCsdb2JD", - "type": "client", - "name": "desktop", - "isMobile": false, - "tabs": [] - } -]; - -add_task(function* testGetDataEmpty() { - let store = new SyncedTabsListStore(SyncedTabs); - let spy = sinon.spy(); - - sinon.stub(SyncedTabs, "getTabClients", () => { - return Promise.resolve([]); - }); - store.on("change", spy); - - yield store.getData(); - - Assert.ok(SyncedTabs.getTabClients.calledWith("")); - Assert.ok(spy.calledWith({ - clients: [], - canUpdateAll: false, - canUpdateInput: false, - filter: "", - inputFocused: false - })); - - yield store.getData("filter"); - - Assert.ok(SyncedTabs.getTabClients.calledWith("filter")); - Assert.ok(spy.calledWith({ - clients: [], - canUpdateAll: false, - canUpdateInput: true, - filter: "filter", - inputFocused: false - })); - - SyncedTabs.getTabClients.restore(); -}); - -add_task(function* testRowSelectionWithoutFilter() { - let store = new SyncedTabsListStore(SyncedTabs); - let spy = sinon.spy(); - - sinon.stub(SyncedTabs, "getTabClients", () => { - return Promise.resolve(FIXTURE); - }); - - yield store.getData(); - SyncedTabs.getTabClients.restore(); - - store.on("change", spy); - - store.selectRow(0, -1); - Assert.ok(spy.args[0][0].canUpdateAll, "can update the whole view"); - Assert.ok(spy.args[0][0].clients[0].selected, "first client is selected"); - - store.moveSelectionUp(); - Assert.ok(spy.calledOnce, - "can't move up past first client, no change triggered"); - - store.selectRow(0, 0); - Assert.ok(spy.args[1][0].clients[0].tabs[0].selected, - "first tab of first client is selected"); - - store.selectRow(0, 0); - Assert.ok(spy.calledTwice, "selecting same row doesn't trigger change"); - - store.selectRow(0, 1); - Assert.ok(spy.args[2][0].clients[0].tabs[1].selected, - "second tab of first client is selected"); - - store.selectRow(1); - Assert.ok(spy.args[3][0].clients[1].selected, "second client is selected"); - - store.moveSelectionDown(); - Assert.equal(spy.callCount, 4, - "can't move selection down past last client, no change triggered"); - - store.moveSelectionUp(); - Assert.equal(spy.callCount, 5, - "changed"); - Assert.ok(spy.args[4][0].clients[0].tabs[FIXTURE[0].tabs.length - 1].selected, - "move selection up from client selects last tab of previous client"); - - store.moveSelectionUp(); - Assert.ok(spy.args[5][0].clients[0].tabs[FIXTURE[0].tabs.length - 2].selected, - "move selection up from tab selects previous tab of client"); -}); - - -add_task(function* testToggleBranches() { - let store = new SyncedTabsListStore(SyncedTabs); - let spy = sinon.spy(); - - sinon.stub(SyncedTabs, "getTabClients", () => { - return Promise.resolve(FIXTURE); - }); - - yield store.getData(); - SyncedTabs.getTabClients.restore(); - - store.selectRow(0); - store.on("change", spy); - - let clientId = FIXTURE[0].id; - store.closeBranch(clientId); - Assert.ok(spy.args[0][0].clients[0].closed, "first client is closed"); - - store.openBranch(clientId); - Assert.ok(!spy.args[1][0].clients[0].closed, "first client is open"); - - store.toggleBranch(clientId); - Assert.ok(spy.args[2][0].clients[0].closed, "first client is toggled closed"); - - store.moveSelectionDown(); - Assert.ok(spy.args[3][0].clients[1].selected, - "selection skips tabs if client is closed"); - - store.moveSelectionUp(); - Assert.ok(spy.args[4][0].clients[0].selected, - "selection skips tabs if client is closed"); -}); - - -add_task(function* testRowSelectionWithFilter() { - let store = new SyncedTabsListStore(SyncedTabs); - let spy = sinon.spy(); - - sinon.stub(SyncedTabs, "getTabClients", () => { - return Promise.resolve(FIXTURE); - }); - - yield store.getData("filter"); - SyncedTabs.getTabClients.restore(); - - store.on("change", spy); - - store.selectRow(0); - Assert.ok(spy.args[0][0].clients[0].tabs[0].selected, "first tab is selected"); - - store.moveSelectionUp(); - Assert.ok(spy.calledOnce, - "can't move up past first tab, no change triggered"); - - store.moveSelectionDown(); - Assert.ok(spy.args[1][0].clients[0].tabs[1].selected, - "selection skips tabs if client is closed"); - - store.moveSelectionDown(); - Assert.equal(spy.callCount, 2, - "can't move selection down past last tab, no change triggered"); - - store.selectRow(1); - Assert.equal(spy.callCount, 2, - "doesn't trigger change if same row selected"); - -}); - - -add_task(function* testFilterAndClearFilter() { - let store = new SyncedTabsListStore(SyncedTabs); - let spy = sinon.spy(); - - sinon.stub(SyncedTabs, "getTabClients", () => { - return Promise.resolve(FIXTURE); - }); - store.on("change", spy); - - yield store.getData("filter"); - - Assert.ok(SyncedTabs.getTabClients.calledWith("filter")); - Assert.ok(!spy.args[0][0].canUpdateAll, "can't update all"); - Assert.ok(spy.args[0][0].canUpdateInput, "can update just input"); - - store.selectRow(0); - - Assert.equal(spy.args[1][0].filter, "filter"); - Assert.ok(spy.args[1][0].clients[0].tabs[0].selected, - "tab is selected"); - - yield store.clearFilter(); - - Assert.ok(SyncedTabs.getTabClients.calledWith("")); - Assert.ok(!spy.args[2][0].canUpdateAll, "can't update all"); - Assert.ok(!spy.args[2][0].canUpdateInput, "can't just update input"); - - Assert.equal(spy.args[2][0].filter, ""); - Assert.ok(!spy.args[2][0].clients[0].tabs[0].selected, - "tab is no longer selected"); - - SyncedTabs.getTabClients.restore(); -}); - -add_task(function* testFocusBlurInput() { - let store = new SyncedTabsListStore(SyncedTabs); - let spy = sinon.spy(); - - sinon.stub(SyncedTabs, "getTabClients", () => { - return Promise.resolve(FIXTURE); - }); - store.on("change", spy); - - yield store.getData(); - SyncedTabs.getTabClients.restore(); - - Assert.ok(!spy.args[0][0].canUpdateAll, "must rerender all"); - - store.selectRow(0); - Assert.ok(!spy.args[1][0].inputFocused, - "input is not focused"); - Assert.ok(spy.args[1][0].clients[0].selected, - "client is selected"); - Assert.ok(spy.args[1][0].clients[0].focused, - "client is focused"); - - store.focusInput(); - Assert.ok(spy.args[2][0].inputFocused, - "input is focused"); - Assert.ok(spy.args[2][0].clients[0].selected, - "client is still selected"); - Assert.ok(!spy.args[2][0].clients[0].focused, - "client is no longer focused"); - - store.blurInput(); - Assert.ok(!spy.args[3][0].inputFocused, - "input is not focused"); - Assert.ok(spy.args[3][0].clients[0].selected, - "client is selected"); - Assert.ok(spy.args[3][0].clients[0].focused, - "client is focused"); -}); - diff --git a/browser/components/syncedtabs/test/xpcshell/test_TabListComponent.js b/browser/components/syncedtabs/test/xpcshell/test_TabListComponent.js deleted file mode 100644 index 0b0665a1b..000000000 --- a/browser/components/syncedtabs/test/xpcshell/test_TabListComponent.js +++ /dev/null @@ -1,155 +0,0 @@ -"use strict"; - -let { SyncedTabs } = Cu.import("resource://services-sync/SyncedTabs.jsm", {}); -let { TabListComponent } = Cu.import("resource:///modules/syncedtabs/TabListComponent.js", {}); -let { SyncedTabsListStore } = Cu.import("resource:///modules/syncedtabs/SyncedTabsListStore.js", {}); -let { View } = Cu.import("resource:///modules/syncedtabs/TabListView.js", {}); - -const ACTION_METHODS = [ - "onSelectRow", - "onOpenTab", - "onOpenTabs", - "onMoveSelectionDown", - "onMoveSelectionUp", - "onToggleBranch", - "onBookmarkTab", - "onSyncRefresh", - "onFilter", - "onClearFilter", - "onFilterFocus", - "onFilterBlur", -]; - -add_task(function* testInitUninit() { - let store = new SyncedTabsListStore(); - let ViewMock = sinon.stub(); - let view = {render() {}, destroy() {}}; - - ViewMock.returns(view); - - sinon.spy(view, 'render'); - sinon.spy(view, 'destroy'); - - sinon.spy(store, "on"); - sinon.stub(store, "getData"); - sinon.stub(store, "focusInput"); - - let component = new TabListComponent({window, store, View: ViewMock, SyncedTabs}); - - for (let action of ACTION_METHODS) { - sinon.stub(component, action); - } - - component.init(); - - Assert.ok(ViewMock.calledWithNew(), "view is instantiated"); - Assert.ok(store.on.calledOnce, "listener is added to store"); - Assert.equal(store.on.args[0][0], "change"); - Assert.ok(view.render.calledWith({clients: []}), - "render is called on view instance"); - Assert.ok(store.getData.calledOnce, "store gets initial data"); - Assert.ok(store.focusInput.calledOnce, "input field is focused"); - - for (let method of ACTION_METHODS) { - let action = ViewMock.args[0][1][method]; - Assert.ok(action, method + " action is passed to View"); - action("foo", "bar"); - Assert.ok(component[method].calledWith("foo", "bar"), - method + " action passed to View triggers the component method with args"); - } - - store.emit("change", "mock state"); - Assert.ok(view.render.secondCall.calledWith("mock state"), - "view.render is called on state change"); - - component.uninit(); - Assert.ok(view.destroy.calledOnce, "view is destroyed on uninit"); -}); - -add_task(function* testActions() { - let store = new SyncedTabsListStore(); - let chromeWindowMock = { - gBrowser: { - loadTabs() {}, - }, - }; - let getChromeWindowMock = sinon.stub(); - getChromeWindowMock.returns(chromeWindowMock); - let clipboardHelperMock = { - copyString() {}, - }; - let windowMock = { - top: { - PlacesCommandHook: { - bookmarkLink() { return Promise.resolve(); } - }, - PlacesUtils: { bookmarksMenuFolderId: "id" } - }, - getBrowserURL() {}, - openDialog() {}, - openUILinkIn() {} - }; - let component = new TabListComponent({ - window: windowMock, store, View: null, SyncedTabs, - clipboardHelper: clipboardHelperMock, - getChromeWindow: getChromeWindowMock }); - - sinon.stub(store, "getData"); - component.onFilter("query"); - Assert.ok(store.getData.calledWith("query")); - - sinon.stub(store, "clearFilter"); - component.onClearFilter(); - Assert.ok(store.clearFilter.called); - - sinon.stub(store, "focusInput"); - component.onFilterFocus(); - Assert.ok(store.focusInput.called); - - sinon.stub(store, "blurInput"); - component.onFilterBlur(); - Assert.ok(store.blurInput.called); - - sinon.stub(store, "selectRow"); - component.onSelectRow([-1, -1]); - Assert.ok(store.selectRow.calledWith(-1, -1)); - - sinon.stub(store, "moveSelectionDown"); - component.onMoveSelectionDown(); - Assert.ok(store.moveSelectionDown.called); - - sinon.stub(store, "moveSelectionUp"); - component.onMoveSelectionUp(); - Assert.ok(store.moveSelectionUp.called); - - sinon.stub(store, "toggleBranch"); - component.onToggleBranch("foo-id"); - Assert.ok(store.toggleBranch.calledWith("foo-id")); - - sinon.spy(windowMock.top.PlacesCommandHook, "bookmarkLink"); - component.onBookmarkTab("uri", "title"); - Assert.equal(windowMock.top.PlacesCommandHook.bookmarkLink.args[0][1], "uri"); - Assert.equal(windowMock.top.PlacesCommandHook.bookmarkLink.args[0][2], "title"); - - sinon.spy(windowMock, "openUILinkIn"); - component.onOpenTab("uri", "where", "params"); - Assert.ok(windowMock.openUILinkIn.calledWith("uri", "where", "params")); - - sinon.spy(chromeWindowMock.gBrowser, "loadTabs"); - let tabsToOpen = ["uri1", "uri2"]; - component.onOpenTabs(tabsToOpen, "where"); - Assert.ok(getChromeWindowMock.calledWith(windowMock)); - Assert.ok(chromeWindowMock.gBrowser.loadTabs.calledWith(tabsToOpen, false, false)); - component.onOpenTabs(tabsToOpen, "tabshifted"); - Assert.ok(chromeWindowMock.gBrowser.loadTabs.calledWith(tabsToOpen, true, false)); - - sinon.spy(clipboardHelperMock, "copyString"); - component.onCopyTabLocation("uri"); - Assert.ok(clipboardHelperMock.copyString.calledWith("uri")); - - sinon.stub(SyncedTabs, "syncTabs"); - component.onSyncRefresh(); - Assert.ok(SyncedTabs.syncTabs.calledWith(true)); - SyncedTabs.syncTabs.restore(); -}); - diff --git a/browser/components/syncedtabs/test/xpcshell/xpcshell.ini b/browser/components/syncedtabs/test/xpcshell/xpcshell.ini deleted file mode 100644 index 1cb8dcb7a..000000000 --- a/browser/components/syncedtabs/test/xpcshell/xpcshell.ini +++ /dev/null @@ -1,10 +0,0 @@ -[DEFAULT] -head = head.js -tail = -firefox-appdir = browser - -[test_EventEmitter.js] -[test_SyncedTabsDeckStore.js] -[test_SyncedTabsListStore.js] -[test_SyncedTabsDeckComponent.js] -[test_TabListComponent.js] |