@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
JavaScript
;
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