Skip to content

Commit

Permalink
feat: add flush() method, resolves #106
Browse files Browse the repository at this point in the history
  • Loading branch information
nytamin committed Dec 5, 2024
1 parent b3d2f39 commit f0ade46
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 0 deletions.
3 changes: 3 additions & 0 deletions packages/core/src/genericHIDDevice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@ export interface HIDDevice {

write(data: number[]): void

/** Returns a promise which settles when all writes has completed */
flush(): Promise<void>

close(): Promise<void>
}
6 changes: 6 additions & 0 deletions packages/core/src/xkeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,12 @@ export class XKeys extends EventEmitter {
public writeData(message: HIDMessage): void {
this._write(message)
}
/**
* Returns a Promise that settles when all writes have been completed
*/
public async flush(): Promise<void> {
await this.device.flush()
}

/** (Internal function) Called when there has been detected that the device has been disconnected */
public async _handleDeviceDisconnected(): Promise<void> {
Expand Down
91 changes: 91 additions & 0 deletions packages/node/src/__tests__/xkeys.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,95 @@ describe('Unit tests', () => {

expect(onError).toHaveBeenCalledTimes(0)
})
test('flush()', async () => {
const hidDevice = {
vendorId: XKeys.vendorId,
productId: 1029,
interface: 0,
path: 'mockPath',
} as HID.Device

const mockWriteStart = jest.fn()
const mockWriteEnd = jest.fn()
HIDMock.setMockWriteHandler(async (hid, message) => {
mockWriteStart()
await sleep(10)
mockWriteEnd()
handleXkeysMessages(hid, message)
})

const myXkeysPanel = await setupXkeysPanel(hidDevice)

const errorListener = jest.fn(console.error)
myXkeysPanel.on('error', errorListener)

mockWriteStart.mockClear()
mockWriteEnd.mockClear()

myXkeysPanel.toggleAllBacklights()

expect(mockWriteStart).toBeCalledTimes(1)
expect(mockWriteEnd).toBeCalledTimes(0) // Should not have been called yet

// cleanup:
await myXkeysPanel.flush() // waits for all writes to finish

expect(mockWriteEnd).toBeCalledTimes(1)

await myXkeysPanel.close() // close the device.
myXkeysPanel.off('error', errorListener)

expect(errorListener).toHaveBeenCalledTimes(0)
})
test('flush() with error', async () => {
const hidDevice = {
vendorId: XKeys.vendorId,
productId: 1029,
interface: 0,
path: 'mockPath',
} as HID.Device

const mockWriteStart = jest.fn()
const mockWriteEnd = jest.fn()
HIDMock.setMockWriteHandler(async (hid, message) => {
mockWriteStart()
await sleep(10)
mockWriteEnd()
// console.log('message', message)

if (message[0] === 0 && message[1] === 184) {
// toggleAllBacklights
throw new Error('Mock error')
}

handleXkeysMessages(hid, message)
})

const myXkeysPanel = await setupXkeysPanel(hidDevice)

const errorListener = jest.fn((e) => {
if (`${e}`.includes('Mock error')) return // ignore
console.error(e)
})
myXkeysPanel.on('error', errorListener)

mockWriteStart.mockClear()
mockWriteEnd.mockClear()

myXkeysPanel.toggleAllBacklights()

expect(mockWriteStart).toBeCalledTimes(1)
expect(errorListener).toBeCalledTimes(0) // Should not have been called yet

// cleanup:
await myXkeysPanel.flush() // waits for all writes to finish

expect(errorListener).toBeCalledTimes(1)
errorListener.mockClear()

await myXkeysPanel.close() // close the device.
myXkeysPanel.off('error', errorListener)

expect(errorListener).toHaveBeenCalledTimes(0)
})
})
3 changes: 3 additions & 0 deletions packages/node/src/node-hid-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ export class NodeHIDDevice extends EventEmitter implements HIDDevice {
this.device.removeListener('error', this._handleError)
this.device.removeListener('data', this._handleData)
}
public async flush(): Promise<void> {
await this.writeQueue.onIdle()
}

private _handleData = (data: Buffer) => {
this.emit('data', data)
Expand Down
3 changes: 3 additions & 0 deletions packages/webhid/src/web-hid-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ export class WebHIDDevice extends EventEmitter implements CoreHIDDevice {
this.emit('error', err)
})
}
public async flush(): Promise<void> {
await this.reportQueue.onIdle()
}

public async close(): Promise<void> {
await this.device.close()
Expand Down

0 comments on commit f0ade46

Please sign in to comment.