@onlineapps/conn-orch-validator 3.3.2 → 4.0.0
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 +358 -0
- package/README.md +46 -6
- package/TESTING_STRATEGY.md +1 -1
- package/docs/DESIGN.md +18 -11
- package/package.json +2 -3
- package/src/CookbookTestRunner.js +155 -26
- package/src/CookbookTestUtils.js +12 -4
- package/src/ServiceReadinessValidator.js +35 -18
- package/src/ValidationOrchestrator.js +223 -126
- package/src/cli/biz-ci-gate.js +356 -7
- package/src/helpers/README.md +3 -55
- package/src/helpers/createServiceReadinessTests.js +5 -1
- package/src/index.js +5 -2
- package/src/mocks/MockMQClient.js +100 -15
- package/src/utils/bizCiGateContract.js +110 -21
- package/src/utils/connectorContract.js +96 -0
- package/src/utils/cookbookFormat.js +95 -0
- package/src/utils/deployContract.js +488 -0
- package/src/utils/envContract.js +417 -0
- package/src/utils/installContract.js +142 -0
- package/src/utils/integrationRun.js +297 -0
- package/src/utils/libCompat.js +158 -0
- package/src/utils/preValidation.js +137 -0
- package/src/utils/setupDatabase.js +154 -0
- package/src/utils/stepFailure.js +73 -0
- package/src/utils/testNamespace.js +104 -0
- package/src/validators/ServiceStructureValidator.js +195 -48
- package/src/config.js +0 -32
- package/src/defaults.js +0 -11
- package/src/helpers/createPreValidationTests.js +0 -326
- package/test-mq-flow.js +0 -72
- package/test-orchestrator.js +0 -95
|
@@ -1,326 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Create Pre-Validation (Tier 1) Process Tests
|
|
3
|
-
*
|
|
4
|
-
* Generic test suite that validates Tier 1 pre-validation process.
|
|
5
|
-
* Works for ALL business services - no service-specific code needed.
|
|
6
|
-
*
|
|
7
|
-
* @module helpers/createPreValidationTests
|
|
8
|
-
*
|
|
9
|
-
* Purpose:
|
|
10
|
-
* - Validates cookbook tests execution
|
|
11
|
-
* - Validates ValidationProof generation
|
|
12
|
-
* - Validates proof integrity
|
|
13
|
-
* - Tests with MOCKED infrastructure (offline)
|
|
14
|
-
*
|
|
15
|
-
* Part of Two-Tier Validation System (Tier 1: Pre-Validation)
|
|
16
|
-
* See: /docs/architecture/validator.md
|
|
17
|
-
*
|
|
18
|
-
* Usage:
|
|
19
|
-
* const { createPreValidationTests } = require('@onlineapps/conn-orch-validator');
|
|
20
|
-
* createPreValidationTests(__dirname); // Pass tests/integration directory
|
|
21
|
-
*
|
|
22
|
-
* Related:
|
|
23
|
-
* - /docs/architecture/validator.md - Two-tier validation system
|
|
24
|
-
* - /docs/standards/TESTING.md - Testing standards
|
|
25
|
-
* - /tests/TESTING.md - SPOT principles
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
'use strict';
|
|
29
|
-
|
|
30
|
-
const path = require('path');
|
|
31
|
-
const fs = require('fs');
|
|
32
|
-
const { execSync } = require('child_process');
|
|
33
|
-
const { ValidationProofCodec } = require('@onlineapps/service-validator-core');
|
|
34
|
-
const { ServiceStructureValidator } = require('../validators/ServiceStructureValidator');
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Create pre-validation (Tier 1) test suite
|
|
38
|
-
*
|
|
39
|
-
* @param {string} testsDir - Path to tests/integration directory (use __dirname)
|
|
40
|
-
* @param {Object} [options] - Optional configuration
|
|
41
|
-
* @param {number} [options.timeout=60000] - Test timeout in ms
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* // In services/my-service/tests/integration/pre-validation-process.test.js
|
|
45
|
-
* const { createPreValidationTests } = require('@onlineapps/conn-orch-validator');
|
|
46
|
-
*
|
|
47
|
-
* createPreValidationTests(__dirname);
|
|
48
|
-
*/
|
|
49
|
-
function createPreValidationTests(testsDir, options = {}) {
|
|
50
|
-
// Calculate service root (2 levels up from tests/integration/)
|
|
51
|
-
const serviceRoot = path.resolve(testsDir, '../..');
|
|
52
|
-
|
|
53
|
-
const {
|
|
54
|
-
timeout = 60000
|
|
55
|
-
} = options;
|
|
56
|
-
|
|
57
|
-
// Validate service structure FIRST
|
|
58
|
-
console.log('\n🔍 Validating service structure for pre-validation...\n');
|
|
59
|
-
const structureValidator = new ServiceStructureValidator(serviceRoot);
|
|
60
|
-
const structureResult = structureValidator.validate();
|
|
61
|
-
|
|
62
|
-
// Log validation result
|
|
63
|
-
console.log(ServiceStructureValidator.formatResult(structureResult));
|
|
64
|
-
|
|
65
|
-
// FAIL FAST if structure is invalid
|
|
66
|
-
if (!structureResult.valid) {
|
|
67
|
-
throw new Error(
|
|
68
|
-
`Service structure validation failed. Fix errors above before running pre-validation tests.`
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Load configuration — prefer config/service/, fall back to conn-config/
|
|
73
|
-
const resolveConfig = (filename) => {
|
|
74
|
-
const newPath = path.join(serviceRoot, 'config', 'service', filename);
|
|
75
|
-
const legacyPath = path.join(serviceRoot, 'conn-config', filename);
|
|
76
|
-
return fs.existsSync(newPath) ? newPath : legacyPath;
|
|
77
|
-
};
|
|
78
|
-
const configPath = resolveConfig('config.json');
|
|
79
|
-
const operationsPath = resolveConfig('operations.json');
|
|
80
|
-
const proofPath = path.join(serviceRoot, '.validation-proof.json');
|
|
81
|
-
|
|
82
|
-
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
83
|
-
const operations = JSON.parse(fs.readFileSync(operationsPath, 'utf-8'));
|
|
84
|
-
|
|
85
|
-
const serviceName = config.service.name;
|
|
86
|
-
|
|
87
|
-
// Create test suite
|
|
88
|
-
describe(`${serviceName} Pre-Validation (Tier 1) Process @integration`, () => {
|
|
89
|
-
afterEach(() => {
|
|
90
|
-
// Cleanup validation proof after each test
|
|
91
|
-
if (fs.existsSync(proofPath)) {
|
|
92
|
-
fs.unlinkSync(proofPath);
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
describe('1. Pre-requisites Check', () => {
|
|
97
|
-
test('service has tests/cookbooks directory', () => {
|
|
98
|
-
const cookbooksDir = path.join(serviceRoot, 'tests/cookbooks');
|
|
99
|
-
expect(fs.existsSync(cookbooksDir)).toBe(true);
|
|
100
|
-
|
|
101
|
-
const cookbookFiles = fs.readdirSync(cookbooksDir).filter(f => f.endsWith('.json'));
|
|
102
|
-
expect(cookbookFiles.length).toBeGreaterThan(0);
|
|
103
|
-
|
|
104
|
-
console.log(`\n✓ Found ${cookbookFiles.length} cookbook test(s)\n`);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
test('service has operations.json', () => {
|
|
108
|
-
expect(fs.existsSync(operationsPath)).toBe(true);
|
|
109
|
-
|
|
110
|
-
expect(operations.operations).toBeDefined();
|
|
111
|
-
expect(Object.keys(operations.operations).length).toBeGreaterThan(0);
|
|
112
|
-
|
|
113
|
-
console.log(`\n✓ Found ${Object.keys(operations.operations).length} operation(s)\n`);
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
test('service has pre-validation script', () => {
|
|
117
|
-
const packageJson = JSON.parse(
|
|
118
|
-
fs.readFileSync(path.join(serviceRoot, 'package.json'), 'utf-8')
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
const hasScript = packageJson.scripts['test:cookbooks'] ||
|
|
122
|
-
fs.existsSync(path.join(serviceRoot, 'scripts/run-pre-validation.js'));
|
|
123
|
-
|
|
124
|
-
expect(hasScript).toBeTruthy();
|
|
125
|
-
|
|
126
|
-
console.log('\n✓ Pre-validation script configured\n');
|
|
127
|
-
});
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
describe('2. Cookbook Test Execution', () => {
|
|
131
|
-
test('runs cookbook tests successfully', () => {
|
|
132
|
-
console.log('\n🧪 Running cookbook tests...\n');
|
|
133
|
-
|
|
134
|
-
try {
|
|
135
|
-
const output = execSync('npm run test:cookbooks', {
|
|
136
|
-
cwd: serviceRoot,
|
|
137
|
-
encoding: 'utf-8',
|
|
138
|
-
stdio: 'pipe'
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
console.log(output);
|
|
142
|
-
|
|
143
|
-
expect(output).toContain('Pre-Validation Started');
|
|
144
|
-
expect(output).toContain('Passed:');
|
|
145
|
-
expect(output).not.toContain('Failed: 1');
|
|
146
|
-
|
|
147
|
-
console.log('\n✅ Cookbook tests PASSED\n');
|
|
148
|
-
} catch (error) {
|
|
149
|
-
console.error('\n❌ Cookbook tests FAILED:\n');
|
|
150
|
-
console.error(error.stdout || error.message);
|
|
151
|
-
throw error;
|
|
152
|
-
}
|
|
153
|
-
}, timeout);
|
|
154
|
-
|
|
155
|
-
test('mocks infrastructure during tests', () => {
|
|
156
|
-
const runPreValidationPath = path.join(serviceRoot, 'scripts/run-pre-validation.js');
|
|
157
|
-
|
|
158
|
-
if (fs.existsSync(runPreValidationPath)) {
|
|
159
|
-
const scriptContent = fs.readFileSync(runPreValidationPath, 'utf-8');
|
|
160
|
-
expect(scriptContent).toContain('mockInfrastructure: true');
|
|
161
|
-
|
|
162
|
-
console.log('\n✓ Infrastructure mocking confirmed\n');
|
|
163
|
-
} else {
|
|
164
|
-
console.log('\n⚠ No run-pre-validation.js script found (using npm script)\n');
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
describe('3. ValidationProof Generation', () => {
|
|
170
|
-
beforeEach(() => {
|
|
171
|
-
// Run pre-validation to generate proof
|
|
172
|
-
console.log('\n🔐 Generating validation proof...\n');
|
|
173
|
-
execSync('npm run test:cookbooks', {
|
|
174
|
-
cwd: serviceRoot,
|
|
175
|
-
stdio: 'pipe'
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
test('creates .validation-proof.json file', () => {
|
|
180
|
-
expect(fs.existsSync(proofPath)).toBe(true);
|
|
181
|
-
console.log('\n✓ Validation proof file created\n');
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
test('proof has correct structure', () => {
|
|
185
|
-
const proof = JSON.parse(fs.readFileSync(proofPath, 'utf-8'));
|
|
186
|
-
|
|
187
|
-
// Required fields
|
|
188
|
-
expect(proof.validationProof).toBeDefined();
|
|
189
|
-
expect(proof.validationData).toBeDefined();
|
|
190
|
-
|
|
191
|
-
// ValidationData structure
|
|
192
|
-
const { validationData } = proof;
|
|
193
|
-
expect(validationData.serviceName).toBe(serviceName);
|
|
194
|
-
expect(validationData.version).toBeDefined();
|
|
195
|
-
expect(validationData.validator).toBe('@onlineapps/conn-orch-validator');
|
|
196
|
-
expect(validationData.validatorVersion).toBeDefined();
|
|
197
|
-
expect(validationData.validatedAt).toBeDefined();
|
|
198
|
-
expect(validationData.durationMs).toBeGreaterThan(0);
|
|
199
|
-
expect(validationData.testsRun).toBeGreaterThan(0);
|
|
200
|
-
expect(validationData.testsPassed).toBe(validationData.testsRun);
|
|
201
|
-
expect(validationData.testsFailed).toBe(0);
|
|
202
|
-
|
|
203
|
-
console.log('\n📋 Validation Proof Details:');
|
|
204
|
-
console.log(` Service: ${validationData.serviceName} v${validationData.version}`);
|
|
205
|
-
console.log(` Validator: ${validationData.validator} v${validationData.validatorVersion}`);
|
|
206
|
-
console.log(` Tests: ${validationData.testsPassed}/${validationData.testsRun} passed`);
|
|
207
|
-
console.log(` Duration: ${validationData.durationMs}ms`);
|
|
208
|
-
console.log(` Validated: ${validationData.validatedAt}`);
|
|
209
|
-
console.log('');
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
test('proof hash is valid SHA256', () => {
|
|
213
|
-
const proof = JSON.parse(fs.readFileSync(proofPath, 'utf-8'));
|
|
214
|
-
|
|
215
|
-
// SHA256 = 64 hex characters
|
|
216
|
-
expect(proof.validationProof).toMatch(/^[a-f0-9]{64}$/);
|
|
217
|
-
|
|
218
|
-
console.log(`\n✓ Valid SHA256 hash: ${proof.validationProof.substring(0, 16)}...\n`);
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
test('all tests passed', () => {
|
|
222
|
-
const proof = JSON.parse(fs.readFileSync(proofPath, 'utf-8'));
|
|
223
|
-
|
|
224
|
-
expect(proof.validationData.testsFailed).toBe(0);
|
|
225
|
-
expect(proof.validationData.testsPassed).toBeGreaterThan(0);
|
|
226
|
-
expect(proof.validationData.testsPassed).toBe(proof.validationData.testsRun);
|
|
227
|
-
|
|
228
|
-
console.log(`\n✅ All ${proof.validationData.testsPassed} tests PASSED\n`);
|
|
229
|
-
});
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
describe('4. Proof Integrity Verification', () => {
|
|
233
|
-
beforeEach(() => {
|
|
234
|
-
// Generate proof
|
|
235
|
-
execSync('npm run test:cookbooks', {
|
|
236
|
-
cwd: serviceRoot,
|
|
237
|
-
stdio: 'pipe'
|
|
238
|
-
});
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
test('ValidationProofCodec can decode proof', () => {
|
|
242
|
-
const proof = JSON.parse(fs.readFileSync(proofPath, 'utf-8'));
|
|
243
|
-
|
|
244
|
-
const result = ValidationProofCodec.decode(proof);
|
|
245
|
-
|
|
246
|
-
expect(result.valid).toBe(true);
|
|
247
|
-
expect(result.reason).toBe('VALID');
|
|
248
|
-
expect(result.details.serviceName).toBe(serviceName);
|
|
249
|
-
|
|
250
|
-
console.log('\n✓ Proof successfully decoded and verified\n');
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
test('proof hash matches data', () => {
|
|
254
|
-
const proof = JSON.parse(fs.readFileSync(proofPath, 'utf-8'));
|
|
255
|
-
|
|
256
|
-
// Re-encode to verify hash
|
|
257
|
-
const reEncoded = ValidationProofCodec.encode(proof.validationData);
|
|
258
|
-
|
|
259
|
-
expect(reEncoded.validationProof).toBe(proof.validationProof);
|
|
260
|
-
|
|
261
|
-
console.log('\n✓ Proof hash integrity verified\n');
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
test('proof age is recent (< 7 days)', () => {
|
|
265
|
-
const proof = JSON.parse(fs.readFileSync(proofPath, 'utf-8'));
|
|
266
|
-
|
|
267
|
-
const validatedAt = new Date(proof.validationData.validatedAt);
|
|
268
|
-
const now = new Date();
|
|
269
|
-
const ageMs = now - validatedAt;
|
|
270
|
-
const ageDays = ageMs / (24 * 60 * 60 * 1000);
|
|
271
|
-
|
|
272
|
-
expect(ageDays).toBeLessThan(7);
|
|
273
|
-
|
|
274
|
-
console.log(`\n✓ Proof age: ${Math.round(ageMs / 1000)}s (recent)\n`);
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
test('tampered proof fails verification', () => {
|
|
278
|
-
const proof = JSON.parse(fs.readFileSync(proofPath, 'utf-8'));
|
|
279
|
-
|
|
280
|
-
// Tamper with data
|
|
281
|
-
proof.validationData.testsPassed = 999;
|
|
282
|
-
|
|
283
|
-
const result = ValidationProofCodec.decode(proof);
|
|
284
|
-
|
|
285
|
-
expect(result.valid).toBe(false);
|
|
286
|
-
expect(result.reason).toBe('HASH_MISMATCH');
|
|
287
|
-
|
|
288
|
-
console.log('\n✓ Tamper detection working correctly\n');
|
|
289
|
-
});
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
describe('5. Dependencies Tracking', () => {
|
|
293
|
-
beforeEach(() => {
|
|
294
|
-
execSync('npm run test:cookbooks', {
|
|
295
|
-
cwd: serviceRoot,
|
|
296
|
-
stdio: 'pipe'
|
|
297
|
-
});
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
test('proof includes service dependencies', () => {
|
|
301
|
-
const proof = JSON.parse(fs.readFileSync(proofPath, 'utf-8'));
|
|
302
|
-
|
|
303
|
-
expect(proof.validationData.dependencies).toBeDefined();
|
|
304
|
-
expect(typeof proof.validationData.dependencies).toBe('object');
|
|
305
|
-
|
|
306
|
-
// Should include key connectors
|
|
307
|
-
const deps = proof.validationData.dependencies;
|
|
308
|
-
const hasConnector = deps['@onlineapps/service-wrapper'] ||
|
|
309
|
-
deps['@onlineapps/conn-orch-registry'] ||
|
|
310
|
-
deps['@onlineapps/conn-orch-validator'];
|
|
311
|
-
|
|
312
|
-
expect(hasConnector).toBeDefined();
|
|
313
|
-
|
|
314
|
-
console.log('\n📦 Tracked Dependencies:');
|
|
315
|
-
for (const [name, version] of Object.entries(deps)) {
|
|
316
|
-
if (name.startsWith('@onlineapps/')) {
|
|
317
|
-
console.log(` ${name}: ${version}`);
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
console.log('');
|
|
321
|
-
});
|
|
322
|
-
});
|
|
323
|
-
});
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
module.exports = { createPreValidationTests };
|
package/test-mq-flow.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Simple test script to verify MQ message flow
|
|
6
|
-
* Usage: node test-mq-flow.js
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const amqp = require('amqplib');
|
|
10
|
-
|
|
11
|
-
async function sendTestMessage() {
|
|
12
|
-
const rabbitUrl = 'amqp://guest:guest@localhost:33023';
|
|
13
|
-
const queueName = 'hello-service.workflow';
|
|
14
|
-
|
|
15
|
-
try {
|
|
16
|
-
// Connect to RabbitMQ
|
|
17
|
-
const connection = await amqp.connect(rabbitUrl);
|
|
18
|
-
const channel = await connection.createChannel();
|
|
19
|
-
|
|
20
|
-
// Ensure queue exists
|
|
21
|
-
await channel.assertQueue(queueName, { durable: true });
|
|
22
|
-
|
|
23
|
-
// Create test message with cookbook
|
|
24
|
-
const testMessage = {
|
|
25
|
-
workflow_id: `test-${Date.now()}`,
|
|
26
|
-
cookbook: {
|
|
27
|
-
name: 'test-workflow',
|
|
28
|
-
version: '1.0.0',
|
|
29
|
-
steps: [
|
|
30
|
-
{
|
|
31
|
-
id: 'goodDay', // ID se použije jako operation name
|
|
32
|
-
type: 'task',
|
|
33
|
-
service: 'hello-service',
|
|
34
|
-
input: {
|
|
35
|
-
name: 'E2E Test'
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
]
|
|
39
|
-
},
|
|
40
|
-
current_step: 'step1',
|
|
41
|
-
step_index: 0,
|
|
42
|
-
context: {}
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
console.log('Sending test message:', JSON.stringify(testMessage, null, 2));
|
|
46
|
-
|
|
47
|
-
// Send message
|
|
48
|
-
channel.sendToQueue(
|
|
49
|
-
queueName,
|
|
50
|
-
Buffer.from(JSON.stringify(testMessage)),
|
|
51
|
-
{ persistent: true }
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
console.log(`Message sent to queue: ${queueName}`);
|
|
55
|
-
|
|
56
|
-
// Wait a bit to ensure message is sent
|
|
57
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
58
|
-
|
|
59
|
-
// Clean up
|
|
60
|
-
await channel.close();
|
|
61
|
-
await connection.close();
|
|
62
|
-
|
|
63
|
-
console.log('Test completed successfully');
|
|
64
|
-
|
|
65
|
-
} catch (error) {
|
|
66
|
-
console.error('Test failed:', error.message);
|
|
67
|
-
process.exit(1);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Run the test
|
|
72
|
-
sendTestMessage();
|
package/test-orchestrator.js
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Quick test of ValidationOrchestrator
|
|
6
|
-
*
|
|
7
|
-
* Usage: node test-orchestrator.js <serviceRoot>
|
|
8
|
-
* Example: node test-orchestrator.js ../../../services/hello-service
|
|
9
|
-
*
|
|
10
|
-
* Loads service configuration from conn-config/config.json
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
const fs = require('fs');
|
|
14
|
-
const path = require('path');
|
|
15
|
-
const ValidationOrchestrator = require('./src/ValidationOrchestrator');
|
|
16
|
-
|
|
17
|
-
async function test() {
|
|
18
|
-
// Get service root from CLI or default to hello-service
|
|
19
|
-
const serviceRoot = process.argv[2] || path.resolve(__dirname, '../../../services/hello-service');
|
|
20
|
-
|
|
21
|
-
if (!fs.existsSync(serviceRoot)) {
|
|
22
|
-
console.error(`❌ Service root not found: ${serviceRoot}`);
|
|
23
|
-
console.error('Usage: node test-orchestrator.js <serviceRoot>');
|
|
24
|
-
process.exit(1);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Load service configuration
|
|
28
|
-
const configPath = path.join(serviceRoot, 'conn-config', 'config.json');
|
|
29
|
-
if (!fs.existsSync(configPath)) {
|
|
30
|
-
console.error(`❌ Config not found: ${configPath}`);
|
|
31
|
-
console.error('Service must have conn-config/config.json');
|
|
32
|
-
process.exit(1);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
36
|
-
const serviceName = config.service?.name;
|
|
37
|
-
const serviceVersion = config.service?.version;
|
|
38
|
-
|
|
39
|
-
if (!serviceName || !serviceVersion) {
|
|
40
|
-
console.error('❌ Config must contain service.name and service.version');
|
|
41
|
-
process.exit(1);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
console.log(`🧪 Testing ValidationOrchestrator`);
|
|
45
|
-
console.log(` Service: ${serviceName} v${serviceVersion}`);
|
|
46
|
-
console.log(` Root: ${serviceRoot}\n`);
|
|
47
|
-
|
|
48
|
-
const orchestrator = new ValidationOrchestrator({
|
|
49
|
-
serviceRoot,
|
|
50
|
-
serviceName,
|
|
51
|
-
serviceVersion,
|
|
52
|
-
logger: console
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
try {
|
|
56
|
-
const result = await orchestrator.validate();
|
|
57
|
-
|
|
58
|
-
console.log('\n📊 Validation Results:');
|
|
59
|
-
console.log('Success:', result.success);
|
|
60
|
-
console.log('Duration:', result.durationMs, 'ms');
|
|
61
|
-
|
|
62
|
-
if (result.skipped) {
|
|
63
|
-
console.log('✓ Used existing proof (validation skipped)');
|
|
64
|
-
console.log('Fingerprint:', result.proof?.fingerprint);
|
|
65
|
-
} else {
|
|
66
|
-
console.log('Tests run:', result.totalTests);
|
|
67
|
-
console.log('Tests passed:', result.passedTests);
|
|
68
|
-
console.log('Tests failed:', result.failedTests);
|
|
69
|
-
|
|
70
|
-
if (result.errors && result.errors.length > 0) {
|
|
71
|
-
console.log('\n❌ Errors:');
|
|
72
|
-
result.errors.forEach(err => console.log(' -', err));
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (result.warnings && result.warnings.length > 0) {
|
|
76
|
-
console.log('\n⚠️ Warnings:');
|
|
77
|
-
result.warnings.forEach(warn => console.log(' -', warn));
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (result.proof) {
|
|
81
|
-
console.log('\n✅ Proof generated:');
|
|
82
|
-
console.log(' Fingerprint:', result.fingerprint);
|
|
83
|
-
console.log(' Location: conn-runtime/validation-proof.json');
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
process.exit(result.success ? 0 : 1);
|
|
88
|
-
} catch (error) {
|
|
89
|
-
console.error('\n❌ Test failed:', error.message);
|
|
90
|
-
console.error(error.stack);
|
|
91
|
-
process.exit(1);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
test();
|