UNPKG

@ledgerhq/live-common

Version:
478 lines • 19.9 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const rxjs_1 = require("rxjs"); const errors_1 = require("@ledgerhq/errors"); const hw_transport_mocker_1 = require("@ledgerhq/hw-transport-mocker"); const listApps_1 = require("./listApps"); const api_1 = __importDefault(require("../manager/api")); const aDeviceInfo_1 = require("../mock/fixtures/aDeviceInfo"); const HttpManagerApiRepositoryFactory_1 = require("../device/factories/HttpManagerApiRepositoryFactory"); const isCustomLockScreenSupported_1 = require("../device/use-cases/isCustomLockScreenSupported"); const customLockScreenFetchSize_1 = __importDefault(require("../hw/customLockScreenFetchSize")); const getDeviceNameUseCase_1 = require("../device/use-cases/getDeviceNameUseCase"); const currencies_1 = require("../currencies"); const mock_1 = require("./mock"); jest.useFakeTimers(); jest.mock("../hw/customLockScreenFetchSize"); jest.mock("../device/use-cases/getDeviceNameUseCase"); jest.mock("../currencies"); const mockedCustomLockScreenFetchSize = jest.mocked(customLockScreenFetchSize_1.default); const mockedGetDeviceName = jest.mocked(getDeviceNameUseCase_1.getDeviceName); const mockedListCryptoCurrencies = jest.mocked(currencies_1.listCryptoCurrencies); const mockedCurrenciesByMarketCap = jest.mocked(currencies_1.currenciesByMarketcap); const mockedListInstalledAppEvent = { type: "result", payload: [], }; describe("listApps", () => { let mockedManagerApiRepository; let listAppsCommandSpy; let listAppsWithManagerApiSpy; beforeEach(() => { jest .spyOn(jest.requireActual("../device/use-cases/getLatestFirmwareForDeviceUseCase"), "getLatestFirmwareForDeviceUseCase") .mockReturnValue(Promise.resolve(null)); mockedManagerApiRepository = new HttpManagerApiRepositoryFactory_1.StubManagerApiRepository(); mockedGetDeviceName.mockReturnValue(Promise.resolve("Mocked device name")); mockedCurrenciesByMarketCap.mockReturnValue(Promise.resolve([])); mockedListCryptoCurrencies.mockReturnValue([]); listAppsCommandSpy = jest .spyOn(jest.requireActual("../hw/listApps"), "default") .mockReturnValue(Promise.resolve([])); listAppsWithManagerApiSpy = jest .spyOn(api_1.default, "listInstalledApps") .mockReturnValue((0, rxjs_1.from)([mockedListInstalledAppEvent])); }); afterEach(() => { jest.clearAllTimers(); jest.restoreAllMocks(); }); it("should return an observable that errors if deviceInfo.isOSU is true", done => { const transport = (0, hw_transport_mocker_1.aTransportBuilder)(); const deviceInfo = (0, aDeviceInfo_1.aDeviceInfoBuilder)({ isOSU: true, isBootloader: false }); (0, listApps_1.listApps)({ managerDevModeEnabled: false, transport, deviceInfo, managerApiRepository: mockedManagerApiRepository, forceProvider: 1, }).subscribe({ error: err => { expect(err).toBeInstanceOf(errors_1.UnexpectedBootloader); done(); }, complete: () => { done("this observable should not complete"); }, }); jest.advanceTimersByTime(1); }); it("should return an observable that errors if deviceInfo.isBootloader is true", done => { const transport = (0, hw_transport_mocker_1.aTransportBuilder)(); const deviceInfo = (0, aDeviceInfo_1.aDeviceInfoBuilder)({ isOSU: false, isBootloader: true }); (0, listApps_1.listApps)({ managerDevModeEnabled: false, transport, deviceInfo, managerApiRepository: mockedManagerApiRepository, forceProvider: 1, }).subscribe({ error: err => { expect(err).toBeInstanceOf(errors_1.UnexpectedBootloader); done(); }, complete: () => { done("this observable should not complete"); }, }); jest.advanceTimersByTime(1); }); it("should return an observable that errors if transport.deviceModel.id is undefined, identifyTargetId returns a falsy value and deviceProxyModel is undefined", done => { const transport = (0, hw_transport_mocker_1.aTransportBuilder)({ deviceModel: null }); const deviceInfo = (0, aDeviceInfo_1.aDeviceInfoBuilder)({ isOSU: false, isBootloader: false, targetId: 0 }); (0, listApps_1.listApps)({ managerDevModeEnabled: false, transport, deviceInfo, managerApiRepository: mockedManagerApiRepository, forceProvider: 1, }).subscribe({ error: err => { expect(err.message).toBe("Bad usage of listAppsV2: missing deviceModelId"); done(); }, complete: () => { done("this observable should not complete"); }, }); jest.advanceTimersByTime(1); }); it("should call hwListApps() if deviceInfo.managerAllowed is true", done => { const transport = (0, hw_transport_mocker_1.aTransportBuilder)(); const deviceInfo = (0, aDeviceInfo_1.aDeviceInfoBuilder)({ isOSU: false, isBootloader: false, managerAllowed: true, targetId: 0x33200000, }); (0, listApps_1.listApps)({ managerDevModeEnabled: false, transport, deviceInfo, managerApiRepository: mockedManagerApiRepository, forceProvider: 1, }).subscribe({ complete: () => { done(); }, error: () => { done(); }, }); jest.advanceTimersByTime(1); expect(listAppsCommandSpy).toHaveBeenCalled(); expect(listAppsWithManagerApiSpy).not.toHaveBeenCalled(); }); [ errors_1.StatusCodes.CLA_NOT_SUPPORTED, errors_1.StatusCodes.INS_NOT_SUPPORTED, errors_1.StatusCodes.UNKNOWN_APDU, 0x6e01, 0x6d01, ].forEach(statusCode => { it(`should call ManagerAPI.listInstalledApps() if deviceInfo.managerAllowed is true but list apps APDU returns 0x${statusCode.toString(16)}`, done => { const transport = (0, hw_transport_mocker_1.aTransportBuilder)(); const deviceInfo = (0, aDeviceInfo_1.aDeviceInfoBuilder)({ isOSU: false, isBootloader: false, managerAllowed: true, targetId: 0x33200000, }); listAppsCommandSpy.mockRejectedValue(new errors_1.TransportStatusError(statusCode)); (0, listApps_1.listApps)({ managerDevModeEnabled: false, transport, deviceInfo, managerApiRepository: mockedManagerApiRepository, forceProvider: 1, }).subscribe({ complete: () => { try { expect(listAppsCommandSpy).toHaveBeenCalled(); expect(listAppsWithManagerApiSpy).toHaveBeenCalled(); done(); } catch (e) { done(e); } }, error: e => { done(e); }, }); jest.advanceTimersByTime(1); }); }); it("should return an observable that errors if listApps() throws an error that is not a TransportStatusError", done => { const transport = (0, hw_transport_mocker_1.aTransportBuilder)(); const deviceInfo = (0, aDeviceInfo_1.aDeviceInfoBuilder)({ isOSU: false, isBootloader: false, managerAllowed: true, targetId: 0x33200000, }); listAppsCommandSpy.mockRejectedValue(new Error("listApps failed")); (0, listApps_1.listApps)({ managerDevModeEnabled: false, transport, deviceInfo, managerApiRepository: mockedManagerApiRepository, forceProvider: 1, }).subscribe({ error: err => { try { expect(err).toEqual(new Error("listApps failed")); done(); } catch (e) { done(e); } }, complete: () => { done("this observable should not complete"); }, }); jest.advanceTimersByTime(1); }); it("should call ManagerAPI.listInstalledApps() if deviceInfo.managerAllowed is false", () => { const transport = (0, hw_transport_mocker_1.aTransportBuilder)(); const deviceInfo = (0, aDeviceInfo_1.aDeviceInfoBuilder)({ isOSU: false, isBootloader: false, managerAllowed: false, targetId: 0x33200000, }); (0, listApps_1.listApps)({ managerDevModeEnabled: false, transport, deviceInfo, managerApiRepository: mockedManagerApiRepository, forceProvider: 1, }).subscribe(); jest.advanceTimersByTime(1); expect(listAppsCommandSpy).not.toHaveBeenCalled(); expect(listAppsWithManagerApiSpy).toHaveBeenCalled(); }); it("should return an observable that errors if getDeviceVersion() throws", done => { jest.spyOn(mockedManagerApiRepository, "getDeviceVersion").mockImplementation(() => { throw new Error("getDeviceVersion failed"); }); const transport = (0, hw_transport_mocker_1.aTransportBuilder)(); const deviceInfo = (0, aDeviceInfo_1.aDeviceInfoBuilder)({ isOSU: false, isBootloader: false, managerAllowed: false, targetId: 0x33200000, }); (0, listApps_1.listApps)({ managerDevModeEnabled: false, transport, deviceInfo, managerApiRepository: mockedManagerApiRepository, forceProvider: 1, }).subscribe({ error: err => { expect(err.message).toBe("getDeviceVersion failed"); done(); }, complete: () => { done("this observable should not complete"); }, }); jest.advanceTimersByTime(1); }); it("should return an observable that errors if catalogForDevice() throws", done => { jest.spyOn(mockedManagerApiRepository, "catalogForDevice").mockImplementation(() => { throw new Error("catalogForDevice failed"); }); const transport = (0, hw_transport_mocker_1.aTransportBuilder)(); const deviceInfo = (0, aDeviceInfo_1.aDeviceInfoBuilder)({ isOSU: false, isBootloader: false, managerAllowed: false, targetId: 0x33200000, }); (0, listApps_1.listApps)({ managerDevModeEnabled: false, transport, deviceInfo, managerApiRepository: mockedManagerApiRepository, forceProvider: 1, }).subscribe({ error: err => { expect(err.message).toBe("catalogForDevice failed"); done(); }, complete: () => { done("this observable should not complete"); }, }); jest.advanceTimersByTime(1); }); it("should return an observable that errors if getLanguagePackagesForDevice() throws", done => { jest .spyOn(mockedManagerApiRepository, "getLanguagePackagesForDevice") .mockImplementation(() => { throw new Error("getLanguagePackagesForDevice failed"); }); const transport = (0, hw_transport_mocker_1.aTransportBuilder)(); const deviceInfo = (0, aDeviceInfo_1.aDeviceInfoBuilder)({ isOSU: false, isBootloader: false, managerAllowed: false, targetId: 0x33200000, }); (0, listApps_1.listApps)({ managerDevModeEnabled: false, transport, deviceInfo, managerApiRepository: mockedManagerApiRepository, forceProvider: 1, }).subscribe({ error: err => { expect(err.message).toBe("getLanguagePackagesForDevice failed"); done(); }, complete: () => { done("this observable should not complete"); }, }); jest.advanceTimersByTime(1); }); isCustomLockScreenSupported_1.supportedDeviceModelIds.forEach(deviceModelId => { it(`should return customImageBlocks different than 0 for a ${deviceModelId} device with a custom lock screen`, done => { const transport = (0, hw_transport_mocker_1.aTransportBuilder)({ deviceModel: { id: deviceModelId } }); const deviceInfo = (0, aDeviceInfo_1.aDeviceInfoBuilder)({ isOSU: false, isBootloader: false, managerAllowed: true, targetId: 0x33200000, }); mockedCustomLockScreenFetchSize.mockReturnValue(Promise.resolve(10)); let gotResult = false; (0, listApps_1.listApps)({ managerDevModeEnabled: false, transport, deviceInfo, managerApiRepository: mockedManagerApiRepository, forceProvider: 1, }).subscribe({ next: listAppsEvent => { if (listAppsEvent.type === "result") { gotResult = true; const { result: { customImageBlocks }, } = listAppsEvent; try { expect(customImageBlocks).not.toBe(0); } catch (e) { done(e); } } }, complete: () => { gotResult ? done() : done("this observable should not complete without a result"); }, error: error => { done(error); }, }); jest.advanceTimersByTime(1); }); }); it("should keep apps with isDevTools if managerDevModeEnabled is true", done => { const transport = (0, hw_transport_mocker_1.aTransportBuilder)(); const deviceInfo = (0, aDeviceInfo_1.aDeviceInfoBuilder)({ isOSU: false, isBootloader: false, managerAllowed: true, targetId: 0x33200000, }); mockedManagerApiRepository = { ...new HttpManagerApiRepositoryFactory_1.StubManagerApiRepository(), catalogForDevice: () => Promise.resolve([ (0, mock_1.makeAppV2Mock)({ versionName: "Mocked dev app", isDevTools: true }), (0, mock_1.makeAppV2Mock)({ versionName: "Another non dev app", isDevTools: false }), ]), }; (0, listApps_1.listApps)({ managerDevModeEnabled: true, transport, deviceInfo, managerApiRepository: mockedManagerApiRepository, forceProvider: 1, }).subscribe({ next: listAppsEvent => { if (listAppsEvent.type === "result") { const { result: { appsListNames }, } = listAppsEvent; try { expect(appsListNames).toEqual(["Mocked dev app", "Another non dev app"]); done(); } catch (e) { done(e); } } }, }); jest.advanceTimersByTime(1); }); it("should not keep apps with isDevTools if managerDevModeEnabled is false", done => { const transport = (0, hw_transport_mocker_1.aTransportBuilder)(); const deviceInfo = (0, aDeviceInfo_1.aDeviceInfoBuilder)({ isOSU: false, isBootloader: false, managerAllowed: true, targetId: 0x33200000, }); mockedManagerApiRepository = { ...new HttpManagerApiRepositoryFactory_1.StubManagerApiRepository(), catalogForDevice: () => Promise.resolve([ (0, mock_1.makeAppV2Mock)({ versionName: "Mocked dev app", isDevTools: true }), (0, mock_1.makeAppV2Mock)({ versionName: "Another non dev app", isDevTools: false }), ]), }; (0, listApps_1.listApps)({ managerDevModeEnabled: false, transport, deviceInfo, managerApiRepository: mockedManagerApiRepository, forceProvider: 1, }).subscribe({ next: listAppsEvent => { if (listAppsEvent.type === "result") { const { result: { appsListNames }, } = listAppsEvent; try { expect(appsListNames).toEqual(["Another non dev app"]); done(); } catch (e) { done(e); } } }, }); jest.advanceTimersByTime(1); }); it("should keep apps with isDevTools if managerDevModeEnabled is disabled but those apps are installed", done => { const transport = (0, hw_transport_mocker_1.aTransportBuilder)(); const deviceInfo = (0, aDeviceInfo_1.aDeviceInfoBuilder)({ isOSU: false, isBootloader: false, managerAllowed: true, targetId: 0x33200000, }); mockedManagerApiRepository = { ...new HttpManagerApiRepositoryFactory_1.StubManagerApiRepository(), catalogForDevice: () => Promise.resolve([ (0, mock_1.makeAppV2Mock)({ versionName: "Mocked dev app", isDevTools: true }), (0, mock_1.makeAppV2Mock)({ versionName: "Another non dev app", isDevTools: false }), ]), getAppsByHash(hashes) { const hashToApp = { hash1: (0, mock_1.makeAppV2Mock)({ versionName: "Mocked dev app", isDevTools: true }), hash2: (0, mock_1.makeAppV2Mock)({ versionName: "Another non dev app", isDevTools: false }), }; return Promise.resolve(hashes.map(hash => hashToApp[hash])); }, }; listAppsCommandSpy.mockResolvedValue([ { hash: "hash1", name: "Mocked dev app" }, { hash: "hash2", name: "Another non dev app" }, ]); (0, listApps_1.listApps)({ managerDevModeEnabled: false, transport, deviceInfo, managerApiRepository: mockedManagerApiRepository, forceProvider: 1, }).subscribe({ next: listAppsEvent => { if (listAppsEvent.type === "result") { const { result: { appsListNames }, } = listAppsEvent; try { expect(appsListNames).toEqual(["Mocked dev app", "Another non dev app"]); done(); } catch (e) { done(e); } } }, }); jest.advanceTimersByTime(1); }); }); //# sourceMappingURL=listApps.test.js.map