@itentialopensource/adapter-aruba_airwave 0.1.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/.eslintignore +6 -0
- package/.eslintrc.js +18 -0
- package/.gitlab/.gitkeep +0 -0
- package/.gitlab/issue_templates/.gitkeep +0 -0
- package/.gitlab/issue_templates/Default.md +17 -0
- package/.gitlab/issue_templates/bugReportTemplate.md +76 -0
- package/.gitlab/issue_templates/featureRequestTemplate.md +14 -0
- package/.jshintrc +0 -0
- package/CHANGELOG.md +9 -0
- package/CODE_OF_CONDUCT.md +48 -0
- package/CONTRIBUTING.md +158 -0
- package/LICENSE +201 -0
- package/README.md +544 -0
- package/adapter.js +2860 -0
- package/adapterBase.js +906 -0
- package/entities/.system/action.json +50 -0
- package/entities/.system/mockdatafiles/getToken-default.json +3 -0
- package/entities/.system/mockdatafiles/healthcheck-default.json +3 -0
- package/entities/.system/schema.json +19 -0
- package/entities/.system/schemaTokenReq.json +77 -0
- package/entities/.system/schemaTokenResp.json +65 -0
- package/entities/BatchExecuteAPCommandsAPIS/action.json +45 -0
- package/entities/BatchExecuteAPCommandsAPIS/schema.json +20 -0
- package/entities/ConfigurationAPIS/action.json +126 -0
- package/entities/ConfigurationAPIS/schema.json +90 -0
- package/entities/DeviceAPIS/action.json +46 -0
- package/entities/DeviceAPIS/schema.json +20 -0
- package/entities/LOGIN/action.json +24 -0
- package/entities/LOGIN/schema.json +41 -0
- package/entities/QueryAPIS/action.json +298 -0
- package/entities/QueryAPIS/schema.json +32 -0
- package/entities/ReportAPIS/action.json +25 -0
- package/entities/ReportAPIS/schema.json +30 -0
- package/entities/SearchAPIS/action.json +67 -0
- package/entities/SearchAPIS/schema.json +21 -0
- package/error.json +184 -0
- package/package.json +86 -0
- package/pronghorn.json +1589 -0
- package/propertiesSchema.json +801 -0
- package/refs?service=git-upload-pack +0 -0
- package/report/ArubaAirwavePostman.json-OpenApi3Json.json +1583 -0
- package/report/creationReport.json +381 -0
- package/sampleProperties.json +97 -0
- package/test/integration/adapterTestBasicGet.js +85 -0
- package/test/integration/adapterTestConnectivity.js +93 -0
- package/test/integration/adapterTestIntegration.js +1125 -0
- package/test/unit/adapterBaseTestUnit.js +929 -0
- package/test/unit/adapterTestUnit.js +1413 -0
- package/utils/artifactize.js +146 -0
- package/utils/basicGet.js +63 -0
- package/utils/packModificationScript.js +35 -0
- package/utils/pre-commit.sh +27 -0
- package/utils/setup.js +33 -0
- package/utils/tbScript.js +163 -0
- package/utils/tbUtils.js +372 -0
- package/utils/testRunner.js +298 -0
- package/utils/troubleshootingAdapter.js +219 -0
- package/workflows/README.md +3 -0
package/utils/tbUtils.js
ADDED
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
/* @copyright Itential, LLC 2020 */
|
|
2
|
+
|
|
3
|
+
/* eslint import/no-extraneous-dependencies: warn */
|
|
4
|
+
/* eslint global-require: warn */
|
|
5
|
+
/* eslint import/no-dynamic-require: warn */
|
|
6
|
+
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const fs = require('fs-extra');
|
|
9
|
+
const cp = require('child_process');
|
|
10
|
+
|
|
11
|
+
module.exports = {
|
|
12
|
+
SERVICE_CONFIGS_COLLECTION: 'service_configs',
|
|
13
|
+
IAP_PROFILES_COLLECTION: 'iap_profiles',
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @summary update newConnection properties in adapter config
|
|
17
|
+
*
|
|
18
|
+
* @function updateNewConnection
|
|
19
|
+
* @param {Object} config - adaper configuration object required by IAP
|
|
20
|
+
* @param {Object} newConnection - connection related property collection from user
|
|
21
|
+
*/
|
|
22
|
+
updateNewConnection: (config, newConnection) => {
|
|
23
|
+
const updatedConfig = JSON.parse(JSON.stringify(config));
|
|
24
|
+
Object.keys(newConnection).forEach((key) => {
|
|
25
|
+
updatedConfig.properties.properties[key] = newConnection[key];
|
|
26
|
+
});
|
|
27
|
+
return updatedConfig;
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @summary assemble heathcheck endpoint into an URL
|
|
32
|
+
*
|
|
33
|
+
* @function getHealthCheckEndpointURL
|
|
34
|
+
* @param {Object} endpoint - user updated healthcheck endpoint object
|
|
35
|
+
* @param {Object} config - adaper configuration object required by IAP
|
|
36
|
+
*/
|
|
37
|
+
getHealthCheckEndpointURL: (endpoint, config) => {
|
|
38
|
+
const p = config.properties.properties;
|
|
39
|
+
const healthCheckEndpointURL = `${p.protocol}://${p.host}${p.base_path}${p.version}${endpoint.healthCheckEndpoint}`;
|
|
40
|
+
console.log({ healthCheckEndpointURL });
|
|
41
|
+
return healthCheckEndpointURL;
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @summary persist healthcheck endpoint when user make update
|
|
46
|
+
*
|
|
47
|
+
* @function updateHealthCheckEndpoint
|
|
48
|
+
* @param {Object} newHealthCheckEndpoint - user confirmed healthcheck object
|
|
49
|
+
* @param {Object} healthCheckEndpoint - existing healthcheck object
|
|
50
|
+
* @param {Object} healthcheck - ./entities/.system/action.json object
|
|
51
|
+
*/
|
|
52
|
+
updateHealthCheckEndpoint: (newHealthCheckEndpoint, healthCheckEndpoint, healthcheck) => {
|
|
53
|
+
if (newHealthCheckEndpoint.healthCheckEndpoint !== healthCheckEndpoint.healthCheckEndpoint) {
|
|
54
|
+
const p = healthcheck.actions[1].entitypath;
|
|
55
|
+
const newEntitypath = p.slice(0, 21) + newHealthCheckEndpoint.healthCheckEndpoint + p.slice(p.length - 8);
|
|
56
|
+
const updatedHealthcheck = JSON.parse(JSON.stringify(healthcheck));
|
|
57
|
+
updatedHealthcheck.actions[1].entitypath = newEntitypath;
|
|
58
|
+
console.log('updating healthcheck setting');
|
|
59
|
+
fs.writeFileSync('./entities/.system/action.json', JSON.stringify(updatedHealthcheck, null, 2));
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @summary update authentication property given new input value from user
|
|
65
|
+
* compare values from auth and newAuth, if there's difference
|
|
66
|
+
* update adapter config
|
|
67
|
+
* @function updateAuth
|
|
68
|
+
* @param {Object} newAuth - user confirmed authentication object
|
|
69
|
+
* @param {Object} auth - existing authentication object
|
|
70
|
+
* @param {Object} config - adaper configuration object required by IAP
|
|
71
|
+
*/
|
|
72
|
+
updateAuth: (newAuth, auth, config) => {
|
|
73
|
+
const updatedConfig = JSON.parse(JSON.stringify(config));
|
|
74
|
+
if (Object.keys(newAuth).every((key) => newAuth[key] === auth[key])) {
|
|
75
|
+
return config;
|
|
76
|
+
}
|
|
77
|
+
Object.keys(newAuth).forEach((key) => {
|
|
78
|
+
updatedConfig.properties.properties.authentication[key] = newAuth[key];
|
|
79
|
+
});
|
|
80
|
+
console.log(updatedConfig.properties.properties.authentication);
|
|
81
|
+
return updatedConfig;
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @summary add mark current auth_method with `(current)`
|
|
86
|
+
*
|
|
87
|
+
* @function getDisplayAuthOptions
|
|
88
|
+
* @param {String} currentAuth - current auth method in adapter config
|
|
89
|
+
* @param {Array} authOptions - available auth method
|
|
90
|
+
*/
|
|
91
|
+
getDisplayAuthOptions: (currentAuth, authOptions) => {
|
|
92
|
+
const displayAuthOptions = JSON.parse(JSON.stringify(authOptions));
|
|
93
|
+
displayAuthOptions[authOptions.indexOf(currentAuth)] += ' (current)';
|
|
94
|
+
return displayAuthOptions;
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @summary decrypt IAP properties
|
|
99
|
+
* code from pronghorn-core/migration_scripts/installService.js
|
|
100
|
+
*
|
|
101
|
+
* @function decryptProperties
|
|
102
|
+
*/
|
|
103
|
+
decryptProperties: (props, dirname, discovery) => {
|
|
104
|
+
const propertyEncryptionClassPath = path.join(dirname, '../../../@itential/pronghorn-core/core/PropertyEncryption.js');
|
|
105
|
+
const isEncrypted = props.pathProps.encrypted;
|
|
106
|
+
const PropertyEncryption = discovery.require(propertyEncryptionClassPath, isEncrypted);
|
|
107
|
+
const propertyEncryption = new PropertyEncryption({
|
|
108
|
+
algorithm: 'aes-256-ctr',
|
|
109
|
+
key: 'TG9uZ0Rpc3RhbmNlUnVubmVyUHJvbmdob3JuCg==',
|
|
110
|
+
encoding: 'utf-8'
|
|
111
|
+
});
|
|
112
|
+
return propertyEncryption.decryptProps(props);
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* @summary create connection object for verification
|
|
117
|
+
*
|
|
118
|
+
* @function getConnection
|
|
119
|
+
* @param {Object} props - adapter config.properties
|
|
120
|
+
*/
|
|
121
|
+
getConnection: (props) => {
|
|
122
|
+
const connection = {
|
|
123
|
+
host: props.properties.host,
|
|
124
|
+
base_path: props.properties.base_path,
|
|
125
|
+
protocol: props.properties.protocol,
|
|
126
|
+
version: props.properties.version,
|
|
127
|
+
port: props.properties.port
|
|
128
|
+
};
|
|
129
|
+
return connection;
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @summary update connection properties based on user answer
|
|
134
|
+
*
|
|
135
|
+
* @function getNewProps
|
|
136
|
+
* @param {Array} answers - values collected from CLI
|
|
137
|
+
* @param {Object} connection - connection property verified by user
|
|
138
|
+
*/
|
|
139
|
+
getNewProps: (answers, connection) => {
|
|
140
|
+
if (answers.every((answer) => answer === '')) {
|
|
141
|
+
return connection;
|
|
142
|
+
}
|
|
143
|
+
const newConnection = {};
|
|
144
|
+
const properties = Object.keys(connection);
|
|
145
|
+
for (let i = 0; i < answers.length; i += 1) {
|
|
146
|
+
if (answers[i]) {
|
|
147
|
+
newConnection[properties[i]] = Number.isNaN(Number(answers[i])) ? answers[i] : Number(answers[i]);
|
|
148
|
+
} else {
|
|
149
|
+
newConnection[properties[i]] = connection[properties[i]];
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return newConnection;
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* @summary extract endpoint string from healthcheck object
|
|
157
|
+
*
|
|
158
|
+
* @function getHealthCheckEndpoint
|
|
159
|
+
* @param {Object} healthcheck - {Object} healthcheck - ./entities/.system/action.json object
|
|
160
|
+
*/
|
|
161
|
+
getHealthCheckEndpoint: (healthcheck) => {
|
|
162
|
+
const endpoint = healthcheck.actions[1].entitypath.slice(21,
|
|
163
|
+
healthcheck.actions[1].entitypath.length - 8);
|
|
164
|
+
return { healthCheckEndpoint: endpoint };
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* @summary Verify that the adapter is in the correct directory
|
|
169
|
+
* - Within IAP
|
|
170
|
+
* - In node_modules/@ namespace
|
|
171
|
+
* verify the adapter is installed under node_modules/
|
|
172
|
+
* and is consistent with the name property of package.json
|
|
173
|
+
* and the node_modules/ is in the correct path within IAP
|
|
174
|
+
* @param {String} dirname - current path
|
|
175
|
+
* @param {String} name - name property from package.json
|
|
176
|
+
*/
|
|
177
|
+
verifyInstallationDir: (dirname, name) => {
|
|
178
|
+
const pathArray = dirname.split(path.sep);
|
|
179
|
+
const expectedPath = `node_modules/${name}`;
|
|
180
|
+
const currentPath = pathArray.slice(pathArray.length - 4, pathArray.length - 1).join('/');
|
|
181
|
+
if (expectedPath !== currentPath) {
|
|
182
|
+
throw new Error(`adapter should be installed under ${expectedPath}`);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const serverFile = path.join(dirname, '../../../..', 'server.js');
|
|
186
|
+
if (!fs.existsSync(serverFile)) {
|
|
187
|
+
throw new Error(`adapter should be installed under IAP/${expectedPath}`);
|
|
188
|
+
}
|
|
189
|
+
console.log(`adapter correctly installed at ${currentPath}`);
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* @summary execute command and preserve the output the same as run command in shell
|
|
194
|
+
*
|
|
195
|
+
* @function systemSync
|
|
196
|
+
* @param {String} cmd - Command to execute
|
|
197
|
+
* @param {boolean} process - Whether stdout should be processed and returned
|
|
198
|
+
*/
|
|
199
|
+
systemSync: function systemSync(cmd, process) {
|
|
200
|
+
if (process) {
|
|
201
|
+
let stdout;
|
|
202
|
+
try {
|
|
203
|
+
stdout = cp.execSync(cmd).toString();
|
|
204
|
+
} catch (error) {
|
|
205
|
+
stdout = error.stdout.toString();
|
|
206
|
+
}
|
|
207
|
+
const output = this.getTestCount(stdout);
|
|
208
|
+
output.stdout = stdout;
|
|
209
|
+
return output;
|
|
210
|
+
}
|
|
211
|
+
try {
|
|
212
|
+
return cp.execSync(cmd, { stdio: 'inherit' });
|
|
213
|
+
} catch (error) {
|
|
214
|
+
return console.error(error.stdout);
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* @summary parses a string and returns the number parsed from startIndex backwards
|
|
220
|
+
*
|
|
221
|
+
* @function parseNum
|
|
222
|
+
* @param {String} inputStr - Any String
|
|
223
|
+
* @param {Number} startIndex - Index to begin parsing
|
|
224
|
+
*/
|
|
225
|
+
parseNum: function parseNum(inputStr, startIndex) {
|
|
226
|
+
let count = '';
|
|
227
|
+
let currChar;
|
|
228
|
+
let start = startIndex;
|
|
229
|
+
while (currChar !== ' ') {
|
|
230
|
+
currChar = inputStr.charAt(start);
|
|
231
|
+
count = currChar + count;
|
|
232
|
+
start -= 1;
|
|
233
|
+
}
|
|
234
|
+
return parseInt(count, 10);
|
|
235
|
+
},
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* @summary Parses a mocha test result and returns the count of passing and failing tests
|
|
239
|
+
*
|
|
240
|
+
* @function getTestCount
|
|
241
|
+
* @param {String} testStr - Output from mocha test
|
|
242
|
+
*/
|
|
243
|
+
getTestCount: function getTestCount(testStr) {
|
|
244
|
+
const passIndex = testStr.search('passing');
|
|
245
|
+
const failIndex = testStr.search('failing');
|
|
246
|
+
const passCount = passIndex >= 0 ? this.parseNum(testStr, passIndex - 2) : 0;
|
|
247
|
+
const failCount = failIndex >= 0 ? this.parseNum(testStr, failIndex - 2) : 0;
|
|
248
|
+
return { passCount, failCount };
|
|
249
|
+
},
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* @summary remove package-lock.json and node_modules directory if exists
|
|
253
|
+
* run npm install and print result to stdout
|
|
254
|
+
*/
|
|
255
|
+
npmInstall: function npmInstall() {
|
|
256
|
+
fs.removeSync('../package-lock.json');
|
|
257
|
+
fs.removeSync('../node_modules/');
|
|
258
|
+
console.log('Run npm install ...');
|
|
259
|
+
this.systemSync('npm install');
|
|
260
|
+
},
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* @summary run lint, unit test and integration test
|
|
264
|
+
* print result to stdout
|
|
265
|
+
*/
|
|
266
|
+
runTest: function runTest() {
|
|
267
|
+
this.systemSync('npm run lint:errors');
|
|
268
|
+
this.systemSync('npm run test:unit');
|
|
269
|
+
this.systemSync('npm run test:integration');
|
|
270
|
+
},
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* @summary run basicget with mocha
|
|
274
|
+
* @param {boolean} scriptFlag - whether the function is ran from a script
|
|
275
|
+
* print result to stdout
|
|
276
|
+
* returns mocha test results otherwise
|
|
277
|
+
*/
|
|
278
|
+
runBasicGet: function runBasicGet(scriptFlag) {
|
|
279
|
+
const testPath = path.resolve(__dirname, '..', 'test/integration/adapterTestBasicGet.js');
|
|
280
|
+
return this.systemSync(`mocha ${testPath} --exit`, !scriptFlag);
|
|
281
|
+
},
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* @summary run connectivity with mocha
|
|
285
|
+
* @param {String} host - Host url to run healthcheck
|
|
286
|
+
* @param {boolean} scriptFlag - Whether the function is ran from a script
|
|
287
|
+
* print result to stdout if ran from script
|
|
288
|
+
* returns mocha test results otherwise
|
|
289
|
+
*/
|
|
290
|
+
runConnectivity: function runConnectivity(host, scriptFlag) {
|
|
291
|
+
let testPath = 'test/integration/adapterTestConnectivity.js';
|
|
292
|
+
if (!scriptFlag) {
|
|
293
|
+
testPath = path.resolve(__dirname, '..', testPath);
|
|
294
|
+
}
|
|
295
|
+
return this.systemSync(`mocha ${testPath} --HOST=${host} --timeout 10000 --exit`, !scriptFlag);
|
|
296
|
+
},
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* @summary create Adapter property
|
|
300
|
+
*
|
|
301
|
+
* @function createAdapter
|
|
302
|
+
* @param {Object} pronghornProps - decrypted 'properties.json' from IAP root directory
|
|
303
|
+
* @param {Object} profileItem - pronghorn props saved in database
|
|
304
|
+
* @param {Object} adapterPronghorn - ./pronghorn.json in adapter dir
|
|
305
|
+
* @param {Object} sampleProperties - './sampleProperties.json' in adapter dir
|
|
306
|
+
*/
|
|
307
|
+
createAdapter: (pronghornProps, profileItem, sampleProperties, adapterPronghorn) => {
|
|
308
|
+
const adapter = {
|
|
309
|
+
mongoProps: pronghornProps.mongoProps,
|
|
310
|
+
isEncrypted: pronghornProps.pathProps.encrypted,
|
|
311
|
+
model: adapterPronghorn.id,
|
|
312
|
+
name: sampleProperties.id,
|
|
313
|
+
type: adapterPronghorn.type,
|
|
314
|
+
properties: sampleProperties,
|
|
315
|
+
redisProps: profileItem.redisProps,
|
|
316
|
+
loggerProps: profileItem.loggerProps,
|
|
317
|
+
rabbitmq: profileItem.rabbitmq
|
|
318
|
+
};
|
|
319
|
+
adapter.loggerProps.log_filename = `adapter-${adapter.name}.log`;
|
|
320
|
+
adapter.mongoProps.pdb = true;
|
|
321
|
+
return adapter;
|
|
322
|
+
},
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* @summary return async healthcheck result as a Promise
|
|
326
|
+
*
|
|
327
|
+
* @function request
|
|
328
|
+
* @param {Adapter} a - Adapter instance
|
|
329
|
+
*/
|
|
330
|
+
request: function request(a) {
|
|
331
|
+
return new Promise((resolve, reject) => {
|
|
332
|
+
a.healthCheck(null, (data) => {
|
|
333
|
+
if (!data) reject(new Error('healthCheckEndpoint failed'));
|
|
334
|
+
resolve(data);
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
},
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* @summary deal with healthcheck response returned from adapter instace
|
|
341
|
+
*
|
|
342
|
+
* @function healthCheck
|
|
343
|
+
* @param {Adapter} a - Adapter instance
|
|
344
|
+
*/
|
|
345
|
+
healthCheck: async function healthCheck(a) {
|
|
346
|
+
const result = await this.request(a)
|
|
347
|
+
.then((res) => {
|
|
348
|
+
console.log('healthCheckEndpoint OK');
|
|
349
|
+
return res;
|
|
350
|
+
})
|
|
351
|
+
.catch((error) => {
|
|
352
|
+
console.error(error.message);
|
|
353
|
+
return false;
|
|
354
|
+
});
|
|
355
|
+
return result;
|
|
356
|
+
},
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* @summary Check whether adapter is located within IAP node_modules
|
|
360
|
+
* by loading properties.json. If not, return false.
|
|
361
|
+
* @function withinIAP
|
|
362
|
+
* @param {String} iapDir root directory of IAP
|
|
363
|
+
*/
|
|
364
|
+
withinIAP: (iapDir) => {
|
|
365
|
+
try {
|
|
366
|
+
const rawProps = require(path.join(iapDir, 'properties.json'));
|
|
367
|
+
return rawProps;
|
|
368
|
+
} catch (error) {
|
|
369
|
+
return false;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
};
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* @copyright Itential, LLC 2019 */
|
|
3
|
+
|
|
4
|
+
const fs = require('fs-extra');
|
|
5
|
+
const rl = require('readline-sync');
|
|
6
|
+
const execute = require('child_process').exec;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* This script will determine the type of integration test to run
|
|
10
|
+
* based on input. If other information is needed, it will solicit
|
|
11
|
+
* that input and then edit the integration test accordingly.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
let stub = true;
|
|
15
|
+
let isRapidFail = false;
|
|
16
|
+
let isSaveMockData = false;
|
|
17
|
+
let host = 'replace.hostorip.here';
|
|
18
|
+
let username = 'username';
|
|
19
|
+
let password = 'password';
|
|
20
|
+
let protocol = 'http';
|
|
21
|
+
let port = 80;
|
|
22
|
+
let sslenable = false;
|
|
23
|
+
let sslinvalid = false;
|
|
24
|
+
const dstub = true;
|
|
25
|
+
const disRapidFail = false;
|
|
26
|
+
const disSaveMockData = false;
|
|
27
|
+
const dhost = 'replace.hostorip.here';
|
|
28
|
+
const dusername = 'username';
|
|
29
|
+
const dpassword = 'password';
|
|
30
|
+
const dprotocol = 'http';
|
|
31
|
+
const dport = 80;
|
|
32
|
+
const dsslenable = false;
|
|
33
|
+
const dsslinvalid = false;
|
|
34
|
+
|
|
35
|
+
let stderror = false;
|
|
36
|
+
let running = false;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Updates the integration test file with the proper vars
|
|
40
|
+
*/
|
|
41
|
+
function replaceTestVars(test) {
|
|
42
|
+
if (!fs.existsSync(test)) {
|
|
43
|
+
console.log(`Could not find ${test}`);
|
|
44
|
+
return 'error';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let intTest = fs.readFileSync(test, 'utf8');
|
|
48
|
+
|
|
49
|
+
// replace stub variable but check if it exists first
|
|
50
|
+
let sindex = intTest.indexOf('const stub');
|
|
51
|
+
let eindex = intTest.indexOf(';', sindex);
|
|
52
|
+
let replStr = intTest.substring(sindex, eindex + 1);
|
|
53
|
+
if (sindex > -1) {
|
|
54
|
+
intTest = intTest.replace(replStr, `const stub = ${stub};`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// replace isRapidFail variable but check if it exists first
|
|
58
|
+
sindex = intTest.indexOf('const isRapidFail');
|
|
59
|
+
eindex = intTest.indexOf(';', sindex);
|
|
60
|
+
replStr = intTest.substring(sindex, eindex + 1);
|
|
61
|
+
if (sindex > -1) {
|
|
62
|
+
intTest = intTest.replace(replStr, `const isRapidFail = ${isRapidFail};`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// replace isSaveMockData variable but check if it exists first
|
|
66
|
+
sindex = intTest.indexOf('const isSaveMockData');
|
|
67
|
+
eindex = intTest.indexOf(';', sindex);
|
|
68
|
+
replStr = intTest.substring(sindex, eindex + 1);
|
|
69
|
+
if (sindex > -1) {
|
|
70
|
+
intTest = intTest.replace(replStr, `const isSaveMockData = ${isSaveMockData};`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// replace host variable
|
|
74
|
+
sindex = intTest.indexOf('const host');
|
|
75
|
+
eindex = intTest.indexOf(';', sindex);
|
|
76
|
+
replStr = intTest.substring(sindex, eindex + 1);
|
|
77
|
+
intTest = intTest.replace(replStr, `const host = '${host}';`);
|
|
78
|
+
|
|
79
|
+
// replace username variable
|
|
80
|
+
sindex = intTest.indexOf('const username');
|
|
81
|
+
eindex = intTest.indexOf(';', sindex);
|
|
82
|
+
replStr = intTest.substring(sindex, eindex + 1);
|
|
83
|
+
intTest = intTest.replace(replStr, `const username = '${username}';`);
|
|
84
|
+
|
|
85
|
+
// replace password variable
|
|
86
|
+
sindex = intTest.indexOf('const password');
|
|
87
|
+
eindex = intTest.indexOf(';', sindex);
|
|
88
|
+
replStr = intTest.substring(sindex, eindex + 1);
|
|
89
|
+
intTest = intTest.replace(replStr, `const password = '${password}';`);
|
|
90
|
+
|
|
91
|
+
// replace protocol variable
|
|
92
|
+
sindex = intTest.indexOf('const protocol');
|
|
93
|
+
eindex = intTest.indexOf(';', sindex);
|
|
94
|
+
replStr = intTest.substring(sindex, eindex + 1);
|
|
95
|
+
intTest = intTest.replace(replStr, `const protocol = '${protocol}';`);
|
|
96
|
+
|
|
97
|
+
// replace port variable
|
|
98
|
+
sindex = intTest.indexOf('const port');
|
|
99
|
+
eindex = intTest.indexOf(';', sindex);
|
|
100
|
+
replStr = intTest.substring(sindex, eindex + 1);
|
|
101
|
+
intTest = intTest.replace(replStr, `const port = ${port};`);
|
|
102
|
+
|
|
103
|
+
// replace sslenable variable
|
|
104
|
+
sindex = intTest.indexOf('const sslenable');
|
|
105
|
+
eindex = intTest.indexOf(';', sindex);
|
|
106
|
+
replStr = intTest.substring(sindex, eindex + 1);
|
|
107
|
+
intTest = intTest.replace(replStr, `const sslenable = ${sslenable};`);
|
|
108
|
+
|
|
109
|
+
// replace sslinvalid variable
|
|
110
|
+
sindex = intTest.indexOf('const sslinvalid');
|
|
111
|
+
eindex = intTest.indexOf(';', sindex);
|
|
112
|
+
replStr = intTest.substring(sindex, eindex + 1);
|
|
113
|
+
intTest = intTest.replace(replStr, `const sslinvalid = ${sslinvalid};`);
|
|
114
|
+
|
|
115
|
+
console.log(`Updates to ${test} complete`);
|
|
116
|
+
fs.writeFileSync(test, intTest);
|
|
117
|
+
return 'success';
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Updates the integration test file and runs the script
|
|
122
|
+
*/
|
|
123
|
+
function runTest(callback) {
|
|
124
|
+
replaceTestVars('test/integration/adapterTestIntegration.js');
|
|
125
|
+
|
|
126
|
+
let cmdPath = 'npm run test:integration';
|
|
127
|
+
console.log('\nRUNNING INTEGRATION TESTS - THIS WILL TAKE SOME TIME AND WILL NOT PRINT UNTIL TEST IS COMPLETE!\n');
|
|
128
|
+
if (stderror) {
|
|
129
|
+
console.log('\nNOTE: standard error from tests is included - unless test failed, these may be expected errors:\n');
|
|
130
|
+
cmdPath += ' 2>&1';
|
|
131
|
+
} else {
|
|
132
|
+
console.log('stderr not shown');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return execute(cmdPath, (cerror, stdout) => {
|
|
136
|
+
console.log('executed tests:\n');
|
|
137
|
+
console.log(`${stdout}\n`);
|
|
138
|
+
if (cerror) {
|
|
139
|
+
console.log('\x1b[31m%s\x1b[0m', '\nexec error:\n');
|
|
140
|
+
console.log('\x1b[31m%s\x1b[0m', `${cerror}\n`);
|
|
141
|
+
}
|
|
142
|
+
// reset the defaults
|
|
143
|
+
stub = dstub;
|
|
144
|
+
isRapidFail = disRapidFail;
|
|
145
|
+
isSaveMockData = disSaveMockData;
|
|
146
|
+
host = dhost;
|
|
147
|
+
username = dusername;
|
|
148
|
+
password = dpassword;
|
|
149
|
+
protocol = dprotocol;
|
|
150
|
+
port = dport;
|
|
151
|
+
sslenable = dsslenable;
|
|
152
|
+
sslinvalid = dsslinvalid;
|
|
153
|
+
replaceTestVars('test/integration/adapterTestIntegration.js');
|
|
154
|
+
return callback('done');
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Updates the unit test file and runs the script
|
|
160
|
+
*/
|
|
161
|
+
function runUnitTest(callback) {
|
|
162
|
+
let cmdPath = 'npm run test:unit';
|
|
163
|
+
console.log('\nRUNNING UNIT TESTS - THIS WILL TAKE SOME TIME AND WILL NOT PRINT UNTIL TEST IS COMPLETE!\n');
|
|
164
|
+
|
|
165
|
+
if (stderror) {
|
|
166
|
+
console.log('\nNOTE: standard error from tests is included- unless test failed, these may be expected errors:\n');
|
|
167
|
+
cmdPath += ' 2>&1';
|
|
168
|
+
} else {
|
|
169
|
+
console.log('stderr not shown');
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return execute(cmdPath, (cerror, stdout) => {
|
|
173
|
+
console.log('executed tests:\n');
|
|
174
|
+
console.log(`${stdout}\n`);
|
|
175
|
+
|
|
176
|
+
if (cerror) {
|
|
177
|
+
console.log('\x1b[31m%s\x1b[0m', '\nexec error:\n');
|
|
178
|
+
console.log('\x1b[31m%s\x1b[0m', `${cerror}\n`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return callback('done');
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// print process.argv
|
|
186
|
+
const args = process.argv.slice(2);
|
|
187
|
+
|
|
188
|
+
// go through the arguments that where provided
|
|
189
|
+
for (let a = 0; a < args.length; a += 1) {
|
|
190
|
+
if (args[a].toUpperCase() === '-H' || args[a].toUpperCase() === '--HELP') {
|
|
191
|
+
let message = '\nThis tool is used to make it easier to run integration tests.\n';
|
|
192
|
+
message += '\n';
|
|
193
|
+
message += 'Options:\n';
|
|
194
|
+
message += '-h, --help: Prints this message\n';
|
|
195
|
+
message += '-f, --failfast: Fail the test when the first test fails\n';
|
|
196
|
+
message += '-m, --mockdata: Update mock data files with the results from testing (only if running integrated)\n';
|
|
197
|
+
message += '-r, --reset: Resets the variables back to stub settings and removes credentials\n';
|
|
198
|
+
message += '-s, --stderror: Displays the standard error from the run, this can have data even if all the tests pass\n';
|
|
199
|
+
message += '-u, --unit: Runs just the unit tests as well\n';
|
|
200
|
+
console.log(message);
|
|
201
|
+
running = true;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (args[a].toUpperCase() === '-F' || args[a].toUpperCase() === '--FAILFAST') {
|
|
205
|
+
isRapidFail = true;
|
|
206
|
+
}
|
|
207
|
+
if (args[a].toUpperCase() === '-M' || args[a].toUpperCase() === '--MOCKDATA') {
|
|
208
|
+
isSaveMockData = true;
|
|
209
|
+
}
|
|
210
|
+
if (args[a].toUpperCase() === '-R' || args[a].toUpperCase() === '--RESET') {
|
|
211
|
+
running = true;
|
|
212
|
+
replaceTestVars('test/integration/adapterTestIntegration.js');
|
|
213
|
+
replaceTestVars('test/unit/adapterTestUnit.js');
|
|
214
|
+
console.log('test reset complete');
|
|
215
|
+
}
|
|
216
|
+
if (args[a].toUpperCase() === '-S' || args[a].toUpperCase() === '--STDERROR') {
|
|
217
|
+
stderror = true;
|
|
218
|
+
}
|
|
219
|
+
if (args[a].toUpperCase() === '-U' || args[a].toUpperCase() === '--UNIT') {
|
|
220
|
+
running = true;
|
|
221
|
+
runUnitTest((status) => {
|
|
222
|
+
console.log(status);
|
|
223
|
+
process.exit(1);
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (!running) {
|
|
229
|
+
// how are we running the test?
|
|
230
|
+
let answer = rl.question('\nDo you want to run the integration test integrated with the other system? (no): ');
|
|
231
|
+
if (answer && (answer.toLowerCase() === 'yes' || answer.toLowerCase() === 'y')) {
|
|
232
|
+
stub = false;
|
|
233
|
+
console.log('Need more information about the integration!');
|
|
234
|
+
} else {
|
|
235
|
+
running = true;
|
|
236
|
+
runTest((status) => {
|
|
237
|
+
console.log(status);
|
|
238
|
+
process.exit(1);
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (!running) {
|
|
243
|
+
// how are we running the test?
|
|
244
|
+
answer = rl.question('\nWhat is the dns or ip of the system you want to test with? (localhost): ');
|
|
245
|
+
if (answer) {
|
|
246
|
+
host = answer;
|
|
247
|
+
} else {
|
|
248
|
+
host = 'localhost';
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// need the username to authenticate with
|
|
252
|
+
answer = rl.question('\nWhat is the username to authenticate, if no authentication just return? (username): ');
|
|
253
|
+
if (answer) {
|
|
254
|
+
username = answer;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// need the password to authenticate with
|
|
258
|
+
answer = rl.question('\nWhat is the password to authenticate, if no authentication just return? (password): ', { hideEchoBack: true });
|
|
259
|
+
if (answer) {
|
|
260
|
+
password = answer;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// need the protocol used with other system
|
|
264
|
+
answer = rl.question('\nWhat is the protocol used to communicate with the system? (http): ');
|
|
265
|
+
if (answer) {
|
|
266
|
+
protocol = answer;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (protocol === 'https') {
|
|
270
|
+
// if protocol is https, set default port to 443
|
|
271
|
+
port = 443;
|
|
272
|
+
// need the port used with other system
|
|
273
|
+
answer = rl.question('\nWhat is the port used to communicate with the system? (443): ');
|
|
274
|
+
port = 443; // update default answer to 443 for https
|
|
275
|
+
if (answer) {
|
|
276
|
+
port = Number(answer);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// turn on ssl and accept invalid certs
|
|
280
|
+
sslenable = true;
|
|
281
|
+
sslinvalid = true;
|
|
282
|
+
runTest((status) => {
|
|
283
|
+
console.log(status);
|
|
284
|
+
process.exit(1);
|
|
285
|
+
});
|
|
286
|
+
} else {
|
|
287
|
+
// need the port used with other system
|
|
288
|
+
answer = rl.question('\nWhat is the port used to communicate with the system? (80): ');
|
|
289
|
+
if (answer) {
|
|
290
|
+
port = Number(answer);
|
|
291
|
+
}
|
|
292
|
+
runTest((status) => {
|
|
293
|
+
console.log(status);
|
|
294
|
+
process.exit(1);
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|