Skip to content

Commit

Permalink
Add Switch plugin unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
javierbrea committed Dec 7, 2018
1 parent 25402c3 commit e3dce3e
Show file tree
Hide file tree
Showing 5 changed files with 256 additions and 27 deletions.
36 changes: 19 additions & 17 deletions lib/plugins/SwitchFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,33 @@ const SwitchFactory = function (Service, Characteristic) {
this.getServices = this.getServices.bind(this)
this.getSwitchOnCharacteristic = this.getSwitchOnCharacteristic.bind(this)
this.setSwitchOnCharacteristic = this.setSwitchOnCharacteristic.bind(this)

this.requestOptions = {
uri: this.bridgeUrl,
json: true,
headers: {
'X-Api-Key': this.config.apiKey
},
method: 'GET'
}
}

static get name () {
return ACCESORY_SWITCH_NAME
}

logError (error) {
this.log(`${HOMEBRIDGE_ERROR} ${error.message}`)
}

getServices () {
const informationService = new Service.AccessoryInformation()
informationService
.setCharacteristic(Characteristic.Manufacturer, DOMAPIC)
.setCharacteristic(Characteristic.Model, this.config.servicePackageName)
.setCharacteristic(Characteristic.SerialNumber, this.config.serviceProcessId)

const switchService = new Service.Switch(`${this.config.name}`)
const switchService = new Service.Switch(this.config.name)
switchService.getCharacteristic(Characteristic.On)
.on('get', this.getSwitchOnCharacteristic)
.on('set', this.setSwitchOnCharacteristic)
Expand All @@ -40,39 +53,28 @@ const SwitchFactory = function (Service, Characteristic) {

getSwitchOnCharacteristic (next) {
this.log(`Getting state`)
requestPromise({
uri: this.bridgeUrl,
method: 'GET',
json: true,
headers: {
'X-Api-Key': this.config.apiKey
}
}).then(body => {
return requestPromise(this.requestOptions).then(body => {
this.log(`State is "${body.data}"`)
next(null, body.data)
}).catch(error => {
this.log(`${HOMEBRIDGE_ERROR} ${error.message}`)
this.logError(error)
next(error)
})
}

setSwitchOnCharacteristic (on, next) {
this.log(`Setting to "${on}"`)
requestPromise({
uri: this.bridgeUrl,
return requestPromise({
...this.requestOptions,
method: 'POST',
body: {
data: on
},
json: true,
headers: {
'X-Api-Key': this.config.apiKey
}
}).then(() => {
this.log(`Set to "${on}" success`)
next()
}).catch(error => {
this.log(`${HOMEBRIDGE_ERROR} ${error.message}`)
this.logError(error)
next(error)
})
}
Expand Down
54 changes: 54 additions & 0 deletions test/unit/Homebridge.mocks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const test = require('narval')

const Mock = function () {
let sandbox = test.sinon.createSandbox()

const stubs = {
hap: {
Service: sandbox.stub(),
Characteristic: sandbox.stub()
},
registerAccessory: sandbox.stub()
}

const instances = {
accessoryInformation: {
setCharacteristic: sandbox.stub().callsFake(() => {
return instances.accessoryInformation
})
},
switch: {
on: sandbox.stub().callsFake(() => {
return instances.switch
}),
getCharacteristic: sandbox.stub().callsFake(() => {
return instances.switch
})
}
}

stubs.hap.Characteristic.Model = 'MODEL'
stubs.hap.Characteristic.SerialNumber = 'SERIAL_NUMBER'
stubs.hap.Characteristic.Manufacturer = 'MANUFACTURER'
stubs.hap.Characteristic.On = 'ON'

stubs.hap.Service.AccessoryInformation = sandbox.stub().callsFake(function () {
return instances.accessoryInformation
})

stubs.hap.Service.Switch = sandbox.stub().callsFake(function () {
return instances.switch
})

const restore = () => {
sandbox.restore()
}

return {
restore,
stubs,
instances
}
}

module.exports = Mock
25 changes: 25 additions & 0 deletions test/unit/RequestPromise.mocks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const test = require('narval')

const mockery = require('./mockery')

const MODULE = 'request-promise'

const Mock = function () {
let sandbox = test.sinon.createSandbox()

const stub = sandbox.stub().resolves()

const restore = () => {
sandbox.restore()
mockery.deregister(MODULE)
}

mockery.register(MODULE, stub)

return {
restore,
stub
}
}

module.exports = Mock
153 changes: 153 additions & 0 deletions test/unit/lib/plugins/SwitchFactory.specs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
const test = require('narval')

const HomebridgeMocks = require('../../Homebridge.mocks')
const RequestPromiseMocks = require('../../RequestPromise.mocks')

test.describe('Switch Plugin Factory', () => {
let homebridge
let requestPromise
let SwitchFactory
let Switch
let switchPlugin
let fooConfig
let sandbox
let log

test.beforeEach(() => {
sandbox = test.sinon.createSandbox()
log = sandbox.stub()
fooConfig = {
abilityName: 'foo-name',
accessory: 'DomapicSwitch',
apiKey: 'foo-api-key',
bridgeUrl: 'foo-url/foo-id',
name: 'foo-service-name foo-name',
serviceName: 'foo-service-name',
servicePackageName: 'foo-service-package',
serviceProcessId: 'foo-service-processId'
}
homebridge = new HomebridgeMocks()
requestPromise = new RequestPromiseMocks()

SwitchFactory = require('../../../../lib/plugins/SwitchFactory')
Switch = new SwitchFactory(homebridge.stubs.hap.Service, homebridge.stubs.hap.Characteristic)
switchPlugin = new Switch(log, fooConfig)
})

test.afterEach(() => {
sandbox.restore()
homebridge.restore()
requestPromise.restore()
})

test.describe('Switch static name getter', () => {
test.it('should return accessory name', () => {
test.expect(Switch.name).to.equal('DomapicSwitch')
})
})

test.describe('Switch instance', () => {
test.describe('logError method', () => {
test.it('should log error message', () => {
const FOO_MESSAGE = 'Foo error message'
const error = new Error(FOO_MESSAGE)
switchPlugin.logError(error)
test.expect(log).to.have.been.calledWith(`ERROR: ${FOO_MESSAGE}`)
})
})

test.describe('getServices method', () => {
test.it('should set accesory Manufacturer as Domapic', () => {
switchPlugin.getServices()
test.expect(homebridge.instances.accessoryInformation.setCharacteristic).to.have.been.calledWith(
homebridge.stubs.hap.Characteristic.Manufacturer,
'Domapic'
)
})

test.it('should set accesory Model with configuration servicePackageName', () => {
switchPlugin.getServices()
test.expect(homebridge.instances.accessoryInformation.setCharacteristic).to.have.been.calledWith(
homebridge.stubs.hap.Characteristic.Model,
'foo-service-package'
)
})

test.it('should set accesory SerialNumber with configuration serviceProcessId', () => {
switchPlugin.getServices()
test.expect(homebridge.instances.accessoryInformation.setCharacteristic).to.have.been.calledWith(
homebridge.stubs.hap.Characteristic.SerialNumber,
'foo-service-processId'
)
})

test.it('should have configured switch service to call "getSwitchOnCharacteristic" method on get event', () => {
switchPlugin.getServices()
test.expect(homebridge.instances.switch.on).to.have.been.calledWith(
'get',
switchPlugin.getSwitchOnCharacteristic
)
})

test.it('should have configured switch service to call "setSwitchOnCharacteristic" method on set event', () => {
switchPlugin.getServices()
test.expect(homebridge.instances.switch.on).to.have.been.calledWith(
'set',
switchPlugin.setSwitchOnCharacteristic
)
})
})

test.describe('getSwitchOnCharacteristic method', () => {
test.it('should call to request plugin bridge api, and invoque callback with result if request is success', () => {
const fooData = 'foo'
requestPromise.stub.resolves({
data: fooData
})
const cb = sandbox.stub()
return switchPlugin.getSwitchOnCharacteristic(cb)
.then(() => {
return Promise.all([
test.expect(requestPromise.stub).to.have.been.called(),
test.expect(cb).to.have.been.calledWith(null, fooData)
])
})
})

test.it('should invoque callback with error if request fails', () => {
const fooError = new Error('foo')
requestPromise.stub.rejects(fooError)
const cb = sandbox.stub()
return switchPlugin.getSwitchOnCharacteristic(cb)
.then(() => {
return test.expect(cb).to.have.been.calledWith(fooError)
})
})
})

test.describe('setSwitchOnCharacteristic method', () => {
test.it('should call to request plugin bridge api, and invoque callback with no data if request is success', () => {
const fooData = 'foo'
requestPromise.stub.resolves()
const cb = sandbox.stub()
return switchPlugin.setSwitchOnCharacteristic(fooData, cb)
.then(() => {
return Promise.all([
test.expect(requestPromise.stub.getCall(0).args[0].body.data).to.equal(fooData),
test.expect(cb).to.have.been.called()
])
})
})

test.it('should invoque callback with error if request fails', () => {
const fooError = new Error('foo')
requestPromise.stub.rejects(fooError)
const cb = sandbox.stub()
return switchPlugin.setSwitchOnCharacteristic('foo', cb)
.then(() => {
return test.expect(cb).to.have.been.calledWith(fooError)
})
})
})
})
})
15 changes: 5 additions & 10 deletions test/unit/plugin/index.specs.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const test = require('narval')

const SwitchFactoryMocks = require('../lib/plugins/SwitchFactory.mocks')
const HomebridgeMocks = require('../Homebridge.mocks')

test.describe('plugin', () => {
let sandbox
Expand All @@ -10,16 +11,10 @@ test.describe('plugin', () => {

test.before(() => {
sandbox = test.sinon.createSandbox()
homebridge = {
hap: {
Service: 'foo Service',
Characteristic: 'foo Characteristic'
},
registerAccessory: sandbox.stub()
}
homebridge = new HomebridgeMocks()
switchFactory = new SwitchFactoryMocks()
plugin = require('../../../plugin/index')
plugin(homebridge)
plugin(homebridge.stubs)
})

test.after(() => {
Expand All @@ -28,10 +23,10 @@ test.describe('plugin', () => {
})

test.it('should create a new Switch accessory', () => {
test.expect(switchFactory.stubs.Constructor).to.have.been.calledWith(homebridge.hap.Service, homebridge.hap.Characteristic)
test.expect(switchFactory.stubs.Constructor).to.have.been.calledWith(homebridge.stubs.hap.Service, homebridge.stubs.hap.Characteristic)
})

test.it('should register switch accesory in homebridge', () => {
test.expect(homebridge.registerAccessory.getCall(0).args[2]).to.equal(switchFactory.stubs.instance)
test.expect(homebridge.stubs.registerAccessory.getCall(0).args[2]).to.equal(switchFactory.stubs.instance)
})
})

0 comments on commit e3dce3e

Please sign in to comment.