diff --git a/src/api.ts b/src/api.ts index a5ad20a..07d808f 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,4 +1,4 @@ -import { SerialPort } from 'serialport'; +import { SerialPort, SerialPortMock } from 'serialport'; import SerialProcessor from './SerialProcessor'; import { decodeBase64, randomId } from './utils'; @@ -14,18 +14,7 @@ type ProcessingFunctionReturnValue = { }; class API { - constructor(private serialPort: SerialPort) {} - - async waitAPIready(timeout: number = 2000) { - const serialProcessor = new SerialProcessor(this.serialPort, (data) => { - if (data.startsWith('{"m":0')) { - return { resolve: true }; - } - return { resolve: false }; - }); - - return serialProcessor.sendAndProcess('\x04', timeout); - } + constructor(private serialPort: SerialPort | SerialPortMock) {} async sendRequest( request: string, @@ -85,20 +74,18 @@ class API { } export function APIRequest( - serialPort: SerialPort, + serialPort: SerialPort | SerialPortMock, request: string, params: object = {}, timeout_in_ms: number = 5000, cmdResolver?: (line: string) => ProcessingFunctionReturnValue, + reqId?: string, ) { return new API(serialPort).sendRequest( request, params, timeout_in_ms, cmdResolver, + reqId, ); } - -export const _testing = { - API, -}; diff --git a/src/test/api.test.ts b/src/test/api.test.ts index 857aff0..0d74853 100644 --- a/src/test/api.test.ts +++ b/src/test/api.test.ts @@ -1,137 +1,126 @@ -// import * as chai from 'chai'; -// import { _testing } from '../api'; -// import { SerialPort, SerialPortMock } from 'serialport'; - -// const expect = chai.expect; - -// const API = _testing.API; - -// suite('API Test Suite', function () { -// const defaultPortName = '/dev/echoserialport'; - -// const createPortMock = (data: string, opts?: any) => { -// return SerialPortMock.binding.createPort(defaultPortName, { -// echo: true, -// record: true, -// ...opts, -// readyData: Buffer.from(data), -// }); -// }; - -// suite('Waits for the API to be ready', function () { -// test.only('Waits for API to be ready', async function () { -// createPortMock('{"m":0, "r": "response", "i": "1234"}\r'); -// const port = new SerialPort({ path: defaultPortName, baudRate: 9600 }); -// const api = new API(port); - -// await api.waitAPIready(); - -// const portMock = await SerialPortMock.binding.open({ -// path: defaultPortName, -// baudRate: 9600, -// }); -// expect(portMock.recording.toString()).to.equal('\x04\r'); -// }); - -// test('Times out if the device does not emit the correct sequence', async function () { -// createPortMock(''); -// const port = new SerialPort({ path: defaultPortName, baudRate: 9600 }); -// const api = new API(port); - -// try { -// await api.waitAPIready(500); -// } catch (error) { -// expect(error).instanceOf(Error); -// expect((error as Error).message).to.equal( -// "Timeout while processing message '\x04'", -// ); -// } -// }); -// }); - -// suite('Sends request', function () { -// test('and retrieve the corresponding response', async function () { -// const reqId = '1234'; - -// createPortMock(`{"m":0, "r": "response", "i": "${reqId}"}\r`); -// const portMock = await SerialPortMock.binding.open({ -// path: defaultPortName, -// baudRate: 9600, -// }); -// const port = new SerialPort({ path: defaultPortName, baudRate: 9600 }); -// const api = new API(port); - -// const response = await api.sendRequest( -// 'request', -// { param1: '1', param2: 2 }, -// 500, -// undefined, -// reqId, -// ); - -// expect(portMock.recording.toString()).to.equal( -// '{"m":"request","p":{"param1":"1","param2":2},"i":"1234"}\r', -// ); -// expect(response).to.equal('response'); -// }); - -// test('and raises an exception in case of error', async function () { -// const reqId = '1234'; - -// createPortMock( -// `{"m":0, "e": "eyJtZXNzYWdlIjogImVycm9yIn0=", "i": "${reqId}"}\r`, -// ); -// const portMock = await SerialPortMock.binding.open({ -// path: defaultPortName, -// baudRate: 9600, -// }); -// const port = new SerialPort({ path: defaultPortName, baudRate: 9600 }); -// const api = new API(port); - -// try { -// await api.sendRequest( -// 'request', -// { param1: '1', param2: 2 }, -// 500, -// undefined, -// reqId, -// ); -// } catch (error) { -// expect(portMock.recording.toString()).to.equal( -// '{"m":"request","p":{"param1":"1","param2":2},"i":"1234"}\r', -// ); -// expect(error).instanceOf(Error); -// expect((error as Error).message).to.equal('error'); -// } -// }); - -// test('and times out if the response does not come back in time', async function () { -// const reqId = '1234'; -// createPortMock('', { echo: false }); -// const portMock = await SerialPortMock.binding.open({ -// path: defaultPortName, -// baudRate: 9600, -// }); -// const port = new SerialPort({ path: defaultPortName, baudRate: 9600 }); -// const api = new API(port); - -// try { -// await api.sendRequest( -// 'request', -// { param1: '1', param2: 2 }, -// 500, -// undefined, -// reqId, -// ); -// } catch (error) { -// expect(portMock.recording.toString()).to.equal( -// '{"m":"request","p":{"param1":"1","param2":2},"i":"1234"}\r', -// ); -// expect(error).instanceOf(Error); -// expect((error as Error).message).to.equal( -// 'Timeout while processing message \'{"m":"request","p":{"param1":"1","param2":2},"i":"1234"}\'', -// ); -// } -// }); -// }); -// }); +import { expect } from 'chai'; +import { APIRequest } from '../api'; +import { SerialPortMock } from 'serialport'; + +describe('API Test Suite', function () { + const defaultPortName = '/dev/echoserialport'; + + const createPortMock = (data: string, opts?: any) => { + return SerialPortMock.binding.createPort(defaultPortName, { + echo: true, + record: true, + ...opts, + readyData: Buffer.from(data), + }); + }; + + describe('Sends request', function () { + it('retrieves the corresponding response', async function () { + const reqId = '1234'; + createPortMock(`{"m":0, "r": "response", "i": "${reqId}"}\r`); + const portMock = new SerialPortMock({ + path: defaultPortName, + baudRate: 9600, + }); + const response = await APIRequest( + portMock, + 'request', + { param1: '1', param2: 2 }, + 500, + undefined, + reqId, + ); + + expect(portMock.port?.recording.toString()).to.equal( + '{"m":"request","p":{"param1":"1","param2":2},"i":"1234"}\r', + ); + expect(response).to.equal('response'); + }); + + it('raises an exception in case of error', async function () { + const reqId = '1234'; + + createPortMock( + `{"m":0, "e": "eyJtZXNzYWdlIjogImVycm9yIn0=", "i": "${reqId}"}\r`, + ); + const portMock = new SerialPortMock({ + path: defaultPortName, + baudRate: 9600, + }); + + try { + await APIRequest( + portMock, + 'request', + { param1: '1', param2: 2 }, + 500, + undefined, + reqId, + ); + } catch (error) { + expect(portMock.port?.recording.toString()).to.equal( + '{"m":"request","p":{"param1":"1","param2":2},"i":"1234"}\r', + ); + expect(error).instanceOf(Error); + expect((error as Error).message).to.equal('error'); + } + }); + + it("times out if the response doesn't come back in time", async function () { + const reqId = '1234'; + createPortMock('', { echo: false }); + const portMock = new SerialPortMock({ + path: defaultPortName, + baudRate: 9600, + }); + + try { + await APIRequest( + portMock, + 'request', + { param1: '1', param2: 2 }, + 20, + undefined, + reqId, + ); + } catch (error) { + expect(portMock.port?.recording.toString()).to.equal( + '{"m":"request","p":{"param1":"1","param2":2},"i":"1234"}\r', + ); + expect(error).instanceOf(Error); + expect((error as Error).message).to.equal( + 'Timeout while processing message \'{"m":"request","p":{"param1":"1","param2":2},"i":"1234"}\'', + ); + } + }); + + it('uses the command resolver if provided', async function () { + const reqId = '1234'; + createPortMock( + `A line\r\nAnother line\r\ntreasure\r\nAnd a final line\r\n`, + ); + const portMock = new SerialPortMock({ + path: defaultPortName, + baudRate: 9600, + }); + const response = await APIRequest( + portMock, + 'request', + { param1: '1', param2: 2 }, + 500, + (line) => { + if (line.includes('treasure')) { + return { resolve: true, returnValue: 'Success' }; + } + return { resolve: false }; + }, + reqId, + ); + + expect(portMock.port?.recording.toString()).to.equal( + '{"m":"request","p":{"param1":"1","param2":2},"i":"1234"}\r', + ); + expect(response).to.equal('Success'); + }); + }); +});