UNPKG

12.4 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'],
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 }
145 },
146
147 // compress artifacts
148 compress: {
149 main: {
150 options: {
151 archive: 'report.zip'
152 },
153 files: [
154 {src: ['report/**'], dest: '/'}
155 ]
156 }
157 }
158
159 });
160
161 // prepare files & folders for grunt:plato
162 grunt.registerTask('preparePlato', function () {
163 var fs = require('fs');
164
165 // generate dirs for docs & reports
166 ['report', 'report/complexity', 'report/complexity/files',
167 'report/complexity/files/index_js',
168 'report/complexity/files/lib_driver_js',
169 'report/complexity/files/lib_webdriver_js',
170 'report/complexity/files/lib_commands_cookie_js',
171 'report/complexity/files/lib_commands_element_js',
172 'report/complexity/files/lib_commands_execute_js',
173 'report/complexity/files/lib_commands_frame_js',
174 'report/complexity/files/lib_commands_ime_js',
175 'report/complexity/files/lib_commands_interaction_js',
176 'report/complexity/files/lib_commands_page_js',
177 'report/complexity/files/lib_commands_screenshot_js',
178 'report/complexity/files/lib_commands_session_js',
179 'report/complexity/files/lib_commands_storage_js',
180 'report/complexity/files/lib_commands_timeout_js',
181 'report/complexity/files/lib_commands_url_js',
182 'report/complexity/files/lib_commands_window_js'].forEach(function (path) {
183 if (!fs.existsSync(__dirname + '/' + path)) {
184 fs.mkdirSync(__dirname + '/' + path);
185 }
186 });
187
188 // store some dummy reports, so that grunt plato doesnt complain
189 ['report.history.json',
190 'files/index_js/report.history.json',
191 'files/lib_driver_js/report.history.json',
192 'files/lib_webdriver_js/report.history.json',
193 'files/lib_commands_cookie_js/report.history.json',
194 'files/lib_commands_element_js/report.history.json',
195 'files/lib_commands_execute_js/report.history.json',
196 'files/lib_commands_frame_js/report.history.json',
197 'files/lib_commands_ime_js/report.history.json',
198 'files/lib_commands_interaction_js/report.history.json',
199 'files/lib_commands_page_js/report.history.json',
200 'files/lib_commands_screenshot_js/report.history.json',
201 'files/lib_commands_session_js/report.history.json',
202 'files/lib_commands_storage_js/report.history.json',
203 'files/lib_commands_timeout_js/report.history.json',
204 'files/lib_commands_url_js/report.history.json',
205 'files/lib_commands_window_js/report.history.json'].forEach(function (file) {
206 if (!fs.existsSync(__dirname + '/report/complexity/' + file)) {
207 fs.writeFileSync(__dirname + '/report/complexity/' + file, '{}');
208 }
209 });
210 });
211
212 // prepare files & folders for coverage
213 grunt.registerTask('prepareCoverage', function () {
214 var fs = require('fs');
215
216 // generate folders
217 ['coverage', 'report', 'report/coverage'].forEach(function (folder) {
218 if (!fs.existsSync(__dirname + '/' + folder)) {
219 fs.mkdirSync(__dirname + '/' + folder);
220 }
221 });
222
223 // generate code coverage helper file
224 var coverageHelper = 'require("blanket")({pattern: [require("fs").realpathSync(__dirname + "/../index.js"), require("fs").realpathSync(__dirname + "/../lib/")]});';
225 if (!fs.existsSync(__dirname + '/coverage/blanket.js')) {
226 fs.writeFileSync(__dirname + '/coverage/blanket.js', coverageHelper);
227 }
228 });
229
230 // generates a coverage badge
231 grunt.registerTask('generateCoverageBadge', function () {
232 var fs = require('fs');
233 if (fs.existsSync(__dirname + '/node_modules/coverage-badge')) {
234 if (fs.existsSync(__dirname + '/report/coverage/coverage.json')) {
235 var green = [147,188,59];
236 var yellow = [166,157,0];
237 var red = [189,0,2];
238
239 var getColor = function (coverage) {
240 if (coverage > 90) {
241 return mixColors(yellow, green, (coverage-90)/10);
242 }
243
244 if (coverage > 80) {
245 return mixColors(red, yellow, (coverage-80)/10);
246 }
247
248 return createColor(red);
249 };
250
251 var mixColors = function (from, to, ratio) {
252 var result = [], i;
253 for (i=0; i<3; i++) {
254 result[i] = Math.round(from[i] + (ratio * (to[i]-from[i])));
255 }
256 return createColor(result);
257 };
258
259 var createColor = function (values) {
260 return 'rgba('+values[0]+','+values[1]+','+values[2]+',1)';
261 };
262
263 var Badge = require(__dirname + '/node_modules/coverage-badge/lib/Badge.js');
264 var badgeFn = function(coverage) {
265 coverage = Math.floor(Number(coverage));
266 var badge = new Badge({
267 box_color: getColor(coverage),
268 box_text: coverage+'%',
269 label_text: 'cov',
270 height: 18,
271 width: 49,
272 box_width: 25,
273 rounding: 0,
274 padding: 0,
275 label_font: '7pt DejaVu Sans',
276 box_font: 'bold 7pt DejaVu Sans'
277 });
278 return badge.stream();
279 };
280
281 var coverage = JSON.parse(fs.readFileSync(__dirname + '/report/coverage/coverage.json')).coverage;
282 var file = fs.createWriteStream(__dirname + '/report/coverage/coverage.png');
283 badgeFn(coverage).pipe(file);
284 }
285 }
286 });
287
288 // archives the docs if a new version appears
289 grunt.registerTask('archive', function () {
290 var done = this.async();
291 grunt.util.spawn({cmd: 'git', args: ['describe', '--abbrev=0', '--tags']}, function (error, result) {
292 var lastTag = result.toString();
293 if (grunt.file.isFile('_raw/docs/' + lastTag + '/webdriver.html')) {
294 grunt.log.ok('Nothing to archive');
295 done();
296 return true;
297 }
298
299 if (!grunt.file.isDir('_raw/docs/' + lastTag)) {
300 grunt.file.mkdir('_raw/docs/' + lastTag);
301 }
302
303 grunt.file.copy('report/docs/webdriver.html', '_raw/docs/' + lastTag + '/webdriver.html');
304 grunt.log.ok('Archived document with version: ' + lastTag);
305 done();
306 });
307 });
308
309 // releases a new canary build
310 grunt.registerTask('release-canary', function () {
311 var done = this.async();
312 var pkg = grunt.config.get('pkg');
313 var canaryPkg = grunt.util._.clone(pkg);
314
315 Object.keys(canaryPkg.dependencies).forEach(function (pack) {
316 if (pack.search('dalek') !== -1) {
317 delete canaryPkg.dependencies[pack];
318 canaryPkg.dependencies[pack + '-canary'] = 'latest';
319 }
320 });
321
322 canaryPkg.name = canaryPkg.name + '-canary';
323 canaryPkg.version = canaryPkg.version + '-' + grunt.template.today('yyyy-mm-dd-HH-MM-ss');
324
325 grunt.file.write('package.json', JSON.stringify(canaryPkg, true, 2));
326
327 var npm = require('npm');
328 npm.load({}, function() {
329 npm.registry.adduser(process.env.npmuser, process.env.npmpass, process.env.npmmail, function(err) {
330 if (err) {
331 grunt.log.error(err);
332 grunt.file.write('package.json', JSON.stringify(pkg, true, 2));
333 done(false);
334 } else {
335 npm.config.set('email', process.env.npmmail, 'user');
336 npm.commands.publish([], function(err) {
337 grunt.file.write('package.json', JSON.stringify(pkg, true, 2));
338 grunt.log.ok('Published canary build to registry');
339 done(!err);
340 });
341 }
342 });
343 });
344 });
345
346 // release a new version
347 grunt.registerTask('release-package', function () {
348 var done = this.async();
349 var http = require('http');
350 var pkg = grunt.config.get('pkg');
351 var body = '';
352
353 http.get('http://registry.npmjs.org/' + pkg.name, function(res) {
354 res.on('data', function (data) {
355 body += data;
356 });
357
358 res.on('end', function () {
359 var versions = grunt.util._.pluck(JSON.parse(body).versions, 'version');
360 var currVersion = parseInt(pkg.version.replace(/\./gi, ''), 10);
361 var availableVersions = versions.map(function (version) {
362 return parseInt(version.replace(/\./gi, ''), 10);
363 });
364
365 if (!grunt.util._.contains(availableVersions, currVersion)) {
366 var npm = require('npm');
367 npm.load({}, function() {
368 npm.registry.adduser(process.env.npmuser, process.env.npmpass, process.env.npmmail, function(err) {
369 if (err) {
370 grunt.log.error(err);
371 done(false);
372 } else {
373 npm.config.set('email', process.env.npmmail, 'user');
374 npm.commands.publish([], function(err) {
375 grunt.log.ok('Released new version: ', pkg.version);
376 done(!err);
377 });
378 }
379 });
380 });
381 } else {
382 done();
383 }
384 });
385 });
386 });
387
388 // load 3rd party tasks
389 require('load-grunt-tasks')(grunt);
390
391 // define runner tasks
392 grunt.registerTask('lint', 'jshint');
393 grunt.registerTask('test', ['clean:coverage', 'prepareCoverage', 'concurrent:test', 'generateCoverageBadge']);
394 grunt.registerTask('docs', ['clean:reportZip', 'clean:report', 'preparePlato', 'concurrent:docs', 'includereplace', 'compress']);
395 grunt.registerTask('all', ['clean', 'test', 'docs']);
396};