@onekeyfe/hd-transport-web-device 1.2.8-alpha.13 → 1.2.8-alpha.130

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.
@@ -196,6 +196,33 @@ describe('ElectronBleTransport protocol detection', () => {
196
196
  });
197
197
  });
198
198
 
199
+ test('passes the advertised color from the native bridge into the descriptor', async () => {
200
+ const nobleBle = createNobleBle();
201
+ nobleBle.enumerate.mockResolvedValueOnce([
202
+ { id: 'colored-pro2-id', name: 'Pro 2 A1B2', bleColorCode: 'B' },
203
+ { id: 'legacy-pro2-id', name: 'Pro 2 C3D4' },
204
+ ] as never);
205
+ const bleTransport = configureTransport(nobleBle);
206
+
207
+ await expect(bleTransport.enumerate()).resolves.toEqual([
208
+ {
209
+ id: 'colored-pro2-id',
210
+ name: 'Pro 2 A1B2',
211
+ path: 'colored-pro2-id',
212
+ debug: false,
213
+ commType: 'electron-ble',
214
+ bleColorCode: 'B',
215
+ },
216
+ {
217
+ id: 'legacy-pro2-id',
218
+ name: 'Pro 2 C3D4',
219
+ path: 'legacy-pro2-id',
220
+ debug: false,
221
+ commType: 'electron-ble',
222
+ },
223
+ ]);
224
+ });
225
+
199
226
  test('does not treat an error envelope from a legacy preload as a successful connect', async () => {
200
227
  const device = { id: 'legacy-error-id', name: 'OneKey Pro 2' };
201
228
  const nobleBle = createNobleBle(device);
@@ -259,6 +286,192 @@ describe('ElectronBleTransport protocol detection', () => {
259
286
  expect(nobleBle.unsubscribe).not.toHaveBeenCalled();
260
287
  });
261
288
 
289
+ test.each([false, true])(
290
+ 'forwards the existing keepSession=%s release intent to native',
291
+ async keepSession => {
292
+ const device = { id: 'release-intent-pro2-id', name: 'OneKey Pro 2' };
293
+ const release = jest.fn().mockResolvedValue(undefined);
294
+ const nobleBle = { ...createNobleBle(device), release };
295
+ echoProtocolV2(nobleBle, device.id);
296
+ const bleTransport = configureTransport(nobleBle);
297
+ await bleTransport.acquire({ uuid: device.id, expectedProtocol: 'V2' });
298
+
299
+ await bleTransport.release(device.id, false, keepSession);
300
+
301
+ expect(release).toHaveBeenCalledWith(device.id, keepSession);
302
+ expect(nobleBle.disconnect).not.toHaveBeenCalled();
303
+ expect(nobleBle.unsubscribe).not.toHaveBeenCalled();
304
+ }
305
+ );
306
+
307
+ test.each(['Pro 2', 'Neo'])(
308
+ 'reuses the connection, subscription and V2 sequence for %s after release',
309
+ async name => {
310
+ const device = { id: 'retained-v2-id', name };
311
+ const release = jest.fn().mockResolvedValue(undefined);
312
+ const nobleBle = { ...createNobleBle(device), release };
313
+ echoProtocolV2(nobleBle, device.id);
314
+ const bleTransport = configureTransport(nobleBle);
315
+ await bleTransport.acquire({ uuid: device.id, expectedProtocol: 'V2' });
316
+ await bleTransport.call(device.id, 'Ping', { message: 'before-release' });
317
+ const notifyCleanup = nobleBle.onNotification.mock.results[0].value;
318
+
319
+ try {
320
+ await bleTransport.release(device.id, false, true);
321
+ expect(bleTransport.getProtocolType(device.id)).toBe('V2');
322
+ expect(notifyCleanup).not.toHaveBeenCalled();
323
+ await expect(
324
+ bleTransport.acquire({ uuid: device.id, expectedProtocol: 'V2' })
325
+ ).resolves.toMatchObject({ uuid: device.id, protocolType: 'V2' });
326
+ await expect(
327
+ bleTransport.call(device.id, 'Ping', { message: 'after-release' })
328
+ ).resolves.toMatchObject({ type: 'Success' });
329
+
330
+ expect(nobleBle.connect).toHaveBeenCalledTimes(1);
331
+ expect(nobleBle.subscribe).toHaveBeenCalledTimes(1);
332
+ expect(nobleBle.onNotification).toHaveBeenCalledTimes(1);
333
+ expect(nobleBle.onMtuChanged).toHaveBeenCalledTimes(1);
334
+ expect(release).toHaveBeenCalledWith(device.id, true);
335
+ expect(
336
+ nobleBle.write.mock.calls.map(([, hex]) => Number.parseInt(hex.slice(12, 14), 16))
337
+ ).toEqual([1, 2, 3]);
338
+ } finally {
339
+ await bleTransport.disconnect(device.id);
340
+ }
341
+ expect(notifyCleanup).toHaveBeenCalledTimes(1);
342
+ expect(nobleBle.disconnect).toHaveBeenCalledWith(device.id);
343
+ }
344
+ );
345
+
346
+ test.each(['ordinary release', 'onclose', 'forced probe'])(
347
+ 'does not retain renderer state for %s',
348
+ async mode => {
349
+ const device = { id: 'release-fallback-id', name: 'Pro 2' };
350
+ const nobleBle = createNobleBle(device);
351
+ echoProtocolV2(nobleBle, device.id);
352
+ const bleTransport = configureTransport(nobleBle);
353
+ await bleTransport.acquire({ uuid: device.id, expectedProtocol: 'V2' });
354
+ const notifyCleanup = nobleBle.onNotification.mock.results[0].value;
355
+ await bleTransport.release(device.id, mode === 'onclose', mode !== 'ordinary release');
356
+
357
+ const input = {
358
+ uuid: device.id,
359
+ expectedProtocol: 'V2' as const,
360
+ forceProtocolDetection: mode === 'forced probe',
361
+ };
362
+ await bleTransport.acquire(input);
363
+
364
+ expect(notifyCleanup).toHaveBeenCalledTimes(1);
365
+ expect(nobleBle.connect).toHaveBeenCalledTimes(2);
366
+ expect(nobleBle.subscribe).toHaveBeenCalledTimes(2);
367
+ await bleTransport.disconnect(device.id);
368
+ }
369
+ );
370
+
371
+ test.each([false, true])(
372
+ 'rebuilds a retained link after a disconnect, including during lookup: %s',
373
+ async duringLookup => {
374
+ const device = { id: 'retained-drop-id', name: 'Pro 2' };
375
+ const nobleBle = createNobleBle(device);
376
+ echoProtocolV2(nobleBle, device.id);
377
+ const bleTransport = configureTransport(nobleBle);
378
+ await bleTransport.acquire({ uuid: device.id, expectedProtocol: 'V2' });
379
+ await bleTransport.release(device.id, false, true);
380
+ const disconnectHandler = nobleBle.onDeviceDisconnected.mock.calls[0][0];
381
+ const notifyCleanup = nobleBle.onNotification.mock.results[0].value;
382
+ const drop = () =>
383
+ disconnectHandler({ ...device, reason: EBleDisconnectReason.DeviceDisconnected });
384
+ if (duringLookup) {
385
+ nobleBle.getDevice.mockImplementationOnce(() => {
386
+ drop();
387
+ return Promise.resolve(device);
388
+ });
389
+ } else {
390
+ drop();
391
+ }
392
+
393
+ await bleTransport.acquire({ uuid: device.id, expectedProtocol: 'V2' });
394
+ await expect(bleTransport.call(device.id, 'Ping', {})).resolves.toMatchObject({
395
+ type: 'Success',
396
+ });
397
+
398
+ expect(notifyCleanup).toHaveBeenCalledTimes(1);
399
+ expect(nobleBle.connect).toHaveBeenCalledTimes(2);
400
+ expect(nobleBle.subscribe).toHaveBeenCalledTimes(2);
401
+ await bleTransport.disconnect(device.id);
402
+ }
403
+ );
404
+
405
+ test('disconnects a reused link on timeout without replaying the call', async () => {
406
+ const device = { id: 'retained-timeout-id', name: 'Pro 2' };
407
+ const nobleBle = createNobleBle(device);
408
+ echoProtocolV2(nobleBle, device.id);
409
+ const bleTransport = configureTransport(nobleBle);
410
+ await bleTransport.acquire({ uuid: device.id, expectedProtocol: 'V2' });
411
+ await bleTransport.release(device.id, false, true);
412
+ await bleTransport.acquire({ uuid: device.id, expectedProtocol: 'V2' });
413
+ nobleBle.write.mockImplementationOnce(() => Promise.resolve());
414
+
415
+ await expect(bleTransport.call(device.id, 'Ping', {}, { timeoutMs: 10 })).rejects.toMatchObject(
416
+ {
417
+ errorCode: HardwareErrorCode.BleTimeoutError,
418
+ }
419
+ );
420
+
421
+ expect(nobleBle.write).toHaveBeenCalledTimes(2);
422
+ expect(nobleBle.unsubscribe).toHaveBeenCalledWith(device.id);
423
+ expect(nobleBle.disconnect).toHaveBeenCalledWith(device.id);
424
+ expect(bleTransport.getProtocolType(device.id)).toBeUndefined();
425
+ await bleTransport.acquire({ uuid: device.id, expectedProtocol: 'V2' });
426
+ expect(nobleBle.subscribe).toHaveBeenCalledTimes(2);
427
+ await bleTransport.disconnect(device.id);
428
+ });
429
+
430
+ test('invalidates a retained link when native release fails', async () => {
431
+ const device = { id: 'retained-release-failure-id', name: 'Pro 2' };
432
+ const release = jest.fn().mockRejectedValueOnce(new Error('IPC release failed'));
433
+ const nobleBle = { ...createNobleBle(device), release };
434
+ echoProtocolV2(nobleBle, device.id);
435
+ const bleTransport = configureTransport(nobleBle);
436
+ await bleTransport.acquire({ uuid: device.id, expectedProtocol: 'V2' });
437
+ const notifyCleanup = nobleBle.onNotification.mock.results[0].value;
438
+
439
+ await bleTransport.release(device.id, false, true);
440
+
441
+ expect(bleTransport.getProtocolType(device.id)).toBeUndefined();
442
+ expect(notifyCleanup).toHaveBeenCalledTimes(1);
443
+ await bleTransport.acquire({ uuid: device.id, expectedProtocol: 'V2' });
444
+ expect(nobleBle.subscribe).toHaveBeenCalledTimes(2);
445
+ await bleTransport.disconnect(device.id);
446
+ });
447
+
448
+ test('still cancels an in-flight V2 write when release requests retention', async () => {
449
+ const device = { id: 'active-release-id', name: 'Pro 2' };
450
+ const nobleBle = createNobleBle(device);
451
+ echoProtocolV2(nobleBle, device.id);
452
+ const bleTransport = configureTransport(nobleBle);
453
+ await bleTransport.acquire({ uuid: device.id, expectedProtocol: 'V2' });
454
+ const started = createDeferred<void>();
455
+ const write = createDeferred<void>();
456
+ nobleBle.write.mockImplementationOnce(() => {
457
+ started.resolve();
458
+ return write.promise;
459
+ });
460
+ const result = bleTransport.call(device.id, 'Ping', {}).catch(error => error);
461
+ await started.promise;
462
+
463
+ try {
464
+ const releasing = bleTransport.release(device.id, false, true);
465
+ write.resolve();
466
+ await releasing;
467
+ await expect(result).resolves.toMatchObject({ message: 'Electron BLE transport released' });
468
+ expect(bleTransport.getProtocolType(device.id)).toBeUndefined();
469
+ } finally {
470
+ write.resolve();
471
+ await bleTransport.disconnect(device.id);
472
+ }
473
+ });
474
+
262
475
  test('forceNative disconnects a device the renderer no longer tracks', async () => {
263
476
  const device = { id: 'presumed-dead-id', name: 'OneKey Pro 2' };
264
477
  const nobleBle = createNobleBle(device);
@@ -461,6 +674,10 @@ describe('ElectronBleTransport protocol detection', () => {
461
674
  })
462
675
  );
463
676
  expect(transport.getProtocolType(device.id)).toBe('V1');
677
+ const notifyCleanup = nobleBle.onNotification.mock.results[0].value;
678
+ await transport.release(device.id, false, true);
679
+ expect(transport.getProtocolType(device.id)).toBeUndefined();
680
+ expect(notifyCleanup).toHaveBeenCalledTimes(1);
464
681
  await expect(transport.acquire({ uuid: device.id, expectedProtocol: 'V1' })).resolves.toEqual(
465
682
  expect.objectContaining({
466
683
  uuid: device.id,
@@ -561,9 +778,9 @@ describe('ElectronBleTransport protocol detection', () => {
561
778
 
562
779
  const transport = configureTransport(nobleBle);
563
780
 
564
- await expect(transport.acquire({ uuid: device.id })).rejects.toThrow(
565
- /Unable to detect BLE protocol/
566
- );
781
+ await expect(transport.acquire({ uuid: device.id })).rejects.toMatchObject({
782
+ errorCode: HardwareErrorCode.TransportProtocolProbeFailed,
783
+ });
567
784
  expect(nobleBle.unsubscribe).toHaveBeenCalledWith(device.id);
568
785
  expect(nobleBle.disconnect).toHaveBeenCalledWith(device.id);
569
786
  expect(transport.getProtocolType(device.id)).toBeUndefined();
@@ -629,7 +846,8 @@ describe('ElectronBleTransport protocol detection', () => {
629
846
  await expect(
630
847
  transport.acquire({ uuid: device.id, expectedProtocol: 'V2' })
631
848
  ).rejects.toMatchObject({
632
- errorCode: HardwareErrorCode.RuntimeError,
849
+ errorCode: HardwareErrorCode.TransportProtocolProbeFailed,
850
+ params: { expectedProtocol: 'V2' },
633
851
  });
634
852
 
635
853
  expect(nobleBle.connect).toHaveBeenCalledTimes(1);
@@ -645,12 +863,14 @@ describe('ElectronBleTransport protocol detection', () => {
645
863
  await expect(
646
864
  transport.acquire({ uuid: device.id, expectedProtocol: 'V2' })
647
865
  ).rejects.toMatchObject({
648
- errorCode: HardwareErrorCode.RuntimeError,
866
+ errorCode: HardwareErrorCode.TransportProtocolProbeFailed,
867
+ params: { expectedProtocol: 'V2' },
649
868
  });
650
869
  await expect(
651
870
  transport.acquire({ uuid: device.id, expectedProtocol: 'V2' })
652
871
  ).rejects.toMatchObject({
653
- errorCode: HardwareErrorCode.RuntimeError,
872
+ errorCode: HardwareErrorCode.TransportProtocolProbeFailed,
873
+ params: { expectedProtocol: 'V2' },
654
874
  });
655
875
 
656
876
  expect(transport.getProtocolType(device.id)).toBeUndefined();
@@ -755,7 +975,8 @@ describe('ElectronBleTransport protocol detection', () => {
755
975
  await expect(
756
976
  transport.acquire({ uuid: device.id, expectedProtocol: 'V2' })
757
977
  ).rejects.toMatchObject({
758
- errorCode: HardwareErrorCode.RuntimeError,
978
+ errorCode: HardwareErrorCode.TransportProtocolProbeFailed,
979
+ params: { expectedProtocol: 'V2' },
759
980
  });
760
981
 
761
982
  expect(nobleBle.unsubscribe).toHaveBeenCalledWith(device.id);