@iobroker/testing 2.5.0 → 2.5.4
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/lib/adapterTools.js +27 -38
- package/build/lib/executeCommand.js +3 -4
- package/build/tests/index.js +1 -0
- package/build/tests/integration/index.js +59 -76
- package/build/tests/integration/lib/adapterSetup.d.ts +4 -5
- package/build/tests/integration/lib/adapterSetup.js +81 -97
- package/build/tests/integration/lib/controllerSetup.d.ts +4 -7
- package/build/tests/integration/lib/controllerSetup.js +90 -105
- package/build/tests/integration/lib/dbConnection.d.ts +46 -22
- package/build/tests/integration/lib/dbConnection.js +259 -65
- package/build/tests/integration/lib/harness.d.ts +6 -11
- package/build/tests/integration/lib/harness.js +107 -192
- package/build/tests/integration/lib/tools.js +1 -1
- package/build/tests/packageFiles/index.js +32 -26
- package/build/tests/unit/index.js +2 -11
- package/build/tests/unit/mocks/mockAdapter.d.ts +1 -1
- package/build/tests/unit/mocks/mockAdapter.js +17 -18
- package/build/tests/unit/mocks/mockAdapterCore.d.ts +1 -1
- package/build/tests/unit/mocks/mockDatabase.d.ts +2 -2
- package/build/tests/unit/mocks/mockDatabase.js +10 -10
- package/build/tests/unit/mocks/mockLogger.js +8 -8
- package/build/tests/unit/mocks/tools.d.ts +1 -1
- package/build/tests/unit/mocks/tools.js +2 -2
- package/package.json +27 -25
|
@@ -18,21 +18,11 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
18
18
|
__setModuleDefault(result, mod);
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
21
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
22
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
23
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
24
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
25
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
26
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
27
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
28
|
-
});
|
|
29
|
-
};
|
|
30
21
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
31
22
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
32
23
|
};
|
|
33
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
25
|
exports.ControllerSetup = void 0;
|
|
35
|
-
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
36
26
|
// Add debug logging for tests
|
|
37
27
|
const debug_1 = __importDefault(require("debug"));
|
|
38
28
|
const fs_extra_1 = require("fs-extra");
|
|
@@ -41,18 +31,17 @@ const path = __importStar(require("path"));
|
|
|
41
31
|
const adapterTools_1 = require("../../../lib/adapterTools");
|
|
42
32
|
const executeCommand_1 = require("../../../lib/executeCommand");
|
|
43
33
|
const tools_1 = require("./tools");
|
|
44
|
-
const debug = debug_1.default("testing:integration:ControllerSetup");
|
|
34
|
+
const debug = (0, debug_1.default)("testing:integration:ControllerSetup");
|
|
45
35
|
class ControllerSetup {
|
|
46
|
-
constructor(adapterDir, testDir
|
|
36
|
+
constructor(adapterDir, testDir) {
|
|
47
37
|
this.adapterDir = adapterDir;
|
|
48
38
|
this.testDir = testDir;
|
|
49
|
-
this.dbConnection = dbConnection;
|
|
50
39
|
debug("Creating ControllerSetup...");
|
|
51
|
-
this.adapterName = adapterTools_1.getAdapterName(this.adapterDir);
|
|
52
|
-
this.appName = adapterTools_1.getAppName(this.adapterDir);
|
|
53
|
-
this.testAdapterDir = tools_1.getTestAdapterDir(this.adapterDir, this.testDir);
|
|
54
|
-
this.testControllerDir = tools_1.getTestControllerDir(this.appName, this.testDir);
|
|
55
|
-
this.testDataDir = tools_1.getTestDataDir(this.appName, this.testDir);
|
|
40
|
+
this.adapterName = (0, adapterTools_1.getAdapterName)(this.adapterDir);
|
|
41
|
+
this.appName = (0, adapterTools_1.getAppName)(this.adapterDir);
|
|
42
|
+
this.testAdapterDir = (0, tools_1.getTestAdapterDir)(this.adapterDir, this.testDir);
|
|
43
|
+
this.testControllerDir = (0, tools_1.getTestControllerDir)(this.appName, this.testDir);
|
|
44
|
+
this.testDataDir = (0, tools_1.getTestDataDir)(this.appName, this.testDir);
|
|
56
45
|
debug(` directories:`);
|
|
57
46
|
debug(` controller: ${this.testControllerDir}`);
|
|
58
47
|
debug(` adapter: ${this.testAdapterDir}`);
|
|
@@ -60,56 +49,62 @@ class ControllerSetup {
|
|
|
60
49
|
debug(` appName: ${this.appName}`);
|
|
61
50
|
debug(` adapterName: ${this.adapterName}`);
|
|
62
51
|
}
|
|
63
|
-
prepareTestDir() {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
52
|
+
async prepareTestDir() {
|
|
53
|
+
debug("Preparing the test directory...");
|
|
54
|
+
// Make sure the test dir exists
|
|
55
|
+
await (0, fs_extra_1.ensureDir)(this.testDir);
|
|
56
|
+
// Write the package.json
|
|
57
|
+
const packageJson = {
|
|
58
|
+
name: path.basename(this.testDir),
|
|
59
|
+
version: "1.0.0",
|
|
60
|
+
main: "index.js",
|
|
61
|
+
scripts: {
|
|
62
|
+
test: 'echo "Error: no test specified" && exit 1',
|
|
63
|
+
},
|
|
64
|
+
keywords: [],
|
|
65
|
+
author: "",
|
|
66
|
+
license: "ISC",
|
|
67
|
+
dependencies: {
|
|
68
|
+
[`${this.appName}.js-controller`]: "dev",
|
|
69
|
+
},
|
|
70
|
+
description: "",
|
|
71
|
+
};
|
|
72
|
+
await (0, fs_extra_1.writeJSON)(path.join(this.testDir, "package.json"), packageJson, {
|
|
73
|
+
spaces: 2,
|
|
74
|
+
});
|
|
75
|
+
// Delete a possible package-lock.json as it can mess with future installations
|
|
76
|
+
const pckLockPath = path.join(this.testDir, "package-lock.json");
|
|
77
|
+
if (await (0, fs_extra_1.pathExists)(pckLockPath))
|
|
78
|
+
await (0, fs_extra_1.unlink)(pckLockPath);
|
|
79
|
+
// Set the engineStrict flag on new Node.js versions to be in line with newer ioBroker installations
|
|
80
|
+
const nodeMajorVersion = parseInt(process.versions.node.split(".")[0], 10);
|
|
81
|
+
if (nodeMajorVersion >= 10) {
|
|
82
|
+
await (0, fs_extra_1.writeFile)(path.join(this.testDir, ".npmrc"), "engine-strict=true", "utf8");
|
|
83
|
+
}
|
|
84
|
+
// Remember if JS-Controller is installed already. If so, we need to call `setup first` afterwards
|
|
85
|
+
const wasJsControllerInstalled = await this.isJsControllerInstalled();
|
|
86
|
+
// Defer to npm to install the controller (if it wasn't already)
|
|
87
|
+
debug("(Re-)installing JS Controller...");
|
|
88
|
+
await (0, executeCommand_1.executeCommand)("npm", ["i", "--production"], {
|
|
89
|
+
cwd: this.testDir,
|
|
97
90
|
});
|
|
91
|
+
// Prepare/clean the databases and config
|
|
92
|
+
if (wasJsControllerInstalled)
|
|
93
|
+
await this.setupJsController();
|
|
94
|
+
debug(" => done!");
|
|
98
95
|
}
|
|
99
96
|
/**
|
|
100
97
|
* Tests if JS-Controller is already installed
|
|
101
98
|
* @param appName The branded name of "iobroker"
|
|
102
99
|
* @param testDir The directory the integration tests are executed in
|
|
103
100
|
*/
|
|
104
|
-
isJsControllerInstalled() {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return isInstalled;
|
|
112
|
-
});
|
|
101
|
+
async isJsControllerInstalled() {
|
|
102
|
+
debug("Testing if JS-Controller is installed...");
|
|
103
|
+
// We expect js-controller to be installed if the dir in <testDir>/node_modules and the data directory exist
|
|
104
|
+
const isInstalled = (await (0, fs_extra_1.pathExists)(this.testControllerDir)) &&
|
|
105
|
+
(await (0, fs_extra_1.pathExists)(this.testDataDir));
|
|
106
|
+
debug(` => ${isInstalled}`);
|
|
107
|
+
return isInstalled;
|
|
113
108
|
}
|
|
114
109
|
/**
|
|
115
110
|
* Tests if an instance of JS-Controller is already running by attempting to connect to the Objects DB
|
|
@@ -165,41 +160,34 @@ class ControllerSetup {
|
|
|
165
160
|
// }
|
|
166
161
|
/**
|
|
167
162
|
* Sets up an existing JS-Controller instance for testing by executing "iobroker setup first"
|
|
168
|
-
* @param appName The branded name of "iobroker"
|
|
169
|
-
* @param testDir The directory the integration tests are executed in
|
|
170
163
|
*/
|
|
171
|
-
setupJsController() {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
stdout: "ignore",
|
|
182
|
-
});
|
|
183
|
-
if (setupResult.exitCode !== 0)
|
|
184
|
-
throw new Error(`${this.appName} setup first failed!`);
|
|
185
|
-
debug(" => done!");
|
|
164
|
+
async setupJsController() {
|
|
165
|
+
debug("Initializing JS-Controller installation...");
|
|
166
|
+
// Stop the controller before calling setup first
|
|
167
|
+
await (0, executeCommand_1.executeCommand)("node", [`${this.appName}.js`, "stop"], {
|
|
168
|
+
cwd: this.testControllerDir,
|
|
169
|
+
stdout: "ignore",
|
|
170
|
+
});
|
|
171
|
+
const setupResult = await (0, executeCommand_1.executeCommand)("node", [`${this.appName}.js`, "setup", "first", "--console"], {
|
|
172
|
+
cwd: this.testControllerDir,
|
|
173
|
+
stdout: "ignore",
|
|
186
174
|
});
|
|
175
|
+
if (setupResult.exitCode !== 0)
|
|
176
|
+
throw new Error(`${this.appName} setup first failed!`);
|
|
177
|
+
debug(" => done!");
|
|
187
178
|
}
|
|
188
179
|
/**
|
|
189
180
|
* Changes the objects and states db to use alternative ports
|
|
190
181
|
* @param appName The branded name of "iobroker"
|
|
191
182
|
* @param testDir The directory the integration tests are executed in
|
|
192
183
|
*/
|
|
193
|
-
setupSystemConfig() {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
yield fs_extra_1.writeFile(systemFilename, JSON.stringify(systemConfig, null, 2));
|
|
201
|
-
debug(" => done!");
|
|
202
|
-
});
|
|
184
|
+
setupSystemConfig(dbConnection) {
|
|
185
|
+
debug(`Moving databases to different ports...`);
|
|
186
|
+
const systemConfig = dbConnection.getSystemConfig();
|
|
187
|
+
systemConfig.objects.port = 19001;
|
|
188
|
+
systemConfig.states.port = 19000;
|
|
189
|
+
dbConnection.setSystemConfig(systemConfig);
|
|
190
|
+
debug(" => done!");
|
|
203
191
|
}
|
|
204
192
|
/**
|
|
205
193
|
* Clears the log dir for integration tests (and creates it if it doesn't exist)
|
|
@@ -208,7 +196,7 @@ class ControllerSetup {
|
|
|
208
196
|
*/
|
|
209
197
|
clearLogDir() {
|
|
210
198
|
debug("Cleaning log directory...");
|
|
211
|
-
return fs_extra_1.emptyDir(tools_1.getTestLogDir(this.appName, this.testDir));
|
|
199
|
+
return (0, fs_extra_1.emptyDir)((0, tools_1.getTestLogDir)(this.appName, this.testDir));
|
|
212
200
|
}
|
|
213
201
|
/**
|
|
214
202
|
* Clears the sqlite DB dir for integration tests (and creates it if it doesn't exist)
|
|
@@ -217,28 +205,25 @@ class ControllerSetup {
|
|
|
217
205
|
*/
|
|
218
206
|
clearDBDir() {
|
|
219
207
|
debug("Cleaning SQLite directory...");
|
|
220
|
-
return fs_extra_1.emptyDir(tools_1.getTestDBDir(this.appName, this.testDir));
|
|
208
|
+
return (0, fs_extra_1.emptyDir)((0, tools_1.getTestDBDir)(this.appName, this.testDir));
|
|
221
209
|
}
|
|
222
210
|
/**
|
|
223
211
|
* Disables all admin instances in the objects DB
|
|
224
212
|
* @param objects The contents of objects.json
|
|
225
213
|
*/
|
|
226
|
-
disableAdminInstances() {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
for (const id of Object.keys(objects)) {
|
|
232
|
-
if (/^system\.adapter\.admin\.\d.+$/.test(id)) {
|
|
233
|
-
const obj = objects[id];
|
|
234
|
-
if (obj && obj.common)
|
|
235
|
-
obj.common.enabled = false;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
yield this.dbConnection.writeObjectsDB(objects);
|
|
239
|
-
}
|
|
240
|
-
debug(" => done!");
|
|
214
|
+
async disableAdminInstances(dbConnection) {
|
|
215
|
+
debug("Disabling admin instances...");
|
|
216
|
+
const instanceObjects = await dbConnection.getObjectViewAsync("system", "instance", {
|
|
217
|
+
startkey: "system.adapter.admin.",
|
|
218
|
+
endkey: "system.adapter.admin.\u9999",
|
|
241
219
|
});
|
|
220
|
+
for (const { id, value: obj } of instanceObjects.rows) {
|
|
221
|
+
if (obj && obj.common) {
|
|
222
|
+
obj.common.enabled = false;
|
|
223
|
+
await dbConnection.setObject(id, obj);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
debug(" => done!");
|
|
242
227
|
}
|
|
243
228
|
}
|
|
244
229
|
exports.ControllerSetup = ControllerSetup;
|
|
@@ -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
|
}
|