UNPKG

12.5 kBJavaScriptView Raw
1/* jshint camelcase: false */
2module.exports = function (grunt) {
3 'use strict';
4
5 // check task runtime
6 require('time-grunt')(grunt);
7
8 grunt.initConfig({
9
10 // load module meta data
11 pkg: grunt.file.readJSON('package.json'),
12
13 // define a src set of files for other tasks
14 src: {
15 lint: ['Gruntfile.js', 'index.js', 'lib/**/*.js', 'test/*.js'],
16 complexity: ['index.js', 'lib/*.js', 'lib/comands/*.js'],
17 test: ['test/*.js'],
18 src: ['index.js', 'lib/**/*.js']
19 },
20
21 // clean automatically generated helper files & docs
22 clean: {
23 coverage: ['coverage', 'report/coverage'],
24 report: ['report/complexity', 'report/api', 'report/docs'],
25 reportZip: ['report.zip']
26 },
27
28 // speed up build by defining concurrent tasks
29 concurrent: {
30 test: ['lint', 'mochaTest', 'complexity'],
31 docs: ['plato', 'documantix', 'yuidoc']
32 },
33
34 // linting
35 jshint: {
36 options: {
37 jshintrc: '.jshintrc'
38 },
39 all: '<%= src.lint %>'
40 },
41
42 // testing
43 mochaTest: {
44 test: {
45 options: {
46 reporter: 'spec',
47 require: 'coverage/blanket'
48 },
49 src: '<%= src.test %>'
50 },
51 coverage: {
52 options: {
53 reporter: 'html-cov',
54 quiet: true,
55 captureFile: 'report/coverage/index.html'
56 },
57 src: '<%= src.test %>'
58 },
59 jsoncoverage: {
60 options: {
61 reporter: 'json-cov',
62 quiet: true,
63 captureFile: 'report/coverage/coverage.json'
64 },
65 src: '<%= src.test %>'
66 }
67 },
68
69 // code metrics
70 complexity: {
71 generic: {
72 src: '<%= src.complexity %>',
73 options: {
74 cyclomatic: 10,
75 halstead: 23,
76 maintainability: 70
77 }
78 }
79 },
80 plato: {
81 generic: {
82 options : {
83 jshint : grunt.file.readJSON('.jshintrc')
84 },
85 files: {
86 'report/complexity': '<%= src.complexity %>',
87 }
88 }
89 },
90
91 // api docs
92 yuidoc: {
93 compile: {
94 name: '<%= pkg.name %>',
95 description: '<%= pkg.description %>',
96 version: '<%= pkg.version %>',
97 url: '<%= pkg.homepage %>',
98 options: {
99 paths: '.',
100 outdir: 'report/api'
101 }
102 }
103 },
104
105 // user docs
106 documantix: {
107 options: {
108 header: 'dalekjs/dalekjs.com/master/assets/header.html',
109 footer: 'dalekjs/dalekjs.com/master/assets/footer.html',
110 target: 'report/docs',
111 vars: {
112 title: 'DalekJS - Documentation - Webdriver',
113 desc: 'DalekJS - Documentation - Webdriver',
114 docs: true
115 }
116 },
117 src: ['index.js']
118 },
119
120 // add current timestamp to the html document
121 includereplace: {
122 dist: {
123 options: {
124 globals: {
125 timestamp: '<%= grunt.template.today("dddd, mmmm dS, yyyy, h:MM:ss TT") %>'
126 },
127 },
128 src: 'report/docs/*.html',
129 dest: '.'
130 }
131 },
132
133 // up version, tag & commit
134 bump: {
135 options: {
136 files: ['package.json'],
137 commit: true,
138 commitMessage: 'Release v%VERSION%',
139 commitFiles: ['package.json'],
140 createTag: true,
141 tagName: '%VERSION%',
142 tagMessage: '%VERSION%',
143 push: true,
144 pushTo: 'git@github.com:dalekjs/dalek-internal-webdriver.git'
145 }
146 },
147
148 // compress artifacts
149 compress: {
150 main: {
151 options: {
152 archive: 'report.zip'
153 },
154 files: [
155 {src: ['report/**'], dest: '/'}
156 ]
157 }
158 }
159
160 });
161
162 // prepare files & folders for grunt:plato
163 grunt.registerTask('preparePlato', function () {
164 var fs = require('fs');
165
166 // generate dirs for docs & reports
167 ['report', 'report/complexity', 'report/complexity/files',
168 'report/complexity/files/index_js',
169 'report/complexity/files/lib_driver_js',
170 'report/complexity/files/lib_webdriver_js',
171 'report/complexity/files/lib_commands_cookie_js',
172 'report/complexity/files/lib_commands_element_js',
173 'report/complexity/files/lib_commands_execute_js',
174 'report/complexity/files/lib_commands_frame_js',
175 'report/complexity/files/lib_commands_ime_js',
176 'report/complexity/files/lib_commands_interaction_js',
177 'report/complexity/files/lib_commands_page_js',
178 'report/complexity/files/lib_commands_screenshot_js',
179 'report/complexity/files/lib_commands_session_js',
180 'report/complexity/files/lib_commands_storage_js',
181 'report/complexity/files/lib_commands_timeout_js',
182 'report/complexity/files/lib_commands_url_js',
183 'report/complexity/files/lib_commands_window_js'].forEach(function (path) {
184 if (!fs.existsSync(__dirname + '/' + path)) {
185 fs.mkdirSync(__dirname + '/' + path);
186 }
187 });
188
189 // store some dummy reports, so that grunt plato doesnt complain
190 ['report.history.json',
191 'files/index_js/report.history.json',
192 'files/lib_driver_js/report.history.json',
193 'files/lib_webdriver_js/report.history.json',
194 'files/lib_commands_cookie_js/report.history.json',
195 'files/lib_commands_element_js/report.history.json',
196 'files/lib_commands_execute_js/report.history.json',
197 'files/lib_commands_frame_js/report.history.json',
198 'files/lib_commands_ime_js/report.history.json',
199 'files/lib_commands_interaction_js/report.history.json',
200 'files/lib_commands_page_js/report.history.json',
201 'files/lib_commands_screenshot_js/report.history.json',
202 'files/lib_commands_session_js/report.history.json',
203 'files/lib_commands_storage_js/report.history.json',
204 'files/lib_commands_timeout_js/report.history.json',
205 'files/lib_commands_url_js/report.history.json',
206 'files/lib_commands_window_js/report.history.json'].forEach(function (file) {
207 if (!fs.existsSync(__dirname + '/report/complexity/' + file)) {
208 fs.writeFileSync(__dirname + '/report/complexity/' + file, '{}');
209 }
210 });
211 });
212
213 // prepare files & folders for coverage
214 grunt.registerTask('prepareCoverage', function () {
215 var fs = require('fs');
216
217 // generate folders
218 ['coverage', 'report', 'report/coverage'].forEach(function (folder) {
219 if (!fs.existsSync(__dirname + '/' + folder)) {
220 fs.mkdirSync(__dirname + '/' + folder);
221 }
222 });
223
224 // generate code coverage helper file
225 var coverageHelper = 'require("blanket")({pattern: [require("fs").realpathSync(__dirname + "/../index.js"), require("fs").realpathSync(__dirname + "/../lib/")]});';
226 if (!fs.existsSync(__dirname + '/coverage/blanket.js')) {
227 fs.writeFileSync(__dirname + '/coverage/blanket.js', coverageHelper);
228 }
229 });
230
231 // generates a coverage badge
232 grunt.registerTask('generateCoverageBadge', function () {
233 var fs = require('fs');
234 if (fs.existsSync(__dirname + '/node_modules/coverage-badge')) {
235 if (fs.existsSync(__dirname + '/report/coverage/coverage.json')) {
236 var green = [147,188,59];
237 var yellow = [166,157,0];
238 var red = [189,0,2];
239
240 var getColor = function (coverage) {
241 if (coverage > 90) {
242 return mixColors(yellow, green, (coverage-90)/10);
243 }
244
245 if (coverage > 80) {
246 return mixColors(red, yellow, (coverage-80)/10);
247 }
248
249 return createColor(red);
250 };
251
252 var mixColors = function (from, to, ratio) {
253 var result = [], i;
254 for (i=0; i<3; i++) {
255 result[i] = Math.round(from[i] + (ratio * (to[i]-from[i])));
256 }
257 return createColor(result);
258 };
259
260 var createColor = function (values) {
261 return 'rgba('+values[0]+','+values[1]+','+values[2]+',1)';
262 };
263
264 var Badge = require(__dirname + '/node_modules/coverage-badge/lib/Badge.js');
265 var badgeFn = function(coverage) {
266 coverage = Math.floor(Number(coverage));
267 var badge = new Badge({
268 box_color: getColor(coverage),
269 box_text: coverage+'%',
270 label_text: 'cov',
271 height: 18,
272 width: 49,
273 box_width: 25,
274 rounding: 0,
275 padding: 0,
276 label_font: '7pt DejaVu Sans',
277 box_font: 'bold 7pt DejaVu Sans'
278 });
279 return badge.stream();
280 };
281
282 var coverage = JSON.parse(fs.readFileSync(__dirname + '/report/coverage/coverage.json')).coverage;
283 var file = fs.createWriteStream(__dirname + '/report/coverage/coverage.png');
284 badgeFn(coverage).pipe(file);
285 }
286 }
287 });
288
289 // archives the docs if a new version appears
290 grunt.registerTask('archive', function () {
291 var done = this.async();
292 grunt.util.spawn({cmd: 'git', args: ['describe', '--abbrev=0', '--tags']}, function (error, result) {
293 var lastTag = result.toString();
294 if (grunt.file.isFile('_raw/docs/' + lastTag + '/webdriver.html')) {
295 grunt.log.ok('Nothing to archive');
296 done();
297 return true;
298 }
299
300 if (!grunt.file.isDir('_raw/docs/' + lastTag)) {
301 grunt.file.mkdir('_raw/docs/' + lastTag);
302 }
303
304 grunt.file.copy('report/docs/webdriver.html', '_raw/docs/' + lastTag + '/webdriver.html');
305 grunt.log.ok('Archived document with version: ' + lastTag);
306 done();
307 });
308 });
309
310 // releases a new canary build
311 grunt.registerTask('release-canary', function () {
312 var done = this.async();
313 var pkg = grunt.config.get('pkg');
314 var canaryPkg = grunt.util._.clone(pkg);
315
316 Object.keys(canaryPkg.dependencies).forEach(function (pack) {
317 if (pack.search('dalek') !== -1) {
318 delete canaryPkg.dependencies[pack];
319 canaryPkg.dependencies[pack + '-canary'] = 'latest';
320 }
321 });
322
323 canaryPkg.name = canaryPkg.name + '-canary';
324 canaryPkg.version = canaryPkg.version + '-' + grunt.template.today('yyyy-mm-dd-HH-MM-ss');
325
326 grunt.file.write('package.json', JSON.stringify(canaryPkg, true, 2));
327
328 var npm = require('npm');
329 npm.load({}, function() {
330 npm.registry.adduser(process.env.npmuser, process.env.npmpass, process.env.npmmail, function(err) {
331 if (err) {
332 grunt.log.error(err);
333 grunt.file.write('package.json', JSON.stringify(pkg, true, 2));
334 done(false);
335 } else {
336 npm.config.set('email', process.env.npmmail, 'user');
337 npm.commands.publish([], function(err) {
338 grunt.file.write('package.json', JSON.stringify(pkg, true, 2));
339 grunt.log.ok('Published canary build to registry');
340 done(!err);
341 });
342 }
343 });
344 });
345 });
346
347 // release a new version
348 grunt.registerTask('release-package', function () {
349 var done = this.async();
350 var http = require('http');
351 var pkg = grunt.config.get('pkg');
352 var body = '';
353
354 http.get('http://registry.npmjs.org/' + pkg.name, function(res) {
355 res.on('data', function (data) {
356 body += data;
357 });
358
359 res.on('end', function () {
360 var versions = grunt.util._.pluck(JSON.parse(body).versions, 'version');
361 var currVersion = parseInt(pkg.version.replace(/\./gi, ''), 10);
362 var availableVersions = versions.map(function (version) {
363 return parseInt(version.replace(/\./gi, ''), 10);
364 });
365
366 if (!grunt.util._.contains(availableVersions, currVersion)) {
367 var npm = require('npm');
368 npm.load({}, function() {
369 npm.registry.adduser(process.env.npmuser, process.env.npmpass, process.env.npmmail, function(err) {
370 if (err) {
371 grunt.log.error(err);
372 done(false);
373 } else {
374 npm.config.set('email', process.env.npmmail, 'user');
375 npm.commands.publish([], function(err) {
376 grunt.log.ok('Released new version: ', pkg.version);
377 done(!err);
378 });
379 }
380 });
381 });
382 } else {
383 done();
384 }
385 });
386 });
387 });
388
389 // load 3rd party tasks
390 require('load-grunt-tasks')(grunt);
391
392 // define runner tasks
393 grunt.registerTask('lint', 'jshint');
394 grunt.registerTask('test', ['clean:coverage', 'prepareCoverage', 'concurrent:test', 'generateCoverageBadge']);
395 grunt.registerTask('docs', ['clean:reportZip', 'clean:report', 'preparePlato', 'concurrent:docs', 'includereplace', 'compress']);
396 grunt.registerTask('all', ['clean', 'test', 'docs']);
397};