Skip to content

Commit 3624ccc

Browse files
CopilotApollon77
andcommitted
Add CLI tests to CI pipeline and enhance adapter lifecycle testing
Co-authored-by: Apollon77 <11976694+Apollon77@users.noreply.github.com>
1 parent 695ebf7 commit 3624ccc

File tree

3 files changed

+113
-48
lines changed

3 files changed

+113
-48
lines changed

.github/workflows/ci-tests.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ jobs:
9090
- name: Execute Jsonl Tests
9191
run: npm run test-jsonl
9292

93+
- name: Execute CLI Tests
94+
run: npm run test-cli
95+
9396
- name: Redis Socket/Sentinel Tests (Linux)
9497
if: ${{ matrix.os == 'ubuntu-22.04' }}
9598
run: |

packages/cli/test/adapter-lifecycle.test.ts

Lines changed: 110 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -123,17 +123,49 @@ describe('Adapter Lifecycle Tests', function () {
123123
describe('Adapter and Instance Management Lifecycle', function () {
124124
// Use a test adapter that should be available - we'll use 'admin' as it's always present in ioBroker
125125
const testAdapter = 'admin';
126+
let adapterWasInstalled = false;
126127

127-
it('should successfully install an adapter (if not already installed)', async function () {
128+
it('should successfully install admin adapter', async function () {
128129
// First check if adapter is already installed
129130
const listResult = await runCliCommand(['list', 'adapters']);
130131
expect(listResult.exitCode).to.equal(0);
131132

132133
if (!listResult.stdout.includes(testAdapter)) {
133-
// Try to install the adapter - this might fail in test environment, which is OK
134-
const installResult = await runCliCommand(['install', testAdapter]);
135-
// We don't assert success here as it depends on network connectivity and repos
136-
console.log(`Install result for ${testAdapter}: ${installResult.exitCode}`);
134+
// Try to install the adapter
135+
const installResult = await runCliCommand(['install', testAdapter], 60000);
136+
137+
if (installResult.exitCode !== 0) {
138+
if (installResult.stderr.includes('TIMEOUT') ||
139+
installResult.stderr.includes('getaddrinfo ENOTFOUND') ||
140+
installResult.stderr.includes('dns block')) {
141+
console.log(`Skipping test - network not available for adapter installation`);
142+
this.skip();
143+
return;
144+
}
145+
}
146+
147+
expect(installResult.exitCode).to.equal(0, `Failed to install ${testAdapter}: ${installResult.stderr}`);
148+
adapterWasInstalled = true;
149+
150+
// Verify the adapter was actually installed
151+
const verifyResult = await runCliCommand(['list', 'adapters']);
152+
expect(verifyResult.exitCode).to.equal(0);
153+
expect(verifyResult.stdout).to.include(testAdapter);
154+
155+
// Check that adapter files were created
156+
const adapterDir = path.join(testDir, 'node_modules', `iobroker.${testAdapter}`);
157+
expect(await fs.pathExists(adapterDir)).to.be.true;
158+
159+
// Check that io-package.json exists
160+
const ioPackageFile = path.join(adapterDir, 'io-package.json');
161+
expect(await fs.pathExists(ioPackageFile)).to.be.true;
162+
163+
// Validate the io-package.json structure
164+
const ioPackage = await fs.readJSON(ioPackageFile);
165+
expect(ioPackage).to.have.property('common');
166+
expect(ioPackage.common).to.have.property('name', testAdapter);
167+
} else {
168+
console.log(`${testAdapter} adapter already installed`);
137169
}
138170
});
139171

@@ -145,7 +177,7 @@ describe('Adapter Lifecycle Tests', function () {
145177
expect(result.stderr).to.not.include('TIMEOUT');
146178
});
147179

148-
it('should create an adapter instance (if adapter is available)', async function () {
180+
it('should create an adapter instance and validate objects/states', async function () {
149181
// First check if adapter exists
150182
const listResult = await runCliCommand(['list', 'adapters']);
151183

@@ -155,14 +187,37 @@ describe('Adapter Lifecycle Tests', function () {
155187

156188
// The command should complete without crashing
157189
expect(result.stderr).to.not.include('TIMEOUT');
158-
159-
// If successful, should show in instance list
160-
if (result.exitCode === 0) {
161-
const instancesResult = await runCliCommand(['list', 'instances']);
162-
expect(instancesResult.exitCode).to.equal(0);
163-
// Should show the instance we just created
164-
expect(instancesResult.stdout).to.include(`${testAdapter}.`);
190+
expect(result.exitCode).to.equal(0, `Failed to create instance: ${result.stderr}`);
191+
192+
// Verify the instance was created
193+
const instancesResult = await runCliCommand(['list', 'instances']);
194+
expect(instancesResult.exitCode).to.equal(0);
195+
expect(instancesResult.stdout).to.include(`${testAdapter}.`);
196+
197+
// Check that objects were created in the database
198+
const objectsDir = path.join(testDir, 'objects');
199+
const objectFiles = await fs.readdir(objectsDir);
200+
expect(objectFiles.length).to.be.greaterThan(0, 'No object files were created');
201+
202+
// Check for system objects that should be created
203+
const systemObjectFile = path.join(objectsDir, 'system.json');
204+
if (await fs.pathExists(systemObjectFile)) {
205+
const systemObjects = await fs.readJSON(systemObjectFile);
206+
207+
// Should have adapter object
208+
const adapterObjectKey = `system.adapter.${testAdapter}.0`;
209+
expect(systemObjects).to.have.property(adapterObjectKey);
210+
211+
const adapterObject = systemObjects[adapterObjectKey];
212+
expect(adapterObject).to.have.property('common');
213+
expect(adapterObject.common).to.have.property('name', testAdapter);
214+
expect(adapterObject.common).to.have.property('enabled', false);
165215
}
216+
217+
// Check states directory was created and used
218+
const statesDir = path.join(testDir, 'states');
219+
const stateFiles = await fs.readdir(statesDir);
220+
console.log(`Created ${stateFiles.length} state files during instance creation`);
166221
} else {
167222
console.log(`Skipping instance creation - ${testAdapter} adapter not available`);
168223
this.skip();
@@ -221,7 +276,7 @@ describe('Adapter Lifecycle Tests', function () {
221276
});
222277

223278
describe('Database State Validation', function () {
224-
it('should have clean database state after operations', async function () {
279+
it('should have proper database structure after operations', async function () {
225280
// Verify that database operations completed successfully
226281
const objectsDir = path.join(testDir, 'objects');
227282
const statesDir = path.join(testDir, 'states');
@@ -233,9 +288,47 @@ describe('Adapter Lifecycle Tests', function () {
233288
const objectFiles = await fs.readdir(objectsDir);
234289
const stateFiles = await fs.readdir(statesDir);
235290

236-
// Should have at least some files if operations occurred
237-
console.log(`Objects directory contains ${objectFiles.length} files`);
238-
console.log(`States directory contains ${stateFiles.length} files`);
291+
console.log(`Objects directory contains ${objectFiles.length} files: ${objectFiles.join(', ')}`);
292+
console.log(`States directory contains ${stateFiles.length} files: ${stateFiles.join(', ')}`);
293+
294+
// If we performed operations, should have at least some files
295+
if (objectFiles.length > 0) {
296+
// Check that key system files exist
297+
const expectedFiles = ['system.json'];
298+
for (const file of expectedFiles) {
299+
if (objectFiles.includes(file)) {
300+
const filePath = path.join(objectsDir, file);
301+
const fileContent = await fs.readJSON(filePath);
302+
expect(fileContent).to.be.an('object');
303+
console.log(`Validated structure of ${file}`);
304+
}
305+
}
306+
}
307+
});
308+
309+
it('should validate adapter metadata if admin was installed', async function () {
310+
// Check if admin adapter was installed and has proper metadata
311+
const objectsDir = path.join(testDir, 'objects');
312+
const systemFile = path.join(objectsDir, 'system.json');
313+
314+
if (await fs.pathExists(systemFile)) {
315+
const systemObjects = await fs.readJSON(systemFile);
316+
317+
// Look for admin adapter object
318+
const adminAdapterKey = 'system.adapter.admin.0';
319+
if (systemObjects[adminAdapterKey]) {
320+
const adminObject = systemObjects[adminAdapterKey];
321+
322+
expect(adminObject).to.have.property('type', 'instance');
323+
expect(adminObject).to.have.property('common');
324+
expect(adminObject.common).to.have.property('name', 'admin');
325+
expect(adminObject.common).to.have.property('enabled');
326+
327+
console.log('Successfully validated admin adapter metadata in database');
328+
} else {
329+
console.log('Admin adapter not found in database - may have been skipped due to network issues');
330+
}
331+
}
239332
});
240333
});
241334
});

packages/cli/test/testDataLifecycle/iobroker.json

Lines changed: 0 additions & 31 deletions
This file was deleted.

0 commit comments

Comments
 (0)