@mkerix/noble
Version:
A Node.js BLE (Bluetooth Low Energy) central library.
573 lines (417 loc) • 17.5 kB
JavaScript
require('should');
const sinon = require('sinon');
const Peripheral = require('../lib/peripheral');
describe('Peripheral', function () {
let mockNoble = null;
const mockId = 'mock-id';
const mockAddress = 'mock-address';
const mockAddressType = 'mock-address-type';
const mockConnectable = 'mock-connectable';
const mockAdvertisement = 'mock-advertisement';
const mockRssi = 'mock-rssi';
const mockHandle = 'mock-handle';
let mockData = 'mock-data';
let peripheral = null;
beforeEach(function () {
mockNoble = {
connect: sinon.spy(),
disconnect: sinon.spy(),
updateRssi: sinon.spy(),
discoverServices: sinon.spy(),
readHandle: sinon.spy(),
writeHandle: sinon.spy()
};
peripheral = new Peripheral(mockNoble, mockId, mockAddress, mockAddressType, mockConnectable, mockAdvertisement, mockRssi);
});
afterEach(function () {
peripheral = null;
});
it('should have a id', function () {
peripheral.id.should.equal(mockId);
});
it('should have an address', function () {
peripheral.address.should.equal(mockAddress);
});
it('should have an address type', function () {
peripheral.addressType.should.equal(mockAddressType);
});
it('should have connectable', function () {
peripheral.connectable.should.equal(mockConnectable);
});
it('should have advertisement', function () {
peripheral.advertisement.should.equal(mockAdvertisement);
});
it('should have rssi', function () {
peripheral.rssi.should.equal(mockRssi);
});
describe('toString', function () {
it('should be id, address, address type, connectable, advertisement, rssi, state', function () {
peripheral.toString().should.equal('{"id":"mock-id","address":"mock-address","addressType":"mock-address-type","connectable":"mock-connectable","advertisement":"mock-advertisement","rssi":"mock-rssi","mtu":null,"state":"disconnected"}');
});
});
describe('connect', function () {
it('should delegate to noble', function () {
peripheral.connect();
mockNoble.connect.calledWithExactly(mockId).should.equal(true);
});
it('should callback', function () {
let calledback = false;
peripheral.connect(function () {
calledback = true;
});
peripheral.emit('connect');
calledback.should.equal(true);
});
});
describe('connectAsync', () => {
it('should resolve', async () => {
const promise = peripheral.connectAsync();
peripheral.emit('connect');
await promise.should.be.fulfilled();
});
it('should reject on error', async () => {
const promise = peripheral.connectAsync();
peripheral.emit('connect', new Error('error'));
await promise.should.be.rejectedWith('error');
});
it('should delegate to noble', async () => {
const promise = peripheral.connectAsync();
peripheral.emit('connect');
await promise;
mockNoble.connect.calledWithExactly(mockId).should.equal(true);
});
});
describe('disconnect', function () {
it('should delegate to noble', function () {
peripheral.disconnect();
mockNoble.disconnect.calledWithExactly(mockId).should.equal(true);
});
it('should callback', function () {
let calledback = false;
peripheral.disconnect(function () {
calledback = true;
});
peripheral.emit('disconnect');
calledback.should.equal(true);
});
});
describe('disconnectAsync', function () {
it('should resolve', async () => {
const promise = peripheral.disconnectAsync();
peripheral.emit('disconnect');
await promise.should.be.fulfilled();
});
it('should delegate to noble', () => {
peripheral.disconnect();
mockNoble.disconnect.calledWithExactly(mockId).should.equal(true);
});
});
describe('updateRssi', function () {
it('should delegate to noble', function () {
peripheral.updateRssi();
mockNoble.updateRssi.calledWithExactly(mockId).should.equal(true);
});
it('should callback', function () {
let calledback = false;
peripheral.updateRssi(function () {
calledback = true;
});
peripheral.emit('rssiUpdate');
calledback.should.equal(true);
});
it('should callback with rssi', function () {
let calledbackRssi = null;
peripheral.updateRssi(function (error, rssi) {
if (error) {
throw new Error(error);
}
calledbackRssi = rssi;
});
peripheral.emit('rssiUpdate', mockRssi);
calledbackRssi.should.equal(mockRssi);
});
});
describe('updateRssiAsync', () => {
it('should resolve with rssi', async () => {
const promise = peripheral.updateRssiAsync();
peripheral.emit('rssiUpdate', mockRssi);
await promise.should.be.fulfilledWith(mockRssi);
});
it('should delegate to noble', async () => {
const promise = peripheral.updateRssiAsync();
peripheral.emit('rssiUpdate');
await promise;
mockNoble.updateRssi.calledWithExactly(mockId).should.equal(true);
});
});
describe('discoverServices', function () {
it('should delegate to noble', function () {
peripheral.discoverServices();
mockNoble.discoverServices.calledWithExactly(mockId, undefined).should.equal(true);
});
it('should delegate to noble, service uuids', function () {
const mockServiceUuids = [];
peripheral.discoverServices(mockServiceUuids);
mockNoble.discoverServices.calledWithExactly(mockId, mockServiceUuids).should.equal(true);
});
it('should callback', function () {
let calledback = false;
peripheral.discoverServices(null, function () {
calledback = true;
});
peripheral.emit('servicesDiscover');
calledback.should.equal(true);
});
it('should callback with services', function () {
const mockServices = [];
let calledbackServices = null;
peripheral.discoverServices(null, function (error, services) {
if (error) {
throw new Error(error);
}
calledbackServices = services;
});
peripheral.emit('servicesDiscover', mockServices);
calledbackServices.should.equal(mockServices);
});
});
describe('discoverServicesAsync', () => {
it('should resolve with services', async () => {
const mockServices = 'discoveredServices';
const promise = peripheral.discoverServicesAsync();
peripheral.emit('servicesDiscover', mockServices);
await promise.should.be.fulfilledWith(mockServices);
});
it('should delegate to noble', async () => {
const promise = peripheral.discoverServicesAsync();
peripheral.emit('servicesDiscover');
await promise;
mockNoble.discoverServices.calledWithExactly(mockId, undefined).should.equal(true);
});
it('should delegate to noble, service uuids', async () => {
const mockServiceUuids = [];
const promise = peripheral.discoverServicesAsync(mockServiceUuids);
peripheral.emit('servicesDiscover');
await promise;
mockNoble.discoverServices.calledWithExactly(mockId, mockServiceUuids).should.equal(true);
});
});
describe('discoverSomeServicesAndCharacteristics', function () {
const mockServiceUuids = [];
const mockCharacteristicUuids = [];
let mockServices = null;
beforeEach(function () {
peripheral.discoverServices = sinon.spy();
mockServices = [
{
uuid: '1',
discoverCharacteristics: sinon.spy()
},
{
uuid: '2',
discoverCharacteristics: sinon.spy()
}
];
});
it('should call discoverServices', function () {
peripheral.discoverSomeServicesAndCharacteristics(mockServiceUuids);
peripheral.discoverServices.calledWith(mockServiceUuids).should.equal(true);
});
it('should call discoverCharacteristics on each service discovered', function () {
peripheral.discoverSomeServicesAndCharacteristics(mockServiceUuids, mockCharacteristicUuids);
const discoverServicesCallback = peripheral.discoverServices.getCall(0).args[1];
discoverServicesCallback(null, mockServices);
mockServices[0].discoverCharacteristics.calledWith(mockCharacteristicUuids).should.equal(true);
mockServices[1].discoverCharacteristics.calledWith(mockCharacteristicUuids).should.equal(true);
});
it('should callback', function () {
let calledback = false;
peripheral.discoverSomeServicesAndCharacteristics(mockServiceUuids, mockCharacteristicUuids, function () {
calledback = true;
});
const discoverServicesCallback = peripheral.discoverServices.getCall(0).args[1];
discoverServicesCallback(null, mockServices);
mockServices[0].discoverCharacteristics.getCall(0).args[1](null, []);
mockServices[1].discoverCharacteristics.getCall(0).args[1](null, []);
calledback.should.equal(true);
});
it('should callback with the services and characteristics discovered', function () {
let calledbackServices = null;
let calledbackCharacteristics = null;
peripheral.discoverSomeServicesAndCharacteristics(mockServiceUuids, mockCharacteristicUuids, function (err, services, characteristics) {
if (err) {
throw new Error(err);
}
calledbackServices = services;
calledbackCharacteristics = characteristics;
});
const discoverServicesCallback = peripheral.discoverServices.getCall(0).args[1];
discoverServicesCallback(null, mockServices);
const mockCharacteristic1 = { uuid: '1' };
const mockCharacteristic2 = { uuid: '2' };
const mockCharacteristic3 = { uuid: '3' };
mockServices[0].discoverCharacteristics.getCall(0).args[1](null, [mockCharacteristic1]);
mockServices[1].discoverCharacteristics.getCall(0).args[1](null, [mockCharacteristic2, mockCharacteristic3]);
calledbackServices.should.equal(mockServices);
calledbackCharacteristics.should.eql([mockCharacteristic1, mockCharacteristic2, mockCharacteristic3]);
});
});
describe('discoverSomeServicesAndCharacteristicsAsync', () => {
const mockServiceUuids = [];
const mockCharacteristicUuids = [];
let mockServices = null;
beforeEach(function () {
peripheral.discoverServices = sinon.spy();
mockServices = [
{
uuid: '1',
discoverCharacteristics: sinon.spy()
},
{
uuid: '2',
discoverCharacteristics: sinon.spy()
}
];
});
it('should call discoverServices', async () => {
peripheral.discoverSomeServicesAndCharacteristicsAsync(mockServiceUuids);
peripheral.discoverServices.calledWith(mockServiceUuids).should.equal(true);
});
it('should call discoverCharacteristics on each service discovered', () => {
peripheral.discoverSomeServicesAndCharacteristicsAsync(mockServiceUuids, mockCharacteristicUuids);
const discoverServicesCallback = peripheral.discoverServices.getCall(0).args[1];
discoverServicesCallback(null, mockServices);
mockServices[0].discoverCharacteristics.calledWith(mockCharacteristicUuids).should.equal(true);
mockServices[1].discoverCharacteristics.calledWith(mockCharacteristicUuids).should.equal(true);
});
it('should reject on error', async () => {
const promise = peripheral.discoverSomeServicesAndCharacteristicsAsync(mockServiceUuids);
const discoverServicesCallback = peripheral.discoverServices.getCall(0).args[1];
discoverServicesCallback(new Error('error'));
await promise.should.be.rejectedWith('error');
});
it('should resolve with the services and characteristics discovered', async () => {
const promise = peripheral.discoverSomeServicesAndCharacteristicsAsync(mockServiceUuids, mockCharacteristicUuids);
const discoverServicesCallback = peripheral.discoverServices.getCall(0).args[1];
discoverServicesCallback(null, mockServices);
const mockCharacteristic1 = { uuid: '1' };
const mockCharacteristic2 = { uuid: '2' };
const mockCharacteristic3 = { uuid: '3' };
mockServices[0].discoverCharacteristics.getCall(0).args[1](null, [mockCharacteristic1]);
mockServices[1].discoverCharacteristics.getCall(0).args[1](null, [mockCharacteristic2, mockCharacteristic3]);
const result = await promise;
result.services.should.equal(mockServices);
result.characteristics.should.eql([mockCharacteristic1, mockCharacteristic2, mockCharacteristic3]);
});
});
describe('discoverAllServicesAndCharacteristics', function () {
it('should call discoverSomeServicesAndCharacteristics', function () {
const mockCallback = sinon.spy();
peripheral.discoverSomeServicesAndCharacteristics = sinon.spy();
peripheral.discoverAllServicesAndCharacteristics(mockCallback);
peripheral.discoverSomeServicesAndCharacteristics.calledWithExactly([], [], mockCallback).should.equal(true);
});
});
describe('discoverAllServicesAndCharacteristicsAsync', () => {
it('should call discoverSomeServicesAndCharacteristics', async () => {
peripheral.discoverSomeServicesAndCharacteristics = sinon.spy();
const promise = peripheral.discoverAllServicesAndCharacteristicsAsync();
const callback = peripheral.discoverSomeServicesAndCharacteristics.getCall(0).args[2];
callback(null);
await promise;
peripheral.discoverSomeServicesAndCharacteristics.getCall(0).args[0].should.eql([]);
peripheral.discoverSomeServicesAndCharacteristics.getCall(0).args[1].should.eql([]);
});
});
describe('readHandle', function () {
it('should delegate to noble', function () {
peripheral.readHandle(mockHandle);
mockNoble.readHandle.calledWithExactly(mockId, mockHandle).should.equal(true);
});
it('should callback', function () {
let calledback = false;
peripheral.readHandle(mockHandle, function () {
calledback = true;
});
peripheral.emit(`handleRead${mockHandle}`);
calledback.should.equal(true);
});
it('should callback with data', function () {
let calledbackData = null;
peripheral.readHandle(mockHandle, function (error, data) {
if (error) {
throw new Error(error);
}
calledbackData = data;
});
peripheral.emit(`handleRead${mockHandle}`, mockData);
calledbackData.should.equal(mockData);
});
});
describe('readHandleAsync', () => {
it('should delegate to noble', async () => {
const promise = peripheral.readHandleAsync(mockHandle);
peripheral.emit(`handleRead${mockHandle}`);
await promise;
mockNoble.readHandle.calledWithExactly(mockId, mockHandle).should.equal(true);
});
it('should resolve with data', async () => {
const promise = peripheral.readHandleAsync(mockHandle);
peripheral.emit(`handleRead${mockHandle}`, mockData);
await promise.should.be.fulfilledWith(mockData);
});
});
describe('writeHandle', function () {
beforeEach(function () {
mockData = Buffer.alloc(0);
});
it('should only accept data as a buffer', function () {
mockData = {};
(function () {
peripheral.writeHandle(mockHandle, mockData);
}).should.throwError('data must be a Buffer');
});
it('should delegate to noble, withoutResponse false', function () {
peripheral.writeHandle(mockHandle, mockData, false);
mockNoble.writeHandle.calledWithExactly(mockId, mockHandle, mockData, false).should.equal(true);
});
it('should delegate to noble, withoutResponse true', function () {
peripheral.writeHandle(mockHandle, mockData, true);
mockNoble.writeHandle.calledWithExactly(mockId, mockHandle, mockData, true).should.equal(true);
});
it('should callback', function () {
let calledback = false;
peripheral.writeHandle(mockHandle, mockData, false, function () {
calledback = true;
});
peripheral.emit(`handleWrite${mockHandle}`);
calledback.should.equal(true);
});
});
describe('writeHandleAsync', () => {
beforeEach(() => {
mockData = Buffer.alloc(0);
});
it('should only accept data as a buffer', async () => {
mockData = {};
await peripheral.writeHandleAsync(mockHandle, mockData).should.be.rejectedWith('data must be a Buffer');
});
it('should delegate to noble, withoutResponse false', async () => {
const promise = peripheral.writeHandleAsync(mockHandle, mockData, false);
peripheral.emit(`handleWrite${mockHandle}`);
await promise;
mockNoble.writeHandle.calledWithExactly(mockId, mockHandle, mockData, false).should.equal(true);
});
it('should delegate to noble, withoutResponse true', async () => {
const promise = peripheral.writeHandleAsync(mockHandle, mockData, true);
peripheral.emit(`handleWrite${mockHandle}`);
await promise;
mockNoble.writeHandle.calledWithExactly(mockId, mockHandle, mockData, true).should.equal(true);
});
it('should resolve', async () => {
const promise = peripheral.writeHandleAsync(mockHandle, mockData, false);
peripheral.emit(`handleWrite${mockHandle}`);
await promise.should.be.resolvedWith();
});
});
});