2019-09-09 10:48:09 -07:00
const data = require ( './stub/data' ) ;
const logger = require ( './stub/logger' ) ;
const zigbeeHerdsman = require ( './stub/zigbeeHerdsman' ) ;
const MQTT = require ( './stub/mqtt' ) ;
2019-03-29 11:10:13 -07:00
const settings = require ( '../lib/util/settings' ) ;
2019-09-09 10:48:09 -07:00
const Controller = require ( '../lib/controller' ) ;
const flushPromises = ( ) => new Promise ( setImmediate ) ;
2020-09-24 09:06:43 -07:00
const stringify = require ( 'json-stable-stringify-without-jsonify' ) ;
2019-09-09 10:48:09 -07:00
2020-04-15 11:36:40 -07:00
describe ( 'Bind' , ( ) => {
2019-09-09 10:48:09 -07:00
let controller ;
mockClear = ( device ) => {
for ( const endpoint of device . endpoints ) {
endpoint . read . mockClear ( ) ;
endpoint . write . mockClear ( ) ;
endpoint . configureReporting . mockClear ( ) ;
2020-07-12 12:56:11 -07:00
endpoint . bind = jest . fn ( ) ;
2019-09-09 10:48:09 -07:00
endpoint . bind . mockClear ( ) ;
2020-01-27 12:56:11 -07:00
endpoint . unbind . mockClear ( ) ;
2019-03-15 13:19:42 -07:00
}
2019-09-09 10:48:09 -07:00
}
beforeEach ( async ( ) => {
data . writeDefaultConfiguration ( ) ;
settings . _reRead ( ) ;
data . writeEmptyState ( ) ;
2020-07-12 12:56:11 -07:00
settings . set ( [ 'experimental' , 'new_api' ] , true ) ;
2019-09-09 10:48:09 -07:00
controller = new Controller ( ) ;
await controller . start ( ) ;
await flushPromises ( ) ;
this . coordinatorEndoint = zigbeeHerdsman . devices . coordinator . getEndpoint ( 1 ) ;
MQTT . publish . mockClear ( ) ;
2019-03-15 13:19:42 -07:00
} ) ;
2019-09-09 10:48:09 -07:00
it ( 'Should bind' , async ( ) => {
2020-07-12 12:56:11 -07:00
const device = zigbeeHerdsman . devices . remote ;
const target = zigbeeHerdsman . devices . bulb _color . getEndpoint ( 1 ) ;
const endpoint = device . getEndpoint ( 1 ) ;
mockClear ( device ) ;
2020-08-13 11:00:35 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/bind' , stringify ( { from : 'remote' , to : 'bulb_color' } ) ) ;
2020-07-12 12:56:11 -07:00
await flushPromises ( ) ;
expect ( endpoint . bind ) . toHaveBeenCalledTimes ( 3 ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genOnOff" , target ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genLevelCtrl" , target ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genScenes" , target ) ;
2020-09-04 09:42:24 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 5 ) ;
2020-07-12 12:56:11 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/bind' ,
2020-08-13 11:00:35 -07:00
stringify ( { "data" : { "from" : "remote" , "to" : "bulb_color" , "clusters" : [ "genScenes" , "genOnOff" , "genLevelCtrl" ] , "failed" : [ ] } , "status" : "ok" } ) ,
2020-07-12 12:56:11 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
2020-09-04 09:42:24 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/devices' ,
expect . any ( String ) ,
{ retain : true , qos : 0 } ,
expect . any ( Function )
) ;
2020-07-12 12:56:11 -07:00
} ) ;
2020-07-28 12:05:02 -07:00
it ( 'Should bind only specifief clusters' , async ( ) => {
const device = zigbeeHerdsman . devices . remote ;
const target = zigbeeHerdsman . devices . bulb _color . getEndpoint ( 1 ) ;
const endpoint = device . getEndpoint ( 1 ) ;
mockClear ( device ) ;
2020-08-13 11:00:35 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/bind' , stringify ( { from : 'remote' , to : 'bulb_color' , clusters : [ "genOnOff" ] } ) ) ;
2020-07-28 12:05:02 -07:00
await flushPromises ( ) ;
expect ( endpoint . bind ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genOnOff" , target ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/bind' ,
2020-08-13 11:00:35 -07:00
stringify ( { "data" : { "from" : "remote" , "to" : "bulb_color" , "clusters" : [ "genOnOff" ] , "failed" : [ ] } , "status" : "ok" } ) ,
2020-07-28 12:05:02 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
2020-07-12 12:56:11 -07:00
it ( 'Should log error when there is nothing to bind' , async ( ) => {
const device = zigbeeHerdsman . devices . bulb _color ;
const endpoint = device . getEndpoint ( 1 ) ;
mockClear ( device ) ;
logger . error . mockClear ( ) ;
2020-08-13 11:00:35 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/bind' , stringify ( { from : 'remote' , to : 'button' } ) ) ;
2020-07-12 12:56:11 -07:00
await flushPromises ( ) ;
expect ( endpoint . bind ) . toHaveBeenCalledTimes ( 0 ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/bind' ,
2020-08-13 11:00:35 -07:00
stringify ( { "data" : { "from" : "remote" , "to" : "button" , "clusters" : [ ] , "failed" : [ ] } , "status" : "error" , "error" : "Nothing to bind" } ) ,
2020-07-12 12:56:11 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should unbind' , async ( ) => {
const device = zigbeeHerdsman . devices . remote ;
const target = zigbeeHerdsman . devices . bulb _color . getEndpoint ( 1 ) ;
const endpoint = device . getEndpoint ( 1 ) ;
mockClear ( device ) ;
2020-08-13 11:00:35 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/unbind' , stringify ( { from : 'remote' , to : 'bulb_color' } ) ) ;
2020-07-12 12:56:11 -07:00
await flushPromises ( ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledTimes ( 3 ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledWith ( "genOnOff" , target ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledWith ( "genLevelCtrl" , target ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledWith ( "genScenes" , target ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/unbind' ,
2020-08-13 11:00:35 -07:00
stringify ( { "data" : { "from" : "remote" , "to" : "bulb_color" , "clusters" : [ "genScenes" , "genOnOff" , "genLevelCtrl" ] , "failed" : [ ] } , "status" : "ok" } ) ,
2020-07-12 12:56:11 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should unbind coordinator' , async ( ) => {
const device = zigbeeHerdsman . devices . remote ;
const target = zigbeeHerdsman . devices . coordinator . getEndpoint ( 1 ) ;
const endpoint = device . getEndpoint ( 1 ) ;
mockClear ( device ) ;
endpoint . unbind . mockClear ( ) ;
2020-08-13 11:00:35 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/unbind' , stringify ( { from : 'remote' , to : 'Coordinator' } ) ) ;
2020-07-12 12:56:11 -07:00
await flushPromises ( ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledTimes ( 3 ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledWith ( "genOnOff" , target ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledWith ( "genLevelCtrl" , target ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledWith ( "genScenes" , target ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/unbind' ,
2020-08-13 11:00:35 -07:00
stringify ( { "data" : { "from" : "remote" , "to" : "Coordinator" , "clusters" : [ "genScenes" , "genOnOff" , "genLevelCtrl" ] , "failed" : [ ] } , "status" : "ok" } ) ,
2020-07-12 12:56:11 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should bind to groups' , async ( ) => {
const device = zigbeeHerdsman . devices . remote ;
const target = zigbeeHerdsman . groups . group _1 ;
const endpoint = device . getEndpoint ( 1 ) ;
mockClear ( device ) ;
2020-08-13 11:00:35 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/bind' , stringify ( { from : 'remote' , to : 'group_1' } ) ) ;
2020-07-12 12:56:11 -07:00
await flushPromises ( ) ;
expect ( endpoint . bind ) . toHaveBeenCalledTimes ( 3 ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genOnOff" , target ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genLevelCtrl" , target ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genScenes" , target ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/bind' ,
2020-08-13 11:00:35 -07:00
stringify ( { "data" : { "from" : "remote" , "to" : "group_1" , "clusters" : [ "genScenes" , "genOnOff" , "genLevelCtrl" ] , "failed" : [ ] } , "status" : "ok" } ) ,
2020-07-12 12:56:11 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should bind to group by number' , async ( ) => {
const device = zigbeeHerdsman . devices . remote ;
const target = zigbeeHerdsman . groups . group _1 ;
const endpoint = device . getEndpoint ( 1 ) ;
mockClear ( device ) ;
2020-08-13 11:00:35 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/bind' , stringify ( { from : 'remote' , to : '1' } ) ) ;
2020-07-12 12:56:11 -07:00
await flushPromises ( ) ;
expect ( endpoint . bind ) . toHaveBeenCalledTimes ( 3 ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genOnOff" , target ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genLevelCtrl" , target ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genScenes" , target ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/bind' ,
2020-08-13 11:00:35 -07:00
stringify ( { "data" : { "from" : "remote" , "to" : "1" , "clusters" : [ "genScenes" , "genOnOff" , "genLevelCtrl" ] , "failed" : [ ] } , "status" : "ok" } ) ,
2020-07-12 12:56:11 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should log when bind fails' , async ( ) => {
logger . error . mockClear ( ) ;
const device = zigbeeHerdsman . devices . remote ;
const endpoint = device . getEndpoint ( 1 ) ;
mockClear ( device ) ;
endpoint . bind . mockImplementation ( ( ) => { throw new Error ( 'failed' ) } ) ;
2020-08-13 11:00:35 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/bind' , stringify ( { from : 'remote' , to : 'bulb_color' } ) ) ;
2020-07-12 12:56:11 -07:00
await flushPromises ( ) ;
expect ( endpoint . bind ) . toHaveBeenCalledTimes ( 3 ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/bind' ,
2020-08-13 11:00:35 -07:00
stringify ( { "data" : { "from" : "remote" , "to" : "bulb_color" , "clusters" : [ ] , "failed" : [ "genScenes" , "genOnOff" , "genLevelCtrl" ] } , "status" : "error" , "error" : "Failed to bind" } ) ,
2020-07-12 12:56:11 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should bind from non default endpoints' , async ( ) => {
const device = zigbeeHerdsman . devices . remote ;
const target = zigbeeHerdsman . devices . QBKG03LM . getEndpoint ( 3 ) ;
const endpoint = device . getEndpoint ( 2 ) ;
mockClear ( device ) ;
2020-08-13 11:00:35 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/bind' , stringify ( { from : 'remote/ep2' , to : 'wall_switch_double/right' } ) ) ;
2020-07-12 12:56:11 -07:00
await flushPromises ( ) ;
expect ( endpoint . bind ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genOnOff" , target ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/bind' ,
2020-08-13 11:00:35 -07:00
stringify ( { "data" : { "from" : "remote/ep2" , "to" : "wall_switch_double/right" , "clusters" : [ "genOnOff" ] , "failed" : [ ] } , "status" : "ok" } ) ,
2020-07-12 12:56:11 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should bind to default endpoint returned by endpoints()' , async ( ) => {
const device = zigbeeHerdsman . devices . remote ;
const target = zigbeeHerdsman . devices . QBKG04LM . getEndpoint ( 2 ) ;
const endpoint = device . getEndpoint ( 2 ) ;
mockClear ( device ) ;
2020-08-13 11:00:35 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/bind' , stringify ( { from : 'remote/ep2' , to : 'wall_switch' } ) ) ;
2020-07-12 12:56:11 -07:00
await flushPromises ( ) ;
expect ( endpoint . bind ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genOnOff" , target ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/bind' ,
2020-08-13 11:00:35 -07:00
stringify ( { "data" : { "from" : "remote/ep2" , "to" : "wall_switch" , "clusters" : [ "genOnOff" ] , "failed" : [ ] } , "status" : "ok" } ) ,
2020-07-12 12:56:11 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Should unbind from default_bind_group' , async ( ) => {
const device = zigbeeHerdsman . devices . remote ;
const target = 'default_bind_group' ;
const endpoint = device . getEndpoint ( 1 ) ;
mockClear ( device ) ;
2020-08-13 11:00:35 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/unbind' , stringify ( { from : 'remote' , to : target } ) ) ;
2020-07-12 12:56:11 -07:00
await flushPromises ( ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledTimes ( 3 ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledWith ( "genOnOff" , 901 ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledWith ( "genLevelCtrl" , 901 ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledWith ( "genScenes" , 901 ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/unbind' ,
2020-08-13 11:00:35 -07:00
stringify ( { "data" : { "from" : "remote" , "to" : "default_bind_group" , "clusters" : [ "genScenes" , "genOnOff" , "genLevelCtrl" ] , "failed" : [ ] } , "status" : "ok" } ) ,
2020-07-12 12:56:11 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
2020-07-12 14:50:15 -07:00
it ( 'Error bind fails when source not existing' , async ( ) => {
const device = zigbeeHerdsman . devices . remote ;
const target = zigbeeHerdsman . devices . bulb _color . getEndpoint ( 1 ) ;
const endpoint = device . getEndpoint ( 1 ) ;
mockClear ( device ) ;
2020-08-13 11:00:35 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/bind' , stringify ( { from : 'remote_not_existing' , to : 'bulb_color' } ) ) ;
2020-07-12 14:50:15 -07:00
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/bind' ,
2020-08-13 11:00:35 -07:00
stringify ( { "data" : { "from" : "remote_not_existing" , "to" : "bulb_color" } , "status" : "error" , "error" : "Source device 'remote_not_existing' does not exist" } ) ,
2020-07-12 14:50:15 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
it ( 'Error bind fails when target not existing' , async ( ) => {
const device = zigbeeHerdsman . devices . remote ;
const target = zigbeeHerdsman . devices . bulb _color . getEndpoint ( 1 ) ;
const endpoint = device . getEndpoint ( 1 ) ;
mockClear ( device ) ;
2020-08-13 11:00:35 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/request/device/bind' , stringify ( { from : 'remote' , to : 'bulb_color_not_existing' } ) ) ;
2020-07-12 14:50:15 -07:00
await flushPromises ( ) ;
expect ( MQTT . publish ) . toHaveBeenCalledWith (
'zigbee2mqtt/bridge/response/device/bind' ,
2020-08-13 11:00:35 -07:00
stringify ( { "data" : { "from" : "remote" , "to" : "bulb_color_not_existing" } , "status" : "error" , "error" : "Target device or group 'bulb_color_not_existing' does not exist" } ) ,
2020-07-12 14:50:15 -07:00
{ retain : false , qos : 0 } , expect . any ( Function )
) ;
} ) ;
2020-07-12 12:56:11 -07:00
it ( 'Legacy api: Should bind' , async ( ) => {
2019-09-09 10:48:09 -07:00
const device = zigbeeHerdsman . devices . remote ;
const target = zigbeeHerdsman . devices . bulb _color . getEndpoint ( 1 ) ;
const endpoint = device . getEndpoint ( 1 ) ;
mockClear ( device ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/bind/remote' , 'bulb_color' ) ;
await flushPromises ( ) ;
expect ( endpoint . bind ) . toHaveBeenCalledTimes ( 3 ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genOnOff" , target ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genLevelCtrl" , target ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genScenes" , target ) ;
2020-09-04 09:42:24 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 4 ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/bridge/log' ) ;
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { type : 'device_bind' , message : { from : 'remote' , to : 'bulb_color' , cluster : 'genScenes' } } ) ;
expect ( MQTT . publish . mock . calls [ 1 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/bridge/log' ) ;
expect ( JSON . parse ( MQTT . publish . mock . calls [ 1 ] [ 1 ] ) ) . toStrictEqual ( { type : 'device_bind' , message : { from : 'remote' , to : 'bulb_color' , cluster : 'genOnOff' } } ) ;
expect ( MQTT . publish . mock . calls [ 2 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/bridge/log' ) ;
expect ( JSON . parse ( MQTT . publish . mock . calls [ 2 ] [ 1 ] ) ) . toStrictEqual ( { type : 'device_bind' , message : { from : 'remote' , to : 'bulb_color' , cluster : 'genLevelCtrl' } } ) ;
2019-03-15 13:19:42 -07:00
} ) ;
2020-07-12 12:56:11 -07:00
it ( 'Legacy api: Should log error when there is nothing to bind' , async ( ) => {
2020-03-20 11:00:00 -07:00
const device = zigbeeHerdsman . devices . bulb _color ;
const endpoint = device . getEndpoint ( 1 ) ;
mockClear ( device ) ;
logger . error . mockClear ( ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/bind/remote' , 'button' ) ;
await flushPromises ( ) ;
expect ( endpoint . bind ) . toHaveBeenCalledTimes ( 0 ) ;
expect ( logger . error ) . toHaveBeenCalledWith ( ` Nothing to bind from 'remote' to 'button' ` ) ;
} ) ;
2020-07-12 12:56:11 -07:00
it ( 'Legacy api: Should unbind' , async ( ) => {
2019-09-09 10:48:09 -07:00
const device = zigbeeHerdsman . devices . remote ;
const target = zigbeeHerdsman . devices . bulb _color . getEndpoint ( 1 ) ;
const endpoint = device . getEndpoint ( 1 ) ;
mockClear ( device ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/unbind/remote' , 'bulb_color' ) ;
await flushPromises ( ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledTimes ( 3 ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledWith ( "genOnOff" , target ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledWith ( "genLevelCtrl" , target ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledWith ( "genScenes" , target ) ;
2020-09-04 09:42:24 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 4 ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/bridge/log' ) ;
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { type : 'device_unbind' , message : { from : 'remote' , to : 'bulb_color' , cluster : 'genScenes' } } ) ;
expect ( MQTT . publish . mock . calls [ 1 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/bridge/log' ) ;
expect ( JSON . parse ( MQTT . publish . mock . calls [ 1 ] [ 1 ] ) ) . toStrictEqual ( { type : 'device_unbind' , message : { from : 'remote' , to : 'bulb_color' , cluster : 'genOnOff' } } ) ;
expect ( MQTT . publish . mock . calls [ 2 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/bridge/log' ) ;
expect ( JSON . parse ( MQTT . publish . mock . calls [ 2 ] [ 1 ] ) ) . toStrictEqual ( { type : 'device_unbind' , message : { from : 'remote' , to : 'bulb_color' , cluster : 'genLevelCtrl' } } ) ;
} ) ;
2019-03-29 11:10:13 -07:00
2020-07-12 12:56:11 -07:00
it ( 'Legacy api: Should unbind coordinator' , async ( ) => {
2019-09-09 10:48:09 -07:00
const device = zigbeeHerdsman . devices . remote ;
const target = zigbeeHerdsman . devices . coordinator . getEndpoint ( 1 ) ;
const endpoint = device . getEndpoint ( 1 ) ;
mockClear ( device ) ;
endpoint . unbind . mockClear ( ) ;
2019-10-09 10:40:46 -07:00
MQTT . events . message ( 'zigbee2mqtt/bridge/unbind/remote' , 'Coordinator' ) ;
2019-09-09 10:48:09 -07:00
await flushPromises ( ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledTimes ( 3 ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledWith ( "genOnOff" , target ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledWith ( "genLevelCtrl" , target ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledWith ( "genScenes" , target ) ;
2020-09-04 09:42:24 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 4 ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/bridge/log' ) ;
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { type : 'device_unbind' , message : { from : 'remote' , to : 'Coordinator' , cluster : 'genScenes' } } ) ;
expect ( MQTT . publish . mock . calls [ 1 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/bridge/log' ) ;
expect ( JSON . parse ( MQTT . publish . mock . calls [ 1 ] [ 1 ] ) ) . toStrictEqual ( { type : 'device_unbind' , message : { from : 'remote' , to : 'Coordinator' , cluster : 'genOnOff' } } ) ;
expect ( MQTT . publish . mock . calls [ 2 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/bridge/log' ) ;
expect ( JSON . parse ( MQTT . publish . mock . calls [ 2 ] [ 1 ] ) ) . toStrictEqual ( { type : 'device_unbind' , message : { from : 'remote' , to : 'Coordinator' , cluster : 'genLevelCtrl' } } ) ;
} ) ;
2019-03-29 11:10:13 -07:00
2020-07-12 12:56:11 -07:00
it ( 'Legacy api: Should bind to groups' , async ( ) => {
2019-09-09 10:48:09 -07:00
const device = zigbeeHerdsman . devices . remote ;
const target = zigbeeHerdsman . groups . group _1 ;
const endpoint = device . getEndpoint ( 1 ) ;
mockClear ( device ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/bind/remote' , 'group_1' ) ;
await flushPromises ( ) ;
expect ( endpoint . bind ) . toHaveBeenCalledTimes ( 3 ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genOnOff" , target ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genLevelCtrl" , target ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genScenes" , target ) ;
2020-09-04 09:42:24 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 4 ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/bridge/log' ) ;
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { type : 'device_bind' , message : { from : 'remote' , to : 'group_1' , cluster : 'genScenes' } } ) ;
expect ( MQTT . publish . mock . calls [ 1 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/bridge/log' ) ;
expect ( JSON . parse ( MQTT . publish . mock . calls [ 1 ] [ 1 ] ) ) . toStrictEqual ( { type : 'device_bind' , message : { from : 'remote' , to : 'group_1' , cluster : 'genOnOff' } } ) ;
expect ( MQTT . publish . mock . calls [ 2 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/bridge/log' ) ;
expect ( JSON . parse ( MQTT . publish . mock . calls [ 2 ] [ 1 ] ) ) . toStrictEqual ( { type : 'device_bind' , message : { from : 'remote' , to : 'group_1' , cluster : 'genLevelCtrl' } } ) ;
} ) ;
2019-03-15 13:19:42 -07:00
2020-07-12 12:56:11 -07:00
it ( 'Legacy api: Should bind to group by number' , async ( ) => {
2019-09-09 10:48:09 -07:00
const device = zigbeeHerdsman . devices . remote ;
const target = zigbeeHerdsman . groups . group _1 ;
const endpoint = device . getEndpoint ( 1 ) ;
mockClear ( device ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/bind/remote' , '1' ) ;
await flushPromises ( ) ;
expect ( endpoint . bind ) . toHaveBeenCalledTimes ( 3 ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genOnOff" , target ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genLevelCtrl" , target ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genScenes" , target ) ;
2020-09-04 09:42:24 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 4 ) ;
2019-09-09 10:48:09 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/bridge/log' ) ;
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { type : 'device_bind' , message : { from : 'remote' , to : 'group_1' , cluster : 'genScenes' } } ) ;
expect ( MQTT . publish . mock . calls [ 1 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/bridge/log' ) ;
expect ( JSON . parse ( MQTT . publish . mock . calls [ 1 ] [ 1 ] ) ) . toStrictEqual ( { type : 'device_bind' , message : { from : 'remote' , to : 'group_1' , cluster : 'genOnOff' } } ) ;
expect ( MQTT . publish . mock . calls [ 2 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/bridge/log' ) ;
expect ( JSON . parse ( MQTT . publish . mock . calls [ 2 ] [ 1 ] ) ) . toStrictEqual ( { type : 'device_bind' , message : { from : 'remote' , to : 'group_1' , cluster : 'genLevelCtrl' } } ) ;
} ) ;
2019-03-15 13:19:42 -07:00
2020-07-12 12:56:11 -07:00
it ( 'Legacy api: Should log when bind fails' , async ( ) => {
2019-09-09 10:48:09 -07:00
logger . error . mockClear ( ) ;
const device = zigbeeHerdsman . devices . remote ;
const endpoint = device . getEndpoint ( 1 ) ;
mockClear ( device ) ;
endpoint . bind . mockImplementationOnce ( ( ) => { throw new Error ( 'failed' ) } ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/bind/remote' , 'bulb_color' ) ;
await flushPromises ( ) ;
expect ( logger . error ) . toHaveBeenCalledWith ( "Failed to bind cluster 'genScenes' from 'remote' to 'bulb_color' (Error: failed)" ) ;
expect ( endpoint . bind ) . toHaveBeenCalledTimes ( 3 ) ;
} ) ;
2019-06-25 10:13:59 -07:00
2020-07-12 12:56:11 -07:00
it ( 'Legacy api: Should bind from non default endpoints' , async ( ) => {
2019-09-09 10:48:09 -07:00
const device = zigbeeHerdsman . devices . remote ;
const target = zigbeeHerdsman . devices . QBKG03LM . getEndpoint ( 3 ) ;
const endpoint = device . getEndpoint ( 2 ) ;
mockClear ( device ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/bind/remote/ep2' , 'wall_switch_double/right' ) ;
await flushPromises ( ) ;
expect ( endpoint . bind ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genOnOff" , target ) ;
2019-03-15 13:19:42 -07:00
} ) ;
2020-07-12 12:56:11 -07:00
it ( 'Legacy api: Should bind to default endpoint returned by endpoints()' , async ( ) => {
2019-09-09 10:48:09 -07:00
const device = zigbeeHerdsman . devices . remote ;
const target = zigbeeHerdsman . devices . QBKG04LM . getEndpoint ( 2 ) ;
const endpoint = device . getEndpoint ( 2 ) ;
mockClear ( device ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/bind/remote/ep2' , 'wall_switch' ) ;
await flushPromises ( ) ;
expect ( endpoint . bind ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( endpoint . bind ) . toHaveBeenCalledWith ( "genOnOff" , target ) ;
2019-03-15 13:19:42 -07:00
} ) ;
2020-01-27 12:56:11 -07:00
2020-07-12 12:56:11 -07:00
it ( 'Legacy api: Should unbind from default_bind_group' , async ( ) => {
2020-01-27 12:56:11 -07:00
const device = zigbeeHerdsman . devices . remote ;
const target = 'default_bind_group' ;
const endpoint = device . getEndpoint ( 1 ) ;
mockClear ( device ) ;
MQTT . events . message ( 'zigbee2mqtt/bridge/unbind/remote' , target ) ;
await flushPromises ( ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledTimes ( 3 ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledWith ( "genOnOff" , 901 ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledWith ( "genLevelCtrl" , 901 ) ;
expect ( endpoint . unbind ) . toHaveBeenCalledWith ( "genScenes" , 901 ) ;
2020-09-04 09:42:24 -07:00
expect ( MQTT . publish ) . toHaveBeenCalledTimes ( 4 ) ;
2020-01-27 12:56:11 -07:00
expect ( MQTT . publish . mock . calls [ 0 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/bridge/log' ) ;
expect ( JSON . parse ( MQTT . publish . mock . calls [ 0 ] [ 1 ] ) ) . toStrictEqual ( { type : 'device_unbind' , message : { from : 'remote' , to : 'default_bind_group' , cluster : 'genScenes' } } ) ;
expect ( MQTT . publish . mock . calls [ 1 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/bridge/log' ) ;
expect ( JSON . parse ( MQTT . publish . mock . calls [ 1 ] [ 1 ] ) ) . toStrictEqual ( { type : 'device_unbind' , message : { from : 'remote' , to : 'default_bind_group' , cluster : 'genOnOff' } } ) ;
expect ( MQTT . publish . mock . calls [ 2 ] [ 0 ] ) . toStrictEqual ( 'zigbee2mqtt/bridge/log' ) ;
expect ( JSON . parse ( MQTT . publish . mock . calls [ 2 ] [ 1 ] ) ) . toStrictEqual ( { type : 'device_unbind' , message : { from : 'remote' , to : 'default_bind_group' , cluster : 'genLevelCtrl' } } ) ;
} ) ;
2019-03-15 13:19:42 -07:00
} ) ;