forked from postmanlabs/newman
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest-integration.js
executable file
·154 lines (134 loc) · 5.99 KB
/
test-integration.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/env node
require('shelljs/global');
require('colors');
var fs = require('fs'),
_ = require('lodash'),
pathUtils = require('path'),
async = require('async'),
recursive = require('recursive-readdir'),
newman = require(pathUtils.join(__dirname, '..', 'index')),
echoServer = require('./server').createRawEchoServer(),
redirectServer = require('./server').createRedirectServer(),
LOCAL_TEST_ECHO_PORT = 4041,
LOCAL_TEST_REDIRECT_PORT = 4042,
/**
* The source directory containing integration test collections and folders.
*
* @type {String}
*/
SPEC_SOURCE_DIR = './test/integration';
module.exports = function (exit) {
// banner line
console.info('Running integration tests using local newman as node module...'.yellow.bold);
async.waterfall([
/**
* Fetch all files within SPEC_SOURCE_DIR.
*
* @param {Function} next - A callback function that is invoked after the files have been fetched.
* @returns {*}
*/
function (next) {
recursive(SPEC_SOURCE_DIR, next);
},
/**
* Ensures that we proceed only if files exist and has appropriate name conventions.
*
* @param {Array} files - An array of strings, each of which represents the path to an integration test file.
* @param {Function} next - A callback function whose invocation marks the end of the file processing routine.
* @returns {*}
*/
function (files, next) {
next(null, _.reduce(files, function (suites, path) {
// regex: [0:path, 1:test, 2:syntax, 3:skipped, 4: file-format]
var parts = path.match(/(.+)\.postman_([^.]+)(\.skip)?\.([^.]{3,})$/i);
if (!parts) { // if a spec file did not match the pattern, log warning and move on
return (console.warn(` - ignored: ${path}`.gray), suites);
}
else if (parts[3]) { // do not parse skipped files
return (console.warn(` - skipped: ${path}`.cyan), suites);
}
// add the test to the tracking object
(suites[parts[1]] || (suites[parts[1]] = {
name: parts[1]
}))[`${parts[2]}${parts[4].toUpperCase()}`] = path;
return suites;
}, {}));
},
/**
* Start local server used in collections
* - echoServer = custom HTTP method, body with GET
* - redirectServer = protocol profile behavior
*
* @param {Object} suites - An set of tests, arranged by test group names as keys.
* @param {Function} next - A callback function whose invocation marks the end of the integration test run.
* @returns {*}
*/
function (suites, next) {
// start echoServer first
echoServer.listen(LOCAL_TEST_ECHO_PORT, function (err) {
if (err) { return next(err); }
// start redirectServer once echoServer is started
redirectServer.listen(LOCAL_TEST_REDIRECT_PORT, function (err) {
next(err, suites);
});
});
},
/**
* Execute each integration test suite using newman.
*
* @param {Object} suites - An set of tests, arranged by test group names as keys.
* @param {Function} next - A callback function whose invocation marks the end of the integration test run.
* @returns {*}
*/
function (suites, next) {
if (_.isEmpty(suites)) { // if no test files found, it is an error
return next(new Error(`No test files found in ${SPEC_SOURCE_DIR}`));
}
console.info(`\nexecuting ${Object.keys(suites).length} tests in parallel (might take a while)...\n`);
// run tests using the consolidated test set as a guide
async.mapLimit(suites, 10, function (test, next) {
console.info(` - ${test.name}`);
// load configuration JSON object if it is provided. We do this since this is not part of newman
// standard API
var config = test.configJSON ? JSON.parse(fs.readFileSync(test.configJSON).toString()) : {};
newman.run(_.merge({
collection: test.collectionJSON,
environment: test.environmentJSON,
globals: test.globalsJSON,
iterationData: test.dataCSV || test.dataJSON,
abortOnFailure: true
}, config.run), function (err, summary) {
err && (err.source = test); // store the meta in error
next(err, summary);
});
}, next);
}
],
/**
* The integration test exit handler. Receives the error (if at all) from the integration test runner and exits
* accordingly, displaying either a success message or an error message and it's corresponding stacktrace.
*
* @param {?Error} err - An object that is either null or a standard error object.
* @param {Array} results - An array of integration test result objects, one per integration test collection run.
* @returns {*}
*/
function (err, results) {
if (!err) {
console.info(`\n${results.length} integrations ok!\n`.green);
}
else {
console.error('\nintegration test failed:'.red);
console.error(_.omit(err, ['stacktrace', 'stack']), { colors: true });
}
// destroy echoServer
echoServer.destroy(function () {
// destroy redirectServer
redirectServer.destroy(function () {
// exit once both the local server are stopped
exit(err || process.exitCode ? 1 : 0, results);
});
});
});
};
// ensure we run this script exports if this is a direct stdin.tty run
!module.parent && module.exports(exit);