@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 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) 2021 AlCalzone <d.griesel@gmx.net>
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.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
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.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
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.adapterShouldSupportCompactMode = exports.loadIoPackage = exports.loadNpmPackage = void 0;
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 adapterShouldSupportCompactMode(dirOrIoPack) {
49
- if (typeof dirOrIoPack === "string")
50
- dirOrIoPack = loadIoPackage(dirOrIoPack);
51
- return dirOrIoPack.common.compact === true;
52
+ function getAdapterExecutionMode(adapterDir) {
53
+ const ioPackage = loadIoPackage(adapterDir);
54
+ return ioPackage.common.mode;
52
55
  }
53
- exports.adapterShouldSupportCompactMode = adapterShouldSupportCompactMode;
56
+ exports.getAdapterExecutionMode = getAdapterExecutionMode;
54
57
  /**
55
58
  * Locates an adapter's main file
56
59
  * @param adapterDir The directory the adapter resides in
@@ -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.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
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 dbConnection = new dbConnection_1.DBConnection(appName, testDir);
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, dbConnection);
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
- await adapterSetup.copyAdapterFilesToTestDir();
56
- // Remember if JS-Controller is installed already. If so, we need to call setup first later
57
- const wasJsControllerInstalled = await controllerSetup.isJsControllerInstalled();
58
- // Call npm install
59
- await (0, executeCommand_1.executeCommand)("npm", ["i", "--production"], {
60
- cwd: testDir,
61
- });
62
- // Prepare/clean the databases and config
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.readDB());
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.writeDB(objectsBackup, statesBackup),
82
+ dbConnection.restore(objectsBackup, statesBackup),
80
83
  ]);
81
84
  // Create a new test harness
82
- harness = new harness_1.TestHarness(adapterDir, testDir);
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(appName, testDir, adapterName, {
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 (options.allowedExitCodes == undefined ||
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
- private dbConnection;
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
- copyAdapterFilesToTestDir(): Promise<void>;
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.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
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, dbConnection) {
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 copyAdapterFilesToTestDir() {
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 { objects, states } = await this.dbConnection.readDB();
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
- if (objects) {
124
- for (const id of Object.keys(objects)) {
125
- if (belongsToAdapter(id))
126
- delete objects[id];
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
- if (states) {
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
- private dbConnection;
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(): Promise<void>;
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.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
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, dbConnection) {
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
- async setupSystemConfig() {
179
- debug("Moving databases to different ports...");
180
- const systemFilename = path.join(this.testDataDir, `${this.appName}.json`);
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
- await (0, fs_extra_1.writeFile)(systemFilename, JSON.stringify(systemConfig, null, 2));
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 objects = await this.dbConnection.readObjectsDB();
212
- if (objects) {
213
- for (const id of Object.keys(objects)) {
214
- if (/^system\.adapter\.admin\.\d.+$/.test(id)) {
215
- const obj = objects[id];
216
- if (obj && obj.common)
217
- obj.common.enabled = false;
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
- /** The DB connection capsules access to the objects.json and states.json on disk */
5
- export declare class DBConnection {
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 objectsPath;
15
- private statesPath;
16
- readObjectsDB(): Promise<Record<string, ioBroker.Object> | undefined>;
17
- writeObjectsDB(objects: ObjectsDB | undefined): Promise<void>;
18
- writeStatesDB(states: StatesDB | undefined): Promise<void>;
19
- readStatesDB(): Promise<any>;
20
- /**
21
- * Creates a backup of the objects and states DB, so it can be restored after each test
22
- * @param appName The branded name of "iobroker"
23
- * @param testDir The directory the integration tests are executed in
24
- */
25
- readDB(): Promise<{
26
- objects: Record<string, ioBroker.Object> | undefined;
27
- states: any;
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
- * Restores a previous backup of the objects and states DB
31
- * @param appName The branded name of "iobroker"
32
- * @param testDir The directory the integration tests are executed in
33
- */
34
- writeDB(objects: any, states: any): Promise<void>;
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
  }