From 0b331dc3a3895a8fda9281a93c2ee76091bbeeaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86ndrew=20Rininsland?= Date: Mon, 26 Oct 2015 14:35:48 +0000 Subject: [PATCH 1/4] Rewrote all unit tests to use Mocha Chai instead of Tape. --- package.json | 12 +- test/test.auth.js | 46 +++--- test/test.gist.js | 0 test/test.issue.js | 58 +++---- test/test.repo.js | 351 ++++++++++++++++++++++-------------------- test/test.toplevel.js | 0 test/test.user.js | 115 +++++++------- 7 files changed, 306 insertions(+), 276 deletions(-) delete mode 100644 test/test.gist.js delete mode 100644 test/test.toplevel.js diff --git a/package.json b/package.json index 9a557e19..dce781aa 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "xmlhttprequest": "~1.7.0" }, "devDependencies": { + "chai": "^3.4.0", "codecov": "^1.0.1", "gulp": "^3.9.0", "gulp-jscs": "^3.0.1", @@ -18,12 +19,17 @@ "jshint": "^2.5.8", "jshint-stylish": "^2.0.1", "plato": "^1.4.0", - "tape": "^3.0.3" + "karma": "^0.13.14", + "karma-coverage": "^0.5.3", + "karma-mocha": "^0.2.0", + "mocha": "^2.3.3", + "sinon": "^1.17.2", + "sinon-chai": "^2.8.0" }, "scripts": { - "test": "tape test/*.js && npm run-script jshint", + "test": "mocha test/*.js && npm run-script jshint", "jshint": "jshint github.js test/", - "codecov": "istanbul cover tape test/*.js && cat ./coverage/coverage.json | ./node_modules/.bin/codecov" + "codecov": "istanbul cover ./node_modules/mocha/bin/_mocha -- -R spec && cat ./coverage/lcov.info | ./node_modules/.bin/codecov" }, "repository": { "type": "git", diff --git a/test/test.auth.js b/test/test.auth.js index 6b5d7244..643076af 100644 --- a/test/test.auth.js +++ b/test/test.auth.js @@ -1,41 +1,45 @@ 'use strict'; -var test = require('tape'); //jshint ignore:line -var Github = require("../"); +// module dependencies +var chai = require('chai'), + sinonChai = require('sinon-chai'); + +var Github = require('../'); var test_user = require('./user.json'); -test("Basic Auth - Pass", function(t) { - var timeout = setTimeout(function () { t.fail(); }, 10000); +// Use should flavour for Mocha +var should = chai.should(); +chai.use(sinonChai); + +describe('Github constructor', function() { var github = new Github({ username: test_user.USERNAME, password: test_user.PASSWORD, - auth: "basic" + auth: 'basic' }); var user = github.getUser(); - - user.notifications(function(err) { - t.error(err, 'user is authd'); + + it('should authenticate and return no errors', function(done){ + user.notifications(function(err){ + should.not.exist(err); + done(); + }); }); - - clearTimeout(timeout); - t.end(); }); -test("Basic Auth - Fail", function(t) { - var timeout = setTimeout(function () { t.fail(); }, 10000); +describe('Github constructor (failing case)', function() { var github = new Github({ username: test_user.USERNAME, password: 'fake124', - auth: "basic" + auth: 'basic' }); var user = github.getUser(); - user.notifications(function(err) { - t.ok(err, 'user is not authd'); - t.equals(JSON.parse(err.request.responseText).message, 'Bad credentials', 'confirm error'); + it('should fail authentication and return err', function(done){ + user.notifications(function(err){ + err.request.status.should.equal(401, 'Return 401 status for bad auth'); + JSON.parse(err.request.responseText).message.should.equal('Bad credentials'); + done(); + }); }); - - clearTimeout(timeout); - t.end(); - }); diff --git a/test/test.gist.js b/test/test.gist.js deleted file mode 100644 index e69de29b..00000000 diff --git a/test/test.issue.js b/test/test.issue.js index e28ccb81..0c83e5b7 100644 --- a/test/test.issue.js +++ b/test/test.issue.js @@ -1,36 +1,40 @@ 'use strict'; -var test = require('tape'); //jshint ignore:line -var Github = require("../"); +// module dependencies +var chai = require('chai'), sinonChai = require('sinon-chai'); + +// GitHub data +var Github = require('../'); var test_user = require('./user.json'); -test("Issues API", function(t) { - var github = new Github({ - username: test_user.USERNAME, - password: test_user.PASSWORD, - auth: "basic" - }); +// Use should flavour for Mocha +var should = chai.should(); +chai.use(sinonChai); - var issues = github.getIssues('mikedeboertest', 'TestRepo'); +describe('Github.Issue', function() { + var github = new Github({ + username : test_user.USERNAME, + password : test_user.PASSWORD, + auth : 'basic' + }); - t.test('issues.list', function(q) { - issues.list({},function(err, issues) { - q.error(err); - t.equals(issues.length > 0, true, 'Issues!'); - q.end(); - }); - t.end(); - }); + var issues = github.getIssues('mikedeboertest', 'TestRepo'); - t.test('issues.comment', function(q) { - issues.list({},function(err, issuesList) { - issues.comment(issuesList[0], 'Comment test', function(err, res){ - q.error(err); - t.equals(res.body, 'Comment test', 'Comments!'); - q.end(); - }); - }); + it('should list issues', function(done) { + issues.list({}, function(err, issues) { + should.not.exist(err); + issues.should.have.length.above(0); + done(); }); + }); - -}); \ No newline at end of file + it('should post issue comment', function(done) { + issues.list({}, function(err, issuesList) { + issues.comment(issuesList[0], 'Comment test', function(err, res) { + should.not.exist(err); + res.body.should.equal('Comment test'); + done(); + }); + }); + }); +}); diff --git a/test/test.repo.js b/test/test.repo.js index 9d5f3586..57d49a20 100644 --- a/test/test.repo.js +++ b/test/test.repo.js @@ -1,291 +1,302 @@ 'use strict'; -var test = require('tape'); //jshint ignore:line -var Github = require("../"); +// module dependencies +var chai = require('chai'), sinonChai = require('sinon-chai'); + +var Github = require('../'); var test_user = require('./user.json'); -test("Repo API", function(t) { - var timeout = setTimeout(function () { t.fail(); }, 100000); - var github = new Github({ - username: test_user.USERNAME, - password: test_user.PASSWORD, - auth: "basic" - }); - var repo = github.getRepo('michael', 'github'); +// Use should flavour for Mocha +var should = chai.should(); +chai.use(sinonChai); - t.test('repo.show', function(q) { - repo.show(function(err, res) { - q.error(err, 'show repo'); - q.equals(res.full_name, 'michael/github', 'repo name'); - q.end(); - }); +describe('Github.Repository', function() { + var github = new Github({ + username : test_user.USERNAME, + password : test_user.PASSWORD, + auth : 'basic' + }); + var repo = github.getRepo('michael', 'github'); + + it('should show repo', function(done) { + repo.show(function(err, res) { + should.not.exist(err); + res.full_name.should.equal('michael/github'); + done(); }); + }); - t.test('repo.contents', function(q) { - repo.contents('master', './', function(err) { - q.error(err, 'get repo contents'); - q.end(); - }); + it('should show repo contents', function(done) { + repo.contents('master', './', function(err) { + should.not.exist(err); + // @TODO write better assertion. + done(); }); + }); - t.test('repo.fork', function(q) { - repo.fork(function(err) { - q.error(err, 'test fork repo'); - q.end(); - }); + it('should fork repo', function(done) { + repo.fork(function(err) { + should.not.exist(err); + // @TODO write better assertion. + done(); }); + }); - t.test('repo.contributors', function(q) { - repo.contributors(function(err, res) { - q.error(err, 'repo contributors'); - q.ok(res instanceof Array, 'list of contributors'); - q.ok(res.length, 'at least one contributor'); - q.ok(res[0].author, 'contributor info'); - q.ok(res[0].total, 'total number of commits'); - q.ok(res[0].weeks, 'weekly hash'); - q.end(); - }); + it('should show repo contributors', function(done) { + repo.contributors(function(err, res) { + should.not.exist(err); + res.should.be.instanceof(Array); + res.should.have.length.above(1); + should.exist(res[0].author); + should.exist(res[0].total); + should.exist(res[0].weeks); + done(); }); + }); - //@TODO repo.branch, repo.pull + //@TODO repo.branch, repo.pull - t.test('repo.listBranches', function(q) { - repo.listBranches(function(err) { - q.error(err, 'list branches'); - q.end(); - }); + it('should list repo branches', function(done) { + repo.listBranches(function(err) { + should.not.exist(err); + done(); }); + }); - t.test('repo.read', function(q) { - repo.read('master', 'README.md', function(err, res) { - q.notEquals(res.indexOf('# Github.js'), -1, 'Returned README'); - q.end(); - }); + it('should read repo', function(done) { + repo.read('master', 'README.md', function(err, res) { + res.indexOf('# Github.js').should.be.above(-1); + done(); }); + }); - t.test('repo.getCommit', function(q) { - repo.getCommit('master', '20fcff9129005d14cc97b9d59b8a3d37f4fb633b', function(err, commit) { - q.error(err, 'get commit' + err); - q.equals(commit.message, 'v0.10.4', 'Returned commit message.'); - q.equals(commit.author.date, '2015-03-20T17:01:42Z', 'Got correct date.'); - q.end(); - }); + it('should get commit from repo', function(done) { + repo.getCommit('master', '20fcff9129005d14cc97b9d59b8a3d37f4fb633b', function(err, commit) { + should.not.exist(err); + commit.message.should.equal('v0.10.4'); + commit.author.date.should.equal('2015-03-20T17:01:42Z'); + done(); }); + }); - t.test('repo.getSha', function(q) { - repo.getSha('master', '.gitignore', function(err, sha) { - q.error(err, 'get sha error: ' + err); - q.equals(sha, '8293a5658aed839ed52fb0e5bd9e6c467c992d3d', 'Returned sha message.'); - q.end(); - }); + it('should get a SHA from a repo', function(done) { + repo.getSha('master', '.gitignore', function(err, sha) { + should.not.exist(err); + sha.should.equal('8293a5658aed839ed52fb0e5bd9e6c467c992d3d'); + done(); }); + }); - t.test('getRepo(fullname)', function(q) { - var repo2 = github.getRepo('michael/github'); - repo2.show(function(err, res) { - q.error(err, 'show repo'); - q.equals(res.full_name, 'michael/github', 'repo name'); - q.end(); - }); + it('should get a repo by fullname', function(done) { + var repo2 = github.getRepo('michael/github'); + repo2.show(function(err, res) { + should.not.exist(err); + res.full_name.should.equal('michael/github'); + done(); }); - - clearTimeout(timeout); - t.end(); - + }); }); var repoTest = Date.now(); -test('Create Repo', function(t) { - var timeout = setTimeout(function () { t.fail(); }, 10000); +describe('Creating new Github.Repository', function() { var github = new Github({ - username: test_user.USERNAME, - password: test_user.PASSWORD, - auth: "basic" + username : test_user.USERNAME, + password : test_user.PASSWORD, + auth : 'basic' }); var user = github.getUser(); - t.test('user.createRepo', function(q) { - user.createRepo({ "name": repoTest }, function (err, res) { - q.error(err); - q.equals(res.name, repoTest.toString(), 'Repo created'); - q.end(); + it('should create repo', function(done) { + user.createRepo({'name' : repoTest}, function(err, res) { + should.not.exist(err); + res.name.should.equal(repoTest.toString()); + done(); }); }); + var repo = github.getRepo(test_user.USERNAME, repoTest); - t.test('repo.write', function(q) { + it('should write to repo', function(done) { repo.write('master', 'TEST.md', 'THIS IS A TEST', 'Creating test', function(err) { - q.error(err); - q.end(); + should.not.exist(err); + // @TODO write a better assertion. + done(); }); }); - t.test('repo.writeBranch', function(q) { + it('should write to repo branch', function(done) { + this.timeout(8000); // Bit of a longer timeout + repo.branch('master', 'dev', function(err) { - q.error(err); + should.not.exist(err); repo.write('dev', 'TEST.md', 'THIS IS AN UPDATED TEST', 'Updating test', function(err) { - q.error(err); - repo.read('dev', 'TEST.md', function(err, obj) { - t.equals('THIS IS AN UPDATED TEST', obj); - q.error(err); - q.end(); + should.not.exist(err); + repo.read('dev', 'TEST.md', function(err, res) { + res.should.equal('THIS IS AN UPDATED TEST'); + should.not.exist(err); + done(); }); }); }); }); - t.test('repo.getRef', function(q) { + it('should get ref from repo', function(done) { repo.getRef('heads/master', function(err) { - q.error(err); - q.end(); + should.not.exist(err); + // @TODO write better assertion + done(); }); }); - t.test('repo.createRef', function(q) { + it('should create ref on repo', function(done) { repo.getRef('heads/master', function(err, sha) { - var refSpec = { - ref: 'refs/heads/new-test-branch', - sha: sha - }; + var refSpec = {ref : 'refs/heads/new-test-branch', sha : sha}; repo.createRef(refSpec, function(err) { - q.error(err); - q.end(); + should.not.exist(err); + // @TODO write better assertion + done(); }); }); }); - t.test('repo.deleteRef', function(q) { + it('should delete ref on repo', function(done) { repo.deleteRef('heads/new-test-branch', function(err) { - q.error(err); - q.end(); + should.not.exist(err); + // @TODO write better assertion + done(); }); }); - t.test('repo.listTags', function(q) { + it('should list tags on repo', function(done) { repo.listTags(function(err) { - q.error(err); - q.end(); + should.not.exist(err); + // @TODO write better assertion + done(); }); }); - t.test('repo.listPulls', function(q) { + it('should list pulls on repo', function(done) { repo.listPulls('open', function(err) { - q.error(err); - q.end(); + should.not.exist(err); + // @TODO write better assertion + done(); }); }); - t.test('repo.getPull', function(q) { + it('should get pull requests on repo', function(done) { var repo = github.getRepo('michael', 'github'); repo.getPull(153, function(err) { - q.error(err); - q.end(); + should.not.exist(err); + // @TODO write better assertion + done(); }); }); - t.test('repo.listPulls', function(q) { + it('should list pull requests on repo', function(done) { repo.listPulls('open', function(err) { - q.error(err); - q.end(); + should.not.exist(err); + done(); }); }); - t.test('repo.writeAuthorAndCommitter', function(q) { + it('should write author and committer to repo', function(done) { var options = { - author: {name: 'Author Name', email: 'author@example.com'}, - committer: {name: 'Committer Name', email: 'committer@example.com'} + author : {name : 'Author Name', email : 'author@example.com'}, + committer : {name : 'Committer Name', email : 'committer@example.com'} }; repo.write('dev', 'TEST.md', 'THIS IS A TEST BY AUTHOR AND COMMITTER', 'Updating', options, function(err, res) { - q.error(err); + should.not.exist(err); repo.getCommit('dev', res.commit.sha, function(err, commit) { - q.error(err); - q.equals(commit.author.name, 'Author Name', 'Got correct author name.'); - q.equals(commit.author.email, 'author@example.com', 'Got correct author email.'); - q.equals(commit.committer.name, 'Committer Name', 'Got correct committer name.'); - q.equals(commit.committer.email, 'committer@example.com', 'Got correct committer email.'); - q.end(); + should.not.exist(err); + commit.author.name.should.equal('Author Name'); + commit.author.email.should.equal('author@example.com'); + commit.committer.name.should.equal('Committer Name'); + commit.committer.email.should.equal('committer@example.com'); + + done(); }); }); }); - t.test('repo.writeChinese', function(q) { + it('should be able to write CJK unicode to repo', function(done) { repo.write('master', '中文测试.md', 'THIS IS A TEST', 'Creating test', function(err) { - q.error(err); - q.end(); + should.not.exist(err); + // @TODO write better assertion + done(); }); }); - t.test('repo.writeUnicodeContent', function(q) { + it('should be able to write unicode to repo', function(done) { repo.write('master', 'TEST.md', '\u2014', 'Long dash unicode', function(err) { - q.error(err); + should.not.exist(err); + repo.read('master', 'TEST.md', function(err, obj) { - q.error(err); - t.equals('\u2014', obj); + should.not.exist(err); + obj.should.equal('\u2014'); + + done(); }); - q.end(); }); }); - t.test('Regression test for _request (#14)', function(q){ + it('should pass a regression test for _request (#14)', function(done) { + this.timeout(8000); // Bit of a longer timeout + repo.getRef('heads/master', function(err, sha) { - var refSpec = { - ref: 'refs/heads/testing-14', - sha: sha - }; + var refSpec = {ref : 'refs/heads/testing-14', sha : sha}; repo.createRef(refSpec, function(err) { - q.error(err, 'Test branch created'); + should.not.exist(err); - // Triggers GET: https://api.github.com/repos/michael/cmake_cdt7_stalled/git/refs/heads/prose-integration + // Triggers GET: + // https://api.github.com/repos/michael/cmake_cdt7_stalled/git/refs/heads/prose-integration repo.getRef('heads/master', function(err) { - q.error(err, 'Regression test ready'); + should.not.exist(err); - // Triggers DELETE: https://api.github.com/repos/michael/cmake_cdt7_stalled/git/refs/heads/prose-integration + // Triggers DELETE: + // https://api.github.com/repos/michael/cmake_cdt7_stalled/git/refs/heads/prose-integration repo.deleteRef('heads/testing-14', function(err, res, xhr) { - q.error(err); - q.equals(xhr.status, 204, 'Returns 204'); - q.end(); + should.not.exist(err); + xhr.status.should.equal(204); + done(); }); }); }); }); }); - - clearTimeout(timeout); - t.end(); }); -test('delete Repo', function(t) { - var timeout = setTimeout(function () { t.fail(); }, 10000); +describe('deleting a Github.Repository', function() { var github = new Github({ - username: test_user.USERNAME, - password: test_user.PASSWORD, - auth: "basic" + username : test_user.USERNAME, + password : test_user.PASSWORD, + auth : 'basic' }); var repo = github.getRepo(test_user.USERNAME, repoTest); - repo.deleteRepo(function(err, res) { - t.error(err); - t.equals(res, true, 'Repo Deleted'); - clearTimeout(timeout); - t.end(); + it('should delete the repo', function(done){ + repo.deleteRepo(function(err, res) { + should.not.exist(err); + res.should.be.true; //jshint ignore:line + done(); + }); }); }); -test('Repo Returns commit errors correctly', function(t) { - var timeout = setTimeout(function () { t.fail(); }, 10000); +describe('Repo returns commit errors correctly', function() { var github = new Github({ - username: test_user.USERNAME, - password: test_user.PASSWORD, - auth: "basic" + username : test_user.USERNAME, + password : test_user.PASSWORD, + auth : 'basic' }); var repo = github.getRepo(test_user.USERNAME, test_user.REPO); - repo.commit("broken-parent-hash", "broken-tree-hash", "commit message", function(err){ - t.ok(err, 'error thrown for bad commit'); - t.ok(err.request); - t.equals(err.request.status, 422, 'Returns 422 status'); - clearTimeout(timeout); - t.end(); + it('should fail on broken commit', function(done){ + repo.commit('broken-parent-hash', 'broken-tree-hash', 'commit message', function(err) { + should.exist(err); + should.exist(err.request); + err.request.status.should.equal(422); + done(); + }); }); }); diff --git a/test/test.toplevel.js b/test/test.toplevel.js deleted file mode 100644 index e69de29b..00000000 diff --git a/test/test.user.js b/test/test.user.js index e9aee32d..d9c1aea8 100644 --- a/test/test.user.js +++ b/test/test.user.js @@ -1,26 +1,31 @@ 'use strict'; -var test = require('tape'); //jshint ignore:line -var Github = require("../"); +// module dependencies +var chai = require('chai'), sinonChai = require('sinon-chai'); + +var Github = require('../'); var test_user = require('./user.json'); -test("User API", function(t) { - var timeout = setTimeout(function () { t.fail(); }, 100000); +// Use should flavour for Mocha +var should = chai.should(); +chai.use(sinonChai); + +describe('Github.User', function() { var github = new Github({ username: test_user.USERNAME, password: test_user.PASSWORD, - auth: "basic" + auth: 'basic' }); var user = github.getUser(); - t.test('user.repos', function(q) { + it('should get user.repos', function(done) { user.repos(function(err) { - q.error(err, 'user orgs'); - q.end(); + should.not.exist(err); + done(); }); }); - t.test('user.repos with options', function(q) { + it('should get user.repos with options', function(done) { var options = { type: 'owner', sort: 'updated', @@ -28,34 +33,35 @@ test("User API", function(t) { page: 1 }; user.repos(options, function(err, repos) { - q.equals(repos.length, 10); - q.error(err, 'user repos'); - q.end(); + repos.should.have.length(10); + should.not.exist(err); + + done(); }); }); - t.test('user.orgs', function(q) { + it('should get user.orgs', function(done) { user.orgs(function(err) { - q.error(err, 'user orgs'); - q.end(); + should.not.exist(err); + done(); }); }); - t.test('user.gists', function(q) { + it('should get user.gists', function(done) { user.gists(function(err) { - q.error(err, 'user gists'); - q.end(); + should.not.exist(err); + done(); }); }); - t.test('user.notifications', function(q) { + it('should get user.notifications', function(done) { user.notifications(function(err) { - q.error(err, 'user notifications'); - q.end(); + should.not.exist(err); + done(); }); }); - t.test('user.notifications with options', function(q) { + it('should get user.notifications with options', function(done) { var options = { all: true, participating: true, @@ -63,77 +69,76 @@ test("User API", function(t) { before: '2015-02-01T00:00:00Z' }; user.notifications(options, function(err) { - q.error(err, 'user notifications'); - q.end(); + should.not.exist(err); + done(); }); }); - t.test('user.show', function(q) { + it('should show user', function(done) { user.show('ingalls', function(err) { - q.error(err, 'user show'); - q.end(); + should.not.exist(err); + done(); }); }); - t.test('user.userRepos', function(q) { + it('should show user\'s repos', function(done) { + this.timeout(8000); // Bit of a longer timeout + user.userRepos(test_user.USERNAME, function(err) { - q.error(err, 'alt user repos'); - q.end(); + should.not.exist(err); + done(); }); }); - t.test('user.userStarred', function(q) { + it('should show user\'s starred repos', function(done) { user.userStarred(test_user.USERNAME, function(err) { - q.error(err, 'alt user starred'); - q.end(); + should.not.exist(err); + done(); }); }); - t.test('user.userGists', function(q) { + it('should show user\'s gists', function(done) { user.userGists(test_user.USERNAME, function(err) { - q.error(err, 'alt user gists'); - q.end(); + should.not.exist(err); + done(); }); }); - t.test('user.orgRepos', function(q) { + it('should show user\'s organisation repos', function(done) { user.orgRepos('openaddresses', function(err) { - q.error(err, 'org users'); - q.end(); + should.not.exist(err); + done(); }); }); - t.test('user.follow', function(q) { + it('should follow user', function(done) { user.follow('ingalls', function(err) { - q.error(err, 'follow ingalls'); - q.end(); + should.not.exist(err); + done(); }); }); - t.test('user.unfollow', function(q) { + it('should unfollow user', function(done) { user.unfollow('ingalls', function(err) { - q.error(err, 'unfollow ingalls'); - q.end(); + should.not.exist(err); + done(); }); }); - t.test('user.createRepo', function(q) { - var test_user = require('./user.json'); + it('should create a repo', function(done) { + this.timeout(8000); // Bit of a longer timeout var repoTest = Date.now(); var github = new Github({ username: test_user.USERNAME, password: test_user.PASSWORD, - auth: "basic" + auth: 'basic' }); var user = github.getUser(); - user.createRepo({ "name": repoTest }, function (err, res) { - q.error(err); - q.equals(res.name, repoTest.toString(), 'Repo created'); - q.end(); + user.createRepo({ 'name': repoTest }, function (err, res) { + should.not.exist(err); + res.name.should.equal(repoTest.toString()); + done(); }); }); - - clearTimeout(timeout); - t.end(); }); From 4b120b66cbe4b263c48a1bb3bee38982b0a7f78d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86ndrew=20Rininsland?= Date: Mon, 26 Oct 2015 14:46:22 +0000 Subject: [PATCH 2/4] Changed where long dash unicode test was writing. Should fix #246. --- test/test.repo.js | 6 ++-- test/test.search.js | 86 ++++++++++++++++++++++----------------------- test/test.user.js | 7 ++-- 3 files changed, 48 insertions(+), 51 deletions(-) diff --git a/test/test.repo.js b/test/test.repo.js index 57d49a20..9fae6bd9 100644 --- a/test/test.repo.js +++ b/test/test.repo.js @@ -97,7 +97,7 @@ describe('Github.Repository', function() { }); }); -var repoTest = Date.now(); +var repoTest = Math.floor(Math.random() * (100000 - 0)) + 0; describe('Creating new Github.Repository', function() { var github = new Github({ @@ -228,10 +228,10 @@ describe('Creating new Github.Repository', function() { }); it('should be able to write unicode to repo', function(done) { - repo.write('master', 'TEST.md', '\u2014', 'Long dash unicode', function(err) { + repo.write('master', 'TEST_unicode.md', '\u2014', 'Long dash unicode', function(err) { should.not.exist(err); - repo.read('master', 'TEST.md', function(err, obj) { + repo.read('master', 'TEST_unicode.md', function(err, obj) { should.not.exist(err); obj.should.equal('\u2014'); diff --git a/test/test.search.js b/test/test.search.js index 416b38c9..d0f85a2e 100644 --- a/test/test.search.js +++ b/test/test.search.js @@ -1,61 +1,59 @@ 'use strict'; -var test = require('tape'); //jshint ignore:line -var Github = require("../"); +// module dependencies +var chai = require('chai'), sinonChai = require('sinon-chai'); + +var Github = require('../'); var test_user = require('./user.json'); -test("User API", function(t) { - var timeout = setTimeout(function () { t.fail(); }, 100000); - var github = new Github({ - username: test_user.USERNAME, - password: test_user.PASSWORD, - auth: "basic" - }); - // var user = github.getUser(); +// Use should flavour for Mocha +var should = chai.should(); +chai.use(sinonChai); +describe('Github.Search', function() { + var github = new Github({ + username: test_user.USERNAME, + password: test_user.PASSWORD, + auth: "basic" + }); - t.test('Search.repositories', function(q) { - var search = github.getSearch("tetris+language:assembly&sort=stars&order=desc"); - var options = null; + it('should search.repositories', function(done) { + var search = github.getSearch('tetris+language:assembly&sort=stars&order=desc'); + var options = null; - search.repositories(options, function (err) { - q.error(err, 'search repositories'); - q.end(); - }); + search.repositories(options, function (err) { + should.not.exist(err); + done(); }); + }); - t.test('Search.code', function(q) { - var search = github.getSearch("addClass+in:file+language:js+repo:jquery/jquery"); - var options = null; + it('should search.code', function(done) { + var search = github.getSearch('addClass+in:file+language:js+repo:jquery/jquery'); + var options = null; - search.code(options, function (err) { - q.error(err, 'search code'); - q.end(); - }); + search.code(options, function (err) { + should.not.exist(err); + done(); }); + }); - t.test('Search.issues', function(q) { - var search = github.getSearch("windows+label:bug+language:python+state:open&sort=created&order=asc"); - var options = null; + it('should search.issues', function(done) { + var search = github.getSearch('windows+label:bug+language:python+state:open&sort=created&order=asc'); + var options = null; - search.issues(options, function (err) { - q.error(err, 'search issues'); - q.end(); - }); + search.issues(options, function (err) { + should.not.exist(err); + done(); }); + }); - t.test('Search.users', function(q) { - var search = github.getSearch("tom+repos:%3E42+followers:%3E1000"); - var options = null; + it('should search.users', function(done) { + var search = github.getSearch('tom+repos:%3E42+followers:%3E1000'); + var options = null; - search.users(options, function (err) { - q.error(err, 'search users'); - q.end(); - }); + search.users(options, function (err) { + should.not.exist(err); + done(); }); - - - - clearTimeout(timeout); - t.end(); - }); + }); +}); diff --git a/test/test.user.js b/test/test.user.js index d9c1aea8..f684e984 100644 --- a/test/test.user.js +++ b/test/test.user.js @@ -11,6 +11,8 @@ var should = chai.should(); chai.use(sinonChai); describe('Github.User', function() { + this.timeout(8000); // Bit of a longer timeout + var github = new Github({ username: test_user.USERNAME, password: test_user.PASSWORD, @@ -82,8 +84,6 @@ describe('Github.User', function() { }); it('should show user\'s repos', function(done) { - this.timeout(8000); // Bit of a longer timeout - user.userRepos(test_user.USERNAME, function(err) { should.not.exist(err); done(); @@ -126,8 +126,7 @@ describe('Github.User', function() { }); it('should create a repo', function(done) { - this.timeout(8000); // Bit of a longer timeout - var repoTest = Date.now(); + var repoTest = Math.floor(Math.random() * (100000 - 0)) + 0; var github = new Github({ username: test_user.USERNAME, password: test_user.PASSWORD, From 2eec6af8068a5e26d4c991bb10cd63380a2452d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86ndrew=20Rininsland?= Date: Tue, 27 Oct 2015 00:36:28 +0000 Subject: [PATCH 3/4] Adds Karma. --- gulpfile.js | 42 ++++++++++++++++++++++-- package.json | 10 ++++-- test/test.auth.js | 49 +++++++++++++++++---------- test/test.issue.js | 36 ++++++++++++-------- test/test.repo.js | 80 ++++++++++++++++++++++++++++----------------- test/test.search.js | 30 ++++++++++------- test/test.user.js | 36 ++++++++++++-------- test/user.json | 6 +--- 8 files changed, 194 insertions(+), 95 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 0d24394e..c65cf0c2 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -5,6 +5,8 @@ var jshint = require('gulp-jshint'); var jscs = require('gulp-jscs'); var rename = require('gulp-rename'); var uglify = require('gulp-uglify'); +var path = require('path'); +var karma = require('karma'); gulp.task('lint', function() { return gulp.src('github.js') @@ -17,7 +19,12 @@ gulp.task('lint', function() { .pipe(gulp.dest('.')); }); -gulp.task('test', function() { +gulp.task('test', function(done) { + runTests(true, done); +}); + +gulp.task('test:auto', function(done) { + runTests(false, done); }); gulp.task('build', function() { @@ -29,4 +36,35 @@ gulp.task('build', function() { gulp.task('default', function() { gulp.start('lint', 'test', 'build'); -}); \ No newline at end of file +}); + +function runTests (singleRun, done) { + var reporters = ['mocha']; + var preprocessors = {}; + + var pathSrcJs = [ + path.join(__dirname, 'github.js') + ]; + + if (singleRun) { + pathSrcJs.forEach(function(path) { + preprocessors[path] = ['coverage']; + }); + reporters.push('coverage'); + + preprocessors['test/user.json'] = ['json_fixtures']; + } + + var localConfig = { + configFile: path.join(__dirname, './karma.conf.js'), + singleRun: singleRun, + autoWatch: !singleRun, + reporters: reporters, + preprocessors: preprocessors + }; + + var server = new karma.Server(localConfig, function(failCount) { + done(failCount ? new Error('Failed ' + failCount + ' tests.') : null); + }); + server.start(); +} diff --git a/package.json b/package.json index dce781aa..4e505a9e 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,11 @@ { "name": "github-api", - "version": "0.10.6", + "version": "0.10.7", "description": "A higher-level wrapper around the Github API.", "main": "github.js", "dependencies": { "js-base64": "^2.1.8", + "karma-json-fixtures-preprocessor": "0.0.5", "xmlhttprequest": "~1.7.0" }, "devDependencies": { @@ -18,11 +19,16 @@ "istanbul": "^0.3.13", "jshint": "^2.5.8", "jshint-stylish": "^2.0.1", - "plato": "^1.4.0", "karma": "^0.13.14", + "karma-chai": "^0.1.0", "karma-coverage": "^0.5.3", "karma-mocha": "^0.2.0", + "karma-mocha-reporter": "^1.1.1", + "karma-phantomjs-launcher": "^0.2.1", + "karma-sinon": "^1.0.4", "mocha": "^2.3.3", + "phantomjs": "^1.9.18", + "plato": "^1.4.0", "sinon": "^1.17.2", "sinon-chai": "^2.8.0" }, diff --git a/test/test.auth.js b/test/test.auth.js index 643076af..0a3c2d05 100644 --- a/test/test.auth.js +++ b/test/test.auth.js @@ -1,23 +1,32 @@ 'use strict'; -// module dependencies -var chai = require('chai'), - sinonChai = require('sinon-chai'); +var test_user, github, user; -var Github = require('../'); -var test_user = require('./user.json'); +if (typeof window === 'undefined') { + // module dependencies + var chai = require('chai'), + sinonChai = require('sinon-chai'); -// Use should flavour for Mocha -var should = chai.should(); -chai.use(sinonChai); + var Github = require('../'); + test_user = require('./user.json'); + + // Use should flavour for Mocha + var should = chai.should(); + chai.use(sinonChai); +} describe('Github constructor', function() { - var github = new Github({ - username: test_user.USERNAME, - password: test_user.PASSWORD, - auth: 'basic' + before(function(){ + if (typeof window !== 'undefined') test_user = window.__fixtures__['test/user']; + + github = new Github({ + username: test_user.USERNAME, + password: test_user.PASSWORD, + auth: 'basic' + }); + + user = github.getUser(); }); - var user = github.getUser(); it('should authenticate and return no errors', function(done){ user.notifications(function(err){ @@ -28,12 +37,16 @@ describe('Github constructor', function() { }); describe('Github constructor (failing case)', function() { - var github = new Github({ - username: test_user.USERNAME, - password: 'fake124', - auth: 'basic' + before(function(){ + if (typeof window !== 'undefined') test_user = window.__fixtures__['test/user']; + + github = new Github({ + username: test_user.USERNAME, + password: 'fake124', + auth: 'basic' + }); + user = github.getUser(); }); - var user = github.getUser(); it('should fail authentication and return err', function(done){ user.notifications(function(err){ diff --git a/test/test.issue.js b/test/test.issue.js index 0c83e5b7..e85e6f83 100644 --- a/test/test.issue.js +++ b/test/test.issue.js @@ -1,24 +1,32 @@ 'use strict'; -// module dependencies -var chai = require('chai'), sinonChai = require('sinon-chai'); +var test_user, github, issues; -// GitHub data -var Github = require('../'); -var test_user = require('./user.json'); +if (typeof window === 'undefined') { + // module dependencies + var chai = require('chai'), + sinonChai = require('sinon-chai'); -// Use should flavour for Mocha -var should = chai.should(); -chai.use(sinonChai); + var Github = require('../'); + test_user = require('./user.json'); + + // Use should flavour for Mocha + var should = chai.should(); + chai.use(sinonChai); +} describe('Github.Issue', function() { - var github = new Github({ - username : test_user.USERNAME, - password : test_user.PASSWORD, - auth : 'basic' - }); + before(function(){ + if (typeof window !== 'undefined') test_user = window.__fixtures__['test/user']; - var issues = github.getIssues('mikedeboertest', 'TestRepo'); + github = new Github({ + username : test_user.USERNAME, + password : test_user.PASSWORD, + auth : 'basic' + }); + + issues = github.getIssues('mikedeboertest', 'TestRepo'); + }); it('should list issues', function(done) { issues.list({}, function(err, issues) { diff --git a/test/test.repo.js b/test/test.repo.js index 9fae6bd9..9b285932 100644 --- a/test/test.repo.js +++ b/test/test.repo.js @@ -1,22 +1,32 @@ 'use strict'; -// module dependencies -var chai = require('chai'), sinonChai = require('sinon-chai'); +var github, repo, user, test_user; -var Github = require('../'); -var test_user = require('./user.json'); +if (typeof window === 'undefined') { + // module dependencies + var chai = require('chai'), + sinonChai = require('sinon-chai'); -// Use should flavour for Mocha -var should = chai.should(); -chai.use(sinonChai); + var Github = require('../'); + test_user = require('./user.json'); + + // Use should flavour for Mocha + var should = chai.should(); + chai.use(sinonChai); +} describe('Github.Repository', function() { - var github = new Github({ - username : test_user.USERNAME, - password : test_user.PASSWORD, - auth : 'basic' + before(function(){ + if (typeof window !== 'undefined') test_user = window.__fixtures__['test/user']; + + github = new Github({ + username : test_user.USERNAME, + password : test_user.PASSWORD, + auth : 'basic' + }); + + repo = github.getRepo('michael', 'github'); }); - var repo = github.getRepo('michael', 'github'); it('should show repo', function(done) { repo.show(function(err, res) { @@ -82,7 +92,7 @@ describe('Github.Repository', function() { it('should get a SHA from a repo', function(done) { repo.getSha('master', '.gitignore', function(err, sha) { should.not.exist(err); - sha.should.equal('8293a5658aed839ed52fb0e5bd9e6c467c992d3d'); + sha.should.equal('743f72052be92b3e7f42b8318f2663a9011ef5be'); done(); }); }); @@ -100,12 +110,18 @@ describe('Github.Repository', function() { var repoTest = Math.floor(Math.random() * (100000 - 0)) + 0; describe('Creating new Github.Repository', function() { - var github = new Github({ - username : test_user.USERNAME, - password : test_user.PASSWORD, - auth : 'basic' + before(function(){ + if (typeof window !== 'undefined') test_user = window.__fixtures__['test/user']; + + github = new Github({ + username : test_user.USERNAME, + password : test_user.PASSWORD, + auth : 'basic' + }); + + user = github.getUser(); + repo = github.getRepo(test_user.USERNAME, repoTest); }); - var user = github.getUser(); it('should create repo', function(done) { user.createRepo({'name' : repoTest}, function(err, res) { @@ -115,8 +131,6 @@ describe('Creating new Github.Repository', function() { }); }); - var repo = github.getRepo(test_user.USERNAME, repoTest); - it('should write to repo', function(done) { repo.write('master', 'TEST.md', 'THIS IS A TEST', 'Creating test', function(err) { should.not.exist(err); @@ -267,12 +281,15 @@ describe('Creating new Github.Repository', function() { }); describe('deleting a Github.Repository', function() { - var github = new Github({ - username : test_user.USERNAME, - password : test_user.PASSWORD, - auth : 'basic' + before(function(){ + if (typeof window !== 'undefined') test_user = window.__fixtures__['test/user']; + github = new Github({ + username : test_user.USERNAME, + password : test_user.PASSWORD, + auth : 'basic' + }); + repo = github.getRepo(test_user.USERNAME, repoTest); }); - var repo = github.getRepo(test_user.USERNAME, repoTest); it('should delete the repo', function(done){ repo.deleteRepo(function(err, res) { @@ -284,12 +301,15 @@ describe('deleting a Github.Repository', function() { }); describe('Repo returns commit errors correctly', function() { - var github = new Github({ - username : test_user.USERNAME, - password : test_user.PASSWORD, - auth : 'basic' + before(function(){ + if (typeof window !== 'undefined') test_user = window.__fixtures__['test/user']; + github = new Github({ + username : test_user.USERNAME, + password : test_user.PASSWORD, + auth : 'basic' + }); + repo = github.getRepo(test_user.USERNAME, test_user.REPO); }); - var repo = github.getRepo(test_user.USERNAME, test_user.REPO); it('should fail on broken commit', function(done){ repo.commit('broken-parent-hash', 'broken-tree-hash', 'commit message', function(err) { diff --git a/test/test.search.js b/test/test.search.js index d0f85a2e..bd3b11ec 100644 --- a/test/test.search.js +++ b/test/test.search.js @@ -1,20 +1,28 @@ 'use strict'; -// module dependencies -var chai = require('chai'), sinonChai = require('sinon-chai'); +var github; -var Github = require('../'); -var test_user = require('./user.json'); +if (typeof window === 'undefined') { + // module dependencies + var chai = require('chai'), + sinonChai = require('sinon-chai'); -// Use should flavour for Mocha -var should = chai.should(); -chai.use(sinonChai); + var Github = require('../'); + var test_user = require('./user.json'); + + // Use should flavour for Mocha + var should = chai.should(); + chai.use(sinonChai); +} describe('Github.Search', function() { - var github = new Github({ - username: test_user.USERNAME, - password: test_user.PASSWORD, - auth: "basic" + before(function(){ + if (typeof window !== 'undefined') test_user = window.__fixtures__['test/user']; + github = new Github({ + username: test_user.USERNAME, + password: test_user.PASSWORD, + auth: "basic" + }); }); it('should search.repositories', function(done) { diff --git a/test/test.user.js b/test/test.user.js index f684e984..4e92e4fa 100644 --- a/test/test.user.js +++ b/test/test.user.js @@ -1,26 +1,36 @@ 'use strict'; -// module dependencies -var chai = require('chai'), sinonChai = require('sinon-chai'); +var test_user, user, github; -var Github = require('../'); -var test_user = require('./user.json'); +if (typeof window === 'undefined') { + // module dependencies + var chai = require('chai'), + sinonChai = require('sinon-chai'); -// Use should flavour for Mocha -var should = chai.should(); -chai.use(sinonChai); + var Github = require('../'); + test_user = require('./user.json'); + + // Use should flavour for Mocha + var should = chai.should(); + chai.use(sinonChai); +} describe('Github.User', function() { - this.timeout(8000); // Bit of a longer timeout + before(function(){ + if (typeof window !== 'undefined') test_user = window.__fixtures__['test/user']; + github = new Github({ + username: test_user.USERNAME, + password: test_user.PASSWORD, + auth: 'basic' + }); + user = github.getUser(); - var github = new Github({ - username: test_user.USERNAME, - password: test_user.PASSWORD, - auth: 'basic' + this.timeout(8000); // Bit of a longer timeout }); - var user = github.getUser(); it('should get user.repos', function(done) { + this.timeout(8000); // Bit of a longer timeout + user.repos(function(err) { should.not.exist(err); done(); diff --git a/test/user.json b/test/user.json index 96043ed9..2c57a9ed 100644 --- a/test/user.json +++ b/test/user.json @@ -1,5 +1 @@ -{ - "USERNAME": "mikedeboertest", - "PASSWORD": "test1324", - "REPO": "github" -} +{"USERNAME": "mikedeboertest", "PASSWORD": "test1324", "REPO": "github"} From 0d82b20d2c77fd1c2d98f27b5b433c87a2de8eea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86ndrew=20Rininsland?= Date: Tue, 27 Oct 2015 12:35:22 +0000 Subject: [PATCH 4/4] Adding more files to linting, adding forgotten karma.conf.js, linted all files. --- .editorconfig | 2 +- .jscsrc | 5 +- .travis.yml | 1 + github.js | 1607 ++++++++++++++++++++++--------------------- gulpfile.js | 78 ++- karma.conf.js | 49 ++ package.json | 15 +- test/test.auth.js | 88 ++- test/test.issue.js | 72 +- test/test.repo.js | 603 ++++++++-------- test/test.search.js | 95 ++- test/test.user.js | 288 ++++---- 12 files changed, 1524 insertions(+), 1379 deletions(-) create mode 100644 karma.conf.js diff --git a/.editorconfig b/.editorconfig index 4a7ea303..101a559e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -2,7 +2,7 @@ root = true [*] indent_style = space -indent_size = 2 +indent_size = 3 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true diff --git a/.jscsrc b/.jscsrc index b65958ca..eb73c509 100644 --- a/.jscsrc +++ b/.jscsrc @@ -1,5 +1,5 @@ { - "disallowDanglingUnderscores": true, + "disallowDanglingUnderscores": false, "disallowIdentifierNames": [], "disallowImplicitTypeConversion": [], "disallowKeywordsOnNewLine": [ @@ -53,7 +53,6 @@ "do", "else", "for", - "if", "try", "while" ], @@ -139,4 +138,4 @@ }, "validateParameterSeparator": ", ", "validateQuoteMarks": "'" -} \ No newline at end of file +} diff --git a/.travis.yml b/.travis.yml index f7e807e5..bc463672 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,4 +7,5 @@ node_js: - "0.11" - "0.10" script: + - npm test - npm run-script codecov diff --git a/github.js b/github.js index 53c0a04a..918676f0 100644 --- a/github.js +++ b/github.js @@ -11,934 +11,1003 @@ */ (function (root, factory) { - // UMD boilerplate from https://github.com/umdjs/umd/blob/master/returnExportsGlobal.js - 'use strict'; - - /* istanbul ignore next */ - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define(['xmlhttprequest', 'js-base64'], function (XMLHttpRequest, b64encode) { - return (root.Github = factory(XMLHttpRequest.XMLHttpRequest, b64encode.Base64.encode)); - }); - } else if (typeof module === 'object' && module.exports) { - // Node. Does not work with strict CommonJS, but - // only CommonJS-like enviroments that support module.exports, - // like Node. - module.exports = factory(require('xmlhttprequest').XMLHttpRequest, require('js-base64').Base64.encode); - } else { - // Browser globals - var b64encode = function(str) { - return root.btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) { - return String.fromCharCode('0x' + p1); - })); - }; - root.Github = factory(root.XMLHttpRequest, b64encode); - } + // UMD boilerplate from https://github.com/umdjs/umd/blob/master/returnExportsGlobal.js + 'use strict'; + + /* istanbul ignore next */ + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['xmlhttprequest', 'js-base64'], function (XMLHttpRequest, b64encode) { + return (root.Github = factory(XMLHttpRequest.XMLHttpRequest, b64encode.Base64.encode)); + }); + } else if (typeof module === 'object' && module.exports) { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like enviroments that support module.exports, + // like Node. + module.exports = factory(require('xmlhttprequest').XMLHttpRequest, require('js-base64').Base64.encode); + } else { + // Browser globals + var b64encode = function(str) { + return root.btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) { + return String.fromCharCode('0x' + p1); + })); + }; + + root.Github = factory(root.XMLHttpRequest, b64encode); + } }(this, function (XMLHttpRequest, b64encode) { - 'use strict'; - - // Initial Setup - // ------------- - - var Github = function(options) { - var API_URL = options.apiUrl || 'https://api.github.com'; - - // HTTP Request Abstraction - // ======= - // - // I'm not proud of this and neither should you be if you were responsible for the XMLHttpRequest spec. - - var _request = Github._request = function _request(method, path, data, cb, raw, sync) { - function getURL() { - var url = path.indexOf('//') >= 0 ? path : API_URL + path; - url += ((/\?/).test(url) ? '&' : '?'); - if (data && typeof data === 'object' && ['GET', 'HEAD'].indexOf(method) > -1) { - for(var param in data) { - if (data.hasOwnProperty(param)) - url += '&' + encodeURIComponent(param) + '=' + encodeURIComponent(data[param]); - } - } - return url + (typeof window !== 'undefined' ? '&' + new Date().getTime() : ''); - } + 'use strict'; - var xhr = new XMLHttpRequest(); + // Initial Setup + // ------------- + var Github = function(options) { + var API_URL = options.apiUrl || 'https://api.github.com'; - xhr.open(method, getURL(), !sync); - if (!sync) { - xhr.onreadystatechange = function () { - if (this.readyState === 4) { - if (this.status >= 200 && this.status < 300 || this.status === 304) { - cb(null, raw ? this.responseText : this.responseText ? JSON.parse(this.responseText) : true, this); - } else { - cb({path: path, request: this, error: this.status}); + // HTTP Request Abstraction + // ======= + // + // I'm not proud of this and neither should you be if you were responsible for the XMLHttpRequest spec. + + var _request = Github._request = function _request(method, path, data, cb, raw, sync) { + function getURL() { + var url = path.indexOf('//') >= 0 ? path : API_URL + path; + + url += ((/\?/).test(url) ? '&' : '?'); + + if (data && typeof data === 'object' && ['GET', 'HEAD'].indexOf(method) > -1) { + for(var param in data) { + if (data.hasOwnProperty(param)) + url += '&' + encodeURIComponent(param) + '=' + encodeURIComponent(data[param]); + } } - } - }; - } - if (!raw) { - xhr.dataType = 'json'; - xhr.setRequestHeader('Accept','application/vnd.github.v3+json'); - } else { - xhr.setRequestHeader('Accept','application/vnd.github.v3.raw+json'); - } + return url + (typeof window !== 'undefined' ? '&' + new Date().getTime() : ''); + } - xhr.setRequestHeader('Content-Type','application/json;charset=UTF-8'); - if ((options.token) || (options.username && options.password)) { - var authorization = options.token ? 'token ' + options.token : 'Basic ' + b64encode(options.username + ':' + options.password); - xhr.setRequestHeader('Authorization', authorization); - } - if (data) { - xhr.send(JSON.stringify(data)); - } else { - xhr.send(); - } - if (sync) { - return xhr.response; - } - }; - - var _requestAllPages = Github._requestAllPages = function _requestAllPages(path, cb) { - var results = []; - (function iterate() { - _request('GET', path, null, function(err, res, xhr) { - if (err) { - return cb(err); - } - - results.push.apply(results, res); - - var links = (xhr.getResponseHeader('link') || '').split(/\s*,\s*/g), - next = null; - links.forEach(function(link) { - next = /rel="next"/.test(link) ? link : next; - }); - - if (next) { - next = (/<(.*)>/.exec(next) || [])[1]; - } - - if (!next) { - cb(err, results); - } else { - path = next; - iterate(); - } - }); - })(); - }; - - - // User API - // ======= - - Github.User = function() { - this.repos = function(options, cb) { - if (arguments.length === 1 && typeof arguments[0] === 'function') { - cb = options; - options = {}; - } - options = options || {}; - - var url = '/user/repos'; - var params = []; - - params.push("type=" + encodeURIComponent(options.type || 'all')); - params.push("sort=" + encodeURIComponent(options.sort || 'updated')); - params.push("per_page=" + encodeURIComponent(options.per_page || '1000')); - if(options.page) { - params.push("page=" + encodeURIComponent(options.page)); - } - url += '?' + params.join('&'); - - _request("GET", url, null, cb); - }; + var xhr = new XMLHttpRequest(); - // List user organizations - // ------- + xhr.open(method, getURL(), !sync); - this.orgs = function(cb) { - _request("GET", '/user/orgs', null, cb); - }; + if (!sync) { + xhr.onreadystatechange = function () { + if (this.readyState === 4) { + if (this.status >= 200 && this.status < 300 || this.status === 304) { + cb(null, raw ? this.responseText : this.responseText ? JSON.parse(this.responseText) : true, this); + } else { + cb({ + path: path, request: this, error: this.status + }); + } + } + }; + } - // List authenticated user's gists - // ------- + if (!raw) { + xhr.dataType = 'json'; + xhr.setRequestHeader('Accept', 'application/vnd.github.v3+json'); + } else { + xhr.setRequestHeader('Accept', 'application/vnd.github.v3.raw+json'); + } - this.gists = function(cb) { - _request("GET", '/gists', null, cb); - }; + xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8'); - // List authenticated user's unread notifications - // ------- - - this.notifications = function(options, cb) { - if (arguments.length === 1 && typeof arguments[0] === 'function') { - cb = options; - options = {}; - } - options = options || {}; - var url = '/notifications'; - var params = []; - if (options.all) { - params.push('all=true'); - } - if (options.participating) { - params.push('participating=true'); - } - if (options.since) { - var since = options.since; - if (since.constructor === Date) { - since = since.toISOString(); - } - params.push('since=' + encodeURIComponent(since)); - } - if (options.before) { - var before = options.before; - if (before.constructor === Date) { - before = before.toISOString(); - } - params.push('before=' + encodeURIComponent(before)); - } - if (options.page) { - params.push('page=' + encodeURIComponent(options.page)); - } - if (params.length > 0) { - url += '?' + params.join('&'); - } - _request("GET", url, null, cb); - }; + if ((options.token) || (options.username && options.password)) { + var authorization = options.token ? 'token ' + options.token : + 'Basic ' + b64encode(options.username + ':' + options.password); - // Show user information - // ------- + xhr.setRequestHeader('Authorization', authorization); + } - this.show = function(username, cb) { - var command = username ? '/users/' + username : '/user'; + if (data) { + xhr.send(JSON.stringify(data)); + } else { + xhr.send(); + } - _request('GET', command, null, cb); + if (sync) { + return xhr.response; + } }; - // List user repositories - // ------- + var _requestAllPages = Github._requestAllPages = function _requestAllPages(path, cb) { + var results = []; - this.userRepos = function(username, cb) { - // Github does not always honor the 1000 limit so we want to iterate over the data set. - _requestAllPages('/users/' + username + '/repos?type=all&per_page=1000&sort=updated', cb); - }; + (function iterate() { + _request('GET', path, null, function(err, res, xhr) { + if (err) { + return cb(err); + } - // List user starred repositories - // ------- + results.push.apply(results, res); - this.userStarred = function(username, cb) { - // Github does not always honor the 1000 limit so we want to iterate over the data set. - _requestAllPages("/users/"+username+"/starred?type=all&per_page=1000", function(err, res) { - cb(err, res); - }); - }; + var links = (xhr.getResponseHeader('link') || '').split(/\s*,\s*/g); + var next = null; - // List a user's gists - // ------- + links.forEach(function(link) { + next = /rel="next"/.test(link) ? link : next; + }); - this.userGists = function(username, cb) { - _request('GET', '/users/' + username + '/gists', null, cb); + if (next) { + next = (/<(.*)>/.exec(next) || [])[1]; + } + + if (!next) { + cb(err, results); + } else { + path = next; + iterate(); + } + }); + })(); }; - // List organization repositories - // ------- + // User API + // ======= - this.orgRepos = function(orgname, cb) { - // Github does not always honor the 1000 limit so we want to iterate over the data set. - _requestAllPages('/orgs/' + orgname + '/repos?type=all&&page_num=1000&sort=updated&direction=desc', cb); - }; + Github.User = function() { + this.repos = function(options, cb) { + if (arguments.length === 1 && typeof arguments[0] === 'function') { + cb = options; + options = {}; + } - // Follow user - // ------- + options = options || {}; - this.follow = function(username, cb) { - _request('PUT', '/user/following/' + username, null, cb); - }; + var url = '/user/repos'; + var params = []; - // Unfollow user - // ------- + params.push('type=' + encodeURIComponent(options.type || 'all')); + params.push('sort=' + encodeURIComponent(options.sort || 'updated')); + params.push('per_page=' + encodeURIComponent(options.per_page || '1000')); // jscs:ignore - this.unfollow = function(username, cb) { - _request('DELETE', '/user/following/' + username, null, cb); - }; + if (options.page) { + params.push('page=' + encodeURIComponent(options.page)); + } - // Create a repo - // ------- - this.createRepo = function(options, cb) { - _request('POST', '/user/repos', options, cb); - }; + url += '?' + params.join('&'); - }; + _request('GET', url, null, cb); + }; - // Repository API - // ======= + // List user organizations + // ------- - Github.Repository = function(options) { - var repo = options.name; - var user = options.user; - var fullname = options.fullname; + this.orgs = function(cb) { + _request('GET', '/user/orgs', null, cb); + }; - var that = this; - var repoPath; + // List authenticated user's gists + // ------- - if (fullname) { - repoPath = '/repos/' + fullname; - } else { - repoPath = '/repos/' + user + '/' + repo; - } + this.gists = function(cb) { + _request('GET', '/gists', null, cb); + }; - var currentTree = { - 'branch': null, - 'sha': null - }; + // List authenticated user's unread notifications + // ------- + this.notifications = function(options, cb) { + if (arguments.length === 1 && typeof arguments[0] === 'function') { + cb = options; + options = {}; + } - // Delete a repo - // -------- + options = options || {}; + var url = '/notifications'; + var params = []; - this.deleteRepo = function(cb) { - _request('DELETE', repoPath, options, cb); - }; + if (options.all) { + params.push('all=true'); + } - // Uses the cache if branch has not been changed - // ------- + if (options.participating) { + params.push('participating=true'); + } - function updateTree(branch, cb) { - if (branch === currentTree.branch && currentTree.sha) { - return cb(null, currentTree.sha); - } + if (options.since) { + var since = options.since; - that.getRef('heads/' + branch, function(err, sha) { - currentTree.branch = branch; - currentTree.sha = sha; - cb(err, sha); - }); - } + if (since.constructor === Date) { + since = since.toISOString(); + } - // Get a particular reference - // ------- + params.push('since=' + encodeURIComponent(since)); + } - this.getRef = function(ref, cb) { - _request('GET', repoPath + '/git/refs/' + ref, null, function(err, res, xhr) { - if (err) { - return cb(err); - } + if (options.before) { + var before = options.before; - cb(null, res.object.sha, xhr); - }); - }; + if (before.constructor === Date) { + before = before.toISOString(); + } - // Create a new reference - // -------- - // - // { - // "ref": "refs/heads/my-new-branch-name", - // "sha": "827efc6d56897b048c772eb4087f854f46256132" - // } + params.push('before=' + encodeURIComponent(before)); + } - this.createRef = function(options, cb) { - _request('POST', repoPath + '/git/refs', options, cb); - }; + if (options.page) { + params.push('page=' + encodeURIComponent(options.page)); + } - // Delete a reference - // -------- - // - // repo.deleteRef('heads/gh-pages') - // repo.deleteRef('tags/v1.0') + if (params.length > 0) { + url += '?' + params.join('&'); + } - this.deleteRef = function(ref, cb) { - _request('DELETE', repoPath + '/git/refs/' + ref, options, function(err, res, xhr){ - cb(err, res, xhr); - }); - }; + _request('GET', url, null, cb); + }; - // Create a repo - // ------- + // Show user information + // ------- - this.createRepo = function(options, cb) { - _request('POST', '/user/repos', options, cb); - }; + this.show = function(username, cb) { + var command = username ? '/users/' + username : '/user'; - // Delete a repo - // -------- + _request('GET', command, null, cb); + }; - this.deleteRepo = function(cb) { - _request('DELETE', repoPath, options, cb); - }; + // List user repositories + // ------- - // List all tags of a repository - // ------- + this.userRepos = function(username, cb) { + // Github does not always honor the 1000 limit so we want to iterate over the data set. + _requestAllPages('/users/' + username + '/repos?type=all&per_page=1000&sort=updated', cb); + }; - this.listTags = function(cb) { - _request('GET', repoPath + '/tags', null, function(err, tags, xhr) { - if (err) { - return cb(err); - } + // List user starred repositories + // ------- - cb(null, tags, xhr); - }); - }; + this.userStarred = function(username, cb) { + // Github does not always honor the 1000 limit so we want to iterate over the data set. + _requestAllPages('/users/' + username + '/starred?type=all&per_page=1000', function(err, res) { + cb(err, res); + }); + }; - // List all pull requests of a respository - // ------- + // List a user's gists + // ------- - this.listPulls = function(state, cb) { - _request('GET', repoPath + "/pulls" + (state ? '?state=' + state : ''), null, function(err, pulls, xhr) { - if (err) return cb(err); - cb(null, pulls, xhr); - }); - }; + this.userGists = function(username, cb) { + _request('GET', '/users/' + username + '/gists', null, cb); + }; - // Gets details for a specific pull request - // ------- + // List organization repositories + // ------- - this.getPull = function(number, cb) { - _request("GET", repoPath + "/pulls/" + number, null, function(err, pull, xhr) { - if (err) return cb(err); - cb(null, pull, xhr); - }); - }; + this.orgRepos = function(orgname, cb) { + // Github does not always honor the 1000 limit so we want to iterate over the data set. + _requestAllPages('/orgs/' + orgname + '/repos?type=all&&page_num=1000&sort=updated&direction=desc', cb); + }; - // Retrieve the changes made between base and head - // ------- + // Follow user + // ------- - this.compare = function(base, head, cb) { - _request("GET", repoPath + "/compare/" + base + "..." + head, null, function(err, diff, xhr) { - if (err) return cb(err); - cb(null, diff, xhr); - }); - }; + this.follow = function(username, cb) { + _request('PUT', '/user/following/' + username, null, cb); + }; + + // Unfollow user + // ------- - // List all branches of a repository - // ------- + this.unfollow = function(username, cb) { + _request('DELETE', '/user/following/' + username, null, cb); + }; - this.listBranches = function(cb) { - _request("GET", repoPath + "/git/refs/heads", null, function(err, heads, xhr) { - if (err) return cb(err); - cb(null, heads.map(function(head) { - return head.ref.replace(/^refs\/heads\//, ''); - }), xhr); - }); + // Create a repo + // ------- + this.createRepo = function(options, cb) { + _request('POST', '/user/repos', options, cb); + }; }; - // Retrieve the contents of a blob - // ------- + // Repository API + // ======= - this.getBlob = function(sha, cb) { - _request("GET", repoPath + "/git/blobs/" + sha, null, cb, 'raw'); - }; + Github.Repository = function(options) { + var repo = options.name; + var user = options.user; + var fullname = options.fullname; - // For a given file path, get the corresponding sha (blob for files, tree for dirs) - // ------- + var that = this; + var repoPath; - this.getCommit = function(branch, sha, cb) { - _request("GET", repoPath + "/git/commits/"+sha, null, function(err, commit, xhr) { - if (err) return cb(err); - cb(null, commit, xhr); - }); - }; + if (fullname) { + repoPath = '/repos/' + fullname; + } else { + repoPath = '/repos/' + user + '/' + repo; + } - // For a given file path, get the corresponding sha (blob for files, tree for dirs) - // ------- + var currentTree = { + branch: null, + sha: null + }; - this.getSha = function(branch, path, cb) { - if (!path || path === "") return that.getRef("heads/"+branch, cb); - _request("GET", repoPath + "/contents/" + path + (branch ? "?ref=" + branch : ""), null, function(err, pathContent, xhr) { - if (err) return cb(err); - cb(null, pathContent.sha, xhr); - }); - }; + // Delete a repo + // -------- - // Retrieve the tree a commit points to - // ------- + this.deleteRepo = function(cb) { + _request('DELETE', repoPath, options, cb); + }; - this.getTree = function(tree, cb) { - _request("GET", repoPath + "/git/trees/"+tree, null, function(err, res, xhr) { - if (err) return cb(err); - cb(null, res.tree, xhr); - }); - }; + // Uses the cache if branch has not been changed + // ------- - // Post a new blob object, getting a blob SHA back - // ------- - - this.postBlob = function(content, cb) { - if (typeof(content) === "string") { - content = { - "content": content, - "encoding": "utf-8" - }; - } else { - content = { - "content": b64encode(String.fromCharCode.apply(null, new Uint8Array(content))), - "encoding": "base64" - }; - } + function updateTree(branch, cb) { + if (branch === currentTree.branch && currentTree.sha) { + return cb(null, currentTree.sha); + } - _request("POST", repoPath + "/git/blobs", content, function(err, res) { - if (err) return cb(err); - cb(null, res.sha); - }); - }; + that.getRef('heads/' + branch, function(err, sha) { + currentTree.branch = branch; + currentTree.sha = sha; + cb(err, sha); + }); + } + + // Get a particular reference + // ------- + + this.getRef = function(ref, cb) { + _request('GET', repoPath + '/git/refs/' + ref, null, function(err, res, xhr) { + if (err) { + return cb(err); + } + + cb(null, res.object.sha, xhr); + }); + }; + + // Create a new reference + // -------- + // + // { + // "ref": "refs/heads/my-new-branch-name", + // "sha": "827efc6d56897b048c772eb4087f854f46256132" + // } + + this.createRef = function(options, cb) { + _request('POST', repoPath + '/git/refs', options, cb); + }; + + // Delete a reference + // -------- + // + // Repo.deleteRef('heads/gh-pages') + // repo.deleteRef('tags/v1.0') + + this.deleteRef = function(ref, cb) { + _request('DELETE', repoPath + '/git/refs/' + ref, options, function(err, res, xhr) { + cb(err, res, xhr); + }); + }; + + // Create a repo + // ------- + + this.createRepo = function(options, cb) { + _request('POST', '/user/repos', options, cb); + }; + + // Delete a repo + // -------- + + this.deleteRepo = function(cb) { + _request('DELETE', repoPath, options, cb); + }; + + // List all tags of a repository + // ------- + + this.listTags = function(cb) { + _request('GET', repoPath + '/tags', null, function(err, tags, xhr) { + if (err) { + return cb(err); + } + + cb(null, tags, xhr); + }); + }; + + // List all pull requests of a respository + // ------- + + this.listPulls = function(state, cb) { + _request('GET', repoPath + '/pulls' + (state ? '?state=' + state : ''), null, function(err, pulls, xhr) { + if (err) return cb(err); + cb(null, pulls, xhr); + }); + }; + + // Gets details for a specific pull request + // ------- + + this.getPull = function(number, cb) { + _request('GET', repoPath + '/pulls/' + number, null, function(err, pull, xhr) { + if (err) return cb(err); + cb(null, pull, xhr); + }); + }; + + // Retrieve the changes made between base and head + // ------- + + this.compare = function(base, head, cb) { + _request('GET', repoPath + '/compare/' + base + '...' + head, null, function(err, diff, xhr) { + if (err) return cb(err); + cb(null, diff, xhr); + }); + }; + + // List all branches of a repository + // ------- - // Update an existing tree adding a new blob object getting a tree SHA back - // ------- + this.listBranches = function(cb) { + _request('GET', repoPath + '/git/refs/heads', null, function(err, heads, xhr) { + if (err) return cb(err); + cb(null, heads.map(function(head) { + return head.ref.replace(/^refs\/heads\//, ''); + }), xhr); + }); + }; + + // Retrieve the contents of a blob + // ------- + + this.getBlob = function(sha, cb) { + _request('GET', repoPath + '/git/blobs/' + sha, null, cb, 'raw'); + }; + + // For a given file path, get the corresponding sha (blob for files, tree for dirs) + // ------- + + this.getCommit = function(branch, sha, cb) { + _request('GET', repoPath + '/git/commits/' + sha, null, function(err, commit, xhr) { + if (err) return cb(err); + cb(null, commit, xhr); + }); + }; + + // For a given file path, get the corresponding sha (blob for files, tree for dirs) + // ------- + + this.getSha = function(branch, path, cb) { + if (!path || path === '') return that.getRef('heads/' + branch, cb); + _request('GET', repoPath + '/contents/' + path + (branch ? '?ref=' + branch : ''), + null, function(err, pathContent, xhr) { + if (err) return cb(err); + cb(null, pathContent.sha, xhr); + }); + }; + + // Retrieve the tree a commit points to + // ------- + + this.getTree = function(tree, cb) { + _request('GET', repoPath + '/git/trees/' + tree, null, function(err, res, xhr) { + if (err) return cb(err); + cb(null, res.tree, xhr); + }); + }; + + // Post a new blob object, getting a blob SHA back + // ------- + + this.postBlob = function(content, cb) { + if (typeof (content) === 'string') { + content = { + content: content, + encoding: 'utf-8' + }; + } else { + content = { + content: b64encode(String.fromCharCode.apply(null, new Uint8Array(content))), + encoding: 'base64' + }; + } - this.updateTree = function(baseTree, path, blob, cb) { - var data = { - "base_tree": baseTree, - "tree": [ + _request('POST', repoPath + '/git/blobs', content, function(err, res) { + if (err) return cb(err); + cb(null, res.sha); + }); + }; + + // Update an existing tree adding a new blob object getting a tree SHA back + // ------- + + this.updateTree = function(baseTree, path, blob, cb) { + var data = { + base_tree: baseTree, // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers + tree: [ { - "path": path, - "mode": "100644", - "type": "blob", - "sha": blob + path: path, + mode: '100644', + type: 'blob', + sha: blob } ] - }; - _request("POST", repoPath + "/git/trees", data, function(err, res) { - if (err) return cb(err); - cb(null, res.sha); - }); - }; + }; - // Post a new tree object having a file path pointer replaced - // with a new blob SHA getting a tree SHA back - // ------- + _request('POST', repoPath + '/git/trees', data, function(err, res) { + if (err) return cb(err); + cb(null, res.sha); + }); + }; + + // Post a new tree object having a file path pointer replaced + // with a new blob SHA getting a tree SHA back + // ------- + + this.postTree = function(tree, cb) { + _request('POST', repoPath + '/git/trees', { + tree: tree + }, function(err, res) { + if (err) return cb(err); + cb(null, res.sha); + }); + }; + + // Create a new commit object with the current commit SHA as the parent + // and the new tree SHA, getting a commit SHA back + // ------- + + this.commit = function(parent, tree, message, cb) { + var user = new Github.User(); + + user.show(null, function(err, userData) { + if (err) return cb(err); + var data = { + message: message, + author: { + name: options.user, + email: userData.email + }, + parents: [ + parent + ], + tree: tree + }; + + _request('POST', repoPath + '/git/commits', data, function(err, res) { + if (err) return cb(err); + currentTree.sha = res.sha; // Update latest commit + cb(null, res.sha); + }); + }); + }; - this.postTree = function(tree, cb) { - _request("POST", repoPath + "/git/trees", { "tree": tree }, function(err, res) { - if (err) return cb(err); - cb(null, res.sha); - }); - }; + // Update the reference of your head to point to the new commit SHA + // ------- - // Create a new commit object with the current commit SHA as the parent - // and the new tree SHA, getting a commit SHA back - // ------- - - this.commit = function(parent, tree, message, cb) { - var user = new Github.User(); - user.show(null, function(err, userData){ - if (err) return cb(err); - var data = { - "message": message, - "author": { - "name": options.user, - "email": userData.email - }, - "parents": [ - parent - ], - "tree": tree - }; - _request("POST", repoPath + "/git/commits", data, function(err, res) { - if (err) return cb(err); - currentTree.sha = res.sha; // update latest commit - cb(null, res.sha); - }); - }); - }; + this.updateHead = function(head, commit, cb) { + _request('PATCH', repoPath + '/git/refs/heads/' + head, { + sha: commit + }, function(err) { + cb(err); + }); + }; - // Update the reference of your head to point to the new commit SHA - // ------- + // Show repository information + // ------- - this.updateHead = function(head, commit, cb) { - _request("PATCH", repoPath + "/git/refs/heads/" + head, { "sha": commit }, function(err) { - cb(err); - }); - }; + this.show = function(cb) { + _request('GET', repoPath, null, cb); + }; - // Show repository information - // ------- + // Show repository contributors + // ------- - this.show = function(cb) { - _request("GET", repoPath, null, cb); - }; + this.contributors = function (cb, retry) { + retry = retry || 1000; + var that = this; - // Show repository contributors - // ------- + _request('GET', repoPath + '/stats/contributors', null, function (err, data, xhr) { + if (err) return cb(err); - this.contributors = function (cb, retry) { - retry = retry || 1000; - var self = this; - _request("GET", repoPath + "/stats/contributors", null, function (err, data, xhr) { - if (err) return cb(err); - if (xhr.status === 202) { - setTimeout( + if (xhr.status === 202) { + setTimeout( function () { - self.contributors(cb, retry); + that.contributors(cb, retry); }, retry ); - } else { - cb(err, data, xhr); - } - }); - }; + } else { + cb(err, data, xhr); + } + }); + }; - // Get contents - // -------- + // Get contents + // -------- - this.contents = function(ref, path, cb) { - path = encodeURI(path); - _request("GET", repoPath + "/contents" + (path ? "/" + path : ""), { ref: ref }, cb); - }; + this.contents = function(ref, path, cb) { + path = encodeURI(path); + _request('GET', repoPath + '/contents' + (path ? '/' + path : ''), { + ref: ref + }, cb); + }; - // Fork repository - // ------- + // Fork repository + // ------- - this.fork = function(cb) { - _request("POST", repoPath + "/forks", null, cb); - }; + this.fork = function(cb) { + _request('POST', repoPath + '/forks', null, cb); + }; - // Branch repository - // -------- - - this.branch = function(oldBranch,newBranch,cb) { - if(arguments.length === 2 && typeof arguments[1] === "function") { - cb = newBranch; - newBranch = oldBranch; - oldBranch = "master"; - } - this.getRef("heads/" + oldBranch, function(err,ref) { - if(err && cb) return cb(err); - that.createRef({ - ref: "refs/heads/" + newBranch, - sha: ref - },cb); - }); - }; + // Branch repository + // -------- - // Create pull request - // -------- + this.branch = function(oldBranch, newBranch, cb) { + if (arguments.length === 2 && typeof arguments[1] === 'function') { + cb = newBranch; + newBranch = oldBranch; + oldBranch = 'master'; + } - this.createPullRequest = function(options, cb) { - _request("POST", repoPath + "/pulls", options, cb); - }; + this.getRef('heads/' + oldBranch, function(err, ref) { + if (err && cb) return cb(err); + that.createRef({ + ref: 'refs/heads/' + newBranch, + sha: ref + }, cb); + }); + }; - // List hooks - // -------- + // Create pull request + // -------- - this.listHooks = function(cb) { - _request("GET", repoPath + "/hooks", null, cb); - }; + this.createPullRequest = function(options, cb) { + _request('POST', repoPath + '/pulls', options, cb); + }; - // Get a hook - // -------- + // List hooks + // -------- - this.getHook = function(id, cb) { - _request("GET", repoPath + "/hooks/" + id, null, cb); - }; + this.listHooks = function(cb) { + _request('GET', repoPath + '/hooks', null, cb); + }; - // Create a hook - // -------- + // Get a hook + // -------- - this.createHook = function(options, cb) { - _request("POST", repoPath + "/hooks", options, cb); - }; + this.getHook = function(id, cb) { + _request('GET', repoPath + '/hooks/' + id, null, cb); + }; - // Edit a hook - // -------- + // Create a hook + // -------- - this.editHook = function(id, options, cb) { - _request("PATCH", repoPath + "/hooks/" + id, options, cb); - }; + this.createHook = function(options, cb) { + _request('POST', repoPath + '/hooks', options, cb); + }; - // Delete a hook - // -------- + // Edit a hook + // -------- - this.deleteHook = function(id, cb) { - _request("DELETE", repoPath + "/hooks/" + id, null, cb); - }; + this.editHook = function(id, options, cb) { + _request('PATCH', repoPath + '/hooks/' + id, options, cb); + }; - // Read file at given path - // ------- + // Delete a hook + // -------- - this.read = function(branch, path, cb) { - _request("GET", repoPath + "/contents/"+encodeURI(path) + (branch ? "?ref=" + branch : ""), null, function(err, obj, xhr) { - if (err && err.error === 404) return cb("not found", null, null); + this.deleteHook = function(id, cb) { + _request('DELETE', repoPath + '/hooks/' + id, null, cb); + }; - if (err) return cb(err); - cb(null, obj, xhr); - }, true); - }; + // Read file at given path + // ------- + this.read = function(branch, path, cb) { + _request('GET', repoPath + '/contents/' + encodeURI(path) + (branch ? '?ref=' + branch : ''), + null, function(err, obj, xhr) { + if (err && err.error === 404) return cb('not found', null, null); - // Remove a file - // ------- + if (err) return cb(err); + cb(null, obj, xhr); + }, true); + }; - this.remove = function(branch, path, cb) { - that.getSha(branch, path, function(err, sha) { - if (err) return cb(err); - _request("DELETE", repoPath + "/contents/" + path, { - message: path + " is removed", - sha: sha, - branch: branch - }, cb); - }); - }; + // Remove a file + // ------- - // Delete a file from the tree - // ------- - - this.delete = function(branch, path, cb) { - that.getSha(branch, path, function(err, sha) { - if (!sha) return cb("not found", null); - var delPath = repoPath + "/contents/" + path; - var params = { - "message": "Deleted " + path, - "sha": sha - }; - delPath += "?message=" + encodeURIComponent(params.message); - delPath += "&sha=" + encodeURIComponent(params.sha); - delPath += '&branch=' + encodeURIComponent(branch); - _request("DELETE", delPath, null, cb); - }); - }; + this.remove = function(branch, path, cb) { + that.getSha(branch, path, function(err, sha) { + if (err) return cb(err); + _request('DELETE', repoPath + '/contents/' + path, { + message: path + ' is removed', + sha: sha, + branch: branch + }, cb); + }); + }; + + // Delete a file from the tree + // ------- + + this.delete = function(branch, path, cb) { + that.getSha(branch, path, function(err, sha) { + if (!sha) return cb('not found', null); + var delPath = repoPath + '/contents/' + path; + var params = { + message: 'Deleted ' + path, + sha: sha + }; + + delPath += '?message=' + encodeURIComponent(params.message); + delPath += '&sha=' + encodeURIComponent(params.sha); + delPath += '&branch=' + encodeURIComponent(branch); + _request('DELETE', delPath, null, cb); + }); + }; + + // Move a file to a new location + // ------- + + this.move = function(branch, path, newPath, cb) { + updateTree(branch, function(err, latestCommit) { + that.getTree(latestCommit + '?recursive=true', function(err, tree) { + // Update Tree + tree.forEach(function(ref) { + if (ref.path === path) ref.path = newPath; + + if (ref.type === 'tree') delete ref.sha; + }); + + that.postTree(tree, function(err, rootTree) { + that.commit(latestCommit, rootTree, 'Deleted ' + path , function(err, commit) { + that.updateHead(branch, commit, function(err) { + cb(err); + }); + }); + }); + }); + }); + }; - // Move a file to a new location - // ------- + // Write file contents to a given branch and path + // ------- - this.move = function(branch, path, newPath, cb) { - updateTree(branch, function(err, latestCommit) { - that.getTree(latestCommit+"?recursive=true", function(err, tree) { - // Update Tree - tree.forEach(function(ref) { - if (ref.path === path) ref.path = newPath; - if (ref.type === "tree") delete ref.sha; - }); + this.write = function(branch, path, content, message, options, cb) { + if (typeof cb === 'undefined') { + cb = options; + options = {}; + } - that.postTree(tree, function(err, rootTree) { - that.commit(latestCommit, rootTree, 'Deleted '+path , function(err, commit) { - that.updateHead(branch, commit, function(err) { - cb(err); - }); - }); + that.getSha(branch, encodeURI(path), function(err, sha) { + var writeOptions = { + message: message, + content: b64encode(content), + branch: branch, + committer: options && options.committer ? options.committer : undefined, + author: options && options.author ? options.author : undefined + }; + + // If no error, we set the sha to overwrite an existing file + if (!(err && err.error !== 404)) writeOptions.sha = sha; + _request('PUT', repoPath + '/contents/' + encodeURI(path), writeOptions, cb); }); - }); - }); - }; + }; + + // List commits on a repository. Takes an object of optional paramaters: + // sha: SHA or branch to start listing commits from + // path: Only commits containing this file path will be returned + // since: ISO 8601 date - only commits after this date will be returned + // until: ISO 8601 date - only commits before this date will be returned + // ------- + + this.getCommits = function(options, cb) { + options = options || {}; + var url = repoPath + '/commits'; + var params = []; + + if (options.sha) { + params.push('sha=' + encodeURIComponent(options.sha)); + } - // Write file contents to a given branch and path - // ------- - - this.write = function(branch, path, content, message, options, cb) { - if (typeof cb === 'undefined') { - cb = options; - options = {}; - } - that.getSha(branch, encodeURI(path), function(err, sha) { - var writeOptions = { - message: message, - content: b64encode(content), - branch: branch, - committer: options && options.committer ? options.committer : undefined, - author: options && options.author ? options.author : undefined - }; - // if no error, we set the sha to overwrite an existing file - if (!(err && err.error !== 404)) writeOptions.sha = sha; - _request("PUT", repoPath + "/contents/" + encodeURI(path), writeOptions, cb); - }); - }; + if (options.path) { + params.push('path=' + encodeURIComponent(options.path)); + } - // List commits on a repository. Takes an object of optional paramaters: - // sha: SHA or branch to start listing commits from - // path: Only commits containing this file path will be returned - // since: ISO 8601 date - only commits after this date will be returned - // until: ISO 8601 date - only commits before this date will be returned - // ------- - - this.getCommits = function(options, cb) { - options = options || {}; - var url = repoPath + "/commits"; - var params = []; - if (options.sha) { - params.push("sha=" + encodeURIComponent(options.sha)); - } - if (options.path) { - params.push("path=" + encodeURIComponent(options.path)); - } - if (options.since) { - var since = options.since; - if (since.constructor === Date) { + if (options.since) { + var since = options.since; + + if (since.constructor === Date) { since = since.toISOString(); - } - params.push("since=" + encodeURIComponent(since)); - } - if (options.until) { - var until = options.until; - if (until.constructor === Date) { + } + + params.push('since=' + encodeURIComponent(since)); + } + + if (options.until) { + var until = options.until; + + if (until.constructor === Date) { until = until.toISOString(); - } - params.push("until=" + encodeURIComponent(until)); - } - if (options.page) { - params.push("page=" + options.page); - } - if (options.perpage) { - params.push("per_page=" + options.perpage); - } - if (params.length > 0) { - url += "?" + params.join("&"); - } - _request("GET", url, null, cb); - }; - }; + } - // Gists API - // ======= + params.push('until=' + encodeURIComponent(until)); + } - Github.Gist = function(options) { - var id = options.id; - var gistPath = "/gists/"+id; + if (options.page) { + params.push('page=' + options.page); + } - // Read the gist - // -------- + if (options.perpage) { + params.push('per_page=' + options.perpage); + } - this.read = function(cb) { - _request("GET", gistPath, null, cb); - }; + if (params.length > 0) { + url += '?' + params.join('&'); + } - // Create the gist - // -------- - // { - // "description": "the description for this gist", - // "public": true, - // "files": { - // "file1.txt": { - // "content": "String file contents" - // } - // } - // } - - this.create = function(options, cb) { - _request("POST","/gists", options, cb); + _request('GET', url, null, cb); + }; }; - // Delete the gist - // -------- + // Gists API + // ======= - this.delete = function(cb) { - _request("DELETE", gistPath, null, cb); - }; + Github.Gist = function(options) { + var id = options.id; + var gistPath = '/gists/' + id; - // Fork a gist - // -------- + // Read the gist + // -------- - this.fork = function(cb) { - _request("POST", gistPath+"/fork", null, cb); - }; + this.read = function(cb) { + _request('GET', gistPath, null, cb); + }; - // Update a gist with the new stuff - // -------- + // Create the gist + // -------- + // { + // "description": "the description for this gist", + // "public": true, + // "files": { + // "file1.txt": { + // "content": "String file contents" + // } + // } + // } - this.update = function(options, cb) { - _request("PATCH", gistPath, options, cb); - }; + this.create = function(options, cb) { + _request('POST', '/gists', options, cb); + }; - // Star a gist - // -------- + // Delete the gist + // -------- - this.star = function(cb) { - _request("PUT", gistPath+"/star", null, cb); - }; + this.delete = function(cb) { + _request('DELETE', gistPath, null, cb); + }; - // Untar a gist - // -------- + // Fork a gist + // -------- - this.unstar = function(cb) { - _request("DELETE", gistPath+"/star", null, cb); - }; + this.fork = function(cb) { + _request('POST', gistPath + '/fork', null, cb); + }; - // Check if a gist is starred - // -------- + // Update a gist with the new stuff + // -------- - this.isStarred = function(cb) { - _request("GET", gistPath+"/star", null, cb); - }; - }; - - // Issues API - // ========== - - Github.Issue = function(options) { - var path = "/repos/" + options.user + "/" + options.repo + "/issues"; - - this.list = function(options, cb) { - var query = []; - for (var key in options) { - if (options.hasOwnProperty(key)) { - query.push(encodeURIComponent(key) + "=" + encodeURIComponent(options[key])); - } - } - _requestAllPages(path + '?' + query.join("&"), cb); - }; + this.update = function(options, cb) { + _request('PATCH', gistPath, options, cb); + }; - this.comment = function(issue, comment, cb) { - _request("POST", issue.comments_url, {body:comment}, function(err,res) { - cb(err,res); - }); - }; - }; + // Star a gist + // -------- - // Search API - // ========== + this.star = function(cb) { + _request('PUT', gistPath + '/star', null, cb); + }; - Github.Search = function(options) { - var path = "/search/"; - var query = "?q=" + options.query; + // Untar a gist + // -------- - this.repositories = function(options, cb) { - _request("GET", path + "repositories" + query, options, cb); - }; + this.unstar = function(cb) { + _request('DELETE', gistPath + '/star', null, cb); + }; + + // Check if a gist is starred + // -------- - this.code = function(options, cb) { - _request("GET", path + "code" + query, options, cb); + this.isStarred = function(cb) { + _request('GET', gistPath + '/star', null, cb); + }; }; - this.issues = function(options, cb) { - _request("GET", path + "issues" + query, options, cb); + // Issues API + // ========== + + Github.Issue = function(options) { + var path = '/repos/' + options.user + '/' + options.repo + '/issues'; + + this.list = function(options, cb) { + var query = []; + + for(var key in options) { + if (options.hasOwnProperty(key)) { + query.push(encodeURIComponent(key) + '=' + encodeURIComponent(options[key])); + } + } + + _requestAllPages(path + '?' + query.join('&'), cb); + }; + + this.comment = function(issue, comment, cb) { + _request('POST', issue.comments_url, { // jscs:ignore requireCamelCaseOrUpperCaseIdentifiers + body: comment + }, function(err, res) { + cb(err, res); + }); + }; }; - this.users = function(options, cb) { - _request("GET", path + "users" + query, options, cb); + // Search API + // ========== + + Github.Search = function(options) { + var path = '/search/'; + var query = '?q=' + options.query; + + this.repositories = function(options, cb) { + _request('GET', path + 'repositories' + query, options, cb); + }; + + this.code = function(options, cb) { + _request('GET', path + 'code' + query, options, cb); + }; + + this.issues = function(options, cb) { + _request('GET', path + 'issues' + query, options, cb); + }; + + this.users = function(options, cb) { + _request('GET', path + 'users' + query, options, cb); + }; }; - }; - return Github; - }; + return Github; + }; + + // Top Level API + // ------- - // Top Level API - // ------- + Github.getIssues = function(user, repo) { + return new Github.Issue({ + user: user, repo: repo + }); + }; - Github.getIssues = function(user, repo) { - return new Github.Issue({user: user, repo: repo}); - }; + Github.getRepo = function(user, repo) { + if (!repo) { + var fullname = user; - Github.getRepo = function(user, repo) { - if (!repo) { - var fullname = user; - return new Github.Repository({fullname: fullname}); - } else { - return new Github.Repository({user: user, name: repo}); - } - }; + return new Github.Repository({ + fullname: fullname + }); + } else { + return new Github.Repository({ + user: user, name: repo + }); + } + }; - Github.getUser = function() { - return new Github.User(); - }; + Github.getUser = function() { + return new Github.User(); + }; - Github.getGist = function(id) { - return new Github.Gist({id: id}); - }; + Github.getGist = function(id) { + return new Github.Gist({ + id: id + }); + }; - Github.getSearch = function(query) { - return new Github.Search({query: query}); - }; + Github.getSearch = function(query) { + return new Github.Search({ + query: query + }); + }; - return Github; + return Github; })); diff --git a/gulpfile.js b/gulpfile.js index c65cf0c2..5282add5 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -5,26 +5,34 @@ var jshint = require('gulp-jshint'); var jscs = require('gulp-jscs'); var rename = require('gulp-rename'); var uglify = require('gulp-uglify'); +var stylish = require('gulp-jscs-stylish'); var path = require('path'); var karma = require('karma'); gulp.task('lint', function() { - return gulp.src('github.js') - .pipe(jshint()) - .pipe(jshint.reporter('jshint-stylish')) - .pipe(jscs({ - fix: true - })) - .pipe(jscs.reporter()) - .pipe(gulp.dest('.')); + return gulp.src([ + path.join(__dirname, '/*.js'), + path.join(__dirname, '/test/*.js') + ], + { + base: './' + }) + .pipe(jshint()) + .pipe(jscs({ + fix: true + })) + .pipe(stylish.combineWithHintResults()) + .pipe(jscs.reporter()) + .pipe(jshint.reporter('jshint-stylish')) + .pipe(gulp.dest('.')); }); gulp.task('test', function(done) { - runTests(true, done); + runTests(true, done); }); gulp.task('test:auto', function(done) { - runTests(false, done); + runTests(false, done); }); gulp.task('build', function() { @@ -39,32 +47,36 @@ gulp.task('default', function() { }); function runTests (singleRun, done) { - var reporters = ['mocha']; - var preprocessors = {}; + var reporters = ['mocha']; + var preprocessors = {}; + + var pathSrcJs = [ + path.join(__dirname, 'github.js'), + path.join(__dirname, 'test/*.js'), + path.join(__dirname, 'test/user.json') + ]; - var pathSrcJs = [ - path.join(__dirname, 'github.js') - ]; + if (singleRun) { + pathSrcJs.forEach(function(path) { + preprocessors[path] = ['coverage']; + }); + reporters.push('coverage'); - if (singleRun) { - pathSrcJs.forEach(function(path) { - preprocessors[path] = ['coverage']; - }); - reporters.push('coverage'); + preprocessors['test/user.json'] = ['json_fixtures']; + } - preprocessors['test/user.json'] = ['json_fixtures']; - } + var localConfig = { + files: pathSrcJs, + configFile: path.join(__dirname, './karma.conf.js'), + singleRun: singleRun, + autoWatch: !singleRun, + reporters: reporters, + preprocessors: preprocessors + }; - var localConfig = { - configFile: path.join(__dirname, './karma.conf.js'), - singleRun: singleRun, - autoWatch: !singleRun, - reporters: reporters, - preprocessors: preprocessors - }; + var server = new karma.Server(localConfig, function(failCount) { + done(failCount ? new Error('Failed ' + failCount + ' tests.') : null); + }); - var server = new karma.Server(localConfig, function(failCount) { - done(failCount ? new Error('Failed ' + failCount + ' tests.') : null); - }); - server.start(); + server.start(); } diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 00000000..015a91f9 --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,49 @@ +module.exports = function(config) { + 'use strict'; + + var configuration = { + client: { + captureConsole: true + }, + + singleRun: true, + + autoWatch: false, + + frameworks: ['mocha', 'chai'], + + browsers: ['PhantomJS'], + + coverageReporter: { + reporters: [ + { + type: 'lcov' + }, + { + type: 'text-summary' + } + ], + instrumenterOptions: { + istanbul: { + noCompact: true + } + } + } + }; + + // This block is needed to execute Chrome on Travis + // If you ever plan to use Chrome and Travis, you can keep it + // If not, you can safely remove it + // https://github.com/karma-runner/karma/issues/1144#issuecomment-53633076 + if (configuration.browsers[0] === 'Chrome' && process.env.TRAVIS) { + configuration.customLaunchers = { + 'chrome-travis-ci': { + base: 'Chrome', + flags: ['--no-sandbox'] + } + }; + configuration.browsers = ['chrome-travis-ci']; + } + + config.set(configuration); +}; diff --git a/package.json b/package.json index 4e505a9e..9a95bcd6 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,6 @@ "main": "github.js", "dependencies": { "js-base64": "^2.1.8", - "karma-json-fixtures-preprocessor": "0.0.5", "xmlhttprequest": "~1.7.0" }, "devDependencies": { @@ -13,6 +12,7 @@ "codecov": "^1.0.1", "gulp": "^3.9.0", "gulp-jscs": "^3.0.1", + "gulp-jscs-stylish": "^1.2.1", "gulp-jshint": "^1.11.2", "gulp-rename": "^1.2.2", "gulp-uglify": "^1.4.2", @@ -22,20 +22,17 @@ "karma": "^0.13.14", "karma-chai": "^0.1.0", "karma-coverage": "^0.5.3", + "karma-json-fixtures-preprocessor": "0.0.5", "karma-mocha": "^0.2.0", "karma-mocha-reporter": "^1.1.1", "karma-phantomjs-launcher": "^0.2.1", - "karma-sinon": "^1.0.4", "mocha": "^2.3.3", - "phantomjs": "^1.9.18", - "plato": "^1.4.0", - "sinon": "^1.17.2", - "sinon-chai": "^2.8.0" + "phantomjs": "^1.9.18" }, "scripts": { - "test": "mocha test/*.js && npm run-script jshint", - "jshint": "jshint github.js test/", - "codecov": "istanbul cover ./node_modules/mocha/bin/_mocha -- -R spec && cat ./coverage/lcov.info | ./node_modules/.bin/codecov" + "test": "gulp test && gulp lint", + "lint": "gulp lint", + "codecov": "cat coverage/*/lcov.info | codecov" }, "repository": { "type": "git", diff --git a/test/test.auth.js b/test/test.auth.js index 0a3c2d05..af93d28f 100644 --- a/test/test.auth.js +++ b/test/test.auth.js @@ -1,58 +1,56 @@ 'use strict'; -var test_user, github, user; +var testUser, github, user; if (typeof window === 'undefined') { - // module dependencies - var chai = require('chai'), - sinonChai = require('sinon-chai'); + // Module dependencies + var chai = require('chai'); + var Github = require('../'); - var Github = require('../'); - test_user = require('./user.json'); + testUser = require('./user.json'); - // Use should flavour for Mocha - var should = chai.should(); - chai.use(sinonChai); + // Use should flavour for Mocha + var should = chai.should(); } describe('Github constructor', function() { - before(function(){ - if (typeof window !== 'undefined') test_user = window.__fixtures__['test/user']; - - github = new Github({ - username: test_user.USERNAME, - password: test_user.PASSWORD, - auth: 'basic' - }); - - user = github.getUser(); - }); - - it('should authenticate and return no errors', function(done){ - user.notifications(function(err){ - should.not.exist(err); - done(); - }); - }); + before(function() { + if (typeof window !== 'undefined') testUser = window.__fixtures__['test/user']; + + github = new Github({ + username: testUser.USERNAME, + password: testUser.PASSWORD, + auth: 'basic' + }); + + user = github.getUser(); + }); + + it('should authenticate and return no errors', function(done) { + user.notifications(function(err) { + should.not.exist(err); + done(); + }); + }); }); describe('Github constructor (failing case)', function() { - before(function(){ - if (typeof window !== 'undefined') test_user = window.__fixtures__['test/user']; - - github = new Github({ - username: test_user.USERNAME, - password: 'fake124', - auth: 'basic' - }); - user = github.getUser(); - }); - - it('should fail authentication and return err', function(done){ - user.notifications(function(err){ - err.request.status.should.equal(401, 'Return 401 status for bad auth'); - JSON.parse(err.request.responseText).message.should.equal('Bad credentials'); - done(); - }); - }); + before(function() { + if (typeof window !== 'undefined') testUser = window.__fixtures__['test/user']; + + github = new Github({ + username: testUser.USERNAME, + password: 'fake124', + auth: 'basic' + }); + user = github.getUser(); + }); + + it('should fail authentication and return err', function(done) { + user.notifications(function(err) { + err.request.status.should.equal(401, 'Return 401 status for bad auth'); + JSON.parse(err.request.responseText).message.should.equal('Bad credentials'); + done(); + }); + }); }); diff --git a/test/test.issue.js b/test/test.issue.js index e85e6f83..c261a58c 100644 --- a/test/test.issue.js +++ b/test/test.issue.js @@ -1,48 +1,46 @@ 'use strict'; -var test_user, github, issues; +var testUser, github, issues; if (typeof window === 'undefined') { - // module dependencies - var chai = require('chai'), - sinonChai = require('sinon-chai'); + // Module dependencies + var chai = require('chai'); + var Github = require('../'); - var Github = require('../'); - test_user = require('./user.json'); + testUser = require('./user.json'); - // Use should flavour for Mocha - var should = chai.should(); - chai.use(sinonChai); + // Use should flavour for Mocha + var should = chai.should(); } describe('Github.Issue', function() { - before(function(){ - if (typeof window !== 'undefined') test_user = window.__fixtures__['test/user']; - - github = new Github({ - username : test_user.USERNAME, - password : test_user.PASSWORD, - auth : 'basic' - }); - - issues = github.getIssues('mikedeboertest', 'TestRepo'); - }); - - it('should list issues', function(done) { - issues.list({}, function(err, issues) { - should.not.exist(err); - issues.should.have.length.above(0); - done(); - }); - }); - - it('should post issue comment', function(done) { - issues.list({}, function(err, issuesList) { - issues.comment(issuesList[0], 'Comment test', function(err, res) { - should.not.exist(err); - res.body.should.equal('Comment test'); - done(); + before(function() { + if (typeof window !== 'undefined') testUser = window.__fixtures__['test/user']; + + github = new Github({ + username: testUser.USERNAME, + password: testUser.PASSWORD, + auth: 'basic' + }); + + issues = github.getIssues('mikedeboertest', 'TestRepo'); + }); + + it('should list issues', function(done) { + issues.list({}, function(err, issues) { + should.not.exist(err); + issues.should.have.length.above(0); + done(); + }); + }); + + it('should post issue comment', function(done) { + issues.list({}, function(err, issuesList) { + issues.comment(issuesList[0], 'Comment test', function(err, res) { + should.not.exist(err); + res.body.should.equal('Comment test'); + done(); + }); }); - }); - }); + }); }); diff --git a/test/test.repo.js b/test/test.repo.js index 9b285932..76a6cf8b 100644 --- a/test/test.repo.js +++ b/test/test.repo.js @@ -1,322 +1,345 @@ 'use strict'; -var github, repo, user, test_user; +var github, repo, user, testUser; if (typeof window === 'undefined') { - // module dependencies - var chai = require('chai'), - sinonChai = require('sinon-chai'); + // Module dependencies + var chai = require('chai'); + var Github = require('../'); - var Github = require('../'); - test_user = require('./user.json'); + testUser = require('./user.json'); - // Use should flavour for Mocha - var should = chai.should(); - chai.use(sinonChai); + // Use should flavour for Mocha + var should = chai.should(); } describe('Github.Repository', function() { - before(function(){ - if (typeof window !== 'undefined') test_user = window.__fixtures__['test/user']; - - github = new Github({ - username : test_user.USERNAME, - password : test_user.PASSWORD, - auth : 'basic' - }); - - repo = github.getRepo('michael', 'github'); - }); - - it('should show repo', function(done) { - repo.show(function(err, res) { - should.not.exist(err); - res.full_name.should.equal('michael/github'); - done(); - }); - }); - - it('should show repo contents', function(done) { - repo.contents('master', './', function(err) { - should.not.exist(err); - // @TODO write better assertion. - done(); - }); - }); - - it('should fork repo', function(done) { - repo.fork(function(err) { - should.not.exist(err); - // @TODO write better assertion. - done(); - }); - }); - - it('should show repo contributors', function(done) { - repo.contributors(function(err, res) { - should.not.exist(err); - res.should.be.instanceof(Array); - res.should.have.length.above(1); - should.exist(res[0].author); - should.exist(res[0].total); - should.exist(res[0].weeks); - done(); - }); - }); - - //@TODO repo.branch, repo.pull - - it('should list repo branches', function(done) { - repo.listBranches(function(err) { - should.not.exist(err); - done(); - }); - }); - - it('should read repo', function(done) { - repo.read('master', 'README.md', function(err, res) { - res.indexOf('# Github.js').should.be.above(-1); - done(); - }); - }); - - it('should get commit from repo', function(done) { - repo.getCommit('master', '20fcff9129005d14cc97b9d59b8a3d37f4fb633b', function(err, commit) { - should.not.exist(err); - commit.message.should.equal('v0.10.4'); - commit.author.date.should.equal('2015-03-20T17:01:42Z'); - done(); - }); - }); - - it('should get a SHA from a repo', function(done) { - repo.getSha('master', '.gitignore', function(err, sha) { - should.not.exist(err); - sha.should.equal('743f72052be92b3e7f42b8318f2663a9011ef5be'); - done(); - }); - }); - - it('should get a repo by fullname', function(done) { - var repo2 = github.getRepo('michael/github'); - repo2.show(function(err, res) { - should.not.exist(err); - res.full_name.should.equal('michael/github'); - done(); - }); - }); + before(function() { + if (typeof window !== 'undefined') testUser = window.__fixtures__['test/user']; + + github = new Github({ + username: testUser.USERNAME, + password: testUser.PASSWORD, + auth: 'basic' + }); + + repo = github.getRepo('michael', 'github'); + }); + + it('should show repo', function(done) { + repo.show(function(err, res) { + should.not.exist(err); + res.full_name.should.equal('michael/github'); // jscs:ignore + done(); + }); + }); + + it('should show repo contents', function(done) { + repo.contents('master', './', function(err) { + should.not.exist(err); + + // @TODO write better assertion. + done(); + }); + }); + + it('should fork repo', function(done) { + repo.fork(function(err) { + should.not.exist(err); + + // @TODO write better assertion. + done(); + }); + }); + + it('should show repo contributors', function(done) { + repo.contributors(function(err, res) { + should.not.exist(err); + res.should.be.instanceof(Array); + res.should.have.length.above(1); + should.exist(res[0].author); + should.exist(res[0].total); + should.exist(res[0].weeks); + done(); + }); + }); + + // @TODO repo.branch, repo.pull + + it('should list repo branches', function(done) { + repo.listBranches(function(err) { + should.not.exist(err); + done(); + }); + }); + + it('should read repo', function(done) { + repo.read('master', 'README.md', function(err, res) { + res.indexOf('# Github.js').should.be.above(-1); + done(); + }); + }); + + it('should get commit from repo', function(done) { + repo.getCommit('master', '20fcff9129005d14cc97b9d59b8a3d37f4fb633b', function(err, commit) { + should.not.exist(err); + commit.message.should.equal('v0.10.4'); + commit.author.date.should.equal('2015-03-20T17:01:42Z'); + done(); + }); + }); + + it('should get a SHA from a repo', function(done) { + repo.getSha('master', '.gitignore', function(err, sha) { + should.not.exist(err); + sha.should.equal('743f72052be92b3e7f42b8318f2663a9011ef5be'); + done(); + }); + }); + + it('should get a repo by fullname', function(done) { + var repo2 = github.getRepo('michael/github'); + + repo2.show(function(err, res) { + should.not.exist(err); + res.full_name.should.equal('michael/github'); // jscs:ignore + done(); + }); + }); }); var repoTest = Math.floor(Math.random() * (100000 - 0)) + 0; describe('Creating new Github.Repository', function() { - before(function(){ - if (typeof window !== 'undefined') test_user = window.__fixtures__['test/user']; - - github = new Github({ - username : test_user.USERNAME, - password : test_user.PASSWORD, - auth : 'basic' - }); - - user = github.getUser(); - repo = github.getRepo(test_user.USERNAME, repoTest); - }); - - it('should create repo', function(done) { - user.createRepo({'name' : repoTest}, function(err, res) { - should.not.exist(err); - res.name.should.equal(repoTest.toString()); - done(); - }); - }); - - it('should write to repo', function(done) { - repo.write('master', 'TEST.md', 'THIS IS A TEST', 'Creating test', function(err) { - should.not.exist(err); - // @TODO write a better assertion. - done(); - }); - }); - - it('should write to repo branch', function(done) { - this.timeout(8000); // Bit of a longer timeout - - repo.branch('master', 'dev', function(err) { - should.not.exist(err); - repo.write('dev', 'TEST.md', 'THIS IS AN UPDATED TEST', 'Updating test', function(err) { - should.not.exist(err); - repo.read('dev', 'TEST.md', function(err, res) { - res.should.equal('THIS IS AN UPDATED TEST'); - should.not.exist(err); - done(); - }); + before(function() { + if (typeof window !== 'undefined') testUser = window.__fixtures__['test/user']; + + github = new Github({ + username: testUser.USERNAME, + password: testUser.PASSWORD, + auth: 'basic' + }); + + user = github.getUser(); + repo = github.getRepo(testUser.USERNAME, repoTest); + }); + + it('should create repo', function(done) { + user.createRepo({ + name: repoTest + }, function(err, res) { + should.not.exist(err); + res.name.should.equal(repoTest.toString()); + done(); + }); + }); + + it('should write to repo', function(done) { + repo.write('master', 'TEST.md', 'THIS IS A TEST', 'Creating test', function(err) { + should.not.exist(err); + + // @TODO write a better assertion. + done(); + }); + }); + + it('should write to repo branch', function(done) { + this.timeout(8000); // Bit of a longer timeout + + repo.branch('master', 'dev', function(err) { + should.not.exist(err); + repo.write('dev', 'TEST.md', 'THIS IS AN UPDATED TEST', 'Updating test', function(err) { + should.not.exist(err); + repo.read('dev', 'TEST.md', function(err, res) { + res.should.equal('THIS IS AN UPDATED TEST'); + should.not.exist(err); + done(); + }); + }); + }); + }); + + it('should get ref from repo', function(done) { + repo.getRef('heads/master', function(err) { + should.not.exist(err); + + // @TODO write better assertion + done(); }); - }); - }); - - it('should get ref from repo', function(done) { - repo.getRef('heads/master', function(err) { - should.not.exist(err); - // @TODO write better assertion - done(); - }); - }); - - it('should create ref on repo', function(done) { - repo.getRef('heads/master', function(err, sha) { - var refSpec = {ref : 'refs/heads/new-test-branch', sha : sha}; - repo.createRef(refSpec, function(err) { - should.not.exist(err); - // @TODO write better assertion - done(); + }); + + it('should create ref on repo', function(done) { + repo.getRef('heads/master', function(err, sha) { + var refSpec = { + ref: 'refs/heads/new-test-branch', sha: sha + }; + + repo.createRef(refSpec, function(err) { + should.not.exist(err); + + // @TODO write better assertion + done(); + }); + }); + }); + + it('should delete ref on repo', function(done) { + repo.deleteRef('heads/new-test-branch', function(err) { + should.not.exist(err); + + // @TODO write better assertion + done(); }); - }); - }); - - it('should delete ref on repo', function(done) { - repo.deleteRef('heads/new-test-branch', function(err) { - should.not.exist(err); - // @TODO write better assertion - done(); - }); - }); - - it('should list tags on repo', function(done) { - repo.listTags(function(err) { - should.not.exist(err); - // @TODO write better assertion - done(); - }); - }); - - it('should list pulls on repo', function(done) { - repo.listPulls('open', function(err) { - should.not.exist(err); - // @TODO write better assertion - done(); - }); - }); - - it('should get pull requests on repo', function(done) { - var repo = github.getRepo('michael', 'github'); - repo.getPull(153, function(err) { - should.not.exist(err); - // @TODO write better assertion - done(); - }); - }); - - it('should list pull requests on repo', function(done) { - repo.listPulls('open', function(err) { - should.not.exist(err); - done(); - }); - }); - - it('should write author and committer to repo', function(done) { - var options = { - author : {name : 'Author Name', email : 'author@example.com'}, - committer : {name : 'Committer Name', email : 'committer@example.com'} - }; - repo.write('dev', 'TEST.md', 'THIS IS A TEST BY AUTHOR AND COMMITTER', 'Updating', options, function(err, res) { - should.not.exist(err); - repo.getCommit('dev', res.commit.sha, function(err, commit) { - should.not.exist(err); - commit.author.name.should.equal('Author Name'); - commit.author.email.should.equal('author@example.com'); - commit.committer.name.should.equal('Committer Name'); - commit.committer.email.should.equal('committer@example.com'); - - done(); + }); + + it('should list tags on repo', function(done) { + repo.listTags(function(err) { + should.not.exist(err); + + // @TODO write better assertion + done(); }); - }); - }); - - it('should be able to write CJK unicode to repo', function(done) { - repo.write('master', '中文测试.md', 'THIS IS A TEST', 'Creating test', function(err) { - should.not.exist(err); - // @TODO write better assertion - done(); - }); - }); - - it('should be able to write unicode to repo', function(done) { - repo.write('master', 'TEST_unicode.md', '\u2014', 'Long dash unicode', function(err) { - should.not.exist(err); - - repo.read('master', 'TEST_unicode.md', function(err, obj) { - should.not.exist(err); - obj.should.equal('\u2014'); - - done(); + }); + + it('should list pulls on repo', function(done) { + repo.listPulls('open', function(err) { + should.not.exist(err); + + // @TODO write better assertion + done(); }); - }); - }); + }); - it('should pass a regression test for _request (#14)', function(done) { - this.timeout(8000); // Bit of a longer timeout + it('should get pull requests on repo', function(done) { + var repo = github.getRepo('michael', 'github'); - repo.getRef('heads/master', function(err, sha) { - var refSpec = {ref : 'refs/heads/testing-14', sha : sha}; - repo.createRef(refSpec, function(err) { - should.not.exist(err); + repo.getPull(153, function(err) { + should.not.exist(err); - // Triggers GET: - // https://api.github.com/repos/michael/cmake_cdt7_stalled/git/refs/heads/prose-integration - repo.getRef('heads/master', function(err) { - should.not.exist(err); + // @TODO write better assertion + done(); + }); + }); - // Triggers DELETE: - // https://api.github.com/repos/michael/cmake_cdt7_stalled/git/refs/heads/prose-integration - repo.deleteRef('heads/testing-14', function(err, res, xhr) { + it('should list pull requests on repo', function(done) { + repo.listPulls('open', function(err) { + should.not.exist(err); + done(); + }); + }); + + it('should write author and committer to repo', function(done) { + var options = { + author: { + name: 'Author Name', email: 'author@example.com' + }, + committer: { + name: 'Committer Name', email: 'committer@example.com' + } + }; + + repo.write('dev', 'TEST.md', 'THIS IS A TEST BY AUTHOR AND COMMITTER', 'Updating', options, function(err, res) { + should.not.exist(err); + repo.getCommit('dev', res.commit.sha, function(err, commit) { should.not.exist(err); - xhr.status.should.equal(204); + commit.author.name.should.equal('Author Name'); + commit.author.email.should.equal('author@example.com'); + commit.committer.name.should.equal('Committer Name'); + commit.committer.email.should.equal('committer@example.com'); + done(); - }); - }); + }); }); - }); - }); + }); + + it('should be able to write CJK unicode to repo', function(done) { + repo.write('master', '中文测试.md', 'THIS IS A TEST', 'Creating test', function(err) { + should.not.exist(err); + + // @TODO write better assertion + done(); + }); + }); + + it('should be able to write unicode to repo', function(done) { + repo.write('master', 'TEST_unicode.md', '\u2014', 'Long dash unicode', function(err) { + should.not.exist(err); + + repo.read('master', 'TEST_unicode.md', function(err, obj) { + should.not.exist(err); + obj.should.equal('\u2014'); + + done(); + }); + }); + }); + + it('should pass a regression test for _request (#14)', function(done) { + this.timeout(8000); // Bit of a longer timeout + + repo.getRef('heads/master', function(err, sha) { + var refSpec = { + ref: 'refs/heads/testing-14', sha: sha + }; + + repo.createRef(refSpec, function(err) { + should.not.exist(err); + + // Triggers GET: + // https://api.github.com/repos/michael/cmake_cdt7_stalled/git/refs/heads/prose-integration + repo.getRef('heads/master', function(err) { + should.not.exist(err); + + // Triggers DELETE: + // https://api.github.com/repos/michael/cmake_cdt7_stalled/git/refs/heads/prose-integration + repo.deleteRef('heads/testing-14', function(err, res, xhr) { + should.not.exist(err); + xhr.status.should.equal(204); + done(); + }); + }); + }); + }); + }); }); describe('deleting a Github.Repository', function() { - before(function(){ - if (typeof window !== 'undefined') test_user = window.__fixtures__['test/user']; - github = new Github({ - username : test_user.USERNAME, - password : test_user.PASSWORD, - auth : 'basic' - }); - repo = github.getRepo(test_user.USERNAME, repoTest); - }); - - it('should delete the repo', function(done){ - repo.deleteRepo(function(err, res) { - should.not.exist(err); - res.should.be.true; //jshint ignore:line - done(); - }); - }); + before(function() { + if (typeof window !== 'undefined') testUser = window.__fixtures__['test/user']; + github = new Github({ + username: testUser.USERNAME, + password: testUser.PASSWORD, + auth: 'basic' + }); + repo = github.getRepo(testUser.USERNAME, repoTest); + }); + + it('should delete the repo', function(done) { + repo.deleteRepo(function(err, res) { + should.not.exist(err); + res.should.be.true; // jshint ignore:line + done(); + }); + }); }); describe('Repo returns commit errors correctly', function() { - before(function(){ - if (typeof window !== 'undefined') test_user = window.__fixtures__['test/user']; - github = new Github({ - username : test_user.USERNAME, - password : test_user.PASSWORD, - auth : 'basic' - }); - repo = github.getRepo(test_user.USERNAME, test_user.REPO); - }); - - it('should fail on broken commit', function(done){ - repo.commit('broken-parent-hash', 'broken-tree-hash', 'commit message', function(err) { - should.exist(err); - should.exist(err.request); - err.request.status.should.equal(422); - done(); - }); - }); + before(function() { + if (typeof window !== 'undefined') testUser = window.__fixtures__['test/user']; + github = new Github({ + username: testUser.USERNAME, + password: testUser.PASSWORD, + auth: 'basic' + }); + repo = github.getRepo(testUser.USERNAME, testUser.REPO); + }); + + it('should fail on broken commit', function(done) { + repo.commit('broken-parent-hash', 'broken-tree-hash', 'commit message', function(err) { + should.exist(err); + should.exist(err.request); + err.request.status.should.equal(422); + done(); + }); + }); }); diff --git a/test/test.search.js b/test/test.search.js index bd3b11ec..a084d126 100644 --- a/test/test.search.js +++ b/test/test.search.js @@ -3,65 +3,62 @@ var github; if (typeof window === 'undefined') { - // module dependencies - var chai = require('chai'), - sinonChai = require('sinon-chai'); + // Module dependencies + var chai = require('chai'); + var Github = require('../'); + var testUser = require('./user.json'); - var Github = require('../'); - var test_user = require('./user.json'); - - // Use should flavour for Mocha - var should = chai.should(); - chai.use(sinonChai); + // Use should flavour for Mocha + var should = chai.should(); } describe('Github.Search', function() { - before(function(){ - if (typeof window !== 'undefined') test_user = window.__fixtures__['test/user']; - github = new Github({ - username: test_user.USERNAME, - password: test_user.PASSWORD, - auth: "basic" - }); - }); + before(function() { + if (typeof window !== 'undefined') testUser = window.__fixtures__['test/user']; + github = new Github({ + username: testUser.USERNAME, + password: testUser.PASSWORD, + auth: 'basic' + }); + }); - it('should search.repositories', function(done) { - var search = github.getSearch('tetris+language:assembly&sort=stars&order=desc'); - var options = null; + it('should search.repositories', function(done) { + var search = github.getSearch('tetris+language:assembly&sort=stars&order=desc'); + var options = null; - search.repositories(options, function (err) { - should.not.exist(err); - done(); - }); - }); + search.repositories(options, function (err) { + should.not.exist(err); + done(); + }); + }); - it('should search.code', function(done) { - var search = github.getSearch('addClass+in:file+language:js+repo:jquery/jquery'); - var options = null; + it('should search.code', function(done) { + var search = github.getSearch('addClass+in:file+language:js+repo:jquery/jquery'); + var options = null; - search.code(options, function (err) { - should.not.exist(err); - done(); - }); - }); + search.code(options, function (err) { + should.not.exist(err); + done(); + }); + }); - it('should search.issues', function(done) { - var search = github.getSearch('windows+label:bug+language:python+state:open&sort=created&order=asc'); - var options = null; + it('should search.issues', function(done) { + var search = github.getSearch('windows+label:bug+language:python+state:open&sort=created&order=asc'); + var options = null; - search.issues(options, function (err) { - should.not.exist(err); - done(); - }); - }); + search.issues(options, function (err) { + should.not.exist(err); + done(); + }); + }); - it('should search.users', function(done) { - var search = github.getSearch('tom+repos:%3E42+followers:%3E1000'); - var options = null; + it('should search.users', function(done) { + var search = github.getSearch('tom+repos:%3E42+followers:%3E1000'); + var options = null; - search.users(options, function (err) { - should.not.exist(err); - done(); - }); - }); + search.users(options, function (err) { + should.not.exist(err); + done(); + }); + }); }); diff --git a/test/test.user.js b/test/test.user.js index 4e92e4fa..d32c1ee2 100644 --- a/test/test.user.js +++ b/test/test.user.js @@ -1,153 +1,155 @@ 'use strict'; -var test_user, user, github; +var testUser, user, github; if (typeof window === 'undefined') { - // module dependencies - var chai = require('chai'), - sinonChai = require('sinon-chai'); + // Module dependencies + var chai = require('chai'); + var Github = require('../'); - var Github = require('../'); - test_user = require('./user.json'); + testUser = require('./user.json'); - // Use should flavour for Mocha - var should = chai.should(); - chai.use(sinonChai); + // Use should flavour for Mocha + var should = chai.should(); } describe('Github.User', function() { - before(function(){ - if (typeof window !== 'undefined') test_user = window.__fixtures__['test/user']; - github = new Github({ - username: test_user.USERNAME, - password: test_user.PASSWORD, - auth: 'basic' - }); - user = github.getUser(); - - this.timeout(8000); // Bit of a longer timeout - }); - - it('should get user.repos', function(done) { - this.timeout(8000); // Bit of a longer timeout - - user.repos(function(err) { - should.not.exist(err); - done(); - }); - }); - - it('should get user.repos with options', function(done) { - var options = { - type: 'owner', - sort: 'updated', - per_page: 10, - page: 1 - }; - user.repos(options, function(err, repos) { - repos.should.have.length(10); - should.not.exist(err); - - done(); - }); - }); - - it('should get user.orgs', function(done) { - user.orgs(function(err) { - should.not.exist(err); - done(); - }); - }); - - it('should get user.gists', function(done) { - user.gists(function(err) { - should.not.exist(err); - done(); - }); - }); - - it('should get user.notifications', function(done) { - user.notifications(function(err) { - should.not.exist(err); - done(); - }); - }); - - it('should get user.notifications with options', function(done) { - var options = { - all: true, - participating: true, - since: '2015-01-01T00:00:00Z', - before: '2015-02-01T00:00:00Z' - }; - user.notifications(options, function(err) { - should.not.exist(err); - done(); - }); - }); - - it('should show user', function(done) { - user.show('ingalls', function(err) { - should.not.exist(err); - done(); - }); - }); - - it('should show user\'s repos', function(done) { - user.userRepos(test_user.USERNAME, function(err) { - should.not.exist(err); - done(); - }); - }); - - it('should show user\'s starred repos', function(done) { - user.userStarred(test_user.USERNAME, function(err) { - should.not.exist(err); - done(); - }); - }); - - it('should show user\'s gists', function(done) { - user.userGists(test_user.USERNAME, function(err) { - should.not.exist(err); - done(); - }); - }); - - it('should show user\'s organisation repos', function(done) { - user.orgRepos('openaddresses', function(err) { - should.not.exist(err); - done(); - }); - }); - - it('should follow user', function(done) { - user.follow('ingalls', function(err) { - should.not.exist(err); - done(); - }); - }); - - it('should unfollow user', function(done) { - user.unfollow('ingalls', function(err) { - should.not.exist(err); - done(); - }); - }); - - it('should create a repo', function(done) { - var repoTest = Math.floor(Math.random() * (100000 - 0)) + 0; - var github = new Github({ - username: test_user.USERNAME, - password: test_user.PASSWORD, - auth: 'basic' - }); - var user = github.getUser(); - - user.createRepo({ 'name': repoTest }, function (err, res) { - should.not.exist(err); - res.name.should.equal(repoTest.toString()); - done(); - }); - }); + before(function() { + if (typeof window !== 'undefined') testUser = window.__fixtures__['test/user']; + github = new Github({ + username: testUser.USERNAME, + password: testUser.PASSWORD, + auth: 'basic' + }); + user = github.getUser(); + + this.timeout(8000); // Bit of a longer timeout + }); + + it('should get user.repos', function(done) { + this.timeout(8000); // Bit of a longer timeout + + user.repos(function(err) { + should.not.exist(err); + done(); + }); + }); + + it('should get user.repos with options', function(done) { + var options = { + type: 'owner', + sort: 'updated', + per_page: 10, // jscs:ignore + page: 1 + }; + + user.repos(options, function(err, repos) { + repos.should.have.length(10); + should.not.exist(err); + + done(); + }); + }); + + it('should get user.orgs', function(done) { + user.orgs(function(err) { + should.not.exist(err); + done(); + }); + }); + + it('should get user.gists', function(done) { + user.gists(function(err) { + should.not.exist(err); + done(); + }); + }); + + it('should get user.notifications', function(done) { + user.notifications(function(err) { + should.not.exist(err); + done(); + }); + }); + + it('should get user.notifications with options', function(done) { + var options = { + all: true, + participating: true, + since: '2015-01-01T00:00:00Z', + before: '2015-02-01T00:00:00Z' + }; + + user.notifications(options, function(err) { + should.not.exist(err); + done(); + }); + }); + + it('should show user', function(done) { + user.show('ingalls', function(err) { + should.not.exist(err); + done(); + }); + }); + + it('should show user\'s repos', function(done) { + user.userRepos(testUser.USERNAME, function(err) { + should.not.exist(err); + done(); + }); + }); + + it('should show user\'s starred repos', function(done) { + user.userStarred(testUser.USERNAME, function(err) { + should.not.exist(err); + done(); + }); + }); + + it('should show user\'s gists', function(done) { + user.userGists(testUser.USERNAME, function(err) { + should.not.exist(err); + done(); + }); + }); + + it('should show user\'s organisation repos', function(done) { + user.orgRepos('openaddresses', function(err) { + should.not.exist(err); + done(); + }); + }); + + it('should follow user', function(done) { + user.follow('ingalls', function(err) { + should.not.exist(err); + done(); + }); + }); + + it('should unfollow user', function(done) { + user.unfollow('ingalls', function(err) { + should.not.exist(err); + done(); + }); + }); + + it('should create a repo', function(done) { + var repoTest = Math.floor(Math.random() * (100000 - 0)) + 0; + var github = new Github({ + username: testUser.USERNAME, + password: testUser.PASSWORD, + auth: 'basic' + }); + var user = github.getUser(); + + user.createRepo({ + name: repoTest + }, function (err, res) { + should.not.exist(err); + res.name.should.equal(repoTest.toString()); + done(); + }); + }); });