UNPKG

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