package/package.json000644 000765 000024 0000003225 13163212372013017 0ustar00000000 000000 { "name": "coveralls", "description": "takes json-cov output into stdin and POSTs to coveralls.io", "keywords": [ "coverage", "coveralls" ], "version": "3.0.0", "bugs": { "url": "https://github.com/nickmerwin/node-coveralls/issues" }, "scripts": { "test": "snyk test && make test" }, "bin": { "coveralls": "./bin/coveralls.js" }, "maintainers": [ "Nick Merwin (https://coveralls.io)" ], "contributors": [ "Gregg Caines (http://caines.ca)", "Joshua Ma (http://joshma.com)", "Alan Gutierrez (http://www.prettyrobots.com/)", "Kir Belevich (https://github.com/svg)", "elliotcable (http://elliottcable.name/)", "Slotos (http://slotos.net)", "mattjmorrison (http://mattjmorrison.com)", "Arpad Borsos (http://swatinem.de/)", "Adam Moss (https://github.com/adam-moss)" ], "dependencies": { "js-yaml": "^3.6.1", "lcov-parse": "^0.0.10", "log-driver": "^1.2.5", "minimist": "^1.2.0", "request": "^2.79.0" }, "devDependencies": { "istanbul": "^0.4.5", "jshint": "2.9.3", "mocha": "^3.2.0", "mocha-lcov-reporter": "^1.2.0", "should": "^9.0.2", "sinon-restore": "^1.0.1", "snyk": "^1.23.3" }, "engines": { "node": ">=4.0.0" }, "main": "index.js", "directories": { "test": "test" }, "repository": { "type": "git", "url": "git://github.com/nickmerwin/node-coveralls.git" }, "author": "Gregg Caines", "license": "BSD-2-Clause" } package/.npmignore000644 000765 000024 0000000122 13163045624012525 0ustar00000000 000000 node_modules/ coverage/ lib-cov/ coverage.json npm-debug.log # Webstorm IDE .ideapackage/README.md000644 000765 000024 0000016250 13163045624012016 0ustar00000000 000000 # node-coveralls [![Build Status][travis-image]][travis-url] [![Coverage Status][coveralls-image]][coveralls-url] [![Known Vulnerabilities](https://snyk.io/test/github/nickmerwin/node-coveralls/badge.svg)](https://snyk.io/test/github/nickmerwin/node-coveralls) [Coveralls.io](https://coveralls.io/) support for node.js. Get the great coverage reporting of coveralls.io and add a cool coverage button ( like the one above ) to your README. Supported CI services: [travis-ci](https://travis-ci.org/), [codeship](https://www.codeship.io/), [circleci](https://circleci.com/), [jenkins](http://jenkins-ci.org/), [Gitlab CI](http://gitlab.com/) ## Installation: Add the latest version of `coveralls` to your package.json: ``` npm install coveralls --save-dev ``` If you're using mocha, add `mocha-lcov-reporter` to your package.json: ``` npm install mocha-lcov-reporter --save-dev ``` ## Usage: This script ( `bin/coveralls.js` ) can take standard input from any tool that emits the lcov data format (including [mocha](http://mochajs.org/)'s [LCov reporter](https://npmjs.org/package/mocha-lcov-reporter)) and send it to coveralls.io to report your code coverage there. Once your app is instrumented for coverage, and building, you need to pipe the lcov output to `./node_modules/coveralls/bin/coveralls.js`. This library currently supports [travis-ci](https://travis-ci.org/) with no extra effort beyond piping the lcov output to coveralls. However, if you're using a different build system, there are a few environment variables that are necessary: * COVERALLS_SERVICE_NAME (the name of your build system) * COVERALLS_REPO_TOKEN (the secret repo token from coveralls.io) There are optional environment variables for other build systems as well: * COVERALLS_SERVICE_JOB_ID (an id that uniquely identifies the build job) * COVERALLS_RUN_AT (a date string for the time that the job ran. RFC 3339 dates work. This defaults to your build system's date/time if you don't set it.) * COVERALLS_PARALLEL (more info here: https://coveralls.zendesk.com/hc/en-us/articles/203484329) ### [Mocha](http://mochajs.org/) + [Blanket.js](https://github.com/alex-seville/blanket) - Install [blanket.js](http://blanketjs.org/) - Configure blanket according to [docs](https://github.com/alex-seville/blanket/blob/master/docs/getting_started_node.md). - Run your tests with a command like this: ```sh NODE_ENV=test YOURPACKAGE_COVERAGE=1 ./node_modules/.bin/mocha \ --require blanket \ --reporter mocha-lcov-reporter | ./node_modules/coveralls/bin/coveralls.js ``` ### [Mocha](http://mochajs.org/) + [JSCoverage](https://github.com/fishbar/jscoverage) Instrumenting your app for coverage is probably harder than it needs to be (read [here](http://www.seejohncode.com/2012/03/13/setting-up-mocha-jscoverage/)), but that's also a necessary step. In mocha, if you've got your code instrumented for coverage, the command for a travis build would look something like this: ```sh YOURPACKAGE_COVERAGE=1 ./node_modules/.bin/mocha test -R mocha-lcov-reporter | ./node_modules/coveralls/bin/coveralls.js ``` Check out an example [Makefile](https://github.com/cainus/urlgrey/blob/master/Makefile) from one of my projects for an example, especially the test-coveralls build target. Note: Travis runs `npm test`, so whatever target you create in your Makefile must be the target that `npm test` runs (This is set in package.json's 'scripts' property). ### [Istanbul](https://github.com/gotwarlost/istanbul) **With Mocha:** ```sh istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage ``` **With Jasmine:** ```sh istanbul cover jasmine-node --captureExceptions spec/ && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage ``` ### [Nodeunit](https://github.com/caolan/nodeunit) + [JSCoverage](https://github.com/fishbar/jscoverage) Depend on nodeunit, jscoverage and coveralls: ```sh npm install nodeunit jscoverage coveralls --save-dev ``` Add a coveralls script to "scripts" in your `package.json`: ```javascript "scripts": { "test": "nodeunit test", "coveralls": "jscoverage lib && YOURPACKAGE_COVERAGE=1 nodeunit --reporter=lcov test | coveralls" } ``` Ensure your app requires instrumented code when `process.env.YOURPACKAGE_COVERAGE` variable is defined. Run your tests with a command like this: ```sh npm run coveralls ``` For detailed instructions on requiring instrumented code, running on Travis and submitting to coveralls [see this guide](https://github.com/alanshaw/nodeunit-lcov-coveralls-example). ### [Poncho](https://github.com/deepsweet/poncho) Client-side JS code coverage using [PhantomJS](https://github.com/ariya/phantomjs), [Mocha](http://mochajs.org/) and [Blanket](https://github.com/alex-seville/blanket): - [Configure](http://mochajs.org/#running-mocha-in-the-browser) Mocha for browser - [Mark](https://github.com/deepsweet/poncho#usage) target script(s) with `data-cover` html-attribute - Run your tests with a command like this: ```sh ./node_modules/.bin/poncho -R lcov test/test.html | ./node_modules/coveralls/bin/coveralls.js ``` ### [Lab](https://github.com/hapijs/lab) ```sh lab -r lcov | ./node_modules/.bin/coveralls ``` ### [nyc](https://github.com/bcoe/nyc) works with almost any testing framework. Simply execute `npm test` with the `nyc` bin followed by running its reporter: ``` nyc npm test && nyc report --reporter=text-lcov | coveralls ``` ### [TAP](https://github.com/isaacs/node-tap) Simply run your tap tests with the `COVERALLS_REPO_TOKEN` environment variable set and tap will automatically use `nyc` to report coverage to coveralls. ### Command Line Parameters Usage: coveralls.js [-v] filepath #### Optional arguments: -v, --verbose filepath - optionally defines the base filepath of your source files. ## Running locally If you're running locally, you must have a `.coveralls.yml` file, as documented in [their documentation](https://coveralls.io/docs/ruby), with your `repo_token` in it; or, you must provide a `COVERALLS_REPO_TOKEN` environment-variable on the command-line. If you want to send commit data to coveralls, you can set the `COVERALLS_GIT_COMMIT` environment-variable to the commit hash you wish to reference. If you don't want to use a hash, you can set it to `HEAD` to supply coveralls with the latest commit data. This requires git to be installed and executable on the current PATH. [travis-image]: https://travis-ci.org/nickmerwin/node-coveralls.svg?branch=master [travis-url]: https://travis-ci.org/nickmerwin/node-coveralls [coveralls-image]: https://coveralls.io/repos/nickmerwin/node-coveralls/badge.svg?branch=master&service=github [coveralls-url]: https://coveralls.io/github/nickmerwin/node-coveralls?branch=master ## Contributing I generally don't accept pull requests that are untested, or break the build, because I'd like to keep the quality high (this is a coverage tool afterall!). I also don't care for "soft-versioning" or "optimistic versioning" (dependencies that have ^, x, > in them, or anything other than numbers and dots). There have been too many problems with bad semantic versioning in dependencies, and I'd rather have a solid library than a bleeding edge one. package/index.js000644 000765 000024 0000001216 13163045624012200 0ustar00000000 000000 var minimist = require('minimist'); // this needs to go before the other require()s so that // the other files can already use index.options exports.options = minimist(process.argv.slice(2), { boolean: ['verbose', 'stdout'], alias: { 'v': 'verbose', 's': 'stdout' } }); var dir = './lib/'; exports.convertLcovToCoveralls = require(dir + 'convertLcovToCoveralls'); exports.sendToCoveralls = require(dir + 'sendToCoveralls'); exports.getBaseOptions = require(dir + 'getOptions').getBaseOptions; exports.getOptions = require(dir + 'getOptions').getOptions; exports.handleInput = require(dir + 'handleInput'); exports.logger = require(dir + 'logger'); package/fixtures/istanbul.lcov000644 000765 000024 0000003270 13163045624015114 0ustar00000000 000000 TN: SF:/Users/deepsweet/Dropbox/projects/svgo/lib/svgo/config.js FN:14,(anonymous_1) FN:51,preparePluginsArray FN:56,(anonymous_3) FN:101,extendConfig FN:108,(anonymous_5) FN:115,(anonymous_6) FN:161,optimizePluginsArray FN:165,(anonymous_8) FN:169,(anonymous_9) FNF:9 FNH:9 FNDA:87,(anonymous_1) FNDA:87,preparePluginsArray FNDA:141,(anonymous_3) FNDA:1,extendConfig FNDA:3,(anonymous_5) FNDA:84,(anonymous_6) FNDA:87,optimizePluginsArray FNDA:141,(anonymous_8) FNDA:141,(anonymous_9) DA:1,1 DA:3,1 DA:5,1 DA:14,1 DA:16,87 DA:18,87 DA:20,85 DA:22,85 DA:23,85 DA:24,85 DA:29,2 DA:31,2 DA:33,2 DA:34,1 DA:37,2 DA:41,87 DA:51,1 DA:53,87 DA:56,87 DA:59,141 DA:61,85 DA:62,85 DA:65,85 DA:66,0 DA:67,0 DA:70,85 DA:71,0 DA:74,85 DA:75,85 DA:78,85 DA:83,56 DA:84,56 DA:88,141 DA:101,1 DA:103,1 DA:106,1 DA:108,1 DA:111,3 DA:113,3 DA:115,3 DA:117,84 DA:119,3 DA:120,2 DA:121,2 DA:124,1 DA:125,1 DA:128,0 DA:129,0 DA:142,1 DA:143,0 DA:147,1 DA:148,0 DA:151,1 DA:161,1 DA:163,87 DA:165,87 DA:166,141 DA:169,87 DA:171,141 DA:172,44 DA:173,44 DA:176,97 DA:178,97 DA:182,87 LF:64 LH:57 BRDA:18,1,0,85 BRDA:18,1,1,2 BRDA:18,2,0,87 BRDA:18,2,1,86 BRDA:22,3,0,85 BRDA:22,3,1,0 BRDA:33,4,0,1 BRDA:33,4,1,1 BRDA:59,5,0,85 BRDA:59,5,1,56 BRDA:65,6,0,0 BRDA:65,6,1,85 BRDA:66,7,0,0 BRDA:66,7,1,0 BRDA:70,8,0,0 BRDA:70,8,1,85 BRDA:74,9,0,85 BRDA:74,9,1,0 BRDA:106,10,0,1 BRDA:106,10,1,0 BRDA:111,11,0,3 BRDA:111,11,1,0 BRDA:117,12,0,3 BRDA:117,12,1,81 BRDA:119,13,0,2 BRDA:119,13,1,1 BRDA:120,14,0,2 BRDA:120,14,1,1 BRDA:124,15,0,1 BRDA:124,15,1,0 BRDA:128,16,0,0 BRDA:128,16,1,0 BRDA:142,17,0,0 BRDA:142,17,1,1 BRDA:147,18,0,0 BRDA:147,18,1,1 BRDA:171,19,0,44 BRDA:171,19,1,97 BRDA:171,20,0,141 BRDA:171,20,1,54 BRF:40 BRH:27 end_of_record package/fixtures/istanbul.remap.lcov000644 000765 000024 0000003531 13163045624016217 0ustar00000000 000000 TN: SF:/Users/deepsweet/Dropbox/projects/svgo/node_modules/angular2-template-loader/index.js!/Users/deepsweet/Dropbox/projects/svgo/node_modules/tslint-loader/index.js!/Users/deepsweet/Dropbox/projects/svgo/lib/svgo/config.js FN:14,(anonymous_1) FN:51,preparePluginsArray FN:56,(anonymous_3) FN:101,extendConfig FN:108,(anonymous_5) FN:115,(anonymous_6) FN:161,optimizePluginsArray FN:165,(anonymous_8) FN:169,(anonymous_9) FNF:9 FNH:9 FNDA:87,(anonymous_1) FNDA:87,preparePluginsArray FNDA:141,(anonymous_3) FNDA:1,extendConfig FNDA:3,(anonymous_5) FNDA:84,(anonymous_6) FNDA:87,optimizePluginsArray FNDA:141,(anonymous_8) FNDA:141,(anonymous_9) DA:1,1 DA:3,1 DA:5,1 DA:14,1 DA:16,87 DA:18,87 DA:20,85 DA:22,85 DA:23,85 DA:24,85 DA:29,2 DA:31,2 DA:33,2 DA:34,1 DA:37,2 DA:41,87 DA:51,1 DA:53,87 DA:56,87 DA:59,141 DA:61,85 DA:62,85 DA:65,85 DA:66,0 DA:67,0 DA:70,85 DA:71,0 DA:74,85 DA:75,85 DA:78,85 DA:83,56 DA:84,56 DA:88,141 DA:101,1 DA:103,1 DA:106,1 DA:108,1 DA:111,3 DA:113,3 DA:115,3 DA:117,84 DA:119,3 DA:120,2 DA:121,2 DA:124,1 DA:125,1 DA:128,0 DA:129,0 DA:142,1 DA:143,0 DA:147,1 DA:148,0 DA:151,1 DA:161,1 DA:163,87 DA:165,87 DA:166,141 DA:169,87 DA:171,141 DA:172,44 DA:173,44 DA:176,97 DA:178,97 DA:182,87 LF:64 LH:57 BRDA:18,1,0,85 BRDA:18,1,1,2 BRDA:18,2,0,87 BRDA:18,2,1,86 BRDA:22,3,0,85 BRDA:22,3,1,0 BRDA:33,4,0,1 BRDA:33,4,1,1 BRDA:59,5,0,85 BRDA:59,5,1,56 BRDA:65,6,0,0 BRDA:65,6,1,85 BRDA:66,7,0,0 BRDA:66,7,1,0 BRDA:70,8,0,0 BRDA:70,8,1,85 BRDA:74,9,0,85 BRDA:74,9,1,0 BRDA:106,10,0,1 BRDA:106,10,1,0 BRDA:111,11,0,3 BRDA:111,11,1,0 BRDA:117,12,0,3 BRDA:117,12,1,81 BRDA:119,13,0,2 BRDA:119,13,1,1 BRDA:120,14,0,2 BRDA:120,14,1,1 BRDA:124,15,0,1 BRDA:124,15,1,0 BRDA:128,16,0,0 BRDA:128,16,1,0 BRDA:142,17,0,0 BRDA:142,17,1,1 BRDA:147,18,0,0 BRDA:147,18,1,1 BRDA:171,19,0,44 BRDA:171,19,1,97 BRDA:171,20,0,141 BRDA:171,20,1,54 BRF:40 BRH:27 end_of_record package/fixtures/lib/index.js000644 000765 000024 0000010155 13163045624014621 0ustar00000000 000000 var nodeUrl = require('url'); var querystring = require('querystring'); var _ = require('underscore'); var UrlGrey = function(url){ this.url = url; this._parsed = null; }; UrlGrey.prototype.parsed = function(){ if (!this._parsed){ this._parsed = nodeUrl.parse(this.url); var p = this._parsed; if (p.protocol){ p.protocol = p.protocol.slice(0,-1); } else { p.protocol = 'http'; } if (p.hash){ p.hash = p.hash.substring(1); } p.username = ''; p.password = ''; if (!p.hostname){ p.hostname = 'localhost'; } if (!p.port){ p.port = 80; } else { p.port = parseInt(p.port, 10); } if (p.auth){ var auth = p.auth.split(':'); p.username = auth[0]; p.password = auth[1]; } } return this._parsed; }; UrlGrey.prototype.query = function(mergeObject){ var path; if (mergeObject === false){ // clear the query entirely if the input === false return this.queryString(''); } var url = this.url; if (!mergeObject){ var parsed = nodeUrl.parse(url); if (!!parsed.search){ var qstr = parsed.search.substring(1); return querystring.parse(qstr); } return {}; } else { // read the object out var oldQuery = querystring.parse(this.queryString()); _.each(mergeObject, function(v, k){ if (v === null){ delete oldQuery[k]; } else { oldQuery[k] = v; } }); var newString = querystring.stringify(oldQuery, '&', '='); return this.queryString(newString); } }; addPropertyGetterSetter('protocol'); addPropertyGetterSetter('port'); addPropertyGetterSetter('username'); addPropertyGetterSetter('password'); addPropertyGetterSetter('hostname'); addPropertyGetterSetter('hash'); // add a method called queryString that manipulates 'query' addPropertyGetterSetter('query', 'queryString'); addPropertyGetterSetter('pathname', 'path'); UrlGrey.prototype.path = function(){ var args = _.toArray(arguments); if (args.length !== 0){ var obj = new UrlGrey(this.toString()); var str = _.flatten(args).join('/'); str = str.replace(/\/+/g, '/'); // remove double slashes str = str.replace(/\/$/, ''); // remove all trailing slashes if (str[0] !== '/'){ str = '/' + str; } obj.parsed().pathname = str; return obj; } return this.parsed().pathname; }; UrlGrey.prototype.encode = function(str){ return querystring.escape(str); }; UrlGrey.prototype.decode = function(str){ return querystring.unescape(str); }; UrlGrey.prototype.parent = function(){ // read-only. (can't SET parent) var pieces = this.path().split("/"); var popped = pieces.pop(); if (popped === ''){ // ignore trailing slash pieces.pop(); } return this.path(pieces.join("/")); }; UrlGrey.prototype.child = function(suffix){ if (suffix){ suffix = encodeURIComponent(suffix); return this.path(this.path(), suffix); } else { // if no suffix, return the child var pieces = this.path().split("/"); var last = _.last(pieces); if ((pieces.length > 1) && (last === '')){ // ignore trailing slashes pieces.pop(); last = _.last(pieces); } return last; } }; UrlGrey.prototype.toJSON = function(){ return this.toString(); }; UrlGrey.prototype.toString = function(){ var p = this.parsed(); var userinfo = p.username + ':' + p.password; var retval = this.protocol() + '://'; if (userinfo != ':'){ retval += userinfo + '@'; } retval += p.hostname; if (this.port() !== 80){ retval += ':' + this.port(); } retval += this.path() === '/' ? '' : this.path(); var qs = this.queryString(); if (qs){ retval += '?' + qs; } if (p.hash){ retval += '#' + p.hash; } return retval; }; module.exports = function(url){ return new UrlGrey(url); }; function addPropertyGetterSetter(propertyName, methodName){ if (!methodName){ methodName = propertyName; } UrlGrey.prototype[methodName] = function(str){ if (!!str || str === ''){ var obj = new UrlGrey(this.toString()); obj.parsed()[propertyName] = str; return obj; } return this.parsed()[propertyName]; }; } package/fixtures/onefile.lcov000644 000765 000024 0000002125 13163045624014712 0ustar00000000 000000 make[1]: Entering directory `/home/cainus/urlgrey' SF:index.js DA:1,1 DA:2,1 DA:3,1 DA:5,1 DA:6,66 DA:7,66 DA:10,1 DA:11,323 DA:12,63 DA:13,63 DA:14,63 DA:15,60 DA:17,3 DA:19,63 DA:20,32 DA:22,63 DA:23,63 DA:24,63 DA:25,3 DA:27,63 DA:28,60 DA:30,3 DA:32,63 DA:33,27 DA:34,27 DA:35,27 DA:38,323 DA:41,1 DA:42,5 DA:43,5 DA:45,2 DA:48,3 DA:49,3 DA:50,1 DA:51,1 DA:52,1 DA:53,1 DA:55,0 DA:58,2 DA:59,2 DA:60,2 DA:61,0 DA:63,2 DA:66,2 DA:67,2 DA:72,1 DA:73,1 DA:74,1 DA:75,1 DA:76,1 DA:77,1 DA:79,1 DA:80,1 DA:82,1 DA:83,87 DA:84,87 DA:85,6 DA:86,6 DA:87,6 DA:88,6 DA:89,9 DA:90,6 DA:91,6 DA:93,81 DA:97,1 DA:98,1 DA:101,1 DA:102,1 DA:105,1 DA:107,2 DA:108,2 DA:109,2 DA:110,1 DA:112,2 DA:115,1 DA:116,3 DA:117,1 DA:118,1 DA:121,2 DA:122,2 DA:123,2 DA:125,1 DA:126,1 DA:128,2 DA:132,1 DA:133,1 DA:136,1 DA:137,50 DA:138,50 DA:139,50 DA:140,50 DA:141,20 DA:143,50 DA:144,50 DA:145,2 DA:147,50 DA:148,50 DA:149,50 DA:150,31 DA:152,50 DA:153,24 DA:155,50 DA:210,40 DA:212,1 DA:213,8 DA:214,6 DA:216,8 DA:217,186 DA:218,21 DA:219,21 DA:220,21 DA:222,165 end_of_record make[1]: Leaving directory `/home/cainus/urlgrey' package/bin/coveralls.js000755 000765 000024 0000000604 13163045624013636 0ustar00000000 000000 #!/usr/bin/env node var handleInput = require('../lib/handleInput'); var logger = require('../lib/logger'); process.stdin.resume(); process.stdin.setEncoding('utf8'); var input = ''; process.stdin.on('data', function(chunk) { input += chunk; }); process.stdin.on('end', function() { handleInput(input, function(err) { if (err) { throw err; } }); }); package/.snyk000644 000765 000024 0000000014 13163045624011513 0ustar00000000 000000 version: v1 package/.travis.yml000644 000765 000024 0000000156 13163212353012641 0ustar00000000 000000 language: node_js node_js: - "node" - "8" - "6" - "5" - "4" script: make test-coveralls sudo: false package/lib/convertLcovToCoveralls.js000644 000765 000024 0000006773 13163045624016336 0ustar00000000 000000 var TRAVIS_JOB_ID = process.env.TRAVIS_JOB_ID || 'unknown'; var fs = require('fs'); var lcovParse = require('lcov-parse'); var path = require('path'); var logger = require('./logger')(); var detailsToCoverage = function(length, details){ var coverage = new Array(length); details.forEach(function(obj){ coverage[obj.line - 1] = obj.hit; }); return coverage; }; var detailsToBranches = function(details){ var branches = []; details.forEach(function(obj){ ['line','block','branch','taken'].forEach(function(key){ branches.push(obj[key] || 0); }); }); return branches; }; var convertLcovFileObject = function(file, filepath){ var rootpath = filepath; filepath = path.resolve(rootpath, file.file); var source = fs.readFileSync(filepath, 'utf8'); var lines = source.split("\n"); var coverage = detailsToCoverage(lines.length, file.lines.details); var branches = detailsToBranches(file.branches.details); return { name : path.relative(rootpath, path.resolve(rootpath, file.file)).split( path.sep ).join( "/" ), source : source, coverage : coverage, branches : branches }; }; var cleanFilePath = function(file) { if (file.indexOf('!') > -1) { var regex = /^(.*!)(.*)$/g; var matches = regex.exec(file); return matches[matches.length-1]; } return file; }; var convertLcovToCoveralls = function(input, options, cb){ var filepath = options.filepath || ''; logger.debug("in: ", filepath); filepath = path.resolve(process.cwd(), filepath); lcovParse(input, function(err, parsed){ if (err){ logger.error("error from lcovParse: ", err); logger.error("input: ", input); return cb(err); } var postJson = { source_files : [] }; if (options.git){ postJson.git = options.git; } if (options.run_at){ postJson.run_at = options.run_at; } if (options.service_name){ postJson.service_name = options.service_name; } if (options.service_job_id){ postJson.service_job_id = options.service_job_id; } if (options.service_pull_request) { postJson.service_pull_request = options.service_pull_request; } if (options.repo_token) { postJson.repo_token = options.repo_token; } if (options.parallel) { postJson.parallel = options.parallel; } if (options.service_pull_request) { postJson.service_pull_request = options.service_pull_request; } parsed.forEach(function(file){ file.file = cleanFilePath(file.file); var currentFilePath = path.resolve(filepath, file.file); if (fs.existsSync(currentFilePath)) { postJson.source_files.push(convertLcovFileObject(file, filepath)); } }); return cb(null, postJson); }); }; module.exports = convertLcovToCoveralls; /* example coveralls json file { "service_job_id": "1234567890", "service_name": "travis-ci", "source_files": [ { "name": "example.rb", "source": "def four\n 4\nend", "coverage": [null, 1, null] }, { "name": "two.rb", "source": "def seven\n eight\n nine\nend", "coverage": [null, 1, 0, null] } ] } example output from lcov parser: [ { "file": "index.js", "lines": { "found": 0, "hit": 0, "details": [ { "line": 1, "hit": 1 }, { "line": 2, "hit": 1 }, { "line": 3, "hit": 1 }, { "line": 5, "hit": 1 }, */ package/lib/detectLocalGit.js000644 000765 000024 0000002673 13163045624014536 0ustar00000000 000000 var fs = require('fs'); var path = require('path'); // branch naming only has a few excluded characters, see git-check-ref-format(1) var REGEX_BRANCH = /^ref: refs\/heads\/([^?*\[\\~^:]+)$/; module.exports = function detectLocalGit() { var dir = process.cwd(), gitDir; while (path.resolve('/') !== dir) { gitDir = path.join(dir, '.git'); var existsSync = fs.existsSync || path.existsSync; if (existsSync(path.join(gitDir, 'HEAD'))) break; dir = path.dirname(dir); } if (path.resolve('/') === dir) return; var head = fs.readFileSync(path.join(dir, '.git', 'HEAD'), 'utf-8').trim(); var branch = (head.match(REGEX_BRANCH) || [])[1]; if (!branch) return { git_commit: head }; var commit = _parseCommitHashFromRef(dir, branch); return { git_commit: commit, git_branch: branch }; }; function _parseCommitHashFromRef(dir, branch) { var ref = path.join(dir, '.git', 'refs', 'heads', branch); if (fs.existsSync(ref)) { return fs.readFileSync(ref, 'utf-8').trim(); } else { // ref does not exist; get it from packed-refs var commit = ''; var packedRefs = path.join(dir, '.git', 'packed-refs'); var packedRefsText = fs.readFileSync(packedRefs, 'utf-8'); packedRefsText.split('\n').forEach(function (line) { if (line.match('refs/heads/'+branch)) { commit = line.split(' ')[0]; } }); return commit; } } package/lib/fetchGitData.js000644 000765 000024 0000005436 13163045624014176 0ustar00000000 000000 var exec = require('child_process').exec; var logger = require('./logger')(); function fetchGitData(git, cb) { if (!cb){ throw new Error("fetchGitData requires a callback"); } //-- Malformed/undefined git object if ('undefined' === typeof git) { return cb(new Error('No options passed')); } if (!git.hasOwnProperty('head')) { return cb(new Error('You must provide the head')); } if (!git.head.hasOwnProperty('id')) { return cb(new Error('You must provide the head.id')); } //-- Set required properties of git if they weren"t provided if (!git.hasOwnProperty("branch")) { git.branch = ""; } if (!git.hasOwnProperty("remotes")) { git.remotes = []; } //-- Assert the property types if ("string" !== typeof git.branch) { git.branch = ""; } if (!(git.remotes instanceof Array)) { git.remotes = []; } //-- Use git? exec("git rev-parse --verify " + git.head.id, function(err, response){ if (err){ // git is not available... git.head.author_name = git.head.author_name || "Unknown Author"; git.head.author_email = git.head.author_email || ""; git.head.committer_name = git.head.committer_name || "Unknown Committer"; git.head.committer_email = git.head.committer_email || ""; git.head.message = git.head.message || "Unknown Commit Message"; return cb(null, git); } fetchHeadDetails(git, cb); }); } function fetchBranch(git, cb) { exec("git branch", function(err, branches){ if (err) return cb(err); git.branch = (branches.match(/^\* (\w+)/) || [])[1]; fetchRemotes(git, cb); }); } var REGEX_COMMIT_DETAILS = /\nauthor (.+?) <([^>]*)>.+\ncommitter (.+?) <([^>]*)>.+[\S\s]*?\n\n(.*)/m; function fetchHeadDetails(git, cb) { exec('git cat-file -p ' + git.head.id, function(err, response) { if (err) return cb(err); var items = response.match(REGEX_COMMIT_DETAILS).slice(1); var fields = ['author_name', 'author_email', 'committer_name', 'committer_email', 'message']; fields.forEach(function(field, index) { git.head[field] = items[index]; }); if (git.branch) { fetchRemotes(git, cb); } else { fetchBranch(git, cb); } }); } function fetchRemotes(git, cb) { exec("git remote -v", function(err, remotes){ if (err) return cb(err); var processed = {}; remotes.split("\n").forEach(function(remote) { if (!/\s\(push\)$/.test(remote)) return; remote = remote.split(/\s+/); saveRemote(processed, git, remote[0], remote[1]); }); cb(null, git); }); } function saveRemote(processed, git, name, url) { var key = name + "-" + url; if (processed.hasOwnProperty(key)) return; processed[key] = true; git.remotes.push({ name: name, url: url }); } module.exports = fetchGitData; package/lib/getOptions.js000644 000765 000024 0000013444 13163045624014000 0ustar00000000 000000 var fs = require('fs'); var path = require('path'); var yaml = require('js-yaml'); var index = require('../index'); var logger = require('./logger')(); var fetchGitData = require('./fetchGitData'); var getBaseOptions = function(cb){ var options = {}; var git_commit = process.env.COVERALLS_GIT_COMMIT; var git_branch = process.env.COVERALLS_GIT_BRANCH; var git_committer_name, git_committer_email, git_message; var match = (process.env.CI_PULL_REQUEST || "").match(/(\d+)$/); if (match) { options.service_pull_request = match[1]; } if (process.env.TRAVIS){ options.service_name = 'travis-ci'; options.service_job_id = process.env.TRAVIS_JOB_ID; options.service_pull_request = process.env.TRAVIS_PULL_REQUEST; git_commit = 'HEAD'; git_branch = process.env.TRAVIS_BRANCH; } if (process.env.DRONE){ options.service_name = 'drone'; options.service_job_id = process.env.DRONE_BUILD_NUMBER; options.service_pull_request = process.env.DRONE_PULL_REQUEST; git_committer_name = process.env.DRONE_COMMIT_AUTHOR; git_committer_email = process.env.DRONE_COMMIT_AUTHOR_EMAIL; git_commit = process.env.DRONE_COMMIT; git_branch = process.env.DRONE_BRANCH; git_message = process.env.DRONE_COMMIT_MESSAGE; } if (process.env.JENKINS_URL || process.env.JENKINS_HOME){ options.service_name = 'jenkins'; options.service_job_id = process.env.BUILD_ID; options.service_pull_request = process.env.ghprbPullId; git_commit = process.env.GIT_COMMIT; git_branch = process.env.GIT_BRANCH || process.env.BRANCH_NAME; } if (process.env.CIRCLECI){ options.service_name = 'circleci'; options.service_job_id = process.env.CIRCLE_BUILD_NUM; if (process.env.CI_PULL_REQUEST) { var pr = process.env.CI_PULL_REQUEST.split('/pull/'); options.service_pull_request = pr[1]; } git_commit = process.env.CIRCLE_SHA1; git_branch = process.env.CIRCLE_BRANCH; } if (process.env.CI_NAME && process.env.CI_NAME === 'codeship'){ options.service_name = 'codeship'; options.service_job_id = process.env.CI_BUILD_NUMBER; git_commit = process.env.CI_COMMIT_ID; git_branch = process.env.CI_BRANCH; git_committer_name = process.env.CI_COMMITTER_NAME; git_committer_email = process.env.CI_COMMITTER_EMAIL; git_message = process.env.CI_COMMIT_MESSAGE; } if (process.env.WERCKER){ options.service_name = 'wercker'; options.service_job_id = process.env.WERCKER_BUILD_ID; git_commit = process.env.WERCKER_GIT_COMMIT; git_branch = process.env.WERCKER_GIT_BRANCH; } if (process.env.GITLAB_CI){ options.service_name = 'gitlab-ci'; options.service_job_number = process.env.CI_BUILD_NAME; options.service_job_id = process.env.CI_BUILD_ID; git_commit = process.env.CI_BUILD_REF; git_branch = process.env.CI_BUILD_REF_NAME; } if(process.env.APPVEYOR){ options.service_name = 'appveyor'; options.service_job_number = process.env.APPVEYOR_BUILD_NUMBER; options.service_job_id = process.env.APPVEYOR_BUILD_ID; git_commit = process.env.APPVEYOR_REPO_COMMIT; git_branch = process.env.APPVEYOR_REPO_BRANCH; } if(process.env.SURF_SHA1){ options.service_name = 'surf'; git_commit = process.env.SURF_SHA1; git_branch = process.env.SURF_REF; } options.run_at = process.env.COVERALLS_RUN_AT || JSON.stringify(new Date()).slice(1, -1); if (process.env.COVERALLS_SERVICE_NAME){ options.service_name = process.env.COVERALLS_SERVICE_NAME; } if (process.env.COVERALLS_SERVICE_JOB_ID){ options.service_job_id = process.env.COVERALLS_SERVICE_JOB_ID; } if (!git_commit || !git_branch) { var data = require('./detectLocalGit')(); if (data) { git_commit = git_commit || data.git_commit; git_branch = git_branch || data.git_branch; } } if (process.env.COVERALLS_PARALLEL) { options.parallel = true; } // try to get the repo token as an environment variable if (process.env.COVERALLS_REPO_TOKEN) { options.repo_token = process.env.COVERALLS_REPO_TOKEN; } else { // try to get the repo token from a .coveralls.yml file var yml = path.join(process.cwd(), '.coveralls.yml'); try { if (fs.statSync(yml).isFile()) { var coveralls_yaml_conf = yaml.safeLoad(fs.readFileSync(yml, 'utf8')); options.repo_token = coveralls_yaml_conf.repo_token; if(coveralls_yaml_conf.service_name) { options.service_name = coveralls_yaml_conf.service_name; } } } catch(ex){ logger.warn("Repo token could not be determined. Continuing without it." + "This is necessary for private repos only, so may not be an issue at all."); } } if (git_commit){ fetchGitData({ head: { id: git_commit, committer_name: git_committer_name, committer_email: git_committer_email, message: git_message }, branch: git_branch }, function(err, git){ if (err){ logger.warn('there was an error getting git data: ', err); } else { options.git = git; } return cb(err, options); }); } else { return cb(null, options); } }; var getOptions = function(cb, _userOptions){ if (!cb){ throw new Error('getOptions requires a callback'); } var userOptions = _userOptions || {}; getBaseOptions(function(err, options){ // minimist populates options._ with non-option command line arguments var firstNonOptionArgument = index.options._[0]; if (firstNonOptionArgument) options.filepath = firstNonOptionArgument; // lodash or else would be better, but no need for the extra dependency for (var option in userOptions) { options[option] = userOptions[option]; } cb(err, options); }); }; module.exports.getBaseOptions = getBaseOptions; module.exports.getOptions = getOptions; package/lib/handleInput.js000644 000765 000024 0000002032 13163045624014107 0ustar00000000 000000 var index = require('../index'); var logger = require('./logger')(); function handleInput(input, cb, userOptions) { logger.debug(input); logger.debug('user options ' + userOptions); index.getOptions(function(err, options){ if (err){ logger.error("error from getOptions"); cb(err); return; } logger.debug(options); index.convertLcovToCoveralls(input, options, function(err, postData){ if (err){ logger.error("error from convertLcovToCoveralls"); cb(err); return; } logger.info("sending this to coveralls.io: ", JSON.stringify(postData)); index.sendToCoveralls(postData, function(err, response, body){ if (err){ cb(err); return; } if (response.statusCode >= 400){ cb("Bad response: " + response.statusCode + " " + body); return; } logger.debug(response.statusCode); logger.debug(body); cb(null); }); }); }, userOptions); } module.exports = handleInput; package/lib/logger.js000644 000765 000024 0000000514 13163045624013116 0ustar00000000 000000 var index = require('../index'); module.exports = function(){ return require('log-driver')({level : getLogLevel()}); }; function getLogLevel(){ if (index.options.verbose || hasDebugEnvVariable()) { return 'warn'; } return 'error'; } function hasDebugEnvVariable(){ return process.env.NODE_COVERALLS_DEBUG == 1; } package/lib/sendToCoveralls.js000644 000765 000024 0000001115 13163045624014744 0ustar00000000 000000 var request = require('request'); var index = require('../index'); var sendToCoveralls = function(obj, cb){ var urlBase = 'https://coveralls.io'; if (process.env.COVERALLS_ENDPOINT) { urlBase = process.env.COVERALLS_ENDPOINT; } var str = JSON.stringify(obj); var url = urlBase + '/api/v1/jobs'; if (index.options.stdout) { process.stdout.write(str); cb(null, { statusCode: 200 }, ''); } else { request.post({url : url, form : { json : str}}, function(err, response, body){ cb(err, response, body); }); } }; module.exports = sendToCoveralls; package/Makefile000644 000765 000024 0000001025 13163045624012171 0ustar00000000 000000 REPORTER = spec test: @$(MAKE) lint @echo TRAVIS_JOB_ID $(TRAVIS_JOB_ID) @NODE_ENV=test ./node_modules/.bin/mocha -b --reporter $(REPORTER) lint: ./node_modules/.bin/jshint ./lib ./test ./index.js test-cov: $(MAKE) lint @NODE_ENV=test ./node_modules/.bin/istanbul cover \ ./node_modules/mocha/bin/_mocha -- -R spec test-coveralls: @NODE_ENV=test ./node_modules/.bin/istanbul cover \ ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && \ cat ./coverage/lcov.info | ./bin/coveralls.js --verbose .PHONY: test package/test/convertLcovToCoveralls.js000644 000765 000024 0000014322 13163045624016534 0ustar00000000 000000 var convertLcovToCoveralls = require('../index').convertLcovToCoveralls; var getOptions = require('../index').getOptions; var should = require('should'); var fs = require('fs'); var logger = require('../lib/logger'); var path = require('path'); logger = require('log-driver')({level : false}); describe("convertLcovToCoveralls", function(){ it ("should convert a simple lcov file", function(done){ delete process.env.TRAVIS; var lcovpath = __dirname + "/../fixtures/onefile.lcov"; var input = fs.readFileSync(lcovpath, "utf8"); var libpath = __dirname + "/../fixtures/lib"; convertLcovToCoveralls(input, {filepath: libpath}, function(err, output){ should.not.exist(err); output.source_files[0].name.should.equal("index.js"); output.source_files[0].source.split("\n").length.should.equal(173); output.source_files[0].coverage[54].should.equal(0); output.source_files[0].coverage[60].should.equal(0); done(); }); }); it ("should pass on all appropriate parameters from the environment", function(done){ delete process.env.TRAVIS; process.env.COVERALLS_GIT_COMMIT = "GIT_HASH"; process.env.COVERALLS_GIT_BRANCH = "master"; process.env.COVERALLS_SERVICE_NAME = "SERVICE_NAME"; process.env.COVERALLS_SERVICE_JOB_ID = "SERVICE_JOB_ID"; process.env.COVERALLS_REPO_TOKEN = "REPO_TOKEN"; process.env.CI_PULL_REQUEST = "https://github.com/fake/fake/pulls/123"; process.env.COVERALLS_PARALLEL = "true"; getOptions(function(err, options){ var lcovpath = __dirname + "/../fixtures/onefile.lcov"; var input = fs.readFileSync(lcovpath, "utf8"); var libpath = "fixtures/lib"; options.filepath = libpath; convertLcovToCoveralls(input, options, function(err, output){ should.not.exist(err); output.service_pull_request.should.equal("123"); output.parallel.should.equal(true); //output.git.should.equal("GIT_HASH"); done(); }); }); }); it ("should work with a relative path as well", function(done){ delete process.env.TRAVIS; var lcovpath = __dirname + "/../fixtures/onefile.lcov"; var input = fs.readFileSync(lcovpath, "utf8"); var libpath = "fixtures/lib"; convertLcovToCoveralls(input, {filepath: libpath}, function(err, output){ should.not.exist(err); output.source_files[0].name.should.equal("index.js"); output.source_files[0].source.split("\n").length.should.equal(173); done(); }); }); it ("should convert absolute input paths to relative", function(done){ delete process.env.TRAVIS; var lcovpath = __dirname + "/../fixtures/istanbul.lcov"; var input = fs.readFileSync(lcovpath, "utf8"); var libpath = "/Users/deepsweet/Dropbox/projects/svgo/lib"; var sourcepath = path.resolve(libpath, "svgo/config.js"); var originalReadFileSync = fs.readFileSync; fs.readFileSync = function(filepath) { if (filepath === sourcepath) { return ''; } return originalReadFileSync.apply(fs, arguments); }; var originalExistsSync = fs.existsSync; fs.existsSync = function () { return true; }; convertLcovToCoveralls(input, {filepath: libpath}, function(err, output){ fs.readFileSync = originalReadFileSync; fs.existsSync = originalExistsSync; should.not.exist(err); output.source_files[0].name.should.equal(path.join("svgo", "config.js")); done(); }); }); it ("should handle branch coverage data", function(done){ process.env.TRAVIS_JOB_ID = -1; var lcovpath = __dirname + "/../fixtures/istanbul.lcov"; var input = fs.readFileSync(lcovpath, "utf8"); var libpath = "/Users/deepsweet/Dropbox/projects/svgo/lib"; var sourcepath = path.resolve(libpath, "svgo/config.js"); var originalReadFileSync = fs.readFileSync; fs.readFileSync = function(filepath) { if (filepath === sourcepath) { return ''; } return originalReadFileSync.apply(fs, arguments); }; var originalExistsSync = fs.existsSync; fs.existsSync = function () { return true; }; convertLcovToCoveralls(input, {filepath: libpath}, function(err, output){ fs.readFileSync = originalReadFileSync; fs.existsSync = originalExistsSync; should.not.exist(err); output.source_files[0].branches.slice(0,8).should.eql([18,1,0,85,18,1,1,2]); done(); }); }); it ("should ignore files that do not exists", function(done){ delete process.env.TRAVIS; var lcovpath = __dirname + "/../fixtures/istanbul.lcov"; var input = fs.readFileSync(lcovpath, "utf8"); var libpath = "/Users/deepsweet/Dropbox/projects/svgo/lib"; var sourcepath = path.resolve(libpath, "svgo/config.js"); var originalReadFileSync = fs.readFileSync; fs.readFileSync = function(filepath) { if (filepath === sourcepath) { return ''; } return originalReadFileSync.apply(fs, arguments); }; var originalExistsSync = fs.existsSync; fs.existsSync = function () { return false; }; convertLcovToCoveralls(input, {filepath: libpath}, function(err, output){ fs.readFileSync = originalReadFileSync; fs.existsSync = originalExistsSync; should.not.exist(err); output.source_files.should.be.empty(); done(); }); }); it ("should parse file paths concatenated by typescript and ng 2", function(done) { process.env.TRAVIS_JOB_ID = -1; var lcovpath = __dirname + "/../fixtures/istanbul.remap.lcov"; var input = fs.readFileSync(lcovpath, "utf8"); var libpath = "/Users/deepsweet/Dropbox/projects/svgo/lib"; var sourcepath = path.resolve(libpath, "svgo/config.js"); var originalReadFileSync = fs.readFileSync; fs.readFileSync = function(filepath) { if (filepath === sourcepath) { return ''; } return originalReadFileSync.apply(fs, arguments); }; var originalExistsSync = fs.existsSync; fs.existsSync = function () { return true; }; convertLcovToCoveralls(input, {filepath: libpath}, function(err, output){ fs.readFileSync = originalReadFileSync; fs.existsSync = originalExistsSync; should.not.exist(err); output.source_files[0].name.should.equal(path.join("svgo", "config.js")); done(); }); }); }); package/test/detectLocalGit.js000644 000765 000024 0000003671 13163045624014746 0ustar00000000 000000 var should = require('should'); var fs = require('fs'); var path = require('path'); var detectLocalGit = require('../lib/detectLocalGit'); var ORIGINAL_CWD = process.cwd(); var TEST_DIR = path.resolve(__dirname); var TEMP_GIT_DIR = path.join(TEST_DIR, '.git'); describe("detectLocalGit", function() { before(function() { _makeTempGitDir(); process.chdir(TEST_DIR); }); after(function() { _cleanTempGitDir(); process.chdir(ORIGINAL_CWD); }); it('should get commit hash from packed-refs when refs/heads/master does not exist', function() { var results = detectLocalGit(); should.exist(results); (results).should.deepEqual({ git_commit: '0000000000000000ffffffffffffffffffffffff', git_branch: 'master' }); }); }); function _makeTempGitDir() { _cleanTempGitDir(); var dir = TEMP_GIT_DIR; fs.mkdirSync(dir); var HEAD = path.join(dir, 'HEAD'); var packedRefs = path.join(dir, 'packed-refs'); fs.writeFileSync(HEAD, 'ref: refs/heads/master'); fs.writeFileSync(packedRefs, "" + "# pack-refs with: peeled fully-peeled\n" + "0000000000000000000000000000000000000000 refs/heads/other/ref\n" + "0000000000000000ffffffffffffffffffffffff refs/heads/master\n" + "ffffffffffffffffffffffffffffffffffffffff refs/remotes/origin/other\n"); } function _cleanTempGitDir() { _deleteFolderRecursive(TEMP_GIT_DIR); } function _deleteFolderRecursive(dir) { if (!dir.match('node-coveralls/test')) { throw new Error('Tried to clean a temp git directory that did not match path: node-coveralls/test'); } if(fs.existsSync(dir)) { fs.readdirSync(dir).forEach(function(file,index){ var curPath = path.join(dir, file); if(fs.lstatSync(curPath).isDirectory()) { // recurse _deleteFolderRecursive(curPath); } else { // delete file fs.unlinkSync(curPath); } }); fs.rmdirSync(dir); } } package/test/fetchGitData.js000644 000765 000024 0000011512 13163045624014377 0ustar00000000 000000 var should = require('should'); var fetchGitData = require('../lib/fetchGitData'); var getOptions = require('../index').getOptions; describe("fetchGitData", function(){ beforeEach(function(){ process.env = {PATH: process.env.PATH}; }); it("should throw an error when no data is passed", function() { fetchGitData.should.throw(/fetchGitData requires a callback/); }); it('should throw an error when no git context is provided', function(done) { fetchGitData(undefined, function(err){ err.should.match(/No options passed/); done(); }); }); it("should throw an error if no head is provided", function(done) { fetchGitData({ }, function(err){ err.should.match(/You must provide the head/); done(); }); }); it("should throw an error if no head.id is provided", function(done) { fetchGitData({ head: {} }, function(err){ err.should.match(/You must provide the head.id/); done(); }); }); it("should return default values", function(done) { var options = fetchGitData({ head: { id: "COMMIT_HASH" } }, function(err, options){ options.should.eql({ "head": { "id": "COMMIT_HASH", "author_name": "Unknown Author", "author_email": "", "committer_name": "Unknown Committer", "committer_email": "", "message": "Unknown Commit Message" }, "branch": "", "remotes": [] }); done(); }); }); it("should override default values", function(done) { var options = fetchGitData({ "head": { "id": "COMMIT_HASH", "author_name": "MY AUTHOR", "author_email": "", "committer_name": "MY COMMITTER", "committer_email": "", "message": "MY COMMIT MESSAGE" }, "branch": "TEST", "remotes": [ { "name": "TEST", "url": "test-url" } ] }, function(err, options){ options.should.eql({ "head": { "id": "COMMIT_HASH", "author_name": "MY AUTHOR", "author_email": "", "committer_name": "MY COMMITTER", "committer_email": "", "message": "MY COMMIT MESSAGE" }, "branch": "TEST", "remotes": [ { "name": "TEST", "url": "test-url" } ] }); done(); }); }); it("should convert git.branch to a string", function(done) { fetchGitData({ "head": { "id": "COMMIT_HASH" }, "branch": { "covert": "to a string" } }, function(err, str){ str.branch.should.be.String(); fetchGitData({ "head": { "id": "COMMIT_HASH" }, "branch": ["convert", "to", "a", "string"] }, function(err, str){ str.branch.should.be.String(); done(); }); }); }); it("should convert git.remotes to an array", function(done) { fetchGitData({ "head": { "id": "COMMIT_HASH" }, "remotes": "convert from string to an array" }, function(err, arr){ arr.remotes.should.be.instanceof(Array); fetchGitData({ "head": { "id": "COMMIT_HASH" }, "remotes": { "convert": "from object to an array" } }, function(err, arr){ arr.remotes.should.be.instanceof(Array); done(); }); }); }); it("should save passed remotes", function(done) { fetchGitData({ "head": { "id": "COMMIT_HASH" }, "remotes": [ { "name": "test", "url": "https://my.test.url" } ] }, function(err, options){ options.should.eql({ "head": { "id": "COMMIT_HASH", "author_name": "Unknown Author", "author_email": "", "committer_name": "Unknown Committer", "committer_email": "", "message": "Unknown Commit Message" }, "branch": "", "remotes": [ { "name": "test", "url": "https://my.test.url" } ] }); done(); }); }); it("should execute git commands when a valid commit hash is given", function(done) { process.env.COVERALLS_GIT_COMMIT = "HEAD"; process.env.COVERALLS_GIT_BRANCH = "master"; getOptions(function(err, options){ options = options.git; options.head.should.be.Object(); options.head.author_name.should.not.equal("Unknown Author"); options.head.committer_name.should.not.equal("Unknown Committer"); options.head.message.should.not.equal("Unknown Commit Message"); options.branch.should.be.String(); options.should.have.property("remotes"); options.remotes.should.be.instanceof(Array); options.remotes.length.should.be.above(0); done(); }); }); }); package/test/getOptions.js000644 000765 000024 0000043446 13163045624014216 0ustar00000000 000000 var should = require('should'); var index = require('../index'); var getOptions = index.getOptions; var getBaseOptions = index.getBaseOptions; describe("getBaseOptions", function(){ beforeEach(function(){ process.env = {PATH: process.env.PATH}; }); it ("should set service_job_id if it exists", function(done){ testServiceJobId(getBaseOptions, done); }); it ("should set git hash if it exists", function(done){ testGitHash(getBaseOptions, done); }); it ("should set git branch if it exists", function(done){ testGitBranch(getBaseOptions, done); }); it ("should detect current git hash if not passed in", function(done) { testGitHashDetection(getBaseOptions, done); }); it ("should detect current git branch if not passed in", function(done) { testGitBranchDetection(getBaseOptions, done); }); it ("should detect detached git head if no hash passed in", function(done) { testGitDetachedHeadDetection(getBaseOptions, done); }); it ("should fail local Git detection if no .git directory", function(done) { testNoLocalGit(getBaseOptions, done); }); it ("should set repo_token if it exists", function(done){ testRepoToken(getBaseOptions, done); }); it ("should detect repo_token if not passed in", function(done){ testRepoTokenDetection(getBaseOptions, done); }); it ("should set service_name if it exists", function(done){ testServiceName(getBaseOptions, done); }); it ("should set service_name and service_job_id if it's running on travis-ci", function(done){ testTravisCi(getBaseOptions, done); }); it ("should set service_name and service_job_id if it's running on jenkins", function(done){ testJenkins(getBaseOptions, done); }); it ("should set service_name and service_job_id if it's running on circleci", function(done){ testCircleCi(getBaseOptions, done); }); it ("should set service_name and service_job_id if it's running on codeship", function(done){ testCodeship(getBaseOptions, done); }); it ("should set service_name and service_job_id if it's running on drone", function(done){ testDrone(getBaseOptions, done); }); it ("should set service_name and service_job_id if it's running on wercker", function(done){ testWercker(getBaseOptions, done); }); }); describe("getOptions", function(){ beforeEach(function(){ process.env = {PATH: process.env.PATH}; }); it ("should require a callback", function(done) { (function() { getOptions(); }).should.throw(); done(); }); it ("should get a filepath if there is one", function(done){ index.options._ = ["somepath"]; getOptions(function(err, options){ options.filepath.should.equal("somepath"); done(); }); }); it ("should get a filepath if there is one, even in verbose mode", function(done){ index.options.verbose = "true"; index.options._ = ["somepath"]; getOptions(function(err, options){ options.filepath.should.equal("somepath"); done(); }); }); it ("should set service_job_id if it exists", function(done){ testServiceJobId(getOptions, done); }); it ("should set git hash if it exists", function(done){ testGitHash(getOptions, done); }); it ("should set git branch if it exists", function(done){ testGitBranch(getOptions, done); }); it ("should detect current git hash if not passed in", function(done) { testGitHashDetection(getOptions, done); }); it ("should detect current git branch if not passed in", function(done) { testGitBranchDetection(getOptions, done); }); it ("should detect detached git head if no hash passed in", function(done) { testGitDetachedHeadDetection(getOptions, done); }); it ("should fail local Git detection if no .git directory", function(done) { testNoLocalGit(getOptions, done); }); it ("should set repo_token if it exists", function(done){ testRepoToken(getOptions, done); }); it ("should detect repo_token if not passed in", function(done){ testRepoTokenDetection(getOptions, done); }); it ("should set paralell if env var set", function(done){ testParallel(getOptions, done); }); it ("should set service_name if it exists", function(done){ testServiceName(getOptions, done); }); it("should set service_pull_request if it exists", function(done){ testServicePullRequest(getOptions, done); }); it ("should set service_name and service_job_id if it's running on travis-ci", function(done){ testTravisCi(getOptions, done); }); it ("should set service_name and service_job_id if it's running on jenkins", function(done){ testJenkins(getOptions, done); }); it ("should set service_name and service_job_id if it's running on circleci", function(done){ testCircleCi(getOptions, done); }); it ("should set service_name and service_job_id if it's running on codeship", function(done){ testCodeship(getOptions, done); }); it ("should set service_name and service_job_id if it's running on drone", function(done){ testDrone(getBaseOptions, done); }); it ("should set service_name and service_job_id if it's running on wercker", function(done){ testWercker(getOptions, done); }); it ("should set service_name and service_job_id if it's running on Gitlab", function(done){ testGitlab(getOptions, done); }); it ("should set service_name and service_job_id if it's running via Surf", function(done){ testSurf(getOptions, done); }); it ("should override set options with user options", function(done){ var userOptions = {service_name: 'OVERRIDDEN_SERVICE_NAME'}; process.env.COVERALLS_SERVICE_NAME = "SERVICE_NAME"; getOptions(function(err, options){ options.service_name.should.equal("OVERRIDDEN_SERVICE_NAME"); done(); }, userOptions); }); }); var testServiceJobId = function(sut, done){ process.env.COVERALLS_SERVICE_JOB_ID = "SERVICE_JOB_ID"; sut(function(err, options){ options.service_job_id.should.equal("SERVICE_JOB_ID"); done(); }); }; var testGitHash = function(sut, done){ process.env.COVERALLS_GIT_COMMIT = "e3e3e3e3e3e3e3e3e"; sut(function(err, options){ options.git.head.id.should.equal("e3e3e3e3e3e3e3e3e"); done(); }); }; var testGitDetachedHeadDetection = function(sut, done){ var localGit = ensureLocalGitContext({ detached: true }); sut(function(err, options) { options.git.head.id.should.equal(localGit.id); localGit.wrapUp(); done(); }); }; var testGitHashDetection = function(sut, done){ var localGit = ensureLocalGitContext(); sut(function(err, options) { options.git.head.id.should.equal(localGit.id); localGit.wrapUp(); done(); }); }; var testGitBranch = function(sut, done){ process.env.COVERALLS_GIT_COMMIT = "e3e3e3e3e3e3e3e3e"; process.env.COVERALLS_GIT_BRANCH = "master"; sut(function(err, options){ options.git.branch.should.equal("master"); done(); }); }; var testGitBranchDetection = function(sut, done){ var localGit = ensureLocalGitContext(); sut(function(err, options) { if (localGit.branch) options.git.branch.should.equal(localGit.branch); else options.git.should.not.have.key('branch'); localGit.wrapUp(); done(); }); }; var testNoLocalGit = function(sut, done){ var localGit = ensureLocalGitContext({ noGit: true }); sut(function(err, options) { options.should.not.have.property('git'); localGit.wrapUp(); done(); }); }; var testRepoToken = function(sut, done){ process.env.COVERALLS_REPO_TOKEN = "REPO_TOKEN"; sut(function(err, options){ options.repo_token.should.equal("REPO_TOKEN"); done(); }); }; var testParallel = function(sut, done){ process.env.COVERALLS_PARALLEL = "true"; sut(function(err, options){ options.parallel.should.equal(true); done(); }); }; var testRepoTokenDetection = function(sut, done) { var fs = require('fs'); var path = require('path'); var file = path.join(process.cwd(), '.coveralls.yml'), token, service_name, synthetic = false; if (fs.exists(file)) { var yaml = require('js-yaml'); var coveralls_yml_doc = yaml.safeLoad(fs.readFileSync(yml, 'utf8')); token = coveralls_yml_doc.repo_token; if(coveralls_yml_doc.service_name) { service_name = coveralls_yml_doc.service_name; } } else { token = 'REPO_TOKEN'; service_name = 'travis-pro'; fs.writeFileSync(file, 'repo_token: ' + token+'\nservice_name: ' + service_name); synthetic = true; } sut(function(err, options) { options.repo_token.should.equal(token); if(service_name) { options.service_name.should.equal(service_name); } if (synthetic) fs.unlink(file); done(); }); }; var testServiceName = function(sut, done){ process.env.COVERALLS_SERVICE_NAME = "SERVICE_NAME"; sut(function(err, options){ options.service_name.should.equal("SERVICE_NAME"); done(); }); }; var testServicePullRequest = function(sut, done){ process.env.CI_PULL_REQUEST = "https://github.com/fake/fake/pulls/123"; sut(function(err, options){ options.service_pull_request.should.equal("123"); done(); }); }; var testTravisCi = function(sut, done){ process.env.TRAVIS = "TRUE"; process.env.TRAVIS_JOB_ID = "1234"; process.env.TRAVIS_PULL_REQUEST = "123"; sut(function(err, options){ options.service_name.should.equal("travis-ci"); options.service_job_id.should.equal("1234"); options.service_pull_request.should.equal("123"); done(); }); }; var testJenkins = function(sut, done){ process.env.JENKINS_URL = "something"; process.env.BUILD_ID = "1234"; process.env.GIT_COMMIT = "a12s2d3df4f435g45g45g67h5g6"; process.env.GIT_BRANCH = "master"; sut(function(err, options){ options.service_name.should.equal("jenkins"); options.service_job_id.should.equal("1234"); options.git.should.eql({ head: { id: 'a12s2d3df4f435g45g45g67h5g6', author_name: 'Unknown Author', author_email: '', committer_name: 'Unknown Committer', committer_email: '', message: 'Unknown Commit Message' }, branch: 'master', remotes: [] }); done(); }); }; var testCircleCi = function(sut, done){ process.env.CIRCLECI = true; process.env.CIRCLE_BRANCH = "master"; process.env.CIRCLE_BUILD_NUM = "1234"; process.env.CIRCLE_SHA1 = "e3e3e3e3e3e3e3e3e"; process.env.CI_PULL_REQUEST = 'http://github.com/node-coveralls/pull/3'; sut(function(err, options){ options.service_name.should.equal("circleci"); options.service_job_id.should.equal("1234"); options.service_pull_request.should.equal('3'); options.git.should.eql({ head: { id: 'e3e3e3e3e3e3e3e3e', author_name: 'Unknown Author', author_email: '', committer_name: 'Unknown Committer', committer_email: '', message: 'Unknown Commit Message' }, branch: 'master', remotes: [] }); done(); }); }; var testCodeship = function(sut, done) { process.env.CI_NAME = 'codeship'; process.env.CI_BUILD_NUMBER = '1234'; process.env.CI_COMMIT_ID = "e3e3e3e3e3e3e3e3e"; process.env.CI_BRANCH = "master"; process.env.CI_COMMITTER_NAME = "John Doe"; process.env.CI_COMMITTER_EMAIL = "jd@example.com"; process.env.CI_COMMIT_MESSAGE = "adadadadadadadadadad"; sut(function(err, options){ options.service_name.should.equal("codeship"); options.service_job_id.should.equal("1234"); options.git.should.eql({ head: { id: 'e3e3e3e3e3e3e3e3e', author_name: 'Unknown Author', author_email: '', committer_name: 'John Doe', committer_email: 'jd@example.com', message: 'adadadadadadadadadad' }, branch: 'master', remotes: [] }); done(); }); }; var testDrone = function(sut, done) { process.env.DRONE = true; process.env.DRONE_BUILD_NUMBER = '1234'; process.env.DRONE_COMMIT = "e3e3e3e3e3e3e3e3e"; process.env.DRONE_BRANCH = "master"; process.env.DRONE_PULL_REQUEST = '3'; process.env.DRONE_COMMIT_AUTHOR = 'john doe'; process.env.DRONE_COMMIT_AUTHOR_EMAIL = 'john@doe.com'; process.env.DRONE_COMMIT_MESSAGE = 'msgmsgmsg'; sut(function(err, options){ options.service_name.should.equal("drone"); options.service_job_id.should.equal("1234"); options.git.should.eql({ head: { id: 'e3e3e3e3e3e3e3e3e', author_name: 'Unknown Author', author_email: '', committer_name: 'john doe', committer_email: 'john@doe.com', message: 'msgmsgmsg' }, branch: 'master', remotes: [] }); done(); }); }; var testWercker = function(sut, done) { process.env.WERCKER = true; process.env.WERCKER_BUILD_ID = '1234'; process.env.WERCKER_GIT_COMMIT = "e3e3e3e3e3e3e3e3e"; process.env.WERCKER_GIT_BRANCH = "master"; sut(function(err, options){ options.service_name.should.equal("wercker"); options.service_job_id.should.equal("1234"); options.git.should.eql({ head: { id: 'e3e3e3e3e3e3e3e3e', author_name: 'Unknown Author', author_email: '', committer_name: 'Unknown Committer', committer_email: '', message: 'Unknown Commit Message' }, branch: 'master', remotes: [] }); done(); }); }; var testGitlab = function(sut, done) { process.env.GITLAB_CI = true; process.env.CI_BUILD_NAME = 'spec:one'; process.env.CI_BUILD_ID = "1234"; process.env.CI_BUILD_REF = "e3e3e3e3e3e3e3e3e"; process.env.CI_BUILD_REF_NAME = "feature"; sut(function(err, options){ options.service_name.should.equal("gitlab-ci"); options.service_job_id.should.equal("1234"); options.git.should.eql({ head: { id: 'e3e3e3e3e3e3e3e3e', author_name: 'Unknown Author', author_email: '', committer_name: 'Unknown Committer', committer_email: '', message: 'Unknown Commit Message' }, branch: 'feature', remotes: [] }); done(); }); }; var testSurf = function(sut, done) { process.env.CI_NAME = 'surf'; process.env.SURF_SHA1 = "e3e3e3e3e3e3e3e3e"; process.env.SURF_REF = "feature"; sut(function(err, options){ options.service_name.should.equal("surf"); options.git.should.eql({ head: { id: 'e3e3e3e3e3e3e3e3e', author_name: 'Unknown Author', author_email: '', committer_name: 'Unknown Committer', committer_email: '', message: 'Unknown Commit Message' }, branch: 'feature', remotes: [] }); done(); }); }; function ensureLocalGitContext(options) { var path = require('path'); var fs = require('fs'); var baseDir = process.cwd(), dir = baseDir, gitDir; while (path.resolve('/') !== dir) { gitDir = path.join(dir, '.git'); var existsSync = fs.existsSync || path.existsSync; if (existsSync(path.join(gitDir, 'HEAD'))) break; dir = path.dirname(dir); } options = options || {}; var synthetic = path.resolve('/') === dir; var gitHead, content, branch, id, wrapUp = function() {}; if (synthetic) { branch = 'synthetic'; id = '424242424242424242'; gitHead = path.join('.git', 'HEAD'); var gitBranch = path.join('.git', 'refs', 'heads', branch); fs.mkdirSync('.git'); if (options.detached) { fs.writeFileSync(gitHead, id, { encoding: 'utf8' }); } else { fs.mkdirSync(path.join('.git', 'refs')); fs.mkdirSync(path.join('.git', 'refs', 'heads')); fs.writeFileSync(gitHead, "ref: refs/heads/" + branch, { encoding: 'utf8' }); fs.writeFileSync(gitBranch, id, { encoding: 'utf8' }); } wrapUp = function() { fs.unlinkSync(gitHead); if (!options.detached) { fs.unlinkSync(gitBranch); fs.rmdirSync(path.join('.git', 'refs', 'heads')); fs.rmdirSync(path.join('.git', 'refs')); } fs.rmdirSync('.git'); }; } else if (options.noGit) { fs.renameSync(gitDir, gitDir + '.bak'); wrapUp = function() { fs.renameSync(gitDir + '.bak', gitDir); }; } else if (options.detached) { gitHead = path.join(gitDir, 'HEAD'); content = fs.readFileSync(gitHead, 'utf8').trim(); var b = (content.match(/^ref: refs\/heads\/(\S+)$/) || [])[1]; if (!b) { id = content; } else { id = fs.readFileSync(path.join(gitDir, 'refs', 'heads', b), 'utf8').trim(); fs.writeFileSync(gitHead, id, 'utf8'); wrapUp = function() { fs.writeFileSync(gitHead, content, 'utf8'); }; } } else { content = fs.readFileSync(path.join(gitDir, 'HEAD'), 'utf8').trim(); branch = (content.match(/^ref: refs\/heads\/(\S+)$/) || [])[1]; id = branch ? fs.readFileSync(path.join(gitDir, 'refs', 'heads', branch), 'utf8').trim() : content; } return { id: id, branch: branch, wrapUp: wrapUp }; } package/test/handleInput.js000644 000765 000024 0000005065 13163045624014331 0ustar00000000 000000 var should = require('should'); var sinon = require('sinon-restore'); var index = require('../index'); var fs = require('fs'); logger = require('log-driver')({level : false}); describe("handleInput", function(){ afterEach(function() { sinon.restoreAll(); }); it ("returns an error when there's an error getting options", function(done){ sinon.stub(index, 'getOptions', function(cb){ return cb("some error", {}); }); var path = __dirname + "/../fixtures/onefile.lcov"; var input = fs.readFileSync(path, "utf8"); index.handleInput(input, function(err){ err.should.equal("some error"); done(); }); }); it ("returns an error when there's an error converting", function(done){ sinon.stub(index, 'getOptions', function(cb){ return cb(null, {}); }); sinon.stub(index, 'convertLcovToCoveralls', function(input, options, cb){ cb("some error"); }); var path = __dirname + "/../fixtures/onefile.lcov"; var input = fs.readFileSync(path, "utf8"); index.handleInput(input, function(err){ err.should.equal("some error"); done(); }); }); it ("returns an error when there's an error sending", function(done){ sinon.stub(index, 'getOptions', function(cb){ return cb(null, {}); }); sinon.stub(index, 'sendToCoveralls', function(postData, cb){ cb("some error"); }); var path = __dirname + "/../fixtures/onefile.lcov"; var input = fs.readFileSync(path, "utf8"); index.handleInput(input, function(err){ err.should.equal("some error"); done(); }); }); it ("returns an error when there's a bad status code", function(done){ sinon.stub(index, 'getOptions', function(cb){ return cb(null, {}); }); sinon.stub(index, 'sendToCoveralls', function(postData, cb){ cb(null, {statusCode : 500}, "body"); }); var path = __dirname + "/../fixtures/onefile.lcov"; var input = fs.readFileSync(path, "utf8"); index.handleInput(input, function(err){ err.should.equal("Bad response: 500 body"); done(); }); }); it ("completes successfully when there are no errors", function(done){ sinon.stub(index, 'getOptions', function(cb){ return cb(null, {}); }); sinon.stub(index, 'sendToCoveralls', function(postData, cb){ cb(null, {statusCode : 200}, "body"); }); var path = __dirname + "/../fixtures/onefile.lcov"; var input = fs.readFileSync(path, "utf8"); index.handleInput(input, function(err){ (err === null).should.equal(true); done(); }); }); }); package/test/logger.js000644 000765 000024 0000002152 13163045624013327 0ustar00000000 000000 var should = require('should'); var sinon = require('sinon-restore'); var index = require('../index'); describe("logger", function(){ it ("should log at debug level when --verbose is set", function(){ index.options.verbose = true; var logger = require('../index').logger(); logger.level.should.equal('warn'); }); it ("should log at debug level when NODE_COVERALLS_DEBUG is set in env", function(){ index.options.verbose = false; process.env.NODE_COVERALLS_DEBUG = 1; var logger = require('../index').logger(); logger.level.should.equal('warn'); }); it ("should log at debug level when NODE_COVERALLS_DEBUG is set in env as a string", function(){ index.options.verbose = false; process.env.NODE_COVERALLS_DEBUG = '1'; var logger = require('../index').logger(); logger.level.should.equal('warn'); }); it ("should log at warn level when NODE_COVERALLS_DEBUG not set and no --verbose", function(){ index.options.verbose = false; process.env.NODE_COVERALLS_DEBUG = 0; var logger = require('../index').logger(); logger.level.should.equal('error'); }); }); package/test/sendToCoveralls.js000644 000765 000024 0000004341 13163045624015161 0ustar00000000 000000 var should = require('should'); var request = require('request'); var sinon = require('sinon-restore'); var index = require('../index'); logger = require('log-driver')({level : false}); describe("sendToCoveralls", function(){ var realCoverallsHost; beforeEach(function() { realCoverallsHost = process.env.COVERALLS_ENDPOINT; }); afterEach(function() { sinon.restoreAll(); if (realCoverallsHost !== undefined) { process.env.COVERALLS_ENDPOINT = realCoverallsHost; } else { delete process.env.COVERALLS_ENDPOINT; } }); it ("passes on the correct params to request.post", function(done){ sinon.stub(request, 'post', function(obj, cb){ obj.url.should.equal('https://coveralls.io/api/v1/jobs'); obj.form.should.eql({json : '{"some":"obj"}'}); cb('err', 'response', 'body'); }); var obj = {"some":"obj"}; index.sendToCoveralls(obj, function(err, response, body){ err.should.equal('err'); response.should.equal('response'); body.should.equal('body'); done(); }); }); it ("allows sending to enterprise url", function(done){ process.env.COVERALLS_ENDPOINT = 'https://coveralls-ubuntu.domain.com'; sinon.stub(request, 'post', function(obj, cb){ obj.url.should.equal('https://coveralls-ubuntu.domain.com/api/v1/jobs'); obj.form.should.eql({json : '{"some":"obj"}'}); cb('err', 'response', 'body'); }); var obj = {"some":"obj"}; index.sendToCoveralls(obj, function(err, response, body){ err.should.equal('err'); response.should.equal('response'); body.should.equal('body'); done(); }); }); it ("writes output to stdout when --stdout is passed", function(done) { var obj = {"some":"obj"}; // set up mock process.stdout.write temporarily var origStdoutWrite = process.stdout.write; process.stdout.write = function(string) { if (string == JSON.stringify(obj)) { process.stdout.write = origStdoutWrite; return done(); } origStdoutWrite.apply(this, arguments); }; index.options.stdout = true; index.sendToCoveralls(obj, function(err, response, body) { response.statusCode.should.equal(200); }); }); });