"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const testing_1 = require("rxjs/testing");
const installApp_1 = __importDefault(require("./installApp"));
const api_1 = __importDefault(require("../manager/api"));
const rxjs_1 = require("rxjs");
const anApp_1 = require("../mock/fixtures/anApp");
const hw_transport_mocker_1 = require("@ledgerhq/hw-transport-mocker");
const errors_1 = require("@ledgerhq/errors");
// Mocking ManagerAPI
jest.mock("../manager/api", () => {
    const originalModule = jest.requireActual("../manager/api");
    return {
        ...originalModule,
        install: jest.fn(),
    };
});
const mockManagerApiInstall = jest.mocked(api_1.default.install);
describe("installApp", () => {
    let testScheduler;
    beforeEach(() => {
        testScheduler = new testing_1.TestScheduler((actual, expected) => {
            // Makes TestScheduler assertions works with our test framework Jest
            expect(actual).toEqual(expected);
        });
    });
    test("On one error followed by a successfully emitted event, it should retry after the given delay", () => {
        testScheduler.run(({ cold, expectObservable }) => {
            let count = 0;
            const fakeEvent = {
                type: "bulk-progress",
                progress: 0.8,
            };
            // The first time an error is thrown. The 2nd time a correct event is emitted.
            mockManagerApiInstall.mockReturnValueOnce((0, rxjs_1.defer)(() => {
                if (count > 0) {
                    return cold("a", {
                        a: fakeEvent,
                    });
                }
                count += 1;
                // Throws an error
                return cold("#");
            }));
            // The `transport` and `app` can be fake as the ManagerAPI.install is mocked
            const installObservable = (0, installApp_1.default)((0, hw_transport_mocker_1.aTransportBuilder)(), "target-test", (0, anApp_1.anAppBuilder)(), {
                retryDelayMs: 500,
                retryLimit: 1,
            });
            const expectedResult = "- 499ms a";
            expectObservable(installObservable).toBe(expectedResult, {
                a: {
                    progress: 0.8,
                },
            });
        });
    });
    test("On too many errors, it should retry with a delay but finally throw the error", () => {
        const retryLimit = 3;
        testScheduler.run(({ cold, expectObservable }) => {
            let count = 0;
            const fakeEvent = {
                type: "bulk-progress",
                progress: 0.8,
            };
            // The first time an error is thrown. The 2nd time a correct event is emitted.
            mockManagerApiInstall.mockReturnValueOnce((0, rxjs_1.defer)(() => {
                // A correct event is emitted only after the max number of retry attempts
                // which will be too late.
                if (count > retryLimit) {
                    return cold("a", {
                        a: fakeEvent,
                    });
                }
                count += 1;
                // Throws an error
                return cold("#");
            }));
            // The `transport` and `app` can be fake as the ManagerAPI.install is mocked
            const installObservable = (0, installApp_1.default)((0, hw_transport_mocker_1.aTransportBuilder)(), "target-test", (0, anApp_1.anAppBuilder)(), {
                retryDelayMs: 500,
                retryLimit,
            });
            const expectedResult = "- 499ms - 499ms - 499ms #";
            expectObservable(installObservable).toBe(expectedResult);
        });
    });
    test("On a locked device error, it should not retry and throw directly the error", () => {
        const lockedDeviceErrors = [
            new errors_1.LockedDeviceError(),
            new errors_1.ManagerDeviceLockedError(),
            new errors_1.UnresponsiveDeviceError(),
        ];
        for (const error of lockedDeviceErrors) {
            testScheduler.run(({ cold, expectObservable }) => {
                let count = 0;
                const fakeEvent = {
                    type: "bulk-progress",
                    progress: 0.8,
                };
                // The first time an error is thrown. The 2nd time a correct event is emitted.
                mockManagerApiInstall.mockReturnValueOnce((0, rxjs_1.defer)(() => {
                    if (count > 0) {
                        return cold("a", {
                            a: fakeEvent,
                        });
                    }
                    count += 1;
                    // Throws an error
                    return cold("#", undefined, error);
                }));
                // The `transport` and `app` can be fake as the ManagerAPI.install is mocked
                const installObservable = (0, installApp_1.default)((0, hw_transport_mocker_1.aTransportBuilder)(), "target-test", (0, anApp_1.anAppBuilder)(), {
                    retryDelayMs: 500,
                    retryLimit: 1,
                });
                // It emits the error without any retry
                const expectedResult = "#";
                expectObservable(installObservable).toBe(expectedResult, undefined, error);
            });
        }
    });
});
//# sourceMappingURL=installApp.test.js.map