Skip to content

Commit

Permalink
Merge f62bf54 into 9df817d
Browse files Browse the repository at this point in the history
  • Loading branch information
Vladimir Varankin committed Mar 21, 2014
2 parents 9df817d + f62bf54 commit 2143a3e
Show file tree
Hide file tree
Showing 9 changed files with 240 additions and 12 deletions.
27 changes: 27 additions & 0 deletions .bem/borschik/istanbul.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
var path = require('path'),
environ = require('bem-environ'),
instrumenter = new (require('istanbul').Instrumenter)({ preserveComments : true }),
PRJ_ROOT = environ.PRJ_ROOT,
EXCLUDE_RE = new RegExp([
'(?:^' + environ.LIB_ROOT + ')',
'(?:\/node_modules\/)',
'(?:\.spec\.js$)'
].join('|'));

module.exports = function(borschik) {
var base = borschik.getTech('js'),
File = base.File.inherit({
processInclude : function(basePath, content) {
var filePath = this.path;
return EXCLUDE_RE.test(filePath)?
this.__base.apply(this, arguments) :
instrumenter.instrumentSync(this.__base(basePath), path.relative(PRJ_ROOT, filePath));
}
}),
Tech = base.Tech.inherit({ File : File });

return {
File : File,
Tech : Tech
};
};
30 changes: 30 additions & 0 deletions .bem/hooks/mocha-phantomjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* An "after run" hook for [mocha-phantomjs](https://github.com/metaskills/mocha-phantomjs)
* to store instrumented code coverage results to temporary buffer,
* so they could be consumed into Istanbul#Collector for future manipulations.
* @example
* $ mocha-phantomjs \
* --hooks <path/to/hook/file.js> \
* --setting coverage-file=<path/to/coverage/buffer.json>
*/
var fs = require('fs'),
sys = require('system'),
args = sys.args;

module.exports = {
afterEnd : function(reporter) {
var covData = reporter.page.evaluate(function() {
return window.__coverage__;
});

if(!covData || args.length < 3) return;

args = JSON.parse(args[3]);

var covBufferPath = args.settings['coverage-file'];
if(!covBufferPath) return;

fs.write(covBufferPath, JSON.stringify(covData), 'w');
}
};
3 changes: 2 additions & 1 deletion .bem/levels/blocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ exports.getTechs = function() {
'vanilla.js',
'browser.js',
'node.js',
'browser.js+bemhtml'
'browser.js+bemhtml',
'phantomjs'
].forEach(resolveTechs(techs, PRJ_TECHS));

return techs;
Expand Down
2 changes: 1 addition & 1 deletion .bem/levels/bundles.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ exports.baseLevelPath = require.resolve('./blocks');
exports.getTechs = function() {
var techs = this.__base();

['phantomjs', 'spec.bemjson.js'].forEach(
['spec.bemjson.js'].forEach(
this.resolveTechs(techs, BEMPR_TECHS));

return techs;
Expand Down
54 changes: 45 additions & 9 deletions .bem/make.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,14 @@ MAKE.decl('Arch', {
blocksLevelsRegexp : /^.+?\.blocks$/,
bundlesLevelsRegexp : /^.+?\.bundles$/,

libraries : [],

createCustomNodes : function(common, libs, blocks) {
createCustomNodes : function() {
var SetsNode = MAKE.getNodeClass('SetsNode');

if(typeof SetsNode.createId === 'undefined') {
return;
}

return new SetsNode({ root : this.root, arch : this.arch }).alterArch(null, libs);
return new SetsNode({ root : this.root, arch : this.arch }).alterArch();
}

});
Expand Down Expand Up @@ -120,16 +118,54 @@ MAKE.decl('ExampleNode', {
MAKE.decl('SpecNode', {

getTechs : function() {
return this.__base()
.concat([
'spec.js+browser.js+bemhtml',
'phantomjs'
]);
return [
'bemjson.js',
'bemdecl.js',
'deps.js',
'css',
'spec.js+browser.js+bemhtml',
'bemhtml',
'html',
'phantomjs'
];
},

getLevels : function() {
return this.__base.apply(this, arguments)
.concat(environ.getLibPath('bem-pr', 'spec.blocks'));
},

'create-phantomjs-node' : function() {
var arch = this.ctx.arch,
nodes = this.__base.apply(this, arguments);

function getBorchikNodeId(file) {
return PATH.join(PATH.dirname(file), '_' + PATH.basename(file));
}

['css', 'spec.js+browser.js+bemhtml'].forEach(function(tech) {
var bundlePath = this.getBundlePath(tech);
if(!arch.hasNode(bundlePath)) return;

arch
.getNode(bundlePath)
.getFiles()
.forEach(function(file) {
arch.link(getBorchikNodeId(file), nodes);
});
}, this);

return nodes;
},

'create-spec.js+browser.js+bemhtml-optimizer-node' : function(tech, sourceNode, bundleNode) {
if(process.env.ISTANBUL_COVERAGE) {
return this.createBorschikOptimizerNode(
require.resolve('./borschik/istanbul'),
sourceNode,
bundleNode);
}
return this.__base.apply(this, arguments);
}

});
Expand Down
122 changes: 122 additions & 0 deletions .bem/techs/phantomjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
var FS = require('fs'),
PATH = require('path'),
URL = require('url'),
UTIL = require('util'),
BEM = require('bem'),
exec = require('child_process').exec,
Q = BEM.require('q'),
LOGGER = BEM.logger,
MOCHA_PHANTOM_BIN = require.resolve('../../libs/bem-pr/node_modules/mocha-phantomjs/bin/mocha-phantomjs'),
MOCHA_PHANTOM_HOOK = PATH.resolve(__dirname, '../hooks/mocha-phantomjs.js'),
MOCHA_PHANTOM_REPORTER = process.env.MOCHA_PHANTOM_REPORTER || 'spec',
MOCHA_PHANTOM_MAX_COUNT = parseInt(process.env.MOCHA_PHANTOM_MAX_COUNT, 10) || 5,
phantomCount = 0,
phantomQueue = [],
NEED_COVERAGE = process.env.ISTANBUL_COVERAGE,
covCollector,
covIdx;

if(NEED_COVERAGE) {
covCollector = new (require('istanbul').Collector)();
covIdx = 0;
}

exports.API_VER = 2;

exports.techMixin = {

getDependencies : function() {
return ['html', 'spec.js'];
},

getCoverageReportDir : function() {
return this.context.opts.dir || process.cwd();
},

createByDecl : function(item, level) {
var root = this.context.opts.dir || '',
prefix = level.getByObj(item),
relPrefix = PATH.relative(root, prefix),
path = this.getPath(prefix, 'html'),
args = '--reporter ' + MOCHA_PHANTOM_REPORTER,
url = URL.format({
protocol : 'file',
host : '/',
pathname : path
}),
defer = Q.defer(),
covBuffer;

if(NEED_COVERAGE) {
covBuffer = PATH.join(root, UTIL.format(
'__coverage-%s-%s-%s.json',
relPrefix.replace(/[^A-Za-z0-9_. ]/g, '_'),
Date.now()-0,
covIdx++));

LOGGER.fdebug('Store coverage buffer for "%s" into "%s"', relPrefix, covBuffer);

args += ' --hooks ' + MOCHA_PHANTOM_HOOK;
args += ' --setting coverage-file=' + covBuffer;
}

phantomCount < MOCHA_PHANTOM_MAX_COUNT?
runMochaPhantom() :
phantomQueue.push(runMochaPhantom);

var _this = this;

function getCovData() {
var data = {},
exists = FS.existsSync(covBuffer);

LOGGER.fdebug('Coverage buffer for "%s" %s', relPrefix, exists? 'found' : 'doesn\'t exist');

if(exists) {
data = JSON.parse(FS.readFileSync(covBuffer, 'utf8'));
FS.unlinkSync(covBuffer);
}

return data;
}

function runMochaPhantom() {
phantomCount++;

exec([MOCHA_PHANTOM_BIN, args, url].join(' '), function(err, stdout, stderr) {
var passed = err === null;

LOGGER.finfo('Tests results for "%s":\n%s',
PATH.relative(root, path), stdout, stderr? '\nStderr: ' + stderr : '');

if(passed) {
defer.resolve();
if(NEED_COVERAGE) {
LOGGER.fdebug('Going to read coverage buffer for "%s"', relPrefix);
covCollector.add(getCovData());
}
} else {
LOGGER.error('Tests failed:', err);
defer.reject(err);
}

--phantomCount;

phantomQueue.length && phantomQueue.shift()();
phantomCount ||
passed && NEED_COVERAGE && _this.storeFinalCoverage();
});
}

LOGGER.finfo('[i] Page was sent to Phantom (%s)', url);

return defer.promise;
},

storeFinalCoverage : function() {
var covFile = PATH.resolve(this.getCoverageReportDir(), 'coverage.json');
LOGGER.finfo('[i] Store final coverage "%s"', covFile);
FS.writeFileSync(covFile, JSON.stringify(covCollector.getFinalCoverage()), 'utf8');
}

};
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ node_modules
/*.specs
/*.tests

/coverage
/coverage*.json
9 changes: 9 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ matrix:
allow_failures:
- node_js: "0.11"

env: ISTANBUL_COVERAGE=1

before_script:
- npm install coveralls

after_success:
- ./node_modules/.bin/istanbul report lcovonly
- cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && echo "Done!"

branches:
only:
- v1
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"jshint-groups": "0.6.0",
"jscs": "1.0.0",
"git-hooks": "0.0.3",
"bower-npm-install": "~0.5.4"
"bower-npm-install": "~0.5.4",
"istanbul": "^0.2.6"
},
"scripts": {
"lint": "jshint-groups && jscs .",
Expand Down

0 comments on commit 2143a3e

Please sign in to comment.