mirror of
https://github.com/Koenkk/zigbee2mqtt.git
synced 2026-08-06 02:39:38 +00:00
feat: Use Vitest for testing (#25284)
Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
This commit is contained in:
+153
-146
@@ -1,9 +1,18 @@
|
||||
import * as data from './mocks/data';
|
||||
import {mockLogger} from './mocks/logger';
|
||||
import {mockMQTT, mockMQTTConnectAsync, events as mockMQTTEvents} from './mocks/mqtt';
|
||||
import {flushPromises, JestMockAny} from './mocks/utils';
|
||||
import {
|
||||
mockMQTTConnectAsync,
|
||||
mockMQTTEndAsync,
|
||||
events as mockMQTTEvents,
|
||||
mockMQTTPublishAsync,
|
||||
mockMQTTSubscribeAsync,
|
||||
mockMQTTUnsubscribeAsync,
|
||||
} from './mocks/mqtt';
|
||||
import {flushPromises} from './mocks/utils';
|
||||
import {devices, mockController as mockZHController, events as mockZHEvents, returnDevices} from './mocks/zigbeeHerdsman';
|
||||
|
||||
import type {Mock, MockInstance} from 'vitest';
|
||||
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
@@ -18,27 +27,21 @@ import * as settings from '../lib/util/settings';
|
||||
process.env.NOTIFY_SOCKET = 'mocked';
|
||||
const LOG_MQTT_NS = 'z2m:mqtt';
|
||||
|
||||
jest.mock(
|
||||
'sd-notify',
|
||||
() => {
|
||||
return {
|
||||
watchdogInterval: jest.fn(() => 3000),
|
||||
startWatchdogMode: jest.fn(),
|
||||
stopWatchdogMode: jest.fn(),
|
||||
ready: jest.fn(),
|
||||
stopping: jest.fn(),
|
||||
};
|
||||
},
|
||||
{virtual: true},
|
||||
);
|
||||
vi.mock('sd-notify', () => ({
|
||||
watchdogInterval: vi.fn(() => 3000),
|
||||
startWatchdogMode: vi.fn(),
|
||||
stopWatchdogMode: vi.fn(),
|
||||
ready: vi.fn(),
|
||||
stopping: vi.fn(),
|
||||
}));
|
||||
|
||||
const mocksClear = [
|
||||
mockZHController.stop,
|
||||
mockMQTT.endAsync,
|
||||
mockMQTT.publishAsync,
|
||||
mockMQTT.subscribeAsync,
|
||||
mockMQTT.unsubscribeAsync,
|
||||
mockMQTT.endAsync,
|
||||
mockMQTTEndAsync,
|
||||
mockMQTTPublishAsync,
|
||||
mockMQTTSubscribeAsync,
|
||||
mockMQTTUnsubscribeAsync,
|
||||
mockMQTTEndAsync,
|
||||
mockMQTTConnectAsync,
|
||||
devices.bulb_color.removeFromNetwork,
|
||||
devices.bulb.removeFromNetwork,
|
||||
@@ -50,25 +53,25 @@ const mocksClear = [
|
||||
|
||||
describe('Controller', () => {
|
||||
let controller: Controller;
|
||||
let mockExit: JestMockAny;
|
||||
let mockExit: Mock;
|
||||
|
||||
beforeAll(async () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
returnDevices.splice(0);
|
||||
mockExit = jest.fn();
|
||||
mockExit = vi.fn();
|
||||
data.writeDefaultConfiguration();
|
||||
settings.reRead();
|
||||
controller = new Controller(jest.fn(), mockExit);
|
||||
controller = new Controller(vi.fn(), mockExit);
|
||||
mocksClear.forEach((m) => m.mockClear());
|
||||
settings.reRead();
|
||||
data.writeDefaultState();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
jest.useRealTimers();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
@@ -104,12 +107,12 @@ describe('Controller', () => {
|
||||
will: {payload: Buffer.from('{"state":"offline"}'), retain: true, topic: 'zigbee2mqtt/bridge/state', qos: 1},
|
||||
properties: {maximumPacketSize: 1048576},
|
||||
});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith(
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bulb',
|
||||
stringify({state: 'ON', brightness: 50, color_temp: 370, linkquality: 99}),
|
||||
{retain: true, qos: 0},
|
||||
);
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/remote', stringify({brightness: 255}), {retain: true, qos: 0});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/remote', stringify({brightness: 255}), {retain: true, qos: 0});
|
||||
});
|
||||
|
||||
it('Start controller with specific MQTT settings', async () => {
|
||||
@@ -160,9 +163,9 @@ describe('Controller', () => {
|
||||
settings.set(['advanced', 'ext_pan_id'], 'GENERATE');
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
expect((ZHController as unknown as jest.Mock).mock.calls[0][0].network.networkKey.length).toStrictEqual(16);
|
||||
expect((ZHController as unknown as jest.Mock).mock.calls[0][0].network.extendedPanID.length).toStrictEqual(8);
|
||||
expect((ZHController as unknown as jest.Mock).mock.calls[0][0].network.panID).toStrictEqual(expect.any(Number));
|
||||
expect((ZHController as unknown as MockInstance).mock.calls[0][0].network.networkKey.length).toStrictEqual(16);
|
||||
expect((ZHController as unknown as MockInstance).mock.calls[0][0].network.extendedPanID.length).toStrictEqual(8);
|
||||
expect((ZHController as unknown as MockInstance).mock.calls[0][0].network.panID).toStrictEqual(expect.any(Number));
|
||||
expect(data.read().advanced.network_key.length).toStrictEqual(16);
|
||||
expect(data.read().advanced.ext_pan_id.length).toStrictEqual(8);
|
||||
expect(data.read().advanced.pan_id).toStrictEqual(expect.any(Number));
|
||||
@@ -172,13 +175,13 @@ describe('Controller', () => {
|
||||
data.writeDefaultState();
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith(
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bulb',
|
||||
stringify({state: 'ON', brightness: 50, color_temp: 370, linkquality: 99}),
|
||||
{qos: 0, retain: true},
|
||||
);
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/remote', stringify({brightness: 255}), {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/group_1', stringify({state: 'ON'}), {qos: 0, retain: false});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/remote', stringify({brightness: 255}), {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/group_1', stringify({state: 'ON'}), {qos: 0, retain: false});
|
||||
});
|
||||
|
||||
it('Start controller should not publish cached states when disabled', async () => {
|
||||
@@ -186,7 +189,7 @@ describe('Controller', () => {
|
||||
data.writeDefaultState();
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
const publishedTopics = mockMQTT.publishAsync.mock.calls.map((m) => m[0]);
|
||||
const publishedTopics = mockMQTTPublishAsync.mock.calls.map((m) => m[0]);
|
||||
expect(publishedTopics).toEqual(expect.not.arrayContaining(['zigbee2mqtt/bulb', 'zigbee2mqtt/remote']));
|
||||
});
|
||||
|
||||
@@ -195,12 +198,12 @@ describe('Controller', () => {
|
||||
data.writeDefaultState();
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).not.toHaveBeenCalledWith(
|
||||
expect(mockMQTTPublishAsync).not.toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bulb',
|
||||
`{"state":"ON","brightness":50,"color_temp":370,"linkquality":99}`,
|
||||
{qos: 0, retain: true},
|
||||
);
|
||||
expect(mockMQTT.publishAsync).not.toHaveBeenCalledWith('zigbee2mqtt/remote', `{"brightness":255}`, {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).not.toHaveBeenCalledWith('zigbee2mqtt/remote', `{"brightness":255}`, {qos: 0, retain: true});
|
||||
});
|
||||
|
||||
it('Log when MQTT client is unavailable', async () => {
|
||||
@@ -209,7 +212,7 @@ describe('Controller', () => {
|
||||
mockLogger.error.mockClear();
|
||||
// @ts-expect-error private
|
||||
controller.mqtt.client.reconnecting = true;
|
||||
jest.advanceTimersByTime(11 * 1000);
|
||||
vi.advanceTimersByTime(11 * 1000);
|
||||
expect(mockLogger.error).toHaveBeenCalledWith('Not connected to MQTT server!');
|
||||
// @ts-expect-error private
|
||||
controller.mqtt.client.reconnecting = false;
|
||||
@@ -289,7 +292,7 @@ describe('Controller', () => {
|
||||
it('Start controller and stop with restart', async () => {
|
||||
await controller.start();
|
||||
await controller.stop(true);
|
||||
expect(mockMQTT.endAsync).toHaveBeenCalledTimes(1);
|
||||
expect(mockMQTTEndAsync).toHaveBeenCalledTimes(1);
|
||||
expect(mockZHController.stop).toHaveBeenCalledTimes(1);
|
||||
expect(mockExit).toHaveBeenCalledTimes(1);
|
||||
expect(mockExit).toHaveBeenCalledWith(0, true);
|
||||
@@ -299,7 +302,7 @@ describe('Controller', () => {
|
||||
mockZHController.stop.mockRejectedValueOnce('failed');
|
||||
await controller.start();
|
||||
await controller.stop();
|
||||
expect(mockMQTT.endAsync).toHaveBeenCalledTimes(1);
|
||||
expect(mockMQTTEndAsync).toHaveBeenCalledTimes(1);
|
||||
expect(mockZHController.stop).toHaveBeenCalledTimes(1);
|
||||
expect(mockExit).toHaveBeenCalledTimes(1);
|
||||
expect(mockExit).toHaveBeenCalledWith(1, false);
|
||||
@@ -310,7 +313,7 @@ describe('Controller', () => {
|
||||
await controller.start();
|
||||
await mockZHEvents.adapterDisconnected();
|
||||
await flushPromises();
|
||||
expect(mockMQTT.endAsync).toHaveBeenCalledTimes(1);
|
||||
expect(mockMQTTEndAsync).toHaveBeenCalledTimes(1);
|
||||
expect(mockZHController.stop).toHaveBeenCalledTimes(1);
|
||||
expect(mockExit).toHaveBeenCalledTimes(1);
|
||||
expect(mockExit).toHaveBeenCalledWith(1, false);
|
||||
@@ -324,13 +327,15 @@ describe('Controller', () => {
|
||||
mockLogger.info.mockClear();
|
||||
|
||||
mockMQTTEvents.error(new Error('ECONNRESET'));
|
||||
mockMQTT.reconnecting = true;
|
||||
// @ts-expect-error private
|
||||
controller.mqtt.client.reconnecting = true;
|
||||
expect(mockLogger.error).toHaveBeenCalledWith('MQTT error: ECONNRESET');
|
||||
|
||||
await jest.advanceTimersByTimeAsync(11000);
|
||||
await vi.advanceTimersByTimeAsync(11000);
|
||||
expect(mockLogger.error).toHaveBeenCalledWith('Not connected to MQTT server!');
|
||||
|
||||
mockMQTT.reconnecting = false;
|
||||
// @ts-expect-error private
|
||||
controller.mqtt.client.reconnecting = false;
|
||||
await mockMQTTEvents.connect();
|
||||
expect(mockLogger.info).toHaveBeenCalledWith('Connected to MQTT server');
|
||||
});
|
||||
@@ -346,13 +351,15 @@ describe('Controller', () => {
|
||||
reasonCode: 149,
|
||||
properties: {reasonString: 'Maximum packet size was exceeded'},
|
||||
});
|
||||
mockMQTT.disconnecting = true;
|
||||
// @ts-expect-error private
|
||||
controller.mqtt.client.disconnecting = true;
|
||||
expect(mockLogger.error).toHaveBeenCalledWith('MQTT disconnect: reason 149 (Maximum packet size was exceeded)');
|
||||
|
||||
await jest.advanceTimersByTimeAsync(11000);
|
||||
await vi.advanceTimersByTimeAsync(11000);
|
||||
expect(mockLogger.error).toHaveBeenCalledWith('Not connected to MQTT server!');
|
||||
|
||||
mockMQTT.disconnecting = false;
|
||||
// @ts-expect-error private
|
||||
controller.mqtt.client.disconnecting = false;
|
||||
await mockMQTTEvents.connect();
|
||||
expect(mockLogger.info).toHaveBeenCalledWith('Connected to MQTT server');
|
||||
});
|
||||
@@ -360,9 +367,9 @@ describe('Controller', () => {
|
||||
it('Handles MQTT publish error', async () => {
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
// fail on device_joined (has skipLog=false)
|
||||
mockMQTT.publishAsync.mockImplementationOnce(mockMQTT.publishAsync.getMockImplementation()!).mockImplementationOnce(() => {
|
||||
mockMQTTPublishAsync.mockImplementationOnce(mockMQTTPublishAsync.getMockImplementation()!).mockImplementationOnce(() => {
|
||||
throw new Error('client disconnecting');
|
||||
});
|
||||
await mockZHEvents.deviceJoined({device: devices.bulb});
|
||||
@@ -373,7 +380,7 @@ describe('Controller', () => {
|
||||
|
||||
it('Handle mqtt message', async () => {
|
||||
// @ts-expect-error private
|
||||
const spyEventbusEmitMQTTMessage = jest.spyOn(controller.eventBus, 'emitMQTTMessage').mockImplementation();
|
||||
const spyEventbusEmitMQTTMessage = vi.spyOn(controller.eventBus, 'emitMQTTMessage').mockImplementation(vi.fn());
|
||||
|
||||
await controller.start();
|
||||
mockLogger.debug.mockClear();
|
||||
@@ -384,7 +391,7 @@ describe('Controller', () => {
|
||||
|
||||
it('Skip MQTT messages on topic we published to', async () => {
|
||||
// @ts-expect-error private
|
||||
const spyEventbusEmitMQTTMessage = jest.spyOn(controller.eventBus, 'emitMQTTMessage').mockImplementation();
|
||||
const spyEventbusEmitMQTTMessage = vi.spyOn(controller.eventBus, 'emitMQTTMessage').mockImplementation(vi.fn());
|
||||
|
||||
await controller.start();
|
||||
mockLogger.debug.mockClear();
|
||||
@@ -450,7 +457,7 @@ describe('Controller', () => {
|
||||
const payload = {device};
|
||||
await mockZHEvents.deviceJoined(payload);
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith(
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bridge/event',
|
||||
stringify({type: 'device_joined', data: {friendly_name: 'bulb', ieee_address: device.ieeeAddr}}),
|
||||
{retain: false, qos: 0},
|
||||
@@ -461,7 +468,7 @@ describe('Controller', () => {
|
||||
await controller.start();
|
||||
const device = devices.bulb;
|
||||
settings.set(['blocklist'], [device.ieeeAddr]);
|
||||
const handler = (ZHController as unknown as jest.Mock).mock.calls[0][0].acceptJoiningDeviceHandler;
|
||||
const handler = (ZHController as unknown as MockInstance).mock.calls[0][0].acceptJoiningDeviceHandler;
|
||||
expect(await handler(device.ieeeAddr)).toBe(false);
|
||||
});
|
||||
|
||||
@@ -469,7 +476,7 @@ describe('Controller', () => {
|
||||
await controller.start();
|
||||
const device = devices.bulb;
|
||||
settings.set(['blocklist'], ['123']);
|
||||
const handler = (ZHController as unknown as jest.Mock).mock.calls[0][0].acceptJoiningDeviceHandler;
|
||||
const handler = (ZHController as unknown as MockInstance).mock.calls[0][0].acceptJoiningDeviceHandler;
|
||||
expect(await handler(device.ieeeAddr)).toBe(true);
|
||||
});
|
||||
|
||||
@@ -477,7 +484,7 @@ describe('Controller', () => {
|
||||
await controller.start();
|
||||
const device = devices.bulb;
|
||||
settings.set(['passlist'], [device.ieeeAddr]);
|
||||
const handler = (ZHController as unknown as jest.Mock).mock.calls[0][0].acceptJoiningDeviceHandler;
|
||||
const handler = (ZHController as unknown as MockInstance).mock.calls[0][0].acceptJoiningDeviceHandler;
|
||||
expect(await handler(device.ieeeAddr)).toBe(true);
|
||||
});
|
||||
|
||||
@@ -485,7 +492,7 @@ describe('Controller', () => {
|
||||
await controller.start();
|
||||
const device = devices.bulb;
|
||||
settings.set(['passlist'], ['123']);
|
||||
const handler = (ZHController as unknown as jest.Mock).mock.calls[0][0].acceptJoiningDeviceHandler;
|
||||
const handler = (ZHController as unknown as MockInstance).mock.calls[0][0].acceptJoiningDeviceHandler;
|
||||
expect(await handler(device.ieeeAddr)).toBe(false);
|
||||
});
|
||||
|
||||
@@ -494,14 +501,14 @@ describe('Controller', () => {
|
||||
const device = devices.bulb;
|
||||
settings.set(['passlist'], [device.ieeeAddr]);
|
||||
settings.set(['blocklist'], [device.ieeeAddr]);
|
||||
const handler = (ZHController as unknown as jest.Mock).mock.calls[0][0].acceptJoiningDeviceHandler;
|
||||
const handler = (ZHController as unknown as MockInstance).mock.calls[0][0].acceptJoiningDeviceHandler;
|
||||
expect(await handler(device.ieeeAddr)).toBe(true);
|
||||
});
|
||||
|
||||
it('acceptJoiningDeviceHandler accept when not on blocklist and passlist', async () => {
|
||||
await controller.start();
|
||||
const device = devices.bulb;
|
||||
const handler = (ZHController as unknown as jest.Mock).mock.calls[0][0].acceptJoiningDeviceHandler;
|
||||
const handler = (ZHController as unknown as MockInstance).mock.calls[0][0].acceptJoiningDeviceHandler;
|
||||
expect(await handler(device.ieeeAddr)).toBe(true);
|
||||
});
|
||||
|
||||
@@ -512,7 +519,7 @@ describe('Controller', () => {
|
||||
mockZHEvents.deviceJoined(payload);
|
||||
mockZHEvents.deviceJoined(payload);
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith(
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bridge/event',
|
||||
stringify({type: 'device_joined', data: {friendly_name: 'bulb', ieee_address: device.ieeeAddr}}),
|
||||
{retain: false, qos: 0},
|
||||
@@ -525,7 +532,7 @@ describe('Controller', () => {
|
||||
const payload = {device, status: 'started'};
|
||||
await mockZHEvents.deviceInterview(payload);
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith(
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bridge/event',
|
||||
stringify({type: 'device_interview', data: {friendly_name: 'bulb', status: 'started', ieee_address: device.ieeeAddr}}),
|
||||
{retain: false, qos: 0},
|
||||
@@ -538,7 +545,7 @@ describe('Controller', () => {
|
||||
const payload = {device, status: 'failed'};
|
||||
await mockZHEvents.deviceInterview(payload);
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith(
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bridge/event',
|
||||
stringify({type: 'device_interview', data: {friendly_name: 'bulb', status: 'failed', ieee_address: device.ieeeAddr}}),
|
||||
{retain: false, qos: 0},
|
||||
@@ -547,13 +554,13 @@ describe('Controller', () => {
|
||||
|
||||
it('On zigbee deviceInterview successful supported', async () => {
|
||||
await controller.start();
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
const device = devices.bulb;
|
||||
const payload = {device, status: 'successful'};
|
||||
await mockZHEvents.deviceInterview(payload);
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync.mock.calls[1][0]).toStrictEqual('zigbee2mqtt/bridge/event');
|
||||
const parsedMessage = JSON.parse(mockMQTT.publishAsync.mock.calls[1][1]);
|
||||
expect(mockMQTTPublishAsync.mock.calls[1][0]).toStrictEqual('zigbee2mqtt/bridge/event');
|
||||
const parsedMessage = JSON.parse(mockMQTTPublishAsync.mock.calls[1][1]);
|
||||
expect(parsedMessage.type).toStrictEqual('device_interview');
|
||||
expect(parsedMessage.data.friendly_name).toStrictEqual('bulb');
|
||||
expect(parsedMessage.data.status).toStrictEqual('successful');
|
||||
@@ -564,18 +571,18 @@ describe('Controller', () => {
|
||||
expect(parsedMessage.data.definition.description).toStrictEqual('TRADFRI bulb E26/E27, white spectrum, globe, opal, 980 lm');
|
||||
expect(parsedMessage.data.definition.exposes).toStrictEqual(expect.any(Array));
|
||||
expect(parsedMessage.data.definition.options).toStrictEqual(expect.any(Array));
|
||||
expect(mockMQTT.publishAsync.mock.calls[1][2]).toStrictEqual({retain: false, qos: 0});
|
||||
expect(mockMQTTPublishAsync.mock.calls[1][2]).toStrictEqual({retain: false, qos: 0});
|
||||
});
|
||||
|
||||
it('On zigbee deviceInterview successful not supported', async () => {
|
||||
await controller.start();
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
const device = devices.unsupported;
|
||||
const payload = {device, status: 'successful'};
|
||||
await mockZHEvents.deviceInterview(payload);
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync.mock.calls[1][0]).toStrictEqual('zigbee2mqtt/bridge/event');
|
||||
const parsedMessage = JSON.parse(mockMQTT.publishAsync.mock.calls[1][1]);
|
||||
expect(mockMQTTPublishAsync.mock.calls[1][0]).toStrictEqual('zigbee2mqtt/bridge/event');
|
||||
const parsedMessage = JSON.parse(mockMQTTPublishAsync.mock.calls[1][1]);
|
||||
expect(parsedMessage.type).toStrictEqual('device_interview');
|
||||
expect(parsedMessage.data.friendly_name).toStrictEqual(device.ieeeAddr);
|
||||
expect(parsedMessage.data.status).toStrictEqual('successful');
|
||||
@@ -586,7 +593,7 @@ describe('Controller', () => {
|
||||
expect(parsedMessage.data.definition.description).toStrictEqual('Automatically generated definition');
|
||||
expect(parsedMessage.data.definition.exposes).toStrictEqual(expect.any(Array));
|
||||
expect(parsedMessage.data.definition.options).toStrictEqual(expect.any(Array));
|
||||
expect(mockMQTT.publishAsync.mock.calls[1][2]).toStrictEqual({retain: false, qos: 0});
|
||||
expect(mockMQTTPublishAsync.mock.calls[1][2]).toStrictEqual({retain: false, qos: 0});
|
||||
});
|
||||
|
||||
it('On zigbee event device announce', async () => {
|
||||
@@ -596,7 +603,7 @@ describe('Controller', () => {
|
||||
await mockZHEvents.deviceAnnounce(payload);
|
||||
await flushPromises();
|
||||
expect(mockLogger.debug).toHaveBeenCalledWith(`Device 'bulb' announced itself`);
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith(
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bridge/event',
|
||||
stringify({type: 'device_announce', data: {friendly_name: 'bulb', ieee_address: device.ieeeAddr}}),
|
||||
{retain: false, qos: 0},
|
||||
@@ -607,12 +614,12 @@ describe('Controller', () => {
|
||||
await controller.start();
|
||||
returnDevices.push('0x00124b00120144ae');
|
||||
settings.set(['devices'], {});
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
const device = devices.bulb;
|
||||
const payload = {ieeeAddr: device.ieeeAddr};
|
||||
await mockZHEvents.deviceLeave(payload);
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith(
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bridge/event',
|
||||
stringify({type: 'device_leave', data: {ieee_address: device.ieeeAddr, friendly_name: device.ieeeAddr}}),
|
||||
{retain: false, qos: 0},
|
||||
@@ -623,11 +630,11 @@ describe('Controller', () => {
|
||||
await controller.start();
|
||||
returnDevices.push('0x00124b00120144ae');
|
||||
const device = devices.bulb;
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
const payload = {ieeeAddr: device.ieeeAddr};
|
||||
await mockZHEvents.deviceLeave(payload);
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith(
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bridge/event',
|
||||
stringify({type: 'device_leave', data: {ieee_address: device.ieeeAddr, friendly_name: 'bulb'}}),
|
||||
{retain: false, qos: 0},
|
||||
@@ -637,7 +644,7 @@ describe('Controller', () => {
|
||||
it('Publish entity state attribute output', async () => {
|
||||
await controller.start();
|
||||
settings.set(['advanced', 'output'], 'attribute');
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
// @ts-expect-error private
|
||||
const device = controller.zigbee.resolveEntity('bulb')!;
|
||||
await controller.publishEntityState(device, {
|
||||
@@ -650,30 +657,30 @@ describe('Controller', () => {
|
||||
brightness: 50,
|
||||
});
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/state', 'ON', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/brightness', '50', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/color_temp', '370', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/color', '100,50,10', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/dummy-1', 'yes', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/dummy-2', 'no', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/test1', '', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/test', '', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/state', 'ON', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/brightness', '50', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/color_temp', '370', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/color', '100,50,10', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/dummy-1', 'yes', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/dummy-2', 'no', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/test1', '', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/test', '', {qos: 0, retain: true});
|
||||
});
|
||||
|
||||
it('Publish entity state attribute_json output', async () => {
|
||||
await controller.start();
|
||||
settings.set(['advanced', 'output'], 'attribute_and_json');
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
// @ts-expect-error private
|
||||
const device = controller.zigbee.resolveEntity('bulb')!;
|
||||
await controller.publishEntityState(device, {state: 'ON', brightness: 200, color_temp: 370, linkquality: 99});
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledTimes(5);
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/state', 'ON', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/brightness', '200', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/color_temp', '370', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/linkquality', '99', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith(
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(5);
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/state', 'ON', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/brightness', '200', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/color_temp', '370', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/linkquality', '99', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bulb',
|
||||
stringify({state: 'ON', brightness: 200, color_temp: 370, linkquality: 99}),
|
||||
{qos: 0, retain: true},
|
||||
@@ -684,37 +691,37 @@ describe('Controller', () => {
|
||||
await controller.start();
|
||||
settings.set(['advanced', 'output'], 'attribute_and_json');
|
||||
settings.set(['devices', devices.bulb.ieeeAddr, 'filtered_attributes'], ['color_temp', 'linkquality']);
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
// @ts-expect-error private
|
||||
const device = controller.zigbee.resolveEntity('bulb')!;
|
||||
await controller.publishEntityState(device, {state: 'ON', brightness: 200, color_temp: 370, linkquality: 99});
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledTimes(3);
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/state', 'ON', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/brightness', '200', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb', stringify({state: 'ON', brightness: 200}), {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(3);
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/state', 'ON', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/brightness', '200', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb', stringify({state: 'ON', brightness: 200}), {qos: 0, retain: true});
|
||||
});
|
||||
|
||||
it('Publish entity state attribute_json output filtered (device_options)', async () => {
|
||||
await controller.start();
|
||||
settings.set(['advanced', 'output'], 'attribute_and_json');
|
||||
settings.set(['device_options', 'filtered_attributes'], ['color_temp', 'linkquality']);
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
// @ts-expect-error private
|
||||
const device = controller.zigbee.resolveEntity('bulb')!;
|
||||
await controller.publishEntityState(device, {state: 'ON', brightness: 200, color_temp: 370, linkquality: 99});
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledTimes(3);
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/state', 'ON', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/brightness', '200', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb', stringify({state: 'ON', brightness: 200}), {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(3);
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/state', 'ON', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/brightness', '200', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb', stringify({state: 'ON', brightness: 200}), {qos: 0, retain: true});
|
||||
});
|
||||
|
||||
it('Publish entity state attribute_json output filtered cache', async () => {
|
||||
await controller.start();
|
||||
settings.set(['advanced', 'output'], 'attribute_and_json');
|
||||
settings.set(['devices', devices.bulb.ieeeAddr, 'filtered_cache'], ['linkquality']);
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
|
||||
// @ts-expect-error private
|
||||
const device = controller.zigbee.resolveEntity('bulb')!;
|
||||
@@ -726,11 +733,11 @@ describe('Controller', () => {
|
||||
|
||||
// @ts-expect-error private
|
||||
expect(controller.state.state[device.ieeeAddr]).toStrictEqual({brightness: 200, color_temp: 370, state: 'ON'});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledTimes(5);
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/state', 'ON', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/brightness', '200', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/linkquality', '87', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith(
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(5);
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/state', 'ON', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/brightness', '200', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/linkquality', '87', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bulb',
|
||||
stringify({state: 'ON', brightness: 200, color_temp: 370, linkquality: 87}),
|
||||
{qos: 0, retain: true},
|
||||
@@ -741,7 +748,7 @@ describe('Controller', () => {
|
||||
await controller.start();
|
||||
settings.set(['advanced', 'output'], 'attribute_and_json');
|
||||
settings.set(['device_options', 'filtered_cache'], ['linkquality']);
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
|
||||
// @ts-expect-error private
|
||||
const device = controller.zigbee.resolveEntity('bulb')!;
|
||||
@@ -753,11 +760,11 @@ describe('Controller', () => {
|
||||
|
||||
// @ts-expect-error private
|
||||
expect(controller.state.state[device.ieeeAddr]).toStrictEqual({brightness: 200, color_temp: 370, state: 'ON'});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledTimes(5);
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/state', 'ON', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/brightness', '200', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/linkquality', '87', {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith(
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(5);
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/state', 'ON', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/brightness', '200', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb/linkquality', '87', {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bulb',
|
||||
stringify({state: 'ON', brightness: 200, color_temp: 370, linkquality: 87}),
|
||||
{qos: 0, retain: true},
|
||||
@@ -767,12 +774,12 @@ describe('Controller', () => {
|
||||
it('Publish entity state with device information', async () => {
|
||||
await controller.start();
|
||||
settings.set(['mqtt', 'include_device_information'], true);
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
// @ts-expect-error private
|
||||
let device = controller.zigbee.resolveEntity('bulb')!;
|
||||
await controller.publishEntityState(device, {state: 'ON'});
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith(
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bulb',
|
||||
stringify({
|
||||
state: 'ON',
|
||||
@@ -797,7 +804,7 @@ describe('Controller', () => {
|
||||
device = controller.zigbee.resolveEntity('unsupported2')!;
|
||||
await controller.publishEntityState(device, {state: 'ON'});
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith(
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/unsupported2',
|
||||
stringify({
|
||||
state: 'ON',
|
||||
@@ -818,12 +825,12 @@ describe('Controller', () => {
|
||||
it('Should publish entity state without retain', async () => {
|
||||
await controller.start();
|
||||
settings.set(['devices', devices.bulb.ieeeAddr, 'retain'], false);
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
// @ts-expect-error private
|
||||
const device = controller.zigbee.resolveEntity('bulb')!;
|
||||
await controller.publishEntityState(device, {state: 'ON'});
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith(
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bulb',
|
||||
stringify({state: 'ON', brightness: 50, color_temp: 370, linkquality: 99}),
|
||||
{qos: 0, retain: false},
|
||||
@@ -833,12 +840,12 @@ describe('Controller', () => {
|
||||
it('Should publish entity state with retain', async () => {
|
||||
await controller.start();
|
||||
settings.set(['devices', devices.bulb.ieeeAddr, 'retain'], true);
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
// @ts-expect-error private
|
||||
const device = controller.zigbee.resolveEntity('bulb')!;
|
||||
await controller.publishEntityState(device, {state: 'ON'});
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith(
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bulb',
|
||||
stringify({state: 'ON', brightness: 50, color_temp: 370, linkquality: 99}),
|
||||
{qos: 0, retain: true},
|
||||
@@ -850,12 +857,12 @@ describe('Controller', () => {
|
||||
settings.set(['mqtt', 'version'], 5);
|
||||
settings.set(['devices', devices.bulb.ieeeAddr, 'retain'], true);
|
||||
settings.set(['devices', devices.bulb.ieeeAddr, 'retention'], 37);
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
// @ts-expect-error private
|
||||
const device = controller.zigbee.resolveEntity('bulb')!;
|
||||
await controller.publishEntityState(device, {state: 'ON'});
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith(
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/bulb',
|
||||
stringify({state: 'ON', brightness: 50, color_temp: 370, linkquality: 99}),
|
||||
{qos: 0, retain: true, properties: {messageExpiryInterval: 37}},
|
||||
@@ -865,27 +872,27 @@ describe('Controller', () => {
|
||||
it('Publish entity state no empty messages', async () => {
|
||||
data.writeEmptyState();
|
||||
await controller.start();
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
// @ts-expect-error private
|
||||
const device = controller.zigbee.resolveEntity('bulb')!;
|
||||
await controller.publishEntityState(device, {});
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledTimes(0);
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it('Should allow to disable state persistency', async () => {
|
||||
settings.set(['advanced', 'cache_state_persistent'], false);
|
||||
data.removeState();
|
||||
await controller.start();
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
// @ts-expect-error private
|
||||
const device = controller.zigbee.resolveEntity('bulb')!;
|
||||
await controller.publishEntityState(device, {state: 'ON'});
|
||||
await controller.publishEntityState(device, {brightness: 200});
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledTimes(2);
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb', stringify({state: 'ON'}), {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb', stringify({state: 'ON', brightness: 200}), {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(2);
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb', stringify({state: 'ON'}), {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb', stringify({state: 'ON', brightness: 200}), {qos: 0, retain: true});
|
||||
await controller.stop();
|
||||
expect(data.stateExists()).toBeFalsy();
|
||||
});
|
||||
@@ -905,15 +912,15 @@ describe('Controller', () => {
|
||||
settings.set(['advanced', 'cache_state'], false);
|
||||
data.writeEmptyState();
|
||||
await controller.start();
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
// @ts-expect-error private
|
||||
const device = controller.zigbee.resolveEntity('bulb')!;
|
||||
await controller.publishEntityState(device, {state: 'ON'});
|
||||
await controller.publishEntityState(device, {brightness: 200});
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledTimes(2);
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb', stringify({state: 'ON'}), {qos: 0, retain: true});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb', stringify({brightness: 200}), {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(2);
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb', stringify({state: 'ON'}), {qos: 0, retain: true});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb', stringify({brightness: 200}), {qos: 0, retain: true});
|
||||
});
|
||||
|
||||
it('Should start when state is corrupted', async () => {
|
||||
@@ -945,44 +952,44 @@ describe('Controller', () => {
|
||||
controller.mqtt.retainedMessages,
|
||||
).length;
|
||||
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
await jest.advanceTimersByTimeAsync(2500); // before any startup configure triggers
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
await vi.advanceTimersByTimeAsync(2500); // before any startup configure triggers
|
||||
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledTimes(retainedMessages);
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bridge/info', expect.any(String), {retain: true, qos: 0});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(retainedMessages);
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bridge/info', expect.any(String), {retain: true, qos: 0});
|
||||
});
|
||||
|
||||
it('Should not republish retained messages on MQTT initial connect when retained message are sent', async () => {
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
await mockMQTTEvents.message('zigbee2mqtt/bridge/info', 'dummy');
|
||||
await jest.advanceTimersByTimeAsync(2500); // before any startup configure triggers
|
||||
await vi.advanceTimersByTimeAsync(2500); // before any startup configure triggers
|
||||
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledTimes(0);
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it('Should prevent any message being published with retain flag when force_disable_retain is set', async () => {
|
||||
settings.set(['mqtt', 'force_disable_retain'], true);
|
||||
// @ts-expect-error private
|
||||
await controller.mqtt.connect();
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
// @ts-expect-error private
|
||||
await controller.mqtt.publish('fo', 'bar', {retain: true});
|
||||
await flushPromises();
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledTimes(1);
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/fo', 'bar', {retain: false, qos: 0});
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/fo', 'bar', {retain: false, qos: 0});
|
||||
});
|
||||
|
||||
it('Should publish last seen changes', async () => {
|
||||
settings.set(['advanced', 'last_seen'], 'epoch');
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
const device = devices.remote;
|
||||
await mockZHEvents.lastSeenChanged({device, reason: 'deviceAnnounce'});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledTimes(1);
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/remote', stringify({brightness: 255, last_seen: 1000}), {
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(1);
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/remote', stringify({brightness: 255, last_seen: 1000}), {
|
||||
qos: 0,
|
||||
retain: true,
|
||||
});
|
||||
@@ -992,10 +999,10 @@ describe('Controller', () => {
|
||||
settings.set(['advanced', 'last_seen'], 'epoch');
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
mockMQTT.publishAsync.mockClear();
|
||||
mockMQTTPublishAsync.mockClear();
|
||||
const device = devices.remote;
|
||||
await mockZHEvents.lastSeenChanged({device, reason: 'messageEmitted'});
|
||||
expect(mockMQTT.publishAsync).toHaveBeenCalledTimes(0);
|
||||
expect(mockMQTTPublishAsync).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it('Ignore messages from coordinator', async () => {
|
||||
@@ -1034,7 +1041,7 @@ describe('Controller', () => {
|
||||
it('EventBus should handle errors', async () => {
|
||||
// @ts-expect-error private
|
||||
const eventbus = controller.eventBus;
|
||||
const callback = jest.fn().mockImplementation(async () => {
|
||||
const callback = vi.fn().mockImplementation(async () => {
|
||||
throw new Error('Whoops!');
|
||||
});
|
||||
eventbus.onStateChange({constructor: {name: 'Test'}}, callback);
|
||||
|
||||
Reference in New Issue
Block a user