@iobroker/testing 5.3.0 → 6.0.0
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
CHANGED
|
@@ -7,7 +7,7 @@ This repo provides utilities for testing of ioBroker adapters and other ioBroker
|
|
|
7
7
|
|
|
8
8
|
The unit tests are realized using the following tools that are provided by this module:
|
|
9
9
|
|
|
10
|
-
- A mock database
|
|
10
|
+
- A mock database that implements the most basic functionality of `ioBroker`'s Objects and States DB by operating on `Map` objects.
|
|
11
11
|
- A mock `Adapter` that is connected to the mock database. It implements basic functionality of the real `Adapter` class, but only operates on the mock database.
|
|
12
12
|
|
|
13
13
|
Predefined methods for both unit and integration tests are exported.
|
|
@@ -136,7 +136,7 @@ This method creates a mock database and a mock adapter. See below for a more det
|
|
|
136
136
|
const asserts = utils.unit.createAsserts(database, adapter);
|
|
137
137
|
```
|
|
138
138
|
|
|
139
|
-
These methods take a mock database and adapter and create a set of
|
|
139
|
+
These methods take a mock database and adapter and create a set of assertions for your tests. All IDs may either be a string, which is taken literally, or an array of strings which are concatenated with `"."`. If an ID is not fully qualified, the adapter namespace is prepended automatically.
|
|
140
140
|
|
|
141
141
|
- `assertObjectExists(id: string | string[])` asserts that an object with the given ID exists in the database.
|
|
142
142
|
- `assertStateExists(id: string | string[])` asserts that a state with the given ID exists in the database.
|
|
@@ -217,7 +217,7 @@ Resetting the mock between tests:
|
|
|
217
217
|
|
|
218
218
|
### Example
|
|
219
219
|
|
|
220
|
-
Here's an example how this can be used in a unit test:
|
|
220
|
+
Here's an example of how this can be used in a unit test:
|
|
221
221
|
|
|
222
222
|
```ts
|
|
223
223
|
import { tests, utils } from "@iobroker/testing";
|
|
@@ -5,9 +5,9 @@ export interface ExecuteCommandOptions {
|
|
|
5
5
|
cwd: string;
|
|
6
6
|
/** Where to redirect the stdin. Default: process.stdin */
|
|
7
7
|
stdin: NodeJS.ReadStream;
|
|
8
|
-
/** A
|
|
8
|
+
/** A writing stream to redirect the stdout, "ignore" to ignore it or "pipe" to return it as a string. Default: process.stdout */
|
|
9
9
|
stdout: NodeJS.WriteStream | 'pipe' | 'ignore';
|
|
10
|
-
/** A
|
|
10
|
+
/** A writing stream to redirect the stderr, "ignore" to ignore it or "pipe" to return it as a string. Default: process.stderr */
|
|
11
11
|
stderr: NodeJS.WriteStream | 'pipe' | 'ignore';
|
|
12
12
|
}
|
|
13
13
|
export interface ExecuteCommandResult {
|
|
@@ -19,6 +19,8 @@ export interface ExecuteCommandResult {
|
|
|
19
19
|
stdout?: string;
|
|
20
20
|
/** If options.stderr was set to "buffer", this contains the stderr of the spawned process */
|
|
21
21
|
stderr?: string;
|
|
22
|
+
/** The error that prevented the process from being spawned, if it could not be started at all */
|
|
23
|
+
error?: Error;
|
|
22
24
|
}
|
|
23
25
|
export declare function executeCommand(command: string, options?: Partial<ExecuteCommandOptions>): Promise<ExecuteCommandResult>;
|
|
24
26
|
/**
|
|
@@ -55,7 +55,22 @@ function executeCommand(command, argsOrOptions, options) {
|
|
|
55
55
|
try {
|
|
56
56
|
let bufferedStdout;
|
|
57
57
|
let bufferedStderr;
|
|
58
|
-
const cmd = (0, node_child_process_1.spawn)(command, args, spawnOptions)
|
|
58
|
+
const cmd = (0, node_child_process_1.spawn)(command, args, spawnOptions)
|
|
59
|
+
.on('error', error => {
|
|
60
|
+
// The process could not be spawned at all - e.g. the command does not
|
|
61
|
+
// exist or the cwd is missing. Without a listener, Node treats this as
|
|
62
|
+
// an unhandled 'error' event and tears down the entire test process
|
|
63
|
+
// with a stack trace from node:internal, which tells the adapter
|
|
64
|
+
// developer nothing about the actual cause.
|
|
65
|
+
// Node emits 'close' after 'error' in this case; that second resolve
|
|
66
|
+
// is a no-op because the promise is already settled.
|
|
67
|
+
resolve({
|
|
68
|
+
error,
|
|
69
|
+
stdout: bufferedStdout,
|
|
70
|
+
stderr: bufferedStderr,
|
|
71
|
+
});
|
|
72
|
+
})
|
|
73
|
+
.on('close', (code, signal) => {
|
|
59
74
|
resolve({
|
|
60
75
|
exitCode: code ?? undefined,
|
|
61
76
|
signal: signal ?? undefined,
|
|
@@ -83,8 +98,11 @@ function executeCommand(command, argsOrOptions, options) {
|
|
|
83
98
|
});
|
|
84
99
|
}
|
|
85
100
|
}
|
|
86
|
-
catch {
|
|
87
|
-
//
|
|
101
|
+
catch (error) {
|
|
102
|
+
// `spawn` can also throw synchronously, e.g. on invalid arguments. There is no
|
|
103
|
+
// child process in that case, so neither 'close' nor 'error' will ever fire and
|
|
104
|
+
// the promise would stay pending forever.
|
|
105
|
+
resolve({ error: error });
|
|
88
106
|
}
|
|
89
107
|
});
|
|
90
108
|
}
|
|
@@ -166,6 +166,12 @@ function validatePackageFiles(adapterDir) {
|
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
168
|
});
|
|
169
|
+
it('No "prepare" script is defined in package.json', () => {
|
|
170
|
+
if ((0, typeguards_1.isObject)(packageContent.scripts) && 'prepare' in packageContent.scripts) {
|
|
171
|
+
// eslint-disable-next-line @typescript-eslint/only-throw-error
|
|
172
|
+
throw new chai_1.AssertionError(`The "prepare" script must not be defined in the "scripts" section of package.json, found "${packageContent.scripts.prepare}"! It runs on every "npm install" of the adapter (including for end users) and can break installations.`);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
169
175
|
it('iobroker.js-controller is not listed as a dependency', () => {
|
|
170
176
|
for (const depType of [
|
|
171
177
|
'dependencies',
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iobroker/testing",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "Shared utilities for adapter and module testing in ioBroker",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
7
7
|
"files": [
|
|
8
8
|
"build/"
|
|
9
9
|
],
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=22.19.0"
|
|
12
|
+
},
|
|
10
13
|
"scripts": {
|
|
11
14
|
"test": "mocha \"src/**/*.test.ts\"",
|
|
12
15
|
"test:watch": "mocha \"src/**/*.test.ts\" --watch",
|
|
@@ -40,14 +43,14 @@
|
|
|
40
43
|
"homepage": "https://github.com/AlCalzone/testing#readme",
|
|
41
44
|
"devDependencies": {
|
|
42
45
|
"@alcalzone/release-script": "^5.2.1",
|
|
43
|
-
"@alcalzone/release-script-plugin-license": "^5.2.
|
|
44
|
-
"@iobroker/adapter-core": "^3.4.
|
|
46
|
+
"@alcalzone/release-script-plugin-license": "^5.2.2",
|
|
47
|
+
"@iobroker/adapter-core": "^3.4.3",
|
|
45
48
|
"@iobroker/eslint-config": "^2.3.4",
|
|
46
49
|
"@iobroker/types": "^7.2.2",
|
|
47
|
-
"@tsconfig/node18": "^18.2.
|
|
50
|
+
"@tsconfig/node18": "^18.2.7",
|
|
48
51
|
"@types/debug": "^4.1.13",
|
|
49
52
|
"@types/fs-extra": "^11.0.4",
|
|
50
|
-
"@types/node": "^
|
|
53
|
+
"@types/node": "^22.20.1",
|
|
51
54
|
"rimraf": "^6.1.3",
|
|
52
55
|
"source-map-support": "^0.5.21",
|
|
53
56
|
"ts-node": "^10.9.2",
|
|
@@ -64,10 +67,10 @@
|
|
|
64
67
|
"chai": "^4.5.0",
|
|
65
68
|
"chai-as-promised": "^7.1.2",
|
|
66
69
|
"debug": "^4.4.3",
|
|
67
|
-
"fs-extra": "^11.
|
|
70
|
+
"fs-extra": "^11.4.0",
|
|
68
71
|
"json5": "^2.2.3",
|
|
69
|
-
"mocha": "^
|
|
70
|
-
"sinon": "^22.
|
|
72
|
+
"mocha": "^12.0.0",
|
|
73
|
+
"sinon": "^22.1.0",
|
|
71
74
|
"sinon-chai": "^3.7.0"
|
|
72
75
|
}
|
|
73
76
|
}
|