263 lines
7.3 KiB
JavaScript
263 lines
7.3 KiB
JavaScript
"use strict";
|
|
|
|
let { SyncedTabs } = ChromeUtils.importESModule(
|
|
"resource://services-sync/SyncedTabs.sys.mjs"
|
|
);
|
|
let { SyncedTabsDeckComponent } = ChromeUtils.importESModule(
|
|
"resource:///modules/syncedtabs/SyncedTabsDeckComponent.sys.mjs"
|
|
);
|
|
let { SyncedTabsListStore } = ChromeUtils.importESModule(
|
|
"resource:///modules/syncedtabs/SyncedTabsListStore.sys.mjs"
|
|
);
|
|
let { SyncedTabsDeckStore } = ChromeUtils.importESModule(
|
|
"resource:///modules/syncedtabs/SyncedTabsDeckStore.sys.mjs"
|
|
);
|
|
const { UIState } = ChromeUtils.importESModule(
|
|
"resource://services-sync/UIState.sys.mjs"
|
|
);
|
|
|
|
add_task(async function testInitUninit() {
|
|
let deckStore = new SyncedTabsDeckStore();
|
|
let listComponent = {};
|
|
let mockWindow = {};
|
|
|
|
let ViewMock = sinon.stub();
|
|
let view = { render: sinon.spy(), destroy: sinon.spy(), container: {} };
|
|
ViewMock.returns(view);
|
|
|
|
sinon.stub(SyncedTabs, "syncTabs").callsFake(() => Promise.resolve());
|
|
|
|
sinon.spy(deckStore, "on");
|
|
sinon.stub(deckStore, "setPanels");
|
|
|
|
let component = new SyncedTabsDeckComponent({
|
|
window: mockWindow,
|
|
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], mockWindow);
|
|
Assert.equal(ViewMock.args[0][1], listComponent);
|
|
Assert.ok(
|
|
ViewMock.args[0][2].onConnectDeviceClick,
|
|
"view is passed onConnectDeviceClick 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");
|
|
});
|
|
|
|
add_task(async function testObserver() {
|
|
let deckStore = new SyncedTabsDeckStore();
|
|
let listStore = new SyncedTabsListStore(SyncedTabs);
|
|
let listComponent = {};
|
|
let mockWindow = {};
|
|
|
|
let ViewMock = sinon.stub();
|
|
let view = { render: sinon.spy(), destroy: sinon.spy(), container: {} };
|
|
ViewMock.returns(view);
|
|
|
|
sinon.stub(SyncedTabs, "syncTabs").callsFake(() => Promise.resolve());
|
|
|
|
sinon.spy(deckStore, "on");
|
|
sinon.stub(deckStore, "setPanels");
|
|
|
|
sinon.stub(listStore, "getData");
|
|
|
|
let component = new SyncedTabsDeckComponent({
|
|
window: mockWindow,
|
|
deckStore,
|
|
listStore,
|
|
listComponent,
|
|
SyncedTabs,
|
|
DeckView: ViewMock,
|
|
});
|
|
|
|
sinon.spy(component, "observe");
|
|
sinon.stub(component, "updatePanel");
|
|
sinon.stub(component, "updateDir");
|
|
|
|
component.init();
|
|
SyncedTabs.syncTabs.restore();
|
|
Assert.ok(component.updatePanel.called, "triggers panel update during init");
|
|
Assert.ok(
|
|
component.updateDir.called,
|
|
"triggers UI direction 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, UIState.ON_UPDATE);
|
|
|
|
Assert.ok(
|
|
component.observe.calledWith(null, UIState.ON_UPDATE),
|
|
"component is notified of FxA/Sync UI Update"
|
|
);
|
|
Assert.equal(
|
|
component.updatePanel.callCount,
|
|
3,
|
|
"triggers panel update again"
|
|
);
|
|
|
|
Services.locale.availableLocales = ["ab-CD"];
|
|
Services.locale.requestedLocales = ["ab-CD"];
|
|
|
|
Assert.ok(
|
|
component.updateDir.calledTwice,
|
|
"locale change triggers UI direction update"
|
|
);
|
|
|
|
Services.prefs.setStringPref("intl.l10n.pseudo", "bidi");
|
|
|
|
Assert.equal(
|
|
component.updateDir.callCount,
|
|
3,
|
|
"pref change triggers UI direction update"
|
|
);
|
|
});
|
|
|
|
add_task(async function testPanelStatus() {
|
|
let deckStore = new SyncedTabsDeckStore();
|
|
let listStore = new SyncedTabsListStore();
|
|
let listComponent = {};
|
|
let SyncedTabsMock = {
|
|
getTabClients() {},
|
|
};
|
|
|
|
sinon.stub(listStore, "getData");
|
|
|
|
let component = new SyncedTabsDeckComponent({
|
|
deckStore,
|
|
listComponent,
|
|
SyncedTabs: SyncedTabsMock,
|
|
});
|
|
|
|
sinon.stub(UIState, "get").returns({ status: UIState.STATUS_NOT_CONFIGURED });
|
|
let result = await component.getPanelStatus();
|
|
Assert.equal(result, component.PANELS.NOT_AUTHED_INFO);
|
|
UIState.get.restore();
|
|
|
|
sinon.stub(UIState, "get").returns({ status: UIState.STATUS_NOT_VERIFIED });
|
|
result = await component.getPanelStatus();
|
|
Assert.equal(result, component.PANELS.UNVERIFIED);
|
|
UIState.get.restore();
|
|
|
|
sinon.stub(UIState, "get").returns({ status: UIState.STATUS_LOGIN_FAILED });
|
|
result = await component.getPanelStatus();
|
|
Assert.equal(result, component.PANELS.LOGIN_FAILED);
|
|
UIState.get.restore();
|
|
|
|
sinon
|
|
.stub(UIState, "get")
|
|
.returns({ status: UIState.STATUS_SIGNED_IN, syncEnabled: false });
|
|
SyncedTabsMock.isConfiguredToSyncTabs = true;
|
|
result = await component.getPanelStatus();
|
|
Assert.equal(result, component.PANELS.SYNC_DISABLED);
|
|
UIState.get.restore();
|
|
|
|
sinon
|
|
.stub(UIState, "get")
|
|
.returns({ status: UIState.STATUS_SIGNED_IN, syncEnabled: true });
|
|
SyncedTabsMock.isConfiguredToSyncTabs = false;
|
|
result = await component.getPanelStatus();
|
|
Assert.equal(result, component.PANELS.TABS_DISABLED);
|
|
|
|
SyncedTabsMock.isConfiguredToSyncTabs = true;
|
|
|
|
SyncedTabsMock.hasSyncedThisSession = false;
|
|
result = await component.getPanelStatus();
|
|
Assert.equal(result, component.PANELS.TABS_FETCHING);
|
|
|
|
SyncedTabsMock.hasSyncedThisSession = true;
|
|
|
|
let clients = [];
|
|
sinon
|
|
.stub(SyncedTabsMock, "getTabClients")
|
|
.callsFake(() => Promise.resolve(clients));
|
|
result = await component.getPanelStatus();
|
|
Assert.equal(result, component.PANELS.SINGLE_DEVICE_INFO);
|
|
|
|
clients = ["mock-client"];
|
|
result = await component.getPanelStatus();
|
|
Assert.equal(result, component.PANELS.TABS_CONTAINER);
|
|
|
|
sinon
|
|
.stub(component, "getPanelStatus")
|
|
.callsFake(() => Promise.resolve("mock-panelId"));
|
|
sinon.spy(deckStore, "selectPanel");
|
|
await component.updatePanel();
|
|
Assert.ok(deckStore.selectPanel.calledWith("mock-panelId"));
|
|
});
|
|
|
|
add_task(async function testActions() {
|
|
let windowMock = {};
|
|
let chromeWindowMock = {
|
|
gSync: {
|
|
openPrefs() {},
|
|
openConnectAnotherDevice() {},
|
|
},
|
|
};
|
|
sinon.spy(chromeWindowMock.gSync, "openPrefs");
|
|
sinon.spy(chromeWindowMock.gSync, "openConnectAnotherDevice");
|
|
|
|
let getChromeWindowMock = sinon.stub();
|
|
getChromeWindowMock.returns(chromeWindowMock);
|
|
|
|
let component = new SyncedTabsDeckComponent({
|
|
window: windowMock,
|
|
getChromeWindowMock,
|
|
});
|
|
|
|
component.openConnectDevice();
|
|
Assert.ok(chromeWindowMock.gSync.openConnectAnotherDevice.called);
|
|
|
|
component.openSyncPrefs();
|
|
Assert.ok(getChromeWindowMock.calledWith(windowMock));
|
|
Assert.ok(chromeWindowMock.gSync.openPrefs.called);
|
|
});
|