Open jmbldwn opened 11 months ago
I experienced the same situation and workout an ugly workaround, hopefully this will help anyone who needs it
port.on('open', () => {
port.port.write = async (buffer) => {
this.writeOperation = Promise.resolve(buffer).then(buff => port.port.emitData(buff)); // do something before emit
return this.writeOperation;
}
}
💥 Proposal
What feature you'd like to see
Mocking currently only supports echoing and explicit reading of history once a port is opened. Provide a "back end" stream interface so we can emulate actual serial devices connected to mock ports.
Motivation
I am building unit tests for the code I write that talks to real serial port devices. Unit tests can't easily run in an environment where there is physical hardware, so we need a way to not only emulate the port, but the protocol the device implements over it.
Pitch
I currently have no unit tests for any of the code I wrote that uses SerialPort to talk to hardware devices. For example, I have a power meter (PZEM), an M-Bus interface, some custom Arduino devices, including a burning man LED display, and several lab meters that run over serial. I want to write emulators for the protocols my devices use so I can create unit tests that can run under CI, in my case using Jest.
The mocking interface falls just short of letting me do what I need. I can substitute SerialPortMock in place of SerialPort using Jest mocking, which lets me create mock ports ('/dev/ROBOT') that my target code will try to open. My target code can open one of those ports, but I have no way of interacting with my target code as if it were talking to a real device.
One approach is to provide a stream interface from a mock port (MockBinding.create...) which I can use to listen for data my target code is sending, and send responses to it. This stream interface would talk to any instance of SerialPortMock that opens that ports, so it would persist across port instances.
I could also extend MockPortBinding to implement my device class by overriding
write
, but there's no way to getMockBinding.createPort
to use my class. If I could specify the port binding to be returned by createPort that would do the trick.I can't extend MockBinding because it's not a class, and I'd end up rewriting most of what it does.
I defer to the core implementers on the best way to achieve this, and indeed if I'm missing something let me know.