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