dnssd
Version:
Bonjour/Avahi-like service discovery in pure JavaScript
163 lines (122 loc) • 4.84 kB
JavaScript
const chai = require('chai');
const expect = chai.expect;
const rewire = require('rewire');
const sinon = require('sinon');
const sinonChai = require('sinon-chai');
chai.use(sinonChai);
const dir = process['test-dir'] || '../../src';
const Fake = require('../Fake');
const DisposableInterface = rewire(dir + '/DisposableInterface');
describe('DisposableInterface', function() {
// interface addresses, same form as os.networkInterfaces() output
const interfaceAddresses = {
'Ethernet':
[ { address: 'fe80::73b6:73b6:73b6:73b6',
family: 'IPv6',
internal: false },
{ address: '169.254.100.175',
family: 'IPv4',
internal: false } ],
'Wi-Fi':
[ { address: 'fe80::7b30:7b30:7b30:7b30',
family: 'IPv6',
internal: false },
{ address: '192.168.1.5',
family: 'IPv4',
internal: false } ],
'Loopback':
[ { address: '::1',
family: 'IPv6',
internal: true },
{ address: '127.0.0.1',
family: 'IPv4',
internal: true } ],
};
const socket = new Fake.Socket();
socket.address.returns({});
const dgram = {createSocket: sinon.stub().returns(socket)};
const osStub = {networkInterfaces: sinon.stub().returns(interfaceAddresses)};
const wifi = interfaceAddresses['Wi-Fi'];
const IPv6 = wifi[0];
const IPv4 = wifi[1];
DisposableInterface.__set__('dgram', dgram);
DisposableInterface.__set__('os', osStub);
beforeEach(function() {
socket.reset();
dgram.createSocket.reset();
});
describe('::create()', function() {
it('should make a new DisposableInterface on INADDR_ANY', function() {
const intf = DisposableInterface.create();
expect(intf).to.be.instanceof(DisposableInterface);
expect(intf._addresses).to.eql([{adderss: '0.0.0.0', family: 'IPv4'}]);
});
it('should return new interface from an interface name', function() {
const intf = DisposableInterface.create('Wi-Fi');
expect(intf).to.be.instanceof(DisposableInterface);
expect(intf._addresses).to.equal(wifi);
});
});
describe('::isValidName()', function() {
it('should be false for bad inputs: "", {}, []', function() {
expect(DisposableInterface.isValidName()).to.be.false;
expect(DisposableInterface.isValidName('')).to.be.false;
expect(DisposableInterface.isValidName({})).to.be.false;
});
it('should be true for active interfaces', function() {
expect(DisposableInterface.isValidName('Ethernet')).to.be.true;
expect(DisposableInterface.isValidName('Wi-Fi')).to.be.true;
});
it('should be false for inactive/non-existent interfaces', function() {
expect(DisposableInterface.isValidName('ScoobyDoo')).to.be.false;
});
});
describe('#.bind()', function() {
it('should bind a socket for each address', function(done) {
const intf = DisposableInterface.create('Wi-Fi');
sinon.stub(intf, '_bindSocket').returns(Promise.resolve());
intf.bind().then(done);
});
});
describe('#_bindSocket()', function() {
it('should create IPv4 socket and resolve when bound', function(done) {
const intf = DisposableInterface.create('Wi-Fi');
intf._bindSocket(IPv4).then(() => {
expect(dgram.createSocket).to.have.been.calledWithMatch({type: 'udp4'});
done();
});
socket.emit('listening');
});
it('should create IPv6 socket and resolve when bound', function(done) {
const intf = DisposableInterface.create('Wi-Fi');
intf._bindSocket(IPv6).then(() => {
expect(dgram.createSocket).to.have.been.calledWithMatch({type: 'udp6'});
done();
});
socket.emit('listening');
});
it('should reject if bind fails', function(done) {
const intf = DisposableInterface.create('Wi-Fi');
intf._bindSocket(IPv4).catch(() => done());
socket.emit('error');
});
it('should _onError when socket closes unexpectedly', function(done) {
const intf = DisposableInterface.create('Wi-Fi');
sinon.stub(intf, '_onError', () => done());
intf._bindSocket(IPv4).then(() => socket.emit('close'));
socket.emit('listening');
});
it('should _onError on any other unexpected error', function(done) {
const intf = DisposableInterface.create('Wi-Fi');
sinon.stub(intf, '_onError', () => done());
intf._bindSocket(IPv4).then(() => socket.emit('error'));
socket.emit('listening');
});
it('should _onMessage when socket receives a message', function(done) {
const intf = DisposableInterface.create('Wi-Fi');
sinon.stub(intf, '_onMessage', () => done());
intf._bindSocket(IPv4).then(() => socket.emit('message'));
socket.emit('listening');
});
});
});