"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