"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
 * @jest-environment jsdom
 */
const react_1 = require("@testing-library/react");
const devices_1 = require("@ledgerhq/devices");
const useBleDevicesScanning_1 = require("./useBleDevicesScanning");
jest.useFakeTimers();
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const nanoXServiceUuid = (0, devices_1.getDeviceModel)(devices_1.DeviceModelId.nanoX).bluetoothSpec[0].serviceUuid;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const staxServiceUuid = (0, devices_1.getDeviceModel)(devices_1.DeviceModelId.stax).bluetoothSpec[0].serviceUuid;
// Fake devices info we would get from the bluetooth transport listen
const aTransportBleDevice = (overrideProps) => {
    return {
        id: "aBleNanoId",
        name: "aBleNano",
        localName: null,
        rssi: 50,
        mtu: 50,
        serviceUUIDs: [nanoXServiceUuid],
        ...overrideProps,
    };
};
const mockBleTransportListenUnsubscribe = jest.fn();
// HOF creating a mocked Transport listen method to be given to useBleDevicesScanning
const setupMockBleTransportListen = (mockEmitValuesByObserver) => (observer) => {
    mockEmitValuesByObserver(observer);
    return {
        unsubscribe: mockBleTransportListenUnsubscribe,
    };
};
describe("useBleDevicesScanning", () => {
    afterEach(() => {
        jest.clearAllTimers();
        mockBleTransportListenUnsubscribe.mockClear();
    });
    describe("When several unique devices are found by the scanner", () => {
        const deviceIdA = "ID_A";
        const deviceIdB = "ID_B";
        const deviceIdC = "ID_C";
        const mockEmitValuesByObserver = (observer) => {
            observer.next({
                type: "add",
                descriptor: aTransportBleDevice({ id: deviceIdA }),
            });
            setTimeout(() => {
                observer.next({
                    type: "add",
                    descriptor: aTransportBleDevice({
                        id: deviceIdB,
                        serviceUUIDs: [staxServiceUuid],
                    }),
                });
            }, 1000);
            setTimeout(() => {
                observer.next({
                    type: "add",
                    descriptor: aTransportBleDevice({ id: deviceIdC }),
                });
            }, 2000);
        };
        describe("and when no filters are applied to the scanning", () => {
            it("should update the list of scanned devices for each new scanned device", async () => {
                const { result } = (0, react_1.renderHook)(() => (0, useBleDevicesScanning_1.useBleDevicesScanning)({
                    bleTransportListen: setupMockBleTransportListen(mockEmitValuesByObserver),
                }));
                expect(result.current.scannedDevices).toHaveLength(1);
                expect(result.current.scannedDevices[0].deviceId).toBe(deviceIdA);
                // The model was correctly deduced from the ble spec
                expect(result.current.scannedDevices[0].deviceModel.id).toBe(devices_1.DeviceModelId.nanoX);
                await (0, react_1.act)(async () => {
                    jest.advanceTimersByTime(1000);
                });
                expect(result.current.scannedDevices).toHaveLength(2);
                expect(result.current.scannedDevices[1].deviceId).toBe(deviceIdB);
                expect(result.current.scannedDevices[1].deviceModel.id).toBe(devices_1.DeviceModelId.stax);
            });
        });
        describe("and when filterByDeviceModelIds is not null", () => {
            it("should filter the scanning result by the given model ids", async () => {
                const { result } = (0, react_1.renderHook)(() => (0, useBleDevicesScanning_1.useBleDevicesScanning)({
                    bleTransportListen: setupMockBleTransportListen(mockEmitValuesByObserver),
                    filterByDeviceModelIds: [devices_1.DeviceModelId.nanoX],
                }));
                // The first scanned device was a nanoX
                expect(result.current.scannedDevices).toHaveLength(1);
                expect(result.current.scannedDevices[0].deviceId).toBe(deviceIdA);
                // The model was correctly deduced from the ble spec
                expect(result.current.scannedDevices[0].deviceModel.id).toBe(devices_1.DeviceModelId.nanoX);
                await (0, react_1.act)(async () => {
                    jest.advanceTimersByTime(1000);
                });
                // The second scanned device was a stax, and was filtered out
                expect(result.current.scannedDevices).toHaveLength(1);
                await (0, react_1.act)(async () => {
                    jest.advanceTimersByTime(1000);
                });
                // The third scanned device was a nanoX
                expect(result.current.scannedDevices).toHaveLength(2);
                expect(result.current.scannedDevices[1].deviceId).toBe(deviceIdC);
                expect(result.current.scannedDevices[1].deviceModel.id).toBe(devices_1.DeviceModelId.nanoX);
            });
        });
        describe("and when filterOutDevicesByDeviceIds is not null nor empty", () => {
            it("should not add the scanned device if its ids is in the array", async () => {
                const { result } = (0, react_1.renderHook)(() => (0, useBleDevicesScanning_1.useBleDevicesScanning)({
                    bleTransportListen: setupMockBleTransportListen(mockEmitValuesByObserver),
                    filterOutDevicesByDeviceIds: [deviceIdA, deviceIdC],
                }));
                // The first scanned device (deviceIdA) should be filtered out
                expect(result.current.scannedDevices).toHaveLength(0);
                await (0, react_1.act)(async () => {
                    jest.advanceTimersByTime(1000);
                });
                // The second scanned device is deviceIdB and should be kept
                expect(result.current.scannedDevices).toHaveLength(1);
                expect(result.current.scannedDevices[0].deviceId).toBe(deviceIdB);
                await (0, react_1.act)(async () => {
                    jest.advanceTimersByTime(1000);
                });
                // The third scanned device (deviceIdC) should be filtered out
                expect(result.current.scannedDevices).toHaveLength(1);
            });
        });
        describe("and when the hook consumer stops the scanning", () => {
            it("should stop the scanning", async () => {
                let stopBleScanning = false;
                const { result, rerender } = (0, react_1.renderHook)(() => (0, useBleDevicesScanning_1.useBleDevicesScanning)({
                    bleTransportListen: setupMockBleTransportListen(mockEmitValuesByObserver),
                    stopBleScanning,
                }));
                // At first the scanning finds device(s)
                expect(result.current.scannedDevices).toHaveLength(1);
                expect(result.current.scannedDevices[0].deviceId).toBe(deviceIdA);
                expect(result.current.scannedDevices[0].deviceModel.id).toBe(devices_1.DeviceModelId.nanoX);
                // Then the consumer stops the scanning
                stopBleScanning = true;
                rerender({
                    bleTransportListen: setupMockBleTransportListen(mockEmitValuesByObserver),
                    stopBleScanning,
                });
                await (0, react_1.act)(async () => {
                    jest.advanceTimersByTime(2000);
                });
                // It should not find any new devices
                expect(result.current.scannedDevices).toHaveLength(1);
            });
        });
    });
    describe("When the same device is being scanned several times", () => {
        const deviceIdA = "ID_A";
        const deviceIdB = "ID_B";
        const mockEmitValuesByObserver = (observer) => {
            observer.next({
                type: "add",
                descriptor: aTransportBleDevice({ id: deviceIdA }),
            });
            setTimeout(() => {
                observer.next({
                    type: "add",
                    descriptor: aTransportBleDevice({ id: deviceIdA }),
                });
            }, 1000);
            setTimeout(() => {
                observer.next({
                    type: "add",
                    descriptor: aTransportBleDevice({ id: deviceIdB }),
                });
            }, 2000);
        };
        it("should update the list of scanned devices without any duplicate", async () => {
            const { result } = (0, react_1.renderHook)(() => (0, useBleDevicesScanning_1.useBleDevicesScanning)({
                bleTransportListen: setupMockBleTransportListen(mockEmitValuesByObserver),
            }));
            // The first time it gets the device from the scanning
            expect(result.current.scannedDevices).toHaveLength(1);
            expect(result.current.scannedDevices[0].deviceId).toBe(deviceIdA);
            expect(result.current.scannedDevices[0].deviceModel.id).toBe(devices_1.DeviceModelId.nanoX);
            await (0, react_1.act)(async () => {
                jest.advanceTimersByTime(1000);
            });
            // The second time it gets the same device from the scanning
            // It should not have been added to the list
            expect(result.current.scannedDevices).toHaveLength(1);
            await (0, react_1.act)(async () => {
                jest.advanceTimersByTime(1000);
            });
            // The third time it gets a new device
            expect(result.current.scannedDevices).toHaveLength(2);
            expect(result.current.scannedDevices[1].deviceId).toBe(deviceIdB);
            expect(result.current.scannedDevices[1].deviceModel.id).toBe(devices_1.DeviceModelId.nanoX);
        });
    });
    describe("When a device is only seen after a cleaned scanning", () => {
        const deviceIdA = "ID_A";
        const deviceIdB = "ID_B";
        const emitTimeOfDeviceB = 3000;
        const mockEmitValuesByObserver = (observer) => {
            observer.next({
                type: "add",
                descriptor: aTransportBleDevice({ id: deviceIdA }),
            });
            setTimeout(() => {
                observer.next({
                    type: "add",
                    descriptor: aTransportBleDevice({ id: deviceIdB }),
                });
            }, emitTimeOfDeviceB);
        };
        it("should restart the scanning after a defined time and update the list of scanned devices", async () => {
            const restartScanningTimeoutMs = emitTimeOfDeviceB;
            // To avoid re-rendering the hook when mockEmitValuesByObserver
            // emits a new value with the setTimeout
            const bleTransportListen = setupMockBleTransportListen(mockEmitValuesByObserver);
            const { result } = (0, react_1.renderHook)(() => (0, useBleDevicesScanning_1.useBleDevicesScanning)({
                bleTransportListen,
                restartScanningTimeoutMs,
            }));
            // The first time it gets the device from the scanning
            expect(result.current.scannedDevices).toHaveLength(1);
            expect(result.current.scannedDevices[0].deviceId).toBe(deviceIdA);
            expect(result.current.scannedDevices[0].deviceModel.id).toBe(devices_1.DeviceModelId.nanoX);
            const nbUnsubscribesHappeningBecauseOfRenderHook = mockBleTransportListenUnsubscribe.mock.calls.length;
            // Advances by less than the first restart timeout
            await (0, react_1.act)(async () => {
                jest.advanceTimersByTime(restartScanningTimeoutMs - 1000);
            });
            expect(mockBleTransportListenUnsubscribe).toBeCalledTimes(nbUnsubscribesHappeningBecauseOfRenderHook);
            // Advances by the total time of the restart timeout
            await (0, react_1.act)(async () => {
                jest.advanceTimersByTime(1000);
            });
            expect(mockBleTransportListenUnsubscribe).toBeCalledTimes(nbUnsubscribesHappeningBecauseOfRenderHook + 1);
            expect(result.current.scannedDevices).toHaveLength(2);
            expect(result.current.scannedDevices[1].deviceId).toBe(deviceIdB);
            expect(result.current.scannedDevices[1].deviceModel.id).toBe(devices_1.DeviceModelId.nanoX);
        });
    });
});
//# sourceMappingURL=useBleDevicesScanning.test.js.map