From 6e0b9ded14b18081bd9b0206b6c3c1c573e8d6b5 Mon Sep 17 00:00:00 2001 From: Matt Smith Date: Sun, 16 Jul 2017 12:02:23 -0600 Subject: [PATCH 1/6] Add ability to add collaborator --- .gitignore | 1 + .npmignore | 1 + lib/Repository.js | 18 ++++++++++++++++-- test/fixtures/alt-user.json | 3 +++ test/repository.spec.js | 17 ++++++++++++++--- test/team.spec.js | 5 +---- 6 files changed, 36 insertions(+), 9 deletions(-) create mode 100644 test/fixtures/alt-user.json diff --git a/.gitignore b/.gitignore index db3cda2f..8917815d 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ node_modules/ .DS_Store npm-debug.log sauce.json +package-lock.json diff --git a/.npmignore b/.npmignore index fe969272..e533e1f5 100644 --- a/.npmignore +++ b/.npmignore @@ -5,3 +5,4 @@ lib/ .nyc_output/ .DS_Store sauce.json +package-lock.json diff --git a/lib/Repository.js b/lib/Repository.js index d338b261..fbd1db7c 100644 --- a/lib/Repository.js +++ b/lib/Repository.js @@ -436,13 +436,27 @@ class Repository extends Requestable { * List the users who are collaborators on the repository. The currently authenticated user must have * push access to use this method * @see https://developer.github.com/v3/repos/collaborators/#list-collaborators - * @param {Requestable.callback} cb - will receive the list of collaborators + * @param {Requestable.callback} cb - will receive the fetched data * @return {Promise} - the promise for the http request */ getCollaborators(cb) { return this._request('GET', `/repos/${this.__fullname}/collaborators`, null, cb); } + /** + * Adds user as a collaborator on the repository. The currently authenticated user must have admin access for the + * repo to use this method + * @see https://developer.github.com/enterprise/2.10/v3/repos/collaborators/#add-user-as-a-collaborator + * @param {string} username - the user to add as a collaborator + * @param {Object} [options] - collaborator permissions, only applicable on repos in an org + * @param {Object} [options.permission=push] - can be one of: `pull`, `push`, or `admin` + * @param {Requestable.callback} cb - will receive the information about the newly added contributor + * @return {Promise} - the promise for the http request + */ + addCollaborator(username, options, cb) { + return this._request('PUT', `/repos/${this.__fullname}/collaborators/${username}`, options, cb); + } + /** * Check if a user is a collaborator on the repository * @see https://developer.github.com/v3/repos/collaborators/#check-if-a-user-is-a-collaborator @@ -451,7 +465,7 @@ class Repository extends Requestable { * @return {Promise} - the promise for the http request {Boolean} [description] */ isCollaborator(username, cb) { - return this._request('GET', `/repos/${this.__fullname}/collaborators/${username}`, null, cb); + return this._request204or404(`/repos/${this.__fullname}/collaborators/${username}`, null, cb); } /** diff --git a/test/fixtures/alt-user.json b/test/fixtures/alt-user.json new file mode 100644 index 00000000..f39cb512 --- /dev/null +++ b/test/fixtures/alt-user.json @@ -0,0 +1,3 @@ +{ + "USERNAME": "mtscout6-test" +} diff --git a/test/repository.spec.js b/test/repository.spec.js index ef5101cf..c31cd0c3 100644 --- a/test/repository.spec.js +++ b/test/repository.spec.js @@ -3,6 +3,7 @@ import expect from 'must'; import Github from '../lib/GitHub'; import wait from './helpers/wait'; import testUser from './fixtures/user.json'; +import altUser from './fixtures/alt-user.json'; import loadImage from './fixtures/imageBlob'; import {assertSuccessful, assertFailure} from './helpers/callbacks'; import getTestRepoName from './helpers/getTestRepoName'; @@ -262,7 +263,7 @@ describe('Repository', function() { }); }); - describe('creating/modifiying', function() { + describe.only('creating/modifiying', function() { const fileName = 'test.md'; const initialText = 'This is a test.'; @@ -343,8 +344,18 @@ describe('Repository', function() { })); }); - it('should test whether user is collaborator', function(done) { - remoteRepo.isCollaborator(testUser.USERNAME, assertSuccessful(done)); + it('should add repo collaborator', async function() { + expect(await remoteRepo.isCollaborator(altUser.USERNAME)).to.be.false; + await remoteRepo.addCollaborator(altUser.USERNAME); + expect(await remoteRepo.isCollaborator(altUser.USERNAME)).to.be.true; + }); + + it('should test whether user is collaborator', async function() { + expect(await remoteRepo.isCollaborator(testUser.USERNAME)).to.be.true; + }); + + it('should test whether user is not collaborator', async function() { + expect(await remoteRepo.isCollaborator(altUser.USERNAME)).to.be.false; }); it('should write to repo', function(done) { diff --git a/test/team.spec.js b/test/team.spec.js index 8a5ec8be..3ec6b686 100644 --- a/test/team.spec.js +++ b/test/team.spec.js @@ -4,10 +4,7 @@ import Github from '../lib/GitHub'; import testUser from './fixtures/user.json'; import {assertFailure} from './helpers/callbacks'; import getTestRepoName from './helpers/getTestRepoName'; - -const altUser = { - USERNAME: 'mtscout6-test', -}; +import altUser from './fixtures/alt-user.json'; function createTestTeam() { const name = getTestRepoName(); From d3a4373fc407b332514ffde074743354991bf4ad Mon Sep 17 00:00:00 2001 From: Matt Smith Date: Sun, 16 Jul 2017 16:59:15 -0600 Subject: [PATCH 2/6] Fix ESLint to work with async/await --- .eslintrc.yaml | 2 +- package.json | 11 ++++++++++- test/repository.spec.js | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 2718e64e..3eb49f5a 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -2,6 +2,7 @@ extends: - eslint:recommended - google + parser: babel-eslint parserOptions: ecmaVersion: 6 sourceType: module @@ -25,7 +26,6 @@ MethodDefinition: true spaced-comment: error valid-jsdoc: [error, {requireParamDescription: true}] - env: es6: true node: true diff --git a/package.json b/package.json index 2ea2eb9a..f60bf60a 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,14 @@ }, "babel": { "presets": [ - "es2015" + [ + "env", + { + "targets": { + "node": 6 + } + } + ] ], "plugins": [ [ @@ -59,9 +66,11 @@ }, "devDependencies": { "babel-core": "^6.7.7", + "babel-eslint": "^7.2.3", "babel-plugin-add-module-exports": "^0.2.1", "babel-plugin-istanbul": "3.0.0", "babel-plugin-transform-es2015-modules-umd": "^6.5.0", + "babel-preset-env": "^1.6.0", "babel-preset-es2015": "^6.5.0", "babel-register": "^6.7.2", "babelify": "^7.3.0", diff --git a/test/repository.spec.js b/test/repository.spec.js index c31cd0c3..739978e0 100644 --- a/test/repository.spec.js +++ b/test/repository.spec.js @@ -263,7 +263,7 @@ describe('Repository', function() { }); }); - describe.only('creating/modifiying', function() { + describe('creating/modifiying', function() { const fileName = 'test.md'; const initialText = 'This is a test.'; From 03914f2e1486afec2f2fa9111a969f06c33f5a92 Mon Sep 17 00:00:00 2001 From: Matt Smith Date: Sun, 16 Jul 2017 17:00:44 -0600 Subject: [PATCH 3/6] Update supported Node Versions --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 26f56aa3..817aa70f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,8 @@ sudo: false language: node_js node_js: + - '8' - '6' - - '5' - - '4' cache: directories: From 4fca61d86effb9e626b9aba5a2ea7a330a01de9b Mon Sep 17 00:00:00 2001 From: Matt Smith Date: Sun, 16 Jul 2017 17:39:05 -0600 Subject: [PATCH 4/6] Cleanup page requests to use async / await --- lib/Requestable.js | 35 +++++++++++++++++++---------------- test/organization.spec.js | 15 +++++++-------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/lib/Requestable.js b/lib/Requestable.js index bad111ac..09c0e47a 100644 --- a/lib/Requestable.js +++ b/lib/Requestable.js @@ -235,15 +235,18 @@ class Requestable { * @param {string} path - the path to request * @param {Object} options - the query parameters to include * @param {Requestable.callback} [cb] - the function to receive the data. The returned data will always be an array. - * @param {Object[]} results - the partial results. This argument is intended for interal use only. * @return {Promise} - a promise which will resolve when all pages have been fetched * @deprecated This will be folded into {@link Requestable#_request} in the 2.0 release. */ - _requestAllPages(path, options, cb, results) { - results = results || []; + async _requestAllPages(path, options, cb) { + let currentPath = path; + let results = []; + let response; + + try { + do { + response = await this._request('GET', currentPath, options); - return this._request('GET', path, options) - .then((response) => { let thisGroup; if (response.data instanceof Array) { thisGroup = response.data; @@ -255,19 +258,18 @@ class Requestable { } results.push(...thisGroup); - const nextUrl = getNextPage(response.headers.link); - if (nextUrl && typeof options.page !== 'number') { - log(`getting next page: ${nextUrl}`); - return this._requestAllPages(nextUrl, options, cb, results); - } + currentPath = getNextPage(response.headers.link); + } while(currentPath); - if (cb) { - cb(null, results, response); - } + if (cb) { + cb(null, results, response); + } - response.data = results; - return response; - }).catch(callbackErrorOrThrow(cb, path)); + response.data = results; + return response; + } catch (err) { + callbackErrorOrThrow(cb, path)(err); + } } } @@ -283,6 +285,7 @@ function methodHasNoBody(method) { function getNextPage(linksHeader = '') { const links = linksHeader.split(/\s*,\s*/); // splits and strips the urls + // TODO: Change this to early abort once it finds the link in question return links.reduce(function(nextUrl, link) { if (link.search(/rel="next"/) !== -1) { return (link.match(/<(.*)>/) || [])[1]; diff --git a/test/organization.spec.js b/test/organization.spec.js index 26fd3607..01363e3d 100644 --- a/test/organization.spec.js +++ b/test/organization.spec.js @@ -21,7 +21,9 @@ describe('Organization', function() { }); after(function() { - return github.getProject(createdProject.id).deleteProject(); + if (createdProject) { + return github.getProject(createdProject.id).deleteProject(); + } }); describe('reading', function() { @@ -95,13 +97,10 @@ describe('Organization', function() { })); }); - it('should list the teams in the organization', function() { - return organization.getTeams() - .then(({data}) => { - const hasTeam = data.some((member) => member.slug === testRepoName); - - expect(hasTeam).to.be.true(); - }); + it('should list the teams in the organization', async function() { + const {data} = await organization.getTeams(); + const hasTeam = data.some((member) => member.slug === testRepoName); + expect(hasTeam).to.be.true(); }); it('should create a project', function(done) { From 699d092e3240f0da78f37e2739bbef1111ee1d2e Mon Sep 17 00:00:00 2001 From: Matt Smith Date: Sun, 16 Jul 2017 17:39:29 -0600 Subject: [PATCH 5/6] Convert rateLimit test to async / await --- test/rate-limit.spec.js | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/test/rate-limit.spec.js b/test/rate-limit.spec.js index c3a5b858..40219fea 100644 --- a/test/rate-limit.spec.js +++ b/test/rate-limit.spec.js @@ -2,7 +2,6 @@ import expect from 'must'; import Github from '../lib/GitHub'; import testUser from './fixtures/user.json'; -import {assertSuccessful} from './helpers/callbacks'; describe('RateLimit', function() { let github; @@ -18,18 +17,15 @@ describe('RateLimit', function() { rateLimit = github.getRateLimit(); }); - it('should get rate limit', function(done) { - rateLimit.getRateLimit(assertSuccessful(done, function(err, rateInfo) { - const rate = rateInfo.rate; + it('should get rate limit', async function() { + const {data: rateInfo} = await rateLimit.getRateLimit(); + const rate = rateInfo.rate; - expect(rate).to.be.an.object(); - expect(rate).to.have.own('limit'); - expect(rate).to.have.own('remaining'); - expect(rate.limit).to.be.a.number(); - expect(rate.remaining).to.be.a.number(); - expect(rate.remaining).to.be.at.most(rateInfo.rate.limit); - - done(); - })); + expect(rate).to.be.an.object(); + expect(rate).to.have.own('limit'); + expect(rate).to.have.own('remaining'); + expect(rate.limit).to.be.a.number(); + expect(rate.remaining).to.be.a.number(); + expect(rate.remaining).to.be.at.most(rateInfo.rate.limit); }); }); From c5c30603b5eb2ae6e770358f7d9d2c1032d2ceff Mon Sep 17 00:00:00 2001 From: Matt Smith Date: Sun, 16 Jul 2017 21:19:23 -0600 Subject: [PATCH 6/6] Fix failing test --- lib/Team.js | 4 ++-- test/team.spec.js | 26 +++++++++++++++----------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/lib/Team.js b/lib/Team.js index f91c9173..67545ae6 100644 --- a/lib/Team.js +++ b/lib/Team.js @@ -90,8 +90,8 @@ class Team extends Requestable { /** * Add a member to the Team - * @see https://developer.github.com/v3/orgs/teams/#add-team-membership - * @param {string} username - can be one of: `all`, `maintainer`, or `member` + * @see https://developer.github.com/v3/orgs/teams/#add-or-update-team-membership + * @param {string} username - user to add or update membership for * @param {object} options - Parameters for adding a team member * @param {string} [options.role=member] - The role that this user should have in the team. Can be one * of: `member`, or `maintainer` diff --git a/test/team.spec.js b/test/team.spec.js index 3ec6b686..671418d5 100644 --- a/test/team.spec.js +++ b/test/team.spec.js @@ -1,8 +1,8 @@ +import assert from 'assert'; import expect from 'must'; import Github from '../lib/GitHub'; import testUser from './fixtures/user.json'; -import {assertFailure} from './helpers/callbacks'; import getTestRepoName from './helpers/getTestRepoName'; import altUser from './fixtures/alt-user.json'; @@ -142,9 +142,15 @@ describe('Team', function() { // Isolate tests that need a new team per test }); // Test for Team deletion - afterEach(function(done) { - team.deleteTeam() - .then(() => team.getTeam(assertFailure(done))); + afterEach(async function() { + await team.deleteTeam(); + + try { + await team.getTeam(); + assert.fail(undefined, undefined, 'Failed to delete the team'); + } catch (error) { + // Swallow intentionally + } }); it('should update team', function() { @@ -155,13 +161,11 @@ describe('Team', function() { // Isolate tests that need a new team per test }); }); - it('should add membership for a given user', function() { - return team.addMembership(testUser.USERNAME) - .then(({data}) => { - const {state, role} = data; - expect(state === 'active' || state === 'pending').to.be.true(); - expect(role).to.equal('member'); - }); + it('should add membership for a given user', async function() { + const {data: {state, role}} = await team.addMembership(testUser.USERNAME); + expect(state === 'active' || state === 'pending').to.be.true(); + // TODO: This does not appear to match the documentation... + expect(role).to.equal('maintainer'); }); it('should add membership as a maintainer for a given user', function() { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy