UNPKG

@huddly/device-api-usb

Version:

Huddly SDK device api which uses node-usb wrapper responsible for handling the transport layer of the communication and discovering the physical device/camera

256 lines 11.8 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const chai_1 = __importDefault(require("chai")); const sinon_chai_1 = __importDefault(require("sinon-chai")); const sinon_1 = __importDefault(require("sinon")); const mocha_param_1 = __importDefault(require("mocha-param")); const transport_1 = __importDefault(require("./../src/transport")); const index_1 = __importDefault(require("./../src/index")); const events_1 = require("events"); const HuddlyHex_1 = __importDefault(require("@huddly/sdk-interfaces/lib/enums/HuddlyHex")); const expect = chai_1.default.expect; chai_1.default.should(); chai_1.default.use(sinon_chai_1.default); const unsupportedMockedDevices = { go: { serialNumber: '123456', productId: HuddlyHex_1.default.GO_PID }, ace: { serialNumber: 'L123456789', productId: HuddlyHex_1.default.L1_PID }, see: { serialNumber: 'S123456789', productId: HuddlyHex_1.default.S1_PID }, base: { serialNumber: '1111111', productId: HuddlyHex_1.default.BASE_PID } }; const supportedMockedDevices = { boxfish: { serialNumber: 'B123456789', productId: HuddlyHex_1.default.BOXFISH_PID }, clownfish: { serialNumber: 'C123456789', productId: HuddlyHex_1.default.CLOWNFISH_PID }, dartfish: { serialNumber: 'D123456789', productId: HuddlyHex_1.default.DARTFISH_PID }, dwarfish: { serialNumber: 'BW123456789', productId: HuddlyHex_1.default.DWARFFISH_PID } }; const dummyDeviceDiscoveryManager = { registerForHotplugEvents: () => { }, deviceList: () => { return supportedMockedDevices; }, getDevice: () => { } }; describe('HuddlyDeviceApiUSB', () => { let deviceApi; beforeEach(() => { deviceApi = new index_1.default({ manager: dummyDeviceDiscoveryManager }); }); describe('initialize', () => { it('shoud call device list to instantiate discovery and emit the first attach events', () => { const spy = sinon_1.default.spy(deviceApi.deviceDiscoveryManager, 'deviceList'); deviceApi.initialize(); expect(spy.callCount).to.equal(1); expect(spy.getCall(0).args[0]).to.be.true; }); }); describe('#registerForHotplugEvents', () => { it('should initialize event emitter and register hotplug events on device manager', () => __awaiter(void 0, void 0, void 0, function* () { const emitter = new events_1.EventEmitter(); const spy = sinon_1.default.spy(deviceApi.deviceDiscoveryManager, 'registerForHotplugEvents'); expect(deviceApi.eventEmitter).to.be.undefined; deviceApi.registerForHotplugEvents(emitter); expect(deviceApi.eventEmitter).to.be.instanceof(events_1.EventEmitter); expect(spy.callCount).to.equal(1); })); }); describe('#getDeviceDiscoveryApi', () => { it('should return the device discovery manager instance', () => __awaiter(void 0, void 0, void 0, function* () { const deviceDiscoveryApi = yield deviceApi.getDeviceDiscoveryAPI(); expect(deviceDiscoveryApi).to.equal(dummyDeviceDiscoveryManager); })); }); describe('#getValidatedTransport', () => { describe('for Huddly GO', () => { it('should not support Huddly GO', () => __awaiter(void 0, void 0, void 0, function* () { const transport = yield deviceApi.getValidatedTransport(unsupportedMockedDevices.go); expect(transport).to.be.undefined; })); }); describe('for Huddly L1', () => { it('should not support Huddly L1', () => __awaiter(void 0, void 0, void 0, function* () { const transport = yield deviceApi.getValidatedTransport(unsupportedMockedDevices.base); expect(transport).to.be.undefined; })); }); describe('for Huddly S1', () => { it('should not support Huddly L1', () => __awaiter(void 0, void 0, void 0, function* () { const transport = yield deviceApi.getValidatedTransport(unsupportedMockedDevices.see); expect(transport).to.be.undefined; })); }); describe('for Huddly Base', () => { it('should not support Huddly BASE', () => __awaiter(void 0, void 0, void 0, function* () { const transport = yield deviceApi.getValidatedTransport(unsupportedMockedDevices.base); expect(transport).to.be.undefined; })); }); describe('boxfish variants', () => { let transportstub; let getTransportStub; beforeEach(() => { transportstub = sinon_1.default.createStubInstance(transport_1.default); }); afterEach(() => { getTransportStub.restore(); }); (0, mocha_param_1.default)('should support ${value} when hlink handshake succeeds', Object.keys(supportedMockedDevices), (value) => __awaiter(void 0, void 0, void 0, function* () { transportstub.performHlinkHandshake.returns(Promise.resolve()); getTransportStub = sinon_1.default.stub(deviceApi, 'getTransport').returns(transportstub); const supported = yield deviceApi.getValidatedTransport(supportedMockedDevices[value]); expect(supported).to.be.instanceof(transport_1.default); })); (0, mocha_param_1.default)('should not support ${value} when hlink handshake fails', Object.keys(supportedMockedDevices), (value) => __awaiter(void 0, void 0, void 0, function* () { transportstub.performHlinkHandshake.returns(Promise.reject()); getTransportStub = sinon_1.default.stub(deviceApi, 'getTransport').returns(transportstub); const supported = yield deviceApi.getValidatedTransport(supportedMockedDevices[value]); expect(supported).to.equal(undefined); })); }); }); describe('#getTransport', () => { let getDeviceStub; const usbDevice = { serialNumber: 'B12344678', open: () => { }, interfaces: { find: () => { return { claim: () => { }, endpoints: { find: () => { } } }; } } }; beforeEach(() => { getDeviceStub = sinon_1.default.stub(dummyDeviceDiscoveryManager, 'getDevice').resolves(usbDevice); }); afterEach(() => { getDeviceStub.restore(); }); it('should fail when the usb device is lacking serial number', () => __awaiter(void 0, void 0, void 0, function* () { try { yield deviceApi.getTransport({}); expect(false).to.be.true; // It should not reach this point } catch (e) { expect(e).to.equal('Transport cannot be initialized since the provided usb device instance is lacking serial number [undefined]!'); } })); it('should initialize transport with the given device instance', () => __awaiter(void 0, void 0, void 0, function* () { const transport = yield deviceApi.getTransport(usbDevice); expect(transport).to.be.instanceof(transport_1.default); expect(transport.device).to.deep.equal(usbDevice); })); it('should retry finding device and fail if it doesnt', () => __awaiter(void 0, void 0, void 0, function* () { getDeviceStub.resolves(undefined); try { yield deviceApi.getTransport(usbDevice); } catch (e) { // Ok to fail } expect(getDeviceStub).to.have.callCount(10); })); it('should retry max attempt times ', () => __awaiter(void 0, void 0, void 0, function* () { deviceApi = new index_1.default({ manager: dummyDeviceDiscoveryManager, maxSearchRetries: 99, }); getDeviceStub.resolves(undefined); try { yield deviceApi.getTransport(usbDevice); } catch (e) { // Ok to fail } expect(getDeviceStub).to.have.callCount(99); })); it('should retry until found ', () => __awaiter(void 0, void 0, void 0, function* () { deviceApi = new index_1.default({ manager: dummyDeviceDiscoveryManager, alwaysRetry: true, }); for (let i = 0; i < 77; i++) { getDeviceStub.onCall(i).resolves(undefined); } getDeviceStub.onCall(78).resolves(usbDevice); const transport = yield deviceApi.getTransport(usbDevice); expect(getDeviceStub).to.have.callCount(78); expect(transport).to.be.instanceof(transport_1.default); expect(transport.device).to.deep.equal(usbDevice); })); }); describe('#isUVCControlsSupported', () => { it('should not support UVC controls', () => __awaiter(void 0, void 0, void 0, function* () { const uvcSupport = yield deviceApi.isUVCControlsSupported(supportedMockedDevices.boxfish); expect(uvcSupport).to.equal(false); })); }); describe('#getUVCControlAPIForDevice', () => { it('should throw error when calling getUVCControlAPIForDevice for node-usb device api', () => __awaiter(void 0, void 0, void 0, function* () { try { yield deviceApi.getUVCControlAPIForDevice(supportedMockedDevices.boxfish); expect(true).to.equal(false); } catch (e) { expect(e.message).to.equal('UVCControlInterface API not available for node-usb'); } })); }); describe('#isHIDSupported', () => { it('should not support HID', () => __awaiter(void 0, void 0, void 0, function* () { const hidSupport = yield deviceApi.isHIDSupported(supportedMockedDevices.boxfish); expect(hidSupport).to.equal(false); })); }); describe('#getHIDApiForDevice', () => { it('should throw error when calling getHIDAPIForDevice for node-usb device api', () => __awaiter(void 0, void 0, void 0, function* () { try { yield deviceApi.getHIDAPIForDevice(supportedMockedDevices.boxfish); expect(true).to.equal(false); } catch (e) { expect(e.message).to.equal('HID Unsupported for device-api usb'); } })); }); }); //# sourceMappingURL=api.spec.js.map