matterbridge 3.4.2 → 3.4.3-dev-20251207-3ce5a0e
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 +25 -0
- package/README-SERVICE-LOCAL.md +3 -3
- package/README-SERVICE-OPT.md +3 -5
- package/README.md +8 -14
- package/dist/broadcastServer.js +0 -119
- package/dist/broadcastServerTypes.js +0 -24
- package/dist/cli.js +3 -97
- package/dist/cliEmitter.js +0 -37
- package/dist/cliHistory.js +0 -38
- package/dist/clusters/export.js +0 -2
- package/dist/deviceManager.js +1 -113
- package/dist/devices/airConditioner.js +0 -57
- package/dist/devices/batteryStorage.js +1 -48
- package/dist/devices/cooktop.js +0 -56
- package/dist/devices/dishwasher.js +0 -57
- package/dist/devices/evse.js +10 -74
- package/dist/devices/export.js +0 -5
- package/dist/devices/extractorHood.js +0 -43
- package/dist/devices/heatPump.js +2 -50
- package/dist/devices/laundryDryer.js +3 -62
- package/dist/devices/laundryWasher.js +4 -70
- package/dist/devices/microwaveOven.js +5 -88
- package/dist/devices/oven.js +0 -85
- package/dist/devices/refrigerator.js +0 -102
- package/dist/devices/roboticVacuumCleaner.js +9 -100
- package/dist/devices/solarPower.js +0 -38
- package/dist/devices/speaker.js +0 -84
- package/dist/devices/temperatureControl.js +3 -24
- package/dist/devices/waterHeater.js +2 -82
- package/dist/dgram/coap.js +13 -126
- package/dist/dgram/dgram.js +2 -114
- package/dist/dgram/mb_coap.js +3 -41
- package/dist/dgram/mb_mdns.js +15 -80
- package/dist/dgram/mdns.js +137 -299
- package/dist/dgram/multicast.js +1 -62
- package/dist/dgram/unicast.js +0 -54
- package/dist/frontend.js +35 -455
- package/dist/frontendTypes.js +0 -45
- package/dist/helpers.js +0 -53
- package/dist/index.js +0 -25
- package/dist/jestutils/export.js +0 -1
- package/dist/jestutils/jestHelpers.js +14 -371
- package/dist/logger/export.js +0 -1
- package/dist/matter/behaviors.js +0 -2
- package/dist/matter/clusters.js +0 -2
- package/dist/matter/devices.js +0 -2
- package/dist/matter/endpoints.js +0 -2
- package/dist/matter/export.js +0 -3
- package/dist/matter/types.js +0 -3
- package/dist/matterNode.js +8 -369
- package/dist/matterbridge.js +54 -817
- package/dist/matterbridgeAccessoryPlatform.js +0 -38
- package/dist/matterbridgeBehaviors.js +5 -68
- package/dist/matterbridgeDeviceTypes.js +14 -635
- package/dist/matterbridgeDynamicPlatform.js +0 -38
- package/dist/matterbridgeEndpoint.js +53 -1444
- package/dist/matterbridgeEndpointHelpers.js +20 -483
- package/dist/matterbridgeEndpointTypes.js +0 -25
- package/dist/matterbridgePlatform.js +1 -451
- package/dist/matterbridgeTypes.js +0 -26
- package/dist/pluginManager.js +5 -341
- package/dist/shelly.js +7 -178
- package/dist/storage/export.js +0 -1
- package/dist/update.js +1 -93
- package/dist/utils/colorUtils.js +2 -97
- package/dist/utils/commandLine.js +0 -60
- package/dist/utils/copyDirectory.js +0 -37
- package/dist/utils/createDirectory.js +0 -33
- package/dist/utils/createZip.js +2 -47
- package/dist/utils/deepCopy.js +0 -39
- package/dist/utils/deepEqual.js +1 -72
- package/dist/utils/error.js +0 -42
- package/dist/utils/export.js +0 -1
- package/dist/utils/format.js +0 -49
- package/dist/utils/hex.js +0 -124
- package/dist/utils/inspector.js +1 -69
- package/dist/utils/isvalid.js +0 -101
- package/dist/utils/network.js +5 -96
- package/dist/utils/spawn.js +1 -71
- package/dist/utils/tracker.js +1 -64
- package/dist/utils/wait.js +8 -60
- package/dist/workerGlobalPrefix.js +5 -37
- package/dist/workerTypes.js +0 -24
- package/dist/workers.js +4 -68
- package/frontend/build/assets/index.js +4 -4
- package/frontend/build/assets/vendor_mui.js +1 -1
- package/frontend/package.json +1 -1
- package/npm-shrinkwrap.json +8 -7
- package/package.json +3 -4
- package/scripts/marked.mjs +132 -0
- package/scripts/markedFooter.html +42 -0
- package/scripts/markedHeader.html +78 -0
- package/dist/broadcastServer.d.ts +0 -144
- package/dist/broadcastServer.d.ts.map +0 -1
- package/dist/broadcastServer.js.map +0 -1
- package/dist/broadcastServerTypes.d.ts +0 -841
- package/dist/broadcastServerTypes.d.ts.map +0 -1
- package/dist/broadcastServerTypes.js.map +0 -1
- package/dist/cli.d.ts +0 -30
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/cliEmitter.d.ts +0 -50
- package/dist/cliEmitter.d.ts.map +0 -1
- package/dist/cliEmitter.js.map +0 -1
- package/dist/cliHistory.d.ts +0 -48
- package/dist/cliHistory.d.ts.map +0 -1
- package/dist/cliHistory.js.map +0 -1
- package/dist/clusters/export.d.ts +0 -2
- package/dist/clusters/export.d.ts.map +0 -1
- package/dist/clusters/export.js.map +0 -1
- package/dist/deviceManager.d.ts +0 -135
- package/dist/deviceManager.d.ts.map +0 -1
- package/dist/deviceManager.js.map +0 -1
- package/dist/devices/airConditioner.d.ts +0 -98
- package/dist/devices/airConditioner.d.ts.map +0 -1
- package/dist/devices/airConditioner.js.map +0 -1
- package/dist/devices/batteryStorage.d.ts +0 -48
- package/dist/devices/batteryStorage.d.ts.map +0 -1
- package/dist/devices/batteryStorage.js.map +0 -1
- package/dist/devices/cooktop.d.ts +0 -61
- package/dist/devices/cooktop.d.ts.map +0 -1
- package/dist/devices/cooktop.js.map +0 -1
- package/dist/devices/dishwasher.d.ts +0 -71
- package/dist/devices/dishwasher.d.ts.map +0 -1
- package/dist/devices/dishwasher.js.map +0 -1
- package/dist/devices/evse.d.ts +0 -76
- package/dist/devices/evse.d.ts.map +0 -1
- package/dist/devices/evse.js.map +0 -1
- package/dist/devices/export.d.ts +0 -17
- package/dist/devices/export.d.ts.map +0 -1
- package/dist/devices/export.js.map +0 -1
- package/dist/devices/extractorHood.d.ts +0 -46
- package/dist/devices/extractorHood.d.ts.map +0 -1
- package/dist/devices/extractorHood.js.map +0 -1
- package/dist/devices/heatPump.d.ts +0 -47
- package/dist/devices/heatPump.d.ts.map +0 -1
- package/dist/devices/heatPump.js.map +0 -1
- package/dist/devices/laundryDryer.d.ts +0 -67
- package/dist/devices/laundryDryer.d.ts.map +0 -1
- package/dist/devices/laundryDryer.js.map +0 -1
- package/dist/devices/laundryWasher.d.ts +0 -81
- package/dist/devices/laundryWasher.d.ts.map +0 -1
- package/dist/devices/laundryWasher.js.map +0 -1
- package/dist/devices/microwaveOven.d.ts +0 -168
- package/dist/devices/microwaveOven.d.ts.map +0 -1
- package/dist/devices/microwaveOven.js.map +0 -1
- package/dist/devices/oven.d.ts +0 -105
- package/dist/devices/oven.d.ts.map +0 -1
- package/dist/devices/oven.js.map +0 -1
- package/dist/devices/refrigerator.d.ts +0 -118
- package/dist/devices/refrigerator.d.ts.map +0 -1
- package/dist/devices/refrigerator.js.map +0 -1
- package/dist/devices/roboticVacuumCleaner.d.ts +0 -112
- package/dist/devices/roboticVacuumCleaner.d.ts.map +0 -1
- package/dist/devices/roboticVacuumCleaner.js.map +0 -1
- package/dist/devices/solarPower.d.ts +0 -40
- package/dist/devices/solarPower.d.ts.map +0 -1
- package/dist/devices/solarPower.js.map +0 -1
- package/dist/devices/speaker.d.ts +0 -87
- package/dist/devices/speaker.d.ts.map +0 -1
- package/dist/devices/speaker.js.map +0 -1
- package/dist/devices/temperatureControl.d.ts +0 -166
- package/dist/devices/temperatureControl.d.ts.map +0 -1
- package/dist/devices/temperatureControl.js.map +0 -1
- package/dist/devices/waterHeater.d.ts +0 -111
- 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.map +0 -1
- package/dist/dgram/dgram.d.ts +0 -141
- package/dist/dgram/dgram.d.ts.map +0 -1
- 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 -290
- package/dist/dgram/mdns.d.ts.map +0 -1
- 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.map +0 -1
- package/dist/dgram/unicast.d.ts +0 -56
- package/dist/dgram/unicast.d.ts.map +0 -1
- package/dist/dgram/unicast.js.map +0 -1
- package/dist/frontend.d.ts +0 -238
- package/dist/frontend.d.ts.map +0 -1
- package/dist/frontend.js.map +0 -1
- package/dist/frontendTypes.d.ts +0 -529
- package/dist/frontendTypes.d.ts.map +0 -1
- package/dist/frontendTypes.js.map +0 -1
- package/dist/helpers.d.ts +0 -48
- package/dist/helpers.d.ts.map +0 -1
- package/dist/helpers.js.map +0 -1
- package/dist/index.d.ts +0 -34
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/jestutils/export.d.ts +0 -2
- package/dist/jestutils/export.d.ts.map +0 -1
- package/dist/jestutils/export.js.map +0 -1
- package/dist/jestutils/jestHelpers.d.ts +0 -345
- package/dist/jestutils/jestHelpers.d.ts.map +0 -1
- package/dist/jestutils/jestHelpers.js.map +0 -1
- package/dist/logger/export.d.ts +0 -2
- package/dist/logger/export.d.ts.map +0 -1
- package/dist/logger/export.js.map +0 -1
- package/dist/matter/behaviors.d.ts +0 -2
- package/dist/matter/behaviors.d.ts.map +0 -1
- package/dist/matter/behaviors.js.map +0 -1
- package/dist/matter/clusters.d.ts +0 -2
- package/dist/matter/clusters.d.ts.map +0 -1
- package/dist/matter/clusters.js.map +0 -1
- package/dist/matter/devices.d.ts +0 -2
- package/dist/matter/devices.d.ts.map +0 -1
- package/dist/matter/devices.js.map +0 -1
- package/dist/matter/endpoints.d.ts +0 -2
- package/dist/matter/endpoints.d.ts.map +0 -1
- package/dist/matter/endpoints.js.map +0 -1
- package/dist/matter/export.d.ts +0 -5
- package/dist/matter/export.d.ts.map +0 -1
- package/dist/matter/export.js.map +0 -1
- package/dist/matter/types.d.ts +0 -3
- package/dist/matter/types.d.ts.map +0 -1
- package/dist/matter/types.js.map +0 -1
- package/dist/matterNode.d.ts +0 -342
- package/dist/matterNode.d.ts.map +0 -1
- package/dist/matterNode.js.map +0 -1
- package/dist/matterbridge.d.ts +0 -492
- package/dist/matterbridge.d.ts.map +0 -1
- package/dist/matterbridge.js.map +0 -1
- package/dist/matterbridgeAccessoryPlatform.d.ts +0 -41
- package/dist/matterbridgeAccessoryPlatform.d.ts.map +0 -1
- package/dist/matterbridgeAccessoryPlatform.js.map +0 -1
- package/dist/matterbridgeBehaviors.d.ts +0 -2404
- package/dist/matterbridgeBehaviors.d.ts.map +0 -1
- package/dist/matterbridgeBehaviors.js.map +0 -1
- package/dist/matterbridgeDeviceTypes.d.ts +0 -698
- package/dist/matterbridgeDeviceTypes.d.ts.map +0 -1
- package/dist/matterbridgeDeviceTypes.js.map +0 -1
- package/dist/matterbridgeDynamicPlatform.d.ts +0 -41
- package/dist/matterbridgeDynamicPlatform.d.ts.map +0 -1
- package/dist/matterbridgeDynamicPlatform.js.map +0 -1
- package/dist/matterbridgeEndpoint.d.ts +0 -1507
- package/dist/matterbridgeEndpoint.d.ts.map +0 -1
- package/dist/matterbridgeEndpoint.js.map +0 -1
- package/dist/matterbridgeEndpointHelpers.d.ts +0 -787
- package/dist/matterbridgeEndpointHelpers.d.ts.map +0 -1
- package/dist/matterbridgeEndpointHelpers.js.map +0 -1
- package/dist/matterbridgeEndpointTypes.d.ts +0 -166
- package/dist/matterbridgeEndpointTypes.d.ts.map +0 -1
- package/dist/matterbridgeEndpointTypes.js.map +0 -1
- package/dist/matterbridgePlatform.d.ts +0 -539
- package/dist/matterbridgePlatform.d.ts.map +0 -1
- package/dist/matterbridgePlatform.js.map +0 -1
- package/dist/matterbridgeTypes.d.ts +0 -251
- package/dist/matterbridgeTypes.d.ts.map +0 -1
- package/dist/matterbridgeTypes.js.map +0 -1
- package/dist/pluginManager.d.ts +0 -372
- package/dist/pluginManager.d.ts.map +0 -1
- package/dist/pluginManager.js.map +0 -1
- package/dist/shelly.d.ts +0 -181
- package/dist/shelly.d.ts.map +0 -1
- package/dist/shelly.js.map +0 -1
- package/dist/storage/export.d.ts +0 -2
- package/dist/storage/export.d.ts.map +0 -1
- package/dist/storage/export.js.map +0 -1
- package/dist/update.d.ts +0 -84
- 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.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.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.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.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.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.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.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.map +0 -1
- package/dist/utils/export.d.ts +0 -13
- 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.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.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.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.map +0 -1
- package/dist/utils/network.d.ts +0 -111
- package/dist/utils/network.d.ts.map +0 -1
- 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.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.map +0 -1
- package/dist/workerGlobalPrefix.d.ts +0 -25
- package/dist/workerGlobalPrefix.d.ts.map +0 -1
- package/dist/workerGlobalPrefix.js.map +0 -1
- package/dist/workerTypes.d.ts +0 -52
- package/dist/workerTypes.d.ts.map +0 -1
- package/dist/workerTypes.js.map +0 -1
- package/dist/workers.d.ts +0 -69
- 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/main/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,41 +157,18 @@ 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
165
|
matterbridge = await Matterbridge.loadInstance(true);
|
|
254
166
|
expect(matterbridge).toBeDefined();
|
|
255
167
|
expect(matterbridge.profile).toBeUndefined();
|
|
256
168
|
expect(matterbridge.bridgeMode).toBe(bridgeMode);
|
|
257
|
-
// Get the frontend, plugins and devices
|
|
258
169
|
frontend = matterbridge.frontend;
|
|
259
170
|
plugins = matterbridge.plugins;
|
|
260
171
|
devices = matterbridge.devices;
|
|
261
|
-
// @ts-expect-error - access to private member for testing
|
|
262
172
|
expect(matterbridge.initialized).toBeTruthy();
|
|
263
173
|
expect(matterbridge.log).toBeDefined();
|
|
264
174
|
expect(matterbridge.rootDirectory).toBe(path.resolve('./'));
|
|
@@ -271,15 +181,10 @@ export async function startMatterbridge(bridgeMode = 'bridge', frontendPort = 82
|
|
|
271
181
|
expect(devices).toBeDefined();
|
|
272
182
|
expect(devices.size).toBe(devicesSize);
|
|
273
183
|
expect(frontend).toBeDefined();
|
|
274
|
-
// @ts-expect-error - access to private member for testing
|
|
275
184
|
expect(frontend.listening).toBeTruthy();
|
|
276
|
-
// @ts-expect-error - access to private member for testing
|
|
277
185
|
expect(frontend.httpServer).toBeDefined();
|
|
278
|
-
// @ts-expect-error - access to private member for testing
|
|
279
186
|
expect(frontend.httpsServer).toBeUndefined();
|
|
280
|
-
// @ts-expect-error - access to private member for testing
|
|
281
187
|
expect(frontend.expressApp).toBeDefined();
|
|
282
|
-
// @ts-expect-error - access to private member for testing
|
|
283
188
|
expect(frontend.webSocketServer).toBeDefined();
|
|
284
189
|
expect(matterbridge.nodeStorage).toBeDefined();
|
|
285
190
|
expect(matterbridge.nodeContext).toBeDefined();
|
|
@@ -317,51 +222,25 @@ export async function startMatterbridge(bridgeMode = 'bridge', frontendPort = 82
|
|
|
317
222
|
});
|
|
318
223
|
});
|
|
319
224
|
}
|
|
320
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("info"
|
|
225
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("info", `The frontend http server is listening on ${UNDERLINE}http://${matterbridge.systemInformation.ipv4Address}:${frontendPort}${UNDERLINEOFF}${rs}`);
|
|
321
226
|
if (bridgeMode === 'bridge') {
|
|
322
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("notice"
|
|
323
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("notice"
|
|
324
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("debug"
|
|
325
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("debug"
|
|
326
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("notice"
|
|
227
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("notice", `Starting Matterbridge server node`);
|
|
228
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("notice", `Server node for Matterbridge is online`);
|
|
229
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("debug", `Starting start matter interval in bridge mode...`);
|
|
230
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("debug", `Cleared startMatterInterval interval in bridge mode`);
|
|
231
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("notice", `Matterbridge bridge started successfully`);
|
|
327
232
|
}
|
|
328
233
|
else if (bridgeMode === 'childbridge') {
|
|
329
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("debug"
|
|
330
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("debug"
|
|
331
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("notice"
|
|
234
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("debug", `Starting start matter interval in childbridge mode...`);
|
|
235
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("debug", `Cleared startMatterInterval interval in childbridge mode`);
|
|
236
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("notice", `Matterbridge childbridge started successfully`);
|
|
332
237
|
}
|
|
333
238
|
return matterbridge;
|
|
334
239
|
}
|
|
335
|
-
/**
|
|
336
|
-
* Stop the fully initialized Matterbridge instance.
|
|
337
|
-
*
|
|
338
|
-
* @param {cleanupPause} cleanupPause The pause duration before cleanup. Default is 10 ms.
|
|
339
|
-
* @param {destroyPause} destroyPause The pause duration before destruction. Default is 250 ms.
|
|
340
|
-
*
|
|
341
|
-
* @example
|
|
342
|
-
* ```typescript
|
|
343
|
-
* // Stop the fully initialized Matterbridge instance.
|
|
344
|
-
* await stopMatterbridge();
|
|
345
|
-
* ```
|
|
346
|
-
*/
|
|
347
240
|
export async function stopMatterbridge(cleanupPause = 10, destroyPause = 250) {
|
|
348
241
|
await destroyMatterbridgeEnvironment(cleanupPause, destroyPause);
|
|
349
242
|
}
|
|
350
|
-
/**
|
|
351
|
-
* Create a Matterbridge instance for testing without initializing it.
|
|
352
|
-
*
|
|
353
|
-
* @param {string} name - Name for the environment (jest/name).
|
|
354
|
-
* @returns {Promise<Matterbridge>} The Matterbridge instance.
|
|
355
|
-
*
|
|
356
|
-
* @example
|
|
357
|
-
* ```typescript
|
|
358
|
-
* // Create Matterbridge environment
|
|
359
|
-
* await createMatterbridgeEnvironment(NAME);
|
|
360
|
-
* await startMatterbridgeEnvironment(MATTER_PORT);
|
|
361
|
-
* ```
|
|
362
|
-
*/
|
|
363
243
|
export async function createMatterbridgeEnvironment(name) {
|
|
364
|
-
// Create a MatterbridgeEdge instance
|
|
365
244
|
matterbridge = await Matterbridge.loadInstance(false);
|
|
366
245
|
expect(matterbridge).toBeDefined();
|
|
367
246
|
expect(matterbridge).toBeInstanceOf(Matterbridge);
|
|
@@ -372,52 +251,28 @@ export async function createMatterbridgeEnvironment(name) {
|
|
|
372
251
|
matterbridge.matterbridgeDirectory = path.join('jest', name, '.matterbridge');
|
|
373
252
|
matterbridge.matterbridgePluginDirectory = path.join('jest', name, 'Matterbridge');
|
|
374
253
|
matterbridge.matterbridgeCertDirectory = path.join('jest', name, '.mattercert');
|
|
375
|
-
matterbridge.log.logLevel = "debug"
|
|
376
|
-
log = new AnsiLogger({ logName: name, logTimestampFormat: 4
|
|
377
|
-
// Get the frontend, plugins and devices
|
|
254
|
+
matterbridge.log.logLevel = "debug";
|
|
255
|
+
log = new AnsiLogger({ logName: name, logTimestampFormat: 4, logLevel: "debug" });
|
|
378
256
|
frontend = matterbridge.frontend;
|
|
379
257
|
plugins = matterbridge.plugins;
|
|
380
258
|
devices = matterbridge.devices;
|
|
381
|
-
// Setup matter environment
|
|
382
|
-
// @ts-expect-error - access to private member for testing
|
|
383
259
|
matterbridge.environment = createTestEnvironment(name);
|
|
384
|
-
// @ts-expect-error - access to private member for testing
|
|
385
260
|
expect(matterbridge.environment).toBeDefined();
|
|
386
|
-
// @ts-expect-error - access to private member for testing
|
|
387
261
|
expect(matterbridge.environment).toBeInstanceOf(Environment);
|
|
388
262
|
return matterbridge;
|
|
389
263
|
}
|
|
390
|
-
/**
|
|
391
|
-
* Start the matterbridge environment.
|
|
392
|
-
* Only node storage, matter storage and the server and aggregator nodes are started.
|
|
393
|
-
*
|
|
394
|
-
* @param {number} port The matter server port.
|
|
395
|
-
* @returns {Promise<[ServerNode<ServerNode.RootEndpoint>, Endpoint<AggregatorEndpoint>]>} The started server and aggregator.
|
|
396
|
-
*
|
|
397
|
-
* @example
|
|
398
|
-
* ```typescript
|
|
399
|
-
* // Create Matterbridge environment
|
|
400
|
-
* await createMatterbridgeEnvironment(NAME);
|
|
401
|
-
* await startMatterbridgeEnvironment(MATTER_PORT);
|
|
402
|
-
* ```
|
|
403
|
-
*/
|
|
404
264
|
export async function startMatterbridgeEnvironment(port = 5540) {
|
|
405
|
-
// Create the node storage
|
|
406
265
|
matterbridge.nodeStorage = new NodeStorageManager({ dir: path.join(matterbridge.matterbridgeDirectory, NODE_STORAGE_DIR), writeQueue: false, expiredInterval: undefined, logging: false });
|
|
407
266
|
matterbridge.nodeContext = await matterbridge.nodeStorage.createStorage('matterbridge');
|
|
408
|
-
// Create the matter storage
|
|
409
|
-
// @ts-expect-error - access to private member for testing
|
|
410
267
|
await matterbridge.startMatterStorage();
|
|
411
268
|
expect(matterbridge.matterStorageService).toBeDefined();
|
|
412
269
|
expect(matterbridge.matterStorageManager).toBeDefined();
|
|
413
270
|
expect(matterbridge.matterbridgeContext).toBeDefined();
|
|
414
|
-
// @ts-expect-error - access to private member for testing
|
|
415
271
|
server = await matterbridge.createServerNode(matterbridge.matterbridgeContext, port);
|
|
416
272
|
expect(server).toBeDefined();
|
|
417
273
|
expect(server).toBeDefined();
|
|
418
274
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
419
275
|
matterbridge.serverNode = server;
|
|
420
|
-
// @ts-expect-error - access to private member for testing
|
|
421
276
|
aggregator = await matterbridge.createAggregatorNode(matterbridge.matterbridgeContext);
|
|
422
277
|
expect(aggregator).toBeDefined();
|
|
423
278
|
matterbridge.aggregatorNode = aggregator;
|
|
@@ -425,7 +280,6 @@ export async function startMatterbridgeEnvironment(port = 5540) {
|
|
|
425
280
|
expect(server.parts.has(aggregator.id)).toBeTruthy();
|
|
426
281
|
expect(server.parts.has(aggregator)).toBeTruthy();
|
|
427
282
|
expect(aggregator.lifecycle.isReady).toBeTruthy();
|
|
428
|
-
// Wait for the server to be online
|
|
429
283
|
expect(server.lifecycle.isOnline).toBeFalsy();
|
|
430
284
|
await new Promise((resolve) => {
|
|
431
285
|
server.lifecycle.online.on(async () => {
|
|
@@ -433,7 +287,6 @@ export async function startMatterbridgeEnvironment(port = 5540) {
|
|
|
433
287
|
});
|
|
434
288
|
server.start();
|
|
435
289
|
});
|
|
436
|
-
// Check if the server is online
|
|
437
290
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
438
291
|
expect(server.lifecycle.isOnline).toBeTruthy();
|
|
439
292
|
expect(server.lifecycle.isCommissioned).toBeFalsy();
|
|
@@ -445,27 +298,11 @@ export async function startMatterbridgeEnvironment(port = 5540) {
|
|
|
445
298
|
expect(aggregator.lifecycle.isPartsReady).toBeTruthy();
|
|
446
299
|
expect(aggregator.lifecycle.hasId).toBeTruthy();
|
|
447
300
|
expect(aggregator.lifecycle.hasNumber).toBeTruthy();
|
|
448
|
-
// Ensure the queue is empty and pause
|
|
449
301
|
await flushAsync();
|
|
450
302
|
return [server, aggregator];
|
|
451
303
|
}
|
|
452
|
-
/**
|
|
453
|
-
* Add a matterbridge platform for testing.
|
|
454
|
-
*
|
|
455
|
-
* @param {MatterbridgePlatform} platform The platform to add.
|
|
456
|
-
* @param {string} [name] Optional name of the platform.
|
|
457
|
-
*
|
|
458
|
-
* @example
|
|
459
|
-
* ```typescript
|
|
460
|
-
* platform = new Platform(matterbridge, log, config);
|
|
461
|
-
* // Add the platform to the Matterbridge environment
|
|
462
|
-
* addMatterbridgePlatform(platform);
|
|
463
|
-
* ```
|
|
464
|
-
*/
|
|
465
304
|
export function addMatterbridgePlatform(platform, name) {
|
|
466
305
|
expect(platform).toBeDefined();
|
|
467
|
-
// Setup the platform MatterNode helpers
|
|
468
|
-
// @ts-expect-error - setMatterNode is intentionally private
|
|
469
306
|
platform.setMatterNode?.(matterbridge.addBridgedEndpoint.bind(matterbridge), matterbridge.removeBridgedEndpoint.bind(matterbridge), matterbridge.removeAllBridgedEndpoints.bind(matterbridge), matterbridge.addVirtualEndpoint.bind(matterbridge));
|
|
470
307
|
if (name)
|
|
471
308
|
platform.config.name = name;
|
|
@@ -476,7 +313,6 @@ export function addMatterbridgePlatform(platform, name) {
|
|
|
476
313
|
expect(platform.version).toBeDefined();
|
|
477
314
|
expect(platform.config.debug).toBeDefined();
|
|
478
315
|
expect(platform.config.unregisterOnShutdown).toBeDefined();
|
|
479
|
-
// @ts-expect-error accessing private member for testing
|
|
480
316
|
matterbridge.plugins._plugins.set(platform.config.name, {
|
|
481
317
|
name: platform.config.name,
|
|
482
318
|
path: './',
|
|
@@ -488,152 +324,66 @@ export function addMatterbridgePlatform(platform, name) {
|
|
|
488
324
|
});
|
|
489
325
|
platform['name'] = platform.config.name;
|
|
490
326
|
}
|
|
491
|
-
/**
|
|
492
|
-
* Stop the matterbridge environment
|
|
493
|
-
*
|
|
494
|
-
* @example
|
|
495
|
-
* ```typescript
|
|
496
|
-
* // Destroy Matterbridge environment
|
|
497
|
-
* await stopMatterbridgeEnvironment();
|
|
498
|
-
* await destroyMatterbridgeEnvironment();
|
|
499
|
-
* ```
|
|
500
|
-
*/
|
|
501
327
|
export async function stopMatterbridgeEnvironment() {
|
|
502
328
|
expect(matterbridge).toBeDefined();
|
|
503
329
|
expect(server).toBeDefined();
|
|
504
330
|
expect(aggregator).toBeDefined();
|
|
505
|
-
// Flush any pending endpoint number persistence
|
|
506
331
|
await flushAllEndpointNumberPersistence(server);
|
|
507
|
-
// Ensure all endpoint numbers are persisted
|
|
508
332
|
await assertAllEndpointNumbersPersisted(server);
|
|
509
|
-
// Close the server node
|
|
510
333
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
511
334
|
expect(server.lifecycle.isOnline).toBeTruthy();
|
|
512
335
|
await server.close();
|
|
513
336
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
514
337
|
expect(server.lifecycle.isOnline).toBeFalsy();
|
|
515
|
-
// Stop the matter storage
|
|
516
|
-
// @ts-expect-error - access to private member for testing
|
|
517
338
|
await matterbridge.stopMatterStorage();
|
|
518
339
|
expect(matterbridge.matterStorageService).not.toBeDefined();
|
|
519
340
|
expect(matterbridge.matterStorageManager).not.toBeDefined();
|
|
520
341
|
expect(matterbridge.matterbridgeContext).not.toBeDefined();
|
|
521
|
-
// Stop the node storage
|
|
522
342
|
await matterbridge.nodeContext?.close();
|
|
523
343
|
matterbridge.nodeContext = undefined;
|
|
524
344
|
await matterbridge.nodeStorage?.close();
|
|
525
345
|
matterbridge.nodeStorage = undefined;
|
|
526
|
-
// Ensure the queue is empty and pause
|
|
527
346
|
await flushAsync();
|
|
528
347
|
}
|
|
529
|
-
/**
|
|
530
|
-
* Destroy the matterbridge environment
|
|
531
|
-
*
|
|
532
|
-
* @param {number} cleanupPause The timeout for the destroy operation (default 10ms).
|
|
533
|
-
* @param {number} destroyPause The pause duration after cleanup before destroying the instance (default 250ms).
|
|
534
|
-
*
|
|
535
|
-
* @example
|
|
536
|
-
* ```typescript
|
|
537
|
-
* // Destroy Matterbridge environment
|
|
538
|
-
* await stopMatterbridgeEnvironment();
|
|
539
|
-
* await destroyMatterbridgeEnvironment();
|
|
540
|
-
* ```
|
|
541
|
-
*/
|
|
542
348
|
export async function destroyMatterbridgeEnvironment(cleanupPause = 10, destroyPause = 250) {
|
|
543
|
-
// Destroy a matterbridge instance
|
|
544
349
|
await destroyInstance(matterbridge, cleanupPause, destroyPause);
|
|
545
|
-
// Close the mDNS service
|
|
546
350
|
await closeMdnsInstance(matterbridge);
|
|
547
|
-
// Reset the singleton instance
|
|
548
|
-
// @ts-expect-error - accessing private member for testing
|
|
549
351
|
Matterbridge.instance = undefined;
|
|
550
352
|
}
|
|
551
|
-
/**
|
|
552
|
-
* Destroy a matterbridge instance
|
|
553
|
-
*
|
|
554
|
-
* @param {Matterbridge} matterbridge The matterbridge instance to destroy.
|
|
555
|
-
* @param {number} cleanupPause The pause duration to wait for the cleanup to complete in milliseconds (default 10ms).
|
|
556
|
-
* @param {number} destroyPause The pause duration to wait after cleanup before destroying the instance in milliseconds (default 250ms).
|
|
557
|
-
*/
|
|
558
353
|
export async function destroyInstance(matterbridge, cleanupPause = 10, destroyPause = 250) {
|
|
559
|
-
// Cleanup the Matterbridge instance
|
|
560
|
-
// @ts-expect-error - accessing private member for testing
|
|
561
354
|
await matterbridge.cleanup('destroying instance...', false, cleanupPause);
|
|
562
|
-
// Pause before destroying the instance
|
|
563
355
|
if (destroyPause > 0)
|
|
564
356
|
await flushAsync(undefined, undefined, destroyPause);
|
|
565
357
|
}
|
|
566
|
-
/**
|
|
567
|
-
* Close the mDNS instance in the matterbridge environment.
|
|
568
|
-
*
|
|
569
|
-
* @param {Matterbridge} matterbridge The matterbridge instance.
|
|
570
|
-
* @returns {Promise<void>} A promise that resolves when the mDNS instance is closed.
|
|
571
|
-
*/
|
|
572
358
|
export async function closeMdnsInstance(matterbridge) {
|
|
573
|
-
// TODO: matter.js 0.16.0 - provide close method to close the mDNS service
|
|
574
|
-
// @ts-expect-error - accessing private member for testing
|
|
575
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
576
359
|
const mdns = matterbridge.environment.get(MdnsService);
|
|
577
360
|
if (mdns && mdns[Symbol.asyncDispose] && typeof mdns[Symbol.asyncDispose] === 'function')
|
|
578
361
|
await mdns[Symbol.asyncDispose]();
|
|
579
362
|
if (mdns && mdns.close && typeof mdns.close === 'function')
|
|
580
363
|
await mdns.close();
|
|
581
364
|
}
|
|
582
|
-
/**
|
|
583
|
-
* Create a matter test environment for testing:
|
|
584
|
-
* - it will remove any existing home directory
|
|
585
|
-
* - setup the matter environment with name, debug logging and ANSI format
|
|
586
|
-
* - setup the mDNS service in the environment
|
|
587
|
-
*
|
|
588
|
-
* @param {string} name - Name for the environment (jest/name).
|
|
589
|
-
* @returns {Environment} - The default matter environment.
|
|
590
|
-
*/
|
|
591
365
|
export function createTestEnvironment(name) {
|
|
592
366
|
expect(name).toBeDefined();
|
|
593
367
|
expect(typeof name).toBe('string');
|
|
594
|
-
expect(name.length).toBeGreaterThanOrEqual(4);
|
|
595
|
-
|
|
596
|
-
log = new AnsiLogger({ logName: name, logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: "debug" /* LogLevel.DEBUG */ });
|
|
597
|
-
// Cleanup any existing home directory
|
|
368
|
+
expect(name.length).toBeGreaterThanOrEqual(4);
|
|
369
|
+
log = new AnsiLogger({ logName: name, logTimestampFormat: 4, logLevel: "debug" });
|
|
598
370
|
rmSync(path.join('jest', name), { recursive: true, force: true });
|
|
599
|
-
// Setup the matter environment
|
|
600
371
|
environment = Environment.default;
|
|
601
372
|
environment.vars.set('log.level', MatterLogLevel.DEBUG);
|
|
602
373
|
environment.vars.set('log.format', MatterLogFormat.ANSI);
|
|
603
374
|
environment.vars.set('path.root', path.join('jest', name, '.matterbridge', MATTER_STORAGE_NAME));
|
|
604
375
|
environment.vars.set('runtime.signals', false);
|
|
605
376
|
environment.vars.set('runtime.exitcode', false);
|
|
606
|
-
// Setup the mDNS service in the environment
|
|
607
377
|
new MdnsService(environment);
|
|
608
|
-
// await environment.get(MdnsService)?.construction.ready;
|
|
609
378
|
return environment;
|
|
610
379
|
}
|
|
611
|
-
/**
|
|
612
|
-
* Destroy the matter test environment by closing the mDNS service.
|
|
613
|
-
*
|
|
614
|
-
* @returns {Promise<void>} A promise that resolves when the test environment is destroyed.
|
|
615
|
-
*/
|
|
616
380
|
export async function destroyTestEnvironment() {
|
|
617
|
-
// stop the mDNS service
|
|
618
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
619
381
|
const mdns = environment.get(MdnsService);
|
|
620
382
|
if (mdns && typeof mdns[Symbol.asyncDispose] === 'function')
|
|
621
383
|
await mdns[Symbol.asyncDispose]();
|
|
622
384
|
if (mdns && typeof mdns.close === 'function')
|
|
623
385
|
await mdns.close();
|
|
624
386
|
}
|
|
625
|
-
/**
|
|
626
|
-
* Advance the Node.js event loop deterministically to allow chained asynchronous work (Promises scheduled in
|
|
627
|
-
* microtasks and follow‑up macrotasks) to complete inside tests without adding arbitrary long timeouts.
|
|
628
|
-
*
|
|
629
|
-
* NOTE: This does not guarantee OS level network IO completion—only JavaScript task queue progression inside the
|
|
630
|
-
* current process.
|
|
631
|
-
*
|
|
632
|
-
* @param {number} ticks Number of macrotask (setImmediate) turns to yield (default 3).
|
|
633
|
-
* @param {number} microTurns Number of microtask drains (Promise.resolve chains) after macrotask yielding (default 10).
|
|
634
|
-
* @param {number} pause Final timer delay in ms; set 0 to disable (default 250ms).
|
|
635
|
-
* @returns {Promise<void>} Resolves after the requested event loop advancement has completed.
|
|
636
|
-
*/
|
|
637
387
|
export async function flushAsync(ticks = 3, microTurns = 10, pause = 250) {
|
|
638
388
|
for (let i = 0; i < ticks; i++)
|
|
639
389
|
await new Promise((resolve) => setImmediate(resolve));
|
|
@@ -642,33 +392,16 @@ export async function flushAsync(ticks = 3, microTurns = 10, pause = 250) {
|
|
|
642
392
|
if (pause)
|
|
643
393
|
await new Promise((resolve) => setTimeout(resolve, pause));
|
|
644
394
|
}
|
|
645
|
-
/**
|
|
646
|
-
* Summarize live libuv handles/requests inside a process.
|
|
647
|
-
*
|
|
648
|
-
* @param {AnsiLogger} log - Logger to use for output
|
|
649
|
-
*
|
|
650
|
-
* @returns {number} - The total number of active handles and requests
|
|
651
|
-
*/
|
|
652
395
|
export function logKeepAlives(log) {
|
|
653
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
654
396
|
const handles = process._getActiveHandles?.() ?? [];
|
|
655
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
656
397
|
const requests = process._getActiveRequests?.() ?? [];
|
|
657
|
-
// istanbul ignore next
|
|
658
398
|
const fmtHandle = (h, i) => {
|
|
659
399
|
const ctor = h?.constructor?.name ?? 'Unknown';
|
|
660
|
-
// Timer-like?
|
|
661
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
662
400
|
const hasRef = typeof h?.hasRef === 'function' ? h.hasRef() : undefined;
|
|
663
|
-
// MessagePort?
|
|
664
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
665
401
|
const isPort = h?.constructor?.name?.includes('MessagePort');
|
|
666
|
-
// Socket/Server?
|
|
667
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
668
402
|
const fd = h?.fd ?? h?._handle?.fd;
|
|
669
403
|
return { i, type: ctor, hasRef, isPort, fd };
|
|
670
404
|
};
|
|
671
|
-
// istanbul ignore next
|
|
672
405
|
const fmtReq = (r, i) => {
|
|
673
406
|
const ctor = r?.constructor?.name ?? 'Unknown';
|
|
674
407
|
return { i, type: ctor };
|
|
@@ -677,7 +410,6 @@ export function logKeepAlives(log) {
|
|
|
677
410
|
handles: handles.map(fmtHandle),
|
|
678
411
|
requests: requests.map(fmtReq),
|
|
679
412
|
};
|
|
680
|
-
// istanbul ignore next if
|
|
681
413
|
if (summary.handles.length === 0 && summary.requests.length === 0) {
|
|
682
414
|
log?.debug('KeepAlive: no active handles or requests.');
|
|
683
415
|
}
|
|
@@ -689,19 +421,6 @@ export function logKeepAlives(log) {
|
|
|
689
421
|
}
|
|
690
422
|
return summary.handles.length + summary.requests.length;
|
|
691
423
|
}
|
|
692
|
-
/**
|
|
693
|
-
* Flush (await) the lazy endpoint number persistence mechanism used by matter.js.
|
|
694
|
-
*
|
|
695
|
-
* Background:
|
|
696
|
-
* assignNumber() batches persistence (store.saveNumber + updating __nextNumber__) via an internal promise (#numbersPersisted).
|
|
697
|
-
* Calling endpointStores.close() waits for the current batch only. If new endpoints were added in the same macrotask
|
|
698
|
-
* cycle additional micro/macro turns might be needed to ensure the batch started. We defensively yield macrotasks
|
|
699
|
-
* (setImmediate) and then await close() multiple rounds.
|
|
700
|
-
*
|
|
701
|
-
* @param {ServerNode} targetServer The server whose endpoint numbering persistence should be flushed.
|
|
702
|
-
* @param {number} rounds Number of macrotask + close cycles to run (2 is usually sufficient; 1 often works).
|
|
703
|
-
* @returns {Promise<void>} Resolves when pending number persistence batches have completed.
|
|
704
|
-
*/
|
|
705
424
|
export async function flushAllEndpointNumberPersistence(targetServer, rounds = 2) {
|
|
706
425
|
const nodeStore = targetServer.env.get(ServerNodeStore);
|
|
707
426
|
for (let i = 0; i < rounds; i++) {
|
|
@@ -709,12 +428,6 @@ export async function flushAllEndpointNumberPersistence(targetServer, rounds = 2
|
|
|
709
428
|
await nodeStore.endpointStores.close();
|
|
710
429
|
}
|
|
711
430
|
}
|
|
712
|
-
/**
|
|
713
|
-
* Collect all endpoints in the server endpoint tree (root -> descendants).
|
|
714
|
-
*
|
|
715
|
-
* @param {Endpoint} root Root endpoint (typically the ServerNode root endpoint cast as Endpoint).
|
|
716
|
-
* @returns {Endpoint[]} Flat array including the root and every descendant once.
|
|
717
|
-
*/
|
|
718
431
|
function collectAllEndpoints(root) {
|
|
719
432
|
const list = [];
|
|
720
433
|
const walk = (ep) => {
|
|
@@ -728,26 +441,14 @@ function collectAllEndpoints(root) {
|
|
|
728
441
|
walk(root);
|
|
729
442
|
return list;
|
|
730
443
|
}
|
|
731
|
-
/**
|
|
732
|
-
* Assert that every endpoint attached to the server has an assigned and (batch-)persisted endpoint number.
|
|
733
|
-
*
|
|
734
|
-
* This waits for any outstanding number persistence batch (endpointStores.close()), then traverses the endpoint
|
|
735
|
-
* graph and asserts:
|
|
736
|
-
* - Root endpoint: number is 0 (allowing undefined to coerce to 0 via nullish coalescing check).
|
|
737
|
-
* - All other endpoints: number > 0.
|
|
738
|
-
*
|
|
739
|
-
* @param {ServerNode} targetServer The server whose endpoint numbers are verified.
|
|
740
|
-
* @returns {Promise<void>} Resolves when assertions complete.
|
|
741
|
-
*/
|
|
742
444
|
export async function assertAllEndpointNumbersPersisted(targetServer) {
|
|
743
445
|
const nodeStore = targetServer.env.get(ServerNodeStore);
|
|
744
|
-
// Ensure any pending persistence finished (flush any in-flight batch promise)
|
|
745
446
|
await nodeStore.endpointStores.close();
|
|
746
447
|
const all = collectAllEndpoints(targetServer);
|
|
747
448
|
for (const ep of all) {
|
|
748
449
|
const store = nodeStore.storeForEndpoint(ep);
|
|
749
450
|
if (ep.maybeNumber === 0) {
|
|
750
|
-
expect(store.number ?? 0).toBe(0);
|
|
451
|
+
expect(store.number ?? 0).toBe(0);
|
|
751
452
|
}
|
|
752
453
|
else {
|
|
753
454
|
expect(store.number).toBeGreaterThan(0);
|
|
@@ -755,42 +456,23 @@ export async function assertAllEndpointNumbersPersisted(targetServer) {
|
|
|
755
456
|
}
|
|
756
457
|
return all.length;
|
|
757
458
|
}
|
|
758
|
-
/**
|
|
759
|
-
* Close the server node stores to flush any pending endpoint number persistence.
|
|
760
|
-
*
|
|
761
|
-
* @param {ServerNode} targetServer The server whose endpoint stores should be closed.
|
|
762
|
-
* @returns {Promise<void>} Resolves when the stores have been closed.
|
|
763
|
-
*/
|
|
764
459
|
export async function closeServerNodeStores(targetServer) {
|
|
765
|
-
// Close endpoint stores to avoid number persistence issues
|
|
766
460
|
if (!targetServer)
|
|
767
461
|
targetServer = server;
|
|
768
462
|
await targetServer?.env.get(ServerNodeStore)?.endpointStores.close();
|
|
769
463
|
}
|
|
770
|
-
/**
|
|
771
|
-
* Start a matter server node for testing.
|
|
772
|
-
*
|
|
773
|
-
* @param {string} name Name of the server (used for logging and product description).
|
|
774
|
-
* @param {number} port TCP port to listen on.
|
|
775
|
-
* @param {DeviceTypeId} deviceType Device type identifier for the server node.
|
|
776
|
-
* @returns {Promise<[ServerNode<ServerNode.RootEndpoint>, Endpoint<AggregatorEndpoint>]>} Resolves to an array containing the created ServerNode and its AggregatorNode.
|
|
777
|
-
*/
|
|
778
464
|
export async function startServerNode(name, port, deviceType = bridge.code) {
|
|
779
465
|
const { randomBytes } = await import('node:crypto');
|
|
780
466
|
const random = randomBytes(8).toString('hex');
|
|
781
|
-
// Create the server node
|
|
782
467
|
server = await ServerNode.create({
|
|
783
468
|
id: name + 'ServerNode',
|
|
784
|
-
// Provide the environment
|
|
785
469
|
environment,
|
|
786
|
-
// Provide Node announcement settings
|
|
787
470
|
productDescription: {
|
|
788
471
|
name: name + 'ServerNode',
|
|
789
472
|
deviceType: DeviceTypeId(deviceType),
|
|
790
473
|
vendorId: VendorId(0xfff1),
|
|
791
474
|
productId: 0x8000,
|
|
792
475
|
},
|
|
793
|
-
// Provide defaults for the BasicInformation cluster on the Root endpoint
|
|
794
476
|
basicInformation: {
|
|
795
477
|
vendorId: VendorId(0xfff1),
|
|
796
478
|
vendorName: 'Matterbridge',
|
|
@@ -803,39 +485,32 @@ export async function startServerNode(name, port, deviceType = bridge.code) {
|
|
|
803
485
|
serialNumber: 'SN' + random,
|
|
804
486
|
uniqueId: 'UI' + random,
|
|
805
487
|
},
|
|
806
|
-
// Provide Network relevant configuration like the port
|
|
807
488
|
network: {
|
|
808
489
|
listeningAddressIpv4: undefined,
|
|
809
490
|
listeningAddressIpv6: undefined,
|
|
810
491
|
port,
|
|
811
492
|
},
|
|
812
|
-
// Provide the certificate for the device
|
|
813
493
|
operationalCredentials: {
|
|
814
494
|
certification: undefined,
|
|
815
495
|
},
|
|
816
496
|
});
|
|
817
497
|
expect(server).toBeDefined();
|
|
818
498
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
819
|
-
// Create the aggregator node
|
|
820
499
|
aggregator = new Endpoint(AggregatorEndpoint, {
|
|
821
500
|
id: name + 'AggregatorNode',
|
|
822
501
|
});
|
|
823
502
|
expect(aggregator).toBeDefined();
|
|
824
|
-
// Add the aggregator to the server
|
|
825
503
|
await server.add(aggregator);
|
|
826
504
|
expect(server.parts.has(aggregator.id)).toBeTruthy();
|
|
827
505
|
expect(server.parts.has(aggregator)).toBeTruthy();
|
|
828
506
|
expect(aggregator.lifecycle.isReady).toBeTruthy();
|
|
829
|
-
// Run the server
|
|
830
507
|
expect(server.lifecycle.isOnline).toBeFalsy();
|
|
831
|
-
// Wait for the server to be online
|
|
832
508
|
await new Promise((resolve) => {
|
|
833
509
|
server.lifecycle.online.on(async () => {
|
|
834
510
|
resolve();
|
|
835
511
|
});
|
|
836
512
|
server.start();
|
|
837
513
|
});
|
|
838
|
-
// Check if the server is online
|
|
839
514
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
840
515
|
expect(server.lifecycle.isOnline).toBeTruthy();
|
|
841
516
|
expect(server.lifecycle.isCommissioned).toBeFalsy();
|
|
@@ -847,53 +522,31 @@ export async function startServerNode(name, port, deviceType = bridge.code) {
|
|
|
847
522
|
expect(aggregator.lifecycle.isPartsReady).toBeTruthy();
|
|
848
523
|
expect(aggregator.lifecycle.hasId).toBeTruthy();
|
|
849
524
|
expect(aggregator.lifecycle.hasNumber).toBeTruthy();
|
|
850
|
-
// Ensure the queue is empty and pause 250ms
|
|
851
525
|
await flushAsync();
|
|
852
526
|
return [server, aggregator];
|
|
853
527
|
}
|
|
854
|
-
/**
|
|
855
|
-
* Stop a matter server node.
|
|
856
|
-
*
|
|
857
|
-
* @param {ServerNode<ServerNode.RootEndpoint>} server The server to stop.
|
|
858
|
-
* @returns {Promise<void>} Resolves when the server has stopped.
|
|
859
|
-
*/
|
|
860
528
|
export async function stopServerNode(server) {
|
|
861
|
-
// Flush any pending endpoint number persistence
|
|
862
529
|
await flushAllEndpointNumberPersistence(server);
|
|
863
|
-
// Ensure all endpoint numbers are persisted
|
|
864
530
|
await assertAllEndpointNumbersPersisted(server);
|
|
865
|
-
// Stop the server
|
|
866
531
|
expect(server).toBeDefined();
|
|
867
532
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
868
533
|
expect(server.lifecycle.isOnline).toBeTruthy();
|
|
869
534
|
await server.close();
|
|
870
535
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
871
536
|
expect(server.lifecycle.isOnline).toBeFalsy();
|
|
872
|
-
// stop the mDNS service
|
|
873
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
874
537
|
const mdns = environment.get(MdnsService);
|
|
875
538
|
if (mdns && typeof mdns[Symbol.asyncDispose] === 'function')
|
|
876
539
|
await mdns[Symbol.asyncDispose]();
|
|
877
540
|
if (mdns && typeof mdns.close === 'function')
|
|
878
541
|
await mdns.close();
|
|
879
|
-
// Ensure the queue is empty and pause 250ms
|
|
880
542
|
await flushAsync();
|
|
881
543
|
}
|
|
882
|
-
/**
|
|
883
|
-
* Add a device (endpoint) to a matter server node or an aggregator.
|
|
884
|
-
*
|
|
885
|
-
* @param {ServerNode<ServerNode.RootEndpoint> | Endpoint<AggregatorEndpoint>} owner The server or aggregator to add the device to.
|
|
886
|
-
* @param {Endpoint} device The device to add.
|
|
887
|
-
* @param {number} pause The pause time in milliseconds after addition (default 10ms).
|
|
888
|
-
* @returns {Promise<void>} Resolves when the device has been added and is ready.
|
|
889
|
-
*/
|
|
890
544
|
export async function addDevice(owner, device, pause = 10) {
|
|
891
545
|
expect(owner).toBeDefined();
|
|
892
546
|
expect(device).toBeDefined();
|
|
893
547
|
expect(owner.lifecycle.isReady).toBeTruthy();
|
|
894
548
|
expect(owner.construction.status).toBe(Lifecycle.Status.Active);
|
|
895
549
|
expect(owner.lifecycle.isPartsReady).toBeTruthy();
|
|
896
|
-
// istanbul ignore next
|
|
897
550
|
try {
|
|
898
551
|
await owner.add(device);
|
|
899
552
|
}
|
|
@@ -913,21 +566,12 @@ export async function addDevice(owner, device, pause = 10) {
|
|
|
913
566
|
await flushAsync(undefined, undefined, pause);
|
|
914
567
|
return true;
|
|
915
568
|
}
|
|
916
|
-
/**
|
|
917
|
-
* Delete a device (endpoint) from a matter server node or an aggregator.
|
|
918
|
-
*
|
|
919
|
-
* @param {ServerNode<ServerNode.RootEndpoint> | Endpoint<AggregatorEndpoint>} owner The server or aggregator to remove the device from.
|
|
920
|
-
* @param {Endpoint} device The device to remove.
|
|
921
|
-
* @param {number} pause The pause time in milliseconds after deletion (default 10ms).
|
|
922
|
-
* @returns {Promise<void>} Resolves when the device has been removed and is no longer ready.
|
|
923
|
-
*/
|
|
924
569
|
export async function deleteDevice(owner, device, pause = 10) {
|
|
925
570
|
expect(owner).toBeDefined();
|
|
926
571
|
expect(device).toBeDefined();
|
|
927
572
|
expect(owner.lifecycle.isReady).toBeTruthy();
|
|
928
573
|
expect(owner.construction.status).toBe(Lifecycle.Status.Active);
|
|
929
574
|
expect(owner.lifecycle.isPartsReady).toBeTruthy();
|
|
930
|
-
// istanbul ignore next
|
|
931
575
|
try {
|
|
932
576
|
await device.delete();
|
|
933
577
|
}
|
|
@@ -947,4 +591,3 @@ export async function deleteDevice(owner, device, pause = 10) {
|
|
|
947
591
|
await flushAsync(undefined, undefined, pause);
|
|
948
592
|
return true;
|
|
949
593
|
}
|
|
950
|
-
//# sourceMappingURL=jestHelpers.js.map
|