fix: support contributors without github accounts (#77)

This commit is contained in:
Chris Vickery 2017-12-14 01:34:06 +09:00 committed by Kent C. Dodds
parent 6fa55d5bd5
commit 5f9fa20346
8 changed files with 80 additions and 20 deletions

View file

@ -26,6 +26,12 @@ function fixtures() {
profile: 'www.profile.url', profile: 'www.profile.url',
contributions: [{type: 'blog', url: 'www.blog.url/path'}, 'code'], contributions: [{type: 'blog', url: 'www.blog.url/path'}, 'code'],
}, },
{
name: 'Missing Login',
avatar_url: 'www.avatar.url',
profile: 'www.profile.url',
contributions: ['code'],
},
], ],
} }
return {options} return {options}
@ -71,8 +77,8 @@ test('add new contributor at the end of the list of contributors', () => {
return addContributor(options, username, contributions, mockInfoFetcher).then( return addContributor(options, username, contributions, mockInfoFetcher).then(
contributors => { contributors => {
expect(contributors.length).toBe(3) expect(contributors.length).toBe(options.contributors.length + 1)
expect(contributors[2]).toEqual({ expect(contributors[options.contributors.length]).toEqual({
login: 'login3', login: 'login3',
name: 'Some name', name: 'Some name',
avatar_url: 'www.avatar.url', avatar_url: 'www.avatar.url',
@ -91,8 +97,8 @@ test('add new contributor at the end of the list of contributors with a url link
return addContributor(options, username, contributions, mockInfoFetcher).then( return addContributor(options, username, contributions, mockInfoFetcher).then(
contributors => { contributors => {
expect(contributors.length).toBe(3) expect(contributors.length).toBe(options.contributors.length + 1)
expect(contributors[2]).toEqual({ expect(contributors[options.contributors.length]).toEqual({
login: 'login3', login: 'login3',
name: 'Some name', name: 'Some name',
avatar_url: 'www.avatar.url', avatar_url: 'www.avatar.url',
@ -133,7 +139,7 @@ test(`should update an existing contributor's contributions if a new type is add
const contributions = ['bug'] const contributions = ['bug']
return addContributor(options, username, contributions, mockInfoFetcher).then( return addContributor(options, username, contributions, mockInfoFetcher).then(
contributors => { contributors => {
expect(contributors.length).toBe(2) expect(contributors.length).toBe(options.contributors.length)
expect(contributors[0]).toEqual({ expect(contributors[0]).toEqual({
login: 'login1', login: 'login1',
name: 'Some name', name: 'Some name',
@ -171,7 +177,7 @@ test(`should update an existing contributor's contributions if a new type is add
return addContributor(options, username, contributions, mockInfoFetcher).then( return addContributor(options, username, contributions, mockInfoFetcher).then(
contributors => { contributors => {
expect(contributors.length).toBe(2) expect(contributors.length).toBe(options.contributors.length)
expect(contributors[0]).toEqual({ expect(contributors[0]).toEqual({
login: 'login1', login: 'login1',
name: 'Some name', name: 'Some name',

View file

@ -27,7 +27,10 @@ function updateContributor(options, contributor, contributions) {
function updateExistingContributor(options, username, contributions) { function updateExistingContributor(options, username, contributions) {
return options.contributors.map(contributor => { return options.contributors.map(contributor => {
if (username.toLowerCase() !== contributor.login.toLowerCase()) { if (
!contributor.login ||
username.toLowerCase() !== contributor.login.toLowerCase()
) {
return contributor return contributor
} }
return updateContributor(options, contributor, contributions) return updateContributor(options, contributor, contributions)
@ -51,7 +54,10 @@ module.exports = function addContributor(
) { ) {
// case insensitive find // case insensitive find
const exists = _.find(contributor => { const exists = _.find(contributor => {
return contributor.login.toLowerCase() === username.toLowerCase() return (
contributor.login &&
contributor.login.toLowerCase() === username.toLowerCase()
)
}, options.contributors) }, options.contributors)
if (exists) { if (exists) {

View file

@ -35,6 +35,7 @@ function getQuestions(options, username, contributions) {
return options.contributors return options.contributors
.filter( .filter(
entry => entry =>
entry.login &&
entry.login.toLowerCase() === answers.username.toLowerCase(), entry.login.toLowerCase() === answers.username.toLowerCase(),
) )
.reduce( .reduce(
@ -48,6 +49,7 @@ function getQuestions(options, username, contributions) {
const previousContributions = options.contributors const previousContributions = options.contributors
.filter( .filter(
entry => entry =>
entry.login &&
entry.login.toLowerCase() === answers.username.toLowerCase(), entry.login.toLowerCase() === answers.username.toLowerCase(),
) )
.reduce( .reduce(

View file

@ -19,5 +19,15 @@
"profile": "http://github.com/chrisinajar", "profile": "http://github.com/chrisinajar",
"avatar_url": "https://avatars1.githubusercontent.com/u/1500684", "avatar_url": "https://avatars1.githubusercontent.com/u/1500684",
"contributions": ["doc"] "contributions": ["doc"]
},
"nologin": {
"name": "No Github Account",
"avatar_url": "https://avatars1.githubusercontent.com/u/1500684",
"contributions": ["translation"]
},
"nologin_badrole": {
"name": "Wildly Misconfigured",
"avatar_url": "https://avatars1.githubusercontent.com/u/1500684",
"contributions": ["plumbis"]
} }
} }

View file

@ -153,3 +153,13 @@ test('throw a helpful error on unknown type', () => {
formatContributionType(options, contributor, 'docs'), formatContributionType(options, contributor, 'docs'),
).toThrowError('Unknown contribution type docs for contributor kentcdodds') ).toThrowError('Unknown contribution type docs for contributor kentcdodds')
}) })
test('throw a helpful error on unknown type and no login', () => {
const contributor = contributors.nologin_badrole
const {options} = fixtures()
expect(() =>
formatContributionType(options, contributor, 'docs'),
).toThrowError(
'Unknown contribution type docs for contributor Wildly Misconfigured',
)
})

View file

@ -65,3 +65,13 @@ test('format contributor with pipes in their name', () => {
expect(formatContributor(options, contributor)).toBe(expected) expect(formatContributor(options, contributor)).toBe(expected)
}) })
test('format contributor with no github account', () => {
const contributor = contributors.nologin
const {options} = fixtures()
const expected =
'<img src="https://avatars1.githubusercontent.com/u/1500684" width="150px;"/><br /><sub><b>No Github Account</b></sub><br />[🌍](#translation "Translation")'
expect(formatContributor(options, contributor)).toBe(expected)
})

View file

@ -19,9 +19,8 @@ module.exports = function formatContribution(
if (!type) { if (!type) {
throw new Error( throw new Error(
`Unknown contribution type ${contribution} for contributor ${ `Unknown contribution type ${contribution} for contributor ${contributor.login ||
contributor.login contributor.name}`,
}`,
) )
} }
@ -32,7 +31,8 @@ module.exports = function formatContribution(
options, options,
} }
let url = `#${contribution}-${contributor.login}` let url = getUrl(contribution, contributor)
if (contribution.url) { if (contribution.url) {
url = contribution.url url = contribution.url
} else if (type.link) { } else if (type.link) {
@ -41,3 +41,11 @@ module.exports = function formatContribution(
return linkTemplate(_.assign({url}, templateData)) return linkTemplate(_.assign({url}, templateData))
} }
function getUrl(contribution, contributor) {
if (contributor.login) {
return `#${contribution}-${contributor.login}`
} else {
return `#${contribution}`
}
}

View file

@ -7,6 +7,9 @@ const avatarTemplate = _.template(
const avatarBlockTemplate = _.template( const avatarBlockTemplate = _.template(
'[<%= avatar %><br /><sub><b><%= name %></b></sub>](<%= contributor.profile %>)', '[<%= avatar %><br /><sub><b><%= name %></b></sub>](<%= contributor.profile %>)',
) )
const avatarBlockTemplateNoProfile = _.template(
'<%= avatar %><br /><sub><b><%= name %></b></sub>',
)
const contributorTemplate = _.template( const contributorTemplate = _.template(
'<%= avatarBlock %><br /><%= contributions %>', '<%= avatarBlock %><br /><%= contributions %>',
) )
@ -15,15 +18,20 @@ const defaultImageSize = 100
function defaultTemplate(templateData) { function defaultTemplate(templateData) {
const avatar = avatarTemplate(templateData) const avatar = avatarTemplate(templateData)
const avatarBlock = avatarBlockTemplate( const avatarBlockTemplateData = _.assign(
_.assign( {
{ name: escapeName(templateData.contributor.name),
name: escapeName(templateData.contributor.name), avatar,
avatar, },
}, templateData,
templateData,
),
) )
let avatarBlock = null
if (templateData.contributor.profile) {
avatarBlock = avatarBlockTemplate(avatarBlockTemplateData)
} else {
avatarBlock = avatarBlockTemplateNoProfile(avatarBlockTemplateData)
}
return contributorTemplate(_.assign({avatarBlock}, templateData)) return contributorTemplate(_.assign({avatarBlock}, templateData))
} }