"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const hw_transport_1 = __importDefault(require("@ledgerhq/hw-transport"));
const core_1 = require("./core");
const rxjs_1 = require("rxjs");
jest.useFakeTimers();
// Only mocks `open`
jest.mock("../../hw/index", () => {
    // Imports and retains the original functionalities
    const originalModule = jest.requireActual("../../hw/index");
    return {
        ...originalModule,
        open: jest.fn().mockReturnValue(Promise.resolve(new hw_transport_1.default())),
    };
});
const deviceId = "test_device";
describe("withTransport", () => {
    describe("When there is only 1 job", () => {
        it("should provide a transport and run the given job", done => {
            const job = jest.fn().mockReturnValue((0, rxjs_1.of)("job test result"));
            (0, core_1.withTransport)(deviceId)(job).subscribe({
                next: () => {
                    try {
                        expect(job).toHaveBeenCalledWith({
                            transportRef: expect.objectContaining({ current: expect.any(hw_transport_1.default) }),
                        });
                        done();
                    }
                    catch (expectError) {
                        done(expectError);
                    }
                },
                error: e => done(`It should not have failed: ${JSON.stringify(e)}`),
            });
        });
    });
    describe("When a 2nd job is trying to run while another job is ongoing", () => {
        describe("And the 1st job is successful", () => {
            it("should run the 2 jobs sequentially", done => {
                const job1Duration = 1000;
                // Mocking rxjs timer is difficult -> using `setTimeout` instead of a rxjs `delay`
                const job1 = jest.fn().mockReturnValue((0, rxjs_1.from)(new Promise(resolve => {
                    setTimeout(() => resolve("job 1 test result"), job1Duration);
                })));
                const job2 = jest.fn().mockReturnValue((0, rxjs_1.of)("job 2 test result"));
                let job1_ended = false;
                // Registers first the job1
                (0, core_1.withTransport)(deviceId)(job1).subscribe({
                    next: () => {
                        job1_ended = true;
                    },
                    error: e => done(`It should not have failed: ${JSON.stringify(e)}`),
                });
                // And then job2, that should wait that job1 is finished
                (0, core_1.withTransport)(deviceId)(job2).subscribe({
                    next: () => {
                        try {
                            // job1 should have been called before
                            expect(job1).toHaveBeenCalledWith({
                                transportRef: expect.objectContaining({ current: expect.any(hw_transport_1.default) }),
                            });
                            expect(job2).toHaveBeenCalledWith({
                                transportRef: expect.objectContaining({ current: expect.any(hw_transport_1.default) }),
                            });
                            done();
                        }
                        catch (expectError) {
                            done(expectError);
                        }
                    },
                    error: e => done(`It should not have failed: ${JSON.stringify(e)}`),
                });
                // job 1 should not have started yet
                expect(job1_ended).toBe(false);
                // Advances job 1
                jest.advanceTimersByTime(job1Duration);
            });
        });
        describe("And the 1st job failed", () => {
            it("should still run the 2 jobs sequentially", done => {
                const job1Duration = 1000;
                // Mocking rxjs timer is difficult -> using `setTimeout` instead of a rxjs `delay`
                const job1 = jest.fn().mockReturnValue((0, rxjs_1.from)(
                // This time, job 1 failed
                new Promise((_resolve, reject) => {
                    setTimeout(() => reject("job 1 failed"), job1Duration);
                })));
                const job2 = jest.fn().mockReturnValue((0, rxjs_1.of)("job 2 test result"));
                let job1_ended = false;
                // Registers first the job1
                (0, core_1.withTransport)(deviceId)(job1).subscribe({
                    next: () => {
                        done(`Job 1 should not have succeeded`);
                    },
                    error: _e => {
                        job1_ended = true;
                    },
                });
                // And then job2, that should wait that job1 is finished
                (0, core_1.withTransport)(deviceId)(job2).subscribe({
                    next: () => {
                        try {
                            // job1 should have been called before
                            expect(job1).toHaveBeenCalledWith({
                                transportRef: expect.objectContaining({ current: expect.any(hw_transport_1.default) }),
                            });
                            expect(job2).toHaveBeenCalledWith({
                                transportRef: expect.objectContaining({ current: expect.any(hw_transport_1.default) }),
                            });
                            done();
                        }
                        catch (expectError) {
                            done(expectError);
                        }
                    },
                    error: e => done(`It should not have failed: ${JSON.stringify(e)}`),
                });
                // job 1 should not have started yet
                expect(job1_ended).toBe(false);
                // Advances job 1
                jest.advanceTimersByTime(job1Duration);
            });
        });
    });
});
//# sourceMappingURL=core.test.js.map