/* * Copyright (c) 2015 Nordic Semiconductor ASA * * SPDX-License-Identifier: LicenseRef-Nordic-4-Clause */ import React from 'react'; import { act, fireEvent, screen, waitFor } from '@testing-library/react'; import { OFFICIAL } from '../../../ipc/sources'; import packageJsonFromShared from '../../../package.json'; import render from '../../../test/testrenderer'; import { addDevice, type Device, removeDevice } from '../deviceSlice'; import { jprogDeviceSetup } from '../jprogOperations'; import DeviceSelector from './DeviceSelector'; jest.mock('../../../nrfutil/device/device'); jest.mock('../../utils/packageJson', () => ({ isLauncher: () => false, packageJson: () => packageJsonFromShared, })); const appDetails = Promise.resolve({ source: OFFICIAL }); jest.mock('../../utils/appDetails', () => ({ __esModule: true, default: () => appDetails, })); const DEVICE_SERIAL_NUMBER = '000000001'; const testDevice: Device = { id: 1, broken: null, usb: { serialNumber: DEVICE_SERIAL_NUMBER, manufacturer: 'testManufacturer', product: 'testProduct', osDevicePath: '/some-path', device: { busNumber: 2, address: 3, descriptor: { bcdDevice: 0, bDescriptorType: 4, idVendor: 5, idProduct: 6, }, configList: { descriptors: [], interfaceLists: [], length: 0, }, }, }, serialNumber: '000000001', serialPorts: [ { path: 'COM1', manufacturer: 'testManufacturer', productId: 'testProduct', serialNumber: '000000001', vendorId: 'testVendor', comName: 'COM1', vcom: 1, }, { path: 'COM2', manufacturer: 'testManufacturer', productId: 'testProduct', serialNumber: '000000001', vendorId: 'testVendor', comName: 'COM2', vcom: 2, }, ], favorite: false, traits: { jlink: true, }, devkit: { boardVersion: 'PCATest', deviceFamily: 'PCATest', }, }; const deviceSetupMock: ReturnType = { supportsProgrammingMode: jest.fn(() => true), getFirmwareOptions: jest.fn(() => [ { key: 'PCATest', programDevice: jest.fn() }, ]), isExpectedFirmware: jest.fn( (device: Device) => () => Promise.resolve({ device, validFirmware: false, }), ), tryToSwitchToApplicationMode: jest.fn(() => () => Promise.resolve(null)), }; const validFirmware = { deviceSetups: [deviceSetupMock], allowCustomDevice: false, }; describe('DeviceSelector', () => { it('has no device selected by default', () => { render( , ); expect(screen.getByText('Select device')).toBeInTheDocument(); }); it('shows an information when no devices are connected', () => { render( , ); fireEvent.click(screen.getByText('Select device')); expect(screen.getByText('Nordic development kit')).toBeInTheDocument(); }); it('shows a list of connected devices', () => { render( , [addDevice(testDevice)], ); expect(screen.getByText(DEVICE_SERIAL_NUMBER)).toBeInTheDocument(); }); it('does not show disconnected devices', () => { render( , [addDevice(testDevice), removeDevice(testDevice)], ); expect(screen.queryByText(DEVICE_SERIAL_NUMBER)).toBeNull(); }); it('shows more device info when selecting the expand button', () => { render( , [addDevice(testDevice)], ); fireEvent.click(screen.getByText('Select device')); fireEvent.click(screen.getByTestId('show-more-device-info')); expect(screen.getAllByText(/COM/)).toHaveLength(2); }); it('allows selecting a device', async () => { render( , [addDevice(testDevice)], ); fireEvent.click(screen.getByText('Select device')); // eslint-disable-next-line testing-library/no-unnecessary-act await act(async () => { await fireEvent.click(screen.getByText(DEVICE_SERIAL_NUMBER)); }); expect(screen.getAllByText(DEVICE_SERIAL_NUMBER)).toHaveLength(2); }); it('allows disconnecting a device', async () => { render( , [addDevice(testDevice)], ); fireEvent.click(screen.getByText('Select device')); fireEvent.click(screen.getByText(DEVICE_SERIAL_NUMBER)); await screen.findByTestId('disconnect-device'); fireEvent.click(screen.getByTestId('disconnect-device')); expect(screen.getAllByText(DEVICE_SERIAL_NUMBER)).toHaveLength(1); expect(screen.getByText('Select device')).toBeInTheDocument(); }); it('allows selecting a device when custom devices are enabled and no valid firmware is defined', async () => { render( , [addDevice(testDevice)], ); fireEvent.click(screen.getByText('Select device')); // eslint-disable-next-line testing-library/no-unnecessary-act await act(async () => { await fireEvent.click(screen.getByText(DEVICE_SERIAL_NUMBER)); }); expect(screen.queryByText('OK')).toBeNull(); expect(screen.getAllByText(DEVICE_SERIAL_NUMBER)).toHaveLength(2); }); it('allows deselecting a device when custom devices are disabled and no valid firmware is defined', async () => { render( , [addDevice(testDevice)], ); fireEvent.click(screen.getByText('Select device')); fireEvent.click(screen.getByText(DEVICE_SERIAL_NUMBER)); expect(screen.queryByText('OK')).toBeNull(); await waitFor(() => { expect(screen.getAllByText(DEVICE_SERIAL_NUMBER)).toHaveLength(1); }); await screen.findByText('Select device'); }); it('shows firmware prompt when a valid firmware is defined', async () => { render( , [addDevice(testDevice)], ); fireEvent.click(screen.getByText('Select device')); fireEvent.click(screen.getByText(DEVICE_SERIAL_NUMBER)); await screen.findByText( 'Device must be programmed. Do you want to proceed?', ); }); it('selects a device when cancelling firmware prompt', async () => { render( , [addDevice(testDevice)], ); fireEvent.click(screen.getByText('Select device')); fireEvent.click(screen.getByText(DEVICE_SERIAL_NUMBER)); await screen.findByText( 'Device must be programmed. Do you want to proceed?', ); fireEvent.click(screen.getByText('No')); expect( screen.queryByText( 'Device must be programmed. Do you want to proceed?', ), ).toBeNull(); expect(screen.getAllByText(DEVICE_SERIAL_NUMBER)).toHaveLength(2); }); });