Skip to content
This repository has been archived by the owner on Feb 2, 2019. It is now read-only.

Commit

Permalink
feat(reporting): show code coverage in build log and export json file…
Browse files Browse the repository at this point in the history
… for examples site

 - refactor site-meta task to support async tasks.
 - add "sources" array to site examples that allows connecting examples to their components and code coverage info.
  • Loading branch information
justindujardin committed Dec 24, 2015
1 parent d1933b4 commit 3b5147e
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 36 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
dist/
out/
site/
public/meta.json
public/version.json
/public/coverage.json
/public/meta.json
/public/version.json

ng2-material/**/*.css
ng2-material/**/*.css.map
Expand Down
137 changes: 108 additions & 29 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,13 +211,23 @@ module.exports = function (grunt) {
src: ['<%- sourceRoot %>/**/*.ts']
}
},
karma: {
cover: {
options: {
singleRun: true
},
configFile: './karma.conf.js',
preprocessors: {"ng2-material/**/*.js": "coverage"}
}
},
remapIstanbul: {
build: {
src: '.coverage/**/coverage-final.json',
options: {
reports: {
'html': 'coverage',
'lcovonly': '.coverage/lcov.info'
'lcovonly': '.coverage/lcov.info',
'text': 'coverage/coverage.txt'
}
}
}
Expand All @@ -231,12 +241,14 @@ module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-postcss');
grunt.loadNpmTasks('grunt-notify');
grunt.loadNpmTasks('grunt-karma');
grunt.loadNpmTasks('grunt-ts');
grunt.loadNpmTasks('dts-generator');
grunt.loadNpmTasks('remap-istanbul');
grunt.registerTask('default', ['dtsGenerator', 'site-meta', 'ts:source', 'sass', 'postcss', 'copy:styles']);
grunt.registerTask('default', ['dtsGenerator', 'ts:source', 'sass', 'postcss', 'copy:styles', 'site-meta']);
grunt.registerTask('develop', ['default', 'watch']);
grunt.registerTask('site', ['build', 'copy:site']);
grunt.registerTask('cover', ['karma:cover', 'remapIstanbul', 'site-meta']);
grunt.registerTask('site', ['build', 'cover', 'copy:site']);
grunt.registerTask('build', ['default', 'ts:release', 'dist-bundle', 'copy:release']);


Expand Down Expand Up @@ -315,57 +327,124 @@ module.exports = function (grunt) {
var path = require('path');
var util = require('util');
var meta = {};
var tasks = [];

fs.writeFileSync('public/version.json', JSON.stringify({
version: require('./package.json').version
}));
writeJson('public/version.json', require('./package.json').version);

glob("examples/components/**/*.html", function (err, files) {
files.forEach(parseDemo);
var output = prepareMeta();
fs.writeFileSync('public/meta.json', JSON.stringify(output, null, 2));
done();
tasks.push(function buildCoverage() {
// Parse Lcov report and generate `coverage.json` file for site.
var parse = require('lcov-parse');
parse('.coverage/lcov.info', function (err, data) {
if(err) {
grunt.log.ok('skipping code coverage because lcov.info is missing');
return next();
}
// Obj has "found" and "hit"
function percent(obj) {
if (obj.found === 0) {
return 100;
}
return parseFloat((obj.hit / obj.found * 100.0).toPrecision(2), 10);
}

var outMeta = data.map(function (d) {
delete d.lines.details;
delete d.functions.details;
delete d.branches.details;
delete d.title;
d.lines.percent = percent(d.lines);
d.functions.percent = percent(d.functions);
d.branches.percent = percent(d.branches);
return d;
});
writeJson('public/coverage.json', outMeta);
next();
});
});
tasks.push(function buildExamples() {
glob("examples/components/**/*.html", function (err, files) {
files.forEach(function parseDemo(templateFile) {
var name = path.basename(templateFile, '.html');
var result = {
template: templateFile
};
var sourceFile = path.join(path.dirname(templateFile), name + '.ts');
var stylesFile = path.join(path.dirname(templateFile), name + '.scss');
if (fileExists(stylesFile)) {
result.styles = stylesFile;
}
if (fileExists(sourceFile)) {
result.source = sourceFile;
}

var component = readableString(path.basename(path.dirname(templateFile)));
result.component = selectorString(component + ' ' + readableString(name));
meta[component] = meta[component] || {};
meta[component].files = [];
meta[component][readableString(name)] = result;
lintDemo(result);
});


glob("ng2-material/components/**/*.ts", function (err, files) {
files.forEach(function linkComponentsToExamples(sourceFile) {
var component = readableString(path.basename(path.dirname(sourceFile)));
if (!meta[component]) {
return;
}
meta[component].files.push(sourceFile);
});
writeJson('public/meta.json', prepareMeta());
next();
});
});
});

function parseDemo(templateFile) {
var name = path.basename(templateFile, '.html');
var result = {
template: templateFile
};
var sourceFile = path.join(path.dirname(templateFile), name + '.ts');
var stylesFile = path.join(path.dirname(templateFile), name + '.scss');
if (fileExists(stylesFile)) {
result.styles = stylesFile;
function next() {
if (tasks.length === 0) {
return done();
}
if (fileExists(sourceFile)) {
result.source = sourceFile;
var current = tasks.shift();
current();
}

return next();

// ------------------------------------------------------------------------
// Helpers and such
// ------------------------------------------------------------------------

function writeJson(to, data) {
try {
fs.writeFileSync(to, JSON.stringify(data, null, 2));
}
catch (e) {
grunt.log.fatal('failed to write (' + to + ') with error: ' + e);

var component = readableString(path.basename(path.dirname(templateFile)));
result.component = selectorString(component + ' ' + readableString(name));
meta[component] = meta[component] || {};
meta[component][readableString(name)] = result;
lintDemo(result);
}
}


// Make the metadata easier to access in angular by using arrays rather than key/value pairs.
// Store as an object internally to group examples by component.
function prepareMeta() {
var keys = Object.keys(meta);

var output = keys.map(function (key) {
return keys.map(function (key) {
var demos = meta[key];
var sources = demos.files.slice();
delete demos.files;
var demoKeys = Object.keys(demos);
return {
name: key,
sources: sources,
id: selectorString(key),
examples: demoKeys.map(function (key) {
demos[key].name = key;
return demos[key];
})
};
});
return output;
}

// Convert readable string of component + demo to a valid element name that
Expand Down
14 changes: 9 additions & 5 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ module.exports = function (config) {

var coverageDebug = false;

var coverageReporters = [
{type: 'json'},
{type: 'lcov'}
];
if (coverageDebug || process.env.TRAVIS) {
coverageReporters.push({type: 'text'});
}

config.set({
basePath: '',
frameworks: ['jasmine'],
Expand Down Expand Up @@ -43,11 +51,7 @@ module.exports = function (config) {
coverageReporter: {
dir: '.coverage',

reporters: [
// reporters not supporting the `file` property
{type: 'json'},
{type: 'lcov'}
]
reporters: coverageReporters
}
});
};
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"grunt-contrib-sass": "0.9.2",
"grunt-contrib-watch": "0.6.1",
"grunt-conventional-changelog": "5.0.0",
"grunt-karma": "0.12.1",
"grunt-notify": "0.4.3",
"grunt-npm": "0.0.2",
"grunt-postcss": "0.7.1",
Expand All @@ -49,6 +50,7 @@
"karma-coverage": "0.5.3",
"karma-firefox-launcher": "0.1.7",
"karma-jasmine": "0.2.2",
"lcov-parse": "0.0.10",
"remap-istanbul": "0.4.0",
"systemjs-builder": "justindujardin/builder.git#typescript-source-maps"
},
Expand Down

0 comments on commit 3b5147e

Please sign in to comment.