@iobroker/testing 2.5.2 → 2.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -1
- package/LICENSE +1 -1
- package/build/index.js +5 -1
- package/build/lib/adapterTools.d.ts +1 -10
- package/build/lib/adapterTools.js +10 -7
- package/build/tests/index.js +1 -0
- package/build/tests/integration/index.js +33 -26
- package/build/tests/integration/lib/adapterSetup.d.ts +3 -4
- package/build/tests/integration/lib/adapterSetup.js +23 -18
- package/build/tests/integration/lib/controllerSetup.d.ts +3 -6
- package/build/tests/integration/lib/controllerSetup.js +29 -21
- package/build/tests/integration/lib/dbConnection.d.ts +46 -22
- package/build/tests/integration/lib/dbConnection.js +263 -47
- package/build/tests/integration/lib/harness.d.ts +7 -11
- package/build/tests/integration/lib/harness.js +48 -104
- package/build/tests/integration/lib/tools.js +5 -1
- package/build/tests/packageFiles/index.js +18 -1
- package/build/tests/unit/mocks/mockAdapterCore.js +5 -1
- package/package.json +26 -26
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,15 @@
|
|
|
4
4
|
PLACEHOLDER for next version:
|
|
5
5
|
## __WORK IN PROGRESS__
|
|
6
6
|
-->
|
|
7
|
+
## 2.5.5 (2022-03-04)
|
|
8
|
+
* Allow immediate exit with code `0` for schedule adapters
|
|
9
|
+
* Check that `npm` is not listed as a local dependency in `package.json`
|
|
10
|
+
* Updated dependencies
|
|
11
|
+
|
|
12
|
+
## 2.5.4 (2022-02-02)
|
|
13
|
+
* 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.
|
|
14
|
+
* Testing adapters with adapter dependencies that try to access the databases during installation now works.
|
|
15
|
+
|
|
7
16
|
## 2.5.2 (2021-09-18)
|
|
8
17
|
* Fix: `adminUI.config` is now respected for the config UI check and JSON config is allowed too
|
|
9
18
|
* Updated dependencies
|
|
@@ -44,4 +53,4 @@
|
|
|
44
53
|
## v2.0.2
|
|
45
54
|
* **Unit tests:** added mocks for `getAbsoluteDefaultDataDir` and `getAbsoluteInstanceDataDir`
|
|
46
55
|
|
|
47
|
-
Sorry, there isn't more yet.
|
|
56
|
+
Sorry, there isn't more yet.
|
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2022 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/build/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -9,16 +9,7 @@ export declare function loadNpmPackage(adapterDir: string): Record<string, any>;
|
|
|
9
9
|
* @param adapterDir The directory the adapter resides in
|
|
10
10
|
*/
|
|
11
11
|
export declare function loadIoPackage(adapterDir: string): Record<string, any>;
|
|
12
|
-
|
|
13
|
-
* Checks if an adapter claims that it supports compact mode
|
|
14
|
-
* @param ioPackage The contents of io-package.json in object format
|
|
15
|
-
*/
|
|
16
|
-
export declare function adapterShouldSupportCompactMode(ioPackage: Record<string, any>): boolean;
|
|
17
|
-
/**
|
|
18
|
-
* Checks if an adapter claims that it supports compact mode
|
|
19
|
-
* @param adapterDir The directory the adapter resides in
|
|
20
|
-
*/
|
|
21
|
-
export declare function adapterShouldSupportCompactMode(adapterDir: string): boolean;
|
|
12
|
+
export declare function getAdapterExecutionMode(adapterDir: string): ioBroker.AdapterCommon["mode"];
|
|
22
13
|
/**
|
|
23
14
|
* Locates an adapter's main file
|
|
24
15
|
* @param adapterDir The directory the adapter resides in
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -22,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
22
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
27
|
};
|
|
24
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.getAdapterDependencies = exports.getAdapterFullName = exports.getAdapterName = exports.getAppName = exports.loadInstanceObjects = exports.loadAdapterCommon = exports.loadAdapterConfig = exports.locateAdapterMainFile = exports.
|
|
29
|
+
exports.getAdapterDependencies = exports.getAdapterFullName = exports.getAdapterName = exports.getAppName = exports.loadInstanceObjects = exports.loadAdapterCommon = exports.loadAdapterConfig = exports.locateAdapterMainFile = exports.getAdapterExecutionMode = exports.loadIoPackage = exports.loadNpmPackage = void 0;
|
|
26
30
|
// Add debug logging for tests
|
|
27
31
|
const typeguards_1 = require("alcalzone-shared/typeguards");
|
|
28
32
|
const debug_1 = __importDefault(require("debug"));
|
|
@@ -45,12 +49,11 @@ function loadIoPackage(adapterDir) {
|
|
|
45
49
|
return require(path.join(adapterDir, "io-package.json"));
|
|
46
50
|
}
|
|
47
51
|
exports.loadIoPackage = loadIoPackage;
|
|
48
|
-
function
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return dirOrIoPack.common.compact === true;
|
|
52
|
+
function getAdapterExecutionMode(adapterDir) {
|
|
53
|
+
const ioPackage = loadIoPackage(adapterDir);
|
|
54
|
+
return ioPackage.common.mode;
|
|
52
55
|
}
|
|
53
|
-
exports.
|
|
56
|
+
exports.getAdapterExecutionMode = getAdapterExecutionMode;
|
|
54
57
|
/**
|
|
55
58
|
* Locates an adapter's main file
|
|
56
59
|
* @param adapterDir The directory the adapter resides in
|
package/build/tests/index.js
CHANGED
|
@@ -8,6 +8,7 @@ const createMocks_1 = require("./unit/harness/createMocks");
|
|
|
8
8
|
const mockDatabase_1 = require("./unit/mocks/mockDatabase");
|
|
9
9
|
var harness_1 = require("./integration/lib/harness");
|
|
10
10
|
Object.defineProperty(exports, "IntegrationTestHarness", { enumerable: true, get: function () { return harness_1.TestHarness; } });
|
|
11
|
+
var mockAdapter_1 = require("./unit/mocks/mockAdapter");
|
|
11
12
|
var mockDatabase_2 = require("./unit/mocks/mockDatabase");
|
|
12
13
|
Object.defineProperty(exports, "MockDatabase", { enumerable: true, get: function () { return mockDatabase_2.MockDatabase; } });
|
|
13
14
|
/** Predefined test sets */
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -24,7 +28,6 @@ const async_1 = require("alcalzone-shared/async");
|
|
|
24
28
|
const os = __importStar(require("os"));
|
|
25
29
|
const path = __importStar(require("path"));
|
|
26
30
|
const adapterTools_1 = require("../../lib/adapterTools");
|
|
27
|
-
const executeCommand_1 = require("../../lib/executeCommand");
|
|
28
31
|
const adapterSetup_1 = require("./lib/adapterSetup");
|
|
29
32
|
const controllerSetup_1 = require("./lib/controllerSetup");
|
|
30
33
|
const dbConnection_1 = require("./lib/dbConnection");
|
|
@@ -33,9 +36,10 @@ function testAdapter(adapterDir, options = {}) {
|
|
|
33
36
|
const appName = (0, adapterTools_1.getAppName)(adapterDir);
|
|
34
37
|
const adapterName = (0, adapterTools_1.getAdapterName)(adapterDir);
|
|
35
38
|
const testDir = path.join(os.tmpdir(), `test-${appName}.${adapterName}`);
|
|
39
|
+
/** This db connection is only used for the lifetime of a test and then re-created */
|
|
40
|
+
let dbConnection;
|
|
36
41
|
let harness;
|
|
37
|
-
const
|
|
38
|
-
const controllerSetup = new controllerSetup_1.ControllerSetup(adapterDir, testDir, dbConnection);
|
|
42
|
+
const controllerSetup = new controllerSetup_1.ControllerSetup(adapterDir, testDir);
|
|
39
43
|
console.log();
|
|
40
44
|
console.log(`Running tests in ${testDir}`);
|
|
41
45
|
console.log();
|
|
@@ -49,46 +53,44 @@ function testAdapter(adapterDir, options = {}) {
|
|
|
49
53
|
if (await controllerSetup.isJsControllerRunning()) {
|
|
50
54
|
throw new Error("JS-Controller is already running! Stop it for the first test run and try again!");
|
|
51
55
|
}
|
|
52
|
-
const adapterSetup = new adapterSetup_1.AdapterSetup(adapterDir, testDir
|
|
56
|
+
const adapterSetup = new adapterSetup_1.AdapterSetup(adapterDir, testDir);
|
|
57
|
+
// Installation happens in two steps:
|
|
58
|
+
// First we need to set up JS Controller, so the databases etc. can be created
|
|
53
59
|
// First we need to copy all files and execute an npm install
|
|
54
60
|
await controllerSetup.prepareTestDir();
|
|
55
|
-
|
|
56
|
-
//
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
await (
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (wasJsControllerInstalled)
|
|
64
|
-
await controllerSetup.setupJsController();
|
|
65
|
-
await controllerSetup.setupSystemConfig();
|
|
66
|
-
await controllerSetup.disableAdminInstances();
|
|
67
|
-
await adapterSetup.deleteOldInstances();
|
|
61
|
+
// Only then we can install the adapter, because some (including VIS) try to access
|
|
62
|
+
// the databases if JS Controller is installed
|
|
63
|
+
await adapterSetup.installAdapterInTestDir();
|
|
64
|
+
const dbConnection = new dbConnection_1.DBConnection(appName, testDir);
|
|
65
|
+
await dbConnection.start();
|
|
66
|
+
controllerSetup.setupSystemConfig(dbConnection);
|
|
67
|
+
await controllerSetup.disableAdminInstances(dbConnection);
|
|
68
|
+
await adapterSetup.deleteOldInstances(dbConnection);
|
|
68
69
|
await adapterSetup.addAdapterInstance();
|
|
70
|
+
await dbConnection.stop();
|
|
69
71
|
// Create a copy of the databases that we can restore later
|
|
70
72
|
({ objects: objectsBackup, states: statesBackup } =
|
|
71
|
-
await dbConnection.
|
|
73
|
+
await dbConnection.backup());
|
|
72
74
|
});
|
|
73
75
|
beforeEach(async function () {
|
|
74
76
|
this.timeout(30000);
|
|
77
|
+
dbConnection = new dbConnection_1.DBConnection(appName, testDir);
|
|
75
78
|
// Clean up before every single test
|
|
76
79
|
await Promise.all([
|
|
77
80
|
controllerSetup.clearDBDir(),
|
|
78
81
|
controllerSetup.clearLogDir(),
|
|
79
|
-
dbConnection.
|
|
82
|
+
dbConnection.restore(objectsBackup, statesBackup),
|
|
80
83
|
]);
|
|
81
84
|
// Create a new test harness
|
|
82
|
-
|
|
85
|
+
await dbConnection.start();
|
|
86
|
+
harness = new harness_1.TestHarness(adapterDir, testDir, dbConnection);
|
|
83
87
|
// Enable the adapter and set its loglevel to debug
|
|
84
|
-
await harness.changeAdapterConfig(
|
|
88
|
+
await harness.changeAdapterConfig(adapterName, {
|
|
85
89
|
common: {
|
|
86
90
|
enabled: true,
|
|
87
91
|
loglevel: "debug",
|
|
88
92
|
},
|
|
89
93
|
});
|
|
90
|
-
// Start the controller instance
|
|
91
|
-
await harness.startController();
|
|
92
94
|
// And enable the sendTo emulation
|
|
93
95
|
await harness.enableSendTo();
|
|
94
96
|
});
|
|
@@ -100,7 +102,13 @@ function testAdapter(adapterDir, options = {}) {
|
|
|
100
102
|
harness.removeAllListeners();
|
|
101
103
|
});
|
|
102
104
|
it("The adapter starts", function () {
|
|
105
|
+
var _a;
|
|
103
106
|
this.timeout(60000);
|
|
107
|
+
const allowedExitCodes = new Set((_a = options.allowedExitCodes) !== null && _a !== void 0 ? _a : []);
|
|
108
|
+
// Schedule adapters are allowed to "immediately" exit with code 0
|
|
109
|
+
if (harness.getAdapterExecutionMode() === "schedule") {
|
|
110
|
+
allowedExitCodes.add(0);
|
|
111
|
+
}
|
|
104
112
|
return new Promise((resolve, reject) => {
|
|
105
113
|
// Register a handler to check the alive state and exit codes
|
|
106
114
|
harness
|
|
@@ -116,8 +124,7 @@ function testAdapter(adapterDir, options = {}) {
|
|
|
116
124
|
}
|
|
117
125
|
})
|
|
118
126
|
.on("failed", (code) => {
|
|
119
|
-
if (
|
|
120
|
-
options.allowedExitCodes.indexOf(code) === -1) {
|
|
127
|
+
if (!allowedExitCodes.has(code)) {
|
|
121
128
|
reject(new Error(`The adapter startup was interrupted unexpectedly with ${typeof code === "number"
|
|
122
129
|
? "code"
|
|
123
130
|
: "signal"} ${code}`));
|
|
@@ -2,8 +2,7 @@ import type { DBConnection } from "./dbConnection";
|
|
|
2
2
|
export declare class AdapterSetup {
|
|
3
3
|
private adapterDir;
|
|
4
4
|
private testDir;
|
|
5
|
-
|
|
6
|
-
constructor(adapterDir: string, testDir: string, dbConnection: DBConnection);
|
|
5
|
+
constructor(adapterDir: string, testDir: string);
|
|
7
6
|
private testAdapterDir;
|
|
8
7
|
private adapterName;
|
|
9
8
|
private adapterFullName;
|
|
@@ -14,10 +13,10 @@ export declare class AdapterSetup {
|
|
|
14
13
|
*/
|
|
15
14
|
isAdapterInstalled(): Promise<boolean>;
|
|
16
15
|
/** Copies all adapter files (except a few) to the test directory */
|
|
17
|
-
|
|
16
|
+
installAdapterInTestDir(): Promise<void>;
|
|
18
17
|
/**
|
|
19
18
|
* Adds an instance for an already installed adapter in the test directory
|
|
20
19
|
*/
|
|
21
20
|
addAdapterInstance(): Promise<void>;
|
|
22
|
-
deleteOldInstances(): Promise<void>;
|
|
21
|
+
deleteOldInstances(dbConnection: DBConnection): Promise<void>;
|
|
23
22
|
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -23,6 +27,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
23
27
|
};
|
|
24
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
29
|
exports.AdapterSetup = void 0;
|
|
30
|
+
/* eslint-disable @typescript-eslint/no-empty-function */
|
|
26
31
|
// Add debug logging for tests
|
|
27
32
|
const objects_1 = require("alcalzone-shared/objects");
|
|
28
33
|
const debug_1 = __importDefault(require("debug"));
|
|
@@ -33,10 +38,9 @@ const executeCommand_1 = require("../../../lib/executeCommand");
|
|
|
33
38
|
const tools_1 = require("./tools");
|
|
34
39
|
const debug = (0, debug_1.default)("testing:integration:AdapterSetup");
|
|
35
40
|
class AdapterSetup {
|
|
36
|
-
constructor(adapterDir, testDir
|
|
41
|
+
constructor(adapterDir, testDir) {
|
|
37
42
|
this.adapterDir = adapterDir;
|
|
38
43
|
this.testDir = testDir;
|
|
39
|
-
this.dbConnection = dbConnection;
|
|
40
44
|
debug("Creating AdapterSetup...");
|
|
41
45
|
this.adapterName = (0, adapterTools_1.getAdapterName)(this.adapterDir);
|
|
42
46
|
this.adapterFullName = (0, adapterTools_1.getAdapterFullName)(this.adapterDir);
|
|
@@ -57,7 +61,7 @@ class AdapterSetup {
|
|
|
57
61
|
return (0, fs_extra_1.pathExists)(this.testAdapterDir);
|
|
58
62
|
}
|
|
59
63
|
/** Copies all adapter files (except a few) to the test directory */
|
|
60
|
-
async
|
|
64
|
+
async installAdapterInTestDir() {
|
|
61
65
|
debug("Copying adapter files to test directory...");
|
|
62
66
|
// We install the adapter almost like it would be installed in the real world
|
|
63
67
|
// Therefore pack it into a tarball and put it in the test dir for installation
|
|
@@ -87,6 +91,11 @@ class AdapterSetup {
|
|
|
87
91
|
debug("Deleting old remains of this adapter");
|
|
88
92
|
if (await (0, fs_extra_1.pathExists)(this.testAdapterDir))
|
|
89
93
|
await (0, fs_extra_1.remove)(this.testAdapterDir);
|
|
94
|
+
debug("Installing adapter");
|
|
95
|
+
// Defer to npm to install the controller (if it wasn't already)
|
|
96
|
+
await (0, executeCommand_1.executeCommand)("npm", ["i", "--production"], {
|
|
97
|
+
cwd: this.testDir,
|
|
98
|
+
});
|
|
90
99
|
debug(" => done!");
|
|
91
100
|
}
|
|
92
101
|
/**
|
|
@@ -109,9 +118,12 @@ class AdapterSetup {
|
|
|
109
118
|
throw new Error(`Adding the adapter instance failed!`);
|
|
110
119
|
debug(" => done!");
|
|
111
120
|
}
|
|
112
|
-
async deleteOldInstances() {
|
|
121
|
+
async deleteOldInstances(dbConnection) {
|
|
113
122
|
debug("Removing old adapter instances...");
|
|
114
|
-
const
|
|
123
|
+
const allKeys = new Set([
|
|
124
|
+
...(await dbConnection.getObjectIDs()),
|
|
125
|
+
...(await dbConnection.getStateIDs()),
|
|
126
|
+
]);
|
|
115
127
|
const instanceRegex = new RegExp(`^system\\.adapter\\.${this.adapterName}\\.\\d+`);
|
|
116
128
|
const instanceObjsRegex = new RegExp(`^${this.adapterName}\\.\\d+\.`);
|
|
117
129
|
const belongsToAdapter = (id) => {
|
|
@@ -120,19 +132,12 @@ class AdapterSetup {
|
|
|
120
132
|
id === this.adapterName ||
|
|
121
133
|
id === `${this.adapterName}.admin`);
|
|
122
134
|
};
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
135
|
+
const idsToDelete = [...allKeys].filter((id) => belongsToAdapter(id));
|
|
136
|
+
for (const id of idsToDelete) {
|
|
137
|
+
await dbConnection.delObject(id).catch(() => { });
|
|
138
|
+
await dbConnection.delState(id).catch(() => { });
|
|
128
139
|
}
|
|
129
|
-
|
|
130
|
-
for (const id of Object.keys(states)) {
|
|
131
|
-
if (belongsToAdapter(id))
|
|
132
|
-
delete states[id];
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
await this.dbConnection.writeDB(objects, states);
|
|
140
|
+
debug(" => done!");
|
|
136
141
|
}
|
|
137
142
|
}
|
|
138
143
|
exports.AdapterSetup = AdapterSetup;
|
|
@@ -2,8 +2,7 @@ import type { DBConnection } from "./dbConnection";
|
|
|
2
2
|
export declare class ControllerSetup {
|
|
3
3
|
private adapterDir;
|
|
4
4
|
private testDir;
|
|
5
|
-
|
|
6
|
-
constructor(adapterDir: string, testDir: string, dbConnection: DBConnection);
|
|
5
|
+
constructor(adapterDir: string, testDir: string);
|
|
7
6
|
private appName;
|
|
8
7
|
private adapterName;
|
|
9
8
|
private testAdapterDir;
|
|
@@ -22,8 +21,6 @@ export declare class ControllerSetup {
|
|
|
22
21
|
isJsControllerRunning(): Promise<boolean>;
|
|
23
22
|
/**
|
|
24
23
|
* Sets up an existing JS-Controller instance for testing by executing "iobroker setup first"
|
|
25
|
-
* @param appName The branded name of "iobroker"
|
|
26
|
-
* @param testDir The directory the integration tests are executed in
|
|
27
24
|
*/
|
|
28
25
|
setupJsController(): Promise<void>;
|
|
29
26
|
/**
|
|
@@ -31,7 +28,7 @@ export declare class ControllerSetup {
|
|
|
31
28
|
* @param appName The branded name of "iobroker"
|
|
32
29
|
* @param testDir The directory the integration tests are executed in
|
|
33
30
|
*/
|
|
34
|
-
setupSystemConfig():
|
|
31
|
+
setupSystemConfig(dbConnection: DBConnection): void;
|
|
35
32
|
/**
|
|
36
33
|
* Clears the log dir for integration tests (and creates it if it doesn't exist)
|
|
37
34
|
* @param appName The branded name of "iobroker"
|
|
@@ -48,5 +45,5 @@ export declare class ControllerSetup {
|
|
|
48
45
|
* Disables all admin instances in the objects DB
|
|
49
46
|
* @param objects The contents of objects.json
|
|
50
47
|
*/
|
|
51
|
-
disableAdminInstances(): Promise<void>;
|
|
48
|
+
disableAdminInstances(dbConnection: DBConnection): Promise<void>;
|
|
52
49
|
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -23,7 +27,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
23
27
|
};
|
|
24
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
29
|
exports.ControllerSetup = void 0;
|
|
26
|
-
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
27
30
|
// Add debug logging for tests
|
|
28
31
|
const debug_1 = __importDefault(require("debug"));
|
|
29
32
|
const fs_extra_1 = require("fs-extra");
|
|
@@ -34,10 +37,9 @@ const executeCommand_1 = require("../../../lib/executeCommand");
|
|
|
34
37
|
const tools_1 = require("./tools");
|
|
35
38
|
const debug = (0, debug_1.default)("testing:integration:ControllerSetup");
|
|
36
39
|
class ControllerSetup {
|
|
37
|
-
constructor(adapterDir, testDir
|
|
40
|
+
constructor(adapterDir, testDir) {
|
|
38
41
|
this.adapterDir = adapterDir;
|
|
39
42
|
this.testDir = testDir;
|
|
40
|
-
this.dbConnection = dbConnection;
|
|
41
43
|
debug("Creating ControllerSetup...");
|
|
42
44
|
this.adapterName = (0, adapterTools_1.getAdapterName)(this.adapterDir);
|
|
43
45
|
this.appName = (0, adapterTools_1.getAppName)(this.adapterDir);
|
|
@@ -83,6 +85,16 @@ class ControllerSetup {
|
|
|
83
85
|
if (nodeMajorVersion >= 10) {
|
|
84
86
|
await (0, fs_extra_1.writeFile)(path.join(this.testDir, ".npmrc"), "engine-strict=true", "utf8");
|
|
85
87
|
}
|
|
88
|
+
// Remember if JS-Controller is installed already. If so, we need to call `setup first` afterwards
|
|
89
|
+
const wasJsControllerInstalled = await this.isJsControllerInstalled();
|
|
90
|
+
// Defer to npm to install the controller (if it wasn't already)
|
|
91
|
+
debug("(Re-)installing JS Controller...");
|
|
92
|
+
await (0, executeCommand_1.executeCommand)("npm", ["i", "--production"], {
|
|
93
|
+
cwd: this.testDir,
|
|
94
|
+
});
|
|
95
|
+
// Prepare/clean the databases and config
|
|
96
|
+
if (wasJsControllerInstalled)
|
|
97
|
+
await this.setupJsController();
|
|
86
98
|
debug(" => done!");
|
|
87
99
|
}
|
|
88
100
|
/**
|
|
@@ -152,8 +164,6 @@ class ControllerSetup {
|
|
|
152
164
|
// }
|
|
153
165
|
/**
|
|
154
166
|
* Sets up an existing JS-Controller instance for testing by executing "iobroker setup first"
|
|
155
|
-
* @param appName The branded name of "iobroker"
|
|
156
|
-
* @param testDir The directory the integration tests are executed in
|
|
157
167
|
*/
|
|
158
168
|
async setupJsController() {
|
|
159
169
|
debug("Initializing JS-Controller installation...");
|
|
@@ -175,13 +185,12 @@ class ControllerSetup {
|
|
|
175
185
|
* @param appName The branded name of "iobroker"
|
|
176
186
|
* @param testDir The directory the integration tests are executed in
|
|
177
187
|
*/
|
|
178
|
-
|
|
179
|
-
debug(
|
|
180
|
-
const
|
|
181
|
-
const systemConfig = require(systemFilename);
|
|
188
|
+
setupSystemConfig(dbConnection) {
|
|
189
|
+
debug(`Moving databases to different ports...`);
|
|
190
|
+
const systemConfig = dbConnection.getSystemConfig();
|
|
182
191
|
systemConfig.objects.port = 19001;
|
|
183
192
|
systemConfig.states.port = 19000;
|
|
184
|
-
|
|
193
|
+
dbConnection.setSystemConfig(systemConfig);
|
|
185
194
|
debug(" => done!");
|
|
186
195
|
}
|
|
187
196
|
/**
|
|
@@ -206,18 +215,17 @@ class ControllerSetup {
|
|
|
206
215
|
* Disables all admin instances in the objects DB
|
|
207
216
|
* @param objects The contents of objects.json
|
|
208
217
|
*/
|
|
209
|
-
async disableAdminInstances() {
|
|
218
|
+
async disableAdminInstances(dbConnection) {
|
|
210
219
|
debug("Disabling admin instances...");
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
220
|
+
const instanceObjects = await dbConnection.getObjectViewAsync("system", "instance", {
|
|
221
|
+
startkey: "system.adapter.admin.",
|
|
222
|
+
endkey: "system.adapter.admin.\u9999",
|
|
223
|
+
});
|
|
224
|
+
for (const { id, value: obj } of instanceObjects.rows) {
|
|
225
|
+
if (obj && obj.common) {
|
|
226
|
+
obj.common.enabled = false;
|
|
227
|
+
await dbConnection.setObject(id, obj);
|
|
219
228
|
}
|
|
220
|
-
await this.dbConnection.writeObjectsDB(objects);
|
|
221
229
|
}
|
|
222
230
|
debug(" => done!");
|
|
223
231
|
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
/// <reference types="iobroker" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import EventEmitter from "events";
|
|
2
4
|
export declare type ObjectsDB = Record<string, ioBroker.Object>;
|
|
3
5
|
export declare type StatesDB = Record<string, ioBroker.State>;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
+
export interface DBConnection {
|
|
7
|
+
on(event: "objectChange", handler: ioBroker.ObjectChangeHandler): this;
|
|
8
|
+
on(event: "stateChange", handler: ioBroker.StateChangeHandler): this;
|
|
9
|
+
}
|
|
10
|
+
/** The DB connection capsules access to the states and objects DB */
|
|
11
|
+
export declare class DBConnection extends EventEmitter {
|
|
6
12
|
private appName;
|
|
7
13
|
private testDir;
|
|
8
14
|
/**
|
|
@@ -11,25 +17,43 @@ export declare class DBConnection {
|
|
|
11
17
|
*/
|
|
12
18
|
constructor(appName: string, testDir: string);
|
|
13
19
|
private testDataDir;
|
|
14
|
-
private
|
|
15
|
-
private
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
private testControllerDir;
|
|
21
|
+
private _objectsServer;
|
|
22
|
+
private _statesServer;
|
|
23
|
+
private _objectsClient;
|
|
24
|
+
/** The underlying objects client instance that can be used to access the objects DB */
|
|
25
|
+
get objectsClient(): any;
|
|
26
|
+
private _statesClient;
|
|
27
|
+
/** The underlying states client instance that can be used to access the states DB */
|
|
28
|
+
get statesClient(): any;
|
|
29
|
+
get objectsType(): "file" | "jsonl";
|
|
30
|
+
get objectsPath(): string;
|
|
31
|
+
get statesType(): "file" | "jsonl";
|
|
32
|
+
get statesPath(): string;
|
|
33
|
+
getSystemConfig(): any;
|
|
34
|
+
backup(): Promise<{
|
|
35
|
+
objects: Buffer;
|
|
36
|
+
states: Buffer;
|
|
28
37
|
}>;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
38
|
+
restore(objects: Buffer, states: Buffer): Promise<void>;
|
|
39
|
+
setSystemConfig(systemConfig: any): void;
|
|
40
|
+
private _isRunning;
|
|
41
|
+
get isRunning(): boolean;
|
|
42
|
+
start(): Promise<void>;
|
|
43
|
+
stop(): Promise<void>;
|
|
44
|
+
/** Creates the objects DB and sets up listeners for it */
|
|
45
|
+
private createObjectsDB;
|
|
46
|
+
/** Creates the states DB and sets up listeners for it */
|
|
47
|
+
private createStatesDB;
|
|
48
|
+
readonly getObject: ioBroker.Adapter["getForeignObjectAsync"];
|
|
49
|
+
readonly setObject: ioBroker.Adapter["setForeignObjectAsync"];
|
|
50
|
+
readonly delObject: ioBroker.Adapter["delForeignObjectAsync"];
|
|
51
|
+
readonly getState: ioBroker.Adapter["getForeignStateAsync"];
|
|
52
|
+
readonly setState: ioBroker.Adapter["setForeignStateAsync"];
|
|
53
|
+
readonly delState: ioBroker.Adapter["delForeignStateAsync"];
|
|
54
|
+
subscribeMessage(id: string): void;
|
|
55
|
+
pushMessage(instanceId: string, msg: any, callback: (err: Error | null, id: any) => void): void;
|
|
56
|
+
readonly getObjectViewAsync: ioBroker.Adapter["getObjectViewAsync"];
|
|
57
|
+
getStateIDs(pattern?: string): Promise<string[]>;
|
|
58
|
+
getObjectIDs(pattern?: string): Promise<string[]>;
|
|
35
59
|
}
|