feat: Use Vitest for testing (#25284)

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
This commit is contained in:
NerivecandKoen Kanters authored and GitHub committed 2024-12-22 20:19:45 +01:00
1 parent 5d059b7bcb
commit 06f44533af
51 files changed
+2606 -4771

No files matched your search

+37 -37
View File
@@ -1,6 +1,6 @@
import * as data from '../mocks/data';
import {mockLogger} from '../mocks/logger';
import {mockMQTT, events as mockMQTTEvents} from '../mocks/mqtt';
import {events as mockMQTTEvents, mockMQTTPublishAsync} from '../mocks/mqtt';
import {flushPromises} from '../mocks/utils';
import {devices, events as mockZHEvents, returnDevices} from '../mocks/zigbeeHerdsman';
@@ -13,7 +13,7 @@ import Availability from '../../lib/extension/availability';
import * as settings from '../../lib/util/settings';
import utils from '../../lib/util/utils';
const mocksClear = [mockMQTT.publishAsync, mockLogger.warning, mockLogger.info];
const mocksClear = [mockMQTTPublishAsync, mockLogger.warning, mockLogger.info];
returnDevices.push(
devices.bulb_color.ieeeAddr,
@@ -37,22 +37,22 @@ describe('Extension: Availability', () => {
};
const setTimeAndAdvanceTimers = async (value: number): Promise<void> => {
jest.setSystemTime(Date.now() + value);
await jest.advanceTimersByTimeAsync(value);
vi.setSystemTime(Date.now() + value);
await vi.advanceTimersByTimeAsync(value);
};
beforeAll(async () => {
jest.spyOn(utils, 'sleep').mockImplementation();
jest.useFakeTimers();
vi.spyOn(utils, 'sleep').mockImplementation(vi.fn());
vi.useFakeTimers();
settings.reRead();
settings.set(['availability'], {enabled: true});
controller = new Controller(jest.fn(), jest.fn());
controller = new Controller(vi.fn(), vi.fn());
await controller.start();
await flushPromises();
});
beforeEach(async () => {
jest.setSystemTime(utils.minutes(1));
vi.setSystemTime(utils.minutes(1));
data.writeDefaultConfiguration();
settings.reRead();
settings.set(['availability'], {enabled: true});
@@ -67,16 +67,16 @@ describe('Extension: Availability', () => {
afterAll(async () => {
await controller.stop();
jest.useRealTimers();
vi.useRealTimers();
});
it('Should publish availability on startup for device where it is enabled for', async () => {
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', stringify({state: 'online'}), {
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', stringify({state: 'online'}), {
retain: true,
qos: 1,
});
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/remote/availability', stringify({state: 'online'}), {retain: true, qos: 1});
expect(mockMQTT.publishAsync).not.toHaveBeenCalledWith('zigbee2mqtt/bulb_color_2/availability', stringify({state: 'online'}), {
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/remote/availability', stringify({state: 'online'}), {retain: true, qos: 1});
expect(mockMQTTPublishAsync).not.toHaveBeenCalledWith('zigbee2mqtt/bulb_color_2/availability', stringify({state: 'online'}), {
retain: true,
qos: 1,
});
@@ -106,14 +106,14 @@ describe('Extension: Availability', () => {
});
it('Should publish offline for active device when not seen for 10 minutes', async () => {
mockMQTT.publishAsync.mockClear();
mockMQTTPublishAsync.mockClear();
await setTimeAndAdvanceTimers(utils.minutes(5));
expect(devices.bulb_color.ping).toHaveBeenCalledTimes(0);
await setTimeAndAdvanceTimers(utils.minutes(7));
expect(devices.bulb_color.ping).toHaveBeenCalledTimes(1);
expect(devices.bulb_color.ping).toHaveBeenNthCalledWith(1, true);
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', stringify({state: 'offline'}), {
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', stringify({state: 'offline'}), {
retain: true,
qos: 1,
});
@@ -127,20 +127,20 @@ describe('Extension: Availability', () => {
});
it('Should publish offline for passive device when not seen for 25 hours', async () => {
mockMQTT.publishAsync.mockClear();
mockMQTTPublishAsync.mockClear();
await setTimeAndAdvanceTimers(utils.hours(26));
expect(devices.remote.ping).toHaveBeenCalledTimes(0);
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/remote/availability', stringify({state: 'offline'}), {retain: true, qos: 1});
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/remote/availability', stringify({state: 'offline'}), {retain: true, qos: 1});
});
it('Should reset ping timer when device last seen changes for active device', async () => {
mockMQTT.publishAsync.mockClear();
mockMQTTPublishAsync.mockClear();
await setTimeAndAdvanceTimers(utils.minutes(5));
expect(devices.bulb_color.ping).toHaveBeenCalledTimes(0);
await mockZHEvents.lastSeenChanged({device: devices.bulb_color});
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', stringify({state: 'offline'}), {
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', stringify({state: 'offline'}), {
retain: true,
qos: 1,
});
@@ -154,7 +154,7 @@ describe('Extension: Availability', () => {
});
it('Should ping again when first ping fails', async () => {
mockMQTT.publishAsync.mockClear();
mockMQTTPublishAsync.mockClear();
await mockZHEvents.lastSeenChanged({device: devices.bulb_color});
@@ -169,13 +169,13 @@ describe('Extension: Availability', () => {
});
it('Should reset ping timer when device last seen changes for passive device', async () => {
mockMQTT.publishAsync.mockClear();
mockMQTTPublishAsync.mockClear();
await setTimeAndAdvanceTimers(utils.hours(24));
expect(devices.remote.ping).toHaveBeenCalledTimes(0);
await mockZHEvents.lastSeenChanged({device: devices.remote});
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/remote/availability', stringify({state: 'offline'}), {retain: true, qos: 1});
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/remote/availability', stringify({state: 'offline'}), {retain: true, qos: 1});
await setTimeAndAdvanceTimers(utils.hours(25));
expect(devices.remote.ping).toHaveBeenCalledTimes(0);
@@ -185,10 +185,10 @@ describe('Extension: Availability', () => {
});
it('Should immediately mark device as online when it lastSeen changes', async () => {
mockMQTT.publishAsync.mockClear();
mockMQTTPublishAsync.mockClear();
await setTimeAndAdvanceTimers(utils.minutes(15));
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', stringify({state: 'offline'}), {
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', stringify({state: 'offline'}), {
retain: true,
qos: 1,
});
@@ -196,7 +196,7 @@ describe('Extension: Availability', () => {
devices.bulb_color.lastSeen = Date.now();
await mockZHEvents.lastSeenChanged({device: devices.bulb_color});
await flushPromises();
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', stringify({state: 'online'}), {
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', stringify({state: 'online'}), {
retain: true,
qos: 1,
});
@@ -310,18 +310,18 @@ describe('Extension: Availability', () => {
});
it('Should republish availability when device is renamed', async () => {
mockMQTT.publishAsync.mockClear();
mockMQTTPublishAsync.mockClear();
mockMQTTEvents.message('zigbee2mqtt/bridge/request/device/rename', stringify({from: 'bulb_color', to: 'bulb_new_name'}));
await flushPromises();
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', '', {retain: true, qos: 1});
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb_new_name/availability', stringify({state: 'online'}), {
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb_color/availability', '', {retain: true, qos: 1});
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb_new_name/availability', stringify({state: 'online'}), {
retain: true,
qos: 1,
});
await setTimeAndAdvanceTimers(utils.hours(12));
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb_new_name/availability', stringify({state: 'offline'}), {
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/bulb_new_name/availability', stringify({state: 'offline'}), {
retain: true,
qos: 1,
});
@@ -330,10 +330,10 @@ describe('Extension: Availability', () => {
it('Should publish availability payload in JSON format', async () => {
await resetExtension();
devices.remote.ping.mockClear();
mockMQTT.publishAsync.mockClear();
mockMQTTPublishAsync.mockClear();
await setTimeAndAdvanceTimers(utils.hours(26));
expect(devices.remote.ping).toHaveBeenCalledTimes(0);
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/remote/availability', stringify({state: 'offline'}), {retain: true, qos: 1});
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/remote/availability', stringify({state: 'offline'}), {retain: true, qos: 1});
});
it('Should publish availability for groups', async () => {
@@ -341,21 +341,21 @@ describe('Extension: Availability', () => {
await resetExtension();
devices.bulb_color_2.ping.mockClear();
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/group_tradfri_remote/availability', stringify({state: 'online'}), {
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/group_tradfri_remote/availability', stringify({state: 'online'}), {
retain: true,
qos: 1,
});
mockMQTT.publishAsync.mockClear();
mockMQTTPublishAsync.mockClear();
await setTimeAndAdvanceTimers(utils.minutes(12));
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/group_tradfri_remote/availability', stringify({state: 'offline'}), {
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/group_tradfri_remote/availability', stringify({state: 'offline'}), {
retain: true,
qos: 1,
});
mockMQTT.publishAsync.mockClear();
mockMQTTPublishAsync.mockClear();
devices.bulb_color_2.lastSeen = Date.now();
await mockZHEvents.lastSeenChanged({device: devices.bulb_color_2});
await flushPromises();
expect(mockMQTT.publishAsync).toHaveBeenCalledWith('zigbee2mqtt/group_tradfri_remote/availability', stringify({state: 'online'}), {
expect(mockMQTTPublishAsync).toHaveBeenCalledWith('zigbee2mqtt/group_tradfri_remote/availability', stringify({state: 'online'}), {
retain: true,
qos: 1,
});
@@ -365,7 +365,7 @@ describe('Extension: Availability', () => {
// @ts-expect-error private
const availability = controller.extensions.find((extension) => extension instanceof Availability)!;
// @ts-expect-error private
const publishAvailabilitySpy = jest.spyOn(availability, 'publishAvailability');
const publishAvailabilitySpy = vi.spyOn(availability, 'publishAvailability');
devices.bulb_color.ping.mockImplementationOnce(() => new Promise((resolve) => setTimeout(resolve, 1000)));
// @ts-expect-error private
@@ -380,7 +380,7 @@ describe('Extension: Availability', () => {
expect(availability.pingQueue).toEqual([]);
// Validate the stop-interrupt implicitly by checking that it prevents further function invocations
expect(publishAvailabilitySpy).not.toHaveBeenCalled();
devices.bulb_color.ping = jest.fn(); // ensure reset
devices.bulb_color.ping = vi.fn(); // ensure reset
});
it('Should prevent instance restart', async () => {