matterbridge 3.4.1 → 3.4.2-dev-20251202-c41a119
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 +20 -0
- package/dist/broadcastServer.js +0 -112
- package/dist/broadcastServerTypes.js +0 -24
- package/dist/cli.js +1 -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 +13 -368
- 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 +46 -807
- 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 -450
- 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 +14 -10
- package/package.json +1 -2
- package/dist/broadcastServer.d.ts +0 -136
- 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 -340
- 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 -493
- 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 -537
- 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';
|
|
@@ -41,7 +16,6 @@ import { Frontend } from '../frontend.js';
|
|
|
41
16
|
import { BroadcastServer } from '../broadcastServer.js';
|
|
42
17
|
export const originalProcessArgv = Object.freeze([...process.argv]);
|
|
43
18
|
export const originalProcessEnv = Object.freeze({ ...process.env });
|
|
44
|
-
// Spy on logger methods
|
|
45
19
|
export let loggerLogSpy;
|
|
46
20
|
export let loggerDebugSpy;
|
|
47
21
|
export let loggerInfoSpy;
|
|
@@ -49,18 +23,15 @@ export let loggerNoticeSpy;
|
|
|
49
23
|
export let loggerWarnSpy;
|
|
50
24
|
export let loggerErrorSpy;
|
|
51
25
|
export let loggerFatalSpy;
|
|
52
|
-
// Spy on console methods
|
|
53
26
|
export let consoleLogSpy;
|
|
54
27
|
export let consoleDebugSpy;
|
|
55
28
|
export let consoleInfoSpy;
|
|
56
29
|
export let consoleWarnSpy;
|
|
57
30
|
export let consoleErrorSpy;
|
|
58
|
-
// Spy on Matterbridge methods
|
|
59
31
|
export let addBridgedEndpointSpy;
|
|
60
32
|
export let removeBridgedEndpointSpy;
|
|
61
33
|
export let removeAllBridgedEndpointsSpy;
|
|
62
34
|
export let addVirtualEndpointSpy;
|
|
63
|
-
// Spy on PluginManager methods
|
|
64
35
|
export let installPluginSpy;
|
|
65
36
|
export let uninstallPluginSpy;
|
|
66
37
|
export let addPluginSpy;
|
|
@@ -71,14 +42,12 @@ export let shutdownPluginSpy;
|
|
|
71
42
|
export let removePluginSpy;
|
|
72
43
|
export let enablePluginSpy;
|
|
73
44
|
export let disablePluginSpy;
|
|
74
|
-
// Spy on Frontend methods
|
|
75
45
|
export let wssSendSnackbarMessageSpy;
|
|
76
46
|
export let wssSendCloseSnackbarMessageSpy;
|
|
77
47
|
export let wssSendUpdateRequiredSpy;
|
|
78
48
|
export let wssSendRefreshRequiredSpy;
|
|
79
49
|
export let wssSendRestartRequiredSpy;
|
|
80
50
|
export let wssSendRestartNotRequiredSpy;
|
|
81
|
-
// Spy on BroadcastServer methods
|
|
82
51
|
export let broadcastServerIsWorkerRequestSpy;
|
|
83
52
|
export let broadcastServerIsWorkerResponseSpy;
|
|
84
53
|
export let broadcastServerBroadcastSpy;
|
|
@@ -96,29 +65,12 @@ export let environment;
|
|
|
96
65
|
export let server;
|
|
97
66
|
export let aggregator;
|
|
98
67
|
export let log;
|
|
99
|
-
/**
|
|
100
|
-
* Setup the Jest environment:
|
|
101
|
-
* - it will remove any existing home directory
|
|
102
|
-
* - setup the spies for logging
|
|
103
|
-
*
|
|
104
|
-
* @param {string} name The name of the test suite.
|
|
105
|
-
* @param {boolean} debug If true, the logging is not mocked.
|
|
106
|
-
*
|
|
107
|
-
* @example
|
|
108
|
-
* ```typescript
|
|
109
|
-
* import { consoleDebugSpy, consoleErrorSpy, consoleInfoSpy, consoleLogSpy, consoleWarnSpy, loggerLogSpy, setDebug, setupTest } from './jestutils/jestHelpers.js';
|
|
110
|
-
*
|
|
111
|
-
* // Setup the test environment
|
|
112
|
-
* await setupTest(NAME, false);
|
|
113
|
-
* ```
|
|
114
|
-
*/
|
|
115
68
|
export async function setupTest(name, debug = false) {
|
|
116
69
|
expect(name).toBeDefined();
|
|
117
70
|
expect(typeof name).toBe('string');
|
|
118
71
|
expect(name.length).toBeGreaterThanOrEqual(4);
|
|
119
72
|
NAME = name;
|
|
120
73
|
HOMEDIR = path.join('jest', name);
|
|
121
|
-
// Cleanup any existing home directory
|
|
122
74
|
rmSync(HOMEDIR, { recursive: true, force: true });
|
|
123
75
|
const { jest } = await import('@jest/globals');
|
|
124
76
|
loggerDebugSpy = jest.spyOn(AnsiLogger.prototype, 'debug');
|
|
@@ -169,26 +121,8 @@ export async function setupTest(name, debug = false) {
|
|
|
169
121
|
broadcastServerRequestSpy = jest.spyOn(BroadcastServer.prototype, 'request');
|
|
170
122
|
broadcastServerRespondSpy = jest.spyOn(BroadcastServer.prototype, 'respond');
|
|
171
123
|
broadcastServerFetchSpy = jest.spyOn(BroadcastServer.prototype, 'fetch');
|
|
172
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
173
124
|
broadcastMessageHandlerSpy = jest.spyOn(BroadcastServer.prototype, 'broadcastMessageHandler');
|
|
174
125
|
}
|
|
175
|
-
/**
|
|
176
|
-
* Set or unset the debug mode.
|
|
177
|
-
*
|
|
178
|
-
* @param {boolean} debug If true, the logging is not mocked.
|
|
179
|
-
* @returns {Promise<void>} A promise that resolves when the debug mode is set.
|
|
180
|
-
*
|
|
181
|
-
* @example
|
|
182
|
-
* ```typescript
|
|
183
|
-
* // Set the debug mode in test environment
|
|
184
|
-
* await setDebug(true);
|
|
185
|
-
* ```
|
|
186
|
-
*
|
|
187
|
-
* ```typescript
|
|
188
|
-
* // Reset the debug mode in test environment
|
|
189
|
-
* await setDebug(false);
|
|
190
|
-
* ```
|
|
191
|
-
*/
|
|
192
126
|
export async function setDebug(debug) {
|
|
193
127
|
const { jest } = await import('@jest/globals');
|
|
194
128
|
if (debug) {
|
|
@@ -214,41 +148,18 @@ export async function setDebug(debug) {
|
|
|
214
148
|
consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => { });
|
|
215
149
|
}
|
|
216
150
|
}
|
|
217
|
-
/**
|
|
218
|
-
* Create and start a fully initialized Matterbridge instance for testing.
|
|
219
|
-
*
|
|
220
|
-
* @param {('bridge' | 'childbridge' | 'controller' | '')} bridgeMode The bridge mode to start the Matterbridge instance in.
|
|
221
|
-
* @param {number} frontendPort The frontend port number.
|
|
222
|
-
* @param {number} matterPort The matter port number.
|
|
223
|
-
* @param {number} passcode The passcode number.
|
|
224
|
-
* @param {number} discriminator The discriminator number.
|
|
225
|
-
* @param {number} pluginSize The expected number of plugins.
|
|
226
|
-
* @param {number} devicesSize The expected number of devices.
|
|
227
|
-
* @returns {Promise<Matterbridge>} The Matterbridge instance.
|
|
228
|
-
*
|
|
229
|
-
* @example
|
|
230
|
-
* ```typescript
|
|
231
|
-
* // Create and start a fully initialized Matterbridge instance for testing.
|
|
232
|
-
* await startMatterbridge();
|
|
233
|
-
* ```
|
|
234
|
-
*/
|
|
235
151
|
export async function startMatterbridge(bridgeMode = 'bridge', frontendPort = 8283, matterPort = 5540, passcode = 20252026, discriminator = 3840, pluginSize = 0, devicesSize = 0) {
|
|
236
|
-
// Set the environment variables
|
|
237
152
|
process.env['MATTERBRIDGE_START_MATTER_INTERVAL_MS'] = '100';
|
|
238
153
|
process.env['MATTERBRIDGE_PAUSE_MATTER_INTERVAL_MS'] = '100';
|
|
239
|
-
// Setup the process arguments
|
|
240
154
|
process.argv.length = 0;
|
|
241
155
|
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());
|
|
242
|
-
// Load Matterbridge instance and initialize it
|
|
243
156
|
matterbridge = await Matterbridge.loadInstance(true);
|
|
244
157
|
expect(matterbridge).toBeDefined();
|
|
245
158
|
expect(matterbridge.profile).toBeUndefined();
|
|
246
159
|
expect(matterbridge.bridgeMode).toBe(bridgeMode);
|
|
247
|
-
// Get the frontend, plugins and devices
|
|
248
160
|
frontend = matterbridge.frontend;
|
|
249
161
|
plugins = matterbridge.plugins;
|
|
250
162
|
devices = matterbridge.devices;
|
|
251
|
-
// @ts-expect-error - access to private member for testing
|
|
252
163
|
expect(matterbridge.initialized).toBeTruthy();
|
|
253
164
|
expect(matterbridge.log).toBeDefined();
|
|
254
165
|
expect(matterbridge.rootDirectory).toBe(path.resolve('./'));
|
|
@@ -261,15 +172,10 @@ export async function startMatterbridge(bridgeMode = 'bridge', frontendPort = 82
|
|
|
261
172
|
expect(devices).toBeDefined();
|
|
262
173
|
expect(devices.size).toBe(devicesSize);
|
|
263
174
|
expect(frontend).toBeDefined();
|
|
264
|
-
// @ts-expect-error - access to private member for testing
|
|
265
175
|
expect(frontend.listening).toBeTruthy();
|
|
266
|
-
// @ts-expect-error - access to private member for testing
|
|
267
176
|
expect(frontend.httpServer).toBeDefined();
|
|
268
|
-
// @ts-expect-error - access to private member for testing
|
|
269
177
|
expect(frontend.httpsServer).toBeUndefined();
|
|
270
|
-
// @ts-expect-error - access to private member for testing
|
|
271
178
|
expect(frontend.expressApp).toBeDefined();
|
|
272
|
-
// @ts-expect-error - access to private member for testing
|
|
273
179
|
expect(frontend.webSocketServer).toBeDefined();
|
|
274
180
|
expect(matterbridge.nodeStorage).toBeDefined();
|
|
275
181
|
expect(matterbridge.nodeContext).toBeDefined();
|
|
@@ -307,51 +213,25 @@ export async function startMatterbridge(bridgeMode = 'bridge', frontendPort = 82
|
|
|
307
213
|
});
|
|
308
214
|
});
|
|
309
215
|
}
|
|
310
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("info"
|
|
216
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("info", `The frontend http server is listening on ${UNDERLINE}http://${matterbridge.systemInformation.ipv4Address}:${frontendPort}${UNDERLINEOFF}${rs}`);
|
|
311
217
|
if (bridgeMode === 'bridge') {
|
|
312
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("notice"
|
|
313
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("notice"
|
|
314
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("debug"
|
|
315
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("debug"
|
|
316
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("notice"
|
|
218
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("notice", `Starting Matterbridge server node`);
|
|
219
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("notice", `Server node for Matterbridge is online`);
|
|
220
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("debug", `Starting start matter interval in bridge mode...`);
|
|
221
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("debug", `Cleared startMatterInterval interval in bridge mode`);
|
|
222
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("notice", `Matterbridge bridge started successfully`);
|
|
317
223
|
}
|
|
318
224
|
else if (bridgeMode === 'childbridge') {
|
|
319
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("debug"
|
|
320
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("debug"
|
|
321
|
-
expect(loggerLogSpy).toHaveBeenCalledWith("notice"
|
|
225
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("debug", `Starting start matter interval in childbridge mode...`);
|
|
226
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("debug", `Cleared startMatterInterval interval in childbridge mode`);
|
|
227
|
+
expect(loggerLogSpy).toHaveBeenCalledWith("notice", `Matterbridge childbridge started successfully`);
|
|
322
228
|
}
|
|
323
229
|
return matterbridge;
|
|
324
230
|
}
|
|
325
|
-
/**
|
|
326
|
-
* Stop the fully initialized Matterbridge instance.
|
|
327
|
-
*
|
|
328
|
-
* @param {cleanupPause} cleanupPause The pause duration before cleanup. Default is 10 ms.
|
|
329
|
-
* @param {destroyPause} destroyPause The pause duration before destruction. Default is 250 ms.
|
|
330
|
-
*
|
|
331
|
-
* @example
|
|
332
|
-
* ```typescript
|
|
333
|
-
* // Stop the fully initialized Matterbridge instance.
|
|
334
|
-
* await stopMatterbridge();
|
|
335
|
-
* ```
|
|
336
|
-
*/
|
|
337
231
|
export async function stopMatterbridge(cleanupPause = 10, destroyPause = 250) {
|
|
338
232
|
await destroyMatterbridgeEnvironment(cleanupPause, destroyPause);
|
|
339
233
|
}
|
|
340
|
-
/**
|
|
341
|
-
* Create a Matterbridge instance for testing without initializing it.
|
|
342
|
-
*
|
|
343
|
-
* @param {string} name - Name for the environment (jest/name).
|
|
344
|
-
* @returns {Promise<Matterbridge>} The Matterbridge instance.
|
|
345
|
-
*
|
|
346
|
-
* @example
|
|
347
|
-
* ```typescript
|
|
348
|
-
* // Create Matterbridge environment
|
|
349
|
-
* await createMatterbridgeEnvironment(NAME);
|
|
350
|
-
* await startMatterbridgeEnvironment(MATTER_PORT);
|
|
351
|
-
* ```
|
|
352
|
-
*/
|
|
353
234
|
export async function createMatterbridgeEnvironment(name) {
|
|
354
|
-
// Create a MatterbridgeEdge instance
|
|
355
235
|
matterbridge = await Matterbridge.loadInstance(false);
|
|
356
236
|
expect(matterbridge).toBeDefined();
|
|
357
237
|
expect(matterbridge).toBeInstanceOf(Matterbridge);
|
|
@@ -362,52 +242,28 @@ export async function createMatterbridgeEnvironment(name) {
|
|
|
362
242
|
matterbridge.matterbridgeDirectory = path.join('jest', name, '.matterbridge');
|
|
363
243
|
matterbridge.matterbridgePluginDirectory = path.join('jest', name, 'Matterbridge');
|
|
364
244
|
matterbridge.matterbridgeCertDirectory = path.join('jest', name, '.mattercert');
|
|
365
|
-
matterbridge.log.logLevel = "debug"
|
|
366
|
-
log = new AnsiLogger({ logName: 'Plugin platform', logTimestampFormat: 4
|
|
367
|
-
// Get the frontend, plugins and devices
|
|
245
|
+
matterbridge.log.logLevel = "debug";
|
|
246
|
+
log = new AnsiLogger({ logName: 'Plugin platform', logTimestampFormat: 4, logLevel: "debug" });
|
|
368
247
|
frontend = matterbridge.frontend;
|
|
369
248
|
plugins = matterbridge.plugins;
|
|
370
249
|
devices = matterbridge.devices;
|
|
371
|
-
// Setup matter environment
|
|
372
|
-
// @ts-expect-error - access to private member for testing
|
|
373
250
|
matterbridge.environment = createTestEnvironment(name);
|
|
374
|
-
// @ts-expect-error - access to private member for testing
|
|
375
251
|
expect(matterbridge.environment).toBeDefined();
|
|
376
|
-
// @ts-expect-error - access to private member for testing
|
|
377
252
|
expect(matterbridge.environment).toBeInstanceOf(Environment);
|
|
378
253
|
return matterbridge;
|
|
379
254
|
}
|
|
380
|
-
/**
|
|
381
|
-
* Start the matterbridge environment.
|
|
382
|
-
* Only node storage, matter storage and the server and aggregator nodes are started.
|
|
383
|
-
*
|
|
384
|
-
* @param {number} port The matter server port.
|
|
385
|
-
* @returns {Promise<[ServerNode<ServerNode.RootEndpoint>, Endpoint<AggregatorEndpoint>]>} The started server and aggregator.
|
|
386
|
-
*
|
|
387
|
-
* @example
|
|
388
|
-
* ```typescript
|
|
389
|
-
* // Create Matterbridge environment
|
|
390
|
-
* await createMatterbridgeEnvironment(NAME);
|
|
391
|
-
* await startMatterbridgeEnvironment(MATTER_PORT);
|
|
392
|
-
* ```
|
|
393
|
-
*/
|
|
394
255
|
export async function startMatterbridgeEnvironment(port = 5540) {
|
|
395
|
-
// Create the node storage
|
|
396
256
|
matterbridge.nodeStorage = new NodeStorageManager({ dir: path.join(matterbridge.matterbridgeDirectory, NODE_STORAGE_DIR), writeQueue: false, expiredInterval: undefined, logging: false });
|
|
397
257
|
matterbridge.nodeContext = await matterbridge.nodeStorage.createStorage('matterbridge');
|
|
398
|
-
// Create the matter storage
|
|
399
|
-
// @ts-expect-error - access to private member for testing
|
|
400
258
|
await matterbridge.startMatterStorage();
|
|
401
259
|
expect(matterbridge.matterStorageService).toBeDefined();
|
|
402
260
|
expect(matterbridge.matterStorageManager).toBeDefined();
|
|
403
261
|
expect(matterbridge.matterbridgeContext).toBeDefined();
|
|
404
|
-
// @ts-expect-error - access to private member for testing
|
|
405
262
|
server = await matterbridge.createServerNode(matterbridge.matterbridgeContext, port);
|
|
406
263
|
expect(server).toBeDefined();
|
|
407
264
|
expect(server).toBeDefined();
|
|
408
265
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
409
266
|
matterbridge.serverNode = server;
|
|
410
|
-
// @ts-expect-error - access to private member for testing
|
|
411
267
|
aggregator = await matterbridge.createAggregatorNode(matterbridge.matterbridgeContext);
|
|
412
268
|
expect(aggregator).toBeDefined();
|
|
413
269
|
matterbridge.aggregatorNode = aggregator;
|
|
@@ -415,7 +271,6 @@ export async function startMatterbridgeEnvironment(port = 5540) {
|
|
|
415
271
|
expect(server.parts.has(aggregator.id)).toBeTruthy();
|
|
416
272
|
expect(server.parts.has(aggregator)).toBeTruthy();
|
|
417
273
|
expect(aggregator.lifecycle.isReady).toBeTruthy();
|
|
418
|
-
// Wait for the server to be online
|
|
419
274
|
expect(server.lifecycle.isOnline).toBeFalsy();
|
|
420
275
|
await new Promise((resolve) => {
|
|
421
276
|
server.lifecycle.online.on(async () => {
|
|
@@ -423,7 +278,6 @@ export async function startMatterbridgeEnvironment(port = 5540) {
|
|
|
423
278
|
});
|
|
424
279
|
server.start();
|
|
425
280
|
});
|
|
426
|
-
// Check if the server is online
|
|
427
281
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
428
282
|
expect(server.lifecycle.isOnline).toBeTruthy();
|
|
429
283
|
expect(server.lifecycle.isCommissioned).toBeFalsy();
|
|
@@ -435,27 +289,11 @@ export async function startMatterbridgeEnvironment(port = 5540) {
|
|
|
435
289
|
expect(aggregator.lifecycle.isPartsReady).toBeTruthy();
|
|
436
290
|
expect(aggregator.lifecycle.hasId).toBeTruthy();
|
|
437
291
|
expect(aggregator.lifecycle.hasNumber).toBeTruthy();
|
|
438
|
-
// Ensure the queue is empty and pause
|
|
439
292
|
await flushAsync();
|
|
440
293
|
return [server, aggregator];
|
|
441
294
|
}
|
|
442
|
-
/**
|
|
443
|
-
* Add a matterbridge platform for testing.
|
|
444
|
-
*
|
|
445
|
-
* @param {MatterbridgePlatform} platform The platform to add.
|
|
446
|
-
* @param {string} [name] Optional name of the platform.
|
|
447
|
-
*
|
|
448
|
-
* @example
|
|
449
|
-
* ```typescript
|
|
450
|
-
* platform = new Platform(matterbridge, log, config);
|
|
451
|
-
* // Add the platform to the Matterbridge environment
|
|
452
|
-
* addMatterbridgePlatform(platform);
|
|
453
|
-
* ```
|
|
454
|
-
*/
|
|
455
295
|
export function addMatterbridgePlatform(platform, name) {
|
|
456
296
|
expect(platform).toBeDefined();
|
|
457
|
-
// Setup the platform MatterNode helpers
|
|
458
|
-
// @ts-expect-error - setMatterNode is intentionally private
|
|
459
297
|
platform.setMatterNode?.(matterbridge.addBridgedEndpoint.bind(matterbridge), matterbridge.removeBridgedEndpoint.bind(matterbridge), matterbridge.removeAllBridgedEndpoints.bind(matterbridge), matterbridge.addVirtualEndpoint.bind(matterbridge));
|
|
460
298
|
if (name)
|
|
461
299
|
platform.config.name = name;
|
|
@@ -466,7 +304,6 @@ export function addMatterbridgePlatform(platform, name) {
|
|
|
466
304
|
expect(platform.version).toBeDefined();
|
|
467
305
|
expect(platform.config.debug).toBeDefined();
|
|
468
306
|
expect(platform.config.unregisterOnShutdown).toBeDefined();
|
|
469
|
-
// @ts-expect-error accessing private member for testing
|
|
470
307
|
matterbridge.plugins._plugins.set(platform.config.name, {
|
|
471
308
|
name: platform.config.name,
|
|
472
309
|
path: './',
|
|
@@ -478,150 +315,65 @@ export function addMatterbridgePlatform(platform, name) {
|
|
|
478
315
|
});
|
|
479
316
|
platform['name'] = platform.config.name;
|
|
480
317
|
}
|
|
481
|
-
/**
|
|
482
|
-
* Stop the matterbridge environment
|
|
483
|
-
*
|
|
484
|
-
* @example
|
|
485
|
-
* ```typescript
|
|
486
|
-
* // Destroy Matterbridge environment
|
|
487
|
-
* await stopMatterbridgeEnvironment();
|
|
488
|
-
* await destroyMatterbridgeEnvironment();
|
|
489
|
-
* ```
|
|
490
|
-
*/
|
|
491
318
|
export async function stopMatterbridgeEnvironment() {
|
|
492
319
|
expect(matterbridge).toBeDefined();
|
|
493
320
|
expect(server).toBeDefined();
|
|
494
321
|
expect(aggregator).toBeDefined();
|
|
495
|
-
// Flush any pending endpoint number persistence
|
|
496
322
|
await flushAllEndpointNumberPersistence(server);
|
|
497
|
-
// Ensure all endpoint numbers are persisted
|
|
498
323
|
await assertAllEndpointNumbersPersisted(server);
|
|
499
|
-
// Close the server node
|
|
500
324
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
501
325
|
expect(server.lifecycle.isOnline).toBeTruthy();
|
|
502
326
|
await server.close();
|
|
503
327
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
504
328
|
expect(server.lifecycle.isOnline).toBeFalsy();
|
|
505
|
-
// Stop the matter storage
|
|
506
|
-
// @ts-expect-error - access to private member for testing
|
|
507
329
|
await matterbridge.stopMatterStorage();
|
|
508
330
|
expect(matterbridge.matterStorageService).not.toBeDefined();
|
|
509
331
|
expect(matterbridge.matterStorageManager).not.toBeDefined();
|
|
510
332
|
expect(matterbridge.matterbridgeContext).not.toBeDefined();
|
|
511
|
-
// Stop the node storage
|
|
512
333
|
await matterbridge.nodeContext?.close();
|
|
513
334
|
matterbridge.nodeContext = undefined;
|
|
514
335
|
await matterbridge.nodeStorage?.close();
|
|
515
336
|
matterbridge.nodeStorage = undefined;
|
|
516
|
-
// Ensure the queue is empty and pause
|
|
517
337
|
await flushAsync();
|
|
518
338
|
}
|
|
519
|
-
/**
|
|
520
|
-
* Destroy the matterbridge environment
|
|
521
|
-
*
|
|
522
|
-
* @param {number} cleanupPause The timeout for the destroy operation (default 10ms).
|
|
523
|
-
* @param {number} destroyPause The pause duration after cleanup before destroying the instance (default 250ms).
|
|
524
|
-
*
|
|
525
|
-
* @example
|
|
526
|
-
* ```typescript
|
|
527
|
-
* // Destroy Matterbridge environment
|
|
528
|
-
* await stopMatterbridgeEnvironment();
|
|
529
|
-
* await destroyMatterbridgeEnvironment();
|
|
530
|
-
* ```
|
|
531
|
-
*/
|
|
532
339
|
export async function destroyMatterbridgeEnvironment(cleanupPause = 10, destroyPause = 250) {
|
|
533
|
-
// Destroy a matterbridge instance
|
|
534
340
|
await destroyInstance(matterbridge, cleanupPause, destroyPause);
|
|
535
|
-
// Close the mDNS service
|
|
536
341
|
await closeMdnsInstance(matterbridge);
|
|
537
|
-
// Reset the singleton instance
|
|
538
|
-
// @ts-expect-error - accessing private member for testing
|
|
539
342
|
Matterbridge.instance = undefined;
|
|
540
343
|
}
|
|
541
|
-
/**
|
|
542
|
-
* Destroy a matterbridge instance
|
|
543
|
-
*
|
|
544
|
-
* @param {Matterbridge} matterbridge The matterbridge instance to destroy.
|
|
545
|
-
* @param {number} cleanupPause The pause duration to wait for the cleanup to complete in milliseconds (default 10ms).
|
|
546
|
-
* @param {number} destroyPause The pause duration to wait after cleanup before destroying the instance in milliseconds (default 250ms).
|
|
547
|
-
*/
|
|
548
344
|
export async function destroyInstance(matterbridge, cleanupPause = 10, destroyPause = 250) {
|
|
549
|
-
// Cleanup the Matterbridge instance
|
|
550
|
-
// @ts-expect-error - accessing private member for testing
|
|
551
345
|
await matterbridge.cleanup('destroying instance...', false, cleanupPause);
|
|
552
|
-
// Pause before destroying the instance
|
|
553
346
|
if (destroyPause > 0)
|
|
554
347
|
await flushAsync(undefined, undefined, destroyPause);
|
|
555
348
|
}
|
|
556
|
-
/**
|
|
557
|
-
* Close the mDNS instance in the matterbridge environment.
|
|
558
|
-
*
|
|
559
|
-
* @param {Matterbridge} matterbridge The matterbridge instance.
|
|
560
|
-
* @returns {Promise<void>} A promise that resolves when the mDNS instance is closed.
|
|
561
|
-
*/
|
|
562
349
|
export async function closeMdnsInstance(matterbridge) {
|
|
563
|
-
// TODO: matter.js 0.16.0 - provide close method to close the mDNS service
|
|
564
|
-
// @ts-expect-error - accessing private member for testing
|
|
565
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
566
350
|
const mdns = matterbridge.environment.get(MdnsService);
|
|
567
351
|
if (mdns && mdns[Symbol.asyncDispose] && typeof mdns[Symbol.asyncDispose] === 'function')
|
|
568
352
|
await mdns[Symbol.asyncDispose]();
|
|
569
353
|
if (mdns && mdns.close && typeof mdns.close === 'function')
|
|
570
354
|
await mdns.close();
|
|
571
355
|
}
|
|
572
|
-
/**
|
|
573
|
-
* Create a matter test environment for testing:
|
|
574
|
-
* - it will remove any existing home directory
|
|
575
|
-
* - setup the matter environment with name, debug logging and ANSI format
|
|
576
|
-
* - setup the mDNS service in the environment
|
|
577
|
-
*
|
|
578
|
-
* @param {string} name - Name for the environment (jest/name).
|
|
579
|
-
* @returns {Environment} - The default matter environment.
|
|
580
|
-
*/
|
|
581
356
|
export function createTestEnvironment(name) {
|
|
582
357
|
expect(name).toBeDefined();
|
|
583
358
|
expect(typeof name).toBe('string');
|
|
584
|
-
expect(name.length).toBeGreaterThanOrEqual(4);
|
|
585
|
-
// Cleanup any existing home directory
|
|
359
|
+
expect(name.length).toBeGreaterThanOrEqual(4);
|
|
586
360
|
rmSync(path.join('jest', name), { recursive: true, force: true });
|
|
587
|
-
// Setup the matter environment
|
|
588
361
|
environment = Environment.default;
|
|
589
362
|
environment.vars.set('log.level', MatterLogLevel.DEBUG);
|
|
590
363
|
environment.vars.set('log.format', MatterLogFormat.ANSI);
|
|
591
364
|
environment.vars.set('path.root', path.join('jest', name, '.matterbridge', MATTER_STORAGE_NAME));
|
|
592
365
|
environment.vars.set('runtime.signals', false);
|
|
593
366
|
environment.vars.set('runtime.exitcode', false);
|
|
594
|
-
// Setup the mDNS service in the environment
|
|
595
367
|
new MdnsService(environment);
|
|
596
|
-
// await environment.get(MdnsService)?.construction.ready;
|
|
597
368
|
return environment;
|
|
598
369
|
}
|
|
599
|
-
/**
|
|
600
|
-
* Destroy the matter test environment by closing the mDNS service.
|
|
601
|
-
*
|
|
602
|
-
* @returns {Promise<void>} A promise that resolves when the test environment is destroyed.
|
|
603
|
-
*/
|
|
604
370
|
export async function destroyTestEnvironment() {
|
|
605
|
-
// stop the mDNS service
|
|
606
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
607
371
|
const mdns = environment.get(MdnsService);
|
|
608
372
|
if (mdns && typeof mdns[Symbol.asyncDispose] === 'function')
|
|
609
373
|
await mdns[Symbol.asyncDispose]();
|
|
610
374
|
if (mdns && typeof mdns.close === 'function')
|
|
611
375
|
await mdns.close();
|
|
612
376
|
}
|
|
613
|
-
/**
|
|
614
|
-
* Advance the Node.js event loop deterministically to allow chained asynchronous work (Promises scheduled in
|
|
615
|
-
* microtasks and follow‑up macrotasks) to complete inside tests without adding arbitrary long timeouts.
|
|
616
|
-
*
|
|
617
|
-
* NOTE: This does not guarantee OS level network IO completion—only JavaScript task queue progression inside the
|
|
618
|
-
* current process.
|
|
619
|
-
*
|
|
620
|
-
* @param {number} ticks Number of macrotask (setImmediate) turns to yield (default 3).
|
|
621
|
-
* @param {number} microTurns Number of microtask drains (Promise.resolve chains) after macrotask yielding (default 10).
|
|
622
|
-
* @param {number} pause Final timer delay in ms; set 0 to disable (default 250ms).
|
|
623
|
-
* @returns {Promise<void>} Resolves after the requested event loop advancement has completed.
|
|
624
|
-
*/
|
|
625
377
|
export async function flushAsync(ticks = 3, microTurns = 10, pause = 250) {
|
|
626
378
|
for (let i = 0; i < ticks; i++)
|
|
627
379
|
await new Promise((resolve) => setImmediate(resolve));
|
|
@@ -630,33 +382,16 @@ export async function flushAsync(ticks = 3, microTurns = 10, pause = 250) {
|
|
|
630
382
|
if (pause)
|
|
631
383
|
await new Promise((resolve) => setTimeout(resolve, pause));
|
|
632
384
|
}
|
|
633
|
-
/**
|
|
634
|
-
* Summarize live libuv handles/requests inside a process.
|
|
635
|
-
*
|
|
636
|
-
* @param {AnsiLogger} log - Logger to use for output
|
|
637
|
-
*
|
|
638
|
-
* @returns {number} - The total number of active handles and requests
|
|
639
|
-
*/
|
|
640
385
|
export function logKeepAlives(log) {
|
|
641
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
642
386
|
const handles = process._getActiveHandles?.() ?? [];
|
|
643
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
644
387
|
const requests = process._getActiveRequests?.() ?? [];
|
|
645
|
-
// istanbul ignore next
|
|
646
388
|
const fmtHandle = (h, i) => {
|
|
647
389
|
const ctor = h?.constructor?.name ?? 'Unknown';
|
|
648
|
-
// Timer-like?
|
|
649
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
650
390
|
const hasRef = typeof h?.hasRef === 'function' ? h.hasRef() : undefined;
|
|
651
|
-
// MessagePort?
|
|
652
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
653
391
|
const isPort = h?.constructor?.name?.includes('MessagePort');
|
|
654
|
-
// Socket/Server?
|
|
655
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
656
392
|
const fd = h?.fd ?? h?._handle?.fd;
|
|
657
393
|
return { i, type: ctor, hasRef, isPort, fd };
|
|
658
394
|
};
|
|
659
|
-
// istanbul ignore next
|
|
660
395
|
const fmtReq = (r, i) => {
|
|
661
396
|
const ctor = r?.constructor?.name ?? 'Unknown';
|
|
662
397
|
return { i, type: ctor };
|
|
@@ -665,7 +400,6 @@ export function logKeepAlives(log) {
|
|
|
665
400
|
handles: handles.map(fmtHandle),
|
|
666
401
|
requests: requests.map(fmtReq),
|
|
667
402
|
};
|
|
668
|
-
// istanbul ignore next if
|
|
669
403
|
if (summary.handles.length === 0 && summary.requests.length === 0) {
|
|
670
404
|
log?.debug('KeepAlive: no active handles or requests.');
|
|
671
405
|
}
|
|
@@ -677,19 +411,6 @@ export function logKeepAlives(log) {
|
|
|
677
411
|
}
|
|
678
412
|
return summary.handles.length + summary.requests.length;
|
|
679
413
|
}
|
|
680
|
-
/**
|
|
681
|
-
* Flush (await) the lazy endpoint number persistence mechanism used by matter.js.
|
|
682
|
-
*
|
|
683
|
-
* Background:
|
|
684
|
-
* assignNumber() batches persistence (store.saveNumber + updating __nextNumber__) via an internal promise (#numbersPersisted).
|
|
685
|
-
* Calling endpointStores.close() waits for the current batch only. If new endpoints were added in the same macrotask
|
|
686
|
-
* cycle additional micro/macro turns might be needed to ensure the batch started. We defensively yield macrotasks
|
|
687
|
-
* (setImmediate) and then await close() multiple rounds.
|
|
688
|
-
*
|
|
689
|
-
* @param {ServerNode} targetServer The server whose endpoint numbering persistence should be flushed.
|
|
690
|
-
* @param {number} rounds Number of macrotask + close cycles to run (2 is usually sufficient; 1 often works).
|
|
691
|
-
* @returns {Promise<void>} Resolves when pending number persistence batches have completed.
|
|
692
|
-
*/
|
|
693
414
|
export async function flushAllEndpointNumberPersistence(targetServer, rounds = 2) {
|
|
694
415
|
const nodeStore = targetServer.env.get(ServerNodeStore);
|
|
695
416
|
for (let i = 0; i < rounds; i++) {
|
|
@@ -697,12 +418,6 @@ export async function flushAllEndpointNumberPersistence(targetServer, rounds = 2
|
|
|
697
418
|
await nodeStore.endpointStores.close();
|
|
698
419
|
}
|
|
699
420
|
}
|
|
700
|
-
/**
|
|
701
|
-
* Collect all endpoints in the server endpoint tree (root -> descendants).
|
|
702
|
-
*
|
|
703
|
-
* @param {Endpoint} root Root endpoint (typically the ServerNode root endpoint cast as Endpoint).
|
|
704
|
-
* @returns {Endpoint[]} Flat array including the root and every descendant once.
|
|
705
|
-
*/
|
|
706
421
|
function collectAllEndpoints(root) {
|
|
707
422
|
const list = [];
|
|
708
423
|
const walk = (ep) => {
|
|
@@ -716,26 +431,14 @@ function collectAllEndpoints(root) {
|
|
|
716
431
|
walk(root);
|
|
717
432
|
return list;
|
|
718
433
|
}
|
|
719
|
-
/**
|
|
720
|
-
* Assert that every endpoint attached to the server has an assigned and (batch-)persisted endpoint number.
|
|
721
|
-
*
|
|
722
|
-
* This waits for any outstanding number persistence batch (endpointStores.close()), then traverses the endpoint
|
|
723
|
-
* graph and asserts:
|
|
724
|
-
* - Root endpoint: number is 0 (allowing undefined to coerce to 0 via nullish coalescing check).
|
|
725
|
-
* - All other endpoints: number > 0.
|
|
726
|
-
*
|
|
727
|
-
* @param {ServerNode} targetServer The server whose endpoint numbers are verified.
|
|
728
|
-
* @returns {Promise<void>} Resolves when assertions complete.
|
|
729
|
-
*/
|
|
730
434
|
export async function assertAllEndpointNumbersPersisted(targetServer) {
|
|
731
435
|
const nodeStore = targetServer.env.get(ServerNodeStore);
|
|
732
|
-
// Ensure any pending persistence finished (flush any in-flight batch promise)
|
|
733
436
|
await nodeStore.endpointStores.close();
|
|
734
437
|
const all = collectAllEndpoints(targetServer);
|
|
735
438
|
for (const ep of all) {
|
|
736
439
|
const store = nodeStore.storeForEndpoint(ep);
|
|
737
440
|
if (ep.maybeNumber === 0) {
|
|
738
|
-
expect(store.number ?? 0).toBe(0);
|
|
441
|
+
expect(store.number ?? 0).toBe(0);
|
|
739
442
|
}
|
|
740
443
|
else {
|
|
741
444
|
expect(store.number).toBeGreaterThan(0);
|
|
@@ -743,42 +446,23 @@ export async function assertAllEndpointNumbersPersisted(targetServer) {
|
|
|
743
446
|
}
|
|
744
447
|
return all.length;
|
|
745
448
|
}
|
|
746
|
-
/**
|
|
747
|
-
* Close the server node stores to flush any pending endpoint number persistence.
|
|
748
|
-
*
|
|
749
|
-
* @param {ServerNode} targetServer The server whose endpoint stores should be closed.
|
|
750
|
-
* @returns {Promise<void>} Resolves when the stores have been closed.
|
|
751
|
-
*/
|
|
752
449
|
export async function closeServerNodeStores(targetServer) {
|
|
753
|
-
// Close endpoint stores to avoid number persistence issues
|
|
754
450
|
if (!targetServer)
|
|
755
451
|
targetServer = server;
|
|
756
452
|
await targetServer?.env.get(ServerNodeStore)?.endpointStores.close();
|
|
757
453
|
}
|
|
758
|
-
/**
|
|
759
|
-
* Start a matter server node for testing.
|
|
760
|
-
*
|
|
761
|
-
* @param {string} name Name of the server (used for logging and product description).
|
|
762
|
-
* @param {number} port TCP port to listen on.
|
|
763
|
-
* @param {DeviceTypeId} deviceType Device type identifier for the server node.
|
|
764
|
-
* @returns {Promise<[ServerNode<ServerNode.RootEndpoint>, Endpoint<AggregatorEndpoint>]>} Resolves to an array containing the created ServerNode and its AggregatorNode.
|
|
765
|
-
*/
|
|
766
454
|
export async function startServerNode(name, port, deviceType = bridge.code) {
|
|
767
455
|
const { randomBytes } = await import('node:crypto');
|
|
768
456
|
const random = randomBytes(8).toString('hex');
|
|
769
|
-
// Create the server node
|
|
770
457
|
server = await ServerNode.create({
|
|
771
458
|
id: name + 'ServerNode',
|
|
772
|
-
// Provide the environment
|
|
773
459
|
environment,
|
|
774
|
-
// Provide Node announcement settings
|
|
775
460
|
productDescription: {
|
|
776
461
|
name: name + 'ServerNode',
|
|
777
462
|
deviceType: DeviceTypeId(deviceType),
|
|
778
463
|
vendorId: VendorId(0xfff1),
|
|
779
464
|
productId: 0x8000,
|
|
780
465
|
},
|
|
781
|
-
// Provide defaults for the BasicInformation cluster on the Root endpoint
|
|
782
466
|
basicInformation: {
|
|
783
467
|
vendorId: VendorId(0xfff1),
|
|
784
468
|
vendorName: 'Matterbridge',
|
|
@@ -791,39 +475,32 @@ export async function startServerNode(name, port, deviceType = bridge.code) {
|
|
|
791
475
|
serialNumber: 'SN' + random,
|
|
792
476
|
uniqueId: 'UI' + random,
|
|
793
477
|
},
|
|
794
|
-
// Provide Network relevant configuration like the port
|
|
795
478
|
network: {
|
|
796
479
|
listeningAddressIpv4: undefined,
|
|
797
480
|
listeningAddressIpv6: undefined,
|
|
798
481
|
port,
|
|
799
482
|
},
|
|
800
|
-
// Provide the certificate for the device
|
|
801
483
|
operationalCredentials: {
|
|
802
484
|
certification: undefined,
|
|
803
485
|
},
|
|
804
486
|
});
|
|
805
487
|
expect(server).toBeDefined();
|
|
806
488
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
807
|
-
// Create the aggregator node
|
|
808
489
|
aggregator = new Endpoint(AggregatorEndpoint, {
|
|
809
490
|
id: name + 'AggregatorNode',
|
|
810
491
|
});
|
|
811
492
|
expect(aggregator).toBeDefined();
|
|
812
|
-
// Add the aggregator to the server
|
|
813
493
|
await server.add(aggregator);
|
|
814
494
|
expect(server.parts.has(aggregator.id)).toBeTruthy();
|
|
815
495
|
expect(server.parts.has(aggregator)).toBeTruthy();
|
|
816
496
|
expect(aggregator.lifecycle.isReady).toBeTruthy();
|
|
817
|
-
// Run the server
|
|
818
497
|
expect(server.lifecycle.isOnline).toBeFalsy();
|
|
819
|
-
// Wait for the server to be online
|
|
820
498
|
await new Promise((resolve) => {
|
|
821
499
|
server.lifecycle.online.on(async () => {
|
|
822
500
|
resolve();
|
|
823
501
|
});
|
|
824
502
|
server.start();
|
|
825
503
|
});
|
|
826
|
-
// Check if the server is online
|
|
827
504
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
828
505
|
expect(server.lifecycle.isOnline).toBeTruthy();
|
|
829
506
|
expect(server.lifecycle.isCommissioned).toBeFalsy();
|
|
@@ -835,53 +512,31 @@ export async function startServerNode(name, port, deviceType = bridge.code) {
|
|
|
835
512
|
expect(aggregator.lifecycle.isPartsReady).toBeTruthy();
|
|
836
513
|
expect(aggregator.lifecycle.hasId).toBeTruthy();
|
|
837
514
|
expect(aggregator.lifecycle.hasNumber).toBeTruthy();
|
|
838
|
-
// Ensure the queue is empty and pause 250ms
|
|
839
515
|
await flushAsync();
|
|
840
516
|
return [server, aggregator];
|
|
841
517
|
}
|
|
842
|
-
/**
|
|
843
|
-
* Stop a matter server node.
|
|
844
|
-
*
|
|
845
|
-
* @param {ServerNode<ServerNode.RootEndpoint>} server The server to stop.
|
|
846
|
-
* @returns {Promise<void>} Resolves when the server has stopped.
|
|
847
|
-
*/
|
|
848
518
|
export async function stopServerNode(server) {
|
|
849
|
-
// Flush any pending endpoint number persistence
|
|
850
519
|
await flushAllEndpointNumberPersistence(server);
|
|
851
|
-
// Ensure all endpoint numbers are persisted
|
|
852
520
|
await assertAllEndpointNumbersPersisted(server);
|
|
853
|
-
// Stop the server
|
|
854
521
|
expect(server).toBeDefined();
|
|
855
522
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
856
523
|
expect(server.lifecycle.isOnline).toBeTruthy();
|
|
857
524
|
await server.close();
|
|
858
525
|
expect(server.lifecycle.isReady).toBeTruthy();
|
|
859
526
|
expect(server.lifecycle.isOnline).toBeFalsy();
|
|
860
|
-
// stop the mDNS service
|
|
861
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
862
527
|
const mdns = environment.get(MdnsService);
|
|
863
528
|
if (mdns && typeof mdns[Symbol.asyncDispose] === 'function')
|
|
864
529
|
await mdns[Symbol.asyncDispose]();
|
|
865
530
|
if (mdns && typeof mdns.close === 'function')
|
|
866
531
|
await mdns.close();
|
|
867
|
-
// Ensure the queue is empty and pause 250ms
|
|
868
532
|
await flushAsync();
|
|
869
533
|
}
|
|
870
|
-
/**
|
|
871
|
-
* Add a device (endpoint) to a matter server node or an aggregator.
|
|
872
|
-
*
|
|
873
|
-
* @param {ServerNode<ServerNode.RootEndpoint> | Endpoint<AggregatorEndpoint>} owner The server or aggregator to add the device to.
|
|
874
|
-
* @param {Endpoint} device The device to add.
|
|
875
|
-
* @param {number} pause The pause time in milliseconds after addition (default 10ms).
|
|
876
|
-
* @returns {Promise<void>} Resolves when the device has been added and is ready.
|
|
877
|
-
*/
|
|
878
534
|
export async function addDevice(owner, device, pause = 10) {
|
|
879
535
|
expect(owner).toBeDefined();
|
|
880
536
|
expect(device).toBeDefined();
|
|
881
537
|
expect(owner.lifecycle.isReady).toBeTruthy();
|
|
882
538
|
expect(owner.construction.status).toBe(Lifecycle.Status.Active);
|
|
883
539
|
expect(owner.lifecycle.isPartsReady).toBeTruthy();
|
|
884
|
-
// istanbul ignore next
|
|
885
540
|
try {
|
|
886
541
|
await owner.add(device);
|
|
887
542
|
}
|
|
@@ -901,21 +556,12 @@ export async function addDevice(owner, device, pause = 10) {
|
|
|
901
556
|
await flushAsync(undefined, undefined, pause);
|
|
902
557
|
return true;
|
|
903
558
|
}
|
|
904
|
-
/**
|
|
905
|
-
* Delete a device (endpoint) from a matter server node or an aggregator.
|
|
906
|
-
*
|
|
907
|
-
* @param {ServerNode<ServerNode.RootEndpoint> | Endpoint<AggregatorEndpoint>} owner The server or aggregator to remove the device from.
|
|
908
|
-
* @param {Endpoint} device The device to remove.
|
|
909
|
-
* @param {number} pause The pause time in milliseconds after deletion (default 10ms).
|
|
910
|
-
* @returns {Promise<void>} Resolves when the device has been removed and is no longer ready.
|
|
911
|
-
*/
|
|
912
559
|
export async function deleteDevice(owner, device, pause = 10) {
|
|
913
560
|
expect(owner).toBeDefined();
|
|
914
561
|
expect(device).toBeDefined();
|
|
915
562
|
expect(owner.lifecycle.isReady).toBeTruthy();
|
|
916
563
|
expect(owner.construction.status).toBe(Lifecycle.Status.Active);
|
|
917
564
|
expect(owner.lifecycle.isPartsReady).toBeTruthy();
|
|
918
|
-
// istanbul ignore next
|
|
919
565
|
try {
|
|
920
566
|
await device.delete();
|
|
921
567
|
}
|
|
@@ -935,4 +581,3 @@ export async function deleteDevice(owner, device, pause = 10) {
|
|
|
935
581
|
await flushAsync(undefined, undefined, pause);
|
|
936
582
|
return true;
|
|
937
583
|
}
|
|
938
|
-
//# sourceMappingURL=jestHelpers.js.map
|