@iobroker/testing 2.4.4 → 2.5.3
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 +11 -0
- package/LICENSE +1 -1
- package/build/lib/adapterTools.js +27 -38
- package/build/lib/executeCommand.js +3 -4
- package/build/tests/integration/index.js +57 -74
- package/build/tests/integration/lib/adapterSetup.d.ts +1 -1
- package/build/tests/integration/lib/adapterSetup.js +76 -93
- package/build/tests/integration/lib/controllerSetup.d.ts +1 -1
- package/build/tests/integration/lib/controllerSetup.js +82 -99
- package/build/tests/integration/lib/dbConnection.js +32 -53
- package/build/tests/integration/lib/harness.js +129 -153
- 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 +30 -28
|
@@ -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.TestHarness = void 0;
|
|
35
|
-
/* eslint-disable @typescript-eslint/camelcase */
|
|
36
26
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
37
27
|
const async_1 = require("alcalzone-shared/async");
|
|
38
28
|
const objects_1 = require("alcalzone-shared/objects");
|
|
@@ -43,7 +33,7 @@ const path = __importStar(require("path"));
|
|
|
43
33
|
const adapterTools_1 = require("../../../lib/adapterTools");
|
|
44
34
|
const dbConnection_1 = require("./dbConnection");
|
|
45
35
|
const tools_1 = require("./tools");
|
|
46
|
-
const debug = debug_1.default("testing:integration:TestHarness");
|
|
36
|
+
const debug = (0, debug_1.default)("testing:integration:TestHarness");
|
|
47
37
|
const isWindows = /^win/.test(process.platform);
|
|
48
38
|
/** The logger instance for the objects and states DB */
|
|
49
39
|
const logger = {
|
|
@@ -69,10 +59,10 @@ class TestHarness extends events_1.EventEmitter {
|
|
|
69
59
|
this.testDir = testDir;
|
|
70
60
|
this.sendToID = 1;
|
|
71
61
|
debug("Creating instance");
|
|
72
|
-
this.adapterName = adapterTools_1.getAdapterName(this.adapterDir);
|
|
73
|
-
this.appName = adapterTools_1.getAppName(adapterDir);
|
|
74
|
-
this.testControllerDir = tools_1.getTestControllerDir(this.appName, testDir);
|
|
75
|
-
this.testAdapterDir = tools_1.getTestAdapterDir(this.adapterDir, testDir);
|
|
62
|
+
this.adapterName = (0, adapterTools_1.getAdapterName)(this.adapterDir);
|
|
63
|
+
this.appName = (0, adapterTools_1.getAppName)(adapterDir);
|
|
64
|
+
this.testControllerDir = (0, tools_1.getTestControllerDir)(this.appName, testDir);
|
|
65
|
+
this.testAdapterDir = (0, tools_1.getTestAdapterDir)(this.adapterDir, testDir);
|
|
76
66
|
debug(` directories:`);
|
|
77
67
|
debug(` controller: ${this.testControllerDir}`);
|
|
78
68
|
debug(` adapter: ${this.testAdapterDir}`);
|
|
@@ -97,56 +87,52 @@ class TestHarness extends events_1.EventEmitter {
|
|
|
97
87
|
return this._adapterExit;
|
|
98
88
|
}
|
|
99
89
|
/** Creates the objects DB and sets up listeners for it */
|
|
100
|
-
createObjectsDB() {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
change: this.emit.bind(this, "objectChange"),
|
|
122
|
-
});
|
|
90
|
+
async createObjectsDB() {
|
|
91
|
+
debug("creating objects DB");
|
|
92
|
+
const Objects = require(path.join(this.testControllerDir, "lib/objects/objectsInMemServer"));
|
|
93
|
+
return new Promise((resolve) => {
|
|
94
|
+
this._objects = new Objects({
|
|
95
|
+
connection: {
|
|
96
|
+
type: "file",
|
|
97
|
+
host: "127.0.0.1",
|
|
98
|
+
port: 19001,
|
|
99
|
+
user: "",
|
|
100
|
+
pass: "",
|
|
101
|
+
noFileCache: false,
|
|
102
|
+
connectTimeout: 2000,
|
|
103
|
+
},
|
|
104
|
+
logger,
|
|
105
|
+
connected: () => {
|
|
106
|
+
debug(" => done!");
|
|
107
|
+
this._objects.subscribe("*");
|
|
108
|
+
resolve();
|
|
109
|
+
},
|
|
110
|
+
change: this.emit.bind(this, "objectChange"),
|
|
123
111
|
});
|
|
124
112
|
});
|
|
125
113
|
}
|
|
126
114
|
/** Creates the states DB and sets up listeners for it */
|
|
127
|
-
createStatesDB() {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
retry_max_delay: 15000,
|
|
140
|
-
},
|
|
141
|
-
},
|
|
142
|
-
logger,
|
|
143
|
-
connected: () => {
|
|
144
|
-
debug(" => done!");
|
|
145
|
-
this._states.subscribe("*");
|
|
146
|
-
resolve();
|
|
115
|
+
async createStatesDB() {
|
|
116
|
+
debug("creating states DB");
|
|
117
|
+
const States = require(path.join(this.testControllerDir, "lib/states/statesInMemServer"));
|
|
118
|
+
return new Promise((resolve) => {
|
|
119
|
+
this._states = new States({
|
|
120
|
+
connection: {
|
|
121
|
+
type: "file",
|
|
122
|
+
host: "127.0.0.1",
|
|
123
|
+
port: 19000,
|
|
124
|
+
options: {
|
|
125
|
+
auth_pass: null,
|
|
126
|
+
retry_max_delay: 15000,
|
|
147
127
|
},
|
|
148
|
-
|
|
149
|
-
|
|
128
|
+
},
|
|
129
|
+
logger,
|
|
130
|
+
connected: () => {
|
|
131
|
+
debug(" => done!");
|
|
132
|
+
this._states.subscribe("*");
|
|
133
|
+
resolve();
|
|
134
|
+
},
|
|
135
|
+
change: this.emit.bind(this, "stateChange"),
|
|
150
136
|
});
|
|
151
137
|
});
|
|
152
138
|
}
|
|
@@ -155,101 +141,93 @@ class TestHarness extends events_1.EventEmitter {
|
|
|
155
141
|
return !!this._objects || !!this._states;
|
|
156
142
|
}
|
|
157
143
|
/** Starts the controller instance by creating the databases */
|
|
158
|
-
startController() {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
debug("controller instance created");
|
|
166
|
-
});
|
|
144
|
+
async startController() {
|
|
145
|
+
debug("starting controller instance...");
|
|
146
|
+
if (this.isControllerRunning())
|
|
147
|
+
throw new Error("The Controller is already running!");
|
|
148
|
+
await this.createObjectsDB();
|
|
149
|
+
await this.createStatesDB();
|
|
150
|
+
debug("controller instance created");
|
|
167
151
|
}
|
|
168
152
|
/** Stops the controller instance (and the adapter if it is running) */
|
|
169
|
-
stopController() {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
stopTimeout += 1000;
|
|
180
|
-
}
|
|
181
|
-
catch (_a) { }
|
|
182
|
-
stopTimeout || (stopTimeout = 5000); // default 5s
|
|
183
|
-
debug(` => giving it ${stopTimeout}ms to terminate`);
|
|
184
|
-
yield Promise.race([this.stopAdapter(), async_1.wait(stopTimeout)]);
|
|
185
|
-
if (this.isAdapterRunning()) {
|
|
186
|
-
debug("Adapter did not terminate, killing it");
|
|
187
|
-
this._adapterProcess.kill("SIGKILL");
|
|
188
|
-
}
|
|
189
|
-
else {
|
|
190
|
-
debug("Adapter terminated");
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
debug("Adapter failed to start - no need to terminate!");
|
|
153
|
+
async stopController() {
|
|
154
|
+
if (!this.isControllerRunning())
|
|
155
|
+
return;
|
|
156
|
+
if (!this.didAdapterStop()) {
|
|
157
|
+
debug("Stopping adapter instance...");
|
|
158
|
+
// Give the adapter time to stop (as long as configured in the io-package.json)
|
|
159
|
+
let stopTimeout;
|
|
160
|
+
try {
|
|
161
|
+
stopTimeout = (await this._objects.getObjectAsync(`system.adapter.${this.adapterName}.0`)).common.stopTimeout;
|
|
162
|
+
stopTimeout += 1000;
|
|
195
163
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
164
|
+
catch { }
|
|
165
|
+
stopTimeout || (stopTimeout = 5000); // default 5s
|
|
166
|
+
debug(` => giving it ${stopTimeout}ms to terminate`);
|
|
167
|
+
await Promise.race([this.stopAdapter(), (0, async_1.wait)(stopTimeout)]);
|
|
168
|
+
if (this.isAdapterRunning()) {
|
|
169
|
+
debug("Adapter did not terminate, killing it");
|
|
170
|
+
this._adapterProcess.kill("SIGKILL");
|
|
200
171
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
this._states = null;
|
|
172
|
+
else {
|
|
173
|
+
debug("Adapter terminated");
|
|
204
174
|
}
|
|
205
|
-
|
|
206
|
-
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
debug("Adapter failed to start - no need to terminate!");
|
|
178
|
+
}
|
|
179
|
+
debug("Stopping controller instance...");
|
|
180
|
+
if (this._objects) {
|
|
181
|
+
await this._objects.destroy();
|
|
182
|
+
this._objects = null;
|
|
183
|
+
}
|
|
184
|
+
if (this._states) {
|
|
185
|
+
await this._states.destroy();
|
|
186
|
+
this._states = null;
|
|
187
|
+
}
|
|
188
|
+
debug("Controller instance stopped");
|
|
207
189
|
}
|
|
208
190
|
/**
|
|
209
191
|
* Starts the adapter in a separate process and monitors its status
|
|
210
192
|
* @param env Additional environment variables to set
|
|
211
193
|
*/
|
|
212
|
-
startAdapter(env = {}) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
this.
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
.on("exit", onClose);
|
|
232
|
-
});
|
|
194
|
+
async startAdapter(env = {}) {
|
|
195
|
+
if (this.isAdapterRunning())
|
|
196
|
+
throw new Error("The adapter is already running!");
|
|
197
|
+
else if (this.didAdapterStop())
|
|
198
|
+
throw new Error("This test harness has already been used. Please create a new one for each test!");
|
|
199
|
+
const mainFileAbsolute = await (0, adapterTools_1.locateAdapterMainFile)(this.testAdapterDir);
|
|
200
|
+
const mainFileRelative = path.relative(this.testAdapterDir, mainFileAbsolute);
|
|
201
|
+
const onClose = (code, signal) => {
|
|
202
|
+
this._adapterProcess.removeAllListeners();
|
|
203
|
+
this._adapterExit = code != undefined ? code : signal;
|
|
204
|
+
this.emit("failed", this._adapterExit);
|
|
205
|
+
};
|
|
206
|
+
this._adapterProcess = (0, child_process_1.spawn)(isWindows ? "node.exe" : "node", [mainFileRelative, "--console"], {
|
|
207
|
+
cwd: this.testAdapterDir,
|
|
208
|
+
stdio: ["inherit", "inherit", "inherit"],
|
|
209
|
+
env: { ...process.env, ...env },
|
|
210
|
+
})
|
|
211
|
+
.on("close", onClose)
|
|
212
|
+
.on("exit", onClose);
|
|
233
213
|
}
|
|
234
214
|
/**
|
|
235
215
|
* Starts the adapter in a separate process and resolves after it has started
|
|
236
216
|
* @param env Additional environment variables to set
|
|
237
217
|
*/
|
|
238
|
-
startAdapterAndWait(env = {}) {
|
|
239
|
-
return
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
.startAdapter(env);
|
|
252
|
-
});
|
|
218
|
+
async startAdapterAndWait(env = {}) {
|
|
219
|
+
return new Promise((resolve, reject) => {
|
|
220
|
+
this.on("stateChange", async (id, state) => {
|
|
221
|
+
if (id === `system.adapter.${this.adapterName}.0.alive` &&
|
|
222
|
+
state &&
|
|
223
|
+
state.val === true) {
|
|
224
|
+
resolve();
|
|
225
|
+
}
|
|
226
|
+
})
|
|
227
|
+
.on("failed", (code) => {
|
|
228
|
+
reject(new Error(`The adapter startup was interrupted unexpectedly with ${typeof code === "number" ? "code" : "signal"} ${code}`));
|
|
229
|
+
})
|
|
230
|
+
.startAdapter(env);
|
|
253
231
|
});
|
|
254
232
|
}
|
|
255
233
|
/** Tests if the adapter process is still running */
|
|
@@ -264,7 +242,7 @@ class TestHarness extends events_1.EventEmitter {
|
|
|
264
242
|
stopAdapter() {
|
|
265
243
|
if (!this.isAdapterRunning())
|
|
266
244
|
return;
|
|
267
|
-
return new Promise((resolve) =>
|
|
245
|
+
return new Promise(async (resolve) => {
|
|
268
246
|
var _a;
|
|
269
247
|
const onClose = (code, signal) => {
|
|
270
248
|
if (!this._adapterProcess)
|
|
@@ -282,7 +260,7 @@ class TestHarness extends events_1.EventEmitter {
|
|
|
282
260
|
.on("exit", onClose);
|
|
283
261
|
// Tell adapter to stop
|
|
284
262
|
if (this._states) {
|
|
285
|
-
|
|
263
|
+
await this._states.setStateAsync(`system.adapter.${this.adapterName}.0.sigKill`, {
|
|
286
264
|
val: -1,
|
|
287
265
|
from: "system.host.testing",
|
|
288
266
|
});
|
|
@@ -290,21 +268,19 @@ class TestHarness extends events_1.EventEmitter {
|
|
|
290
268
|
else {
|
|
291
269
|
(_a = this._adapterProcess) === null || _a === void 0 ? void 0 : _a.kill("SIGTERM");
|
|
292
270
|
}
|
|
293
|
-
})
|
|
271
|
+
});
|
|
294
272
|
}
|
|
295
273
|
/**
|
|
296
274
|
* Updates the adapter config. The changes can be a subset of the target object
|
|
297
275
|
*/
|
|
298
|
-
changeAdapterConfig(appName, testDir, adapterName, changes) {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
}
|
|
307
|
-
});
|
|
276
|
+
async changeAdapterConfig(appName, testDir, adapterName, changes) {
|
|
277
|
+
const objects = await this.dbConnection.readObjectsDB();
|
|
278
|
+
const adapterInstanceId = `system.adapter.${adapterName}.0`;
|
|
279
|
+
if (objects && adapterInstanceId in objects) {
|
|
280
|
+
const target = objects[adapterInstanceId];
|
|
281
|
+
(0, objects_1.extend)(target, changes);
|
|
282
|
+
await this.dbConnection.writeObjectsDB(objects);
|
|
283
|
+
}
|
|
308
284
|
}
|
|
309
285
|
/** Enables the sendTo method */
|
|
310
286
|
enableSendTo() {
|
|
@@ -64,7 +64,7 @@ exports.getTestDBDir = getTestDBDir;
|
|
|
64
64
|
* @param testDir The directory the integration tests are executed in
|
|
65
65
|
*/
|
|
66
66
|
function getTestAdapterDir(adapterDir, testDir) {
|
|
67
|
-
const adapterName = adapterTools_1.getAdapterFullName(adapterDir);
|
|
67
|
+
const adapterName = (0, adapterTools_1.getAdapterFullName)(adapterDir);
|
|
68
68
|
return path.resolve(testDir, "node_modules", adapterName);
|
|
69
69
|
}
|
|
70
70
|
exports.getTestAdapterDir = getTestAdapterDir;
|
|
@@ -54,7 +54,7 @@ function validatePackageFiles(adapterDir) {
|
|
|
54
54
|
it(`The property "${propertyPath}" exists`, () => {
|
|
55
55
|
let prev = targetObj;
|
|
56
56
|
for (const part of propertyParts) {
|
|
57
|
-
chai_1.expect(prev[part]).to.not.be.undefined;
|
|
57
|
+
(0, chai_1.expect)(prev[part]).to.not.be.undefined;
|
|
58
58
|
prev = prev[part];
|
|
59
59
|
}
|
|
60
60
|
});
|
|
@@ -71,15 +71,15 @@ function validatePackageFiles(adapterDir) {
|
|
|
71
71
|
skipIfInvalid.call(this, filename);
|
|
72
72
|
});
|
|
73
73
|
it("exists", () => {
|
|
74
|
-
chai_1.expect(fs.existsSync(packagePath), `${filename} is missing in the adapter dir. Please create it!`).to.be.true;
|
|
74
|
+
(0, chai_1.expect)(fs.existsSync(packagePath), `${filename} is missing in the adapter dir. Please create it!`).to.be.true;
|
|
75
75
|
});
|
|
76
76
|
it("contains valid JSON", () => {
|
|
77
|
-
chai_1.expect(() => {
|
|
77
|
+
(0, chai_1.expect)(() => {
|
|
78
78
|
JSON.parse(fs.readFileSync(packagePath, "utf8"));
|
|
79
79
|
}, `${filename} contains invalid JSON!`).not.to.throw();
|
|
80
80
|
});
|
|
81
81
|
it("is an object", () => {
|
|
82
|
-
chai_1.expect(require(packagePath), `${filename} must contain an object!`).to.be.an("object");
|
|
82
|
+
(0, chai_1.expect)(require(packagePath), `${filename} must contain an object!`).to.be.an("object");
|
|
83
83
|
});
|
|
84
84
|
});
|
|
85
85
|
}
|
|
@@ -102,17 +102,18 @@ function validatePackageFiles(adapterDir) {
|
|
|
102
102
|
requiredProperties.forEach((prop) => ensurePropertyExists(prop, packageContent));
|
|
103
103
|
it("The package name is correct", () => {
|
|
104
104
|
let name = packageContent.name;
|
|
105
|
-
chai_1.expect(name).to.match(/^iobroker\./, `The npm package name must start with lowercase "iobroker."!`);
|
|
105
|
+
(0, chai_1.expect)(name).to.match(/^iobroker\./, `The npm package name must start with lowercase "iobroker."!`);
|
|
106
106
|
name = name.replace(/^iobroker\./, "");
|
|
107
|
-
chai_1.expect(name).to.match(/[a-z0-9_\-]+/, `The adapter name must only contain lowercase letters, numbers, "-" and "_"!`);
|
|
108
|
-
chai_1.expect(name).to.match(/^[a-z]/, `The adapter name must start with a letter!`);
|
|
109
|
-
chai_1.expect(name).to.match(/[a-z0-9]$/, `The adapter name must end with a letter or number!`);
|
|
107
|
+
(0, chai_1.expect)(name).to.match(/[a-z0-9_\-]+/, `The adapter name must only contain lowercase letters, numbers, "-" and "_"!`);
|
|
108
|
+
(0, chai_1.expect)(name).to.match(/^[a-z]/, `The adapter name must start with a letter!`);
|
|
109
|
+
(0, chai_1.expect)(name).to.match(/[a-z0-9]$/, `The adapter name must end with a letter or number!`);
|
|
110
110
|
});
|
|
111
111
|
it(`The repository type is "git"`, () => {
|
|
112
|
-
chai_1.expect(packageContent.repository.type).to.equal("git");
|
|
112
|
+
(0, chai_1.expect)(packageContent.repository.type).to.equal("git");
|
|
113
113
|
});
|
|
114
114
|
});
|
|
115
115
|
describe(`Check contents of io-package.json`, () => {
|
|
116
|
+
var _a;
|
|
116
117
|
beforeEach(function () {
|
|
117
118
|
skipIfInvalid.call(this, "io-package.json");
|
|
118
119
|
});
|
|
@@ -134,35 +135,40 @@ function validatePackageFiles(adapterDir) {
|
|
|
134
135
|
it(`The title does not contain "adapter" or "iobroker"`, () => {
|
|
135
136
|
if (!iopackContent.title)
|
|
136
137
|
return;
|
|
137
|
-
chai_1.expect(iopackContent.common.title).not.to.match(/iobroker|adapter/i);
|
|
138
|
+
(0, chai_1.expect)(iopackContent.common.title).not.to.match(/iobroker|adapter/i);
|
|
138
139
|
});
|
|
139
140
|
it(`titleLang is an object to support multiple languages`, () => {
|
|
140
|
-
chai_1.expect(iopackContent.common.titleLang).to.be.an("object");
|
|
141
|
+
(0, chai_1.expect)(iopackContent.common.titleLang).to.be.an("object");
|
|
141
142
|
});
|
|
142
143
|
it(`titleLang does not contain "adapter" or "iobroker"`, () => {
|
|
143
144
|
for (const title of Object.values(iopackContent.common.titleLang)) {
|
|
144
|
-
chai_1.expect(title).not.to.match(/iobroker|adapter/i);
|
|
145
|
+
(0, chai_1.expect)(title).not.to.match(/iobroker|adapter/i);
|
|
145
146
|
}
|
|
146
147
|
});
|
|
147
148
|
it(`The description is an object to support multiple languages`, () => {
|
|
148
|
-
chai_1.expect(iopackContent.common.desc).to.be.an("object");
|
|
149
|
+
(0, chai_1.expect)(iopackContent.common.desc).to.be.an("object");
|
|
149
150
|
});
|
|
150
151
|
it(`common.authors is an array that is not empty`, () => {
|
|
151
152
|
const authors = iopackContent.common.authors;
|
|
152
|
-
chai_1.expect(typeguards_1.isArray(authors)).to.be.true;
|
|
153
|
-
chai_1.expect(authors.length).to.be.at.least(1);
|
|
153
|
+
(0, chai_1.expect)((0, typeguards_1.isArray)(authors)).to.be.true;
|
|
154
|
+
(0, chai_1.expect)(authors.length).to.be.at.least(1);
|
|
154
155
|
});
|
|
155
156
|
it(`common.news is an object that contains maximum 20 entries`, () => {
|
|
156
157
|
const news = iopackContent.common.news;
|
|
157
|
-
chai_1.expect(typeguards_1.isObject(news)).to.be.true;
|
|
158
|
-
chai_1.expect(Object.keys(news).length).to.be.at.most(20);
|
|
158
|
+
(0, chai_1.expect)((0, typeguards_1.isObject)(news)).to.be.true;
|
|
159
|
+
(0, chai_1.expect)(Object.keys(news).length).to.be.at.most(20);
|
|
159
160
|
});
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
iopackContent.common.
|
|
164
|
-
|
|
165
|
-
|
|
161
|
+
// If the adapter has a configuration page, check that a supported admin UI is used
|
|
162
|
+
const hasNoConfigPage = iopackContent.common.noConfig === true ||
|
|
163
|
+
iopackContent.common.noConfig === "true" ||
|
|
164
|
+
((_a = iopackContent.common.adminUI) === null || _a === void 0 ? void 0 : _a.config) === "none";
|
|
165
|
+
if (!hasNoConfigPage) {
|
|
166
|
+
it("The adapter uses Material UI or JSON Config for the admin UI", () => {
|
|
167
|
+
var _a, _b;
|
|
168
|
+
const hasSupportedUI = !!iopackContent.common.materialize ||
|
|
169
|
+
((_a = iopackContent.common.adminUI) === null || _a === void 0 ? void 0 : _a.config) === "json" ||
|
|
170
|
+
((_b = iopackContent.common.adminUI) === null || _b === void 0 ? void 0 : _b.config) === "materialize";
|
|
171
|
+
(0, chai_1.expect)(hasSupportedUI, "Unsupported Admin UI, must be materialize or json config!").to.be.true;
|
|
166
172
|
});
|
|
167
173
|
}
|
|
168
174
|
});
|
|
@@ -173,13 +179,13 @@ function validatePackageFiles(adapterDir) {
|
|
|
173
179
|
const packageContent = require(packageJsonPath);
|
|
174
180
|
const iopackContent = require(ioPackageJsonPath);
|
|
175
181
|
it("The name matches", () => {
|
|
176
|
-
chai_1.expect("iobroker." + iopackContent.common.name).to.equal(packageContent.name);
|
|
182
|
+
(0, chai_1.expect)("iobroker." + iopackContent.common.name).to.equal(packageContent.name);
|
|
177
183
|
});
|
|
178
184
|
it("The version matches", () => {
|
|
179
|
-
chai_1.expect(iopackContent.common.version).to.equal(packageContent.version);
|
|
185
|
+
(0, chai_1.expect)(iopackContent.common.version).to.equal(packageContent.version);
|
|
180
186
|
});
|
|
181
187
|
it("The license matches", () => {
|
|
182
|
-
chai_1.expect(iopackContent.common.license).to.equal(packageContent.license);
|
|
188
|
+
(0, chai_1.expect)(iopackContent.common.license).to.equal(packageContent.license);
|
|
183
189
|
});
|
|
184
190
|
});
|
|
185
191
|
});
|
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
exports.testAdapterWithMocks = void 0;
|
|
13
4
|
/**
|
|
@@ -16,7 +7,7 @@ exports.testAdapterWithMocks = void 0;
|
|
|
16
7
|
* This is meant to be executed in a mocha context.
|
|
17
8
|
*/
|
|
18
9
|
function testAdapterWithMocks(_adapterDir, options = {}) {
|
|
19
|
-
describe(`Unit tests`, () =>
|
|
10
|
+
describe(`Unit tests`, async () => {
|
|
20
11
|
// Call the user's tests
|
|
21
12
|
if (typeof options.defineAdditionalTests === "function") {
|
|
22
13
|
options.defineAdditionalTests();
|
|
@@ -28,6 +19,6 @@ function testAdapterWithMocks(_adapterDir, options = {}) {
|
|
|
28
19
|
console.warn(`from package.json and from your Travis/Github Actions workflow.\u001b[0m`);
|
|
29
20
|
});
|
|
30
21
|
}
|
|
31
|
-
})
|
|
22
|
+
});
|
|
32
23
|
}
|
|
33
24
|
exports.testAdapterWithMocks = testAdapterWithMocks;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="iobroker" />
|
|
2
|
-
import { MockDatabase } from "./mockDatabase";
|
|
2
|
+
import type { MockDatabase } from "./mockDatabase";
|
|
3
3
|
import { MockLogger } from "./mockLogger";
|
|
4
4
|
import { Mock } from "./tools";
|
|
5
5
|
export declare type MockAdapter = Mock<ioBroker.Adapter> & {
|