@aifabrix/builder 2.32.3 → 2.33.1
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/.cursor/rules/project-rules.mdc +8 -0
- package/README.md +36 -8
- package/bin/aifabrix.js +6 -8
- package/integration/hubspot/README.md +12 -11
- package/integration/hubspot/companies.json +2048 -0
- package/integration/hubspot/create-hubspot.js +665 -0
- package/integration/hubspot/{hubspot-deploy-company.json → hubspot-datasource-company.json} +1 -1
- package/integration/hubspot/{hubspot-deploy-contact.json → hubspot-datasource-contact.json} +1 -1
- package/integration/hubspot/{hubspot-deploy-deal.json → hubspot-datasource-deal.json} +1 -1
- package/integration/hubspot/hubspot-deploy.json +832 -81
- package/integration/hubspot/hubspot-system.json +99 -0
- package/integration/hubspot/test-artifacts/wizard-hubspot-credential-real.yaml +20 -0
- package/integration/hubspot/test-artifacts/wizard-hubspot-env-vars.yaml +9 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-add-datasource.yaml +5 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-app-name.yaml +5 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-credential-create.yaml +7 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-credential-select.yaml +7 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-known-platform.yaml +4 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-missing-app.yaml +4 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-missing-source.yaml +2 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-mode.yaml +5 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-openapi-file.yaml +5 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-openapi-url.yaml +4 -0
- package/integration/hubspot/test-artifacts/wizard-invalid-source.yaml +4 -0
- package/integration/hubspot/test-artifacts/wizard-valid-for-dimension-array-test.yaml +5 -0
- package/integration/hubspot/test-artifacts/wizard-valid-for-dimension-key-test.yaml +5 -0
- package/integration/hubspot/test-artifacts/wizard-valid-for-dimension-path-test.yaml +5 -0
- package/integration/hubspot/test-artifacts/wizard-valid-for-dimension-test.yaml +5 -0
- package/integration/hubspot/test-artifacts/wizard-valid-for-rbac-test.yaml +5 -0
- package/integration/hubspot/test-artifacts/wizard-valid-for-rbac-yaml-test.yaml +5 -0
- package/integration/hubspot/test-dataplane-down-helpers.js +246 -0
- package/integration/hubspot/test-dataplane-down-tests.js +419 -0
- package/integration/hubspot/test-dataplane-down.js +157 -0
- package/integration/hubspot/test.js +1517 -0
- package/integration/hubspot/variables.yaml +4 -4
- package/integration/hubspot/wizard-hubspot-e2e.yaml +16 -0
- package/integration/hubspot/wizard-hubspot-platform.yaml +8 -0
- package/lib/api/applications.api.js +1 -0
- package/lib/api/index.js +6 -2
- package/lib/api/types/wizard.types.js +176 -38
- package/lib/api/wizard.api.js +161 -23
- package/lib/app/deploy.js +116 -54
- package/lib/app/display.js +6 -5
- package/lib/app/dockerfile.js +2 -1
- package/lib/app/list.js +17 -10
- package/lib/app/readme.js +41 -112
- package/lib/app/register.js +44 -9
- package/lib/app/rotate-secret.js +48 -31
- package/lib/cli.js +219 -70
- package/lib/commands/app.js +4 -9
- package/lib/commands/auth-config.js +125 -0
- package/lib/commands/auth-status.js +7 -8
- package/lib/commands/datasource.js +3 -6
- package/lib/commands/login-credentials.js +4 -4
- package/lib/commands/login-device.js +26 -17
- package/lib/commands/login.js +12 -10
- package/lib/commands/wizard-config-normalizer.js +92 -0
- package/lib/commands/wizard-core.js +515 -0
- package/lib/commands/wizard-dataplane.js +122 -0
- package/lib/commands/wizard-headless.js +115 -0
- package/lib/commands/wizard.js +110 -332
- package/lib/core/config.js +46 -0
- package/lib/core/secrets.js +3 -22
- package/lib/core/templates-env.js +1 -1
- package/lib/datasource/deploy.js +59 -23
- package/lib/datasource/list.js +108 -19
- package/lib/deployment/deployer.js +25 -0
- package/lib/deployment/environment.js +10 -13
- package/lib/external-system/delete.js +151 -0
- package/lib/external-system/deploy.js +53 -378
- package/lib/external-system/download-helpers.js +45 -65
- package/lib/external-system/download.js +33 -13
- package/lib/external-system/generator.js +11 -7
- package/lib/external-system/test-auth.js +4 -3
- package/lib/generator/builders.js +3 -1
- package/lib/generator/external-controller-manifest.js +157 -0
- package/lib/generator/external-schema-utils.js +236 -0
- package/lib/generator/external.js +55 -3
- package/lib/generator/index.js +22 -10
- package/lib/generator/wizard-prompts.js +33 -10
- package/lib/generator/wizard.js +69 -86
- package/lib/infrastructure/compose.js +100 -0
- package/lib/infrastructure/helpers.js +139 -0
- package/lib/infrastructure/index.js +52 -311
- package/lib/infrastructure/services.js +168 -0
- package/lib/schema/application-schema.json +23 -4
- package/lib/schema/external-datasource.schema.json +2 -2
- package/lib/schema/wizard-config.schema.json +234 -0
- package/lib/utils/api.js +102 -52
- package/lib/utils/app-existence.js +42 -0
- package/lib/utils/app-register-config.js +7 -2
- package/lib/utils/auth-config-validator.js +92 -0
- package/lib/utils/command-header.js +43 -0
- package/lib/utils/compose-generator.js +113 -70
- package/lib/utils/controller-url.js +65 -17
- package/lib/utils/dataplane-health.js +115 -0
- package/lib/utils/dataplane-resolver.js +29 -0
- package/lib/utils/dev-config.js +6 -2
- package/lib/utils/env-copy.js +2 -1
- package/lib/utils/env-ports.js +2 -1
- package/lib/utils/env-template.js +1 -1
- package/lib/utils/error-formatter.js +49 -0
- package/lib/utils/error-formatters/network-errors.js +13 -3
- package/lib/utils/external-readme.js +125 -0
- package/lib/utils/help-builder.js +190 -0
- package/lib/utils/infra-status.js +13 -3
- package/lib/utils/paths.js +17 -2
- package/lib/utils/port-resolver.js +111 -0
- package/lib/utils/secrets-helpers.js +3 -15
- package/lib/utils/secrets-utils.js +2 -2
- package/lib/utils/token-manager.js +9 -4
- package/lib/utils/variable-transformer.js +7 -2
- package/lib/validation/external-manifest-validator.js +202 -0
- package/lib/validation/validate-display.js +406 -0
- package/lib/validation/validate.js +159 -123
- package/lib/validation/validator.js +36 -3
- package/lib/validation/wizard-config-validator.js +267 -0
- package/package.json +4 -2
- package/templates/applications/README.md.hbs +18 -16
- package/templates/applications/miso-controller/env.template +1 -1
- package/templates/applications/miso-controller/rbac.yaml +7 -7
- package/templates/external-system/README.md.hbs +99 -0
- package/templates/github/ci.yaml.hbs +44 -1
- package/templates/github/release.yaml.hbs +44 -0
- package/templates/infra/compose.yaml.hbs +35 -0
- package/templates/python/docker-compose.hbs +26 -0
- package/templates/typescript/docker-compose.hbs +26 -0
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Functions for Dataplane Down Tests
|
|
3
|
+
*
|
|
4
|
+
* Individual test functions for dataplane down test suite.
|
|
5
|
+
*
|
|
6
|
+
* @fileoverview Test functions for dataplane down tests
|
|
7
|
+
* @author AI Fabrix Team
|
|
8
|
+
* @version 2.0.0
|
|
9
|
+
*/
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const fs = require('fs').promises;
|
|
14
|
+
const {
|
|
15
|
+
logInfo,
|
|
16
|
+
runCommand,
|
|
17
|
+
validateError,
|
|
18
|
+
isTimeoutResult,
|
|
19
|
+
validateDownloadDeleteResult,
|
|
20
|
+
validateDeleteResult,
|
|
21
|
+
validateWizardResult
|
|
22
|
+
} = require('./test-dataplane-down-helpers');
|
|
23
|
+
|
|
24
|
+
const INVALID_DATAPLANE_URL = 'http://localhost:9999';
|
|
25
|
+
const CONTROLLER_URL = process.env.CONTROLLER_URL || 'http://localhost:3110';
|
|
26
|
+
const ENVIRONMENT = process.env.ENVIRONMENT || 'miso';
|
|
27
|
+
const TEST_APP_NAME = 'test-dataplane-down';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Creates wizard config file
|
|
31
|
+
* @async
|
|
32
|
+
* @function createWizardConfig
|
|
33
|
+
* @param {string} configPath - Path to config file
|
|
34
|
+
* @returns {Promise<void>} Resolves when config file is created
|
|
35
|
+
*/
|
|
36
|
+
async function createWizardConfig(configPath) {
|
|
37
|
+
const configContent = `appName: ${TEST_APP_NAME}
|
|
38
|
+
mode: create-system
|
|
39
|
+
source:
|
|
40
|
+
type: known-platform
|
|
41
|
+
platform: hubspot
|
|
42
|
+
deployment:
|
|
43
|
+
controller: ${CONTROLLER_URL}
|
|
44
|
+
environment: ${ENVIRONMENT}
|
|
45
|
+
dataplane: ${INVALID_DATAPLANE_URL}
|
|
46
|
+
`;
|
|
47
|
+
await fs.writeFile(configPath, configContent, 'utf8');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Test wizard command with invalid dataplane
|
|
52
|
+
* @async
|
|
53
|
+
* @function testWizard
|
|
54
|
+
* @returns {Promise<Object>} Test result
|
|
55
|
+
*/
|
|
56
|
+
async function testWizard() {
|
|
57
|
+
logInfo('\n📋 Testing: wizard command');
|
|
58
|
+
|
|
59
|
+
const configPath = path.join(process.cwd(), 'integration', 'test-wizard-config.yaml');
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
await createWizardConfig(configPath);
|
|
63
|
+
|
|
64
|
+
const args = [
|
|
65
|
+
'bin/aifabrix.js',
|
|
66
|
+
'wizard',
|
|
67
|
+
'--config',
|
|
68
|
+
configPath,
|
|
69
|
+
'--controller',
|
|
70
|
+
CONTROLLER_URL,
|
|
71
|
+
'--environment',
|
|
72
|
+
ENVIRONMENT,
|
|
73
|
+
'--dataplane',
|
|
74
|
+
INVALID_DATAPLANE_URL
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
const result = await runCommand('node', args);
|
|
78
|
+
const output = `${result.stdout}\n${result.stderr}`;
|
|
79
|
+
|
|
80
|
+
// Clean up config file
|
|
81
|
+
try {
|
|
82
|
+
await fs.unlink(configPath);
|
|
83
|
+
} catch {
|
|
84
|
+
// Ignore cleanup errors
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return validateWizardResult(result, output);
|
|
88
|
+
} catch (error) {
|
|
89
|
+
return {
|
|
90
|
+
name: 'wizard',
|
|
91
|
+
success: false,
|
|
92
|
+
output: error.message,
|
|
93
|
+
error: error.message
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Test download command with invalid dataplane
|
|
100
|
+
* @async
|
|
101
|
+
* @function testDownload
|
|
102
|
+
* @returns {Promise<Object>} Test result
|
|
103
|
+
*/
|
|
104
|
+
async function testDownload() {
|
|
105
|
+
logInfo('\n📥 Testing: download command');
|
|
106
|
+
|
|
107
|
+
const args = [
|
|
108
|
+
'bin/aifabrix.js',
|
|
109
|
+
'download',
|
|
110
|
+
'non-existent-system-that-should-fail',
|
|
111
|
+
'--environment',
|
|
112
|
+
ENVIRONMENT,
|
|
113
|
+
'--controller',
|
|
114
|
+
CONTROLLER_URL
|
|
115
|
+
];
|
|
116
|
+
|
|
117
|
+
const result = await runCommand('node', args);
|
|
118
|
+
const output = `${result.stdout}\n${result.stderr}`;
|
|
119
|
+
|
|
120
|
+
const expectedPatterns = [
|
|
121
|
+
'failed to connect',
|
|
122
|
+
'connection refused',
|
|
123
|
+
'network error',
|
|
124
|
+
'econnrefused',
|
|
125
|
+
'fetch failed',
|
|
126
|
+
'timeout',
|
|
127
|
+
'unreachable',
|
|
128
|
+
'failed to download system',
|
|
129
|
+
'not found',
|
|
130
|
+
'external system'
|
|
131
|
+
];
|
|
132
|
+
|
|
133
|
+
const validation = validateDownloadDeleteResult(result, output, expectedPatterns);
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
name: 'download',
|
|
137
|
+
success: validation.isValid,
|
|
138
|
+
output: validation.output,
|
|
139
|
+
expectedPatterns: validation.expectedPatterns
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Test delete command with invalid dataplane
|
|
145
|
+
* @async
|
|
146
|
+
* @function testDelete
|
|
147
|
+
* @returns {Promise<Object>} Test result
|
|
148
|
+
*/
|
|
149
|
+
async function testDelete() {
|
|
150
|
+
logInfo('\n🗑️ Testing: delete command');
|
|
151
|
+
|
|
152
|
+
const args = [
|
|
153
|
+
'bin/aifabrix.js',
|
|
154
|
+
'delete',
|
|
155
|
+
'non-existent-system-that-should-fail',
|
|
156
|
+
'--type',
|
|
157
|
+
'external',
|
|
158
|
+
'--environment',
|
|
159
|
+
ENVIRONMENT,
|
|
160
|
+
'--controller',
|
|
161
|
+
CONTROLLER_URL,
|
|
162
|
+
'--yes'
|
|
163
|
+
];
|
|
164
|
+
|
|
165
|
+
const result = await runCommand('node', args);
|
|
166
|
+
const output = `${result.stdout}\n${result.stderr}`;
|
|
167
|
+
|
|
168
|
+
const expectedPatterns = [
|
|
169
|
+
'failed to connect',
|
|
170
|
+
'connection refused',
|
|
171
|
+
'network error',
|
|
172
|
+
'econnrefused',
|
|
173
|
+
'fetch failed',
|
|
174
|
+
'timeout',
|
|
175
|
+
'unreachable',
|
|
176
|
+
'failed to delete',
|
|
177
|
+
'not found',
|
|
178
|
+
'external system'
|
|
179
|
+
];
|
|
180
|
+
|
|
181
|
+
const validation = validateDeleteResult(result, output, expectedPatterns);
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
name: 'delete',
|
|
185
|
+
success: validation.isValid,
|
|
186
|
+
output: validation.output,
|
|
187
|
+
expectedPatterns: validation.expectedPatterns,
|
|
188
|
+
error: validation.error
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Creates test datasource file
|
|
194
|
+
* @async
|
|
195
|
+
* @function createTestDatasource
|
|
196
|
+
* @param {string} datasourcePath - Path to datasource file
|
|
197
|
+
* @returns {Promise<void>} Resolves when datasource file is created
|
|
198
|
+
*/
|
|
199
|
+
async function createTestDatasource(datasourcePath) {
|
|
200
|
+
const datasourceContent = JSON.stringify({
|
|
201
|
+
key: 'test-datasource',
|
|
202
|
+
systemKey: 'test-system',
|
|
203
|
+
displayName: 'Test Datasource',
|
|
204
|
+
entityType: 'company',
|
|
205
|
+
resourceType: 'company'
|
|
206
|
+
}, null, 2);
|
|
207
|
+
await fs.writeFile(datasourcePath, datasourceContent, 'utf8');
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Builds datasource deploy command arguments
|
|
212
|
+
* @function buildDatasourceDeployArgs
|
|
213
|
+
* @param {string} datasourcePath - Path to datasource file
|
|
214
|
+
* @returns {string[]} Command arguments
|
|
215
|
+
*/
|
|
216
|
+
function buildDatasourceDeployArgs(datasourcePath) {
|
|
217
|
+
return [
|
|
218
|
+
'bin/aifabrix.js',
|
|
219
|
+
'datasource',
|
|
220
|
+
'deploy',
|
|
221
|
+
'test-app',
|
|
222
|
+
datasourcePath,
|
|
223
|
+
'--environment',
|
|
224
|
+
ENVIRONMENT,
|
|
225
|
+
'--controller',
|
|
226
|
+
CONTROLLER_URL,
|
|
227
|
+
'--dataplane',
|
|
228
|
+
INVALID_DATAPLANE_URL
|
|
229
|
+
];
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Gets expected error patterns for datasource deploy
|
|
234
|
+
* @function getDatasourceDeployErrorPatterns
|
|
235
|
+
* @returns {string[]} Expected error patterns
|
|
236
|
+
*/
|
|
237
|
+
function getDatasourceDeployErrorPatterns() {
|
|
238
|
+
return [
|
|
239
|
+
'failed to connect',
|
|
240
|
+
'connection refused',
|
|
241
|
+
'network error',
|
|
242
|
+
'econnrefused',
|
|
243
|
+
'fetch failed',
|
|
244
|
+
'timeout',
|
|
245
|
+
'unreachable',
|
|
246
|
+
'failed to publish',
|
|
247
|
+
'deployment failed'
|
|
248
|
+
];
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Test datasource deploy command with invalid dataplane
|
|
253
|
+
* @async
|
|
254
|
+
* @function testDatasourceDeploy
|
|
255
|
+
* @returns {Promise<Object>} Test result
|
|
256
|
+
*/
|
|
257
|
+
async function testDatasourceDeploy() {
|
|
258
|
+
logInfo('\n🚀 Testing: datasource deploy command');
|
|
259
|
+
|
|
260
|
+
const datasourcePath = path.join(process.cwd(), 'integration', 'test-datasource.json');
|
|
261
|
+
|
|
262
|
+
try {
|
|
263
|
+
await createTestDatasource(datasourcePath);
|
|
264
|
+
const args = buildDatasourceDeployArgs(datasourcePath);
|
|
265
|
+
const result = await runCommand('node', args);
|
|
266
|
+
const output = `${result.stdout}\n${result.stderr}`;
|
|
267
|
+
|
|
268
|
+
// Clean up datasource file
|
|
269
|
+
try {
|
|
270
|
+
await fs.unlink(datasourcePath);
|
|
271
|
+
} catch {
|
|
272
|
+
// Ignore cleanup errors
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const expectedPatterns = getDatasourceDeployErrorPatterns();
|
|
276
|
+
const isValid = !result.success && validateError(output, expectedPatterns);
|
|
277
|
+
|
|
278
|
+
return {
|
|
279
|
+
name: 'datasource deploy',
|
|
280
|
+
success: isValid,
|
|
281
|
+
output,
|
|
282
|
+
expectedPatterns
|
|
283
|
+
};
|
|
284
|
+
} catch (error) {
|
|
285
|
+
return {
|
|
286
|
+
name: 'datasource deploy',
|
|
287
|
+
success: false,
|
|
288
|
+
output: error.message,
|
|
289
|
+
error: error.message
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Determines test app name for integration test
|
|
296
|
+
* @async
|
|
297
|
+
* @function determineTestApp
|
|
298
|
+
* @returns {Promise<string>} Test app name
|
|
299
|
+
*/
|
|
300
|
+
async function determineTestApp() {
|
|
301
|
+
const hubspotPath = path.join(process.cwd(), 'integration', 'hubspot');
|
|
302
|
+
try {
|
|
303
|
+
await fs.access(hubspotPath);
|
|
304
|
+
return 'hubspot';
|
|
305
|
+
} catch {
|
|
306
|
+
return 'non-existent-app';
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Test test-integration command with invalid dataplane
|
|
312
|
+
* @async
|
|
313
|
+
* @function testIntegration
|
|
314
|
+
* @returns {Promise<Object>} Test result
|
|
315
|
+
*/
|
|
316
|
+
async function testIntegration() {
|
|
317
|
+
logInfo('\n🧪 Testing: test-integration command');
|
|
318
|
+
|
|
319
|
+
const testApp = await determineTestApp();
|
|
320
|
+
|
|
321
|
+
const args = [
|
|
322
|
+
'bin/aifabrix.js',
|
|
323
|
+
'test-integration',
|
|
324
|
+
testApp,
|
|
325
|
+
'--environment',
|
|
326
|
+
ENVIRONMENT,
|
|
327
|
+
'--controller',
|
|
328
|
+
CONTROLLER_URL
|
|
329
|
+
];
|
|
330
|
+
|
|
331
|
+
const result = await runCommand('node', args);
|
|
332
|
+
const output = `${result.stdout}\n${result.stderr}`;
|
|
333
|
+
|
|
334
|
+
const expectedPatterns = [
|
|
335
|
+
'failed to connect',
|
|
336
|
+
'connection refused',
|
|
337
|
+
'network error',
|
|
338
|
+
'econnrefused',
|
|
339
|
+
'fetch failed',
|
|
340
|
+
'timeout',
|
|
341
|
+
'unreachable',
|
|
342
|
+
'failed to run integration tests',
|
|
343
|
+
'not found',
|
|
344
|
+
'dataplane url not found',
|
|
345
|
+
'application not found'
|
|
346
|
+
];
|
|
347
|
+
|
|
348
|
+
const isValid = !result.success && (
|
|
349
|
+
validateError(output, expectedPatterns) ||
|
|
350
|
+
output.includes('Failed') ||
|
|
351
|
+
output.includes('Error') ||
|
|
352
|
+
output.includes('not found')
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
return {
|
|
356
|
+
name: 'test-integration',
|
|
357
|
+
success: isValid,
|
|
358
|
+
output,
|
|
359
|
+
expectedPatterns
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Test dataplane discovery with invalid dataplane
|
|
365
|
+
* @async
|
|
366
|
+
* @function testDataplaneDiscovery
|
|
367
|
+
* @returns {Promise<Object>} Test result
|
|
368
|
+
*/
|
|
369
|
+
async function testDataplaneDiscovery() {
|
|
370
|
+
logInfo('\n🌐 Testing: dataplane discovery');
|
|
371
|
+
|
|
372
|
+
const args = [
|
|
373
|
+
'bin/aifabrix.js',
|
|
374
|
+
'download',
|
|
375
|
+
'non-existent-system-for-discovery-test',
|
|
376
|
+
'--environment',
|
|
377
|
+
ENVIRONMENT,
|
|
378
|
+
'--controller',
|
|
379
|
+
CONTROLLER_URL
|
|
380
|
+
];
|
|
381
|
+
|
|
382
|
+
const result = await runCommand('node', args);
|
|
383
|
+
const output = `${result.stdout}\n${result.stderr}`;
|
|
384
|
+
|
|
385
|
+
const expectedPatterns = [
|
|
386
|
+
'failed to discover dataplane url',
|
|
387
|
+
'dataplane service not found',
|
|
388
|
+
'application not found',
|
|
389
|
+
'dataplane url not found',
|
|
390
|
+
'failed to download system',
|
|
391
|
+
'not found',
|
|
392
|
+
'external system'
|
|
393
|
+
];
|
|
394
|
+
|
|
395
|
+
const timeout = isTimeoutResult(result);
|
|
396
|
+
const isValid = (!result.success || timeout) && (
|
|
397
|
+
timeout ||
|
|
398
|
+
validateError(output, expectedPatterns) ||
|
|
399
|
+
output.includes('not found') ||
|
|
400
|
+
output.includes('Failed') ||
|
|
401
|
+
output.includes('Error')
|
|
402
|
+
);
|
|
403
|
+
|
|
404
|
+
return {
|
|
405
|
+
name: 'dataplane discovery',
|
|
406
|
+
success: isValid,
|
|
407
|
+
output: timeout ? `${output}\n[Command timed out - this indicates the command may be hanging]` : output,
|
|
408
|
+
expectedPatterns: timeout ? [...expectedPatterns, 'timeout'] : expectedPatterns
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
module.exports = {
|
|
413
|
+
testWizard,
|
|
414
|
+
testDownload,
|
|
415
|
+
testDelete,
|
|
416
|
+
testDatasourceDeploy,
|
|
417
|
+
testIntegration,
|
|
418
|
+
testDataplaneDiscovery
|
|
419
|
+
};
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Dataplane Down Test Suite
|
|
4
|
+
*
|
|
5
|
+
* Tests all commands that interact with dataplane when dataplane is unavailable.
|
|
6
|
+
* Validates that appropriate error messages are returned.
|
|
7
|
+
*
|
|
8
|
+
* @fileoverview Dataplane down error handling tests
|
|
9
|
+
* @author AI Fabrix Team
|
|
10
|
+
* @version 2.0.0
|
|
11
|
+
*/
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
const {
|
|
15
|
+
logInfo,
|
|
16
|
+
logSuccess,
|
|
17
|
+
logError,
|
|
18
|
+
logWarn
|
|
19
|
+
} = require('./test-dataplane-down-helpers');
|
|
20
|
+
const {
|
|
21
|
+
testWizard,
|
|
22
|
+
testDownload,
|
|
23
|
+
testDelete,
|
|
24
|
+
testDatasourceDeploy,
|
|
25
|
+
testIntegration,
|
|
26
|
+
testDataplaneDiscovery
|
|
27
|
+
} = require('./test-dataplane-down-tests');
|
|
28
|
+
|
|
29
|
+
const INVALID_DATAPLANE_URL = 'http://localhost:9999';
|
|
30
|
+
const CONTROLLER_URL = process.env.CONTROLLER_URL || 'http://localhost:3110';
|
|
31
|
+
const ENVIRONMENT = process.env.ENVIRONMENT || 'miso';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Displays failed test details
|
|
35
|
+
* @function displayFailedTestDetails
|
|
36
|
+
* @param {Array} failedTests - Failed test results
|
|
37
|
+
* @returns {void}
|
|
38
|
+
*/
|
|
39
|
+
function displayFailedTestDetails(failedTests) {
|
|
40
|
+
if (failedTests.length === 0) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
logError('\nFailed Tests:');
|
|
45
|
+
for (const test of failedTests) {
|
|
46
|
+
logError(` - ${test.name}`);
|
|
47
|
+
if (test.output) {
|
|
48
|
+
const outputPreview = test.output.length > 500 ? test.output.substring(0, 500) + '...' : test.output;
|
|
49
|
+
logWarn(` Output: ${outputPreview}`);
|
|
50
|
+
}
|
|
51
|
+
if (test.error) {
|
|
52
|
+
logWarn(` Error: ${test.error}`);
|
|
53
|
+
}
|
|
54
|
+
if (test.expectedPatterns) {
|
|
55
|
+
logWarn(` Expected patterns: ${test.expectedPatterns.join(', ')}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Displays test results summary
|
|
62
|
+
* @function displaySummary
|
|
63
|
+
* @param {Array} results - Test results
|
|
64
|
+
* @returns {void}
|
|
65
|
+
*/
|
|
66
|
+
function displaySummary(results) {
|
|
67
|
+
logInfo('\n' + '='.repeat(60));
|
|
68
|
+
logInfo('Test Summary');
|
|
69
|
+
logInfo('='.repeat(60));
|
|
70
|
+
|
|
71
|
+
const passed = results.filter(r => r.success).length;
|
|
72
|
+
const failed = results.filter(r => !r.success).length;
|
|
73
|
+
|
|
74
|
+
logInfo(`Total tests: ${results.length}`);
|
|
75
|
+
logSuccess(`Passed: ${passed}`);
|
|
76
|
+
if (failed > 0) {
|
|
77
|
+
logError(`Failed: ${failed}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const failedTests = results.filter(r => !r.success);
|
|
81
|
+
displayFailedTestDetails(failedTests);
|
|
82
|
+
|
|
83
|
+
logInfo('='.repeat(60));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Runs all test cases
|
|
88
|
+
* @async
|
|
89
|
+
* @function runTests
|
|
90
|
+
* @returns {Promise<Array>} Test results
|
|
91
|
+
*/
|
|
92
|
+
async function runTests() {
|
|
93
|
+
const tests = [
|
|
94
|
+
testWizard,
|
|
95
|
+
testDownload,
|
|
96
|
+
testDelete,
|
|
97
|
+
testDatasourceDeploy,
|
|
98
|
+
testIntegration,
|
|
99
|
+
testDataplaneDiscovery
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
const results = [];
|
|
103
|
+
|
|
104
|
+
for (const testFn of tests) {
|
|
105
|
+
try {
|
|
106
|
+
const result = await testFn();
|
|
107
|
+
results.push(result);
|
|
108
|
+
|
|
109
|
+
if (result.success) {
|
|
110
|
+
logSuccess(`✓ ${result.name}: Error handling validated`);
|
|
111
|
+
} else {
|
|
112
|
+
logError(`✗ ${result.name}: Error handling failed`);
|
|
113
|
+
if (result.output) {
|
|
114
|
+
logWarn(` Output: ${result.output.substring(0, 200)}...`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
} catch (error) {
|
|
118
|
+
logError(`✗ ${testFn.name}: Unexpected error: ${error.message}`);
|
|
119
|
+
results.push({
|
|
120
|
+
name: testFn.name,
|
|
121
|
+
success: false,
|
|
122
|
+
error: error.message
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return results;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Main test runner
|
|
132
|
+
* @async
|
|
133
|
+
* @function main
|
|
134
|
+
* @returns {Promise<void>} Resolves when tests complete
|
|
135
|
+
*/
|
|
136
|
+
async function main() {
|
|
137
|
+
logInfo('='.repeat(60));
|
|
138
|
+
logInfo('Dataplane Down Error Handling Test Suite');
|
|
139
|
+
logInfo('='.repeat(60));
|
|
140
|
+
logInfo(`Invalid Dataplane URL: ${INVALID_DATAPLANE_URL}`);
|
|
141
|
+
logInfo(`Controller URL: ${CONTROLLER_URL}`);
|
|
142
|
+
logInfo(`Environment: ${ENVIRONMENT}`);
|
|
143
|
+
logInfo('='.repeat(60));
|
|
144
|
+
|
|
145
|
+
const results = await runTests();
|
|
146
|
+
displaySummary(results);
|
|
147
|
+
|
|
148
|
+
const failed = results.filter(r => !r.success).length;
|
|
149
|
+
if (failed > 0) {
|
|
150
|
+
process.exitCode = 1;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
main().catch(error => {
|
|
155
|
+
logError(`Fatal error: ${error.message}`);
|
|
156
|
+
process.exitCode = 1;
|
|
157
|
+
});
|