diff --git a/libs/api-devices-testing/.babelrc b/libs/api-devices-testing/.babelrc new file mode 100644 index 000000000..1ea870ead --- /dev/null +++ b/libs/api-devices-testing/.babelrc @@ -0,0 +1,12 @@ +{ + "presets": [ + [ + "@nx/react/babel", + { + "runtime": "automatic", + "useBuiltIns": "usage" + } + ] + ], + "plugins": [] +} diff --git a/libs/api-devices-testing/.eslintrc.json b/libs/api-devices-testing/.eslintrc.json new file mode 100644 index 000000000..d3e61a2ea --- /dev/null +++ b/libs/api-devices-testing/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": ["../../.eslintrc.js"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/libs/api-devices-testing/README.md b/libs/api-devices-testing/README.md new file mode 100644 index 000000000..c6a5fb15c --- /dev/null +++ b/libs/api-devices-testing/README.md @@ -0,0 +1,7 @@ +# api-devices-testing + +This library was generated with [Nx](https://nx.dev). + +## Running unit tests + +Run `nx test api-devices-testing` to execute the unit tests via [Jest](https://jestjs.io). diff --git a/libs/api-devices-testing/jest.config.ts b/libs/api-devices-testing/jest.config.ts new file mode 100644 index 000000000..a64a8d301 --- /dev/null +++ b/libs/api-devices-testing/jest.config.ts @@ -0,0 +1,12 @@ +/* eslint-disable */ +export default { + displayName: "api-devices-testing", + preset: "../../jest.preset.js", + transform: { + "^(?!.*\\.(js|jsx|ts|tsx|css|json)$)": "@nx/react/plugins/jest", + "^.+\\.[tj]sx?$": ["babel-jest", { presets: ["@nx/react/babel"] }], + }, + moduleFileExtensions: ["ts", "tsx", "js", "jsx"], + coverageDirectory: "../../coverage/libs/api-devices-testing", + maxWorkers: 1, +} diff --git a/libs/api-devices-testing/project.json b/libs/api-devices-testing/project.json new file mode 100644 index 000000000..1e16cc357 --- /dev/null +++ b/libs/api-devices-testing/project.json @@ -0,0 +1,20 @@ +{ + "name": "api-devices-testing", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/api-devices-testing/src", + "projectType": "library", + "tags": [], + "targets": { + "lint": { + "executor": "@nx/eslint:lint", + "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "libs/api-devices-testing/jest.config.ts" + } + } + } +} diff --git a/libs/api-devices-testing/src/lib/api-configuration.spec.tsx b/libs/api-devices-testing/src/lib/api-configuration.spec.tsx new file mode 100644 index 000000000..42dc16fbe --- /dev/null +++ b/libs/api-devices-testing/src/lib/api-configuration.spec.tsx @@ -0,0 +1,50 @@ +/** + * Copyright (c) Mudita sp. z o.o. All rights reserved. + * For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md + */ + +import { DeviceProtocol } from "device-protocol/feature" +import { setKompaktConnection } from "./helpers/set-connection" +import { APIConfigService } from "device/feature" + +jest.mock("shared/utils", () => { + return { callRenderer: () => {} } +}) +jest.mock("Core/device-manager/services/usb-devices/usb-devices.helper", () => { + return { getUsbDevices: () => {} } +}) +jest.mock("electron-better-ipc", () => { + return { + ipcMain: { + emit: () => {}, + }, + } +}) + +describe("API configuration", () => { + let deviceProtocol: DeviceProtocol | undefined = undefined + + beforeEach(async () => { + deviceProtocol = await setKompaktConnection() + }) + + afterEach(async () => { + await deviceProtocol?.activeDevice?.disconnect() + }, 10000) + + it("should receive API configuration", async () => { + expect(deviceProtocol?.devices).toHaveLength(1) + + if (deviceProtocol === undefined) { + return + } + + deviceProtocol.setActiveDevice(deviceProtocol.devices[0].id) + + const apiConfigService = new APIConfigService(deviceProtocol) + + const result = await apiConfigService.getAPIConfig() + + expect(result.ok).toBeTruthy() + }) +}) diff --git a/libs/api-devices-testing/src/lib/connection.spec.tsx b/libs/api-devices-testing/src/lib/connection.spec.tsx new file mode 100644 index 000000000..ad852ae6c --- /dev/null +++ b/libs/api-devices-testing/src/lib/connection.spec.tsx @@ -0,0 +1,49 @@ +/** + * Copyright (c) Mudita sp. z o.o. All rights reserved. + * For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md + */ + +import { + DeviceProtocol, + DeviceResolverService, + SerialPortService, +} from "device-protocol/feature" +import { EventEmitter } from "events" + +jest.mock("shared/utils", () => { + return { callRenderer: () => {} } +}) +jest.mock("Core/device-manager/services/usb-devices/usb-devices.helper", () => { + return { getUsbDevices: () => {} } +}) + +describe("Connection", () => { + it.each([{ vendorId: "0e8d", productId: "200a" }])( + "should connect successfully", + async ({ vendorId, productId }) => { + const eventEmitter = new EventEmitter() + + const deviceProtocol = new DeviceProtocol( + new SerialPortService(), + new DeviceResolverService(), + eventEmitter + ) + expect(deviceProtocol.devices).toHaveLength(0) + const attachedDevice = (await deviceProtocol.getAttachedDevices()).find( + (port) => { + return port.vendorId === vendorId && port.productId === productId + } + ) + + expect(attachedDevice).toBeTruthy() + if (attachedDevice === undefined) { + return + } + + await deviceProtocol.addDevice(attachedDevice) + + expect(deviceProtocol.devices).toHaveLength(1) + await deviceProtocol.activeDevice?.disconnect() + } + ) +}) diff --git a/libs/api-devices-testing/src/lib/helpers/set-connection.ts b/libs/api-devices-testing/src/lib/helpers/set-connection.ts new file mode 100644 index 000000000..4e3193f3c --- /dev/null +++ b/libs/api-devices-testing/src/lib/helpers/set-connection.ts @@ -0,0 +1,38 @@ +/** + * Copyright (c) Mudita sp. z o.o. All rights reserved. + * For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md + */ + +import { + DeviceProtocol, + DeviceResolverService, + SerialPortService, +} from "device-protocol/feature" +import { EventEmitter } from "events" + +export const setConnection = async (vendorId: string, productId: string) => { + const eventEmitter = new EventEmitter() + + const deviceProtocol = new DeviceProtocol( + new SerialPortService(), + new DeviceResolverService(), + eventEmitter + ) + const attachedDevice = (await deviceProtocol.getAttachedDevices()).find( + (port) => { + return port.vendorId === vendorId && port.productId === productId + } + ) + + if (attachedDevice === undefined) { + return + } + + await deviceProtocol.addDevice(attachedDevice) + + return deviceProtocol +} + +export const setKompaktConnection = () => { + return setConnection("0e8d", "200a") +} diff --git a/libs/api-devices-testing/tsconfig.json b/libs/api-devices-testing/tsconfig.json new file mode 100644 index 000000000..3c41f10fb --- /dev/null +++ b/libs/api-devices-testing/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "allowJs": false, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "extends": "../../tsconfig.base.json" +} diff --git a/libs/api-devices-testing/tsconfig.lib.json b/libs/api-devices-testing/tsconfig.lib.json new file mode 100644 index 000000000..cfc484329 --- /dev/null +++ b/libs/api-devices-testing/tsconfig.lib.json @@ -0,0 +1,24 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": [ + "node", + + "@nx/react/typings/cssmodule.d.ts", + "@nx/react/typings/image.d.ts" + ] + }, + "exclude": [ + "jest.config.ts", + "src/**/*.spec.ts", + "src/**/*.test.ts", + "src/**/*.spec.tsx", + "src/**/*.test.tsx", + "src/**/*.spec.js", + "src/**/*.test.js", + "src/**/*.spec.jsx", + "src/**/*.test.jsx" + ], + "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"] +} diff --git a/libs/api-devices-testing/tsconfig.spec.json b/libs/api-devices-testing/tsconfig.spec.json new file mode 100644 index 000000000..26ef046ac --- /dev/null +++ b/libs/api-devices-testing/tsconfig.spec.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.test.tsx", + "src/**/*.spec.tsx", + "src/**/*.test.js", + "src/**/*.spec.js", + "src/**/*.test.jsx", + "src/**/*.spec.jsx", + "src/**/*.d.ts" + ] +} diff --git a/libs/core/device/modules/base-device.ts b/libs/core/device/modules/base-device.ts index f96532fd3..29b743cab 100644 --- a/libs/core/device/modules/base-device.ts +++ b/libs/core/device/modules/base-device.ts @@ -41,6 +41,10 @@ export abstract class BaseDevice { abstract connect(): Promise> + public disconnect(): Promise { + return Promise.resolve() + } + abstract request(config: unknown): Promise private generateDeviceIdBySerialNumber = ( diff --git a/libs/core/device/modules/base.adapter.ts b/libs/core/device/modules/base.adapter.ts index 88c54471e..94429ffdb 100644 --- a/libs/core/device/modules/base.adapter.ts +++ b/libs/core/device/modules/base.adapter.ts @@ -34,6 +34,7 @@ export abstract class BaseAdapter< return new Promise((resolve) => { const serialPort = new SerialPort(this.path, (error) => { if (error) { + console.error(error) resolve( Result.failed( new AppError(DeviceError.Initialization, error.message) diff --git a/libs/device-protocol/feature/src/services/device-protocol.ts b/libs/device-protocol/feature/src/services/device-protocol.ts index 762904338..f7db404ca 100644 --- a/libs/device-protocol/feature/src/services/device-protocol.ts +++ b/libs/device-protocol/feature/src/services/device-protocol.ts @@ -106,7 +106,6 @@ export class DeviceProtocol { } public async addDevice(port: PortInfo): Promise { - console.log("===== addDevice =====") await this.mutex.runExclusive(async () => { await this.addDeviceTask(port) }) diff --git a/libs/device/adapters/src/lib/serial-port-api-device.ts b/libs/device/adapters/src/lib/serial-port-api-device.ts index 1af4e052b..9375c0de2 100644 --- a/libs/device/adapters/src/lib/serial-port-api-device.ts +++ b/libs/device/adapters/src/lib/serial-port-api-device.ts @@ -44,6 +44,7 @@ export class SerialPortDeviceAPIAdapter { return new Promise((resolve) => { const serialPort = new SerialPort(this.path, (error) => { if (error) { + console.error(error) resolve( Result.failed( new AppError(DeviceError.Initialization, error.message) @@ -58,6 +59,17 @@ export class SerialPortDeviceAPIAdapter { }) } + public closeConnection() { + return new Promise((resolve) => { + if (this.serialPort) { + this.serialPort.close((error) => { + resolve(undefined) + }) + } + resolve(undefined) + }) + } + public async request(config: APIRequestData) { if (this.serialPort === undefined) { return Result.failed( @@ -222,7 +234,6 @@ export class SerialPortDeviceAPIAdapter { ) } }) - this.serialPort.on("close", () => { callRenderer( ApiSerialPortToRendererEvents.Closed, diff --git a/libs/device/feature/src/lib/api-device.ts b/libs/device/feature/src/lib/api-device.ts index 3d95738c8..2b46e3014 100644 --- a/libs/device/feature/src/lib/api-device.ts +++ b/libs/device/feature/src/lib/api-device.ts @@ -30,6 +30,10 @@ export class APIDevice extends BaseDevice { return this.adapter.connect() } + override disconnect() { + return this.adapter.closeConnection() + } + public request( config: APIRequestWithPayload ) { diff --git a/nx.json b/nx.json index 426779638..ebe2de2c4 100644 --- a/nx.json +++ b/nx.json @@ -1,4 +1,9 @@ { + "pluginsConfig": { + "@nx/js": { + "analyzeSourceFiles": true + } + }, "extends": "nx/presets/npm.json", "$schema": "./node_modules/nx/schemas/nx-schema.json", "tasksRunnerOptions": { @@ -39,10 +44,5 @@ } } } - }, - "pluginsConfig": { - "@nx/js": { - "analyzeSourceFiles": true - } } } diff --git a/package.json b/package.json index d8b8c1a80..bfb5cea90 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "app:translations:sync": "nx translations:sync mudita-center", "test": "npm run test:nx && npm run test:core", "test:core": "cross-env TZ=UTC jest --config=jest/jest.config.js", - "test:nx": "nx run-many --target=test", + "test:nx": "nx run-many --target=test --exclude api-devices-testing", "lint": "npm run lint:js && npm run lint:css", "lint:css": "cross-env stylelint '{libs,apps/mudita-center/src}/**/*.{ts,tsx}'", "lint:fix": "npm run lint:js -- --fix", @@ -37,7 +37,8 @@ "e2e:test:cicd:standalone": "xvfb-run --auto-servernum --server-args='-screen 0 1024x768x24' nx e2e:test:cicd:standalone mudita-center-e2e", "e2e:test:cicd:mock": "xvfb-run --auto-servernum --server-args='-screen 0 1024x768x24' nx e2e:test:cicd:mock mudita-center-e2e", "test-file:generate-and-push": "ts-node scripts/manage-test-files/generate-and-push-test-files.ts", - "test-file:clear": "ts-node scripts/manage-test-files/clear-test-files.ts" + "test-file:clear": "ts-node scripts/manage-test-files/clear-test-files.ts", + "api-device-testing": "npx nx run api-devices-testing:test" }, "repository": { "type": "git", diff --git a/tsconfig.base.json b/tsconfig.base.json index 735a100be..bcf62d5c5 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -34,6 +34,7 @@ "active-device-registry/models": [ "libs/active-device-registry/models/src/index.ts" ], + "api-devices-testing": ["libs/api-devices-testing/src/index.ts"], "core-device/feature": ["libs/core-device/feature/src/index.ts"], "core-device/models": ["libs/core-device/models/src/index.ts"], "device-manager/feature": ["libs/device-manager/feature/src/index.ts"],