@onlineapps/conn-orch-validator 2.0.32 → 2.0.34

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.
@@ -1,250 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Example: How service-wrapper uses connector-testing
5
- * Shows the integration between service-wrapper and testing framework
6
- */
7
-
8
- const { ServiceReadinessValidator, TestOrchestrator } = require('../src');
9
-
10
- /**
11
- * Enhanced ServiceWrapper with integrated testing
12
- */
13
- class ServiceWrapperWithTesting {
14
- constructor(options) {
15
- this.service = options.service;
16
- this.serviceName = options.serviceName;
17
- this.openApiSpec = options.openApiSpec;
18
- this.config = options.config;
19
-
20
- // Testing configuration
21
- this.testingEnabled = options.testingEnabled !== false;
22
- this.testLevel = options.testLevel || 'component'; // unit, component, or integration
23
- this.validator = new ServiceReadinessValidator();
24
- }
25
-
26
- /**
27
- * Start service with validation
28
- */
29
- async start() {
30
- console.log(`Starting ${this.serviceName}...`);
31
-
32
- // Step 1: Pre-start validation
33
- if (this.testingEnabled) {
34
- const validation = await this.validateBeforeStart();
35
-
36
- if (!validation.ready) {
37
- throw new Error(`Service validation failed: ${validation.recommendation}`);
38
- }
39
-
40
- console.log(`Validation passed with score: ${validation.score}/100`);
41
- }
42
-
43
- // Step 2: Start the actual service
44
- await this.startService();
45
-
46
- // Step 3: Post-start verification
47
- if (this.testingEnabled) {
48
- await this.verifyAfterStart();
49
- }
50
-
51
- console.log(`${this.serviceName} started successfully`);
52
- }
53
-
54
- /**
55
- * Validate service before starting
56
- */
57
- async validateBeforeStart() {
58
- console.log('Running pre-start validation...');
59
-
60
- // Use TestOrchestrator for comprehensive testing
61
- const orchestrator = new TestOrchestrator({
62
- service: this.service,
63
- serviceName: this.serviceName,
64
- openApiSpec: this.openApiSpec
65
- });
66
-
67
- // Run tests based on configured level
68
- let testResults;
69
- switch (this.testLevel) {
70
- case 'unit':
71
- testResults = await orchestrator.runUnitTests();
72
- break;
73
- case 'component':
74
- testResults = await orchestrator.runComponentTests();
75
- break;
76
- case 'integration':
77
- testResults = await orchestrator.runIntegrationTests();
78
- break;
79
- default:
80
- testResults = await orchestrator.runComponentTests();
81
- }
82
-
83
- // Convert test results to readiness format
84
- return {
85
- ready: testResults.passed,
86
- score: testResults.coverage || 0,
87
- recommendation: testResults.passed
88
- ? 'Service passed validation'
89
- : 'Service failed validation tests',
90
- details: testResults
91
- };
92
- }
93
-
94
- /**
95
- * Start the actual service
96
- */
97
- async startService() {
98
- // This would contain the actual service startup logic
99
- // - Start Express server
100
- // - Connect to MQ
101
- // - Register with registry
102
- // - etc.
103
-
104
- return new Promise((resolve) => {
105
- const PORT = this.config.port || 3000;
106
- this.server = this.service.listen(PORT, () => {
107
- console.log(`Service listening on port ${PORT}`);
108
- resolve();
109
- });
110
- });
111
- }
112
-
113
- /**
114
- * Verify service after start
115
- */
116
- async verifyAfterStart() {
117
- console.log('Running post-start verification...');
118
-
119
- const serviceUrl = `http://localhost:${this.config.port || 3000}`;
120
-
121
- // Quick readiness check
122
- const readiness = await this.validator.validateReadiness({
123
- name: this.serviceName,
124
- url: serviceUrl,
125
- openApiSpec: this.openApiSpec,
126
- healthEndpoint: '/health'
127
- });
128
-
129
- if (!readiness.ready) {
130
- console.warn('Post-start verification found issues:', readiness.errors);
131
- }
132
-
133
- return readiness;
134
- }
135
-
136
- /**
137
- * Stop service
138
- */
139
- async stop() {
140
- if (this.server) {
141
- await new Promise((resolve) => {
142
- this.server.close(resolve);
143
- });
144
- }
145
- }
146
- }
147
-
148
- // === Example Usage ===
149
-
150
- async function demonstrateUsage() {
151
- const express = require('express');
152
-
153
- // Create a simple service
154
- const app = express();
155
- app.use(express.json());
156
-
157
- app.get('/health', (req, res) => {
158
- res.json({ status: 'healthy' });
159
- });
160
-
161
- app.post('/api/process', (req, res) => {
162
- res.json({ processed: true, data: req.body });
163
- });
164
-
165
- // OpenAPI spec
166
- const openApiSpec = {
167
- openapi: '3.0.0',
168
- info: { title: 'Demo Service', version: '1.0.0' },
169
- paths: {
170
- '/health': {
171
- get: {
172
- operationId: 'healthCheck',
173
- responses: {
174
- '200': {
175
- content: {
176
- 'application/json': {
177
- schema: {
178
- type: 'object',
179
- properties: {
180
- status: { type: 'string' }
181
- }
182
- }
183
- }
184
- }
185
- }
186
- }
187
- }
188
- },
189
- '/api/process': {
190
- post: {
191
- operationId: 'processData',
192
- requestBody: {
193
- content: {
194
- 'application/json': {
195
- schema: { type: 'object' }
196
- }
197
- }
198
- },
199
- responses: {
200
- '200': {
201
- content: {
202
- 'application/json': {
203
- schema: { type: 'object' }
204
- }
205
- }
206
- }
207
- }
208
- }
209
- }
210
- }
211
- };
212
-
213
- // Create wrapper with testing
214
- const wrapper = new ServiceWrapperWithTesting({
215
- service: app,
216
- serviceName: 'demo-service',
217
- openApiSpec,
218
- config: {
219
- port: 3333
220
- },
221
- testingEnabled: true,
222
- testLevel: 'unit' // Start with unit tests for speed
223
- });
224
-
225
- try {
226
- // Start service (will run validation first)
227
- await wrapper.start();
228
-
229
- console.log('\nService is running with validation!');
230
- console.log('Try: curl http://localhost:3333/health');
231
-
232
- // Keep running for demo
233
- await new Promise(resolve => setTimeout(resolve, 5000));
234
-
235
- // Stop service
236
- await wrapper.stop();
237
- console.log('\nService stopped');
238
-
239
- } catch (error) {
240
- console.error('Failed to start service:', error.message);
241
- process.exit(1);
242
- }
243
- }
244
-
245
- // Run demonstration
246
- if (require.main === module) {
247
- demonstrateUsage().catch(console.error);
248
- }
249
-
250
- module.exports = { ServiceWrapperWithTesting };
@@ -1,144 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Example: Three-tier testing strategy
5
- * Shows how to use connector-testing for comprehensive service validation
6
- */
7
-
8
- const { TestOrchestrator } = require('../src');
9
- const express = require('express');
10
-
11
- // Example service
12
- const app = express();
13
- app.use(express.json());
14
-
15
- app.get('/health', (req, res) => {
16
- res.json({ status: 'healthy', service: 'example-service' });
17
- });
18
-
19
- app.post('/process', (req, res) => {
20
- res.json({
21
- processed: true,
22
- input: req.body,
23
- timestamp: Date.now()
24
- });
25
- });
26
-
27
- app.get('/status', (req, res) => {
28
- res.json({
29
- running: true,
30
- uptime: process.uptime()
31
- });
32
- });
33
-
34
- // OpenAPI specification
35
- const openApiSpec = {
36
- openapi: '3.0.0',
37
- info: {
38
- title: 'Example Service',
39
- version: '1.0.0'
40
- },
41
- paths: {
42
- '/health': {
43
- get: {
44
- operationId: 'healthCheck',
45
- responses: {
46
- '200': {
47
- content: {
48
- 'application/json': {
49
- schema: {
50
- type: 'object',
51
- properties: {
52
- status: { type: 'string' },
53
- service: { type: 'string' }
54
- }
55
- }
56
- }
57
- }
58
- }
59
- }
60
- }
61
- },
62
- '/process': {
63
- post: {
64
- operationId: 'processData',
65
- requestBody: {
66
- content: {
67
- 'application/json': {
68
- schema: { type: 'object' }
69
- }
70
- }
71
- },
72
- responses: {
73
- '200': {
74
- content: {
75
- 'application/json': {
76
- schema: {
77
- type: 'object',
78
- properties: {
79
- processed: { type: 'boolean' },
80
- input: { type: 'object' },
81
- timestamp: { type: 'number' }
82
- }
83
- }
84
- }
85
- }
86
- }
87
- }
88
- }
89
- },
90
- '/status': {
91
- get: {
92
- operationId: 'getStatus',
93
- responses: {
94
- '200': {
95
- content: {
96
- 'application/json': {
97
- schema: {
98
- type: 'object',
99
- properties: {
100
- running: { type: 'boolean' },
101
- uptime: { type: 'number' }
102
- }
103
- }
104
- }
105
- }
106
- }
107
- }
108
- }
109
- }
110
- }
111
- };
112
-
113
- async function runExample() {
114
- console.log('=== Three-Tier Testing Example ===\n');
115
-
116
- // Create test orchestrator
117
- const orchestrator = new TestOrchestrator({
118
- service: app,
119
- serviceName: 'example-service',
120
- openApiSpec,
121
- logger: console
122
- });
123
-
124
- // Run all three levels of testing
125
- console.log('Starting comprehensive test suite...\n');
126
- const results = await orchestrator.runAllTests();
127
-
128
- // Generate and display report
129
- const report = orchestrator.generateReport(results);
130
- console.log('\n' + report);
131
-
132
- // Return exit code based on results
133
- process.exit(results.passed ? 0 : 1);
134
- }
135
-
136
- // Run if executed directly
137
- if (require.main === module) {
138
- runExample().catch(error => {
139
- console.error('Test failed:', error);
140
- process.exit(1);
141
- });
142
- }
143
-
144
- module.exports = { app, openApiSpec, runExample };
@@ -1,256 +0,0 @@
1
- 'use strict';
2
-
3
- const MockMQClient = require('./mocks/MockMQClient');
4
- const MockRegistry = require('./mocks/MockRegistry');
5
- const MockStorage = require('./mocks/MockStorage');
6
- const axios = require('axios');
7
-
8
- /**
9
- * ServiceTestHarness - Complete test environment for services
10
- */
11
- class ServiceTestHarness {
12
- constructor(options = {}) {
13
- this.service = options.service; // Express app
14
- this.serviceName = options.serviceName || 'test-service';
15
- this.openApiSpec = options.openApiSpec || {};
16
- this.mockInfrastructure = options.mockInfrastructure !== false;
17
-
18
- // Initialize mocks if requested
19
- if (this.mockInfrastructure) {
20
- this.mqClient = new MockMQClient();
21
- this.registry = new MockRegistry();
22
- this.storage = new MockStorage();
23
- }
24
-
25
- // Test state
26
- this.server = null;
27
- this.port = options.port || 0; // 0 = random port
28
- this.baseUrl = null;
29
- this.isRunning = false;
30
- }
31
-
32
- /**
33
- * Start test harness
34
- */
35
- async start() {
36
- if (this.isRunning) {
37
- return;
38
- }
39
-
40
- // Start Express server if provided
41
- if (this.service) {
42
- await this.startServer();
43
- }
44
-
45
- // Connect mocks
46
- if (this.mockInfrastructure) {
47
- await this.mqClient.connect();
48
- await this.registry.register({
49
- name: this.serviceName,
50
- url: this.baseUrl,
51
- openapi: this.openApiSpec
52
- });
53
- }
54
-
55
- this.isRunning = true;
56
- }
57
-
58
- /**
59
- * Stop test harness
60
- */
61
- async stop() {
62
- if (!this.isRunning) {
63
- return;
64
- }
65
-
66
- // Stop server
67
- if (this.server) {
68
- await new Promise(resolve => {
69
- this.server.close(resolve);
70
- });
71
- }
72
-
73
- // Disconnect mocks
74
- if (this.mockInfrastructure) {
75
- await this.mqClient.disconnect();
76
- await this.registry.unregister(this.serviceName);
77
- }
78
-
79
- this.isRunning = false;
80
- }
81
-
82
- /**
83
- * Start Express server
84
- * @private
85
- */
86
- async startServer() {
87
- return new Promise((resolve) => {
88
- this.server = this.service.listen(this.port, () => {
89
- const actualPort = this.server.address().port;
90
- this.baseUrl = `http://127.0.0.1:${actualPort}`;
91
- resolve();
92
- });
93
- });
94
- }
95
-
96
- /**
97
- * Call API endpoint
98
- */
99
- async callApi(method, path, data = null, headers = {}) {
100
- if (!this.baseUrl) {
101
- throw new Error('Service not started');
102
- }
103
-
104
- const config = {
105
- method,
106
- url: `${this.baseUrl}${path}`,
107
- headers,
108
- timeout: 5000
109
- };
110
-
111
- if (data) {
112
- if (method === 'GET') {
113
- config.params = data;
114
- } else {
115
- config.data = data;
116
- }
117
- }
118
-
119
- const response = await axios(config);
120
- return response.data;
121
- }
122
-
123
- /**
124
- * Simulate workflow execution
125
- */
126
- async simulateWorkflow(workflow) {
127
- const results = [];
128
-
129
- for (const step of workflow.steps) {
130
- if (step.type === 'task' && step.service === this.serviceName) {
131
- // Execute task step
132
- const result = await this.executeStep(step);
133
- results.push(result);
134
-
135
- // Simulate publishing result to queue
136
- if (this.mockInfrastructure) {
137
- await this.mqClient.publish('workflow.completed', {
138
- step: step.id,
139
- result
140
- });
141
- }
142
- }
143
- }
144
-
145
- return {
146
- workflow: workflow,
147
- results,
148
- completed: true
149
- };
150
- }
151
-
152
- /**
153
- * Execute a single workflow step
154
- * @private
155
- */
156
- async executeStep(step) {
157
- // Map step to API call based on operation
158
- const operation = step.operation || step.id;
159
- const endpoint = this.findEndpoint(operation);
160
-
161
- if (!endpoint) {
162
- throw new Error(`No endpoint found for operation: ${operation}`);
163
- }
164
-
165
- // Call the API
166
- const response = await this.callApi(
167
- endpoint.method,
168
- endpoint.path,
169
- step.input
170
- );
171
-
172
- return {
173
- stepId: step.id,
174
- operation,
175
- response
176
- };
177
- }
178
-
179
- /**
180
- * Find endpoint in OpenAPI spec
181
- * @private
182
- */
183
- findEndpoint(operationId) {
184
- if (!this.openApiSpec.paths) {
185
- return null;
186
- }
187
-
188
- for (const [path, pathItem] of Object.entries(this.openApiSpec.paths)) {
189
- for (const [method, operation] of Object.entries(pathItem)) {
190
- if (operation.operationId === operationId) {
191
- return { method: method.toUpperCase(), path };
192
- }
193
- }
194
- }
195
-
196
- return null;
197
- }
198
-
199
- /**
200
- * Get published messages from mock MQ
201
- */
202
- getPublishedMessages(queue = null) {
203
- if (!this.mockInfrastructure) {
204
- throw new Error('Mock infrastructure not enabled');
205
- }
206
- return this.mqClient.getPublishedMessages(queue);
207
- }
208
-
209
- /**
210
- * Get service registration from mock registry
211
- */
212
- getServiceRegistration() {
213
- if (!this.mockInfrastructure) {
214
- throw new Error('Mock infrastructure not enabled');
215
- }
216
- return this.registry.getService(this.serviceName);
217
- }
218
-
219
- /**
220
- * Get storage contents from mock storage
221
- */
222
- async getStorageObject(bucket, key) {
223
- if (!this.mockInfrastructure) {
224
- throw new Error('Mock infrastructure not enabled');
225
- }
226
- return await this.storage.get(bucket, key);
227
- }
228
-
229
- /**
230
- * Clear all test data
231
- */
232
- clear() {
233
- if (this.mockInfrastructure) {
234
- this.mqClient.clear();
235
- this.registry.clear();
236
- this.storage.clear();
237
- }
238
- }
239
-
240
- /**
241
- * Get test statistics
242
- */
243
- getStats() {
244
- if (!this.mockInfrastructure) {
245
- return { mocks: 'disabled' };
246
- }
247
-
248
- return {
249
- mq: this.mqClient.getStats(),
250
- registry: this.registry.getStats(),
251
- storage: this.storage.getStats()
252
- };
253
- }
254
- }
255
-
256
- module.exports = ServiceTestHarness;