UNPKG

github-url-to-object

Version:

Extract user, repo, and other interesting properties from GitHub URLs

377 lines (306 loc) 11.7 kB
/* globals before, describe, it */ var assert = require('assert') var gh = require('..') describe('github-url-to-object', function () { describe('shorthand', function () { it('supports user/repo style', function () { var obj = gh('user/repo#branch') assert.equal(obj.user, 'user') assert.equal(obj.repo, 'repo') }) it('supports user/repo#branch style', function () { var obj = gh('user/repo#branch') assert.equal(obj.user, 'user') assert.equal(obj.repo, 'repo') assert.equal(obj.branch, 'branch') }) it('defaults to master branch', function () { var obj = gh('user/repo') assert.equal(obj.user, 'user') assert.equal(obj.repo, 'repo') assert.equal(obj.branch, 'master') }) it('is not vulnerable to REDOS', function () { var prefix = 'a/a' var pump = 'a' var suffix = 'a/' var attackString = prefix for (var i = 0; i < 25000; i++) { attackString += pump } attackString += suffix console.log('matching') var before = process.hrtime() var obj = gh(attackString) var elapsed = process.hrtime(before) // Invalid input so should be rejected... assert.equal(obj, null) // ...but how quickly? assert.equal(elapsed[0], 0) }) }) describe('mediumhand', function () { it('supports github:user/repo style', function () { var obj = gh('github:user/repo#branch') assert.equal(obj.user, 'user') assert.equal(obj.repo, 'repo') }) it('supports github:user/repo#branch style', function () { var obj = gh('github:user/repo#branch') assert.equal(obj.user, 'user') assert.equal(obj.repo, 'repo') assert.equal(obj.branch, 'branch') }) it('defaults to master branch', function () { var obj = gh('github:user/repo') assert.equal(obj.user, 'user') assert.equal(obj.repo, 'repo') assert.equal(obj.branch, 'master') }) it('rejects bitbucket', function () { var obj = gh('bitbucket:user/repo') assert.equal(obj, null) }) it('is not vulnerable to REDOS', function () { var prefix = 'github:a/a' var pump = 'a' var suffix = 'ub.:' var attackString = prefix for (var i = 0; i < 25000; i++) { attackString += pump } attackString += suffix var before = process.hrtime() var obj = gh(attackString) var elapsed = process.hrtime(before) // Invalid input so should be rejected... assert.equal(obj, null) // ...but how quickly? assert.equal(elapsed[0], 0) }) }) describe('oldschool', function () { it('supports git@ URLs', function () { var obj = gh('git@github.com:heroku/heroku-flags.git') assert.equal(obj.user, 'heroku') assert.equal(obj.repo, 'heroku-flags') }) it('defaults to master branch for git@ URLs', function () { var obj = gh('git@github.com:heroku/heroku-flags.git') assert.equal(obj.branch, 'master') }) it('supports git+ssh:// URLs', function () { var obj = gh('git+ssh://git@github.com/foo/bar.git') assert.equal(obj.user, 'foo') assert.equal(obj.repo, 'bar') }) it('supports git+https:// URLs', function () { var obj = gh('git+https://github.com/foo/bar.git') assert.equal(obj.user, 'foo') assert.equal(obj.repo, 'bar') }) it('supports git:// URLs', function () { var obj = gh('git://github.com/foo/bar.git') assert.equal(obj.user, 'foo') assert.equal(obj.repo, 'bar') }) it('defaults to master branch for git:// URLs', function () { var obj = gh('git://github.com/foo/bar.git') assert.equal(obj.branch, 'master') }) describe('github enterprise', function () { it('supports git@ URLs', function () { var obj = gh('git@ghe.example.com:heroku/heroku-flags.git', {enterprise: true}) assert.equal(obj.user, 'heroku') assert.equal(obj.repo, 'heroku-flags') }) it('supports git:// URLs', function () { var obj = gh('git://ghe.example.com/foo/bar.git', {enterprise: true}) assert.equal(obj.user, 'foo') assert.equal(obj.repo, 'bar') }) }) }) describe('repository.url object', function () { it('accepts an object with a `url` property; common in package.json files', function () { var obj = gh({url: 'http://github.com/zeke/outlet.git', type: 'git'}) assert.equal(obj.user, 'zeke') assert.equal(obj.repo, 'outlet') }) }) describe('http', function () { it('supports http URLs', function () { var obj = gh('http://github.com/zeke/outlet.git') assert.equal(obj.user, 'zeke') assert.equal(obj.repo, 'outlet') }) it('supports https URLs', function () { var obj = gh('https://github.com/zeke/outlet.git') assert.equal(obj.user, 'zeke') assert.equal(obj.repo, 'outlet') }) it('supports URLs with www', function () { var obj = gh('https://www.github.com/zeke/outlet') assert.equal(obj.user, 'zeke') assert.equal(obj.repo, 'outlet') }) it('supports deep URLs', function () { var obj = gh('https://github.com/zeke/ruby-rails-sample/blob/b1e1000fedb6ca448dd78702de4fc78dedfee48c/app.json') assert.equal(obj.user, 'zeke') assert.equal(obj.repo, 'ruby-rails-sample') }) it("doesn't require .git extension", function () { var obj = gh('https://github.com/zeke/outlet') assert.equal(obj.user, 'zeke') assert.equal(obj.repo, 'outlet') }) it('defaults to master branch', function () { var obj = gh('https://github.com/zeke/outlet') assert.equal(obj.branch, 'master') }) it('resolves tree-style URLS for branches other than master', function () { var obj = gh('https://github.com/zeke/outlet/tree/other-branch') assert.equal(obj.branch, 'other-branch') }) it('resolves URLS for branches containing /', function () { var obj = gh('https://github.com/zeke/outlet/tree/feature/other-branch') assert.equal(obj.branch, 'feature/other-branch') }) it('resolves URLS for branches containing .', function () { var obj = gh('https://github.com/zeke/outlet/tree/2.1') assert.equal(obj.branch, '2.1') }) it('resolves URLS for branches with single character names', function () { var obj = gh('https://github.com/zeke/outlet/tree/q') assert.strictEqual(obj.branch, 'q') }) it('resolves URLS for branches with single digit names', function () { var obj = gh('https://github.com/zeke/outlet/tree/0') assert.strictEqual(obj.branch, '0') }) it('resolves URLS for branches containing special characters', function () { var obj = gh('https://github.com/zeke/outlet/tree/%3D%40') assert.strictEqual(obj.branch, '%3D%40') }) it('resolves URLS for branches containing special characters following after normal one', function () { var obj = gh('https://github.com/zeke/outlet/tree/v%3D%40') assert.strictEqual(obj.branch, 'v%3D%40') }) it('resolves blob-style URLS for branches other than master', function () { var obj = gh('https://github.com/zeke/ord/blob/new-style/.gitignore') assert.equal(obj.branch, 'new-style') }) it('supports nested packages (lerna-style)', function () { var obj = gh('https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-object-rest-spread/') assert.equal(obj.https_url, 'https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-object-rest-spread') }) describe('github enterprise', function () { it('supports http URLs', function () { var obj = gh('http://ghe.example.com/zeke/outlet.git', {enterprise: true}) assert.equal(obj.user, 'zeke') assert.equal(obj.repo, 'outlet') }) it('supports https URLs', function () { var obj = gh('https://ghe.example.com/zeke/outlet.git', {enterprise: true}) assert.equal(obj.user, 'zeke') assert.equal(obj.repo, 'outlet') }) }) }) describe('properties', function () { var obj describe('github.com', function () { before(function () { obj = gh('zeke/ord') }) it('user', function () { assert.equal(obj.user, 'zeke') }) it('repo', function () { assert.equal(obj.repo, 'ord') }) it('branch', function () { assert.equal(obj.branch, 'master') }) it('tarball_url', function () { assert.equal(obj.tarball_url, 'https://api.github.com/repos/zeke/ord/tarball/master') }) it('api_url', function () { assert.equal(obj.api_url, 'https://api.github.com/repos/zeke/ord') }) it('https_url', function () { assert.equal(obj.https_url, 'https://github.com/zeke/ord') }) it('travis_url', function () { assert.equal(obj.travis_url, 'https://travis-ci.org/zeke/ord') }) it('zip_url', function () { assert.equal(obj.zip_url, 'https://github.com/zeke/ord/archive/master.zip') }) }) describe('github enterprise', function () { before(function () { obj = gh('https://ghe.example.com/zeke/outlet.git', {enterprise: true}) }) it('user', function () { assert.equal(obj.user, 'zeke') }) it('repo', function () { assert.equal(obj.repo, 'outlet') }) it('branch', function () { assert.equal(obj.branch, 'master') }) it('tarball_url', function () { assert.equal(obj.tarball_url, 'https://ghe.example.com/api/v3/repos/zeke/outlet/tarball/master') }) it('api_url', function () { assert.equal(obj.api_url, 'https://ghe.example.com/api/v3/repos/zeke/outlet') }) it('https_url', function () { assert.equal(obj.https_url, 'https://ghe.example.com/zeke/outlet') }) it('zip_url', function () { assert.equal(obj.zip_url, 'https://ghe.example.com/zeke/outlet/archive/master.zip') }) }) }) describe('branch other than master', function () { var obj before(function () { obj = gh('zeke/ord#experiment') }) it('applies to tarball_url', function () { assert.equal(obj.tarball_url, 'https://api.github.com/repos/zeke/ord/tarball/experiment') }) it('applies to https_url', function () { assert.equal(obj.https_url, 'https://github.com/zeke/ord/blob/experiment') }) it('applies to clone_url', function () { assert.equal(obj.clone_url, 'https://github.com/zeke/ord') }) it("doesn't apply to api_url", function () { assert.equal(obj.api_url, 'https://api.github.com/repos/zeke/ord') }) it('applies to travis_url', function () { assert.equal(obj.travis_url, 'https://travis-ci.org/zeke/ord?branch=experiment') }) it('applies to zip_url', function () { assert.equal(obj.zip_url, 'https://github.com/zeke/ord/archive/experiment.zip') }) }) describe('failure', function () { it('returns null if url is falsy', function () { assert.equal(gh(), null) assert.equal(gh(null), null) assert.equal(gh(undefined), null) assert.equal(gh(''), null) assert.equal(gh({url: '', type: 'git'}), null) assert.equal(gh({url: null, type: 'git'}), null) assert.equal(gh({url: undefined, type: 'git'}), null) }) it('returns null if hostname is not github.com', function () { assert.equal(gh('https://ghe.something.com/foo/bar'), null) }) }) })