2020-05-24 09:16:39 -07:00
const data = require ( './stub/data' ) ;
const logger = require ( './stub/logger' ) ;
const zigbeeHerdsman = require ( './stub/zigbeeHerdsman' ) ;
const MQTT = require ( './stub/mqtt' ) ;
const settings = require ( '../lib/util/settings' ) ;
const Controller = require ( '../lib/controller' ) ;
const flushPromises = ( ) => new Promise ( setImmediate ) ;
const mockExit = jest . spyOn ( process , 'exit' ) . mockImplementation ( ( ) => { } ) ;
const { coordinator , bulb , unsupported } = zigbeeHerdsman . devices ;
zigbeeHerdsman . returnDevices . push ( coordinator . ieeeAddr ) ;
zigbeeHerdsman . returnDevices . push ( bulb . ieeeAddr ) ;
zigbeeHerdsman . returnDevices . push ( unsupported . ieeeAddr ) ;
describe ( 'Bridge' , ( ) => {
let controller ;
beforeEach ( async ( ) => {
data . writeDefaultConfiguration ( ) ;
settings . _reRead ( ) ;
settings . set ( [ 'advanced' , 'legacy_api' ] , false ) ;
settings . set ( [ 'experimental' , 'new_api' ] , true ) ;
data . writeDefaultState ( ) ;
logger . info . mockClear ( ) ;
logger . warn . mockClear ( ) ;
MQTT . publish . mockClear ( ) ;
2020-06-13 08:22:00 -07:00
const device = zigbeeHerdsman . devices . bulb ;
device . removeFromDatabase . mockClear ( ) ;
device . removeFromNetwork . mockClear ( ) ;
2020-05-24 09:16:39 -07:00
controller = new Controller ( ) ;
await controller . start ( ) ;
await flushPromises ( ) ;
} ) ;
it ( 'Should publish bridge info on startup' , async ( ) => {
const version = await require ( '../lib/util/utils' ) . getZigbee2mqttVersion ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/info' ,
2020-07-13 14:00:33 -07:00
JSON . stringify ( { "version" : version . version , "commit" : version . commitHash , "coordinator" : { "type" : "z-Stack" , "meta" : { "version" : 1 , "revision" : 20190425 } } , "log_level" : "info" , "permit_join" : false } ) ,
2020-05-24 09:16:39 -07:00
{ retain : true , qos : 0 } ,
expect . any ( Function )
) ;
} ) ;
it ( 'Should publish devices on startup' , async ( ) => {
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/devices' ,
2020-07-13 14:00:33 -07:00
JSON . stringify ( [ { "ieee_address" : "0x000b57fffec6a5b2" , "type" : "Router" , "network_address" : 40369 , "supported" : true , "friendly_name" : "bulb" , "definition" : { "model" : "LED1545G12" , "vendor" : "IKEA" , "description" : "TRADFRI LED bulb E26/E27 980 lumen, dimmable, white spectrum, opal white" , "supports" : "on/off, brightness, color temperature" } , "power_source" : "Mains (single phase)" , "date_code" : null , "interviewing" : false , "interview_completed" : true } , { "ieee_address" : "0x0017880104e45518" , "type" : "EndDevice" , "network_address" : 6536 , "supported" : false , "friendly_name" : "0x0017880104e45518" , "definition" : null , "power_source" : "Battery" , "date_code" : null , "interviewing" : false , "interview_completed" : true } ] ) ,
2020-05-24 09:16:39 -07:00
{ retain : true , qos : 0 } ,
expect . any ( Function )
) ;
} ) ;
it ( 'Should publish devices on startup' , async ( ) => {
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/groups' ,
2020-07-15 13:16:18 -07:00
JSON . stringify ( [ { "id" : 1 , "friendly_name" : "group_1" , "members" : [ ] } , { "id" : 15071 , "friendly_name" : "group_tradfri_remote" , "members" : [ ] } , { "id" : 99 , "friendly_name" : 99 , "members" : [ ] } , { "id" : 11 , "friendly_name" : "group_with_tradfri" , "members" : [ ] } , { "id" : 2 , "friendly_name" : "group_2" , "members" : [ ] } ] ) ,
2020-05-24 09:16:39 -07:00
{ retain : true , qos : 0 } ,
expect . any ( Function )
) ;
} ) ;
it ( 'Should publish event when device joined' , async ( ) => {
MQTT . publish . mockClear ( ) ;
await zigbeeHerdsman . events . deviceJoined ( { device : zigbeeHerdsman . devices . bulb } ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/event' ,
2020-07-13 14:00:33 -07:00
JSON . stringify ( { "type" : "device_joined" , "data" : { "friendly_name" : "bulb" , "ieee_address" : "0x000b57fffec6a5b2" } } ) ,
2020-05-24 09:16:39 -07:00
{ retain : false , qos : 0 } ,
expect . any ( Function )
) ;
} ) ;
it ( 'Should publish event when device interview started' , async ( ) => {
MQTT . publish . mockClear ( ) ;
await zigbeeHerdsman . events . deviceInterview ( { device : zigbeeHerdsman . devices . bulb , status : 'started' } ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/event' ,
2020-07-13 14:00:33 -07:00
JSON . stringify ( { "type" : "device_interview" , "data" : { "friendly_name" : "bulb" , "status" : "started" , "ieee_address" : "0x000b57fffec6a5b2" } } ) ,
2020-05-24 09:16:39 -07:00
{ retain : false , qos : 0 } ,
expect . any ( Function )
) ;
} ) ;
it ( 'Should publish event and devices when device interview failed' , async ( ) => {
MQTT . publish . mockClear ( ) ;
await zigbeeHerdsman . events . deviceInterview ( { device : zigbeeHerdsman . devices . bulb , status : 'failed' } ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 2 ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/event' ,
2020-07-13 14:00:33 -07:00
JSON . stringify ( { "type" : "device_interview" , "data" : { "friendly_name" : "bulb" , "status" : "failed" , "ieee_address" : "0x000b57fffec6a5b2" } } ) ,
2020-05-24 09:16:39 -07:00
{ retain : false , qos : 0 } ,
expect . any ( Function )
) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/devices' ,
expect . any ( String ) ,
{ retain : true , qos : 0 } ,
expect . any ( Function )
) ;
} ) ;
it ( 'Should publish event and devices when device interview successful' , async ( ) => {
MQTT . publish . mockClear ( ) ;
await zigbeeHerdsman . events . deviceInterview ( { device : zigbeeHerdsman . devices . bulb , status : 'successful' } ) ;
await zigbeeHerdsman . events . deviceInterview ( { device : zigbeeHerdsman . devices . unsupported , status : 'successful' } ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 4 ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/event' ,
2020-07-13 14:00:33 -07:00
JSON . stringify ( { "type" : "device_interview" , "data" : { "friendly_name" : "bulb" , "status" : "successful" , "ieee_address" : "0x000b57fffec6a5b2" , "supported" : true , "definition" : { "model" : "LED1545G12" , "vendor" : "IKEA" , "description" : "TRADFRI LED bulb E26/E27 980 lumen, dimmable, white spectrum, opal white" , "supports" : "on/off, brightness, color temperature" } } } ) ,
2020-05-24 09:16:39 -07:00
{ retain : false , qos : 0 } ,
expect . any ( Function )
) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/event' ,
2020-07-13 14:00:33 -07:00
JSON . stringify ( { "type" : "device_interview" , "data" : { "friendly_name" : "0x0017880104e45518" , "status" : "successful" , "ieee_address" : "0x0017880104e45518" , "supported" : false , "definition" : null } } ) ,
2020-05-24 09:16:39 -07:00
{ retain : false , qos : 0 } ,
expect . any ( Function )
) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/devices' ,
expect . any ( String ) ,
{ retain : true , qos : 0 } ,
expect . any ( Function )
) ;
} ) ;
it ( 'Should publish event and devices when device leaves' , async ( ) => {
MQTT . publish . mockClear ( ) ;
await zigbeeHerdsman . events . deviceLeave ( { ieeeAddr : zigbeeHerdsman . devices . bulb . ieeeAddr } ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 2 ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/event' ,
2020-07-13 14:00:33 -07:00
JSON . stringify ( { "type" : "device_leave" , "data" : { "ieee_address" : "0x000b57fffec6a5b2" } } ) ,
2020-05-24 09:16:39 -07:00
{ retain : false , qos : 0 } ,
expect . any ( Function )
) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/devices' ,
expect . any ( String ) ,
{ retain : true , qos : 0 } ,
expect . any ( Function )
) ;
} ) ;
it ( 'Should allow permit join' , async ( ) => {
zigbeeHerdsman . permitJoin . mockClear ( ) ;
MQTT . publish . mockClear ( ) ;
2020-07-13 14:00:33 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/permit_join' , 'true' ) ;
2020-05-24 09:16:39 -07:00
await flushPromises ( ) ;
expect ( zigbeeHerdsman . permitJoin ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( zigbeeHerdsman . permitJoin ) . toHaveBeenCalledWith ( true ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith ( 'zigbee2mqtt/bridge/info' , expect . any ( String ) , { retain : true , qos : 0 } , expect . any ( Function ) ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
2020-07-13 14:00:33 -07:00
'zigbee2mqtt/bridge/response/permit_join' ,
2020-05-24 09:16:39 -07:00
JSON . stringify ( { "data" : { "value" : true } , "status" : "ok" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
zigbeeHerdsman . permitJoin . mockClear ( ) ;
MQTT . publish . mockClear ( ) ;
2020-07-13 14:00:33 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/permit_join' , JSON . stringify ( { "value" : false } ) ) ;
2020-05-24 09:16:39 -07:00
await flushPromises ( ) ;
expect ( zigbeeHerdsman . permitJoin ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( zigbeeHerdsman . permitJoin ) . toHaveBeenCalledWith ( false ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith ( 'zigbee2mqtt/bridge/info' , expect . any ( String ) , { retain : true , qos : 0 } , expect . any ( Function ) ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
2020-07-13 14:00:33 -07:00
'zigbee2mqtt/bridge/response/permit_join' ,
2020-05-24 09:16:39 -07:00
JSON . stringify ( { "data" : { "value" : false } , "status" : "ok" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should put transaction in response when request is done with transaction' , async ( ) => {
MQTT . publish . mockClear ( ) ;
2020-07-13 14:00:33 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/permit_join' , JSON . stringify ( { "value" : false , "transaction" : 22 } ) ) ;
2020-05-24 09:16:39 -07:00
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
2020-07-13 14:00:33 -07:00
'zigbee2mqtt/bridge/response/permit_join' ,
2020-05-24 09:16:39 -07:00
JSON . stringify ( { "data" : { "value" : false } , "status" : "ok" , "transaction" : 22 } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
2020-05-26 08:36:04 -07:00
it ( 'Should put error in response when request fails' , async ( ) => {
2020-05-24 09:16:39 -07:00
zigbeeHerdsman . permitJoin . mockImplementationOnce ( ( ) => { throw new Error ( 'Failed to connect to adapter' ) } ) ;
MQTT . publish . mockClear ( ) ;
2020-07-13 14:00:33 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/permit_join' , JSON . stringify ( { "value" : false } ) ) ;
2020-05-24 09:16:39 -07:00
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
2020-07-13 14:00:33 -07:00
'zigbee2mqtt/bridge/response/permit_join' ,
2020-05-24 09:16:39 -07:00
JSON . stringify ( { "data" : { } , "status" : "error" , "error" : "Failed to connect to adapter" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
2020-06-15 09:58:32 -07:00
it ( 'Should put error in response when format is incorrect' , async ( ) => {
MQTT . publish . mockClear ( ) ;
2020-07-13 14:00:33 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/permit_join' , JSON . stringify ( { "value_not_good" : false } ) ) ;
2020-06-15 09:58:32 -07:00
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
2020-07-13 14:00:33 -07:00
'zigbee2mqtt/bridge/response/permit_join' ,
2020-06-15 09:58:32 -07:00
JSON . stringify ( { "data" : { } , "status" : "error" , "error" : "No value given" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
2020-05-24 09:16:39 -07:00
it ( 'Coverage satisfaction' , async ( ) => {
MQTT . publish . mockClear ( ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/request/random' , JSON . stringify ( { "value" : false } ) ) ;
const device = zigbeeHerdsman . devices . bulb ;
await zigbeeHerdsman . events . message ( { data : { onOff : 1 } , cluster : 'genOnOff' , device , endpoint : device . getEndpoint ( 1 ) , type : 'attributeReport' , linkquality : 10 } ) ;
await flushPromises ( ) ;
} ) ;
2020-06-13 08:22:00 -07:00
2020-07-21 12:14:39 -07:00
it ( 'Should allow a healthcheck' , async ( ) => {
MQTT . publish . mockClear ( ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/request/health_check' , '' ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/health_check' ,
JSON . stringify ( { "data" : { "healthy" : true } , "status" : "ok" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
2020-06-13 08:22:00 -07:00
it ( 'Should allow to remove device by string' , async ( ) => {
const device = zigbeeHerdsman . devices . bulb ;
controller . state . state = { '0x000b57fffec6a5b3' : { brightness : 100 } } ;
MQTT . publish . mockClear ( ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/remove' , 'bulb' ) ;
await flushPromises ( ) ;
expect ( controller . state [ device . ieeeAddr ] ) . toBeUndefined ( ) ;
expect ( device . removeFromNetwork ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( device . removeFromDatabase ) . not . toHaveBeenCalled ( ) ;
expect ( settings . getDevice ( 'bulb' ) ) . toBeNull ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith ( 'zigbee2mqtt/bridge/devices' , expect . any ( String ) , expect . any ( Object ) , expect . any ( Function ) ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/remove' ,
2020-07-15 14:22:32 -07:00
JSON . stringify ( { "data" : { "id" : "bulb" , "block" : false , "force" : false } , "status" : "ok" } ) ,
2020-06-13 08:22:00 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
2020-07-15 14:22:32 -07:00
expect ( settings . get ( ) . blocklist ) . toStrictEqual ( [ ] ) ;
2020-06-13 08:22:00 -07:00
} ) ;
it ( 'Should allow to remove device by object ID' , async ( ) => {
const device = zigbeeHerdsman . devices . bulb ;
MQTT . publish . mockClear ( ) ;
2020-07-15 13:16:18 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/remove' , JSON . stringify ( { id : "bulb" } ) ) ;
2020-06-13 08:22:00 -07:00
await flushPromises ( ) ;
expect ( device . removeFromNetwork ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( device . removeFromDatabase ) . not . toHaveBeenCalled ( ) ;
expect ( settings . getDevice ( 'bulb' ) ) . toBeNull ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith ( 'zigbee2mqtt/bridge/devices' , expect . any ( String ) , expect . any ( Object ) , expect . any ( Function ) ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/remove' ,
2020-07-15 14:22:32 -07:00
JSON . stringify ( { "data" : { "id" : "bulb" , "block" : false , "force" : false } , "status" : "ok" } ) ,
2020-06-13 08:22:00 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should allow to force remove device' , async ( ) => {
const device = zigbeeHerdsman . devices . bulb ;
MQTT . publish . mockClear ( ) ;
2020-07-15 13:16:18 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/remove' , JSON . stringify ( { id : "bulb" , force : true } ) ) ;
2020-06-13 08:22:00 -07:00
await flushPromises ( ) ;
expect ( device . removeFromDatabase ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( device . removeFromNetwork ) . not . toHaveBeenCalled ( ) ;
expect ( settings . getDevice ( 'bulb' ) ) . toBeNull ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith ( 'zigbee2mqtt/bridge/devices' , expect . any ( String ) , expect . any ( Object ) , expect . any ( Function ) ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/remove' ,
2020-07-15 14:22:32 -07:00
JSON . stringify ( { "data" : { "id" : "bulb" , "block" : false , "force" : true } , "status" : "ok" } ) ,
2020-06-13 08:22:00 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
2020-07-15 14:22:32 -07:00
it ( 'Should allow to block device' , async ( ) => {
2020-06-13 08:22:00 -07:00
const device = zigbeeHerdsman . devices . bulb ;
MQTT . publish . mockClear ( ) ;
2020-07-15 14:22:32 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/remove' , JSON . stringify ( { id : "bulb" , block : true , force : true } ) ) ;
2020-06-13 08:22:00 -07:00
await flushPromises ( ) ;
expect ( device . removeFromDatabase ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( settings . getDevice ( 'bulb' ) ) . toBeNull ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith ( 'zigbee2mqtt/bridge/devices' , expect . any ( String ) , expect . any ( Object ) , expect . any ( Function ) ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/remove' ,
2020-07-15 14:22:32 -07:00
JSON . stringify ( { "data" : { "id" : "bulb" , "block" : true , "force" : true } , "status" : "ok" } ) ,
2020-06-13 08:22:00 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
2020-07-15 14:22:32 -07:00
expect ( settings . get ( ) . blocklist ) . toStrictEqual ( [ "0x000b57fffec6a5b2" ] ) ;
2020-06-13 08:22:00 -07:00
} ) ;
it ( 'Should allow to remove group' , async ( ) => {
const group = zigbeeHerdsman . groups . group _1 ;
MQTT . publish . mockClear ( ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/request/group/remove' , 'group_1' ) ;
await flushPromises ( ) ;
2020-07-07 12:16:35 -07:00
expect ( group . removeFromNetwork ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( settings . getGroup ( 'group_1' ) ) . toBeNull ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith ( 'zigbee2mqtt/bridge/groups' , expect . any ( String ) , expect . any ( Object ) , expect . any ( Function ) ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/group/remove' ,
2020-07-15 13:16:18 -07:00
JSON . stringify ( { "data" : { "id" : "group_1" , "force" : false } , "status" : "ok" } ) ,
2020-07-07 12:16:35 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should allow to force remove group' , async ( ) => {
const group = zigbeeHerdsman . groups . group _1 ;
MQTT . publish . mockClear ( ) ;
2020-07-15 13:16:18 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/group/remove' , JSON . stringify ( { id : "group_1" , force : true } ) ) ;
2020-07-07 12:16:35 -07:00
await flushPromises ( ) ;
2020-06-13 08:22:00 -07:00
expect ( group . removeFromDatabase ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( settings . getGroup ( 'group_1' ) ) . toBeNull ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith ( 'zigbee2mqtt/bridge/groups' , expect . any ( String ) , expect . any ( Object ) , expect . any ( Function ) ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/group/remove' ,
2020-07-15 13:16:18 -07:00
JSON . stringify ( { "data" : { "id" : "group_1" , "force" : true } , "status" : "ok" } ) ,
2020-06-13 08:22:00 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should throw error on removing non-existing device' , async ( ) => {
const device = zigbeeHerdsman . devices . bulb ;
MQTT . publish . mockClear ( ) ;
2020-07-15 13:16:18 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/remove' , JSON . stringify ( { id : "non-existing-device" } ) ) ;
2020-06-13 08:22:00 -07:00
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/remove' ,
JSON . stringify ( { "data" : { } , "status" : "error" , "error" : "Device 'non-existing-device' does not exist" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should throw error when remove device fails' , async ( ) => {
const device = zigbeeHerdsman . devices . bulb ;
MQTT . publish . mockClear ( ) ;
device . removeFromNetwork . mockImplementationOnce ( ( ) => { throw new Error ( 'device timeout' ) } )
2020-07-15 13:16:18 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/remove' , JSON . stringify ( { id : "bulb" } ) ) ;
2020-06-13 08:22:00 -07:00
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/remove' ,
2020-07-15 14:22:32 -07:00
JSON . stringify ( { "data" : { } , "status" : "error" , "error" : "Failed to remove device 'bulb' (block: false, force: false) (Error: device timeout)" } ) ,
2020-06-13 08:22:00 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
2020-06-13 10:35:09 -07:00
it ( 'Should allow rename device' , async ( ) => {
MQTT . publish . mockClear ( ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/rename' , JSON . stringify ( { from : 'bulb' , to : 'bulb_new_name' } ) ) ;
await flushPromises ( ) ;
expect ( settings . getDevice ( 'bulb' ) ) . toBeNull ( ) ;
2020-07-13 14:00:33 -07:00
expect ( settings . getDevice ( 'bulb_new_name' ) ) . toStrictEqual ( { "ID" : "0x000b57fffec6a5b2" , "friendly_name" : "bulb_new_name" , "friendlyName" : "bulb_new_name" , "retain" : true } ) ;
2020-06-13 10:35:09 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledWith ( 'zigbee2mqtt/bridge/devices' , expect . any ( String ) , expect . any ( Object ) , expect . any ( Function ) ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/rename' ,
JSON . stringify ( { "data" : { "from" : "bulb" , "to" : "bulb_new_name" } , "status" : "ok" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should allow rename group' , async ( ) => {
MQTT . publish . mockClear ( ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/request/group/rename' , JSON . stringify ( { from : 'group_1' , to : 'group_new_name' } ) ) ;
await flushPromises ( ) ;
expect ( settings . getGroup ( 'group_1' ) ) . toBeNull ( ) ;
2020-07-13 14:00:33 -07:00
expect ( settings . getGroup ( 'group_new_name' ) ) . toStrictEqual ( { "ID" : 1 , "devices" : [ ] , "friendly_name" : "group_new_name" , "friendlyName" : "group_new_name" , "optimistic" : true , "retain" : false } ) ;
2020-06-13 10:35:09 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledWith ( 'zigbee2mqtt/bridge/groups' , expect . any ( String ) , expect . any ( Object ) , expect . any ( Function ) ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/group/rename' ,
JSON . stringify ( { "data" : { "from" : "group_1" , "to" : "group_new_name" } , "status" : "ok" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should throw error on invalid device rename payload' , async ( ) => {
MQTT . publish . mockClear ( ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/rename' , JSON . stringify ( { from _bla : 'bulb' , to : 'bulb_new_name' } ) ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/rename' ,
JSON . stringify ( { "data" : { } , "status" : "error" , "error" : "Invalid payload" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should throw error on non-existing device rename' , async ( ) => {
MQTT . publish . mockClear ( ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/rename' , JSON . stringify ( { from : 'bulb_not_existing' , to : 'bulb_new_name' } ) ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/rename' ,
JSON . stringify ( { "data" : { } , "status" : "error" , "error" : "Device 'bulb_not_existing' does not exist" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should allow to rename last joined device' , async ( ) => {
MQTT . publish . mockClear ( ) ;
await zigbeeHerdsman . events . deviceJoined ( { device : zigbeeHerdsman . devices . bulb } ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/rename' , JSON . stringify ( { last : true , to : 'bulb_new_name' } ) ) ;
await flushPromises ( ) ;
expect ( settings . getDevice ( 'bulb' ) ) . toBeNull ( ) ;
2020-07-13 14:00:33 -07:00
expect ( settings . getDevice ( 'bulb_new_name' ) ) . toStrictEqual ( { "ID" : "0x000b57fffec6a5b2" , "friendly_name" : "bulb_new_name" , "friendlyName" : "bulb_new_name" , "retain" : true } ) ;
2020-06-13 10:35:09 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledWith ( 'zigbee2mqtt/bridge/devices' , expect . any ( String ) , expect . any ( Object ) , expect . any ( Function ) ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/rename' ,
JSON . stringify ( { "data" : { "from" : "bulb" , "to" : "bulb_new_name" } , "status" : "ok" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should throw error when renaming last joined device but none has joined' , async ( ) => {
MQTT . publish . mockClear ( ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/rename' , JSON . stringify ( { last : true , to : 'bulb_new_name' } ) ) ;
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/rename' ,
JSON . stringify ( { "data" : { } , "status" : "error" , "error" : "No device has joined since start" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
2020-06-13 14:28:06 -07:00
it ( 'Should allow change device options' , async ( ) => {
MQTT . publish . mockClear ( ) ;
2020-07-13 14:00:33 -07:00
expect ( settings . getDevice ( 'bulb' ) ) . toStrictEqual ( { "ID" : "0x000b57fffec6a5b2" , "friendly_name" : "bulb" , "friendlyName" : "bulb" , "retain" : true } ) ;
2020-07-15 13:16:18 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/options' , JSON . stringify ( { options : { retain : false , transition : 1 } , id : 'bulb' } ) ) ;
2020-06-13 14:28:06 -07:00
await flushPromises ( ) ;
2020-07-13 14:00:33 -07:00
expect ( settings . getDevice ( 'bulb' ) ) . toStrictEqual ( { "ID" : "0x000b57fffec6a5b2" , "friendly_name" : "bulb" , "friendlyName" : "bulb" , "retain" : false , "transition" : 1 } ) ;
2020-06-13 14:28:06 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledWith (
2020-06-13 15:28:24 -07:00
'zigbee2mqtt/bridge/response/device/options' ,
2020-07-15 13:16:18 -07:00
JSON . stringify ( { "data" : { "from" : { "retain" : true } , "to" : { "retain" : false , "transition" : 1 } , "id" : "bulb" } , "status" : "ok" } ) ,
2020-06-13 14:28:06 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should allow change group options' , async ( ) => {
MQTT . publish . mockClear ( ) ;
expect ( settings . getGroup ( 'group_1' ) ) . toStrictEqual ( { "ID" : 1 , "devices" : [ ] , "friendly_name" : "group_1" , "retain" : false , "friendlyName" : "group_1" , "optimistic" : true } ) ;
2020-07-15 13:16:18 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/group/options' , JSON . stringify ( { options : { retain : true , transition : 1 } , id : 'group_1' } ) ) ;
2020-06-13 14:28:06 -07:00
await flushPromises ( ) ;
expect ( settings . getGroup ( 'group_1' ) ) . toStrictEqual ( { "ID" : 1 , "devices" : [ ] , "friendly_name" : "group_1" , "retain" : true , "friendlyName" : "group_1" , "optimistic" : true , "transition" : 1 } ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
2020-06-13 15:28:24 -07:00
'zigbee2mqtt/bridge/response/group/options' ,
2020-07-15 13:16:18 -07:00
JSON . stringify ( { "data" : { "from" : { "optimistic" : true , "retain" : false } , "to" : { "optimistic" : true , "retain" : true , "transition" : 1 } , "id" : "group_1" } , "status" : "ok" } ) ,
2020-06-13 14:28:06 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should throw error on invalid device change options payload' , async ( ) => {
MQTT . publish . mockClear ( ) ;
2020-07-15 13:16:18 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/options' , JSON . stringify ( { options _ : { retain : true , transition : 1 } , id : 'bulb' } ) ) ;
2020-06-13 14:28:06 -07:00
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
2020-06-13 15:28:24 -07:00
'zigbee2mqtt/bridge/response/device/options' ,
2020-06-13 14:28:06 -07:00
JSON . stringify ( { "data" : { } , "status" : "error" , "error" : "Invalid payload" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
2020-06-13 14:42:58 -07:00
it ( 'Should allow to add group by string' , async ( ) => {
MQTT . publish . mockClear ( ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/request/group/add' , 'group_193' ) ;
await flushPromises ( ) ;
2020-07-13 14:00:33 -07:00
expect ( settings . getGroup ( 'group_193' ) ) . toStrictEqual ( { "ID" : 3 , "devices" : [ ] , "friendly_name" : "group_193" , "friendlyName" : "group_193" , "optimistic" : true } ) ;
2020-06-13 14:42:58 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledWith ( 'zigbee2mqtt/bridge/groups' , expect . any ( String ) , expect . any ( Object ) , expect . any ( Function ) ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/group/add' ,
2020-07-15 13:16:18 -07:00
JSON . stringify ( { "data" : { "friendly_name" : "group_193" , "id" : 3 } , "status" : "ok" } ) ,
2020-06-13 14:42:58 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should allow to add group with ID' , async ( ) => {
MQTT . publish . mockClear ( ) ;
2020-07-15 13:16:18 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/group/add' , JSON . stringify ( { friendly _name : "group_193" , id : 9 } ) ) ;
2020-06-13 14:42:58 -07:00
await flushPromises ( ) ;
2020-07-13 14:00:33 -07:00
expect ( settings . getGroup ( 'group_193' ) ) . toStrictEqual ( { "ID" : 9 , "devices" : [ ] , "friendly_name" : "group_193" , "friendlyName" : "group_193" , "optimistic" : true } ) ;
2020-06-13 14:42:58 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledWith ( 'zigbee2mqtt/bridge/groups' , expect . any ( String ) , expect . any ( Object ) , expect . any ( Function ) ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/group/add' ,
2020-07-15 13:16:18 -07:00
JSON . stringify ( { "data" : { "friendly_name" : "group_193" , "id" : 9 } , "status" : "ok" } ) ,
2020-06-13 14:42:58 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should throw error when add with invalid payload' , async ( ) => {
MQTT . publish . mockClear ( ) ;
2020-07-13 14:00:33 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/group/add' , JSON . stringify ( { friendly _name9 : "group_193" } ) ) ;
2020-06-13 14:42:58 -07:00
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/group/add' ,
JSON . stringify ( { "data" : { } , "status" : "error" , "error" : "Invalid payload" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
2020-06-15 09:58:32 -07:00
it ( 'Should allow to set last_seen' , async ( ) => {
MQTT . publish . mockClear ( ) ;
2020-07-13 14:00:33 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/config/last_seen' , 'ISO_8601' ) ;
2020-06-15 09:58:32 -07:00
await flushPromises ( ) ;
expect ( settings . get ( ) . advanced . last _seen ) . toBe ( 'ISO_8601' ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
2020-07-13 14:00:33 -07:00
'zigbee2mqtt/bridge/response/config/last_seen' ,
2020-06-15 09:58:32 -07:00
JSON . stringify ( { "data" : { "value" : "ISO_8601" } , "status" : "ok" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should fail to set last_seen when invalid type' , async ( ) => {
MQTT . publish . mockClear ( ) ;
2020-07-13 14:00:33 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/config/last_seen' , 'invalid_one' ) ;
2020-06-15 09:58:32 -07:00
await flushPromises ( ) ;
expect ( settings . get ( ) . advanced . last _seen ) . toBe ( 'disable' ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
2020-07-13 14:00:33 -07:00
'zigbee2mqtt/bridge/response/config/last_seen' ,
2020-06-15 09:58:32 -07:00
JSON . stringify ( { "data" : { } , "status" : "error" , "error" : "'invalid_one' is not an allowed value, allowed: disable,ISO_8601,epoch,ISO_8601_local" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should allow to set elapsed' , async ( ) => {
MQTT . publish . mockClear ( ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/request/config/elapsed' , 'true' ) ;
await flushPromises ( ) ;
expect ( settings . get ( ) . advanced . elapsed ) . toBe ( true ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/config/elapsed' ,
JSON . stringify ( { "data" : { "value" : true } , "status" : "ok" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should fail to set last_seen when invalid type' , async ( ) => {
MQTT . publish . mockClear ( ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/request/config/elapsed' , 'not_valid' ) ;
await flushPromises ( ) ;
expect ( settings . get ( ) . advanced . elapsed ) . toBe ( false ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/config/elapsed' ,
JSON . stringify ( { "data" : { } , "status" : "error" , "error" : "'not_valid' is not an allowed value, allowed: true,false" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should allow to set log level' , async ( ) => {
MQTT . publish . mockClear ( ) ;
2020-07-13 14:00:33 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/config/log_level' , 'debug' ) ;
2020-06-15 09:58:32 -07:00
await flushPromises ( ) ;
expect ( logger . getLevel ( ) ) . toBe ( 'debug' ) ;
2020-06-15 10:06:08 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledWith ( 'zigbee2mqtt/bridge/info' , expect . any ( String ) , expect . any ( Object ) , expect . any ( Function ) ) ;
2020-06-15 09:58:32 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledWith (
2020-07-13 14:00:33 -07:00
'zigbee2mqtt/bridge/response/config/log_level' ,
2020-06-15 09:58:32 -07:00
JSON . stringify ( { "data" : { "value" : 'debug' } , "status" : "ok" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should fail to set log level when invalid type' , async ( ) => {
MQTT . publish . mockClear ( ) ;
2020-07-13 14:00:33 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/config/log_level' , 'not_valid' ) ;
2020-06-15 09:58:32 -07:00
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
2020-07-13 14:00:33 -07:00
'zigbee2mqtt/bridge/response/config/log_level' ,
2020-06-15 09:58:32 -07:00
JSON . stringify ( { "data" : { } , "status" : "error" , "error" : "'not_valid' is not an allowed value, allowed: error,warn,info,debug" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
2020-06-15 10:19:57 -07:00
it ( 'Should allow to touchlink factory reset (succeeds)' , async ( ) => {
MQTT . publish . mockClear ( ) ;
zigbeeHerdsman . touchlinkFactoryReset . mockClear ( ) ;
zigbeeHerdsman . touchlinkFactoryReset . mockReturnValueOnce ( true ) ;
2020-07-13 14:00:33 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/touchlink/factory_reset' , '' ) ;
2020-06-15 10:19:57 -07:00
await flushPromises ( ) ;
expect ( zigbeeHerdsman . touchlinkFactoryReset ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
2020-07-13 14:00:33 -07:00
'zigbee2mqtt/bridge/response/touchlink/factory_reset' ,
2020-06-15 10:19:57 -07:00
JSON . stringify ( { "data" : { } , "status" : "ok" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should allow to touchlink factory reset (fails)' , async ( ) => {
MQTT . publish . mockClear ( ) ;
zigbeeHerdsman . touchlinkFactoryReset . mockClear ( ) ;
zigbeeHerdsman . touchlinkFactoryReset . mockReturnValueOnce ( false ) ;
2020-07-13 14:00:33 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/touchlink/factory_reset' , '' ) ;
2020-06-15 10:19:57 -07:00
await flushPromises ( ) ;
expect ( zigbeeHerdsman . touchlinkFactoryReset ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
2020-07-13 14:00:33 -07:00
'zigbee2mqtt/bridge/response/touchlink/factory_reset' ,
2020-06-15 10:19:57 -07:00
JSON . stringify ( { "data" : { } , "status" : "error" , "error" : "Failed to factory reset device through Touchlink" } ) ,
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
2020-05-24 09:16:39 -07:00
} ) ;