softphone-vendor-headsets 2.5.6-develop.3 → 2.5.6-develop.5
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.
- package/README.md +382 -10
- package/dist/deploy-info.json +2 -2
- package/dist/manifest.json +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,17 +1,389 @@
|
|
|
1
|
-
# Softphone Vendor Headsets
|
|
1
|
+
# Softphone Vendor Headsets
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Overview
|
|
4
|
+
This library's goal is to abstract all the different headset implementations behind a single interface.
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
This project has a [React](https://github.com/facebook/react/) test app bootstrapped with [create-react-app](https://reactjs.org/docs/create-a-new-react-app.html).
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
At this moment (12/10/2021) there are three supported vendors already handled with this library:
|
|
9
|
+
- Plantronics/Poly
|
|
10
|
+
- Sennheiser/EPOS
|
|
11
|
+
- Jabra
|
|
8
12
|
|
|
9
|
-
|
|
13
|
+
As of 11/3/2022 we now support:
|
|
14
|
+
- Yealink
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
|
|
16
|
+
As of 2/12/24 we now support:
|
|
17
|
+
- VBeT
|
|
18
|
+
- CyberAcoustics
|
|
13
19
|
|
|
14
|
-
|
|
20
|
+
## Installation
|
|
15
21
|
|
|
16
|
-
|
|
17
|
-
|
|
22
|
+
``` sh
|
|
23
|
+
# npm
|
|
24
|
+
npm install --save softphone-vendor-headsets
|
|
25
|
+
# yarn
|
|
26
|
+
yarn add softphone-vendor-headsets
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Documentation
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
### Headset Service API
|
|
33
|
+
<br/><br/>
|
|
34
|
+
#### `getInstance`
|
|
35
|
+
This will create a new instance of the headset service if one doesn't already exist. It's important to note the original instance will *always* be returned, even if you pass in different config options
|
|
36
|
+
so make sure you get it right the first time. There's only one relevant option for the headset config, see below.
|
|
37
|
+
``` ts
|
|
38
|
+
static getInstance(config: ImplementationConfig);
|
|
39
|
+
|
|
40
|
+
interface ImplementationConfig {
|
|
41
|
+
logger: any;
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
<br/><br/><br/>
|
|
45
|
+
|
|
46
|
+
#### `implementations`
|
|
47
|
+
This is a computed value that returns a list of selectable headset vendors based on browser/environment compatibility. It does not ensure the required 3rd party software is installed. That gets checked when a vendor is selected or changed.
|
|
48
|
+
<br/><br/><br/>
|
|
49
|
+
#### `activeMicChange`
|
|
50
|
+
The selected headset vendor is determined by the active mic. This method notifies headset service the active mic has changed and it should determine if the "new" mic has an associated vendor implementation.
|
|
51
|
+
``` ts
|
|
52
|
+
activeMicChange (newMicLabel: string): void;
|
|
53
|
+
```
|
|
54
|
+
Params:
|
|
55
|
+
* `newMicLabel: string` Required: This label should match the device label returned from navigator.getUserMedia()
|
|
56
|
+
<br/><br/><br/>
|
|
57
|
+
|
|
58
|
+
#### `changeImplementation`
|
|
59
|
+
Allows you to manually change the selected headset. This is an alternative to `activeMicChange(...)`.
|
|
60
|
+
``` ts
|
|
61
|
+
changeImplementation (implementation: VendorImplementation | null, deviceLabel: string): Promise<void>
|
|
62
|
+
```
|
|
63
|
+
params:
|
|
64
|
+
* `implementation: VendorImplementation | null` Required: The desired vendor implementation
|
|
65
|
+
* `deviceLabel: string` Required: This can be null if the `implementation` is null, otherwise this will be the device associated with the vendor implementation to which you'd like to connect.
|
|
66
|
+
<br/><br/><br/>
|
|
67
|
+
|
|
68
|
+
#### `incomingCall`
|
|
69
|
+
Notifies the headset you have an incoming call. In most cases this will result in the headset ringing.
|
|
70
|
+
``` ts
|
|
71
|
+
incomingCall (callInfo: CallInfo, hasOtherActiveCalls?: boolean): Promise<any>
|
|
72
|
+
```
|
|
73
|
+
params:
|
|
74
|
+
* `callInfo: CallInfo` Required: The desired vendor implementation
|
|
75
|
+
* Basic interface
|
|
76
|
+
``` ts
|
|
77
|
+
interface CallInfo {
|
|
78
|
+
conversationId: string,
|
|
79
|
+
contactName?: string
|
|
80
|
+
}
|
|
81
|
+
* `conversationId: string`: Required: Most of the vendors use conversation or call ids in order to help maintain proper state of the headset. This is the conversationId associated with the incoming call.
|
|
82
|
+
* `contactName: string`: Optional: Some vendors will announce the caller through the headset if the `contactName` is provided.
|
|
83
|
+
* `hasOtherActiveCalls?: boolean` Required: This can be null if the `implementation` is null, otherwise this will be the device associated with the vendor implementation to which you'd like to connect.
|
|
84
|
+
<br/><br/><br/>
|
|
85
|
+
|
|
86
|
+
#### `outgoingCall`
|
|
87
|
+
Notifies the headset you are placing an outgoing call.
|
|
88
|
+
``` ts
|
|
89
|
+
outgoingCall (callInfo: CallInfo): Promise<any>
|
|
90
|
+
```
|
|
91
|
+
params:
|
|
92
|
+
* `callInfo: CallInfo` Required: The desired vendor implementation
|
|
93
|
+
* Basic interface
|
|
94
|
+
``` ts
|
|
95
|
+
interface CallInfo {
|
|
96
|
+
conversationId: string,
|
|
97
|
+
contactName?: string
|
|
98
|
+
}
|
|
99
|
+
* `conversationId: string`: Required: Most of the vendors use conversation or call ids in order to help maintain proper state of the headset. This is the conversationId associated with the incoming call.
|
|
100
|
+
* `contactName: string`: Optional: Some vendors will announce the caller through the headset if the `contactName` is provided.
|
|
101
|
+
<br/><br/><br/>
|
|
102
|
+
|
|
103
|
+
#### `answerCall`
|
|
104
|
+
Notifies the headset you are answering an incoming call. This will end the ringing and enable headset controls.
|
|
105
|
+
``` ts
|
|
106
|
+
answerCall (conversationId: string): Promise<any>
|
|
107
|
+
```
|
|
108
|
+
params:
|
|
109
|
+
* `conversationId: string`: Required: Most of the vendors use conversation or call ids in order to help maintain proper state of the headset. This is the conversationId associated with the incoming call.
|
|
110
|
+
<br/><br/><br/>
|
|
111
|
+
|
|
112
|
+
#### `rejectCall`
|
|
113
|
+
Notifies the headset you are rejecting an incoming call. This will end the ringing.
|
|
114
|
+
``` ts
|
|
115
|
+
rejectCall (conversationId: string): Promise<any>
|
|
116
|
+
```
|
|
117
|
+
params:
|
|
118
|
+
* `conversationId: string`: Required: Most of the vendors use conversation or call ids in order to help maintain proper state of the headset. This is the conversationId associated with the incoming call.
|
|
119
|
+
<br/><br/>
|
|
120
|
+
|
|
121
|
+
#### `setMute`
|
|
122
|
+
Tells the headset to mute or unmute.
|
|
123
|
+
``` ts
|
|
124
|
+
setMute (value: boolean): Promise<any>
|
|
125
|
+
```
|
|
126
|
+
params:
|
|
127
|
+
* `value: boolean`: Required: If `true`, the headset will be muted. If `false`, the headset will be unmuted.
|
|
128
|
+
<br/><br/><br/>
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
#### `setHold`
|
|
132
|
+
Tells the headset you are holding or resuming a call.
|
|
133
|
+
``` ts
|
|
134
|
+
setHold (conversationId: string, value: boolean): Promise<any>
|
|
135
|
+
```
|
|
136
|
+
params:
|
|
137
|
+
* `conversationId: string`: Required: The id associated with the conversation you'd are holding or resuming.
|
|
138
|
+
* `value: boolean`: Required: If `true`, the headset will be held. If `false`, the headset will be resumed.
|
|
139
|
+
<br/><br/><br/>
|
|
140
|
+
#### `endCall`
|
|
141
|
+
Tells the headset a call is ending.
|
|
142
|
+
``` ts
|
|
143
|
+
endCall (conversationId: string, hasOtherActiveCalls?: boolean): Promise<any>
|
|
144
|
+
```
|
|
145
|
+
params:
|
|
146
|
+
* `conversationId: string`: Required: The id associated with the conversation you'd are holding or resuming.
|
|
147
|
+
* `hasOtherActiveCalls?: boolean`: Optional: Some vendors differ in how much state they manage across multiple calls and it has to be shimmed. This allows us to make better decisions in those cases.
|
|
148
|
+
<br/><br/><br/>
|
|
149
|
+
#### `endAllCalls`
|
|
150
|
+
Ends all calls and returns the headset to a vanilla state.
|
|
151
|
+
``` ts
|
|
152
|
+
endAllCalls (): Promise<void>
|
|
153
|
+
```
|
|
154
|
+
<br/><br/><br/>
|
|
155
|
+
#### `retryConnection`
|
|
156
|
+
There are cases where 3rd party software needs to be started in order for the headset to connect. The method allows you to retry the connection after spinning up 3rd party software.
|
|
157
|
+
``` ts
|
|
158
|
+
retryConnection (micLabel: string): Promise<void>
|
|
159
|
+
```
|
|
160
|
+
Params:
|
|
161
|
+
* `micLabel: string` Required: This label should match the device label returned from navigator.getUserMedia()
|
|
162
|
+
<br/><br/><br/>
|
|
163
|
+
|
|
164
|
+
#### `connectionStatus`
|
|
165
|
+
Returns the current connection state of the headset.
|
|
166
|
+
``` ts
|
|
167
|
+
connectionStatus (): DeviceConnectionStatus
|
|
168
|
+
```
|
|
169
|
+
Returns:
|
|
170
|
+
``` ts
|
|
171
|
+
type DeviceConnectionStatus = 'checking' | 'running' | 'notRunning' | 'noVendor';
|
|
172
|
+
```
|
|
173
|
+
<br/><br/><br/>
|
|
174
|
+
|
|
175
|
+
### Headset Events
|
|
176
|
+
The Headset service does not explicitly emit events itself. It uses [RxJS observables](https://rxjs.dev/guide/observable) to emit the events which are then subscribed to within the consuming app.
|
|
177
|
+
|
|
178
|
+
#### `deviceAnsweredCall`
|
|
179
|
+
Event emitted when a user presses the answer call button during an incoming call on their selected device. The event includes the event `name` as it is interpretted by the headset and a collection of items that may help with logging (`event`). It can also potentially have a `code` that corresponds to the event.
|
|
180
|
+
|
|
181
|
+
Declaration:
|
|
182
|
+
``` ts
|
|
183
|
+
headset.headsetEvents.subscribe(event: {
|
|
184
|
+
event: 'deviceAnsweredCall',
|
|
185
|
+
payload: {
|
|
186
|
+
name: string,
|
|
187
|
+
code?: string,
|
|
188
|
+
event: { `containing various items mostly for logging purposes` }
|
|
189
|
+
}
|
|
190
|
+
} => {
|
|
191
|
+
if (event.event === 'deviceAnsweredCall') {
|
|
192
|
+
sdk.acceptPendingSession();
|
|
193
|
+
}
|
|
194
|
+
})
|
|
195
|
+
```
|
|
196
|
+
Value of event:
|
|
197
|
+
* `event: HeadsetEvents` - string value emitted by the headset library to determine what event had just occurred
|
|
198
|
+
* `payload:` - object containing
|
|
199
|
+
* `name: string` - Name of the recent event as interpretted by the headset device
|
|
200
|
+
* `event`: { containing various items mostly for logging purposes}
|
|
201
|
+
* `code?: string` - Optional: A string value of a number that represents the action that was just taken. Not all vendors supply a code which is why it is only optional
|
|
202
|
+
|
|
203
|
+
<br/><br/>
|
|
204
|
+
|
|
205
|
+
#### `deviceEndedCall`
|
|
206
|
+
Event emitted when a user presses the answer call button while in an active call on their selected device. The event includes the event `name` as it is interpretted by the headset and a collection of items that may help with logging (`event`). It can also potentially have a `code` that corresponds to the event.
|
|
207
|
+
|
|
208
|
+
Declaration:
|
|
209
|
+
``` ts
|
|
210
|
+
headset.headsetEvents.subscribe(event: {
|
|
211
|
+
event: 'deviceEndedCall',
|
|
212
|
+
payload: {
|
|
213
|
+
name: string,
|
|
214
|
+
event: { `containing various items mostly for logging purposes` },
|
|
215
|
+
code?: string
|
|
216
|
+
} => {
|
|
217
|
+
if (event.event === 'deviceEndedCall') {
|
|
218
|
+
sdk.endSession({ conversationId });
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
})
|
|
222
|
+
```
|
|
223
|
+
Value of event:
|
|
224
|
+
* `event: HeadsetEvents` - string value emitted by the headset library to determine what event had just occurred
|
|
225
|
+
* `payload:` - object containing
|
|
226
|
+
* `name: string` - Name of the recent event as interpretted by the headset device
|
|
227
|
+
* `event`: { containing various items mostly for logging purposes}
|
|
228
|
+
* `code?: string` - Optional: A string value of a number that represents the action that was just taken. Not all vendors supply a code which is why it is only optional
|
|
229
|
+
<br/><br/>
|
|
230
|
+
|
|
231
|
+
#### `deviceMuteStatusChanged`
|
|
232
|
+
Event emitted when a user presses the mute call button on their selected device. It doesn't matter if the device state is currently muted or unmuted,
|
|
233
|
+
this event will be emitted with the _OPPOSITE_ value. For example, if the headset is currently muted, it will emit the event with the corresponding
|
|
234
|
+
value to unmute the device. The event includes the event `name` as it is interpretted by the headset and a collection of items that may help with
|
|
235
|
+
logging (`event`). It also comes with a value known as `isMuted` which determines the event is trying to mute or unmute the call. It can also
|
|
236
|
+
potentially have a `code` that corresponds to the event.
|
|
237
|
+
|
|
238
|
+
Declaration:
|
|
239
|
+
``` ts
|
|
240
|
+
headset.headsetEvents.subscribe(event: {
|
|
241
|
+
event: 'deviceMuteStatusChanged',
|
|
242
|
+
payload: {
|
|
243
|
+
name: string,
|
|
244
|
+
event: { `containing various items mostly for logging purposes` },
|
|
245
|
+
isMuted: boolean,
|
|
246
|
+
code?: string
|
|
247
|
+
} => {
|
|
248
|
+
if (event.event === 'deviceMuteStatusChanged') {
|
|
249
|
+
sdk.setAudioMute(event.payload.isMuted);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
})
|
|
253
|
+
```
|
|
254
|
+
Value of event:
|
|
255
|
+
* `event: HeadsetEvents` - string value emitted by the headset library to determine what event had just occurred
|
|
256
|
+
* `payload:` - object containing
|
|
257
|
+
* `name: string` - Name of the recent event as interpretted by the headset device
|
|
258
|
+
* `event`: { containing various items mostly for logging purposes}
|
|
259
|
+
* `isMuted: boolean` - the value determining if the event is to mute (`true`) or unmute (`false`) the device
|
|
260
|
+
* `code?: string` - Optional: A string value of a number that represents the action that was just taken. Not all vendors supply a code which is why it is only optional
|
|
261
|
+
<br/><br/>
|
|
262
|
+
|
|
263
|
+
#### `deviceHoldStatusChanged`
|
|
264
|
+
Event emitted when a user presses the hold call button on their selected device. It doesn't matter if the device state is currently on hold or not,
|
|
265
|
+
this event will be emitted with the _OPPOSITE_ value. For example, if the headset is currently on hold, it will emit the event with the corresponding value to
|
|
266
|
+
resume the call. The event includes the event `name` as it is interpretted by the headset and a collection of items that may help with logging (`event`).
|
|
267
|
+
It also comes with a value known as `holdRequested` which determines the event is trying to hold or resume the call. It will also have an optional value for `toggle`.
|
|
268
|
+
It can also potentially have a `code` that corresponds to the event.
|
|
269
|
+
|
|
270
|
+
Declaration:
|
|
271
|
+
``` ts
|
|
272
|
+
headset.headsetEvents.subscribe(event: {
|
|
273
|
+
event: 'deviceHoldStatusChanged',
|
|
274
|
+
payload: {
|
|
275
|
+
name: string,
|
|
276
|
+
event: { `containing various items mostly for logging purposes` },
|
|
277
|
+
holdRequested: boolean,
|
|
278
|
+
code?: string
|
|
279
|
+
} => {
|
|
280
|
+
if (event.event === 'deviceHoldStatusChanged') {
|
|
281
|
+
sdk.setConversationHold(event.payload.holdRequested, event.payload.toggle);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
})
|
|
285
|
+
```
|
|
286
|
+
Value of event:
|
|
287
|
+
* `event: HeadsetEvents` - string value emitted by the headset library to determine what event had just occurred
|
|
288
|
+
* `payload:` - object containing
|
|
289
|
+
* `name: string` - Name of the recent event as interpretted by the headset device
|
|
290
|
+
* `event`: { containing various items mostly for logging purposes}
|
|
291
|
+
* `holdRequested: boolean` - the value determining if the event is to hold (`true`) or resume (`false`) the call
|
|
292
|
+
* `code?: string` - Optional: A string value of a number that represents the action that was just taken. Not all vendors supply a code which is why it is only optional
|
|
293
|
+
<br/><br/>
|
|
294
|
+
|
|
295
|
+
#### `webHidPermissionRequested`
|
|
296
|
+
This is a special event that is only necessary for specific devices. Certain devices (such as Jabra) support a technology known as
|
|
297
|
+
[WebHID](https://developer.mozilla.org/en-US/docs/Web/API/WebHID_API) that requires additional permissions in order to use the call controls.
|
|
298
|
+
This event is emitted when a WebHID enabled device is selected. The event includes a `callback` function that is required in order to
|
|
299
|
+
achieve additional permissions for WebHID
|
|
300
|
+
|
|
301
|
+
Declaration:
|
|
302
|
+
``` ts
|
|
303
|
+
headset.headsetEvents.subscribe(event: {
|
|
304
|
+
event: 'webHidPermissionRequested',
|
|
305
|
+
payload: {
|
|
306
|
+
callback: Function
|
|
307
|
+
} => {
|
|
308
|
+
if (event.event === 'webHidPermissionRequested') {
|
|
309
|
+
event.payload.body.callback();
|
|
310
|
+
/* Please note: The above example will not work as is. You can't trigger the WebHID callback by simply calling, it must be triggered through user interaction such as clicking a button */
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
})
|
|
314
|
+
```
|
|
315
|
+
Value of event:
|
|
316
|
+
* `event: HeadsetEvents` - string value emitted by the headset library to determine what event had just occurred
|
|
317
|
+
* `payload:` - object containing
|
|
318
|
+
* `callback: Function` - the passed in function that will help achieve additional permissions for WebHID devices
|
|
319
|
+
<br/><br/>
|
|
320
|
+
#### `deviceConnectionStatusChanged`
|
|
321
|
+
Event emitted when a device implementation's connection status changes in some way. This can be the flags of `isConnected` or `isConnecting` changing in any way.
|
|
322
|
+
These flags are also included with the events payload.
|
|
323
|
+
|
|
324
|
+
Declaration:
|
|
325
|
+
``` ts
|
|
326
|
+
headset.headsetEvents.subscribe(event: {
|
|
327
|
+
event: 'deviceConnectionStatusChanged',
|
|
328
|
+
payload: {
|
|
329
|
+
isConnected: boolean,
|
|
330
|
+
isConnecting: boolean
|
|
331
|
+
} => {
|
|
332
|
+
if (event.event === 'deviceConnectionStatusChanged') {
|
|
333
|
+
correspondingFunctionToHandleConnectionChange({event.payload.isConnected, event.payload.isConnecting});
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
})
|
|
337
|
+
```
|
|
338
|
+
Value of event:
|
|
339
|
+
* `event: HeadsetEvents` - string value emitted by the headset library to determine what event had just occurred
|
|
340
|
+
* `payload:` - object containing
|
|
341
|
+
* `isConnected: boolean` - if the vendor implementation is fully connected
|
|
342
|
+
* `isConnecting: boolean` - if the vendor implementation is in the process of connecting
|
|
343
|
+
<br/><br/><br/>
|
|
344
|
+
|
|
345
|
+
#### Structure and flow
|
|
346
|
+
- The consuming app will first above anything else hit the HeadsetService (`headsets.ts`).
|
|
347
|
+
- From there, the service will determine what vendor is currently selected out of the supported vendors above. This will also be a hub to call the proper functions that correspond with app to headset events (More on that later)
|
|
348
|
+
- Once the desired vendor has been determined, an instance of that vendor's adapter/service will be created. This adapter will interact with the service or sdk the vendor requires to communicate information to and from the headset.
|
|
349
|
+
- If an event is received from the headset itself, the vendor adapters will emit an event that `headset.ts` is listening for. This event will then be passed to the consuming app to properly reflect the state on screen to match that of the headset
|
|
350
|
+
|
|
351
|
+
**Example 1 - User clicks mute in the consuming app**:
|
|
352
|
+
- From the consuming app, the user clicks on an on-screen mute button
|
|
353
|
+
- The consuming app calls headsetService.mute(...)
|
|
354
|
+
- Which is passed to the corresponding function of the vendor adapter that aligns with the selected device (for example, plantronics.ts -> setMute(true))
|
|
355
|
+
- This function will then send a message to the headset itself
|
|
356
|
+
- The user will then see the light on their device that represents the "muted" state light up.
|
|
357
|
+
|
|
358
|
+
**Example 2 - User presses the mute button from the headset**:
|
|
359
|
+
- From the headset, the user presses the button which corresponds to mute
|
|
360
|
+
- This is then received by the vendor instance (for example sennheiser.ts)
|
|
361
|
+
- This event is then sent to `headset.ts` which in turn lets the consuming app know so that the screen can properly reflect the state of the headset
|
|
362
|
+
|
|
363
|
+
#### WebHID
|
|
364
|
+
One of our supported vendors has began working with a technology known as [WebHID][1]. This is a relatively newer technology with a lot of promise but with its own caveats as well - https://wicg.github.io/webhid/
|
|
365
|
+
- At this moment, WebHID only works with Chromium browsers (Google Chrome/Microsoft Edge). Keep this in mind when developing and using the vendors we currently support
|
|
366
|
+
- In order to use WebHID, you must grant permissions for the site you are currently on. There is a function that must be called that causes a popup to show on screen where the user is then required to select their device and approve its use for WebHID purposes. This function MUST be called with user action (i.e. clicking a button). The solution we currently have in place is after the user changes and selects a new microphone, we check if it is the specific vendor that supports WebHID, then we emit an event that a consuming app should listen for. Once the consuming app receives that event, we will render an initial popup informing the user that additional permissions are required and prompting them to click either "Yes" or "No". Clicking "Yes" acts as the necessary `user action` and we render the necessary WebHID permission popup with the help of the passed in function.
|
|
367
|
+
### Contributing
|
|
368
|
+
This repo uses [Jest][3] for tests and code coverage
|
|
369
|
+
|
|
370
|
+
To get started in development:
|
|
371
|
+
```sh
|
|
372
|
+
npm install
|
|
373
|
+
cd react-app
|
|
374
|
+
yarn start
|
|
375
|
+
```
|
|
376
|
+
Then navigate to https://localhost:8443 to see the test app. This way you can see the effects of the events from the headset on the app and vice versa.
|
|
377
|
+
|
|
378
|
+
### Testing
|
|
379
|
+
Run the tests using `npm run test:watch` or `npm run test:coverage`. Both commands should be run in the folder.
|
|
380
|
+
- `test:watch` will rerun the tests after changes to the code or the test itself
|
|
381
|
+
- `test:coverage` will run the test suites and produce a report on coverage of the code
|
|
382
|
+
|
|
383
|
+
All linting and tests must pass 100% and coverage should remain at 100%
|
|
384
|
+
|
|
385
|
+
**Important Note**: Out of the box, the test scripts will not work on Windows machines. A developer will more than likely need to make modifications to the scripts in the package.json as well as the shell scripts found in the `scripts` folder. If you do not want to modify the scripts out of the box, using a Linux instance seemed to help. The author of the library used an Ubuntu instance
|
|
386
|
+
|
|
387
|
+
[1]: https://developer.mozilla.org/en-US/docs/Web/API/WebHID_API
|
|
388
|
+
[2]: https://wicg.github.io/webhid/
|
|
389
|
+
[3]: https://jestjs.io/en/
|
package/dist/deploy-info.json
CHANGED
package/dist/manifest.json
CHANGED