From 6f13d71fce4a09eb3b4e3f3c57767180e3470625 Mon Sep 17 00:00:00 2001 From: Clay Reimann Date: Mon, 29 Feb 2016 08:33:48 -0600 Subject: [PATCH 1/2] Add release events api --- src/github.js | 28 ++++++++++++++++++++++ test/test.repo.js | 59 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/src/github.js b/src/github.js index cb6546a5..dd4da081 100644 --- a/src/github.js +++ b/src/github.js @@ -927,6 +927,34 @@ this.unstar = function(owner, repository, cb) { _request('DELETE', '/user/starred/' + owner + '/' + repository, null, cb); }; + + // Create a new release + // -------- + + this.createRelease = function(options, cb) { + _request('POST', repoPath + '/releases', options, cb); + }; + + // Edit a release + // -------- + + this.editRelease = function(id, options, cb) { + _request('PATCH', repoPath + '/releases/' + id, options, cb); + }; + + // Get a single release + // -------- + + this.getRelease = function(id, cb) { + _request('GET', repoPath + '/releases/' + id, null, cb); + }; + + // Remove a release + // -------- + + this.deleteRelease = function(id, cb) { + _request('DELETE', repoPath + '/releases/' + id, null, cb); + }; }; // Gists API diff --git a/test/test.repo.js b/test/test.repo.js index bb405cdc..fe9e73d5 100644 --- a/test/test.repo.js +++ b/test/test.repo.js @@ -2,7 +2,12 @@ var Github = require('../src/github.js'); var testUser = require('./user.json'); -var github, repo, user, imageB64, imageBlob; +var RELEASE_TAG = 'foo'; +var RELEASE_NAME = 'My awesome release'; +var RELEASE_BODY = 'Foo bar bazzy baz'; +var STATUS_URL = 'https://api.github.com/repos/michael/github/statuses/20fcff9129005d14cc97b9d59b8a3d37f4fb633b'; + +var github, repo, user, imageB64, imageBlob, sha, releaseId; if (typeof window === 'undefined') { // We're in NodeJS var fs = require('fs'); @@ -33,6 +38,7 @@ if (typeof window === 'undefined') { // We're in NodeJS // jscs:disable imageB64 = 'iVBORw0KGgoAAAANSUhEUgAAACsAAAAmCAAAAAB4qD3CAAABgElEQVQ4y9XUsUocURQGYN/pAyMWBhGtrEIMiFiooGuVIoYsSBAsRSQvYGFWC4uFhUBYsilXLERQsDA20YAguIbo5PQp3F3inVFTheSvZoavGO79z+mJP0/Pv2nPtlfLpfLq9tljNquO62S8mj1kmy/8nrHm/Xaz1930bt5n1+SzVmyrilItsod9ON0td1V59xR9hwV2HsMRsbfROLo4amzsRcQw5vO2CZPJEU5CM2cXYTCxg7CY2mwIVhK7AkNZYg9g4CqxVwNwkNg6zOTKMQP1xFZgKWeXoJLYdSjl7BysJ7YBIzk7Ap8TewLOE3oOTtIz6y/64bfQn55ZTIAPd2gNTOTurcbzp7z50v1y/Pq2Q7Wczca8vFjG6LvbMo92hiPL96xO+eYVPkVExMdONetFXZ+l+eP9cuV7RER8a9PZwrloTXv2tfv285ZOt4rnrTXlydxCu9sZmGrdN8eXC3ATERHXsHD5wC7ZL3HdsaX9R3bUzlb7YWvn/9ipf93+An8cHsx3W3WHAAAAAElFTkSuQmCC'; imageBlob = new Blob(); + // jscs:enable } } @@ -207,7 +213,7 @@ describe('Github.Repository', function() { xhr.should.be.instanceof(XMLHttpRequest); statuses.length.should.equal(6); statuses.every(function(status) { - return status.url === 'https://api.github.com/repos/michael/github/statuses/20fcff9129005d14cc97b9d59b8a3d37f4fb633b'; + return status.url === STATUS_URL; }).should.equal(true); done(); @@ -534,6 +540,7 @@ describe('Creating new Github.Repository', function() { }, function(err, res, xhr) { should.not.exist(err); xhr.should.be.instanceof(XMLHttpRequest); + sha = res.commit.sha; done(); }); @@ -578,6 +585,54 @@ describe('Creating new Github.Repository', function() { }); }); }); + + it('should create a release', function(done) { + var options = { + tag_name: RELEASE_TAG, + target_commitish: sha + }; + + repo.createRelease(options, function(err, res, xhr) { + should.not.exist(err); + xhr.should.be.instanceof(XMLHttpRequest); + + releaseId = res.id; + done(); + }); + }); + + it('should edit a release', function(done) { + var options = { + name: RELEASE_NAME, + body: RELEASE_BODY + }; + + repo.editRelease(releaseId, options, function(err, res, xhr) { + should.not.exist(err); + res.name.should.equal(RELEASE_NAME); + res.body.should.equal(RELEASE_BODY); + xhr.should.be.instanceof(XMLHttpRequest); + + done(); + }); + }); + + it('should read a release', function(done) { + repo.getRelease(releaseId, function(err, res, xhr) { + should.not.exist(err); + res.name.should.equal(RELEASE_NAME); + xhr.should.be.instanceof(XMLHttpRequest); + done(); + }); + }); + + it('should delete a release', function(done) { + repo.deleteRelease(releaseId, function(err, res, xhr) { + should.not.exist(err); + xhr.should.be.instanceof(XMLHttpRequest); + done(); + }); + }); }); describe('deleting a Github.Repository', function() { From 476076b3539e0c6ed0e7e9b28bbf40744ec4a313 Mon Sep 17 00:00:00 2001 From: Clay Reimann Date: Mon, 29 Feb 2016 16:06:57 -0600 Subject: [PATCH 2/2] Add PR and comment related methods --- src/github.js | 282 ++++++++++++++++++++++++++++------------------ test/test.repo.js | 131 +++++++++++++++++---- 2 files changed, 281 insertions(+), 132 deletions(-) diff --git a/src/github.js b/src/github.js index dd4da081..9c57932e 100644 --- a/src/github.js +++ b/src/github.js @@ -11,7 +11,7 @@ */ 'use strict'; -(function (root, factory) { +(function(root, factory) { /* istanbul ignore next */ if (typeof define === 'function' && define.amd) { define( @@ -21,7 +21,7 @@ 'utf8', 'axios' ], - function (Promise, Base64, Utf8, axios) { + function(Promise, Base64, Utf8, axios) { return (root.Github = factory(Promise, Base64, Utf8, axios)); } ); @@ -42,7 +42,7 @@ // Initial Setup // ------------- - var Github = function (options) { + var Github = function(options) { options = options || {}; var API_URL = options.apiUrl || 'https://api.github.com'; @@ -87,13 +87,13 @@ } return axios(config) - .then(function (response) { + .then(function(response) { cb( null, response.data || true, response.request ); - }, function (response) { + }, function(response) { if (response.status === 304) { cb( null, @@ -114,7 +114,7 @@ var results = []; (function iterate() { - _request('GET', path, null, function (err, res, xhr) { + _request('GET', path, null, function(err, res, xhr) { if (err) { return cb(err); } @@ -128,7 +128,7 @@ var next = (xhr.getResponseHeader('link') || '') .split(',') .filter(function(link) { - return /rel="next"/.test(link); + return /rel='next'/.test(link); }) .map(function(link) { return (/<(.*)>/.exec(link) || [])[1]; @@ -148,8 +148,8 @@ // User API // ======= - Github.User = function () { - this.repos = function (options, cb) { + Github.User = function() { + this.repos = function(options, cb) { if (typeof options === 'function') { cb = options; options = {}; @@ -176,21 +176,21 @@ // List user organizations // ------- - this.orgs = function (cb) { + this.orgs = function(cb) { _request('GET', '/user/orgs', null, cb); }; // List authenticated user's gists // ------- - this.gists = function (cb) { + this.gists = function(cb) { _request('GET', '/gists', null, cb); }; // List authenticated user's unread notifications // ------- - this.notifications = function (options, cb) { + this.notifications = function(options, cb) { if (typeof options === 'function') { cb = options; options = {}; @@ -242,7 +242,7 @@ // Show user information // ------- - this.show = function (username, cb) { + this.show = function(username, cb) { var command = username ? '/users/' + username : '/user'; _request('GET', command, null, cb); @@ -251,7 +251,7 @@ // List user repositories // ------- - this.userRepos = function (username, options, cb) { + this.userRepos = function(username, options, cb) { if (typeof options === 'function') { cb = options; options = {}; @@ -276,7 +276,7 @@ // List user starred repositories // ------- - this.userStarred = function (username, cb) { + 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=100', cb); }; @@ -284,14 +284,14 @@ // List a user's gists // ------- - this.userGists = function (username, cb) { + this.userGists = function(username, cb) { _request('GET', '/users/' + username + '/gists', null, cb); }; // List organization repositories // ------- - this.orgRepos = function (orgname, cb) { + 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); }; @@ -299,20 +299,20 @@ // Follow user // ------- - this.follow = function (username, cb) { + this.follow = function(username, cb) { _request('PUT', '/user/following/' + username, null, cb); }; // Unfollow user // ------- - this.unfollow = function (username, cb) { + this.unfollow = function(username, cb) { _request('DELETE', '/user/following/' + username, null, cb); }; // Create a repo // ------- - this.createRepo = function (options, cb) { + this.createRepo = function(options, cb) { _request('POST', '/user/repos', options, cb); }; }; @@ -320,7 +320,7 @@ // Repository API // ======= - Github.Repository = function (options) { + Github.Repository = function(options) { var repo = options.name; var user = options.user; var fullname = options.fullname; @@ -347,7 +347,7 @@ return cb(null, currentTree.sha); } - that.getRef('heads/' + branch, function (err, sha) { + that.getRef('heads/' + branch, function(err, sha) { currentTree.branch = branch; currentTree.sha = sha; cb(err, sha); @@ -357,8 +357,8 @@ // Get a particular reference // ------- - this.getRef = function (ref, cb) { - _request('GET', repoPath + '/git/refs/' + ref, null, function (err, res, xhr) { + this.getRef = function(ref, cb) { + _request('GET', repoPath + '/git/refs/' + ref, null, function(err, res, xhr) { if (err) { return cb(err); } @@ -371,11 +371,11 @@ // -------- // // { - // "ref": "refs/heads/my-new-branch-name", - // "sha": "827efc6d56897b048c772eb4087f854f46256132" + // 'ref': 'refs/heads/my-new-branch-name', + // 'sha': '827efc6d56897b048c772eb4087f854f46256132' // } - this.createRef = function (options, cb) { + this.createRef = function(options, cb) { _request('POST', repoPath + '/git/refs', options, cb); }; @@ -385,28 +385,28 @@ // Repo.deleteRef('heads/gh-pages') // repo.deleteRef('tags/v1.0') - this.deleteRef = function (ref, cb) { + this.deleteRef = function(ref, cb) { _request('DELETE', repoPath + '/git/refs/' + ref, options, cb); }; // Delete a repo // -------- - this.deleteRepo = function (cb) { + this.deleteRepo = function(cb) { _request('DELETE', repoPath, options, cb); }; // List all tags of a repository // ------- - this.listTags = function (cb) { + this.listTags = function(cb) { _request('GET', repoPath + '/tags', null, cb); }; // List all pull requests of a respository // ------- - this.listPulls = function (options, cb) { + this.listPulls = function(options, cb) { options = options || {}; var url = repoPath + '/pulls'; var params = []; @@ -454,27 +454,91 @@ // Gets details for a specific pull request // ------- - this.getPull = function (number, cb) { + this.getPull = function(number, cb) { _request('GET', repoPath + '/pulls/' + number, null, cb); }; + // Gets files for a specific pull request + + this.getPullFiles = function(number, cb) { + _request('GET', repoPath + '/pulls/' + number + '/files', null, function(err, files, xhr) { + if (err) { + return cb(err); + } + + cb(null, files, xhr); + }); + }; + + this.getPullComments = function(number, cb) { + _request('GET', repoPath + '/issues/' + number + '/comments', null, function(err, comments, xhr) { + if (err) { + return cb(err); + } + + cb(null, comments, xhr); + }); + }; + + // Create a comment for a specific pull issue + + this.createIssueComment = function(number, comment, cb) { + _request('POST', repoPath + '/issues/' + number + '/comments', { + body: comment + }, function(err, comment, xhr) { + if (err) { + return cb(err); + } + + cb(null, comment, xhr); + }); + }; + + /* Options: + * commit_id: sha, + * path: path, + * position: position + * body: comment, + */ + this.createFileComment = function(number, options, cb) { + _request('POST', repoPath + '/pulls/' + number + '/comments', options, function(err, comment, xhr) { + if (err) { + return cb(err); + } + + cb(null, comment, xhr); + }); + }; + + // Create a commit comment + // see #createFileComment for options (w/o commit_id) + this.createCommitComment = function(sha, options, cb) { + _request('POST', repoPath + '/commits/' + sha + '/comments', options, function(err, comment, xhr) { + if (err) { + return cb(err); + } + + cb(null, comment, xhr); + }); + }; + // Retrieve the changes made between base and head // ------- - this.compare = function (base, head, cb) { + this.compare = function(base, head, cb) { _request('GET', repoPath + '/compare/' + base + '...' + head, null, cb); }; // List all branches of a repository // ------- - this.listBranches = function (cb) { - _request('GET', repoPath + '/git/refs/heads', null, function (err, heads, xhr) { + this.listBranches = function(cb) { + _request('GET', repoPath + '/git/refs/heads', null, function(err, heads, xhr) { if (err) { return cb(err); } - heads = heads.map(function (head) { + heads = heads.map(function(head) { return head.ref.replace(/^refs\/heads\//, ''); }); @@ -485,27 +549,27 @@ // Retrieve the contents of a blob // ------- - this.getBlob = function (sha, cb) { + 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) { + this.getCommit = function(branch, sha, cb) { _request('GET', repoPath + '/git/commits/' + sha, null, cb); }; // For a given file path, get the corresponding sha (blob for files, tree for dirs) // ------- - this.getSha = function (branch, path, cb) { + 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) { + null, function(err, pathContent, xhr) { if (err) { return cb(err); } @@ -517,15 +581,15 @@ // Get the statuses for a particular SHA // ------- - this.getStatuses = function (sha, cb) { + this.getStatuses = function(sha, cb) { _request('GET', repoPath + '/statuses/' + sha, null, cb); }; // Retrieve the tree a commit points to // ------- - this.getTree = function (tree, cb) { - _request('GET', repoPath + '/git/trees/' + tree, null, function (err, res, xhr) { + this.getTree = function(tree, cb) { + _request('GET', repoPath + '/git/trees/' + tree, null, function(err, res, xhr) { if (err) { return cb(err); } @@ -537,7 +601,7 @@ // Post a new blob object, getting a blob SHA back // ------- - this.postBlob = function (content, cb) { + this.postBlob = function(content, cb) { if (typeof content === 'string') { content = { content: content, @@ -550,7 +614,7 @@ }; } - _request('POST', repoPath + '/git/blobs', content, function (err, res, xhr) { + _request('POST', repoPath + '/git/blobs', content, function(err, res, xhr) { if (err) { return cb(err); } @@ -562,7 +626,7 @@ // Update an existing tree adding a new blob object getting a tree SHA back // ------- - this.updateTree = function (baseTree, path, blob, cb) { + this.updateTree = function(baseTree, path, blob, cb) { var data = { base_tree: baseTree, tree: [ @@ -575,7 +639,7 @@ ] }; - _request('POST', repoPath + '/git/trees', data, function (err, res, xhr) { + _request('POST', repoPath + '/git/trees', data, function(err, res, xhr) { if (err) { return cb(err); } @@ -588,10 +652,10 @@ // with a new blob SHA getting a tree SHA back // ------- - this.postTree = function (tree, cb) { + this.postTree = function(tree, cb) { _request('POST', repoPath + '/git/trees', { tree: tree - }, function (err, res, xhr) { + }, function(err, res, xhr) { if (err) { return cb(err); } @@ -604,10 +668,10 @@ // and the new tree SHA, getting a commit SHA back // ------- - this.commit = function (parent, tree, message, cb) { + this.commit = function(parent, tree, message, cb) { var user = new Github.User(); - user.show(null, function (err, userData) { + user.show(null, function(err, userData) { if (err) { return cb(err); } @@ -624,7 +688,7 @@ tree: tree }; - _request('POST', repoPath + '/git/commits', data, function (err, res, xhr) { + _request('POST', repoPath + '/git/commits', data, function(err, res, xhr) { if (err) { return cb(err); } @@ -639,7 +703,7 @@ // Update the reference of your head to point to the new commit SHA // ------- - this.updateHead = function (head, commit, cb) { + this.updateHead = function(head, commit, cb) { _request('PATCH', repoPath + '/git/refs/heads/' + head, { sha: commit }, cb); @@ -648,25 +712,25 @@ // Show repository information // ------- - this.show = function (cb) { + this.show = function(cb) { _request('GET', repoPath, null, cb); }; // Show repository contributors // ------- - this.contributors = function (cb, retry) { + this.contributors = function(cb, retry) { retry = retry || 1000; var that = this; - _request('GET', repoPath + '/stats/contributors', null, function (err, data, xhr) { + _request('GET', repoPath + '/stats/contributors', null, function(err, data, xhr) { if (err) { return cb(err); } if (xhr.status === 202) { setTimeout( - function () { + function() { that.contributors(cb, retry); }, retry @@ -680,7 +744,7 @@ // Get contents // -------- - this.contents = function (ref, path, cb) { + this.contents = function(ref, path, cb) { path = encodeURI(path); _request('GET', repoPath + '/contents' + (path ? '/' + path : ''), { ref: ref @@ -690,28 +754,28 @@ // Fork repository // ------- - this.fork = function (cb) { + this.fork = function(cb) { _request('POST', repoPath + '/forks', null, cb); }; // List forks // -------- - this.listForks = function (cb) { + this.listForks = function(cb) { _request('GET', repoPath + '/forks', null, cb); }; // Branch repository // -------- - this.branch = function (oldBranch, newBranch, cb) { + 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) { + this.getRef('heads/' + oldBranch, function(err, ref) { if (err && cb) { return cb(err); } @@ -726,49 +790,49 @@ // Create pull request // -------- - this.createPullRequest = function (options, cb) { + this.createPullRequest = function(options, cb) { _request('POST', repoPath + '/pulls', options, cb); }; // List hooks // -------- - this.listHooks = function (cb) { + this.listHooks = function(cb) { _request('GET', repoPath + '/hooks', null, cb); }; // Get a hook // -------- - this.getHook = function (id, cb) { + this.getHook = function(id, cb) { _request('GET', repoPath + '/hooks/' + id, null, cb); }; // Create a hook // -------- - this.createHook = function (options, cb) { + this.createHook = function(options, cb) { _request('POST', repoPath + '/hooks', options, cb); }; // Edit a hook // -------- - this.editHook = function (id, options, cb) { + this.editHook = function(id, options, cb) { _request('PATCH', repoPath + '/hooks/' + id, options, cb); }; // Delete a hook // -------- - this.deleteHook = function (id, cb) { + this.deleteHook = function(id, cb) { _request('DELETE', repoPath + '/hooks/' + id, null, cb); }; // Read file at given path // ------- - this.read = function (branch, path, cb) { + this.read = function(branch, path, cb) { _request('GET', repoPath + '/contents/' + encodeURI(path) + (branch ? '?ref=' + branch : ''), null, cb, true); }; @@ -776,8 +840,8 @@ // Remove a file // ------- - this.remove = function (branch, path, cb) { - that.getSha(branch, path, function (err, sha) { + this.remove = function(branch, path, cb) { + that.getSha(branch, path, function(err, sha) { if (err) { return cb(err); } @@ -797,11 +861,11 @@ // 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) { + 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) { + tree.forEach(function(ref) { if (ref.path === path) { ref.path = newPath; } @@ -811,8 +875,8 @@ } }); - that.postTree(tree, function (err, rootTree) { - that.commit(latestCommit, rootTree, 'Deleted ' + path, function (err, commit) { + that.postTree(tree, function(err, rootTree) { + that.commit(latestCommit, rootTree, 'Deleted ' + path, function(err, commit) { that.updateHead(branch, commit, cb); }); }); @@ -823,13 +887,13 @@ // Write file contents to a given branch and path // ------- - this.write = function (branch, path, content, message, options, cb) { + this.write = function(branch, path, content, message, options, cb) { if (typeof options === 'function') { cb = options; options = {}; } - that.getSha(branch, encodeURI(path), function (err, sha) { + that.getSha(branch, encodeURI(path), function(err, sha) { var writeOptions = { message: message, content: typeof options.encode === 'undefined' || options.encode ? b64encode(content) : content, @@ -855,7 +919,7 @@ // until: ISO 8601 date - only commits before this date will be returned // ------- - this.getCommits = function (options, cb) { + this.getCommits = function(options, cb) { options = options || {}; var url = repoPath + '/commits'; var params = []; @@ -960,72 +1024,72 @@ // Gists API // ======= - Github.Gist = function (options) { + Github.Gist = function(options) { var id = options.id; var gistPath = '/gists/' + id; // Read the gist // -------- - this.read = function (cb) { + this.read = function(cb) { _request('GET', gistPath, null, cb); }; // Create the gist // -------- // { - // "description": "the description for this gist", - // "public": true, - // "files": { - // "file1.txt": { - // "content": "String file contents" + // 'description': 'the description for this gist', + // 'public': true, + // 'files': { + // 'file1.txt': { + // 'content': 'String file contents' // } // } // } - this.create = function (options, cb) { + this.create = function(options, cb) { _request('POST', '/gists', options, cb); }; // Delete the gist // -------- - this.delete = function (cb) { + this.delete = function(cb) { _request('DELETE', gistPath, null, cb); }; // Fork a gist // -------- - this.fork = function (cb) { + this.fork = function(cb) { _request('POST', gistPath + '/fork', null, cb); }; // Update a gist with the new stuff // -------- - this.update = function (options, cb) { + this.update = function(options, cb) { _request('PATCH', gistPath, options, cb); }; // Star a gist // -------- - this.star = function (cb) { + this.star = function(cb) { _request('PUT', gistPath + '/star', null, cb); }; // Untar a gist // -------- - this.unstar = function (cb) { + this.unstar = function(cb) { _request('DELETE', gistPath + '/star', null, cb); }; // Check if a gist is starred // -------- - this.isStarred = function (cb) { + this.isStarred = function(cb) { _request('GET', gistPath + '/star', null, cb); }; }; @@ -1033,14 +1097,14 @@ // Issues API // ========== - Github.Issue = function (options) { + Github.Issue = function(options) { var path = '/repos/' + options.user + '/' + options.repo + '/issues'; this.create = function(options, cb) { _request('POST', path, options, cb); }; - this.list = function (options, cb) { + this.list = function(options, cb) { var query = []; for(var key in options) { @@ -1052,17 +1116,17 @@ _requestAllPages(path + '?' + query.join('&'), cb); }; - this.comment = function (issue, comment, cb) { + this.comment = function(issue, comment, cb) { _request('POST', issue.comments_url, { body: comment }, cb); }; - this.edit = function (issue, options, cb) { + this.edit = function(issue, options, cb) { _request('PATCH', path + '/' + issue, options, cb); }; - this.get = function (issue, cb) { + this.get = function(issue, cb) { _request('GET', path + '/' + issue, null, cb); }; }; @@ -1070,23 +1134,23 @@ // Search API // ========== - Github.Search = function (options) { + Github.Search = function(options) { var path = '/search/'; var query = '?q=' + options.query; - this.repositories = function (options, cb) { + this.repositories = function(options, cb) { _request('GET', path + 'repositories' + query, options, cb); }; - this.code = function (options, cb) { + this.code = function(options, cb) { _request('GET', path + 'code' + query, options, cb); }; - this.issues = function (options, cb) { + this.issues = function(options, cb) { _request('GET', path + 'issues' + query, options, cb); }; - this.users = function (options, cb) { + this.users = function(options, cb) { _request('GET', path + 'users' + query, options, cb); }; }; @@ -1106,14 +1170,14 @@ // Top Level API // ------- - Github.getIssues = function (user, repo) { + Github.getIssues = function(user, repo) { return new Github.Issue({ user: user, repo: repo }); }; - Github.getRepo = function (user, repo) { + Github.getRepo = function(user, repo) { if (!repo) { return new Github.Repository({ fullname: user @@ -1126,17 +1190,17 @@ } }; - Github.getUser = function () { + Github.getUser = function() { return new Github.User(); }; - Github.getGist = function (id) { + Github.getGist = function(id) { return new Github.Gist({ id: id }); }; - Github.getSearch = function (query) { + Github.getSearch = function(query) { return new Github.Search({ query: query }); diff --git a/test/test.repo.js b/test/test.repo.js index fe9e73d5..d744e575 100644 --- a/test/test.repo.js +++ b/test/test.repo.js @@ -5,9 +5,14 @@ var testUser = require('./user.json'); var RELEASE_TAG = 'foo'; var RELEASE_NAME = 'My awesome release'; var RELEASE_BODY = 'Foo bar bazzy baz'; +var TEST_FILE_NAME = 'TEST.md'; +var TEST_FILE_CONTENTS = 'THIS IS A TEST'; +var PULL_REQUEST_TITLE = 'Test pull request'; +var PULL_REQUEST_BODY = 'This is a test pull request'; +var COMMENT_TEXT = 'This is a comment'; var STATUS_URL = 'https://api.github.com/repos/michael/github/statuses/20fcff9129005d14cc97b9d59b8a3d37f4fb633b'; -var github, repo, user, imageB64, imageBlob, sha, releaseId; +var github, repo, user, imageB64, imageBlob, sha, releaseId, pullRequestId; if (typeof window === 'undefined') { // We're in NodeJS var fs = require('fs'); @@ -175,8 +180,7 @@ describe('Github.Repository', function() { }); }); - // @TODO repo.branch, repo.pull - + // @TODO repo.branch it('should list repo branches', function(done) { repo.listBranches(function(err, branches, xhr) { should.not.exist(err); @@ -278,12 +282,12 @@ describe('Creating new Github.Repository', function() { }); it('should write to repo', function(done) { - repo.write('master', 'TEST.md', 'THIS IS A TEST', 'Creating test', function(err) { + repo.write('master', TEST_FILE_NAME, TEST_FILE_CONTENTS, 'Creating test', function(err) { should.not.exist(err); - repo.read('master', 'TEST.md', function(err, res) { + repo.read('master', TEST_FILE_NAME, function(err, res) { should.not.exist(err); - res.should.equal('THIS IS A TEST'); + res.should.equal(TEST_FILE_CONTENTS); done(); }); @@ -293,9 +297,9 @@ describe('Creating new Github.Repository', function() { it('should write to repo branch', function(done) { repo.branch('master', 'dev', function(err) { should.not.exist(err); - repo.write('dev', 'TEST.md', 'THIS IS AN UPDATED TEST', 'Updating test', function(err) { + repo.write('dev', TEST_FILE_NAME, 'THIS IS AN UPDATED TEST', 'Updating test', function(err) { should.not.exist(err); - repo.read('dev', 'TEST.md', function(err, res, xhr) { + repo.read('dev', TEST_FILE_NAME, function(err, res, xhr) { should.not.exist(err); xhr.should.be.instanceof(XMLHttpRequest); res.should.equal('THIS IS AN UPDATED TEST'); @@ -308,12 +312,12 @@ describe('Creating new Github.Repository', function() { it('should compare two branches', function(done) { repo.branch('master', 'compare', function() { - repo.write('compare', 'TEST.md', 'THIS IS AN UPDATED TEST', 'Updating test', function() { + repo.write('compare', TEST_FILE_NAME, 'THIS IS AN UPDATED TEST', 'Updating test', function() { repo.compare('master', 'compare', function(err, diff, xhr) { should.not.exist(err); xhr.should.be.instanceof(XMLHttpRequest); diff.should.have.property('total_commits', 1); - diff.should.have.deep.property('files[0].filename', 'TEST.md'); + diff.should.have.deep.property('files[0].filename', TEST_FILE_NAME); done(); }); @@ -321,27 +325,28 @@ describe('Creating new Github.Repository', function() { }); }); - it('should submit a pull request', function(done) { + it('should open a pull request', function(done) { var baseBranch = 'master'; var headBranch = 'pull-request'; - var pullRequestTitle = 'Test pull request'; - var pullRequestBody = 'This is a test pull request'; repo.branch(baseBranch, headBranch, function() { - repo.write(headBranch, 'TEST.md', 'THIS IS AN UPDATED TEST', 'Updating test', function() { + repo.write(headBranch, TEST_FILE_NAME, 'THIS IS AN UPDATED TEST', 'Updating test', function() { repo.createPullRequest( { - title: pullRequestTitle, - body: pullRequestBody, + title: PULL_REQUEST_TITLE, + body: PULL_REQUEST_BODY, base: baseBranch, head: headBranch }, function(err, pullRequest, xhr) { should.not.exist(err); xhr.should.be.instanceof(XMLHttpRequest); - pullRequest.should.have.property('number').above(0); - pullRequest.should.have.property('title', pullRequestTitle); - pullRequest.should.have.property('body', pullRequestBody); + + sha = pullRequest.head.sha; + pullRequestId = pullRequest.number; + pullRequestId.should.be.above(0); + pullRequest.should.have.property('title', PULL_REQUEST_TITLE); + pullRequest.should.have.property('body', PULL_REQUEST_BODY); done(); } @@ -350,6 +355,86 @@ describe('Creating new Github.Repository', function() { }); }); + it('should get a pull request', function(done) { + repo.getPull(pullRequestId, function(err, pullRequest, xhr) { + should.not.exist(err); + xhr.should.be.instanceof(XMLHttpRequest); + + pullRequest.should.have.property('title', PULL_REQUEST_TITLE); + pullRequest.should.have.property('body', PULL_REQUEST_BODY); + + done(); + }); + }); + + it('should get files from a pull request', function(done) { + repo.getPullFiles(pullRequestId, function(err, files, xhr) { + should.not.exist(err); + xhr.should.be.instanceof(XMLHttpRequest); + + files.should.have.length(1); + + done(); + }); + }); + + it('should comment on a file from a pull request', function(done) { + var options = { + commit_id: sha, + body: COMMENT_TEXT, + position: 1, + path: TEST_FILE_NAME + }; + + repo.createFileComment(pullRequestId, options, function(err, comment, xhr) { + should.not.exist(err); + xhr.should.be.instanceof(XMLHttpRequest); + + comment.body.should.equal(COMMENT_TEXT); + + done(); + }); + }); + + it('should comment on a pull request', function(done) { + repo.createIssueComment(pullRequestId, COMMENT_TEXT, function(err, comment, xhr) { + should.not.exist(err); + xhr.should.be.instanceof(XMLHttpRequest); + + comment.body.should.equal(COMMENT_TEXT); + + done(); + }); + }); + + it('should comment on a commit', function(done) { + var options = { + body: COMMENT_TEXT, + position: 1, + path: TEST_FILE_NAME + }; + + repo.createCommitComment(sha, options, function(err, comment, xhr) { + should.not.exist(err); + xhr.should.be.instanceof(XMLHttpRequest); + + comment.should.have.property('body', COMMENT_TEXT); + + done(); + }); + }); + + it('should get comments on a pull request', function(done) { + repo.getPullComments(pullRequestId, function(err, comments, xhr) { + should.not.exist(err); + xhr.should.be.instanceof(XMLHttpRequest); + + comments.should.have.length(1); + + done(); + }); + }); + it('should get ref from repo', function(done) { repo.getRef('heads/master', function(err, res, xhr) { should.not.exist(err); @@ -432,7 +517,7 @@ describe('Creating new Github.Repository', function() { }); it('should delete a file on the repo', function(done) { - repo.write('master', 'REMOVE-TEST.md', 'THIS IS A TEST', 'Remove test', function(err) { + repo.write('master', 'REMOVE-TEST.md', TEST_FILE_CONTENTS, 'Remove test', function(err) { should.not.exist(err); repo.remove('master', 'REMOVE-TEST.md', function(err, res, xhr) { @@ -445,7 +530,7 @@ describe('Creating new Github.Repository', function() { }); it('should use repo.delete as an alias for repo.remove', function(done) { - repo.write('master', 'REMOVE-TEST.md', 'THIS IS A TEST', 'Remove test', function(err) { + repo.write('master', 'REMOVE-TEST.md', TEST_FILE_CONTENTS, 'Remove test', function(err) { should.not.exist(err); repo.delete('master', 'REMOVE-TEST.md', function(err, res, xhr) { @@ -467,7 +552,7 @@ describe('Creating new Github.Repository', function() { } }; - repo.write('dev', 'TEST.md', 'THIS IS A TEST BY AUTHOR AND COMMITTER', 'Updating', options, function(err, res) { + repo.write('dev', TEST_FILE_NAME, '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, xhr) { should.not.exist(err); @@ -483,7 +568,7 @@ describe('Creating new Github.Repository', function() { }); it('should be able to write CJK unicode to repo', function(done) { - repo.write('master', '中文测试.md', 'THIS IS A TEST', 'Creating test', function(err, res, xhr) { + repo.write('master', '中文测试.md', TEST_FILE_CONTENTS, 'Creating test', function(err, res, xhr) { should.not.exist(err); xhr.should.be.instanceof(XMLHttpRequest);