@iobroker/testing 3.0.2 → 4.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 +9 -0
- package/build/lib/executeCommand.js +2 -2
- package/build/tests/integration/index.d.ts +10 -1
- package/build/tests/integration/index.js +23 -17
- package/build/tests/integration/lib/dbConnection.d.ts +2 -0
- package/build/tests/integration/lib/dbConnection.js +8 -11
- package/build/tests/integration/lib/harness.d.ts +3 -0
- package/build/tests/integration/lib/harness.js +1 -2
- package/build/tests/integration/lib/logger.js +1 -2
- package/build/tests/packageFiles/index.js +3 -5
- package/build/tests/unit/mocks/mockDatabase.d.ts +1 -0
- package/build/tests/unit/mocks/tools.d.ts +1 -1
- package/package.json +16 -16
- package/CHANGELOG.md +0 -69
package/README.md
CHANGED
|
@@ -70,6 +70,15 @@ tests.integration(path.join(__dirname, ".."), {
|
|
|
70
70
|
});
|
|
71
71
|
});
|
|
72
72
|
});
|
|
73
|
+
|
|
74
|
+
// While developing the tests, you can run only a single suite using `suite.only`...
|
|
75
|
+
suite.only("Only this will run", (getHarness) => {
|
|
76
|
+
// ...
|
|
77
|
+
});
|
|
78
|
+
// ...or prevent a suite from running using `suite.skip`:
|
|
79
|
+
suite.skip("This will never run", (getHarness) => {
|
|
80
|
+
// ...
|
|
81
|
+
});
|
|
73
82
|
},
|
|
74
83
|
});
|
|
75
84
|
```
|
|
@@ -46,8 +46,8 @@ function executeCommand(command, argsOrOptions, options) {
|
|
|
46
46
|
let bufferedStderr;
|
|
47
47
|
const cmd = (0, child_process_1.spawn)(command, args, spawnOptions).on("close", (code, signal) => {
|
|
48
48
|
resolve({
|
|
49
|
-
exitCode: code
|
|
50
|
-
signal: signal
|
|
49
|
+
exitCode: code ?? undefined,
|
|
50
|
+
signal: signal ?? undefined,
|
|
51
51
|
stdout: bufferedStdout,
|
|
52
52
|
stderr: bufferedStderr,
|
|
53
53
|
});
|
|
@@ -10,6 +10,15 @@ export interface TestAdapterOptions {
|
|
|
10
10
|
/** Allows you to define additional tests */
|
|
11
11
|
defineAdditionalTests?: (args: TestContext) => void;
|
|
12
12
|
}
|
|
13
|
+
export interface TestSuiteFn {
|
|
14
|
+
(name: string, fn: (getHarness: () => TestHarness) => void): void;
|
|
15
|
+
}
|
|
16
|
+
export interface TestSuite extends TestSuiteFn {
|
|
17
|
+
/** Only runs the tests inside this `suite` for the current file */
|
|
18
|
+
only: TestSuiteFn;
|
|
19
|
+
/** Skips running the tests inside this `suite` for the current file */
|
|
20
|
+
skip: TestSuiteFn;
|
|
21
|
+
}
|
|
13
22
|
export interface TestContext {
|
|
14
23
|
/**
|
|
15
24
|
* Defines a test suite. At the start of each suite, the adapter will be started with a fresh environment.
|
|
@@ -17,7 +26,7 @@ export interface TestContext {
|
|
|
17
26
|
*
|
|
18
27
|
* Each suite has its own test harness, which can be retrieved using the function that is passed to the suite callback.
|
|
19
28
|
*/
|
|
20
|
-
suite:
|
|
29
|
+
suite: TestSuite;
|
|
21
30
|
describe: Mocha.SuiteFunction;
|
|
22
31
|
it: Mocha.TestFunction;
|
|
23
32
|
}
|
|
@@ -48,7 +48,6 @@ function testAdapter(adapterDir, options = {}) {
|
|
|
48
48
|
console.log(`Running tests in ${testDir}`);
|
|
49
49
|
console.log();
|
|
50
50
|
async function prepareTests() {
|
|
51
|
-
var _a;
|
|
52
51
|
// Installation may take a while - especially if rsa-compat needs to be installed
|
|
53
52
|
const oneMinute = 60000;
|
|
54
53
|
this.timeout(30 * oneMinute);
|
|
@@ -63,7 +62,7 @@ function testAdapter(adapterDir, options = {}) {
|
|
|
63
62
|
// Only then we can install the adapter, because some (including VIS) try to access
|
|
64
63
|
// the databases if JS Controller is installed
|
|
65
64
|
await adapterSetup.installAdapterInTestDir();
|
|
66
|
-
const dbConnection = new dbConnection_1.DBConnection(appName, testDir, (0, logger_1.createLogger)(
|
|
65
|
+
const dbConnection = new dbConnection_1.DBConnection(appName, testDir, (0, logger_1.createLogger)(options.loglevel ?? "debug"));
|
|
67
66
|
await dbConnection.start();
|
|
68
67
|
controllerSetup.setupSystemConfig(dbConnection);
|
|
69
68
|
await controllerSetup.disableAdminInstances(dbConnection);
|
|
@@ -82,9 +81,8 @@ function testAdapter(adapterDir, options = {}) {
|
|
|
82
81
|
harness.removeAllListeners();
|
|
83
82
|
}
|
|
84
83
|
async function resetDbAndStartHarness() {
|
|
85
|
-
var _a, _b;
|
|
86
84
|
this.timeout(30000);
|
|
87
|
-
dbConnection = new dbConnection_1.DBConnection(appName, testDir, (0, logger_1.createLogger)(
|
|
85
|
+
dbConnection = new dbConnection_1.DBConnection(appName, testDir, (0, logger_1.createLogger)(options.loglevel ?? "debug"));
|
|
88
86
|
// Clean up before every single test
|
|
89
87
|
await Promise.all([
|
|
90
88
|
controllerSetup.clearDBDir(),
|
|
@@ -98,7 +96,7 @@ function testAdapter(adapterDir, options = {}) {
|
|
|
98
96
|
await harness.changeAdapterConfig(adapterName, {
|
|
99
97
|
common: {
|
|
100
98
|
enabled: true,
|
|
101
|
-
loglevel:
|
|
99
|
+
loglevel: options.loglevel ?? "debug",
|
|
102
100
|
},
|
|
103
101
|
});
|
|
104
102
|
// And enable the sendTo emulation
|
|
@@ -110,9 +108,8 @@ function testAdapter(adapterDir, options = {}) {
|
|
|
110
108
|
beforeEach(resetDbAndStartHarness);
|
|
111
109
|
afterEach(shutdownTests);
|
|
112
110
|
it("The adapter starts", function () {
|
|
113
|
-
var _a;
|
|
114
111
|
this.timeout(60000);
|
|
115
|
-
const allowedExitCodes = new Set(
|
|
112
|
+
const allowedExitCodes = new Set(options.allowedExitCodes ?? []);
|
|
116
113
|
// Adapters with these modes are allowed to "immediately" exit with code 0
|
|
117
114
|
switch (harness.getAdapterExecutionMode()) {
|
|
118
115
|
case "schedule":
|
|
@@ -175,17 +172,26 @@ function testAdapter(adapterDir, options = {}) {
|
|
|
175
172
|
describe("User-defined tests", () => {
|
|
176
173
|
// patch the global it() function so nobody can bypass the checks
|
|
177
174
|
global.it = patchedIt;
|
|
175
|
+
// a test suite is a special describe which sets up and tears down the test environment before and after ALL tests
|
|
176
|
+
const suiteBody = (fn) => {
|
|
177
|
+
isInSuite = true;
|
|
178
|
+
before(resetDbAndStartHarness);
|
|
179
|
+
fn(() => harness);
|
|
180
|
+
after(shutdownTests);
|
|
181
|
+
isInSuite = false;
|
|
182
|
+
};
|
|
183
|
+
const suite = ((name, fn) => {
|
|
184
|
+
describe(name, () => suiteBody(fn));
|
|
185
|
+
});
|
|
186
|
+
// Support .skip and .only
|
|
187
|
+
suite.skip = (name, fn) => {
|
|
188
|
+
describe.skip(name, () => suiteBody(fn));
|
|
189
|
+
};
|
|
190
|
+
suite.only = (name, fn) => {
|
|
191
|
+
describe.only(name, () => suiteBody(fn));
|
|
192
|
+
};
|
|
178
193
|
const args = {
|
|
179
|
-
|
|
180
|
-
suite: (name, fn) => {
|
|
181
|
-
describe(name, () => {
|
|
182
|
-
isInSuite = true;
|
|
183
|
-
before(resetDbAndStartHarness);
|
|
184
|
-
fn(() => harness);
|
|
185
|
-
after(shutdownTests);
|
|
186
|
-
isInSuite = false;
|
|
187
|
-
});
|
|
188
|
-
},
|
|
194
|
+
suite,
|
|
189
195
|
describe,
|
|
190
196
|
it: patchedIt,
|
|
191
197
|
};
|
|
@@ -152,17 +152,16 @@ class DBConnection extends events_1.default {
|
|
|
152
152
|
debug("DB instances started");
|
|
153
153
|
}
|
|
154
154
|
async stop() {
|
|
155
|
-
var _a, _b, _c, _d;
|
|
156
155
|
if (!this._isRunning) {
|
|
157
156
|
debug("No DB instance is running, nothing to stop...");
|
|
158
157
|
return;
|
|
159
158
|
}
|
|
160
159
|
debug("Stopping DB instances...");
|
|
161
160
|
// Stop clients before servers
|
|
162
|
-
await
|
|
163
|
-
await
|
|
164
|
-
await
|
|
165
|
-
await
|
|
161
|
+
await this._objectsClient?.destroy();
|
|
162
|
+
await this._objectsServer?.destroy();
|
|
163
|
+
await this._statesClient?.destroy();
|
|
164
|
+
await this._statesServer?.destroy();
|
|
166
165
|
this._objectsClient = null;
|
|
167
166
|
this._objectsServer = null;
|
|
168
167
|
this._statesClient = null;
|
|
@@ -279,20 +278,18 @@ class DBConnection extends events_1.default {
|
|
|
279
278
|
this._statesClient.pushMessage(instanceId, msg, callback);
|
|
280
279
|
}
|
|
281
280
|
async getStateIDs(pattern = "*") {
|
|
282
|
-
var _a, _b, _c, _d;
|
|
283
281
|
if (!this._statesClient) {
|
|
284
282
|
throw new Error("States DB is not running");
|
|
285
283
|
}
|
|
286
|
-
return (
|
|
287
|
-
|
|
284
|
+
return (this._statesClient.getKeysAsync?.(pattern) ||
|
|
285
|
+
this._statesClient.getKeys?.(pattern));
|
|
288
286
|
}
|
|
289
287
|
async getObjectIDs(pattern = "*") {
|
|
290
|
-
var _a, _b, _c, _d;
|
|
291
288
|
if (!this._objectsClient) {
|
|
292
289
|
throw new Error("Objects DB is not running");
|
|
293
290
|
}
|
|
294
|
-
return (
|
|
295
|
-
|
|
291
|
+
return (this._objectsClient.getKeysAsync?.(pattern) ||
|
|
292
|
+
this._objectsClient.getKeys?.(pattern));
|
|
296
293
|
}
|
|
297
294
|
}
|
|
298
295
|
exports.DBConnection = DBConnection;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/// <reference types="iobroker" />
|
|
2
2
|
/// <reference types="node" />
|
|
3
|
+
/// <reference types="node" />
|
|
4
|
+
/// <reference types="iobroker" />
|
|
5
|
+
/// <reference types="node" />
|
|
3
6
|
import { ChildProcess } from "child_process";
|
|
4
7
|
import { EventEmitter } from "events";
|
|
5
8
|
import type { DBConnection } from "./dbConnection";
|
|
@@ -190,7 +190,6 @@ class TestHarness extends events_1.EventEmitter {
|
|
|
190
190
|
if (!this.isAdapterRunning())
|
|
191
191
|
return;
|
|
192
192
|
return new Promise(async (resolve) => {
|
|
193
|
-
var _a;
|
|
194
193
|
const onClose = (code, signal) => {
|
|
195
194
|
if (!this._adapterProcess)
|
|
196
195
|
return;
|
|
@@ -214,7 +213,7 @@ class TestHarness extends events_1.EventEmitter {
|
|
|
214
213
|
}
|
|
215
214
|
catch {
|
|
216
215
|
// DB connection may be closed already, kill the process
|
|
217
|
-
|
|
216
|
+
this._adapterProcess?.kill("SIGTERM");
|
|
218
217
|
}
|
|
219
218
|
});
|
|
220
219
|
}
|
|
@@ -10,8 +10,7 @@ var LoglevelOrder;
|
|
|
10
10
|
LoglevelOrder[LoglevelOrder["silly"] = 4] = "silly";
|
|
11
11
|
})(LoglevelOrder || (LoglevelOrder = {}));
|
|
12
12
|
function createLogger(loglevel) {
|
|
13
|
-
|
|
14
|
-
const loglevelNumeric = (_a = LoglevelOrder[loglevel !== null && loglevel !== void 0 ? loglevel : "debug"]) !== null && _a !== void 0 ? _a : LoglevelOrder.debug;
|
|
13
|
+
const loglevelNumeric = LoglevelOrder[loglevel ?? "debug"] ?? LoglevelOrder.debug;
|
|
15
14
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
16
15
|
const ignore = () => { };
|
|
17
16
|
return {
|
|
@@ -130,7 +130,6 @@ function validatePackageFiles(adapterDir) {
|
|
|
130
130
|
});
|
|
131
131
|
});
|
|
132
132
|
describe(`Check contents of io-package.json`, () => {
|
|
133
|
-
var _a;
|
|
134
133
|
beforeEach(function () {
|
|
135
134
|
skipIfInvalid.call(this, "io-package.json");
|
|
136
135
|
});
|
|
@@ -178,13 +177,12 @@ function validatePackageFiles(adapterDir) {
|
|
|
178
177
|
// If the adapter has a configuration page, check that a supported admin UI is used
|
|
179
178
|
const hasNoConfigPage = iopackContent.common.noConfig === true ||
|
|
180
179
|
iopackContent.common.noConfig === "true" ||
|
|
181
|
-
|
|
180
|
+
iopackContent.common.adminUI?.config === "none";
|
|
182
181
|
if (!hasNoConfigPage) {
|
|
183
182
|
it("The adapter uses Material UI or JSON Config for the admin UI", () => {
|
|
184
|
-
var _a, _b;
|
|
185
183
|
const hasSupportedUI = !!iopackContent.common.materialize ||
|
|
186
|
-
|
|
187
|
-
|
|
184
|
+
iopackContent.common.adminUI?.config === "json" ||
|
|
185
|
+
iopackContent.common.adminUI?.config === "materialize";
|
|
188
186
|
(0, chai_1.expect)(hasSupportedUI, "Unsupported Admin UI, must be materialize or json config!").to.be.true;
|
|
189
187
|
});
|
|
190
188
|
}
|
|
@@ -4,7 +4,7 @@ export declare type IsAny<T> = Equals<T extends never ? false : true, boolean>;
|
|
|
4
4
|
export declare type MockableMethods<T, All = Required<T>, NoAny = {
|
|
5
5
|
[K in keyof All]: IsAny<All[K]> extends true ? never : All[K] extends (...args: any[]) => void ? K : never;
|
|
6
6
|
}> = NoAny[keyof NoAny];
|
|
7
|
-
export declare type Mock<T> = Overwrite<T, {
|
|
7
|
+
export declare type Mock<T extends {}> = Overwrite<T, {
|
|
8
8
|
[K in MockableMethods<T>]: sinon.SinonStub;
|
|
9
9
|
}>;
|
|
10
10
|
export declare function doResetHistory(parent: Record<string, any>): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iobroker/testing",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.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",
|
|
@@ -41,35 +41,35 @@
|
|
|
41
41
|
"@alcalzone/release-script": "^3.5.9",
|
|
42
42
|
"@alcalzone/release-script-plugin-license": "^3.5.9",
|
|
43
43
|
"@iobroker/adapter-core": "^2.6.0",
|
|
44
|
-
"@tsconfig/
|
|
45
|
-
"@types/chai": "^4.3.
|
|
44
|
+
"@tsconfig/node14": "^1.0.3",
|
|
45
|
+
"@types/chai": "^4.3.3",
|
|
46
46
|
"@types/chai-as-promised": "^7.1.5",
|
|
47
47
|
"@types/debug": "4.1.7",
|
|
48
48
|
"@types/fs-extra": "^9.0.13",
|
|
49
|
-
"@types/iobroker": "^4.0.
|
|
49
|
+
"@types/iobroker": "^4.0.4",
|
|
50
50
|
"@types/mocha": "^9.1.1",
|
|
51
|
-
"@types/node": "^
|
|
52
|
-
"@types/sinon": "^10.0.
|
|
51
|
+
"@types/node": "^14.18.26",
|
|
52
|
+
"@types/sinon": "^10.0.13",
|
|
53
53
|
"@types/sinon-chai": "^3.2.8",
|
|
54
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
55
|
-
"@typescript-eslint/parser": "^5.
|
|
56
|
-
"eslint": "^8.
|
|
54
|
+
"@typescript-eslint/eslint-plugin": "^5.35.1",
|
|
55
|
+
"@typescript-eslint/parser": "^5.35.1",
|
|
56
|
+
"eslint": "^8.23.0",
|
|
57
57
|
"eslint-config-prettier": "^8.5.0",
|
|
58
|
-
"eslint-plugin-prettier": "^4.
|
|
59
|
-
"prettier": "^2.
|
|
58
|
+
"eslint-plugin-prettier": "^4.2.1",
|
|
59
|
+
"prettier": "^2.7.1",
|
|
60
60
|
"rimraf": "^3.0.2",
|
|
61
61
|
"source-map-support": "^0.5.21",
|
|
62
|
-
"ts-node": "^10.
|
|
63
|
-
"typescript": "~4.
|
|
62
|
+
"ts-node": "^10.9.1",
|
|
63
|
+
"typescript": "~4.8.2"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"alcalzone-shared": "~4.0.
|
|
66
|
+
"alcalzone-shared": "~4.0.3",
|
|
67
67
|
"chai": "^4.3.6",
|
|
68
68
|
"chai-as-promised": "^7.1.1",
|
|
69
69
|
"debug": "^4.3.4",
|
|
70
70
|
"fs-extra": "^10.1.0",
|
|
71
|
-
"mocha": "^
|
|
72
|
-
"sinon": "^
|
|
71
|
+
"mocha": "^10.0.0",
|
|
72
|
+
"sinon": "^14.0.0",
|
|
73
73
|
"sinon-chai": "^3.7.0"
|
|
74
74
|
}
|
|
75
75
|
}
|
package/CHANGELOG.md
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
## Changelog
|
|
2
|
-
|
|
3
|
-
<!--
|
|
4
|
-
PLACEHOLDER for next version:
|
|
5
|
-
## __WORK IN PROGRESS__
|
|
6
|
-
-->
|
|
7
|
-
## 3.0.2 (2022-05-15)
|
|
8
|
-
* Fix: Replace the `harness` argument to the `suite()` function with a `getHarness()` function to avoid accessing a stale harness.
|
|
9
|
-
|
|
10
|
-
## 3.0.1 (2022-05-09)
|
|
11
|
-
* BREAKING: The function signature of `defineAdditionalTests` in integration tests has changed. All user-defined integration tests must now be grouped in one or more `suite` blocks. The adapter will now only be started at the beginning of each suite. See the documentation for details.
|
|
12
|
-
* BREAKING: The function signature of `harness.startAdapterAndWait` has changed. It now accepts a boolean as the first parameter which controls whether to wait for the `alive` state (`false`) or the `info.connection` state (`true`).
|
|
13
|
-
|
|
14
|
-
## 2.6.0 (2022-04-18)
|
|
15
|
-
* The loglevel for the adapter and DB instances is now configurable and defaults to `"debug"` in both cases
|
|
16
|
-
|
|
17
|
-
## 2.5.6 (2022-03-05)
|
|
18
|
-
* Allow immediate exit with code `0` for `once` and `subscribe` adapters too
|
|
19
|
-
|
|
20
|
-
## 2.5.5 (2022-03-04)
|
|
21
|
-
* Allow immediate exit with code `0` for `schedule` adapters
|
|
22
|
-
* Check that `npm` is not listed as a local dependency in `package.json`
|
|
23
|
-
* Updated dependencies
|
|
24
|
-
|
|
25
|
-
## 2.5.4 (2022-02-02)
|
|
26
|
-
* Modifying ioBroker databases now uses the same methods that JS-Controller uses internally. This ensures that the testing is compatible with the `jsonl` database format.
|
|
27
|
-
* Testing adapters with adapter dependencies that try to access the databases during installation now works.
|
|
28
|
-
|
|
29
|
-
## 2.5.2 (2021-09-18)
|
|
30
|
-
* Fix: `adminUI.config` is now respected for the config UI check and JSON config is allowed too
|
|
31
|
-
* Updated dependencies
|
|
32
|
-
* Modernized build process
|
|
33
|
-
|
|
34
|
-
## 2.5.1 (2021-09-05)
|
|
35
|
-
* We now use the nightly js-controller dev builds instead of GitHub installation
|
|
36
|
-
|
|
37
|
-
## 2.4.4 (2021-03-14)
|
|
38
|
-
* Fix error: `iopackContent.common.titleLang` is not iterable
|
|
39
|
-
|
|
40
|
-
## 2.4.3 (2021-03-12)
|
|
41
|
-
* Fix: The adapter main file now correctly gets located when it is only defined in `package.json`, not `io-package.json`
|
|
42
|
-
|
|
43
|
-
## 2.4.2 (2021-01-06)
|
|
44
|
-
* Fixed compatibility with the reworked database classes
|
|
45
|
-
* Improved shutdown behavior of the adapter
|
|
46
|
-
|
|
47
|
-
## 2.4.1 (2021-01-01)
|
|
48
|
-
* Fixed a bug where the wrong `js-controller` dependency would be installed
|
|
49
|
-
|
|
50
|
-
## 2.4.0 (2020-12-07)
|
|
51
|
-
* Unit tests for adapter startup were removed and only log a warning that you can remove them
|
|
52
|
-
* Upgrade many packages
|
|
53
|
-
|
|
54
|
-
## 2.3.0 (2020-08-20)
|
|
55
|
-
* Added missing async functions to adapter mock
|
|
56
|
-
* Fixed: `TypeError "Cannot redefine property readyHandler"` when using `createMocks` more than once
|
|
57
|
-
* Upgrade to `@types/iobroker` v3.0.12
|
|
58
|
-
|
|
59
|
-
## 2.2.0 (2020-04-15)
|
|
60
|
-
* Upgrade to `@types/iobroker` v3.0.2
|
|
61
|
-
* Added mocks for `supportsFeature`, `getPluginInstance`, `getPluginConfig`
|
|
62
|
-
|
|
63
|
-
## 2.1.0 (2020-03-01)
|
|
64
|
-
* **Integration tests:** For Node.js >= 10, the `engine-strict` flag is now set to `true` to be in line with newer ioBroker installations
|
|
65
|
-
|
|
66
|
-
## v2.0.2
|
|
67
|
-
* **Unit tests:** added mocks for `getAbsoluteDefaultDataDir` and `getAbsoluteInstanceDataDir`
|
|
68
|
-
|
|
69
|
-
Sorry, there isn't more yet.
|