Refactor [Coveralls] (#3130)
* refactor(coveralls) * chore: added comment with link to api * doc: updated coveralls api doc comment * doc: updated coveralls api doc comment
This commit is contained in:
committed by
Pierre-Yves B
parent
f0eac60191
commit
cad3ea434f
@@ -1,54 +1,63 @@
|
||||
'use strict'
|
||||
|
||||
const LegacyService = require('../legacy-service')
|
||||
const { makeBadgeData: getBadgeData } = require('../../lib/badge-data')
|
||||
const {
|
||||
coveragePercentage: coveragePercentageColor,
|
||||
} = require('../color-formatters')
|
||||
const Joi = require('joi')
|
||||
const { BaseJsonService } = require('..')
|
||||
const { coveragePercentage } = require('../color-formatters')
|
||||
|
||||
// This legacy service should be rewritten to use e.g. BaseJsonService.
|
||||
//
|
||||
// Tips for rewriting:
|
||||
// https://github.com/badges/shields/blob/master/doc/rewriting-services.md
|
||||
//
|
||||
// Do not base new services on this code.
|
||||
module.exports = class Coveralls extends LegacyService {
|
||||
const schema = Joi.object({
|
||||
covered_percent: Joi.number()
|
||||
.min(0)
|
||||
.max(100)
|
||||
.required(),
|
||||
}).required()
|
||||
|
||||
module.exports = class Coveralls extends BaseJsonService {
|
||||
static get category() {
|
||||
return 'coverage'
|
||||
}
|
||||
|
||||
static get defaultBadgeData() {
|
||||
return { label: 'coverage' }
|
||||
}
|
||||
|
||||
static render({ coverage }) {
|
||||
return {
|
||||
message: `${coverage.toFixed(0)}%`,
|
||||
color: coveragePercentage(coverage),
|
||||
}
|
||||
}
|
||||
|
||||
static get route() {
|
||||
return {
|
||||
base: 'coveralls',
|
||||
pattern: '',
|
||||
pattern: ':vcsType(github|bitbucket)?/:user/:repo/:branch*',
|
||||
}
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
const { staticPreview } = this
|
||||
return [
|
||||
{
|
||||
title: 'Coveralls github',
|
||||
pattern: ':vcsType/:user/:repo',
|
||||
namedParams: { vcsType: 'github', user: 'jekyll', repo: 'jekyll' },
|
||||
staticPreview,
|
||||
staticPreview: this.render({ coverage: 86 }),
|
||||
},
|
||||
{
|
||||
title: 'Coveralls github branch',
|
||||
pattern: ':vcsType/:user/:repo/:branch',
|
||||
namedParams: {
|
||||
vcsType: 'github',
|
||||
user: 'jekyll',
|
||||
repo: 'jekyll',
|
||||
user: 'lemurheavy',
|
||||
repo: 'coveralls-ruby',
|
||||
branch: 'master',
|
||||
},
|
||||
staticPreview,
|
||||
staticPreview: this.render({ coverage: 91.81 }),
|
||||
},
|
||||
{
|
||||
title: 'Coveralls bitbucket',
|
||||
pattern: ':vcsType/:user/:repo',
|
||||
namedParams: { vcsType: 'bitbucket', user: 'pyKLIP', repo: 'pyklip' },
|
||||
staticPreview,
|
||||
staticPreview: this.render({ coverage: 86 }),
|
||||
},
|
||||
{
|
||||
title: 'Coveralls bitbucket branch',
|
||||
@@ -59,68 +68,39 @@ module.exports = class Coveralls extends LegacyService {
|
||||
repo: 'pyklip',
|
||||
branch: 'master',
|
||||
},
|
||||
staticPreview,
|
||||
staticPreview: this.render({ coverage: 96 }),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static get staticPreview() {
|
||||
return { message: '83%', color: 'yellowgreen' }
|
||||
}
|
||||
|
||||
static get defaultBadgeData() {
|
||||
return {
|
||||
label: 'coverage',
|
||||
async fetch({ vcsType, user, repo, branch }) {
|
||||
// https://docs.coveralls.io/api-introduction#getting-data-from-coveralls
|
||||
const url = `https://coveralls.io/${vcsType ||
|
||||
'github'}/${user}/${repo}.json`
|
||||
const options = {
|
||||
qs: {
|
||||
// The API returns the latest result (across any branch) if no branch is explicitly specified,
|
||||
// whereas the Coveralls native badge (and the Shields.io badges for Coveralls) show
|
||||
// the coverage for the default branch if no branch is explicitly specified. If the user
|
||||
// doesn't specify their desired badge, then we can get the Coverage for the latest branch
|
||||
// from the API by specifying an invalid branch name in which case the API returns the coverage
|
||||
// for the default branch. This ensures we show the same percentage value.
|
||||
branch: branch || '@',
|
||||
},
|
||||
}
|
||||
|
||||
return this._requestJson({
|
||||
schema,
|
||||
url,
|
||||
options,
|
||||
errorMessages: {
|
||||
404: 'repository not found',
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
static registerLegacyRouteHandler({ camp, cache }) {
|
||||
camp.route(
|
||||
/^\/coveralls\/(?:(bitbucket|github)\/)?([^/]+\/[^/]+)(?:\/(.+))?\.(svg|png|gif|jpg|json)$/,
|
||||
cache((data, match, sendBadge, request) => {
|
||||
const repoService = match[1] ? match[1] : 'github'
|
||||
const userRepo = match[2] // eg, `jekyll/jekyll`.
|
||||
const branch = match[3]
|
||||
const format = match[4]
|
||||
const apiUrl = {
|
||||
url: `https://coveralls.io/repos/${repoService}/${userRepo}/badge.svg`,
|
||||
followRedirect: false,
|
||||
method: 'HEAD',
|
||||
}
|
||||
if (branch) {
|
||||
apiUrl.url += `?branch=${branch}`
|
||||
}
|
||||
const badgeData = getBadgeData('coverage', data)
|
||||
request(apiUrl, (err, res) => {
|
||||
if (err != null) {
|
||||
badgeData.text[1] = 'invalid'
|
||||
sendBadge(format, badgeData)
|
||||
return
|
||||
}
|
||||
// We should get a 302. Look inside the Location header.
|
||||
const buffer = res.headers.location
|
||||
if (!buffer) {
|
||||
badgeData.text[1] = 'invalid'
|
||||
sendBadge(format, badgeData)
|
||||
return
|
||||
}
|
||||
try {
|
||||
const score = buffer.split('_')[1].split('.')[0]
|
||||
const percentage = parseInt(score)
|
||||
if (Number.isNaN(percentage)) {
|
||||
badgeData.text[1] = 'unknown'
|
||||
sendBadge(format, badgeData)
|
||||
return
|
||||
}
|
||||
badgeData.text[1] = `${score}%`
|
||||
badgeData.colorscheme = coveragePercentageColor(percentage)
|
||||
sendBadge(format, badgeData)
|
||||
} catch (e) {
|
||||
badgeData.text[1] = 'malformed'
|
||||
sendBadge(format, badgeData)
|
||||
}
|
||||
})
|
||||
})
|
||||
)
|
||||
async handle({ vcsType, user, repo, branch }) {
|
||||
const json = await this.fetch({ vcsType, user, repo, branch })
|
||||
return this.constructor.render({ coverage: json.covered_percent })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,143 +1,20 @@
|
||||
'use strict'
|
||||
|
||||
const { isIntegerPercentage } = require('../test-validators')
|
||||
const { ServiceTester } = require('../tester')
|
||||
|
||||
const t = (module.exports = new ServiceTester({
|
||||
id: 'coveralls',
|
||||
title: 'Coveralls.io',
|
||||
}))
|
||||
|
||||
t.create('error status code - location header is missing')
|
||||
.get('/github/not/existed.json')
|
||||
.intercept(nock =>
|
||||
nock('https://coveralls.io')
|
||||
.head('/repos/github/not/existed/badge.svg')
|
||||
.reply(404)
|
||||
)
|
||||
.expectBadge({ label: 'coverage', message: 'invalid' })
|
||||
|
||||
t.create('malformed location')
|
||||
.get('/github/user/repository.json')
|
||||
.intercept(nock =>
|
||||
nock('https://coveralls.io')
|
||||
.head('/repos/github/user/repository/badge.svg')
|
||||
.reply(
|
||||
302,
|
||||
{},
|
||||
{
|
||||
Location:
|
||||
'https://s3.amazonaws.com/assets.coveralls.io/badges/malformedlocation.svg',
|
||||
}
|
||||
)
|
||||
)
|
||||
.expectBadge({ label: 'coverage', message: 'malformed' })
|
||||
|
||||
t.create('NaN percentage in location')
|
||||
.get('/github/user/repository.json')
|
||||
.intercept(nock =>
|
||||
nock('https://coveralls.io')
|
||||
.head('/repos/github/user/repository/badge.svg')
|
||||
.reply(
|
||||
302,
|
||||
{},
|
||||
{
|
||||
Location:
|
||||
'https://s3.amazonaws.com/assets.coveralls.io/badges/coveralls_notanumber.svg',
|
||||
}
|
||||
)
|
||||
)
|
||||
.expectBadge({ label: 'coverage', message: 'unknown' })
|
||||
|
||||
t.create('connection error')
|
||||
.get('/github/user/repository.json')
|
||||
.networkOff()
|
||||
.expectBadge({ label: 'coverage', message: 'invalid' })
|
||||
|
||||
t.create('show coverage')
|
||||
.get('/github/user/repository.json')
|
||||
.intercept(nock =>
|
||||
nock('https://coveralls.io')
|
||||
.head('/repos/github/user/repository/badge.svg')
|
||||
.reply(
|
||||
302,
|
||||
{},
|
||||
{
|
||||
Location:
|
||||
'https://s3.amazonaws.com/assets.coveralls.io/badges/coveralls_50.svg',
|
||||
}
|
||||
)
|
||||
)
|
||||
.expectBadge({ label: 'coverage', message: '50%' })
|
||||
|
||||
t.create('show coverage for legacy github link')
|
||||
.get('/user/repository.json')
|
||||
.intercept(nock =>
|
||||
nock('https://coveralls.io')
|
||||
.head('/repos/github/user/repository/badge.svg')
|
||||
.reply(
|
||||
302,
|
||||
{},
|
||||
{
|
||||
Location:
|
||||
'https://s3.amazonaws.com/assets.coveralls.io/badges/coveralls_50.svg',
|
||||
}
|
||||
)
|
||||
)
|
||||
.expectBadge({ label: 'coverage', message: '50%' })
|
||||
|
||||
t.create('show coverage for branch')
|
||||
.get('/github/user/repository/branch.json')
|
||||
.intercept(nock =>
|
||||
nock('https://coveralls.io')
|
||||
.head('/repos/github/user/repository/badge.svg?branch=branch')
|
||||
.reply(
|
||||
302,
|
||||
{},
|
||||
{
|
||||
Location:
|
||||
'https://s3.amazonaws.com/assets.coveralls.io/badges/coveralls_50.svg',
|
||||
}
|
||||
)
|
||||
)
|
||||
.expectBadge({ label: 'coverage', message: '50%' })
|
||||
|
||||
t.create('show coverage for bitbucket')
|
||||
.get('/bitbucket/user/repository.json')
|
||||
.intercept(nock =>
|
||||
nock('https://coveralls.io')
|
||||
.head('/repos/bitbucket/user/repository/badge.svg')
|
||||
.reply(
|
||||
302,
|
||||
{},
|
||||
{
|
||||
Location:
|
||||
'https://s3.amazonaws.com/assets.coveralls.io/badges/coveralls_50.svg',
|
||||
}
|
||||
)
|
||||
)
|
||||
.expectBadge({ label: 'coverage', message: '50%' })
|
||||
|
||||
t.create('show coverage for bitbucket with branch')
|
||||
.get('/bitbucket/user/repository/branch.json')
|
||||
.intercept(nock =>
|
||||
nock('https://coveralls.io')
|
||||
.head('/repos/bitbucket/user/repository/badge.svg?branch=branch')
|
||||
.reply(
|
||||
302,
|
||||
{},
|
||||
{
|
||||
Location:
|
||||
'https://s3.amazonaws.com/assets.coveralls.io/badges/coveralls_50.svg',
|
||||
}
|
||||
)
|
||||
)
|
||||
.expectBadge({ label: 'coverage', message: '50%' })
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
|
||||
t.create('github coverage')
|
||||
.get('/github/jekyll/jekyll.json')
|
||||
.expectBadge({ label: 'coverage', message: isIntegerPercentage })
|
||||
|
||||
t.create('nonexistent project')
|
||||
.get('/github/fake-shields-io/not-a-real-repository.json')
|
||||
.expectBadge({ label: 'coverage', message: 'repository not found' })
|
||||
|
||||
t.create('github branch coverage')
|
||||
.get('/github/lemurheavy/coveralls-ruby/master.json')
|
||||
.expectBadge({ label: 'coverage', message: isIntegerPercentage })
|
||||
|
||||
t.create('github coverage for legacy link')
|
||||
.get('/jekyll/jekyll.json')
|
||||
.expectBadge({ label: 'coverage', message: isIntegerPercentage })
|
||||
|
||||
Reference in New Issue
Block a user