@onlineapps/conn-orch-validator 2.0.13 → 2.0.15

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlineapps/conn-orch-validator",
3
- "version": "2.0.13",
3
+ "version": "2.0.15",
4
4
  "description": "Validation orchestrator for OA Drive microservices - coordinates validation across all layers (base, infra, orch, business)",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -22,6 +22,7 @@
22
22
  "license": "PROPRIETARY",
23
23
  "dependencies": {
24
24
  "@onlineapps/service-validator-core": "^1.0.4",
25
+ "@onlineapps/runtime-config": "1.0.2",
25
26
  "ajv": "^8.12.0",
26
27
  "ajv-formats": "^2.1.1",
27
28
  "amqplib": "^0.10.9",
@@ -369,8 +369,17 @@ class ServiceReadinessValidator {
369
369
  }
370
370
  break;
371
371
  case 'file':
372
- // For file types, generate a placeholder - actual file handling depends on implementation
373
- testData[fieldName] = fieldSpec.default || 'minio://test/validation/placeholder.txt';
372
+ // For file types, generate a VALID Content Descriptor object (type=file)
373
+ // This keeps endpoint checks predictable and avoids service-specific file upload flows.
374
+ testData[fieldName] = fieldSpec.default || {
375
+ _descriptor: true,
376
+ type: 'file',
377
+ storage_ref: 'minio://test/validation/placeholder.txt',
378
+ filename: 'placeholder.txt',
379
+ content_type: 'text/plain',
380
+ size: 1,
381
+ fingerprint: 'test-fingerprint'
382
+ };
374
383
  break;
375
384
  default:
376
385
  testData[fieldName] = null;
@@ -184,13 +184,21 @@ class ServiceValidator {
184
184
  case 'object':
185
185
  const obj = {};
186
186
  if (schema.properties) {
187
- Object.entries(schema.properties).forEach(([key, prop]) => {
187
+ const entries = Object.entries(schema.properties);
188
+ entries.forEach(([key, prop]) => {
188
189
  if (schema.required && schema.required.includes(key)) {
189
190
  obj[key] = this.generateTestValue(prop);
190
191
  } else if (Math.random() > 0.5) {
191
192
  obj[key] = this.generateTestValue(prop);
192
193
  }
193
194
  });
195
+
196
+ // If schema has properties but nothing was picked (e.g., no required fields and randomness skipped),
197
+ // pick the first property to keep requests deterministic and non-empty.
198
+ if (Object.keys(obj).length === 0 && entries.length > 0) {
199
+ const [firstKey, firstSchema] = entries[0];
200
+ obj[firstKey] = this.generateTestValue(firstSchema);
201
+ }
194
202
  }
195
203
  return obj;
196
204
 
@@ -4,6 +4,7 @@ const ServiceValidator = require('./ServiceValidator');
4
4
  const WorkflowTestRunner = require('./WorkflowTestRunner');
5
5
  const ServiceTestHarness = require('./ServiceTestHarness');
6
6
  const ServiceReadinessValidator = require('./ServiceReadinessValidator');
7
+ const runtimeCfg = require('./config');
7
8
 
8
9
  /**
9
10
  * TestOrchestrator - Three-tier testing strategy
@@ -17,6 +18,7 @@ class TestOrchestrator {
17
18
  this.serviceName = options.serviceName;
18
19
  this.openApiSpec = options.openApiSpec;
19
20
  this.logger = options.logger || console;
21
+ this.integrationConfig = options.integrationConfig || {};
20
22
 
21
23
  // Test configuration
22
24
  this.testLevels = {
@@ -628,11 +630,12 @@ class TestOrchestrator {
628
630
 
629
631
  getIntegrationTestConfig() {
630
632
  // Get configuration for integration tests
633
+ const resolved = runtimeCfg.resolve(this.integrationConfig);
631
634
  return {
632
- serviceUrl: process.env.TEST_SERVICE_URL || `http://localhost:${process.env.PORT || 3000}`,
633
- mqUrl: process.env.TEST_MQ_URL || process.env.RABBITMQ_URL,
634
- registryUrl: process.env.TEST_REGISTRY_URL || 'http://localhost:8080',
635
- storageUrl: process.env.TEST_STORAGE_URL || process.env.MINIO_URL,
635
+ serviceUrl: resolved.serviceUrl,
636
+ mqUrl: resolved.mqUrl,
637
+ registryUrl: resolved.registryUrl,
638
+ storageUrl: resolved.storageUrl,
636
639
  registry: null, // Would be real registry instance
637
640
  mqClient: null // Would be real MQ client instance
638
641
  };
@@ -117,7 +117,9 @@ class ValidationOrchestrator {
117
117
 
118
118
  return true;
119
119
  } catch (error) {
120
- console.error(`[ValidationOrchestrator] Proof validation error: ${error.message}`);
120
+ if (this.logger && typeof this.logger.error === 'function') {
121
+ this.logger.error(`[ValidationOrchestrator] Proof validation error: ${error.message}`);
122
+ }
121
123
  return false;
122
124
  }
123
125
  }
package/src/config.js ADDED
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Runtime configuration schema for @onlineapps/conn-orch-validator.
5
+ *
6
+ * Uses @onlineapps/runtime-config for unified priority:
7
+ * 1. Explicit config (passed to TestOrchestrator options)
8
+ * 2. Environment variable
9
+ * 3. Module-owned defaults (none for topology)
10
+ *
11
+ * IMPORTANT: Integration test topology is FAIL-FAST (no defaults).
12
+ */
13
+
14
+ const { createRuntimeConfig } = require('@onlineapps/runtime-config');
15
+ const DEFAULTS = require('./defaults');
16
+
17
+ const runtimeCfg = createRuntimeConfig({
18
+ defaults: DEFAULTS,
19
+ schema: {
20
+ serviceUrl: { env: 'TEST_SERVICE_URL', required: true },
21
+ mqUrl: { env: 'TEST_MQ_URL', required: true },
22
+ registryUrl: { env: 'TEST_REGISTRY_URL', required: true },
23
+ storageUrl: { env: 'TEST_STORAGE_URL', required: true },
24
+ }
25
+ });
26
+
27
+ module.exports = runtimeCfg;
28
+
29
+
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Module-owned defaults for @onlineapps/conn-orch-validator.
5
+ *
6
+ * NOTE: Integration test topology (URLs) is FAIL-FAST and has NO defaults.
7
+ */
8
+
9
+ module.exports = {};
10
+
11
+
@@ -53,6 +53,33 @@ class MockMQClient {
53
53
  this.queues[queue].push(messageWrapper);
54
54
  this.publishedMessages.push({ queue, message, options, timestamp: Date.now() });
55
55
 
56
+ // Auto-reply simulation for workflow task requests:
57
+ // When a task is published to service.*.request, publish a deterministic response
58
+ // to workflow.<workflow_id>.response so WorkflowTestRunner unit tests can run
59
+ // end-to-end with mocked MQ.
60
+ if (
61
+ typeof queue === 'string' &&
62
+ queue.startsWith('service.') &&
63
+ queue.endsWith('.request') &&
64
+ message &&
65
+ typeof message === 'object' &&
66
+ message.workflow_id &&
67
+ message.step_id
68
+ ) {
69
+ const responseQueue = `workflow.${message.workflow_id}.response`;
70
+ const response = {
71
+ step_id: message.step_id,
72
+ result: {
73
+ processed: true,
74
+ operation: message.operation,
75
+ input: message.input,
76
+ output: { mocked: true }
77
+ }
78
+ };
79
+ // Enqueue response (does not recurse into auto-reply because queue prefix differs)
80
+ await this.publish(responseQueue, response);
81
+ }
82
+
56
83
  // Trigger consumers if any
57
84
  if (this.consumers[queue]) {
58
85
  const consumer = this.consumers[queue];
@@ -114,9 +141,10 @@ class MockMQClient {
114
141
 
115
142
  if (requeue && message.fields) {
116
143
  const queue = message.fields.routingKey;
117
- if (this.queues[queue]) {
118
- this.queues[queue].push(message);
144
+ if (!this.queues[queue]) {
145
+ this.queues[queue] = [];
119
146
  }
147
+ this.queues[queue].push(message);
120
148
  }
121
149
 
122
150
  return Promise.resolve();