'use strict' const { expect } = require('chai') const Camp = require('camp') const got = require('got') const sinon = require('sinon') const portfinder = require('portfinder') const queryString = require('query-string') const nock = require('nock') const serverSecrets = require('../../../lib/server-secrets') const acceptor = require('./acceptor') const fakeClientId = 'githubdabomb' const fakeShieldsSecret = 'letmeinplz' describe('Github token acceptor', function() { before(function() { // Make sure properties exist. // https://github.com/sinonjs/sinon/pull/1557 serverSecrets.gh_client_id = undefined serverSecrets.shields_ips = undefined serverSecrets.shields_secret = undefined sinon.stub(serverSecrets, 'gh_client_id').value(fakeClientId) sinon.stub(serverSecrets, 'shields_ips').value([]) sinon.stub(serverSecrets, 'shields_secret').value(fakeShieldsSecret) }) after(function() { sinon.restore() }) let port, baseUrl beforeEach(async function() { port = await portfinder.getPortPromise() baseUrl = `http://127.0.0.1:${port}` }) let camp beforeEach(async function() { camp = Camp.start({ port, hostname: '::' }) await new Promise(resolve => camp.on('listening', () => resolve())) }) afterEach(async function() { if (camp) { await new Promise(resolve => camp.close(resolve)) camp = undefined } }) let onTokenAccepted beforeEach(function() { onTokenAccepted = sinon.stub() acceptor.setRoutes({ server: camp, onTokenAccepted, }) }) it('should start the OAuth process', async function() { const res = await got(`${baseUrl}/github-auth`, { followRedirect: false }) expect(res.statusCode).to.equal(302) const qs = queryString.stringify({ client_id: fakeClientId, redirect_uri: 'https://img.shields.io/github-auth/done', }) const expectedLocationHeader = `https://github.com/login/oauth/authorize?${qs}` expect(res.headers.location).to.equal(expectedLocationHeader) }) describe('Finishing the OAuth process', function() { context('no code is provided', function() { it('should return an error', async function() { const res = await got(`${baseUrl}/github-auth/done`) expect(res.body).to.equal( 'GitHub OAuth authentication failed to provide a code.' ) }) }) const fakeCode = '123456789' const fakeAccessToken = 'abcdef' context('a code is provided', function() { let scope beforeEach(function() { nock.enableNetConnect(/127\.0\.0\.1/) scope = nock('https://github.com') .post('/login/oauth/access_token') .reply((url, requestBody) => { expect(queryString.parse(requestBody).code).to.equal(fakeCode) return queryString.stringify({ access_token: fakeAccessToken }) }) }) afterEach(function() { if (scope) { scope.done() scope = null } }) afterEach(function() { nock.enableNetConnect() nock.cleanAll() }) it('should finish the OAuth process', async function() { const res = await got(`${baseUrl}/github-auth/done`, { form: true, body: { code: fakeCode }, }) expect(res.body).to.startWith( '
Shields.io has received your app-specific GitHub user token.' ) }) }) }) it('should add a received token', async function() { const fakeAccessToken = 'its-my-token' const { body } = await got(`${baseUrl}/github-auth/add-token`, { form: true, body: { shieldsSecret: fakeShieldsSecret, token: fakeAccessToken }, }) expect(onTokenAccepted).to.have.been.calledWith(fakeAccessToken) expect(body).to.equal('Thanks!') }) })