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