@risleylima/escpos 0.2.1 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/README.md +116 -755
  2. package/dist/adapter/index.d.ts +29 -0
  3. package/dist/adapter/index.d.ts.map +1 -0
  4. package/dist/adapter/index.js +25 -0
  5. package/dist/adapter/index.js.map +1 -0
  6. package/dist/index.d.ts +14 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +25 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/network-adapter/index.d.ts +24 -0
  11. package/dist/network-adapter/index.d.ts.map +1 -0
  12. package/dist/network-adapter/index.js +263 -0
  13. package/dist/network-adapter/index.js.map +1 -0
  14. package/dist/printer/commands-types.d.ts +37 -0
  15. package/dist/printer/commands-types.d.ts.map +1 -0
  16. package/dist/printer/commands-types.js +63 -0
  17. package/dist/printer/commands-types.js.map +1 -0
  18. package/dist/printer/commands.d.ts +169 -0
  19. package/dist/printer/commands.d.ts.map +1 -0
  20. package/dist/printer/commands.js +192 -0
  21. package/dist/printer/commands.js.map +1 -0
  22. package/dist/printer/image-loader.d.ts +17 -0
  23. package/dist/printer/image-loader.d.ts.map +1 -0
  24. package/dist/printer/image-loader.js +462 -0
  25. package/dist/printer/image-loader.js.map +1 -0
  26. package/dist/printer/image.d.ts +43 -0
  27. package/dist/printer/image.d.ts.map +1 -0
  28. package/dist/printer/image.js +132 -0
  29. package/dist/printer/image.js.map +1 -0
  30. package/dist/printer/index.d.ts +158 -0
  31. package/dist/printer/index.d.ts.map +1 -0
  32. package/dist/printer/index.js +703 -0
  33. package/dist/printer/index.js.map +1 -0
  34. package/dist/printer/profiles/bematech/mp4200th.d.ts +13 -0
  35. package/dist/printer/profiles/bematech/mp4200th.d.ts.map +1 -0
  36. package/dist/printer/profiles/bematech/mp4200th.js +29 -0
  37. package/dist/printer/profiles/bematech/mp4200th.js.map +1 -0
  38. package/dist/printer/profiles/custom/bematech-mp4200th.d.ts +13 -0
  39. package/dist/printer/profiles/custom/bematech-mp4200th.d.ts.map +1 -0
  40. package/dist/printer/profiles/custom/bematech-mp4200th.js +21 -0
  41. package/dist/printer/profiles/custom/bematech-mp4200th.js.map +1 -0
  42. package/dist/printer/profiles/custom/vkp80iii.d.ts +19 -0
  43. package/dist/printer/profiles/custom/vkp80iii.d.ts.map +1 -0
  44. package/dist/printer/profiles/custom/vkp80iii.js +87 -0
  45. package/dist/printer/profiles/custom/vkp80iii.js.map +1 -0
  46. package/dist/printer/profiles/default.d.ts +7 -0
  47. package/dist/printer/profiles/default.d.ts.map +1 -0
  48. package/dist/printer/profiles/default.js +15 -0
  49. package/dist/printer/profiles/default.js.map +1 -0
  50. package/dist/printer/profiles/index.d.ts +41 -0
  51. package/dist/printer/profiles/index.d.ts.map +1 -0
  52. package/dist/printer/profiles/index.js +98 -0
  53. package/dist/printer/profiles/index.js.map +1 -0
  54. package/dist/printer/profiles/merge.d.ts +7 -0
  55. package/dist/printer/profiles/merge.d.ts.map +1 -0
  56. package/dist/printer/profiles/merge.js +58 -0
  57. package/dist/printer/profiles/merge.js.map +1 -0
  58. package/dist/printer/profiles/types.d.ts +99 -0
  59. package/dist/printer/profiles/types.d.ts.map +1 -0
  60. package/dist/printer/profiles/types.js +8 -0
  61. package/dist/printer/profiles/types.js.map +1 -0
  62. package/dist/printer/utils.d.ts +9 -0
  63. package/dist/printer/utils.d.ts.map +1 -0
  64. package/dist/printer/utils.js +54 -0
  65. package/dist/printer/utils.js.map +1 -0
  66. package/dist/serial-adapter/index.d.ts +21 -0
  67. package/dist/serial-adapter/index.d.ts.map +1 -0
  68. package/dist/serial-adapter/index.js +180 -0
  69. package/dist/serial-adapter/index.js.map +1 -0
  70. package/dist/usb-adapter/index.d.ts +20 -0
  71. package/dist/usb-adapter/index.d.ts.map +1 -0
  72. package/dist/usb-adapter/index.js +264 -0
  73. package/dist/usb-adapter/index.js.map +1 -0
  74. package/package.json +42 -15
  75. package/CHANGELOG.md +0 -74
  76. package/docs/COVERAGE_ANALYSIS.md +0 -98
  77. package/docs/DEPENDENCIES_REVIEW.md +0 -127
  78. package/docs/JSDOC_REVIEW.md +0 -122
  79. package/docs/LIBRARY_OVERVIEW.md +0 -383
  80. package/docs/PRE_PUBLISH_CHECKLIST.md +0 -331
  81. package/docs/PUBLIC_API_ANALYSIS.md +0 -223
  82. package/docs/README.md +0 -37
  83. package/docs/SERIALPORT_V13_MIGRATION_COMPLETE.md +0 -127
  84. package/docs/TESTS_IMPLEMENTED.md +0 -129
  85. package/docs/USB_V2_REVIEW.md +0 -148
  86. package/docs/VERIFICATION_RESULTS.md +0 -172
  87. package/docs/VERSIONING.md +0 -102
  88. package/examples/printTest.js +0 -59
  89. package/index.js +0 -7
  90. package/jest.config.js +0 -16
  91. package/src/adapter/index.js +0 -75
  92. package/src/printer/commands.js +0 -199
  93. package/src/printer/image.js +0 -159
  94. package/src/printer/index.js +0 -621
  95. package/src/printer/utils.js +0 -58
  96. package/src/serial-adapter/index.js +0 -198
  97. package/src/usb-adapter/index.js +0 -283
  98. package/tests/README.md +0 -67
  99. package/tests/integration/printer-flow.test.js +0 -128
  100. package/tests/unit/adapters/adapter.test.js +0 -49
  101. package/tests/unit/adapters/serial-adapter.test.js +0 -238
  102. package/tests/unit/adapters/usb-adapter.test.js +0 -319
  103. package/tests/unit/image/image.test.js +0 -157
  104. package/tests/unit/printer/buffer.test.js +0 -60
  105. package/tests/unit/printer/commands.test.js +0 -109
  106. package/tests/unit/printer/printer.test.js +0 -405
  107. package/tests/unit/utils/utils.test.js +0 -96
@@ -1,49 +0,0 @@
1
- 'use strict';
2
-
3
- const Adapter = require('../../../src/adapter');
4
-
5
- describe('Adapter', () => {
6
- let adapter;
7
-
8
- beforeEach(() => {
9
- adapter = new Adapter();
10
- });
11
-
12
- it('should be an instance of EventEmitter', () => {
13
- const EventEmitter = require('events');
14
- expect(adapter).toBeInstanceOf(EventEmitter);
15
- });
16
-
17
- it('should throw NotImplementedException for connect', () => {
18
- expect(() => adapter.connect()).toThrow(Error);
19
- });
20
-
21
- it('should throw NotImplementedException for open', () => {
22
- expect(() => adapter.open()).toThrow(Error);
23
- });
24
-
25
- it('should throw NotImplementedException for write', () => {
26
- expect(() => adapter.write()).toThrow(Error);
27
- });
28
-
29
- it('should throw NotImplementedException for close', () => {
30
- expect(() => adapter.close()).toThrow(Error);
31
- });
32
-
33
- it('should throw NotImplementedException for read', () => {
34
- expect(() => adapter.read()).toThrow(Error);
35
- });
36
-
37
- it('should copy properties from provided adapter', () => {
38
- const mockAdapter = {
39
- connect: jest.fn(),
40
- write: jest.fn(),
41
- customProp: 'test'
42
- };
43
-
44
- const adapter = new Adapter(mockAdapter);
45
- expect(adapter.customProp).toBe('test');
46
- expect(adapter.connect).toBe(mockAdapter.connect);
47
- });
48
- });
49
-
@@ -1,238 +0,0 @@
1
- 'use strict';
2
-
3
- const Serial = require('../../../src/serial-adapter');
4
- const { SerialPort } = require('serialport');
5
-
6
- // Mock serialport (v13 API - uses Promises)
7
- jest.mock('serialport', () => {
8
- const mockPort = {
9
- isOpen: false,
10
- open: jest.fn().mockResolvedValue(undefined),
11
- close: jest.fn().mockResolvedValue(undefined),
12
- write: jest.fn().mockResolvedValue(undefined),
13
- flush: jest.fn().mockResolvedValue(undefined),
14
- drain: jest.fn().mockResolvedValue(undefined),
15
- on: jest.fn(),
16
- removeListener: jest.fn()
17
- };
18
-
19
- // Update isOpen when open/close are called
20
- const originalOpen = mockPort.open;
21
- mockPort.open = jest.fn().mockImplementation(async () => {
22
- mockPort.isOpen = true;
23
- return originalOpen();
24
- });
25
-
26
- const originalClose = mockPort.close;
27
- mockPort.close = jest.fn().mockImplementation(async () => {
28
- mockPort.isOpen = false;
29
- return originalClose();
30
- });
31
-
32
- const SerialPortConstructor = jest.fn().mockImplementation((options) => {
33
- return mockPort;
34
- });
35
-
36
- // Attach list as static method to SerialPort constructor
37
- SerialPortConstructor.list = jest.fn().mockResolvedValue([
38
- { path: '/dev/ttyUSB0' },
39
- { path: '/dev/ttyUSB1' }
40
- ]);
41
-
42
- return {
43
- SerialPort: SerialPortConstructor
44
- };
45
- });
46
-
47
- describe('Serial Adapter', () => {
48
- beforeEach(() => {
49
- jest.clearAllMocks();
50
- });
51
-
52
- describe('listSerial', () => {
53
- it('should list all available serial ports', async () => {
54
- const ports = await Serial.listSerial();
55
- expect(Array.isArray(ports)).toBe(true);
56
- expect(SerialPort.list).toHaveBeenCalled();
57
- });
58
-
59
- it('should return port objects with path property', async () => {
60
- const ports = await Serial.listSerial();
61
- expect(ports.length).toBeGreaterThan(0);
62
- expect(ports[0]).toHaveProperty('path');
63
- });
64
- });
65
-
66
- describe('connect', () => {
67
- it('should connect to serial port', async () => {
68
- const result = await Serial.connect('/dev/ttyUSB0');
69
- expect(result).toBe(true);
70
- expect(SerialPort).toHaveBeenCalled();
71
- });
72
-
73
- it('should verify port exists', async () => {
74
- await Serial.connect('/dev/ttyUSB0');
75
- expect(SerialPort.list).toHaveBeenCalled();
76
- });
77
-
78
- it('should throw error if port does not exist', async () => {
79
- await expect(Serial.connect('/dev/invalid')).rejects.toThrow('The specified port does not exist!');
80
- });
81
-
82
- it('should emit connect event', (done) => {
83
- Serial.once('connect', () => {
84
- done();
85
- });
86
- Serial.connect('/dev/ttyUSB0');
87
- });
88
- });
89
-
90
- describe('open', () => {
91
- beforeEach(async () => {
92
- await Serial.connect('/dev/ttyUSB0');
93
- });
94
-
95
- it('should open port if closed', async () => {
96
- const result = await Serial.open();
97
- expect(result).toBe(true);
98
-
99
- // Verify port.open was called
100
- const mockPort = SerialPort.mock.results[0].value;
101
- expect(mockPort.open).toHaveBeenCalled();
102
- });
103
-
104
- it('should return true if already open', async () => {
105
- // Get the mock port and set it as already open
106
- const mockPort = SerialPort.mock.results[0].value;
107
- const previousCallCount = mockPort.open.mock.calls.length;
108
- mockPort.isOpen = true;
109
-
110
- const result = await Serial.open();
111
- expect(result).toBe(true);
112
-
113
- // Verify port.open was NOT called again (call count should be the same)
114
- // Since isOpen is true, the code should return early without calling open()
115
- expect(mockPort.open.mock.calls.length).toBe(previousCallCount);
116
- });
117
- });
118
-
119
- describe('write', () => {
120
- beforeEach(async () => {
121
- await Serial.connect('/dev/ttyUSB0');
122
- await Serial.open();
123
- });
124
-
125
- it('should write data to port', async () => {
126
- const testData = Buffer.from('test', 'ascii');
127
- const result = await Serial.write(testData);
128
- expect(result).toBe(true);
129
-
130
- // Verify port.write was called with correct data
131
- const mockPort = SerialPort.mock.results[0].value;
132
- expect(mockPort.write).toHaveBeenCalledWith(testData);
133
- });
134
-
135
- it('should drain port after write', async () => {
136
- const testData = Buffer.from('test', 'ascii');
137
- await Serial.write(testData);
138
-
139
- const mockPort = SerialPort.mock.results[0].value;
140
- expect(mockPort.write).toHaveBeenCalled();
141
- expect(mockPort.drain).toHaveBeenCalled();
142
- });
143
- });
144
-
145
- describe('close', () => {
146
- beforeEach(async () => {
147
- await Serial.connect('/dev/ttyUSB0');
148
- await Serial.open();
149
- });
150
-
151
- it('should close port', async () => {
152
- const result = await Serial.close();
153
- expect(result).toBe(true);
154
-
155
- // Verify close sequence was called
156
- const mockPort = SerialPort.mock.results[0].value;
157
- expect(mockPort.flush).toHaveBeenCalled();
158
- expect(mockPort.drain).toHaveBeenCalled();
159
- expect(mockPort.close).toHaveBeenCalled();
160
- });
161
-
162
- it('should flush before closing', async () => {
163
- await Serial.close();
164
-
165
- const mockPort = SerialPort.mock.results[0].value;
166
- expect(mockPort.flush).toHaveBeenCalled();
167
- expect(mockPort.drain).toHaveBeenCalled();
168
- expect(mockPort.close).toHaveBeenCalled();
169
- });
170
-
171
- it('should use default timeout of 50ms', async () => {
172
- await Serial.close();
173
- // Should complete without error
174
- expect(true).toBe(true);
175
- });
176
-
177
- it('should use custom timeout', async () => {
178
- await Serial.close(100);
179
- // Should complete without error
180
- expect(true).toBe(true);
181
- });
182
-
183
- it('should emit close event', async () => {
184
- let eventReceived = false;
185
- const promise = new Promise((resolve) => {
186
- Serial.once('close', () => {
187
- eventReceived = true;
188
- resolve();
189
- });
190
- });
191
-
192
- expect(Serial.listenerCount('close')).toBe(1);
193
-
194
- await Serial.close();
195
-
196
- await Promise.race([
197
- promise,
198
- new Promise((_, reject) => setTimeout(() => reject(new Error('Close event not emitted within timeout')), 1000))
199
- ]);
200
-
201
- expect(eventReceived).toBe(true);
202
- });
203
- });
204
-
205
- describe('disconnect', () => {
206
- beforeEach(async () => {
207
- await Serial.connect('/dev/ttyUSB0');
208
- });
209
-
210
- it('should disconnect (calls close)', async () => {
211
- const result = await Serial.disconnect();
212
- expect(result).toBe(true);
213
- });
214
- });
215
-
216
- describe('read', () => {
217
- beforeEach(async () => {
218
- await Serial.connect('/dev/ttyUSB0');
219
- await Serial.open();
220
- });
221
-
222
- it('should read data from port', async () => {
223
- const mockPort = SerialPort.mock.results[0].value;
224
- const testData = Buffer.from('response', 'ascii');
225
-
226
- // Mock data event
227
- mockPort.on.mockImplementation((event, handler) => {
228
- if (event === 'data') {
229
- setTimeout(() => handler(testData), 10);
230
- }
231
- });
232
-
233
- const data = await Serial.read();
234
- expect(Buffer.isBuffer(data)).toBe(true);
235
- });
236
- });
237
- });
238
-
@@ -1,319 +0,0 @@
1
- 'use strict';
2
-
3
- const USB = require('../../../src/usb-adapter');
4
- const usb = require('usb');
5
-
6
- // Mock usb module (v2 API - uses Promises)
7
- jest.mock('usb', () => {
8
- const createMockDevice = () => {
9
- const mockEndpoint = {
10
- direction: 'out',
11
- transfer: jest.fn().mockResolvedValue(undefined)
12
- };
13
-
14
- const mockInterface = {
15
- isKernelDriverActive: jest.fn().mockReturnValue(false),
16
- claim: jest.fn().mockResolvedValue(undefined),
17
- release: jest.fn().mockResolvedValue(undefined),
18
- detachKernelDriver: jest.fn().mockResolvedValue(undefined),
19
- descriptor: {
20
- bInterfaceClass: 0x07, // PRINTER class
21
- bInterfaceNumber: 0
22
- },
23
- endpoints: [mockEndpoint]
24
- };
25
-
26
- // Link endpoint to interface (v2 API structure)
27
- mockEndpoint.interface = mockInterface;
28
-
29
- return {
30
- open: jest.fn().mockResolvedValue(undefined),
31
- close: jest.fn().mockResolvedValue(undefined),
32
- interfaces: [mockInterface],
33
- configDescriptor: {
34
- interfaces: [
35
- [
36
- {
37
- bInterfaceClass: 0x07 // PRINTER class
38
- }
39
- ]
40
- ]
41
- },
42
- deviceDescriptor: {
43
- iManufacturer: 1,
44
- iProduct: 2
45
- },
46
- getStringDescriptor: jest.fn().mockResolvedValue('Device String')
47
- };
48
- };
49
-
50
- // Create a single shared mock device instance that persists across tests
51
- // This ensures the same device is returned every time, maintaining state
52
- const mockDeviceInstance = createMockDevice();
53
-
54
- return {
55
- getDeviceList: jest.fn().mockReturnValue([mockDeviceInstance]),
56
- findByIds: jest.fn().mockReturnValue(mockDeviceInstance),
57
- on: jest.fn()
58
- };
59
- });
60
-
61
- describe('USB Adapter', () => {
62
- beforeEach(() => {
63
- // Don't clear mocks that break the device structure
64
- // Only clear call history for methods that need it
65
- const mockDevice = usb.findByIds(1046, 20497);
66
- if (mockDevice) {
67
- // Clear call history but preserve mock structure
68
- if (mockDevice.open && typeof mockDevice.open.mockClear === 'function') {
69
- mockDevice.open.mockClear();
70
- }
71
- if (mockDevice.close && typeof mockDevice.close.mockClear === 'function') {
72
- mockDevice.close.mockClear();
73
- }
74
- if (mockDevice.interfaces && mockDevice.interfaces[0]) {
75
- if (mockDevice.interfaces[0].claim && typeof mockDevice.interfaces[0].claim.mockClear === 'function') {
76
- mockDevice.interfaces[0].claim.mockClear();
77
- }
78
- if (mockDevice.interfaces[0].release && typeof mockDevice.interfaces[0].release.mockClear === 'function') {
79
- mockDevice.interfaces[0].release.mockClear();
80
- }
81
- if (mockDevice.interfaces[0].endpoints && mockDevice.interfaces[0].endpoints[0]) {
82
- if (mockDevice.interfaces[0].endpoints[0].transfer && typeof mockDevice.interfaces[0].endpoints[0].transfer.mockClear === 'function') {
83
- mockDevice.interfaces[0].endpoints[0].transfer.mockClear();
84
- }
85
- }
86
- }
87
- }
88
- // Don't clear findByIds mock as it needs to return the device
89
- // usb.findByIds.mockClear(); // Commented out to preserve mock return value
90
- // usb.getDeviceList.mockClear(); // Commented out to preserve mock return value
91
- });
92
-
93
- describe('listUSB', () => {
94
- it('should list USB printer devices', async () => {
95
- const devices = await USB.listUSB();
96
- expect(Array.isArray(devices)).toBe(true);
97
- });
98
-
99
- it('should filter only printer devices', async () => {
100
- const devices = await USB.listUSB();
101
- // Should only return devices with PRINTER interface class
102
- expect(devices.length).toBeGreaterThanOrEqual(0);
103
- });
104
-
105
- it('should get device manufacturer and product strings', async () => {
106
- const devices = await USB.listUSB();
107
- if (devices.length > 0) {
108
- const device = devices[0];
109
- expect(device.manufacturer).toBeDefined();
110
- expect(device.product).toBeDefined();
111
- }
112
- });
113
-
114
- it('should handle devices without descriptors gracefully', async () => {
115
- // Mock a device that fails to get descriptor
116
- const mockDeviceWithoutDescriptor = {
117
- open: jest.fn().mockResolvedValue(undefined),
118
- close: jest.fn().mockResolvedValue(undefined),
119
- getStringDescriptor: jest.fn().mockRejectedValue(new Error('Descriptor error')),
120
- configDescriptor: {
121
- interfaces: [
122
- [
123
- {
124
- bInterfaceClass: 0x07
125
- }
126
- ]
127
- ]
128
- },
129
- deviceDescriptor: {
130
- iManufacturer: 1,
131
- iProduct: 2
132
- }
133
- };
134
-
135
- usb.getDeviceList.mockReturnValueOnce([mockDeviceWithoutDescriptor]);
136
-
137
- const devices = await USB.listUSB();
138
- // Should not include devices that fail to get descriptors
139
- expect(devices.length).toBe(0);
140
- });
141
- });
142
-
143
- describe('connect', () => {
144
- it('should connect to device by VID/PID', async () => {
145
- const result = await USB.connect(1046, 20497);
146
- expect(result).toBe(true);
147
- expect(usb.findByIds).toHaveBeenCalledWith(1046, 20497);
148
- });
149
-
150
- it('should connect to first available device if no VID/PID', async () => {
151
- const result = await USB.connect();
152
- expect(result).toBe(true);
153
- });
154
-
155
- it('should throw error if device not found', async () => {
156
- usb.findByIds.mockReturnValueOnce(null);
157
- usb.getDeviceList.mockReturnValueOnce([]);
158
-
159
- await expect(USB.connect(9999, 9999)).rejects.toThrow('Cannot find printer!');
160
- });
161
-
162
- it('should emit connect event', (done) => {
163
- USB.once('connect', () => {
164
- done();
165
- });
166
- USB.connect(1046, 20497);
167
- });
168
- });
169
-
170
- describe('open', () => {
171
- beforeEach(async () => {
172
- await USB.connect(1046, 20497);
173
- });
174
-
175
- it('should open device connection', async () => {
176
- const result = await USB.open();
177
- expect(result).toBe(true);
178
-
179
- // Verify device.open was called
180
- const mockDevice = usb.findByIds(1046, 20497);
181
- expect(mockDevice.open).toHaveBeenCalled();
182
-
183
- // Verify interface was claimed
184
- if (mockDevice.interfaces && mockDevice.interfaces[0]) {
185
- expect(mockDevice.interfaces[0].claim).toHaveBeenCalled();
186
- }
187
- });
188
-
189
- it('should find output endpoint', async () => {
190
- await USB.open();
191
- // Endpoint should be found (mocked)
192
- expect(USB.write).toBeDefined();
193
-
194
- // Verify endpoint was found
195
- const mockDevice = usb.findByIds(1046, 20497);
196
- if (mockDevice.interfaces && mockDevice.interfaces[0] && mockDevice.interfaces[0].endpoints[0]) {
197
- expect(mockDevice.interfaces[0].endpoints[0].direction).toBe('out');
198
- }
199
- });
200
-
201
- it('should throw error if endpoint not found', async () => {
202
- const mockDevice = usb.findByIds(1046, 20497);
203
- // Save original interfaces to restore later
204
- const originalInterfaces = mockDevice.interfaces;
205
-
206
- const mockInterfaceWithoutEndpoints = {
207
- isKernelDriverActive: jest.fn().mockReturnValue(false),
208
- claim: jest.fn().mockResolvedValue(undefined),
209
- release: jest.fn().mockResolvedValue(undefined),
210
- detachKernelDriver: jest.fn().mockResolvedValue(undefined),
211
- descriptor: {
212
- bInterfaceClass: 0x07,
213
- bInterfaceNumber: 0
214
- },
215
- endpoints: [] // No endpoints
216
- };
217
- mockDevice.interfaces = [mockInterfaceWithoutEndpoints];
218
-
219
- try {
220
- await expect(USB.open()).rejects.toThrow('Can not find endpoint from printer');
221
- } finally {
222
- // Restore original interfaces to prevent affecting other tests
223
- mockDevice.interfaces = originalInterfaces;
224
- }
225
- });
226
- });
227
-
228
- describe('write', () => {
229
- beforeEach(async () => {
230
- await USB.connect(1046, 20497);
231
- await USB.open();
232
- });
233
-
234
- it('should write data to endpoint', async () => {
235
- const testData = Buffer.from('test', 'ascii');
236
- const result = await USB.write(testData);
237
- expect(result).toBe(true);
238
-
239
- // Verify that endpoint.transfer was called with correct data
240
- const mockDevice = usb.findByIds(1046, 20497);
241
- if (mockDevice.interfaces && mockDevice.interfaces[0] && mockDevice.interfaces[0].endpoints[0]) {
242
- expect(mockDevice.interfaces[0].endpoints[0].transfer).toHaveBeenCalledWith(testData);
243
- }
244
- });
245
- });
246
-
247
- describe('close', () => {
248
- beforeEach(async () => {
249
- await USB.connect(1046, 20497);
250
- await USB.open();
251
- });
252
-
253
- it('should close device connection', async () => {
254
- const result = await USB.close();
255
- expect(result).toBe(true);
256
-
257
- // Verify that interface release was called
258
- const mockDevice = usb.findByIds(1046, 20497);
259
- if (mockDevice.interfaces && mockDevice.interfaces[0]) {
260
- expect(mockDevice.interfaces[0].release).toHaveBeenCalled();
261
- }
262
- expect(mockDevice.close).toHaveBeenCalled();
263
- });
264
-
265
- it('should emit close event', async () => {
266
- let eventReceived = false;
267
- const promise = new Promise((resolve) => {
268
- USB.once('close', () => {
269
- eventReceived = true;
270
- resolve();
271
- });
272
- });
273
-
274
- expect(USB.listenerCount('close')).toBe(1);
275
-
276
- await USB.close();
277
-
278
- await Promise.race([
279
- promise,
280
- new Promise((_, reject) => setTimeout(() => reject(new Error('Close event not emitted within timeout')), 1000))
281
- ]);
282
-
283
- expect(eventReceived).toBe(true);
284
- });
285
- });
286
-
287
- describe('disconnect', () => {
288
- beforeEach(async () => {
289
- await USB.connect(1046, 20497);
290
- });
291
-
292
- it('should disconnect device', async () => {
293
- const result = await USB.disconnect();
294
- expect(result).toBe(true);
295
- });
296
-
297
- it('should emit disconnect event', async () => {
298
- let eventReceived = false;
299
- const promise = new Promise((resolve) => {
300
- USB.once('disconnect', () => {
301
- eventReceived = true;
302
- resolve();
303
- });
304
- });
305
-
306
- expect(USB.listenerCount('disconnect')).toBe(1);
307
-
308
- await USB.disconnect();
309
-
310
- await Promise.race([
311
- promise,
312
- new Promise((_, reject) => setTimeout(() => reject(new Error('Disconnect event not emitted within timeout')), 1000))
313
- ]);
314
-
315
- expect(eventReceived).toBe(true);
316
- });
317
- });
318
- });
319
-