This repository has been archived by the owner on Feb 2, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 123
/
Copy pathprotractor_runner.js
195 lines (175 loc) · 6.14 KB
/
protractor_runner.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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/*
* grunt-protractor-runner
* https://github.com/teerapap/grunt-protractor-runner
*
* Copyright (c) 2013 Teerapap Changwichukarn
* Licensed under the MIT license.
*/
'use strict';
var util = require('util');
var path = require('path');
var fs = require('fs');
var split = require('split');
var through2 = require('through2');
module.exports = function(grunt) {
grunt.registerMultiTask('protractor', 'A grunt task to run protractor.', function() {
// '.../node_modules/protractor/lib/protractor.js'
var protractorMainPath = require.resolve('protractor');
// '.../node_modules/protractor/bin/protractor'
var protractorBinPath = path.resolve(protractorMainPath, '../../bin/protractor');
// '.../node_modules/protractor/bin/webdriver-manager'
var webdriverManagerPath = path.resolve(protractorMainPath, '../../bin/webdriver-manager');
// Merge task-specific and/or target-specific options with these defaults.
var opts = this.options({
keepAlive: false,
noColor: false,
debug: false,
nodeBin: 'node',
args: {},
output: false,
outputOptions: {},
webdriverManagerUpdate: false
});
// configFile is a special property which need not to be in options{} object.
if (!grunt.util._.isUndefined(this.data.configFile)) {
opts.configFile = this.data.configFile;
}
grunt.verbose.writeln("Options: " + util.inspect(opts));
var keepAlive = opts['keepAlive'];
var strArgs = ["seleniumAddress", "seleniumServerJar", "seleniumPort", "baseUrl", "rootElement", "browser", "chromeDriver", "chromeOnly", "directConnect", "sauceUser", "sauceKey", "sauceSeleniumAddress", "framework", "frameworkPath", "beforeLaunch", "onPrepare", "webDriverProxy"];
var listArgs = ["specs", "exclude", "suite"];
var boolArgs = ["includeStackTrace", "verbose"];
var objectArgs = ["params", "capabilities", "cucumberOpts", "mochaOpts"];
var cmd = [protractorBinPath];
if (!grunt.util._.isUndefined(opts.configFile)){
cmd.push(opts.configFile);
}
var args = process.execArgv.concat(cmd);
if (opts.noColor){
args.push('--no-jasmineNodeOpts.showColors');
}
if (!grunt.util._.isUndefined(opts.debug) && opts.debug === true){
args.splice(1,0,'debug');
}
// Iterate over all supported arguments.
strArgs.forEach(function(a) {
if (a in opts.args || grunt.option(a)) {
args.push('--'+a, grunt.option(a) || opts.args[a]);
}
});
listArgs.forEach(function(a) {
if (a in opts.args || grunt.option(a)) {
var arg = opts.args[a];
if (arg instanceof Array) {
arg = arg.join(",");
}
args.push('--'+a, grunt.option(a) || arg);
}
});
boolArgs.forEach(function(a) {
if (a in opts.args || grunt.option(a)) {
args.push('--'+a);
}
});
// Convert [object] to --[object].key1 val1 --[object].key2 val2 ....
objectArgs.forEach(function(a) {
(function convert(prefix, obj, args) {
if (typeof obj === 'string'){
obj = JSON.parse(obj);
}
for (var key in obj) {
var val = obj[key];
var type = typeof obj[key];
if (type === "object") {
if (Array.isArray(val)) {
// Add duplicates --[object].key val1 --[object].key val2 ...
for (var i=0;i<val.length;i++) {
args.push(prefix+"."+key, val[i]);
}
} else {
// Dig deeper
convert(prefix+"."+key, val, args);
}
} else if (type === "undefined" || type === "function") {
// Skip these types
} else if (type === "boolean") {
// Add --[object].key
if (val) {
args.push(prefix+"."+key);
} else {
args.push("--no"+prefix.substring(1)+"."+key);
}
} else {
// Add --[object].key value
args.push(prefix+"."+key, val);
}
}
})("--" + a, grunt.option(a) || opts.args[a], args);
});
// Spawn protractor command
var done = this.async();
var startProtractor = function(){
grunt.verbose.writeln("Spawn node with arguments: " + args.join(" "));
var child = grunt.util.spawn({
cmd: opts.nodeBin,
args: args,
opts: {
stdio:'pipe'
}
},
function(error, result, code) {
if (error) {
grunt.log.error(String(result));
if(code === 1 && keepAlive) {
// Test fails but do not want to stop the grunt process.
grunt.log.oklns("Test failed but keep the grunt process alive.");
} else {
// Test fails and want to stop the grunt process,
// or protractor exited with other reason.
grunt.warn('Tests failed, protractor exited with code: '+code, code);
}
}
done();
done = null;
}
);
try {
process.stdin.pipe(child.stdin);
}
catch (e) {
grunt.log.debug("Non-fatal: stdin cannot be piped in this shell");
}
child.stdout.pipe(process.stdout);
child.stderr.pipe(process.stderr);
// Write the result in the output file
if (!grunt.util._.isUndefined(opts.output) && opts.output !== false) {
grunt.log.writeln("Output test result to: " + opts.output);
grunt.file.mkdir(path.dirname(opts.output));
child.stdout
.pipe(split())
.pipe(through2(function (chunk, encoding, callback) {
if ((/^Using the selenium server at/).test(chunk.toString())) {
// skip
}
else {
this.push(chunk + '\n');
}
callback();
}))
.pipe(fs.createWriteStream(opts.output, opts.outputOptions));
}
};
if (opts.webdriverManagerUpdate) {
grunt.log.writeln('webdriver-manager path: ' + webdriverManagerPath);
grunt.util.spawn({
cmd: opts.nodeBin,
args: [webdriverManagerPath, 'update'],
opts: {
stdio: 'inherit'
}
}, startProtractor);
} else {
startProtractor();
}
});
};