|
|
@ -1,11 +1,13 @@ |
|
|
import { describe, vi, expect, beforeEach, afterEach } from "vitest"; |
|
|
import { describe, expect, vi } from "vitest"; |
|
|
import { runTransportContract } from "../../../tests/utils/transportContract"; |
|
|
import { runTransportContract } from "../../../tests/utils/transportContract"; |
|
|
import { TransportWebBluetooth } from "./transport"; |
|
|
import { TransportWebBluetooth } from "./transport"; |
|
|
|
|
|
|
|
|
class MiniEmitter { |
|
|
class MiniEmitter { |
|
|
private listeners = new Map<string, Set<(e: Event) => void>>(); |
|
|
private listeners = new Map<string, Set<(e: Event) => void>>(); |
|
|
addEventListener(type: string, listener: (e: Event) => void) { |
|
|
addEventListener(type: string, listener: (e: Event) => void) { |
|
|
if (!this.listeners.has(type)) this.listeners.set(type, new Set()); |
|
|
if (!this.listeners.has(type)) { |
|
|
|
|
|
this.listeners.set(type, new Set()); |
|
|
|
|
|
} |
|
|
this.listeners.get(type)!.add(listener); |
|
|
this.listeners.get(type)!.add(listener); |
|
|
} |
|
|
} |
|
|
removeEventListener(type: string, listener: (e: Event) => void) { |
|
|
removeEventListener(type: string, listener: (e: Event) => void) { |
|
|
@ -66,10 +68,16 @@ function stubWebBluetooth() { |
|
|
// Primary service returns our three characteristics by UUID
|
|
|
// Primary service returns our three characteristics by UUID
|
|
|
const primaryService: BluetoothRemoteGATTService = { |
|
|
const primaryService: BluetoothRemoteGATTService = { |
|
|
async getCharacteristic(uuid: string) { |
|
|
async getCharacteristic(uuid: string) { |
|
|
if (uuid === TransportWebBluetooth.ToRadioUuid) return toRadioCharacteristic; |
|
|
if (uuid === TransportWebBluetooth.ToRadioUuid) { |
|
|
if (uuid === TransportWebBluetooth.FromRadioUuid) return fromRadioCharacteristic; |
|
|
return toRadioCharacteristic; |
|
|
if (uuid === TransportWebBluetooth.FromNumUuid) return fromNumCharacteristic; |
|
|
} |
|
|
throw new Error("Unknown characteristic: " + uuid); |
|
|
if (uuid === TransportWebBluetooth.FromRadioUuid) { |
|
|
|
|
|
return fromRadioCharacteristic; |
|
|
|
|
|
} |
|
|
|
|
|
if (uuid === TransportWebBluetooth.FromNumUuid) { |
|
|
|
|
|
return fromNumCharacteristic; |
|
|
|
|
|
} |
|
|
|
|
|
throw new Error(`Unknown characteristic: ${uuid}`); |
|
|
}, |
|
|
}, |
|
|
} as unknown as BluetoothRemoteGATTService; |
|
|
} as unknown as BluetoothRemoteGATTService; |
|
|
|
|
|
|
|
|
@ -94,10 +102,20 @@ function stubWebBluetooth() { |
|
|
return primaryService; |
|
|
return primaryService; |
|
|
}, |
|
|
}, |
|
|
device: { |
|
|
device: { |
|
|
addEventListener: (...args: Parameters<EventTarget["addEventListener"]>) => |
|
|
addEventListener: ( |
|
|
deviceEmitter.addEventListener(args[0] as string, args[1] as (e: Event) => void), |
|
|
...args: Parameters<EventTarget["addEventListener"]> |
|
|
removeEventListener: (...args: Parameters<EventTarget["removeEventListener"]>) => |
|
|
) => |
|
|
deviceEmitter.removeEventListener(args[0] as string, args[1] as (e: Event) => void), |
|
|
deviceEmitter.addEventListener( |
|
|
|
|
|
args[0] as string, |
|
|
|
|
|
args[1] as (e: Event) => void, |
|
|
|
|
|
), |
|
|
|
|
|
removeEventListener: ( |
|
|
|
|
|
...args: Parameters<EventTarget["removeEventListener"]> |
|
|
|
|
|
) => |
|
|
|
|
|
deviceEmitter.removeEventListener( |
|
|
|
|
|
args[0] as string, |
|
|
|
|
|
args[1] as (e: Event) => void, |
|
|
|
|
|
), |
|
|
} as unknown as BluetoothDevice, |
|
|
} as unknown as BluetoothDevice, |
|
|
} as unknown as BluetoothRemoteGATTServer; |
|
|
} as unknown as BluetoothRemoteGATTServer; |
|
|
|
|
|
|
|
|
@ -114,7 +132,10 @@ function stubWebBluetooth() { |
|
|
}, |
|
|
}, |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
vi.stubGlobal("navigator", Object.assign({}, globalThis.navigator, fakeNavigator)); |
|
|
vi.stubGlobal( |
|
|
|
|
|
"navigator", |
|
|
|
|
|
Object.assign({}, globalThis.navigator, fakeNavigator), |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
// helper actions for tests/contract
|
|
|
// helper actions for tests/contract
|
|
|
return { |
|
|
return { |
|
|
@ -142,24 +163,36 @@ describe("TransportWebBluetooth (contract)", () => { |
|
|
name: "TransportWebBluetooth", |
|
|
name: "TransportWebBluetooth", |
|
|
setup: () => {}, |
|
|
setup: () => {}, |
|
|
teardown: () => { |
|
|
teardown: () => { |
|
|
(globalThis as unknown as { __ble?: ReturnType<typeof stubWebBluetooth> }).__ble?.cleanup(); |
|
|
( |
|
|
(globalThis as unknown as { __ble?: ReturnType<typeof stubWebBluetooth> }).__ble = undefined; |
|
|
globalThis as unknown as { __ble?: ReturnType<typeof stubWebBluetooth> } |
|
|
|
|
|
).__ble?.cleanup(); |
|
|
|
|
|
( |
|
|
|
|
|
globalThis as unknown as { __ble?: ReturnType<typeof stubWebBluetooth> } |
|
|
|
|
|
).__ble = undefined; |
|
|
vi.restoreAllMocks(); |
|
|
vi.restoreAllMocks(); |
|
|
vi.unstubAllGlobals(); |
|
|
vi.unstubAllGlobals(); |
|
|
}, |
|
|
}, |
|
|
create: async () => { |
|
|
create: async () => { |
|
|
(globalThis as unknown as { __ble: ReturnType<typeof stubWebBluetooth> }).__ble = stubWebBluetooth(); |
|
|
( |
|
|
|
|
|
globalThis as unknown as { __ble: ReturnType<typeof stubWebBluetooth> } |
|
|
|
|
|
).__ble = stubWebBluetooth(); |
|
|
return await TransportWebBluetooth.create(); |
|
|
return await TransportWebBluetooth.create(); |
|
|
}, |
|
|
}, |
|
|
pushIncoming: async (bytes) => { |
|
|
pushIncoming: async (bytes) => { |
|
|
(globalThis as unknown as { __ble: ReturnType<typeof stubWebBluetooth> }).__ble.pushIncoming(bytes); |
|
|
( |
|
|
|
|
|
globalThis as unknown as { __ble: ReturnType<typeof stubWebBluetooth> } |
|
|
|
|
|
).__ble.pushIncoming(bytes); |
|
|
await Promise.resolve(); |
|
|
await Promise.resolve(); |
|
|
}, |
|
|
}, |
|
|
assertLastWritten: (bytes) => { |
|
|
assertLastWritten: (bytes) => { |
|
|
(globalThis as unknown as { __ble: ReturnType<typeof stubWebBluetooth> }).__ble.assertLastWritten(bytes); |
|
|
( |
|
|
|
|
|
globalThis as unknown as { __ble: ReturnType<typeof stubWebBluetooth> } |
|
|
|
|
|
).__ble.assertLastWritten(bytes); |
|
|
}, |
|
|
}, |
|
|
triggerDisconnect: async () => { |
|
|
triggerDisconnect: async () => { |
|
|
(globalThis as unknown as { __ble: ReturnType<typeof stubWebBluetooth> }).__ble.triggerGattDisconnect(); |
|
|
( |
|
|
|
|
|
globalThis as unknown as { __ble: ReturnType<typeof stubWebBluetooth> } |
|
|
|
|
|
).__ble.triggerGattDisconnect(); |
|
|
await Promise.resolve(); |
|
|
await Promise.resolve(); |
|
|
}, |
|
|
}, |
|
|
}); |
|
|
}); |
|
|
|