@iobroker/testing 5.0.0 → 5.0.2
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/LICENSE +1 -1
- package/README.md +1 -1
- package/build/index.d.ts +1 -1
- package/build/lib/adapterTools.d.ts +7 -1
- package/build/lib/adapterTools.js +36 -21
- package/build/lib/executeCommand.d.ts +3 -2
- package/build/lib/executeCommand.js +30 -29
- package/build/lib/str2regex.js +4 -4
- package/build/tests/index.d.ts +9 -9
- package/build/tests/integration/index.d.ts +1 -1
- package/build/tests/integration/index.js +44 -39
- package/build/tests/integration/lib/adapterSetup.d.ts +1 -1
- package/build/tests/integration/lib/adapterSetup.js +50 -50
- package/build/tests/integration/lib/controllerSetup.d.ts +1 -10
- package/build/tests/integration/lib/controllerSetup.js +59 -56
- package/build/tests/integration/lib/dbConnection.d.ts +12 -12
- package/build/tests/integration/lib/dbConnection.js +71 -69
- package/build/tests/integration/lib/harness.d.ts +9 -7
- package/build/tests/integration/lib/harness.js +68 -49
- package/build/tests/integration/lib/logger.js +1 -1
- package/build/tests/integration/lib/tools.d.ts +6 -1
- package/build/tests/integration/lib/tools.js +27 -12
- package/build/tests/packageFiles/index.js +92 -90
- package/build/tests/unit/harness/createMocks.d.ts +3 -2
- package/build/tests/unit/harness/createMocks.js +0 -1
- package/build/tests/unit/index.js +5 -4
- package/build/tests/unit/mocks/mockAdapter.d.ts +3 -3
- package/build/tests/unit/mocks/mockAdapter.js +196 -162
- package/build/tests/unit/mocks/mockAdapterCore.d.ts +4 -9
- package/build/tests/unit/mocks/mockAdapterCore.js +23 -14
- package/build/tests/unit/mocks/mockDatabase.d.ts +13 -12
- package/build/tests/unit/mocks/mockDatabase.js +39 -43
- package/build/tests/unit/mocks/mockLogger.d.ts +1 -1
- package/build/tests/unit/mocks/mockLogger.js +1 -1
- package/build/tests/unit/mocks/tools.d.ts +2 -2
- package/build/tests/unit/mocks/tools.js +14 -11
- package/package.json +15 -22
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2024 AlCalzone <d.griesel@gmx.net>
|
|
3
|
+
Copyright (c) 2024-2025 AlCalzone <d.griesel@gmx.net>
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This repo provides utilities for testing of ioBroker adapters and other ioBroker-related modules. It supports:
|
|
4
4
|
|
|
5
|
-
- **Unit tests** using mocks (without a running JS-Controller)
|
|
5
|
+
- **Unit tests** using mocks (without a running JS-Controller) **deprecated** and no longer used
|
|
6
6
|
- **Integration tests** that test against a running JS-Controller instance.
|
|
7
7
|
|
|
8
8
|
The unit tests are realized using the following tools that are provided by this module:
|
package/build/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from
|
|
1
|
+
export * from './tests';
|
|
@@ -1,31 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Loads an adapter's package.json
|
|
3
|
+
*
|
|
3
4
|
* @param adapterDir The directory the adapter resides in
|
|
4
5
|
*/
|
|
5
6
|
export declare function loadNpmPackage(adapterDir: string): Record<string, any>;
|
|
6
7
|
/**
|
|
7
8
|
* Loads an adapter's io-package.json
|
|
9
|
+
*
|
|
8
10
|
* @param adapterDir The directory the adapter resides in
|
|
9
11
|
*/
|
|
10
12
|
export declare function loadIoPackage(adapterDir: string): Record<string, any>;
|
|
11
|
-
export declare function getAdapterExecutionMode(adapterDir: string): ioBroker.AdapterCommon[
|
|
13
|
+
export declare function getAdapterExecutionMode(adapterDir: string): ioBroker.AdapterCommon['mode'];
|
|
12
14
|
/**
|
|
13
15
|
* Locates an adapter's main file
|
|
16
|
+
*
|
|
14
17
|
* @param adapterDir The directory the adapter resides in
|
|
15
18
|
*/
|
|
16
19
|
export declare function locateAdapterMainFile(adapterDir: string): Promise<string>;
|
|
17
20
|
/**
|
|
18
21
|
* Locates an adapter's config to populate the `adapter.config` object with
|
|
22
|
+
*
|
|
19
23
|
* @param adapterDir The directory the adapter resides in
|
|
20
24
|
*/
|
|
21
25
|
export declare function loadAdapterConfig(adapterDir: string): Record<string, any>;
|
|
22
26
|
/**
|
|
23
27
|
* Loads the adapter's common configuration from `io-package.json`
|
|
28
|
+
*
|
|
24
29
|
* @param adapterDir The directory the adapter resides in
|
|
25
30
|
*/
|
|
26
31
|
export declare function loadAdapterCommon(adapterDir: string): Record<string, any>;
|
|
27
32
|
/**
|
|
28
33
|
* Loads the instanceObjects for an adapter from its `io-package.json`
|
|
34
|
+
*
|
|
29
35
|
* @param adapterDir The directory the adapter resides in
|
|
30
36
|
*/
|
|
31
37
|
export declare function loadInstanceObjects(adapterDir: string): ioBroker.Object[];
|
|
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
25
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
37
|
};
|
|
@@ -42,22 +52,22 @@ const typeguards_1 = require("alcalzone-shared/typeguards");
|
|
|
42
52
|
const debug_1 = __importDefault(require("debug"));
|
|
43
53
|
const fs_extra_1 = require("fs-extra");
|
|
44
54
|
const path = __importStar(require("path"));
|
|
45
|
-
const debug = (0, debug_1.default)(
|
|
55
|
+
const debug = (0, debug_1.default)('testing:unit:adapterTools');
|
|
46
56
|
/**
|
|
47
57
|
* Loads an adapter's package.json
|
|
58
|
+
*
|
|
48
59
|
* @param adapterDir The directory the adapter resides in
|
|
49
60
|
*/
|
|
50
61
|
function loadNpmPackage(adapterDir) {
|
|
51
|
-
|
|
52
|
-
return require(path.join(adapterDir, "package.json"));
|
|
62
|
+
return require(path.join(adapterDir, 'package.json'));
|
|
53
63
|
}
|
|
54
64
|
/**
|
|
55
65
|
* Loads an adapter's io-package.json
|
|
66
|
+
*
|
|
56
67
|
* @param adapterDir The directory the adapter resides in
|
|
57
68
|
*/
|
|
58
69
|
function loadIoPackage(adapterDir) {
|
|
59
|
-
|
|
60
|
-
return require(path.join(adapterDir, "io-package.json"));
|
|
70
|
+
return require(path.join(adapterDir, 'io-package.json'));
|
|
61
71
|
}
|
|
62
72
|
function getAdapterExecutionMode(adapterDir) {
|
|
63
73
|
const ioPackage = loadIoPackage(adapterDir);
|
|
@@ -65,6 +75,7 @@ function getAdapterExecutionMode(adapterDir) {
|
|
|
65
75
|
}
|
|
66
76
|
/**
|
|
67
77
|
* Locates an adapter's main file
|
|
78
|
+
*
|
|
68
79
|
* @param adapterDir The directory the adapter resides in
|
|
69
80
|
*/
|
|
70
81
|
async function locateAdapterMainFile(adapterDir) {
|
|
@@ -72,11 +83,11 @@ async function locateAdapterMainFile(adapterDir) {
|
|
|
72
83
|
const ioPackage = loadIoPackage(adapterDir);
|
|
73
84
|
const npmPackage = loadNpmPackage(adapterDir);
|
|
74
85
|
// First look for the file defined in io-package.json or package.json or use "main.js" as a fallback
|
|
75
|
-
const mainFile = typeof ioPackage.common.main ===
|
|
86
|
+
const mainFile = typeof ioPackage.common.main === 'string'
|
|
76
87
|
? ioPackage.common.main
|
|
77
|
-
: typeof npmPackage.main ===
|
|
88
|
+
: typeof npmPackage.main === 'string'
|
|
78
89
|
? npmPackage.main
|
|
79
|
-
:
|
|
90
|
+
: 'main.js';
|
|
80
91
|
let ret = path.join(adapterDir, mainFile);
|
|
81
92
|
debug(` => trying ${ret}`);
|
|
82
93
|
if (await (0, fs_extra_1.pathExists)(ret)) {
|
|
@@ -84,7 +95,7 @@ async function locateAdapterMainFile(adapterDir) {
|
|
|
84
95
|
return ret;
|
|
85
96
|
}
|
|
86
97
|
// If both don't exist, JS-Controller uses <adapter name>.js as another fallback
|
|
87
|
-
ret = path.join(adapterDir, ioPackage.common.name
|
|
98
|
+
ret = path.join(adapterDir, `${ioPackage.common.name}.js`);
|
|
88
99
|
debug(` => trying ${ret}`);
|
|
89
100
|
if (await (0, fs_extra_1.pathExists)(ret)) {
|
|
90
101
|
debug(` => found ${mainFile}`);
|
|
@@ -94,6 +105,7 @@ async function locateAdapterMainFile(adapterDir) {
|
|
|
94
105
|
}
|
|
95
106
|
/**
|
|
96
107
|
* Locates an adapter's config to populate the `adapter.config` object with
|
|
108
|
+
*
|
|
97
109
|
* @param adapterDir The directory the adapter resides in
|
|
98
110
|
*/
|
|
99
111
|
function loadAdapterConfig(adapterDir) {
|
|
@@ -102,6 +114,7 @@ function loadAdapterConfig(adapterDir) {
|
|
|
102
114
|
}
|
|
103
115
|
/**
|
|
104
116
|
* Loads the adapter's common configuration from `io-package.json`
|
|
117
|
+
*
|
|
105
118
|
* @param adapterDir The directory the adapter resides in
|
|
106
119
|
*/
|
|
107
120
|
function loadAdapterCommon(adapterDir) {
|
|
@@ -110,6 +123,7 @@ function loadAdapterCommon(adapterDir) {
|
|
|
110
123
|
}
|
|
111
124
|
/**
|
|
112
125
|
* Loads the instanceObjects for an adapter from its `io-package.json`
|
|
126
|
+
*
|
|
113
127
|
* @param adapterDir The directory the adapter resides in
|
|
114
128
|
*/
|
|
115
129
|
function loadInstanceObjects(adapterDir) {
|
|
@@ -119,7 +133,7 @@ function loadInstanceObjects(adapterDir) {
|
|
|
119
133
|
/** Returns the branded name of "iobroker" */
|
|
120
134
|
function getAppName(adapterDir) {
|
|
121
135
|
const npmPackage = loadNpmPackage(adapterDir);
|
|
122
|
-
return npmPackage.name.split(
|
|
136
|
+
return npmPackage.name.split('.')[0] || 'iobroker';
|
|
123
137
|
}
|
|
124
138
|
/** Returns the name of an adapter without the prefix */
|
|
125
139
|
function getAdapterName(adapterDir) {
|
|
@@ -137,13 +151,14 @@ function getAdapterDependencies(adapterDir) {
|
|
|
137
151
|
const ret = {};
|
|
138
152
|
if ((0, typeguards_1.isArray)(ioPackage.common.dependencies)) {
|
|
139
153
|
for (const dep of ioPackage.common.dependencies) {
|
|
140
|
-
if (typeof dep ===
|
|
141
|
-
ret[dep] =
|
|
154
|
+
if (typeof dep === 'string') {
|
|
155
|
+
ret[dep] = 'latest';
|
|
142
156
|
}
|
|
143
157
|
else if ((0, typeguards_1.isObject)(dep)) {
|
|
144
158
|
const key = Object.keys(dep)[0];
|
|
145
|
-
if (key)
|
|
146
|
-
ret[key] = dep[key] ||
|
|
159
|
+
if (key) {
|
|
160
|
+
ret[key] = dep[key] || 'latest';
|
|
161
|
+
}
|
|
147
162
|
}
|
|
148
163
|
}
|
|
149
164
|
}
|
|
@@ -6,9 +6,9 @@ export interface ExecuteCommandOptions {
|
|
|
6
6
|
/** Where to redirect the stdin. Default: process.stdin */
|
|
7
7
|
stdin: NodeJS.ReadStream;
|
|
8
8
|
/** A write stream to redirect the stdout, "ignore" to ignore it or "pipe" to return it as a string. Default: process.stdout */
|
|
9
|
-
stdout: NodeJS.WriteStream |
|
|
9
|
+
stdout: NodeJS.WriteStream | 'pipe' | 'ignore';
|
|
10
10
|
/** A write stream to redirect the stderr, "ignore" to ignore it or "pipe" to return it as a string. Default: process.stderr */
|
|
11
|
-
stderr: NodeJS.WriteStream |
|
|
11
|
+
stderr: NodeJS.WriteStream | 'pipe' | 'ignore';
|
|
12
12
|
}
|
|
13
13
|
export interface ExecuteCommandResult {
|
|
14
14
|
/** The exit code of the spawned process */
|
|
@@ -23,6 +23,7 @@ export interface ExecuteCommandResult {
|
|
|
23
23
|
export declare function executeCommand(command: string, options?: Partial<ExecuteCommandOptions>): Promise<ExecuteCommandResult>;
|
|
24
24
|
/**
|
|
25
25
|
* Executes a command and returns the exit code and (if requested) the stdout
|
|
26
|
+
*
|
|
26
27
|
* @param command The command to execute
|
|
27
28
|
* @param args The command line arguments for the command
|
|
28
29
|
* @param options (optional) Some options for the command execution
|
|
@@ -1,55 +1,54 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.executeCommand = executeCommand;
|
|
4
|
-
const typeguards_1 = require("alcalzone-shared/typeguards");
|
|
5
4
|
const child_process_1 = require("child_process");
|
|
6
5
|
const isWindows = /^win/.test(process.platform);
|
|
7
6
|
function executeCommand(command, argsOrOptions, options) {
|
|
8
|
-
return new Promise(
|
|
7
|
+
return new Promise(resolve => {
|
|
9
8
|
let args;
|
|
10
|
-
if (
|
|
9
|
+
if (Array.isArray(argsOrOptions)) {
|
|
11
10
|
args = argsOrOptions;
|
|
12
11
|
}
|
|
13
|
-
else if (
|
|
12
|
+
else if (argsOrOptions && typeof argsOrOptions === 'object') {
|
|
14
13
|
// no args were given
|
|
15
14
|
options = argsOrOptions;
|
|
16
15
|
}
|
|
17
|
-
if (options == null)
|
|
16
|
+
if (options == null) {
|
|
18
17
|
options = {};
|
|
19
|
-
|
|
18
|
+
}
|
|
19
|
+
if (args == null) {
|
|
20
20
|
args = [];
|
|
21
|
+
}
|
|
21
22
|
const spawnOptions = {
|
|
22
|
-
stdio: [
|
|
23
|
-
options.stdin || process.stdin,
|
|
24
|
-
options.stdout || process.stdout,
|
|
25
|
-
options.stderr || process.stderr,
|
|
26
|
-
],
|
|
23
|
+
stdio: [options.stdin || process.stdin, options.stdout || process.stdout, options.stderr || process.stderr],
|
|
27
24
|
windowsHide: true,
|
|
28
25
|
};
|
|
29
|
-
if (options.cwd != null)
|
|
26
|
+
if (options.cwd != null) {
|
|
30
27
|
spawnOptions.cwd = options.cwd;
|
|
28
|
+
}
|
|
31
29
|
// Fix npm / node executable paths on Windows
|
|
32
30
|
if (isWindows) {
|
|
33
|
-
if (command ===
|
|
34
|
-
command +=
|
|
31
|
+
if (command === 'npm') {
|
|
32
|
+
command += '.cmd';
|
|
35
33
|
// Needed since Node.js v18.20.2 and v20.12.2
|
|
36
34
|
// https://github.com/nodejs/node/releases/tag/v18.20.2
|
|
37
35
|
spawnOptions.shell = true;
|
|
38
36
|
}
|
|
39
|
-
else if (command ===
|
|
40
|
-
command +=
|
|
37
|
+
else if (command === 'node') {
|
|
38
|
+
command += '.exe';
|
|
41
39
|
}
|
|
42
40
|
}
|
|
43
|
-
if (options.logCommandExecution == null)
|
|
41
|
+
if (options.logCommandExecution == null) {
|
|
44
42
|
options.logCommandExecution = false;
|
|
43
|
+
}
|
|
45
44
|
if (options.logCommandExecution) {
|
|
46
|
-
console.log(
|
|
45
|
+
console.log(`executing: ${command} ${args.join(' ')}`);
|
|
47
46
|
}
|
|
48
47
|
// Now execute the npm process and avoid throwing errors
|
|
49
48
|
try {
|
|
50
49
|
let bufferedStdout;
|
|
51
50
|
let bufferedStderr;
|
|
52
|
-
const cmd = (0, child_process_1.spawn)(command, args, spawnOptions).on(
|
|
51
|
+
const cmd = (0, child_process_1.spawn)(command, args, spawnOptions).on('close', (code, signal) => {
|
|
53
52
|
resolve({
|
|
54
53
|
exitCode: code ?? undefined,
|
|
55
54
|
signal: signal ?? undefined,
|
|
@@ -58,19 +57,21 @@ function executeCommand(command, argsOrOptions, options) {
|
|
|
58
57
|
});
|
|
59
58
|
});
|
|
60
59
|
// Capture stdout/stderr if requested
|
|
61
|
-
if (options.stdout ===
|
|
62
|
-
bufferedStdout =
|
|
63
|
-
cmd.stdout.on(
|
|
64
|
-
if (Buffer.isBuffer(chunk))
|
|
65
|
-
chunk = chunk.toString(
|
|
60
|
+
if (options.stdout === 'pipe') {
|
|
61
|
+
bufferedStdout = '';
|
|
62
|
+
cmd.stdout.on('data', (chunk) => {
|
|
63
|
+
if (Buffer.isBuffer(chunk)) {
|
|
64
|
+
chunk = chunk.toString('utf8');
|
|
65
|
+
}
|
|
66
66
|
bufferedStdout += chunk;
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
|
-
if (options.stderr ===
|
|
70
|
-
bufferedStderr =
|
|
71
|
-
cmd.stderr.on(
|
|
72
|
-
if (Buffer.isBuffer(chunk))
|
|
73
|
-
chunk = chunk.toString(
|
|
69
|
+
if (options.stderr === 'pipe') {
|
|
70
|
+
bufferedStderr = '';
|
|
71
|
+
cmd.stderr.on('data', (chunk) => {
|
|
72
|
+
if (Buffer.isBuffer(chunk)) {
|
|
73
|
+
chunk = chunk.toString('utf8');
|
|
74
|
+
}
|
|
74
75
|
bufferedStderr += chunk;
|
|
75
76
|
});
|
|
76
77
|
}
|
package/build/lib/str2regex.js
CHANGED
|
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.str2regex = str2regex;
|
|
4
4
|
function str2regex(pattern) {
|
|
5
5
|
return new RegExp(pattern
|
|
6
|
-
.replace(/\\/g,
|
|
7
|
-
.replace(/\./g,
|
|
8
|
-
.replace(/\*/g,
|
|
9
|
-
.replace(/!/g,
|
|
6
|
+
.replace(/\\/g, '\\\\') // Backslashes escapen
|
|
7
|
+
.replace(/\./g, '\\.') // Punkte als solche matchen
|
|
8
|
+
.replace(/\*/g, '.*') // Wildcard in Regex umsetzen
|
|
9
|
+
.replace(/!/g, '?!'));
|
|
10
10
|
}
|
package/build/tests/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { testAdapter } from
|
|
2
|
-
import { validatePackageFiles } from
|
|
3
|
-
import { testAdapterWithMocks } from
|
|
4
|
-
import { createMocks } from
|
|
5
|
-
import { createAsserts } from
|
|
6
|
-
export { TestHarness as IntegrationTestHarness } from
|
|
7
|
-
export { MockAdapter } from
|
|
8
|
-
export { MockDatabase } from
|
|
1
|
+
import { testAdapter } from './integration';
|
|
2
|
+
import { validatePackageFiles } from './packageFiles';
|
|
3
|
+
import { testAdapterWithMocks } from './unit';
|
|
4
|
+
import { createMocks } from './unit/harness/createMocks';
|
|
5
|
+
import { createAsserts } from './unit/mocks/mockDatabase';
|
|
6
|
+
export { TestHarness as IntegrationTestHarness } from './integration/lib/harness';
|
|
7
|
+
export type { MockAdapter } from './unit/mocks/mockAdapter';
|
|
8
|
+
export { MockDatabase } from './unit/mocks/mockDatabase';
|
|
9
9
|
/** Predefined test sets */
|
|
10
10
|
export declare const tests: {
|
|
11
11
|
/** @deprecated Adapter startup unit tests are no longer supported */
|
|
@@ -19,6 +19,6 @@ export declare const utils: {
|
|
|
19
19
|
createMocks: typeof createMocks;
|
|
20
20
|
createAsserts: typeof createAsserts;
|
|
21
21
|
/** @deprecated Adapter startup unit tests are no longer supported */
|
|
22
|
-
startMockAdapter: () =>
|
|
22
|
+
startMockAdapter: () => any;
|
|
23
23
|
};
|
|
24
24
|
};
|
|
@@ -15,16 +15,25 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
25
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
36
|
exports.testAdapter = testAdapter;
|
|
27
|
-
const async_1 = require("alcalzone-shared/async");
|
|
28
37
|
const os = __importStar(require("os"));
|
|
29
38
|
const path = __importStar(require("path"));
|
|
30
39
|
const adapterTools_1 = require("../../lib/adapterTools");
|
|
@@ -52,7 +61,7 @@ function testAdapter(adapterDir, options = {}) {
|
|
|
52
61
|
const oneMinute = 60000;
|
|
53
62
|
this.timeout(30 * oneMinute);
|
|
54
63
|
if (await controllerSetup.isJsControllerRunning()) {
|
|
55
|
-
throw new Error(
|
|
64
|
+
throw new Error('JS-Controller is already running! Stop it for the first test run and try again!');
|
|
56
65
|
}
|
|
57
66
|
const adapterSetup = new adapterSetup_1.AdapterSetup(adapterDir, testDir);
|
|
58
67
|
// Installation happens in two steps:
|
|
@@ -62,7 +71,7 @@ function testAdapter(adapterDir, options = {}) {
|
|
|
62
71
|
// Only then we can install the adapter, because some (including VIS) try to access
|
|
63
72
|
// the databases if JS Controller is installed
|
|
64
73
|
await adapterSetup.installAdapterInTestDir();
|
|
65
|
-
const dbConnection = new dbConnection_1.DBConnection(appName, testDir, (0, logger_1.createLogger)(options.loglevel ??
|
|
74
|
+
const dbConnection = new dbConnection_1.DBConnection(appName, testDir, (0, logger_1.createLogger)(options.loglevel ?? 'debug'));
|
|
66
75
|
await dbConnection.start();
|
|
67
76
|
controllerSetup.setupSystemConfig(dbConnection);
|
|
68
77
|
await controllerSetup.disableAdminInstances(dbConnection);
|
|
@@ -70,8 +79,7 @@ function testAdapter(adapterDir, options = {}) {
|
|
|
70
79
|
await adapterSetup.addAdapterInstance();
|
|
71
80
|
await dbConnection.stop();
|
|
72
81
|
// Create a copy of the databases that we can restore later
|
|
73
|
-
({ objects: objectsBackup, states: statesBackup } =
|
|
74
|
-
await dbConnection.backup());
|
|
82
|
+
({ objects: objectsBackup, states: statesBackup } = await dbConnection.backup());
|
|
75
83
|
}
|
|
76
84
|
async function shutdownTests() {
|
|
77
85
|
// Stopping the processes may take a while
|
|
@@ -82,7 +90,7 @@ function testAdapter(adapterDir, options = {}) {
|
|
|
82
90
|
}
|
|
83
91
|
async function resetDbAndStartHarness() {
|
|
84
92
|
this.timeout(30000);
|
|
85
|
-
dbConnection = new dbConnection_1.DBConnection(appName, testDir, (0, logger_1.createLogger)(options.loglevel ??
|
|
93
|
+
dbConnection = new dbConnection_1.DBConnection(appName, testDir, (0, logger_1.createLogger)(options.loglevel ?? 'debug'));
|
|
86
94
|
// Clean up before every single test
|
|
87
95
|
await Promise.all([
|
|
88
96
|
controllerSetup.clearDBDir(),
|
|
@@ -96,7 +104,7 @@ function testAdapter(adapterDir, options = {}) {
|
|
|
96
104
|
await harness.changeAdapterConfig(adapterName, {
|
|
97
105
|
common: {
|
|
98
106
|
enabled: true,
|
|
99
|
-
loglevel: options.loglevel ??
|
|
107
|
+
loglevel: options.loglevel ?? 'debug',
|
|
100
108
|
},
|
|
101
109
|
});
|
|
102
110
|
// And enable the sendTo emulation
|
|
@@ -104,60 +112,57 @@ function testAdapter(adapterDir, options = {}) {
|
|
|
104
112
|
}
|
|
105
113
|
describe(`Adapter integration tests`, () => {
|
|
106
114
|
before(prepareTests);
|
|
107
|
-
describe(
|
|
115
|
+
describe('Adapter startup', () => {
|
|
108
116
|
beforeEach(resetDbAndStartHarness);
|
|
109
117
|
afterEach(shutdownTests);
|
|
110
|
-
it(
|
|
118
|
+
it('The adapter starts', function () {
|
|
111
119
|
this.timeout(60000);
|
|
112
120
|
const allowedExitCodes = new Set(options.allowedExitCodes ?? []);
|
|
113
121
|
// Adapters with these modes are allowed to "immediately" exit with code 0
|
|
114
122
|
switch (harness.getAdapterExecutionMode()) {
|
|
115
|
-
case
|
|
116
|
-
|
|
123
|
+
case 'schedule':
|
|
124
|
+
allowedExitCodes.add(0);
|
|
125
|
+
break;
|
|
126
|
+
case 'once':
|
|
127
|
+
allowedExitCodes.add(0);
|
|
128
|
+
break;
|
|
117
129
|
// @ts-expect-error subscribe was deprecated
|
|
118
|
-
case
|
|
130
|
+
case 'subscribe':
|
|
119
131
|
allowedExitCodes.add(0);
|
|
132
|
+
break;
|
|
120
133
|
}
|
|
121
134
|
return new Promise((resolve, reject) => {
|
|
122
135
|
// Register a handler to check the alive state and exit codes
|
|
123
136
|
harness
|
|
124
|
-
.on(
|
|
125
|
-
if (id ===
|
|
126
|
-
`system.adapter.${adapterName}.0.alive` &&
|
|
127
|
-
state &&
|
|
128
|
-
state.val === true) {
|
|
137
|
+
.on('stateChange', async (id, state) => {
|
|
138
|
+
if (id === `system.adapter.${adapterName}.0.alive` && state && state.val === true) {
|
|
129
139
|
// Wait a bit so we can catch errors that do not happen immediately
|
|
130
|
-
await (
|
|
131
|
-
undefined
|
|
140
|
+
await new Promise(resolve => setTimeout(resolve, options.waitBeforeStartupSuccess !== undefined
|
|
132
141
|
? options.waitBeforeStartupSuccess
|
|
133
|
-
: 5000);
|
|
142
|
+
: 5000));
|
|
134
143
|
resolve(`The adapter started successfully.`);
|
|
135
144
|
}
|
|
136
145
|
})
|
|
137
|
-
.on(
|
|
146
|
+
.on('failed', code => {
|
|
138
147
|
if (!allowedExitCodes.has(code)) {
|
|
139
|
-
reject(new Error(`The adapter startup was interrupted unexpectedly with ${typeof code ===
|
|
140
|
-
? "code"
|
|
141
|
-
: "signal"} ${code}`));
|
|
148
|
+
reject(new Error(`The adapter startup was interrupted unexpectedly with ${typeof code === 'number' ? 'code' : 'signal'} ${code}`));
|
|
142
149
|
}
|
|
143
150
|
else {
|
|
144
151
|
// This was a valid exit code
|
|
145
|
-
resolve(`The expected ${typeof code ===
|
|
146
|
-
? "exit code"
|
|
147
|
-
: "signal"} ${code} was received.`);
|
|
152
|
+
resolve(`The expected ${typeof code === 'number' ? 'exit code' : 'signal'} ${code} was received.`);
|
|
148
153
|
}
|
|
149
154
|
});
|
|
150
|
-
harness.startAdapter();
|
|
151
|
-
}).then(
|
|
155
|
+
void harness.startAdapter();
|
|
156
|
+
}).then(msg => console.log(msg));
|
|
152
157
|
});
|
|
153
158
|
});
|
|
154
159
|
// Call the user's tests
|
|
155
|
-
if (typeof options.defineAdditionalTests ===
|
|
160
|
+
if (typeof options.defineAdditionalTests === 'function') {
|
|
156
161
|
const originalIt = global.it;
|
|
157
162
|
// Ensure no it() gets called outside of a suite()
|
|
158
163
|
function assertSuite() {
|
|
159
164
|
if (!isInSuite) {
|
|
160
|
-
throw new Error(
|
|
165
|
+
throw new Error('In user-defined adapter tests, it() must NOT be called outside of a suite()');
|
|
161
166
|
}
|
|
162
167
|
}
|
|
163
168
|
const patchedIt = new Proxy(originalIt, {
|
|
@@ -170,7 +175,7 @@ function testAdapter(adapterDir, options = {}) {
|
|
|
170
175
|
return target[propKey];
|
|
171
176
|
},
|
|
172
177
|
});
|
|
173
|
-
describe(
|
|
178
|
+
describe('User-defined tests', () => {
|
|
174
179
|
// patch the global it() function so nobody can bypass the checks
|
|
175
180
|
global.it = patchedIt;
|
|
176
181
|
// a test suite is a special describe which sets up and tears down the test environment before and after ALL tests
|