matterbridge 3.5.0 → 3.5.1-dev-20260121-22e98b4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/bin/mb_coap.js +1 -1
- package/bin/mb_mdns.js +1 -1
- package/dist/broadcastServer.d.ts +0 -115
- package/dist/broadcastServer.js +1 -119
- package/dist/broadcastServerTypes.d.ts +0 -43
- package/dist/broadcastServerTypes.js +0 -24
- package/dist/cli.d.ts +1 -26
- package/dist/cli.js +2 -102
- package/dist/cliEmitter.d.ts +0 -36
- package/dist/cliEmitter.js +0 -37
- package/dist/cliHistory.d.ts +0 -42
- package/dist/cliHistory.js +1 -39
- package/dist/clusters/export.d.ts +0 -1
- package/dist/clusters/export.js +0 -2
- package/dist/deviceManager.d.ts +0 -108
- package/dist/deviceManager.js +2 -114
- package/dist/devices/airConditioner.d.ts +0 -75
- package/dist/devices/airConditioner.js +0 -57
- package/dist/devices/batteryStorage.d.ts +0 -43
- package/dist/devices/batteryStorage.js +1 -48
- package/dist/devices/cooktop.d.ts +0 -55
- package/dist/devices/cooktop.js +0 -56
- package/dist/devices/dishwasher.d.ts +0 -55
- package/dist/devices/dishwasher.js +0 -57
- package/dist/devices/evse.d.ts +0 -57
- package/dist/devices/evse.js +10 -74
- package/dist/devices/export.d.ts +0 -1
- package/dist/devices/export.js +0 -5
- package/dist/devices/extractorHood.d.ts +0 -41
- package/dist/devices/extractorHood.js +0 -43
- package/dist/devices/heatPump.d.ts +0 -43
- package/dist/devices/heatPump.js +2 -50
- package/dist/devices/laundryDryer.d.ts +0 -58
- package/dist/devices/laundryDryer.js +3 -62
- package/dist/devices/laundryWasher.d.ts +0 -64
- package/dist/devices/laundryWasher.js +4 -70
- package/dist/devices/microwaveOven.d.ts +1 -77
- package/dist/devices/microwaveOven.js +5 -88
- package/dist/devices/oven.d.ts +0 -82
- package/dist/devices/oven.js +0 -85
- package/dist/devices/refrigerator.d.ts +0 -100
- package/dist/devices/refrigerator.js +0 -102
- package/dist/devices/roboticVacuumCleaner.d.ts +0 -83
- package/dist/devices/roboticVacuumCleaner.js +9 -100
- package/dist/devices/solarPower.d.ts +0 -36
- package/dist/devices/solarPower.js +0 -38
- package/dist/devices/speaker.d.ts +0 -79
- package/dist/devices/speaker.js +0 -84
- package/dist/devices/temperatureControl.d.ts +0 -21
- package/dist/devices/temperatureControl.js +3 -24
- package/dist/devices/waterHeater.d.ts +0 -74
- package/dist/devices/waterHeater.js +2 -82
- package/dist/frontend.d.ts +0 -187
- package/dist/frontend.js +39 -505
- package/dist/frontendTypes.d.ts +0 -57
- package/dist/frontendTypes.js +0 -45
- package/dist/helpers.d.ts +0 -43
- package/dist/helpers.js +1 -54
- package/dist/index.d.ts +0 -23
- package/dist/index.js +0 -25
- package/dist/jestutils/export.d.ts +0 -1
- package/dist/jestutils/export.js +0 -1
- package/dist/jestutils/jestHelpers.d.ts +0 -255
- package/dist/jestutils/jestHelpers.js +14 -372
- package/dist/logger/export.d.ts +0 -1
- package/dist/logger/export.js +0 -1
- package/dist/matter/behaviors.d.ts +0 -1
- package/dist/matter/behaviors.js +0 -2
- package/dist/matter/clusters.d.ts +0 -1
- package/dist/matter/clusters.js +0 -2
- package/dist/matter/devices.d.ts +0 -1
- package/dist/matter/devices.js +0 -2
- package/dist/matter/endpoints.d.ts +0 -1
- package/dist/matter/endpoints.js +0 -2
- package/dist/matter/export.d.ts +0 -1
- package/dist/matter/export.js +0 -2
- package/dist/matter/types.d.ts +0 -1
- package/dist/matter/types.js +0 -2
- package/dist/matterNode.d.ts +0 -258
- package/dist/matterNode.js +9 -364
- package/dist/matterbridge.d.ts +0 -362
- package/dist/matterbridge.js +60 -860
- package/dist/matterbridgeAccessoryPlatform.d.ts +0 -36
- package/dist/matterbridgeAccessoryPlatform.js +0 -38
- package/dist/matterbridgeBehaviors.d.ts +0 -24
- package/dist/matterbridgeBehaviors.js +5 -68
- package/dist/matterbridgeDeviceTypes.d.ts +0 -649
- package/dist/matterbridgeDeviceTypes.js +6 -673
- package/dist/matterbridgeDynamicPlatform.d.ts +0 -36
- package/dist/matterbridgeDynamicPlatform.js +0 -38
- package/dist/matterbridgeEndpoint.d.ts +2 -1332
- package/dist/matterbridgeEndpoint.js +94 -1459
- package/dist/matterbridgeEndpointHelpers.d.ts +0 -425
- package/dist/matterbridgeEndpointHelpers.js +21 -486
- package/dist/matterbridgeEndpointTypes.d.ts +0 -70
- package/dist/matterbridgeEndpointTypes.js +0 -25
- package/dist/matterbridgePlatform.d.ts +0 -425
- package/dist/matterbridgePlatform.js +2 -453
- package/dist/matterbridgeTypes.d.ts +0 -46
- package/dist/matterbridgeTypes.js +0 -26
- package/dist/mb_coap.d.ts +1 -0
- package/dist/{dgram/mb_coap.js → mb_coap.js} +3 -41
- package/dist/mb_mdns.d.ts +1 -0
- package/dist/{dgram/mb_mdns.js → mb_mdns.js} +37 -81
- package/dist/pluginManager.d.ts +0 -305
- package/dist/pluginManager.js +8 -345
- package/dist/shelly.d.ts +0 -157
- package/dist/shelly.js +7 -178
- package/dist/spawn.d.ts +1 -0
- package/dist/{utils/spawn.js → spawn.js} +3 -73
- package/dist/storage/export.d.ts +0 -1
- package/dist/storage/export.js +0 -1
- package/dist/update.d.ts +0 -75
- package/dist/update.js +7 -100
- package/dist/utils/export.d.ts +1 -13
- package/dist/utils/export.js +1 -13
- package/dist/workerGlobalPrefix.d.ts +0 -24
- package/dist/workerGlobalPrefix.js +6 -40
- package/dist/workerTypes.d.ts +0 -25
- package/dist/workerTypes.js +0 -24
- package/dist/workers.d.ts +0 -61
- package/dist/workers.js +4 -68
- package/npm-shrinkwrap.json +35 -5
- package/package.json +5 -5
- package/dist/broadcastServer.d.ts.map +0 -1
- package/dist/broadcastServer.js.map +0 -1
- package/dist/broadcastServerTypes.d.ts.map +0 -1
- package/dist/broadcastServerTypes.js.map +0 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/cliEmitter.d.ts.map +0 -1
- package/dist/cliEmitter.js.map +0 -1
- package/dist/cliHistory.d.ts.map +0 -1
- package/dist/cliHistory.js.map +0 -1
- package/dist/clusters/export.d.ts.map +0 -1
- package/dist/clusters/export.js.map +0 -1
- package/dist/deviceManager.d.ts.map +0 -1
- package/dist/deviceManager.js.map +0 -1
- package/dist/devices/airConditioner.d.ts.map +0 -1
- package/dist/devices/airConditioner.js.map +0 -1
- package/dist/devices/batteryStorage.d.ts.map +0 -1
- package/dist/devices/batteryStorage.js.map +0 -1
- package/dist/devices/cooktop.d.ts.map +0 -1
- package/dist/devices/cooktop.js.map +0 -1
- package/dist/devices/dishwasher.d.ts.map +0 -1
- package/dist/devices/dishwasher.js.map +0 -1
- package/dist/devices/evse.d.ts.map +0 -1
- package/dist/devices/evse.js.map +0 -1
- package/dist/devices/export.d.ts.map +0 -1
- package/dist/devices/export.js.map +0 -1
- package/dist/devices/extractorHood.d.ts.map +0 -1
- package/dist/devices/extractorHood.js.map +0 -1
- package/dist/devices/heatPump.d.ts.map +0 -1
- package/dist/devices/heatPump.js.map +0 -1
- package/dist/devices/laundryDryer.d.ts.map +0 -1
- package/dist/devices/laundryDryer.js.map +0 -1
- package/dist/devices/laundryWasher.d.ts.map +0 -1
- package/dist/devices/laundryWasher.js.map +0 -1
- package/dist/devices/microwaveOven.d.ts.map +0 -1
- package/dist/devices/microwaveOven.js.map +0 -1
- package/dist/devices/oven.d.ts.map +0 -1
- package/dist/devices/oven.js.map +0 -1
- package/dist/devices/refrigerator.d.ts.map +0 -1
- package/dist/devices/refrigerator.js.map +0 -1
- package/dist/devices/roboticVacuumCleaner.d.ts.map +0 -1
- package/dist/devices/roboticVacuumCleaner.js.map +0 -1
- package/dist/devices/solarPower.d.ts.map +0 -1
- package/dist/devices/solarPower.js.map +0 -1
- package/dist/devices/speaker.d.ts.map +0 -1
- package/dist/devices/speaker.js.map +0 -1
- package/dist/devices/temperatureControl.d.ts.map +0 -1
- package/dist/devices/temperatureControl.js.map +0 -1
- package/dist/devices/waterHeater.d.ts.map +0 -1
- package/dist/devices/waterHeater.js.map +0 -1
- package/dist/dgram/coap.d.ts +0 -205
- package/dist/dgram/coap.d.ts.map +0 -1
- package/dist/dgram/coap.js +0 -365
- package/dist/dgram/coap.js.map +0 -1
- package/dist/dgram/dgram.d.ts +0 -144
- package/dist/dgram/dgram.d.ts.map +0 -1
- package/dist/dgram/dgram.js +0 -363
- package/dist/dgram/dgram.js.map +0 -1
- package/dist/dgram/mb_coap.d.ts +0 -24
- package/dist/dgram/mb_coap.d.ts.map +0 -1
- package/dist/dgram/mb_coap.js.map +0 -1
- package/dist/dgram/mb_mdns.d.ts +0 -24
- package/dist/dgram/mb_mdns.d.ts.map +0 -1
- package/dist/dgram/mb_mdns.js.map +0 -1
- package/dist/dgram/mdns.d.ts +0 -371
- package/dist/dgram/mdns.d.ts.map +0 -1
- package/dist/dgram/mdns.js +0 -934
- package/dist/dgram/mdns.js.map +0 -1
- package/dist/dgram/multicast.d.ts +0 -67
- package/dist/dgram/multicast.d.ts.map +0 -1
- package/dist/dgram/multicast.js +0 -179
- package/dist/dgram/multicast.js.map +0 -1
- package/dist/dgram/unicast.d.ts +0 -64
- package/dist/dgram/unicast.d.ts.map +0 -1
- package/dist/dgram/unicast.js +0 -100
- package/dist/dgram/unicast.js.map +0 -1
- package/dist/frontend.d.ts.map +0 -1
- package/dist/frontend.js.map +0 -1
- package/dist/frontendTypes.d.ts.map +0 -1
- package/dist/frontendTypes.js.map +0 -1
- package/dist/helpers.d.ts.map +0 -1
- package/dist/helpers.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/jestutils/export.d.ts.map +0 -1
- package/dist/jestutils/export.js.map +0 -1
- package/dist/jestutils/jestHelpers.d.ts.map +0 -1
- package/dist/jestutils/jestHelpers.js.map +0 -1
- package/dist/logger/export.d.ts.map +0 -1
- package/dist/logger/export.js.map +0 -1
- package/dist/matter/behaviors.d.ts.map +0 -1
- package/dist/matter/behaviors.js.map +0 -1
- package/dist/matter/clusters.d.ts.map +0 -1
- package/dist/matter/clusters.js.map +0 -1
- package/dist/matter/devices.d.ts.map +0 -1
- package/dist/matter/devices.js.map +0 -1
- package/dist/matter/endpoints.d.ts.map +0 -1
- package/dist/matter/endpoints.js.map +0 -1
- package/dist/matter/export.d.ts.map +0 -1
- package/dist/matter/export.js.map +0 -1
- package/dist/matter/types.d.ts.map +0 -1
- package/dist/matter/types.js.map +0 -1
- package/dist/matterNode.d.ts.map +0 -1
- package/dist/matterNode.js.map +0 -1
- package/dist/matterbridge.d.ts.map +0 -1
- package/dist/matterbridge.js.map +0 -1
- package/dist/matterbridgeAccessoryPlatform.d.ts.map +0 -1
- package/dist/matterbridgeAccessoryPlatform.js.map +0 -1
- package/dist/matterbridgeBehaviors.d.ts.map +0 -1
- package/dist/matterbridgeBehaviors.js.map +0 -1
- package/dist/matterbridgeDeviceTypes.d.ts.map +0 -1
- package/dist/matterbridgeDeviceTypes.js.map +0 -1
- package/dist/matterbridgeDynamicPlatform.d.ts.map +0 -1
- package/dist/matterbridgeDynamicPlatform.js.map +0 -1
- package/dist/matterbridgeEndpoint.d.ts.map +0 -1
- package/dist/matterbridgeEndpoint.js.map +0 -1
- package/dist/matterbridgeEndpointHelpers.d.ts.map +0 -1
- package/dist/matterbridgeEndpointHelpers.js.map +0 -1
- package/dist/matterbridgeEndpointTypes.d.ts.map +0 -1
- package/dist/matterbridgeEndpointTypes.js.map +0 -1
- package/dist/matterbridgePlatform.d.ts.map +0 -1
- package/dist/matterbridgePlatform.js.map +0 -1
- package/dist/matterbridgeTypes.d.ts.map +0 -1
- package/dist/matterbridgeTypes.js.map +0 -1
- package/dist/pluginManager.d.ts.map +0 -1
- package/dist/pluginManager.js.map +0 -1
- package/dist/shelly.d.ts.map +0 -1
- package/dist/shelly.js.map +0 -1
- package/dist/storage/export.d.ts.map +0 -1
- package/dist/storage/export.js.map +0 -1
- package/dist/update.d.ts.map +0 -1
- package/dist/update.js.map +0 -1
- package/dist/utils/colorUtils.d.ts +0 -101
- package/dist/utils/colorUtils.d.ts.map +0 -1
- package/dist/utils/colorUtils.js +0 -282
- package/dist/utils/colorUtils.js.map +0 -1
- package/dist/utils/commandLine.d.ts +0 -66
- package/dist/utils/commandLine.d.ts.map +0 -1
- package/dist/utils/commandLine.js +0 -123
- package/dist/utils/commandLine.js.map +0 -1
- package/dist/utils/copyDirectory.d.ts +0 -35
- package/dist/utils/copyDirectory.d.ts.map +0 -1
- package/dist/utils/copyDirectory.js +0 -76
- package/dist/utils/copyDirectory.js.map +0 -1
- package/dist/utils/createDirectory.d.ts +0 -34
- package/dist/utils/createDirectory.d.ts.map +0 -1
- package/dist/utils/createDirectory.js +0 -54
- package/dist/utils/createDirectory.js.map +0 -1
- package/dist/utils/createZip.d.ts +0 -39
- package/dist/utils/createZip.d.ts.map +0 -1
- package/dist/utils/createZip.js +0 -114
- package/dist/utils/createZip.js.map +0 -1
- package/dist/utils/deepCopy.d.ts +0 -32
- package/dist/utils/deepCopy.d.ts.map +0 -1
- package/dist/utils/deepCopy.js +0 -79
- package/dist/utils/deepCopy.js.map +0 -1
- package/dist/utils/deepEqual.d.ts +0 -54
- package/dist/utils/deepEqual.d.ts.map +0 -1
- package/dist/utils/deepEqual.js +0 -129
- package/dist/utils/deepEqual.js.map +0 -1
- package/dist/utils/error.d.ts +0 -45
- package/dist/utils/error.d.ts.map +0 -1
- package/dist/utils/error.js +0 -54
- package/dist/utils/error.js.map +0 -1
- package/dist/utils/export.d.ts.map +0 -1
- package/dist/utils/export.js.map +0 -1
- package/dist/utils/format.d.ts +0 -53
- package/dist/utils/format.d.ts.map +0 -1
- package/dist/utils/format.js +0 -78
- package/dist/utils/format.js.map +0 -1
- package/dist/utils/hex.d.ts +0 -89
- package/dist/utils/hex.d.ts.map +0 -1
- package/dist/utils/hex.js +0 -242
- package/dist/utils/hex.js.map +0 -1
- package/dist/utils/inspector.d.ts +0 -87
- package/dist/utils/inspector.d.ts.map +0 -1
- package/dist/utils/inspector.js +0 -268
- package/dist/utils/inspector.js.map +0 -1
- package/dist/utils/isValid.d.ts +0 -103
- package/dist/utils/isValid.d.ts.map +0 -1
- package/dist/utils/isValid.js +0 -162
- package/dist/utils/isValid.js.map +0 -1
- package/dist/utils/network.d.ts +0 -141
- package/dist/utils/network.d.ts.map +0 -1
- package/dist/utils/network.js +0 -314
- package/dist/utils/network.js.map +0 -1
- package/dist/utils/spawn.d.ts +0 -33
- package/dist/utils/spawn.d.ts.map +0 -1
- package/dist/utils/spawn.js.map +0 -1
- package/dist/utils/tracker.d.ts +0 -108
- package/dist/utils/tracker.d.ts.map +0 -1
- package/dist/utils/tracker.js +0 -264
- package/dist/utils/tracker.js.map +0 -1
- package/dist/utils/wait.d.ts +0 -54
- package/dist/utils/wait.d.ts.map +0 -1
- package/dist/utils/wait.js +0 -125
- package/dist/utils/wait.js.map +0 -1
- package/dist/workerGlobalPrefix.d.ts.map +0 -1
- package/dist/workerGlobalPrefix.js.map +0 -1
- package/dist/workerTypes.d.ts.map +0 -1
- package/dist/workerTypes.js.map +0 -1
- package/dist/workers.d.ts.map +0 -1
- package/dist/workers.js.map +0 -1
|
@@ -1,38 +1,13 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @description This file contains the Jest helpers.
|
|
3
|
-
* @file src/helpers.test.ts
|
|
4
|
-
* @author Luca Liguori
|
|
5
|
-
* @created 2025-09-03
|
|
6
|
-
* @version 1.0.14
|
|
7
|
-
* @license Apache-2.0
|
|
8
|
-
*
|
|
9
|
-
* Copyright 2025, 2026, 2027 Luca Liguori.
|
|
10
|
-
*
|
|
11
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
12
|
-
* you may not use this file except in compliance with the License.
|
|
13
|
-
* You may obtain a copy of the License at
|
|
14
|
-
*
|
|
15
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
16
|
-
*
|
|
17
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
18
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
20
|
-
* See the License for the specific language governing permissions and
|
|
21
|
-
* limitations under the License.
|
|
22
|
-
*/
|
|
23
1
|
import { rmSync } from 'node:fs';
|
|
24
2
|
import { inspect } from 'node:util';
|
|
25
3
|
import path from 'node:path';
|
|
26
|
-
// Imports from node-ansi-logger
|
|
27
4
|
import { AnsiLogger, er, rs, UNDERLINE, UNDERLINEOFF } from 'node-ansi-logger';
|
|
28
|
-
// Imports from @matter
|
|
29
5
|
import { LogLevel as MatterLogLevel, LogFormat as MatterLogFormat, Environment, Lifecycle } from '@matter/general';
|
|
30
6
|
import { Endpoint, ServerNode, ServerNodeStore } from '@matter/node';
|
|
31
7
|
import { DeviceTypeId, VendorId } from '@matter/types/datatype';
|
|
32
8
|
import { AggregatorEndpoint } from '@matter/node/endpoints';
|
|
33
9
|
import { MdnsService } from '@matter/protocol';
|
|
34
10
|
import { NodeStorageManager } from 'node-persist-manager';
|
|
35
|
-
// Imports from Matterbridge
|
|
36
11
|
import { Matterbridge } from '../matterbridge.js';
|
|
37
12
|
import { MATTER_STORAGE_NAME, NODE_STORAGE_DIR } from '../matterbridgeTypes.js';
|
|
38
13
|
import { bridge } from '../matterbridgeDeviceTypes.js';
|
|
@@ -42,7 +17,6 @@ import { BroadcastServer } from '../broadcastServer.js';
|
|
|
42
17
|
import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
|
|
43
18
|
export const originalProcessArgv = Object.freeze([...process.argv]);
|
|
44
19
|
export const originalProcessEnv = Object.freeze({ ...process.env });
|
|
45
|
-
// Spy on logger methods
|
|
46
20
|
export let loggerLogSpy;
|
|
47
21
|
export let loggerDebugSpy;
|
|
48
22
|
export let loggerInfoSpy;
|
|
@@ -50,23 +24,19 @@ export let loggerNoticeSpy;
|
|
|
50
24
|
export let loggerWarnSpy;
|
|
51
25
|
export let loggerErrorSpy;
|
|
52
26
|
export let loggerFatalSpy;
|
|
53
|
-
// Spy on console methods
|
|
54
27
|
export let consoleLogSpy;
|
|
55
28
|
export let consoleDebugSpy;
|
|
56
29
|
export let consoleInfoSpy;
|
|
57
30
|
export let consoleWarnSpy;
|
|
58
31
|
export let consoleErrorSpy;
|
|
59
|
-
// Spy on Matterbridge methods
|
|
60
32
|
export let addBridgedEndpointSpy;
|
|
61
33
|
export let removeBridgedEndpointSpy;
|
|
62
34
|
export let removeAllBridgedEndpointsSpy;
|
|
63
35
|
export let addVirtualEndpointSpy;
|
|
64
|
-
// Spy on MatterbridgeEndpoint methods
|
|
65
36
|
export let setAttributeSpy;
|
|
66
37
|
export let updateAttributeSpy;
|
|
67
38
|
export let triggerEventSpy;
|
|
68
39
|
export let triggerSwitchEventSpy;
|
|
69
|
-
// Spy on PluginManager methods
|
|
70
40
|
export let installPluginSpy;
|
|
71
41
|
export let uninstallPluginSpy;
|
|
72
42
|
export let addPluginSpy;
|
|
@@ -77,14 +47,12 @@ export let shutdownPluginSpy;
|
|
|
77
47
|
export let removePluginSpy;
|
|
78
48
|
export let enablePluginSpy;
|
|
79
49
|
export let disablePluginSpy;
|
|
80
|
-
// Spy on Frontend methods
|
|
81
50
|
export let wssSendSnackbarMessageSpy;
|
|
82
51
|
export let wssSendCloseSnackbarMessageSpy;
|
|
83
52
|
export let wssSendUpdateRequiredSpy;
|
|
84
53
|
export let wssSendRefreshRequiredSpy;
|
|
85
54
|
export let wssSendRestartRequiredSpy;
|
|
86
55
|
export let wssSendRestartNotRequiredSpy;
|
|
87
|
-
// Spy on BroadcastServer methods
|
|
88
56
|
export let broadcastServerIsWorkerRequestSpy;
|
|
89
57
|
export let broadcastServerIsWorkerResponseSpy;
|
|
90
58
|
export let broadcastServerBroadcastSpy;
|
|
@@ -102,29 +70,12 @@ export let environment;
|
|
|
102
70
|
export let server;
|
|
103
71
|
export let aggregator;
|
|
104
72
|
export let log;
|
|
105
|
-
/**
|
|
106
|
-
* Setup the Jest environment:
|
|
107
|
-
* - it will remove any existing home directory
|
|
108
|
-
* - setup the spies for logging
|
|
109
|
-
*
|
|
110
|
-
* @param {string} name The name of the test suite.
|
|
111
|
-
* @param {boolean} debug If true, the logging is not mocked.
|
|
112
|
-
*
|
|
113
|
-
* @example
|
|
114
|
-
* ```typescript
|
|
115
|
-
* import { consoleDebugSpy, consoleErrorSpy, consoleInfoSpy, consoleLogSpy, consoleWarnSpy, loggerLogSpy, setDebug, setupTest } from './jestutils/jestHelpers.js';
|
|
116
|
-
*
|
|
117
|
-
* // Setup the test environment
|
|
118
|
-
* await setupTest(NAME, false);
|
|
119
|
-
* ```
|
|
120
|
-
*/
|
|
121
73
|
export async function setupTest(name, debug = false) {
|
|
122
74
|
expect(name).toBeDefined();
|
|
123
75
|
expect(typeof name).toBe('string');
|
|
124
76
|
expect(name.length).toBeGreaterThanOrEqual(4);
|
|
125
77
|
NAME = name;
|
|
126
78
|
HOMEDIR = path.join('jest', name);
|
|
127
|
-
// Cleanup any existing home directory
|
|
128
79
|
rmSync(HOMEDIR, { recursive: true, force: true });
|
|
129
80
|
const { jest } = await import('@jest/globals');
|
|
130
81
|
loggerDebugSpy = jest.spyOn(AnsiLogger.prototype, 'debug');
|
|
@@ -179,26 +130,8 @@ export async function setupTest(name, debug = false) {
|
|
|
179
130
|
broadcastServerRequestSpy = jest.spyOn(BroadcastServer.prototype, 'request');
|
|
180
131
|
broadcastServerRespondSpy = jest.spyOn(BroadcastServer.prototype, 'respond');
|
|
181
132
|
broadcastServerFetchSpy = jest.spyOn(BroadcastServer.prototype, 'fetch');
|
|
182
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
183
133
|
broadcastMessageHandlerSpy = jest.spyOn(BroadcastServer.prototype, 'broadcastMessageHandler');
|
|
184
134
|
}
|
|
185
|
-
/**
|
|
186
|
-
* Set or unset the debug mode.
|
|
187
|
-
*
|
|
188
|
-
* @param {boolean} debug If true, the logging is not mocked.
|
|
189
|
-
* @returns {Promise<void>} A promise that resolves when the debug mode is set.
|
|
190
|
-
*
|
|
191
|
-
* @example
|
|
192
|
-
* ```typescript
|
|
193
|
-
* // Set the debug mode in test environment
|
|
194
|
-
* await setDebug(true);
|
|
195
|
-
* ```
|
|
196
|
-
*
|
|
197
|
-
* ```typescript
|
|
198
|
-
* // Reset the debug mode in test environment
|
|
199
|
-
* await setDebug(false);
|
|
200
|
-
* ```
|
|
201
|
-
*/
|
|
202
135
|
export async function setDebug(debug) {
|
|
203
136
|
const { jest } = await import('@jest/globals');
|
|
204
137
|
if (debug) {
|
|
@@ -224,48 +157,21 @@ export async function setDebug(debug) {
|
|
|
224
157
|
consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => { });
|
|
225
158
|
}
|
|
226
159
|
}
|
|
227
|
-
/**
|
|
228
|
-
* Create and start a fully initialized Matterbridge instance for testing.
|
|
229
|
-
*
|
|
230
|
-
* @param {('bridge' | 'childbridge' | 'controller' | '')} bridgeMode The bridge mode to start the Matterbridge instance in.
|
|
231
|
-
* @param {number} frontendPort The frontend port number.
|
|
232
|
-
* @param {number} matterPort The matter port number.
|
|
233
|
-
* @param {number} passcode The passcode number.
|
|
234
|
-
* @param {number} discriminator The discriminator number.
|
|
235
|
-
* @param {number} pluginSize The expected number of plugins.
|
|
236
|
-
* @param {number} devicesSize The expected number of devices.
|
|
237
|
-
* @returns {Promise<Matterbridge>} The Matterbridge instance.
|
|
238
|
-
*
|
|
239
|
-
* @example
|
|
240
|
-
* ```typescript
|
|
241
|
-
* // Create and start a fully initialized Matterbridge instance for testing.
|
|
242
|
-
* await startMatterbridge();
|
|
243
|
-
* ```
|
|
244
|
-
*/
|
|
245
160
|
export async function startMatterbridge(bridgeMode = 'bridge', frontendPort = 8283, matterPort = 5540, passcode = 20252026, discriminator = 3840, pluginSize = 0, devicesSize = 0) {
|
|
246
|
-
// Set the environment variables
|
|
247
161
|
process.env['MATTERBRIDGE_START_MATTER_INTERVAL_MS'] = '100';
|
|
248
162
|
process.env['MATTERBRIDGE_PAUSE_MATTER_INTERVAL_MS'] = '100';
|
|
249
|
-
// Setup the process arguments
|
|
250
163
|
process.argv.length = 0;
|
|
251
164
|
process.argv.push(...originalProcessArgv, '-novirtual', '-debug', '-verbose', '-logger', 'debug', '-matterlogger', 'debug', bridgeMode === '' ? '-test' : '-' + bridgeMode, '-homedir', HOMEDIR, '-frontend', frontendPort.toString(), '-port', matterPort.toString(), '-passcode', passcode.toString(), '-discriminator', discriminator.toString());
|
|
252
|
-
// Load Matterbridge instance and initialize it
|
|
253
|
-
// @ts-expect-error - access to private member for testing
|
|
254
165
|
expect(Matterbridge.instance).toBeUndefined();
|
|
255
166
|
matterbridge = await Matterbridge.loadInstance(true);
|
|
256
|
-
// @ts-expect-error - access to private member for testing
|
|
257
167
|
expect(matterbridge.environment).toBeDefined();
|
|
258
|
-
// Setup the mDNS service in the environment
|
|
259
|
-
// @ts-expect-error - access to private member for testing
|
|
260
168
|
new MdnsService(matterbridge.environment);
|
|
261
169
|
expect(matterbridge).toBeDefined();
|
|
262
170
|
expect(matterbridge.profile).toBeUndefined();
|
|
263
171
|
expect(matterbridge.bridgeMode).toBe(bridgeMode);
|
|
264
|
-
// Get the frontend, plugins and devices
|
|
265
172
|
frontend = matterbridge.frontend;
|
|
266
173
|
plugins = matterbridge.plugins;
|
|
267
174
|
devices = matterbridge.devices;
|
|
268
|
-
// @ts-expect-error - access to private member for testing
|
|
269
175
|
expect(matterbridge.initialized).toBeTruthy();
|
|
270
176
|
expect(matterbridge.log).toBeDefined();
|
|
271
177
|
expect(matterbridge.rootDirectory).toBe(path.resolve('./'));
|
|
@@ -278,15 +184,10 @@ export async function startMatterbridge(bridgeMode = 'bridge', frontendPort = 82
|
|
|
278
184
|
expect(devices).toBeDefined();
|
|
279
185
|
expect(devices.size).toBe(devicesSize);
|
|
280
186
|
expect(frontend).toBeDefined();
|
|
281
|
-
// @ts-expect-error - access to private member for testing
|
|
282
187
|
expect(frontend.listening).toBeTruthy();
|
|
283
|
-
// @ts-expect-error - access to private member for testing
|
|
284
188
|
expect(frontend.httpServer).toBeDefined();
|
|
285
|
-
// @ts-expect-error - access to private member for testing
|
|
286
189
|
expect(frontend.httpsServer).toBeUndefined();
|
|
287
|
-
// @ts-expect-error - access to private member for testing
|
|
288
190
|
expect(frontend.expressApp).toBeDefined();
|
|
289
|
-
// @ts-expect-error - access to private member for testing
|
|
290
191
|
expect(frontend.webSocketServer).toBeDefined();
|
|
291
192
|
expect(matterbridge.nodeStorage).toBeDefined();
|
|
292
193
|
expect(matterbridge.nodeContext).toBeDefined();
|
|
@@ -324,51 +225,25 @@ export async function startMatterbridge(bridgeMode = 'bridge', frontendPort = 82
|
|
|
324
225
|
});
|
|
325
226
|
});
|
|
326
227
|
}
|
|
327
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("info"
|
|
228
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("info", `The frontend http server is listening on ${UNDERLINE}http://${matterbridge.systemInformation.ipv4Address}:${frontendPort}${UNDERLINEOFF}${rs}`);
|
|
328
229
|
if (bridgeMode === 'bridge') {
|
|
329
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("notice"
|
|
330
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("notice"
|
|
331
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("debug"
|
|
332
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("debug"
|
|
333
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("notice"
|
|
230
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("notice", `Starting Matterbridge server node`);
|
|
231
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("notice", `Server node for Matterbridge is online`);
|
|
232
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("debug", `Starting start matter interval in bridge mode...`);
|
|
233
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("debug", `Cleared startMatterInterval interval in bridge mode`);
|
|
234
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("notice", `Matterbridge bridge started successfully`);
|
|
334
235
|
}
|
|
335
236
|
else if (bridgeMode === 'childbridge') {
|
|
336
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("debug"
|
|
337
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("debug"
|
|
338
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("notice"
|
|
237
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("debug", `Starting start matter interval in childbridge mode...`);
|
|
238
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("debug", `Cleared startMatterInterval interval in childbridge mode`);
|
|
239
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("notice", `Matterbridge childbridge started successfully`);
|
|
339
240
|
}
|
|
340
241
|
return matterbridge;
|
|
341
242
|
}
|
|
342
|
-
/**
|
|
343
|
-
* Stop the fully initialized Matterbridge instance.
|
|
344
|
-
*
|
|
345
|
-
* @param {cleanupPause} cleanupPause The pause duration before cleanup. Default is 10 ms.
|
|
346
|
-
* @param {destroyPause} destroyPause The pause duration before destruction. Default is 250 ms.
|
|
347
|
-
*
|
|
348
|
-
* @example
|
|
349
|
-
* ```typescript
|
|
350
|
-
* // Stop the fully initialized Matterbridge instance.
|
|
351
|
-
* await stopMatterbridge();
|
|
352
|
-
* ```
|
|
353
|
-
*/
|
|
354
243
|
export async function stopMatterbridge(cleanupPause = 10, destroyPause = 250) {
|
|
355
244
|
await destroyMatterbridgeEnvironment(cleanupPause, destroyPause);
|
|
356
245
|
}
|
|
357
|
-
/**
|
|
358
|
-
* Create a Matterbridge instance for testing without initializing it.
|
|
359
|
-
*
|
|
360
|
-
* @param {string} name - Name for the environment (jest/name).
|
|
361
|
-
* @returns {Promise<Matterbridge>} The Matterbridge instance.
|
|
362
|
-
*
|
|
363
|
-
* @example
|
|
364
|
-
* ```typescript
|
|
365
|
-
* // Create Matterbridge environment
|
|
366
|
-
* await createMatterbridgeEnvironment(NAME);
|
|
367
|
-
* await startMatterbridgeEnvironment(MATTER_PORT);
|
|
368
|
-
* ```
|
|
369
|
-
*/
|
|
370
246
|
export async function createMatterbridgeEnvironment(name) {
|
|
371
|
-
// Create a MatterbridgeEdge instance
|
|
372
247
|
matterbridge = await Matterbridge.loadInstance(false);
|
|
373
248
|
expect(matterbridge).toBeDefined();
|
|
374
249
|
expect(matterbridge).toBeInstanceOf(Matterbridge);
|
|
@@ -379,52 +254,28 @@ export async function createMatterbridgeEnvironment(name) {
|
|
|
379
254
|
matterbridge.matterbridgeDirectory = path.join('jest', name, '.matterbridge');
|
|
380
255
|
matterbridge.matterbridgePluginDirectory = path.join('jest', name, 'Matterbridge');
|
|
381
256
|
matterbridge.matterbridgeCertDirectory = path.join('jest', name, '.mattercert');
|
|
382
|
-
matterbridge.log.logLevel = "debug"
|
|
383
|
-
log = new AnsiLogger({ logName: name, logTimestampFormat: 4
|
|
384
|
-
// Get the frontend, plugins and devices
|
|
257
|
+
matterbridge.log.logLevel = "debug";
|
|
258
|
+
log = new AnsiLogger({ logName: name, logTimestampFormat: 4, logLevel: "debug" });
|
|
385
259
|
frontend = matterbridge.frontend;
|
|
386
260
|
plugins = matterbridge.plugins;
|
|
387
261
|
devices = matterbridge.devices;
|
|
388
|
-
// Setup matter environment
|
|
389
|
-
// @ts-expect-error - access to private member for testing
|
|
390
262
|
matterbridge.environment = createTestEnvironment(name);
|
|
391
|
-
// @ts-expect-error - access to private member for testing
|
|
392
263
|
expect(matterbridge.environment).toBeDefined();
|
|
393
|
-
// @ts-expect-error - access to private member for testing
|
|
394
264
|
expect(matterbridge.environment).toBeInstanceOf(Environment);
|
|
395
265
|
return matterbridge;
|
|
396
266
|
}
|
|
397
|
-
/**
|
|
398
|
-
* Start the matterbridge environment.
|
|
399
|
-
* Only node storage, matter storage and the server and aggregator nodes are started.
|
|
400
|
-
*
|
|
401
|
-
* @param {number} port The matter server port.
|
|
402
|
-
* @returns {Promise<[ServerNode<ServerNode.RootEndpoint>, Endpoint<AggregatorEndpoint>]>} The started server and aggregator.
|
|
403
|
-
*
|
|
404
|
-
* @example
|
|
405
|
-
* ```typescript
|
|
406
|
-
* // Create Matterbridge environment
|
|
407
|
-
* await createMatterbridgeEnvironment(NAME);
|
|
408
|
-
* await startMatterbridgeEnvironment(MATTER_PORT);
|
|
409
|
-
* ```
|
|
410
|
-
*/
|
|
411
267
|
export async function startMatterbridgeEnvironment(port = 5540) {
|
|
412
|
-
// Create the node storage
|
|
413
268
|
matterbridge.nodeStorage = new NodeStorageManager({ dir: path.join(matterbridge.matterbridgeDirectory, NODE_STORAGE_DIR), writeQueue: false, expiredInterval: undefined, logging: false });
|
|
414
269
|
matterbridge.nodeContext = await matterbridge.nodeStorage.createStorage('matterbridge');
|
|
415
|
-
// Create the matter storage
|
|
416
|
-
// @ts-expect-error - access to private member for testing
|
|
417
270
|
await matterbridge.startMatterStorage();
|
|
418
271
|
expect(matterbridge.matterStorageService).toBeDefined();
|
|
419
272
|
expect(matterbridge.matterStorageManager).toBeDefined();
|
|
420
273
|
expect(matterbridge.matterbridgeContext).toBeDefined();
|
|
421
|
-
// @ts-expect-error - access to private member for testing
|
|
422
274
|
server = await matterbridge.createServerNode(matterbridge.matterbridgeContext, port);
|
|
423
275
|
expect(server).toBeDefined();
|
|
424
276
|
expect(server).toBeDefined();
|
|
425
277
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
426
278
|
matterbridge.serverNode = server;
|
|
427
|
-
// @ts-expect-error - access to private member for testing
|
|
428
279
|
aggregator = await matterbridge.createAggregatorNode(matterbridge.matterbridgeContext);
|
|
429
280
|
expect(aggregator).toBeDefined();
|
|
430
281
|
matterbridge.aggregatorNode = aggregator;
|
|
@@ -432,7 +283,6 @@ export async function startMatterbridgeEnvironment(port = 5540) {
|
|
|
432
283
|
expect(server.parts.has(aggregator.id)).toBeTruthy();
|
|
433
284
|
expect(server.parts.has(aggregator)).toBeTruthy();
|
|
434
285
|
expect(aggregator.lifecycle.isReady).toBeTruthy();
|
|
435
|
-
// Wait for the server to be online
|
|
436
286
|
expect(server.lifecycle.isOnline).toBeFalsy();
|
|
437
287
|
await new Promise((resolve) => {
|
|
438
288
|
server.lifecycle.online.on(async () => {
|
|
@@ -440,7 +290,6 @@ export async function startMatterbridgeEnvironment(port = 5540) {
|
|
|
440
290
|
});
|
|
441
291
|
server.start();
|
|
442
292
|
});
|
|
443
|
-
// Check if the server is online
|
|
444
293
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
445
294
|
expect(server.lifecycle.isOnline).toBeTruthy();
|
|
446
295
|
expect(server.lifecycle.isCommissioned).toBeFalsy();
|
|
@@ -452,27 +301,11 @@ export async function startMatterbridgeEnvironment(port = 5540) {
|
|
|
452
301
|
expect(aggregator.lifecycle.isPartsReady).toBeTruthy();
|
|
453
302
|
expect(aggregator.lifecycle.hasId).toBeTruthy();
|
|
454
303
|
expect(aggregator.lifecycle.hasNumber).toBeTruthy();
|
|
455
|
-
// Ensure the queue is empty and pause
|
|
456
304
|
await flushAsync();
|
|
457
305
|
return [server, aggregator];
|
|
458
306
|
}
|
|
459
|
-
/**
|
|
460
|
-
* Add a matterbridge platform for testing.
|
|
461
|
-
*
|
|
462
|
-
* @param {MatterbridgePlatform} platform The platform to add.
|
|
463
|
-
* @param {string} [name] Optional name of the platform.
|
|
464
|
-
*
|
|
465
|
-
* @example
|
|
466
|
-
* ```typescript
|
|
467
|
-
* platform = new Platform(matterbridge, log, config);
|
|
468
|
-
* // Add the platform to the Matterbridge environment
|
|
469
|
-
* addMatterbridgePlatform(platform);
|
|
470
|
-
* ```
|
|
471
|
-
*/
|
|
472
307
|
export function addMatterbridgePlatform(platform, name) {
|
|
473
308
|
expect(platform).toBeDefined();
|
|
474
|
-
// Setup the platform MatterNode helpers
|
|
475
|
-
// @ts-expect-error - setMatterNode is intentionally private
|
|
476
309
|
platform.setMatterNode?.(matterbridge.addBridgedEndpoint.bind(matterbridge), matterbridge.removeBridgedEndpoint.bind(matterbridge), matterbridge.removeAllBridgedEndpoints.bind(matterbridge), matterbridge.addVirtualEndpoint.bind(matterbridge));
|
|
477
310
|
if (name)
|
|
478
311
|
platform.config.name = name;
|
|
@@ -483,7 +316,6 @@ export function addMatterbridgePlatform(platform, name) {
|
|
|
483
316
|
expect(platform.version).toBeDefined();
|
|
484
317
|
expect(platform.config.debug).toBeDefined();
|
|
485
318
|
expect(platform.config.unregisterOnShutdown).toBeDefined();
|
|
486
|
-
// @ts-expect-error accessing private member for testing
|
|
487
319
|
matterbridge.plugins._plugins.set(platform.config.name, {
|
|
488
320
|
name: platform.config.name,
|
|
489
321
|
path: './',
|
|
@@ -495,143 +327,60 @@ export function addMatterbridgePlatform(platform, name) {
|
|
|
495
327
|
});
|
|
496
328
|
platform['name'] = platform.config.name;
|
|
497
329
|
}
|
|
498
|
-
/**
|
|
499
|
-
* Stop the matterbridge environment
|
|
500
|
-
*
|
|
501
|
-
* @example
|
|
502
|
-
* ```typescript
|
|
503
|
-
* // Destroy Matterbridge environment
|
|
504
|
-
* await stopMatterbridgeEnvironment();
|
|
505
|
-
* await destroyMatterbridgeEnvironment();
|
|
506
|
-
* ```
|
|
507
|
-
*/
|
|
508
330
|
export async function stopMatterbridgeEnvironment() {
|
|
509
331
|
expect(matterbridge).toBeDefined();
|
|
510
332
|
expect(server).toBeDefined();
|
|
511
333
|
expect(aggregator).toBeDefined();
|
|
512
|
-
// Flush any pending endpoint number persistence
|
|
513
334
|
await flushAllEndpointNumberPersistence(server);
|
|
514
|
-
// Ensure all endpoint numbers are persisted
|
|
515
335
|
await assertAllEndpointNumbersPersisted(server);
|
|
516
|
-
// Close the server node
|
|
517
336
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
518
337
|
expect(server.lifecycle.isOnline).toBeTruthy();
|
|
519
338
|
await server.close();
|
|
520
339
|
expect(server.lifecycle.isReady).toBeFalsy();
|
|
521
340
|
expect(server.lifecycle.isOnline).toBeFalsy();
|
|
522
|
-
// Stop the matter storage
|
|
523
|
-
// @ts-expect-error - access to private member for testing
|
|
524
341
|
await matterbridge.stopMatterStorage();
|
|
525
342
|
expect(matterbridge.matterStorageService).not.toBeDefined();
|
|
526
343
|
expect(matterbridge.matterStorageManager).not.toBeDefined();
|
|
527
344
|
expect(matterbridge.matterbridgeContext).not.toBeDefined();
|
|
528
|
-
// Stop the node storage
|
|
529
345
|
await matterbridge.nodeContext?.close();
|
|
530
346
|
matterbridge.nodeContext = undefined;
|
|
531
347
|
await matterbridge.nodeStorage?.close();
|
|
532
348
|
matterbridge.nodeStorage = undefined;
|
|
533
|
-
// Ensure the queue is empty and pause
|
|
534
349
|
await flushAsync();
|
|
535
350
|
}
|
|
536
|
-
/**
|
|
537
|
-
* Destroy the matterbridge environment
|
|
538
|
-
*
|
|
539
|
-
* @param {number} cleanupPause The timeout for the destroy operation (default 10ms).
|
|
540
|
-
* @param {number} destroyPause The pause duration after cleanup before destroying the instance (default 250ms).
|
|
541
|
-
*
|
|
542
|
-
* @example
|
|
543
|
-
* ```typescript
|
|
544
|
-
* // Destroy Matterbridge environment
|
|
545
|
-
* await stopMatterbridgeEnvironment();
|
|
546
|
-
* await destroyMatterbridgeEnvironment();
|
|
547
|
-
* ```
|
|
548
|
-
*/
|
|
549
351
|
export async function destroyMatterbridgeEnvironment(cleanupPause = 10, destroyPause = 250) {
|
|
550
|
-
// Destroy a matterbridge instance
|
|
551
352
|
await destroyInstance(matterbridge, cleanupPause, destroyPause);
|
|
552
|
-
// Close the mDNS service
|
|
553
353
|
await closeMdnsInstance(matterbridge);
|
|
554
|
-
// Reset the singleton instance
|
|
555
|
-
// @ts-expect-error - accessing private member for testing
|
|
556
354
|
Matterbridge.instance = undefined;
|
|
557
355
|
}
|
|
558
|
-
/**
|
|
559
|
-
* Destroy a matterbridge instance
|
|
560
|
-
*
|
|
561
|
-
* @param {Matterbridge} matterbridge The matterbridge instance to destroy.
|
|
562
|
-
* @param {number} cleanupPause The pause duration to wait for the cleanup to complete in milliseconds (default 10ms).
|
|
563
|
-
* @param {number} destroyPause The pause duration to wait after cleanup before destroying the instance in milliseconds (default 250ms).
|
|
564
|
-
*/
|
|
565
356
|
export async function destroyInstance(matterbridge, cleanupPause = 10, destroyPause = 250) {
|
|
566
|
-
// Cleanup the Matterbridge instance
|
|
567
|
-
// @ts-expect-error - accessing private member for testing
|
|
568
357
|
await matterbridge.cleanup('destroying instance...', false, cleanupPause);
|
|
569
|
-
// Pause before destroying the instance
|
|
570
358
|
if (destroyPause > 0)
|
|
571
359
|
await flushAsync(undefined, undefined, destroyPause);
|
|
572
360
|
}
|
|
573
|
-
/**
|
|
574
|
-
* Close the mDNS instance in the matterbridge environment.
|
|
575
|
-
*
|
|
576
|
-
* @param {Matterbridge} matterbridge The matterbridge instance.
|
|
577
|
-
* @returns {Promise<void>} A promise that resolves when the mDNS instance is closed.
|
|
578
|
-
*/
|
|
579
361
|
export async function closeMdnsInstance(matterbridge) {
|
|
580
|
-
// @ts-expect-error - accessing private member for testing
|
|
581
362
|
const mdns = matterbridge.environment.get(MdnsService);
|
|
582
363
|
await mdns.close();
|
|
583
364
|
}
|
|
584
|
-
/**
|
|
585
|
-
* Create a matter test environment for testing:
|
|
586
|
-
* - it will remove any existing home directory
|
|
587
|
-
* - setup the matter environment with name, debug logging and ANSI format
|
|
588
|
-
* - setup the mDNS service in the environment
|
|
589
|
-
*
|
|
590
|
-
* @param {string} name - Name for the environment (jest/name).
|
|
591
|
-
* @returns {Environment} - The default matter environment.
|
|
592
|
-
*/
|
|
593
365
|
export function createTestEnvironment(name) {
|
|
594
366
|
expect(name).toBeDefined();
|
|
595
367
|
expect(typeof name).toBe('string');
|
|
596
|
-
expect(name.length).toBeGreaterThanOrEqual(4);
|
|
597
|
-
|
|
598
|
-
log = new AnsiLogger({ logName: name, logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: "debug" /* LogLevel.DEBUG */ });
|
|
599
|
-
// Cleanup any existing home directory
|
|
368
|
+
expect(name.length).toBeGreaterThanOrEqual(4);
|
|
369
|
+
log = new AnsiLogger({ logName: name, logTimestampFormat: 4, logLevel: "debug" });
|
|
600
370
|
rmSync(path.join('jest', name), { recursive: true, force: true });
|
|
601
|
-
// Setup the matter environment
|
|
602
371
|
environment = Environment.default;
|
|
603
372
|
environment.vars.set('log.level', MatterLogLevel.DEBUG);
|
|
604
373
|
environment.vars.set('log.format', MatterLogFormat.ANSI);
|
|
605
374
|
environment.vars.set('path.root', path.join('jest', name, '.matterbridge', MATTER_STORAGE_NAME));
|
|
606
375
|
environment.vars.set('runtime.signals', false);
|
|
607
376
|
environment.vars.set('runtime.exitcode', false);
|
|
608
|
-
// Setup the mDNS service in the environment
|
|
609
377
|
new MdnsService(environment);
|
|
610
|
-
// await environment.get(MdnsService)?.construction.ready;
|
|
611
378
|
return environment;
|
|
612
379
|
}
|
|
613
|
-
/**
|
|
614
|
-
* Destroy the matter test environment by closing the mDNS service.
|
|
615
|
-
*
|
|
616
|
-
* @returns {Promise<void>} A promise that resolves when the test environment is destroyed.
|
|
617
|
-
*/
|
|
618
380
|
export async function destroyTestEnvironment() {
|
|
619
|
-
// stop the mDNS service
|
|
620
381
|
const mdns = environment.get(MdnsService);
|
|
621
382
|
await mdns.close();
|
|
622
383
|
}
|
|
623
|
-
/**
|
|
624
|
-
* Advance the Node.js event loop deterministically to allow chained asynchronous work (Promises scheduled in
|
|
625
|
-
* microtasks and follow‑up macrotasks) to complete inside tests without adding arbitrary long timeouts.
|
|
626
|
-
*
|
|
627
|
-
* NOTE: This does not guarantee OS level network IO completion—only JavaScript task queue progression inside the
|
|
628
|
-
* current process.
|
|
629
|
-
*
|
|
630
|
-
* @param {number} ticks Number of macrotask (setImmediate) turns to yield (default 3).
|
|
631
|
-
* @param {number} microTurns Number of microtask drains (Promise.resolve chains) after macrotask yielding (default 10).
|
|
632
|
-
* @param {number} pause Final timer delay in ms; set 0 to disable (default 250ms).
|
|
633
|
-
* @returns {Promise<void>} Resolves after the requested event loop advancement has completed.
|
|
634
|
-
*/
|
|
635
384
|
export async function flushAsync(ticks = 3, microTurns = 10, pause = 250) {
|
|
636
385
|
for (let i = 0; i < ticks; i++)
|
|
637
386
|
await new Promise((resolve) => setImmediate(resolve));
|
|
@@ -640,33 +389,16 @@ export async function flushAsync(ticks = 3, microTurns = 10, pause = 250) {
|
|
|
640
389
|
if (pause)
|
|
641
390
|
await new Promise((resolve) => setTimeout(resolve, pause));
|
|
642
391
|
}
|
|
643
|
-
/**
|
|
644
|
-
* Summarize live libuv handles/requests inside a process.
|
|
645
|
-
*
|
|
646
|
-
* @param {AnsiLogger} log - Logger to use for output
|
|
647
|
-
*
|
|
648
|
-
* @returns {number} - The total number of active handles and requests
|
|
649
|
-
*/
|
|
650
392
|
export function logKeepAlives(log) {
|
|
651
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
652
393
|
const handles = process._getActiveHandles?.() ?? [];
|
|
653
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
654
394
|
const requests = process._getActiveRequests?.() ?? [];
|
|
655
|
-
// istanbul ignore next
|
|
656
395
|
const fmtHandle = (h, i) => {
|
|
657
396
|
const ctor = h?.constructor?.name ?? 'Unknown';
|
|
658
|
-
// Timer-like?
|
|
659
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
660
397
|
const hasRef = typeof h?.hasRef === 'function' ? h.hasRef() : undefined;
|
|
661
|
-
// MessagePort?
|
|
662
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
663
398
|
const isPort = h?.constructor?.name?.includes('MessagePort');
|
|
664
|
-
// Socket/Server?
|
|
665
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
666
399
|
const fd = h?.fd ?? h?._handle?.fd;
|
|
667
400
|
return { i, type: ctor, hasRef, isPort, fd };
|
|
668
401
|
};
|
|
669
|
-
// istanbul ignore next
|
|
670
402
|
const fmtReq = (r, i) => {
|
|
671
403
|
const ctor = r?.constructor?.name ?? 'Unknown';
|
|
672
404
|
return { i, type: ctor };
|
|
@@ -675,7 +407,6 @@ export function logKeepAlives(log) {
|
|
|
675
407
|
handles: handles.map(fmtHandle),
|
|
676
408
|
requests: requests.map(fmtReq),
|
|
677
409
|
};
|
|
678
|
-
// istanbul ignore next if
|
|
679
410
|
if (summary.handles.length === 0 && summary.requests.length === 0) {
|
|
680
411
|
log?.debug('KeepAlive: no active handles or requests.');
|
|
681
412
|
}
|
|
@@ -687,19 +418,6 @@ export function logKeepAlives(log) {
|
|
|
687
418
|
}
|
|
688
419
|
return summary.handles.length + summary.requests.length;
|
|
689
420
|
}
|
|
690
|
-
/**
|
|
691
|
-
* Flush (await) the lazy endpoint number persistence mechanism used by matter.js.
|
|
692
|
-
*
|
|
693
|
-
* Background:
|
|
694
|
-
* assignNumber() batches persistence (store.saveNumber + updating __nextNumber__) via an internal promise (#numbersPersisted).
|
|
695
|
-
* Calling endpointStores.close() waits for the current batch only. If new endpoints were added in the same macrotask
|
|
696
|
-
* cycle additional micro/macro turns might be needed to ensure the batch started. We defensively yield macrotasks
|
|
697
|
-
* (setImmediate) and then await close() multiple rounds.
|
|
698
|
-
*
|
|
699
|
-
* @param {ServerNode} targetServer The server whose endpoint numbering persistence should be flushed.
|
|
700
|
-
* @param {number} rounds Number of macrotask + close cycles to run (2 is usually sufficient; 1 often works).
|
|
701
|
-
* @returns {Promise<void>} Resolves when pending number persistence batches have completed.
|
|
702
|
-
*/
|
|
703
421
|
export async function flushAllEndpointNumberPersistence(targetServer, rounds = 2) {
|
|
704
422
|
const nodeStore = targetServer.env.get(ServerNodeStore);
|
|
705
423
|
for (let i = 0; i < rounds; i++) {
|
|
@@ -707,12 +425,6 @@ export async function flushAllEndpointNumberPersistence(targetServer, rounds = 2
|
|
|
707
425
|
await nodeStore.endpointStores.close();
|
|
708
426
|
}
|
|
709
427
|
}
|
|
710
|
-
/**
|
|
711
|
-
* Collect all endpoints in the server endpoint tree (root -> descendants).
|
|
712
|
-
*
|
|
713
|
-
* @param {Endpoint} root Root endpoint (typically the ServerNode root endpoint cast as Endpoint).
|
|
714
|
-
* @returns {Endpoint[]} Flat array including the root and every descendant once.
|
|
715
|
-
*/
|
|
716
428
|
function collectAllEndpoints(root) {
|
|
717
429
|
const list = [];
|
|
718
430
|
const walk = (ep) => {
|
|
@@ -726,26 +438,14 @@ function collectAllEndpoints(root) {
|
|
|
726
438
|
walk(root);
|
|
727
439
|
return list;
|
|
728
440
|
}
|
|
729
|
-
/**
|
|
730
|
-
* Assert that every endpoint attached to the server has an assigned and (batch-)persisted endpoint number.
|
|
731
|
-
*
|
|
732
|
-
* This waits for any outstanding number persistence batch (endpointStores.close()), then traverses the endpoint
|
|
733
|
-
* graph and asserts:
|
|
734
|
-
* - Root endpoint: number is 0 (allowing undefined to coerce to 0 via nullish coalescing check).
|
|
735
|
-
* - All other endpoints: number > 0.
|
|
736
|
-
*
|
|
737
|
-
* @param {ServerNode} targetServer The server whose endpoint numbers are verified.
|
|
738
|
-
* @returns {Promise<void>} Resolves when assertions complete.
|
|
739
|
-
*/
|
|
740
441
|
export async function assertAllEndpointNumbersPersisted(targetServer) {
|
|
741
442
|
const nodeStore = targetServer.env.get(ServerNodeStore);
|
|
742
|
-
// Ensure any pending persistence finished (flush any in-flight batch promise)
|
|
743
443
|
await nodeStore.endpointStores.close();
|
|
744
444
|
const all = collectAllEndpoints(targetServer);
|
|
745
445
|
for (const ep of all) {
|
|
746
446
|
const store = nodeStore.storeForEndpoint(ep);
|
|
747
447
|
if (ep.maybeNumber === 0) {
|
|
748
|
-
expect(store.number ?? 0).toBe(0);
|
|
448
|
+
expect(store.number ?? 0).toBe(0);
|
|
749
449
|
}
|
|
750
450
|
else {
|
|
751
451
|
expect(store.number).toBeGreaterThan(0);
|
|
@@ -753,42 +453,23 @@ export async function assertAllEndpointNumbersPersisted(targetServer) {
|
|
|
753
453
|
}
|
|
754
454
|
return all.length;
|
|
755
455
|
}
|
|
756
|
-
/**
|
|
757
|
-
* Close the server node stores to flush any pending endpoint number persistence.
|
|
758
|
-
*
|
|
759
|
-
* @param {ServerNode} targetServer The server whose endpoint stores should be closed.
|
|
760
|
-
* @returns {Promise<void>} Resolves when the stores have been closed.
|
|
761
|
-
*/
|
|
762
456
|
export async function closeServerNodeStores(targetServer) {
|
|
763
|
-
// Close endpoint stores to avoid number persistence issues
|
|
764
457
|
if (!targetServer)
|
|
765
458
|
targetServer = server;
|
|
766
459
|
await targetServer?.env.get(ServerNodeStore)?.endpointStores.close();
|
|
767
460
|
}
|
|
768
|
-
/**
|
|
769
|
-
* Start a matter server node for testing.
|
|
770
|
-
*
|
|
771
|
-
* @param {string} name Name of the server (used for logging and product description).
|
|
772
|
-
* @param {number} port TCP port to listen on.
|
|
773
|
-
* @param {DeviceTypeId} deviceType Device type identifier for the server node.
|
|
774
|
-
* @returns {Promise<[ServerNode<ServerNode.RootEndpoint>, Endpoint<AggregatorEndpoint>]>} Resolves to an array containing the created ServerNode and its AggregatorNode.
|
|
775
|
-
*/
|
|
776
461
|
export async function startServerNode(name, port, deviceType = bridge.code) {
|
|
777
462
|
const { randomBytes } = await import('node:crypto');
|
|
778
463
|
const random = randomBytes(8).toString('hex');
|
|
779
|
-
// Create the server node
|
|
780
464
|
server = await ServerNode.create({
|
|
781
465
|
id: name + 'ServerNode',
|
|
782
|
-
// Provide the environment
|
|
783
466
|
environment,
|
|
784
|
-
// Provide Node announcement settings
|
|
785
467
|
productDescription: {
|
|
786
468
|
name: name + 'ServerNode',
|
|
787
469
|
deviceType: DeviceTypeId(deviceType),
|
|
788
470
|
vendorId: VendorId(0xfff1),
|
|
789
471
|
productId: 0x8000,
|
|
790
472
|
},
|
|
791
|
-
// Provide defaults for the BasicInformation cluster on the Root endpoint
|
|
792
473
|
basicInformation: {
|
|
793
474
|
vendorId: VendorId(0xfff1),
|
|
794
475
|
vendorName: 'Matterbridge',
|
|
@@ -801,39 +482,32 @@ export async function startServerNode(name, port, deviceType = bridge.code) {
|
|
|
801
482
|
serialNumber: 'SN' + random,
|
|
802
483
|
uniqueId: 'UI' + random,
|
|
803
484
|
},
|
|
804
|
-
// Provide Network relevant configuration like the port
|
|
805
485
|
network: {
|
|
806
486
|
listeningAddressIpv4: undefined,
|
|
807
487
|
listeningAddressIpv6: undefined,
|
|
808
488
|
port,
|
|
809
489
|
},
|
|
810
|
-
// Provide the certificate for the device
|
|
811
490
|
operationalCredentials: {
|
|
812
491
|
certification: undefined,
|
|
813
492
|
},
|
|
814
493
|
});
|
|
815
494
|
expect(server).toBeDefined();
|
|
816
495
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
817
|
-
// Create the aggregator node
|
|
818
496
|
aggregator = new Endpoint(AggregatorEndpoint, {
|
|
819
497
|
id: name + 'AggregatorNode',
|
|
820
498
|
});
|
|
821
499
|
expect(aggregator).toBeDefined();
|
|
822
|
-
// Add the aggregator to the server
|
|
823
500
|
await server.add(aggregator);
|
|
824
501
|
expect(server.parts.has(aggregator.id)).toBeTruthy();
|
|
825
502
|
expect(server.parts.has(aggregator)).toBeTruthy();
|
|
826
503
|
expect(aggregator.lifecycle.isReady).toBeTruthy();
|
|
827
|
-
// Run the server
|
|
828
504
|
expect(server.lifecycle.isOnline).toBeFalsy();
|
|
829
|
-
// Wait for the server to be online
|
|
830
505
|
await new Promise((resolve) => {
|
|
831
506
|
server.lifecycle.online.on(async () => {
|
|
832
507
|
resolve();
|
|
833
508
|
});
|
|
834
509
|
server.start();
|
|
835
510
|
});
|
|
836
|
-
// Check if the server is online
|
|
837
511
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
838
512
|
expect(server.lifecycle.isOnline).toBeTruthy();
|
|
839
513
|
expect(server.lifecycle.isCommissioned).toBeFalsy();
|
|
@@ -845,53 +519,31 @@ export async function startServerNode(name, port, deviceType = bridge.code) {
|
|
|
845
519
|
expect(aggregator.lifecycle.isPartsReady).toBeTruthy();
|
|
846
520
|
expect(aggregator.lifecycle.hasId).toBeTruthy();
|
|
847
521
|
expect(aggregator.lifecycle.hasNumber).toBeTruthy();
|
|
848
|
-
// Ensure the queue is empty and pause 250ms
|
|
849
522
|
await flushAsync();
|
|
850
523
|
return [server, aggregator];
|
|
851
524
|
}
|
|
852
|
-
/**
|
|
853
|
-
* Stop a matter server node.
|
|
854
|
-
*
|
|
855
|
-
* @param {ServerNode<ServerNode.RootEndpoint>} server The server to stop.
|
|
856
|
-
* @returns {Promise<void>} Resolves when the server has stopped.
|
|
857
|
-
*/
|
|
858
525
|
export async function stopServerNode(server) {
|
|
859
|
-
// Flush any pending endpoint number persistence
|
|
860
526
|
await flushAllEndpointNumberPersistence(server);
|
|
861
|
-
// Ensure all endpoint numbers are persisted
|
|
862
527
|
await assertAllEndpointNumbersPersisted(server);
|
|
863
|
-
// Stop the server
|
|
864
528
|
expect(server).toBeDefined();
|
|
865
529
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
866
530
|
expect(server.lifecycle.isOnline).toBeTruthy();
|
|
867
531
|
await server.close();
|
|
868
532
|
expect(server.lifecycle.isReady).toBeFalsy();
|
|
869
533
|
expect(server.lifecycle.isOnline).toBeFalsy();
|
|
870
|
-
// stop the mDNS service
|
|
871
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
872
534
|
const mdns = environment.get(MdnsService);
|
|
873
535
|
if (mdns && typeof mdns[Symbol.asyncDispose] === 'function')
|
|
874
536
|
await mdns[Symbol.asyncDispose]();
|
|
875
537
|
if (mdns && typeof mdns.close === 'function')
|
|
876
538
|
await mdns.close();
|
|
877
|
-
// Ensure the queue is empty and pause 250ms
|
|
878
539
|
await flushAsync();
|
|
879
540
|
}
|
|
880
|
-
/**
|
|
881
|
-
* Add a device (endpoint) to a matter server node or an aggregator.
|
|
882
|
-
*
|
|
883
|
-
* @param {ServerNode<ServerNode.RootEndpoint> | Endpoint<AggregatorEndpoint>} owner The server or aggregator to add the device to.
|
|
884
|
-
* @param {Endpoint} device The device to add.
|
|
885
|
-
* @param {number} pause The pause time in milliseconds after addition (default 10ms).
|
|
886
|
-
* @returns {Promise<void>} Resolves when the device has been added and is ready.
|
|
887
|
-
*/
|
|
888
541
|
export async function addDevice(owner, device, pause = 10) {
|
|
889
542
|
expect(owner).toBeDefined();
|
|
890
543
|
expect(device).toBeDefined();
|
|
891
544
|
expect(owner.lifecycle.isReady).toBeTruthy();
|
|
892
545
|
expect(owner.construction.status).toBe(Lifecycle.Status.Active);
|
|
893
546
|
expect(owner.lifecycle.isPartsReady).toBeTruthy();
|
|
894
|
-
// istanbul ignore next
|
|
895
547
|
try {
|
|
896
548
|
await owner.add(device);
|
|
897
549
|
}
|
|
@@ -911,21 +563,12 @@ export async function addDevice(owner, device, pause = 10) {
|
|
|
911
563
|
await flushAsync(undefined, undefined, pause);
|
|
912
564
|
return true;
|
|
913
565
|
}
|
|
914
|
-
/**
|
|
915
|
-
* Delete a device (endpoint) from a matter server node or an aggregator.
|
|
916
|
-
*
|
|
917
|
-
* @param {ServerNode<ServerNode.RootEndpoint> | Endpoint<AggregatorEndpoint>} owner The server or aggregator to remove the device from.
|
|
918
|
-
* @param {Endpoint} device The device to remove.
|
|
919
|
-
* @param {number} pause The pause time in milliseconds after deletion (default 10ms).
|
|
920
|
-
* @returns {Promise<void>} Resolves when the device has been removed and is no longer ready.
|
|
921
|
-
*/
|
|
922
566
|
export async function deleteDevice(owner, device, pause = 10) {
|
|
923
567
|
expect(owner).toBeDefined();
|
|
924
568
|
expect(device).toBeDefined();
|
|
925
569
|
expect(owner.lifecycle.isReady).toBeTruthy();
|
|
926
570
|
expect(owner.construction.status).toBe(Lifecycle.Status.Active);
|
|
927
571
|
expect(owner.lifecycle.isPartsReady).toBeTruthy();
|
|
928
|
-
// istanbul ignore next
|
|
929
572
|
try {
|
|
930
573
|
await device.delete();
|
|
931
574
|
}
|
|
@@ -945,4 +588,3 @@ export async function deleteDevice(owner, device, pause = 10) {
|
|
|
945
588
|
await flushAsync(undefined, undefined, pause);
|
|
946
589
|
return true;
|
|
947
590
|
}
|
|
948
|
-
//# sourceMappingURL=jestHelpers.js.map
|