Add SymfonyInsight stars badge, run [SymfonyInsight sensiolabs amo chrome-web-store redmine spigetratings vaadin-directory visualstudiomarketplacerating wordpress] (#2971)
* feat: added stars badge for symfony insight * refactor: changed symfony star determination logic * feat: updating symfony to handle old scan scenarios * feat: updated symfony insight to handle older projects * tests: removed another test for symfony insight per request
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
const moment = require('moment')
|
||||
moment().format()
|
||||
|
||||
function starRating(rating) {
|
||||
function starRating(rating, max = 5) {
|
||||
const flooredRating = Math.floor(rating)
|
||||
let stars = ''
|
||||
while (stars.length < flooredRating) {
|
||||
@@ -23,7 +23,8 @@ function starRating(rating) {
|
||||
} else if (decimal >= 0.125) {
|
||||
stars += '¼'
|
||||
}
|
||||
while (stars.length < 5) {
|
||||
|
||||
while (stars.length < max) {
|
||||
stars += '☆'
|
||||
}
|
||||
return stars
|
||||
|
||||
@@ -23,6 +23,7 @@ describe('Text formatters', function() {
|
||||
given(2.566).expect('★★½☆☆')
|
||||
given(2.2).expect('★★¼☆☆')
|
||||
given(3).expect('★★★☆☆')
|
||||
given(2, 4).expect('★★☆☆')
|
||||
})
|
||||
|
||||
test(currencyFromCode, () => {
|
||||
|
||||
17
services/symfony/sensiolabs-redirect.service.js
Normal file
17
services/symfony/sensiolabs-redirect.service.js
Normal file
@@ -0,0 +1,17 @@
|
||||
'use strict'
|
||||
|
||||
const { redirector } = require('..')
|
||||
|
||||
module.exports = [
|
||||
// The SymfonyInsight service was previously branded as SensioLabs, and
|
||||
// accordingly the badge path used to be /sensiolabs/i/projectUuid'.
|
||||
redirector({
|
||||
category: 'analysis',
|
||||
route: {
|
||||
base: 'sensiolabs/i',
|
||||
pattern: ':projectUuid',
|
||||
},
|
||||
target: ({ projectUuid }) => `/symfony/i/grade/${projectUuid}`,
|
||||
dateAdded: new Date('2019-02-08'),
|
||||
}),
|
||||
]
|
||||
18
services/symfony/sensiolabs-redirect.tester.js
Normal file
18
services/symfony/sensiolabs-redirect.tester.js
Normal file
@@ -0,0 +1,18 @@
|
||||
'use strict'
|
||||
|
||||
const { ServiceTester } = require('../tester')
|
||||
|
||||
const t = (module.exports = new ServiceTester({
|
||||
id: 'sensiolabs',
|
||||
title: 'SensioLabs',
|
||||
}))
|
||||
|
||||
t.create('sensiolabs insight')
|
||||
.get('/i/45afb680-d4e6-4e66-93ea-bcfa79eb8a87.svg', {
|
||||
followRedirect: false,
|
||||
})
|
||||
.expectStatus(301)
|
||||
.expectHeader(
|
||||
'Location',
|
||||
'/symfony/i/grade/45afb680-d4e6-4e66-93ea-bcfa79eb8a87.svg'
|
||||
)
|
||||
146
services/symfony/symfony-insight-base.js
Normal file
146
services/symfony/symfony-insight-base.js
Normal file
@@ -0,0 +1,146 @@
|
||||
'use strict'
|
||||
|
||||
const Joi = require('joi')
|
||||
const serverSecrets = require('../../lib/server-secrets')
|
||||
const { BaseXmlService, Inaccessible } = require('..')
|
||||
|
||||
const violationSchema = Joi.object({
|
||||
severity: Joi.equal('info', 'minor', 'major', 'critical').required(),
|
||||
}).required()
|
||||
|
||||
const schema = Joi.object({
|
||||
project: Joi.object({
|
||||
'last-analysis': Joi.object({
|
||||
status: Joi.equal(
|
||||
'ordered',
|
||||
'running',
|
||||
'measured',
|
||||
'analyzed',
|
||||
'finished'
|
||||
)
|
||||
.allow('')
|
||||
.required(),
|
||||
grade: Joi.equal('platinum', 'gold', 'silver', 'bronze', 'none'),
|
||||
violations: Joi.object({
|
||||
// RE: https://github.com/NaturalIntelligence/fast-xml-parser/issues/68
|
||||
// The BaseXmlService uses the fast-xml-parser which doesn't support forcing
|
||||
// the xml nodes to always be parsed as an array. Currently, if the response
|
||||
// only contains a single violation then it will be parsed as an object,
|
||||
// otherwise it will be parsed as an array.
|
||||
violation: Joi.array()
|
||||
.items(violationSchema)
|
||||
.single()
|
||||
.required(),
|
||||
}),
|
||||
}),
|
||||
}).required(),
|
||||
}).required()
|
||||
|
||||
const keywords = ['sensiolabs', 'sensio']
|
||||
|
||||
const gradeColors = {
|
||||
none: 'red',
|
||||
bronze: '#C88F6A',
|
||||
silver: '#C0C0C0',
|
||||
gold: '#EBC760',
|
||||
platinum: '#E5E4E2',
|
||||
}
|
||||
|
||||
class SymfonyInsightBase extends BaseXmlService {
|
||||
static get defaultBadgeData() {
|
||||
return {
|
||||
label: 'symfony insight',
|
||||
}
|
||||
}
|
||||
|
||||
static get category() {
|
||||
return 'analysis'
|
||||
}
|
||||
|
||||
async fetch({ projectUuid }) {
|
||||
const url = `https://insight.symfony.com/api/projects/${projectUuid}`
|
||||
const options = {
|
||||
headers: {
|
||||
Accept: 'application/vnd.com.sensiolabs.insight+xml',
|
||||
},
|
||||
}
|
||||
|
||||
if (
|
||||
!serverSecrets.sl_insight_userUuid ||
|
||||
!serverSecrets.sl_insight_apiToken
|
||||
) {
|
||||
throw new Inaccessible({
|
||||
prettyMessage: 'required API tokens not found in config',
|
||||
})
|
||||
}
|
||||
|
||||
options.auth = {
|
||||
user: serverSecrets.sl_insight_userUuid,
|
||||
pass: serverSecrets.sl_insight_apiToken,
|
||||
}
|
||||
|
||||
return this._requestXml({
|
||||
url,
|
||||
options,
|
||||
schema,
|
||||
errorMessages: {
|
||||
401: 'not authorized to access project',
|
||||
404: 'project not found',
|
||||
},
|
||||
parserOptions: {
|
||||
attributeNamePrefix: '',
|
||||
ignoreAttributes: false,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
transform({ data }) {
|
||||
const lastAnalysis = data.project['last-analysis']
|
||||
let numViolations = 0
|
||||
let numCriticalViolations = 0
|
||||
let numMajorViolations = 0
|
||||
let numMinorViolations = 0
|
||||
let numInfoViolations = 0
|
||||
|
||||
const violationContainer = lastAnalysis.violations
|
||||
if (violationContainer && violationContainer.violation) {
|
||||
let violations = []
|
||||
// See above note on schema RE: https://github.com/NaturalIntelligence/fast-xml-parser/issues/68
|
||||
// This covers the scenario of multiple violations which are parsed as an array and single
|
||||
// violations which is parsed as a single object.
|
||||
if (Array.isArray(violationContainer.violation)) {
|
||||
violations = violationContainer.violation
|
||||
} else {
|
||||
violations.push(violationContainer.violation)
|
||||
}
|
||||
numViolations = violations.length
|
||||
violations.forEach(violation => {
|
||||
if (violation.severity === 'critical') {
|
||||
numCriticalViolations++
|
||||
} else if (violation.severity === 'major') {
|
||||
numMajorViolations++
|
||||
} else if (violation.severity === 'minor') {
|
||||
numMinorViolations++
|
||||
} else {
|
||||
numInfoViolations++
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
status: lastAnalysis.status,
|
||||
grade: lastAnalysis.grade,
|
||||
numViolations,
|
||||
numCriticalViolations,
|
||||
numMajorViolations,
|
||||
numMinorViolations,
|
||||
numInfoViolations,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
SymfonyInsightBase,
|
||||
keywords,
|
||||
gradeColors,
|
||||
}
|
||||
57
services/symfony/symfony-insight-grade.service.js
Normal file
57
services/symfony/symfony-insight-grade.service.js
Normal file
@@ -0,0 +1,57 @@
|
||||
'use strict'
|
||||
|
||||
const {
|
||||
SymfonyInsightBase,
|
||||
keywords,
|
||||
gradeColors,
|
||||
} = require('./symfony-insight-base')
|
||||
|
||||
module.exports = class SymfonyInsightGrade extends SymfonyInsightBase {
|
||||
static render({ status, grade }) {
|
||||
const label = 'grade'
|
||||
if (status !== 'finished' && status !== '') {
|
||||
return {
|
||||
label,
|
||||
message: 'pending',
|
||||
color: 'lightgrey',
|
||||
}
|
||||
}
|
||||
|
||||
const message = grade === 'none' ? 'no medal' : grade
|
||||
return {
|
||||
label,
|
||||
message,
|
||||
color: gradeColors[grade],
|
||||
}
|
||||
}
|
||||
|
||||
static get route() {
|
||||
return {
|
||||
base: 'symfony/i/grade',
|
||||
pattern: ':projectUuid',
|
||||
}
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
return [
|
||||
{
|
||||
title: 'SymfonyInsight Grade',
|
||||
namedParams: {
|
||||
projectUuid: '45afb680-d4e6-4e66-93ea-bcfa79eb8a87',
|
||||
},
|
||||
staticPreview: this.render({
|
||||
grade: 'bronze',
|
||||
status: 'finished',
|
||||
}),
|
||||
keywords,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
async handle({ projectUuid }) {
|
||||
const data = await this.fetch({ projectUuid })
|
||||
const { grade, status } = this.transform({ data })
|
||||
|
||||
return this.constructor.render({ grade, status })
|
||||
}
|
||||
}
|
||||
152
services/symfony/symfony-insight-grade.tester.js
Normal file
152
services/symfony/symfony-insight-grade.tester.js
Normal file
@@ -0,0 +1,152 @@
|
||||
'use strict'
|
||||
|
||||
const Joi = require('joi')
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
const {
|
||||
createTest,
|
||||
runningMockResponse,
|
||||
platinumMockResponse,
|
||||
goldMockResponse,
|
||||
silverMockResponse,
|
||||
bronzeMockResponse,
|
||||
noMedalMockResponse,
|
||||
prepLiveTest,
|
||||
sampleProjectUuid,
|
||||
realTokenExists,
|
||||
setSymfonyInsightCredsToFalsy,
|
||||
restore,
|
||||
} = require('./symfony-test-helpers')
|
||||
|
||||
createTest(t, 'live: valid project grade', { withMockCreds: false })
|
||||
.before(prepLiveTest)
|
||||
.get(`/${sampleProjectUuid}.json`)
|
||||
.timeout(15000)
|
||||
.interceptIf(!realTokenExists, nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, platinumMockResponse)
|
||||
)
|
||||
.expectJSONTypes(
|
||||
Joi.object().keys({
|
||||
name: 'grade',
|
||||
value: Joi.equal(
|
||||
'platinum',
|
||||
'gold',
|
||||
'silver',
|
||||
'bronze',
|
||||
'no medal'
|
||||
).required(),
|
||||
})
|
||||
)
|
||||
|
||||
createTest(t, 'live: nonexistent project', { withMockCreds: false })
|
||||
.before(prepLiveTest)
|
||||
.get('/45afb680-d4e6-4e66-93ea-bcfa79eb8a88.json')
|
||||
.interceptIf(!realTokenExists, nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get('/45afb680-d4e6-4e66-93ea-bcfa79eb8a88')
|
||||
.reply(404)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'symfony insight',
|
||||
value: 'project not found',
|
||||
})
|
||||
|
||||
createTest(t, '401 not authorized grade')
|
||||
.get(`/${sampleProjectUuid}.json`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(401)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'symfony insight',
|
||||
value: 'not authorized to access project',
|
||||
})
|
||||
|
||||
createTest(t, 'pending project grade')
|
||||
.get(`/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, runningMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'grade',
|
||||
value: 'pending',
|
||||
color: 'lightgrey',
|
||||
})
|
||||
|
||||
createTest(t, 'platinum grade')
|
||||
.get(`/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, platinumMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'grade',
|
||||
value: 'platinum',
|
||||
color: '#e5e4e2',
|
||||
})
|
||||
|
||||
createTest(t, 'gold grade')
|
||||
.get(`/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, goldMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'grade',
|
||||
value: 'gold',
|
||||
color: '#ebc760',
|
||||
})
|
||||
|
||||
createTest(t, 'silver grade')
|
||||
.get(`/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, silverMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'grade',
|
||||
value: 'silver',
|
||||
color: '#c0c0c0',
|
||||
})
|
||||
|
||||
createTest(t, 'bronze grade')
|
||||
.get(`/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, bronzeMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'grade',
|
||||
value: 'bronze',
|
||||
color: '#c88f6a',
|
||||
})
|
||||
|
||||
createTest(t, 'no medal grade')
|
||||
.get(`/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, noMedalMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'grade',
|
||||
value: 'no medal',
|
||||
color: 'red',
|
||||
})
|
||||
|
||||
createTest(t, 'auth missing', { withMockCreds: false })
|
||||
.before(setSymfonyInsightCredsToFalsy)
|
||||
.get(`/${sampleProjectUuid}.json`)
|
||||
.expectJSON({
|
||||
name: 'symfony insight',
|
||||
value: 'required API tokens not found in config',
|
||||
})
|
||||
.after(restore)
|
||||
64
services/symfony/symfony-insight-stars.service.js
Normal file
64
services/symfony/symfony-insight-stars.service.js
Normal file
@@ -0,0 +1,64 @@
|
||||
'use strict'
|
||||
|
||||
const { starRating } = require('../../lib/text-formatters')
|
||||
const {
|
||||
SymfonyInsightBase,
|
||||
keywords,
|
||||
gradeColors,
|
||||
} = require('./symfony-insight-base')
|
||||
|
||||
const gradeStars = {
|
||||
none: 0,
|
||||
bronze: 1,
|
||||
silver: 2,
|
||||
gold: 3,
|
||||
platinum: 4,
|
||||
}
|
||||
|
||||
module.exports = class SymfonyInsightStars extends SymfonyInsightBase {
|
||||
static render({ status, grade }) {
|
||||
const label = 'stars'
|
||||
if (status !== 'finished' && status !== '') {
|
||||
return {
|
||||
label,
|
||||
message: 'pending',
|
||||
color: 'lightgrey',
|
||||
}
|
||||
}
|
||||
const numStars = gradeStars[grade]
|
||||
return {
|
||||
label,
|
||||
message: starRating(numStars, 4),
|
||||
color: gradeColors[grade],
|
||||
}
|
||||
}
|
||||
|
||||
static get route() {
|
||||
return {
|
||||
base: 'symfony/i/stars',
|
||||
pattern: ':projectUuid',
|
||||
}
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
return [
|
||||
{
|
||||
title: 'SymfonyInsight Stars',
|
||||
namedParams: {
|
||||
projectUuid: '45afb680-d4e6-4e66-93ea-bcfa79eb8a87',
|
||||
},
|
||||
staticPreview: this.render({
|
||||
grade: 'silver',
|
||||
status: 'finished',
|
||||
}),
|
||||
keywords,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
async handle({ projectUuid }) {
|
||||
const data = await this.fetch({ projectUuid })
|
||||
const { grade, status } = this.transform({ data })
|
||||
return this.constructor.render({ grade, status })
|
||||
}
|
||||
}
|
||||
126
services/symfony/symfony-insight-stars.tester.js
Normal file
126
services/symfony/symfony-insight-stars.tester.js
Normal file
@@ -0,0 +1,126 @@
|
||||
'use strict'
|
||||
|
||||
const Joi = require('joi')
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
const { withRegex } = require('../test-validators')
|
||||
const {
|
||||
createTest,
|
||||
runningMockResponse,
|
||||
platinumMockResponse,
|
||||
goldMockResponse,
|
||||
silverMockResponse,
|
||||
bronzeMockResponse,
|
||||
noMedalMockResponse,
|
||||
prepLiveTest,
|
||||
sampleProjectUuid,
|
||||
realTokenExists,
|
||||
} = require('./symfony-test-helpers')
|
||||
|
||||
createTest(t, 'live: valid project stars', { withMockCreds: false })
|
||||
.before(prepLiveTest)
|
||||
.get(`/${sampleProjectUuid}.json`)
|
||||
.timeout(15000)
|
||||
.interceptIf(!realTokenExists, nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, platinumMockResponse)
|
||||
)
|
||||
.expectJSONTypes(
|
||||
Joi.object().keys({
|
||||
name: 'stars',
|
||||
value: withRegex(
|
||||
/^(?=.{4}$)(\u2605{0,4}[\u00BC\u00BD\u00BE]?\u2606{0,4})$/
|
||||
),
|
||||
})
|
||||
)
|
||||
|
||||
createTest(t, 'live (stars): nonexistent project', { withMockCreds: false })
|
||||
.before(prepLiveTest)
|
||||
.get('/abc.json')
|
||||
.interceptIf(!realTokenExists, nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get('/abc')
|
||||
.reply(404)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'symfony insight',
|
||||
value: 'project not found',
|
||||
})
|
||||
|
||||
createTest(t, 'pending project stars')
|
||||
.get(`/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, runningMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'stars',
|
||||
value: 'pending',
|
||||
color: 'lightgrey',
|
||||
})
|
||||
|
||||
createTest(t, 'platinum stars')
|
||||
.get(`/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, platinumMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'stars',
|
||||
value: '★★★★',
|
||||
color: '#e5e4e2',
|
||||
})
|
||||
|
||||
createTest(t, 'gold stars')
|
||||
.get(`/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, goldMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'stars',
|
||||
value: '★★★☆',
|
||||
color: '#ebc760',
|
||||
})
|
||||
|
||||
createTest(t, 'silver stars')
|
||||
.get(`/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, silverMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'stars',
|
||||
value: '★★☆☆',
|
||||
color: '#c0c0c0',
|
||||
})
|
||||
|
||||
createTest(t, 'bronze stars')
|
||||
.get(`/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, bronzeMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'stars',
|
||||
value: '★☆☆☆',
|
||||
color: '#c88f6a',
|
||||
})
|
||||
|
||||
createTest(t, 'no medal stars')
|
||||
.get(`/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, noMedalMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'stars',
|
||||
value: '☆☆☆☆',
|
||||
color: 'red',
|
||||
})
|
||||
85
services/symfony/symfony-insight-violations.service.js
Normal file
85
services/symfony/symfony-insight-violations.service.js
Normal file
@@ -0,0 +1,85 @@
|
||||
'use strict'
|
||||
|
||||
const { SymfonyInsightBase, keywords } = require('./symfony-insight-base')
|
||||
|
||||
module.exports = class SymfonyInsightViolations extends SymfonyInsightBase {
|
||||
static render({
|
||||
status,
|
||||
numViolations,
|
||||
numCriticalViolations,
|
||||
numMajorViolations,
|
||||
numMinorViolations,
|
||||
numInfoViolations,
|
||||
}) {
|
||||
const label = 'violations'
|
||||
if (status !== 'finished' && status !== '') {
|
||||
return {
|
||||
label,
|
||||
message: 'pending',
|
||||
color: 'lightgrey',
|
||||
}
|
||||
}
|
||||
|
||||
if (numViolations === 0) {
|
||||
return {
|
||||
label,
|
||||
message: '0',
|
||||
color: 'brightgreen',
|
||||
}
|
||||
}
|
||||
|
||||
let color = 'yellowgreen'
|
||||
const violationSummary = []
|
||||
|
||||
if (numInfoViolations > 0) {
|
||||
violationSummary.push(`${numInfoViolations} info`)
|
||||
}
|
||||
if (numMinorViolations > 0) {
|
||||
violationSummary.unshift(`${numMinorViolations} minor`)
|
||||
color = 'yellow'
|
||||
}
|
||||
if (numMajorViolations > 0) {
|
||||
violationSummary.unshift(`${numMajorViolations} major`)
|
||||
color = 'orange'
|
||||
}
|
||||
if (numCriticalViolations > 0) {
|
||||
violationSummary.unshift(`${numCriticalViolations} critical`)
|
||||
color = 'red'
|
||||
}
|
||||
|
||||
return {
|
||||
label,
|
||||
message: violationSummary.join(', '),
|
||||
color,
|
||||
}
|
||||
}
|
||||
|
||||
static get route() {
|
||||
return {
|
||||
base: 'symfony/i/violations',
|
||||
pattern: ':projectUuid',
|
||||
}
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
return [
|
||||
{
|
||||
title: 'SymfonyInsight Violations',
|
||||
namedParams: {
|
||||
projectUuid: '45afb680-d4e6-4e66-93ea-bcfa79eb8a87',
|
||||
},
|
||||
staticPreview: this.render({
|
||||
numViolations: 0,
|
||||
status: 'finished',
|
||||
}),
|
||||
keywords,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
async handle({ projectUuid }) {
|
||||
const data = await this.fetch({ projectUuid })
|
||||
const lastAnalysis = this.transform({ data })
|
||||
return this.constructor.render(lastAnalysis)
|
||||
}
|
||||
}
|
||||
141
services/symfony/symfony-insight-violations.tester.js
Normal file
141
services/symfony/symfony-insight-violations.tester.js
Normal file
@@ -0,0 +1,141 @@
|
||||
'use strict'
|
||||
|
||||
const Joi = require('joi')
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
const { withRegex } = require('../test-validators')
|
||||
const {
|
||||
createTest,
|
||||
goldMockResponse,
|
||||
runningMockResponse,
|
||||
prepLiveTest,
|
||||
sampleProjectUuid,
|
||||
realTokenExists,
|
||||
mockSymfonyUser,
|
||||
mockSymfonyToken,
|
||||
criticalViolation,
|
||||
majorViolation,
|
||||
minorViolation,
|
||||
infoViolation,
|
||||
multipleViolations,
|
||||
} = require('./symfony-test-helpers')
|
||||
|
||||
createTest(t, 'live: valid project violations', { withMockCreds: false })
|
||||
.before(prepLiveTest)
|
||||
.get(`/${sampleProjectUuid}.json`)
|
||||
.timeout(15000)
|
||||
.interceptIf(!realTokenExists, nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, multipleViolations)
|
||||
)
|
||||
.expectJSONTypes(
|
||||
Joi.object().keys({
|
||||
name: 'violations',
|
||||
value: withRegex(
|
||||
/\d* critical|\d* critical, \d* major|\d* critical, \d* major, \d* minor|\d* critical, \d* major, \d* minor, \d* info|\d* critical, \d* minor|\d* critical, \d* info|\d* major|\d* major, \d* minor|\d* major, \d* minor, \d* info|\d* major, \d* info|\d* minor|\d* minor, \d* info/
|
||||
),
|
||||
})
|
||||
)
|
||||
|
||||
createTest(t, 'pending project grade')
|
||||
.get(`/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, runningMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'violations',
|
||||
value: 'pending',
|
||||
color: 'lightgrey',
|
||||
})
|
||||
|
||||
createTest(t, 'zero violations')
|
||||
.get(`/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, goldMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'violations',
|
||||
value: '0',
|
||||
color: 'brightgreen',
|
||||
})
|
||||
|
||||
createTest(t, 'critical violations')
|
||||
.get(`/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, criticalViolation)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'violations',
|
||||
value: '1 critical',
|
||||
color: 'red',
|
||||
})
|
||||
|
||||
createTest(t, 'major violations')
|
||||
.get(`/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, majorViolation)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'violations',
|
||||
value: '1 major',
|
||||
color: 'orange',
|
||||
})
|
||||
|
||||
createTest(t, 'minor violations')
|
||||
.get(`/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.basicAuth({
|
||||
user: mockSymfonyUser,
|
||||
pass: mockSymfonyToken,
|
||||
})
|
||||
.reply(200, minorViolation)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'violations',
|
||||
value: '1 minor',
|
||||
color: 'yellow',
|
||||
})
|
||||
|
||||
createTest(t, 'info violations')
|
||||
.get(`/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.basicAuth({
|
||||
user: mockSymfonyUser,
|
||||
pass: mockSymfonyToken,
|
||||
})
|
||||
.reply(200, infoViolation)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'violations',
|
||||
value: '1 info',
|
||||
color: 'yellowgreen',
|
||||
})
|
||||
|
||||
createTest(t, 'multiple violations grade')
|
||||
.get(`/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.basicAuth({
|
||||
user: mockSymfonyUser,
|
||||
pass: mockSymfonyToken,
|
||||
})
|
||||
.reply(200, multipleViolations)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'violations',
|
||||
value: '1 critical, 1 info',
|
||||
color: 'red',
|
||||
})
|
||||
@@ -1,288 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const Joi = require('joi')
|
||||
const serverSecrets = require('../../lib/server-secrets')
|
||||
const { BaseXmlService, Inaccessible } = require('..')
|
||||
|
||||
const violationSchema = Joi.object({
|
||||
severity: Joi.equal('info', 'minor', 'major', 'critical').required(),
|
||||
}).required()
|
||||
|
||||
const schema = Joi.object({
|
||||
project: Joi.object({
|
||||
'last-analysis': Joi.object({
|
||||
status: Joi.equal(
|
||||
'ordered',
|
||||
'running',
|
||||
'measured',
|
||||
'analyzed',
|
||||
'finished'
|
||||
).required(),
|
||||
grade: Joi.equal('platinum', 'gold', 'silver', 'bronze', 'none'),
|
||||
violations: Joi.object({
|
||||
// RE: https://github.com/NaturalIntelligence/fast-xml-parser/issues/68
|
||||
// The BaseXmlService uses the fast-xml-parser which doesn't support forcing
|
||||
// the xml nodes to always be parsed as an array. Currently, if the response
|
||||
// only contains a single violation then it will be parsed as an object,
|
||||
// otherwise it will be parsed as an array.
|
||||
violation: Joi.array()
|
||||
.items(violationSchema)
|
||||
.single()
|
||||
.required(),
|
||||
}),
|
||||
}),
|
||||
}).required(),
|
||||
}).required()
|
||||
|
||||
const keywords = ['sensiolabs']
|
||||
|
||||
module.exports = class SymfonyInsight extends BaseXmlService {
|
||||
static render({
|
||||
metric,
|
||||
status,
|
||||
grade,
|
||||
numViolations,
|
||||
numCriticalViolations,
|
||||
numMajorViolations,
|
||||
numMinorViolations,
|
||||
numInfoViolations,
|
||||
}) {
|
||||
if (status !== 'finished') {
|
||||
return {
|
||||
label: metric,
|
||||
message: 'pending',
|
||||
color: 'lightgrey',
|
||||
}
|
||||
}
|
||||
|
||||
if (metric === 'grade') {
|
||||
return this.renderGradeBadge({ grade })
|
||||
} else {
|
||||
return this.renderViolationsBadge({
|
||||
numViolations,
|
||||
numCriticalViolations,
|
||||
numMajorViolations,
|
||||
numMinorViolations,
|
||||
numInfoViolations,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
static renderGradeBadge({ grade }) {
|
||||
let color,
|
||||
message = grade
|
||||
if (grade === 'platinum') {
|
||||
color = '#E5E4E2'
|
||||
} else if (grade === 'gold') {
|
||||
color = '#EBC760'
|
||||
} else if (grade === 'silver') {
|
||||
color = '#C0C0C0'
|
||||
} else if (grade === 'bronze') {
|
||||
color = '#C88F6A'
|
||||
} else {
|
||||
message = 'no medal'
|
||||
color = 'red'
|
||||
}
|
||||
|
||||
return {
|
||||
label: 'grade',
|
||||
message,
|
||||
color,
|
||||
}
|
||||
}
|
||||
|
||||
static renderViolationsBadge({
|
||||
numViolations,
|
||||
numCriticalViolations,
|
||||
numMajorViolations,
|
||||
numMinorViolations,
|
||||
numInfoViolations,
|
||||
}) {
|
||||
if (numViolations === 0) {
|
||||
return {
|
||||
label: 'violations',
|
||||
message: '0',
|
||||
color: 'brightgreen',
|
||||
}
|
||||
}
|
||||
|
||||
let color = 'yellowgreen'
|
||||
const violationSummary = []
|
||||
|
||||
if (numInfoViolations > 0) {
|
||||
violationSummary.push(`${numInfoViolations} info`)
|
||||
}
|
||||
if (numMinorViolations > 0) {
|
||||
violationSummary.unshift(`${numMinorViolations} minor`)
|
||||
color = 'yellow'
|
||||
}
|
||||
if (numMajorViolations > 0) {
|
||||
violationSummary.unshift(`${numMajorViolations} major`)
|
||||
color = 'orange'
|
||||
}
|
||||
if (numCriticalViolations > 0) {
|
||||
violationSummary.unshift(`${numCriticalViolations} critical`)
|
||||
color = 'red'
|
||||
}
|
||||
|
||||
return {
|
||||
label: 'violations',
|
||||
message: violationSummary.join(', '),
|
||||
color,
|
||||
}
|
||||
}
|
||||
|
||||
static get defaultBadgeData() {
|
||||
return {
|
||||
label: 'symfony insight',
|
||||
}
|
||||
}
|
||||
|
||||
static get category() {
|
||||
return 'analysis'
|
||||
}
|
||||
|
||||
static get route() {
|
||||
return {
|
||||
base: '',
|
||||
// The SymfonyInsight service was previously branded as SensioLabs, and
|
||||
// accordingly the badge path used to be /sensiolabs/i/projectUuid'.
|
||||
// This is used to provide backward compatibility for the old path as well as
|
||||
// supporting the new/current path.
|
||||
format: '(?:sensiolabs/i|symfony/i/(grade|violations))/([^/]+)',
|
||||
capture: ['metric', 'projectUuid'],
|
||||
}
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
return [
|
||||
{
|
||||
title: 'SymfonyInsight Grade',
|
||||
pattern: 'symfony/i/grade/:projectUuid',
|
||||
namedParams: {
|
||||
projectUuid: '45afb680-d4e6-4e66-93ea-bcfa79eb8a87',
|
||||
},
|
||||
staticPreview: this.renderGradeBadge({
|
||||
grade: 'bronze',
|
||||
}),
|
||||
keywords,
|
||||
},
|
||||
{
|
||||
title: 'SymfonyInsight Violations',
|
||||
pattern: 'symfony/i/violations/:projectUuid',
|
||||
namedParams: {
|
||||
projectUuid: '45afb680-d4e6-4e66-93ea-bcfa79eb8a87',
|
||||
},
|
||||
staticPreview: this.renderViolationsBadge({
|
||||
numViolations: 0,
|
||||
}),
|
||||
keywords,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
async fetch({ projectUuid }) {
|
||||
const url = `https://insight.symfony.com/api/projects/${projectUuid}`
|
||||
const options = {
|
||||
headers: {
|
||||
Accept: 'application/vnd.com.sensiolabs.insight+xml',
|
||||
},
|
||||
}
|
||||
|
||||
if (
|
||||
!serverSecrets.sl_insight_userUuid ||
|
||||
!serverSecrets.sl_insight_apiToken
|
||||
) {
|
||||
throw new Inaccessible({
|
||||
prettyMessage: 'required API tokens not found in config',
|
||||
})
|
||||
}
|
||||
|
||||
options.auth = {
|
||||
user: serverSecrets.sl_insight_userUuid,
|
||||
pass: serverSecrets.sl_insight_apiToken,
|
||||
}
|
||||
|
||||
return this._requestXml({
|
||||
url,
|
||||
options,
|
||||
schema,
|
||||
errorMessages: {
|
||||
401: 'not authorized to access project',
|
||||
404: 'project not found',
|
||||
},
|
||||
parserOptions: {
|
||||
attributeNamePrefix: '',
|
||||
ignoreAttributes: false,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
transform({ data }) {
|
||||
const lastAnalysis = data.project['last-analysis']
|
||||
let numViolations = 0
|
||||
let numCriticalViolations = 0
|
||||
let numMajorViolations = 0
|
||||
let numMinorViolations = 0
|
||||
let numInfoViolations = 0
|
||||
|
||||
const violationContainer = lastAnalysis.violations
|
||||
if (violationContainer && violationContainer.violation) {
|
||||
let violations = []
|
||||
// See above note on schema RE: https://github.com/NaturalIntelligence/fast-xml-parser/issues/68
|
||||
// This covers the scenario of multiple violations which are parsed as an array and single
|
||||
// violations which is parsed as a single object.
|
||||
if (Array.isArray(violationContainer.violation)) {
|
||||
violations = violationContainer.violation
|
||||
} else {
|
||||
violations.push(violationContainer.violation)
|
||||
}
|
||||
numViolations = violations.length
|
||||
violations.forEach(violation => {
|
||||
if (violation.severity === 'critical') {
|
||||
numCriticalViolations++
|
||||
} else if (violation.severity === 'major') {
|
||||
numMajorViolations++
|
||||
} else if (violation.severity === 'minor') {
|
||||
numMinorViolations++
|
||||
} else {
|
||||
numInfoViolations++
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
status: lastAnalysis.status,
|
||||
grade: lastAnalysis.grade,
|
||||
numViolations,
|
||||
numCriticalViolations,
|
||||
numMajorViolations,
|
||||
numMinorViolations,
|
||||
numInfoViolations,
|
||||
}
|
||||
}
|
||||
|
||||
async handle({ metric = 'grade', projectUuid }) {
|
||||
const data = await this.fetch({ projectUuid })
|
||||
const {
|
||||
status,
|
||||
grade,
|
||||
numViolations,
|
||||
numCriticalViolations,
|
||||
numMajorViolations,
|
||||
numMinorViolations,
|
||||
numInfoViolations,
|
||||
} = this.transform({ data })
|
||||
|
||||
return this.constructor.render({
|
||||
metric,
|
||||
status,
|
||||
grade,
|
||||
numViolations,
|
||||
numCriticalViolations,
|
||||
numMajorViolations,
|
||||
numMinorViolations,
|
||||
numInfoViolations,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,318 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const Joi = require('joi')
|
||||
const { withRegex } = require('../test-validators')
|
||||
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
|
||||
const {
|
||||
runningMockResponse,
|
||||
platinumMockResponse,
|
||||
goldMockResponse,
|
||||
silverMockResponse,
|
||||
bronzeMockResponse,
|
||||
noMedalMockResponse,
|
||||
mockSymfonyUser,
|
||||
mockSymfonyToken,
|
||||
mockSymfonyInsightCreds,
|
||||
setSymfonyInsightCredsToFalsy,
|
||||
restore,
|
||||
realTokenExists,
|
||||
prepLiveTest,
|
||||
criticalViolation,
|
||||
majorViolation,
|
||||
minorViolation,
|
||||
infoViolation,
|
||||
multipleViolations,
|
||||
} = require('./symfony-test-helpers')
|
||||
|
||||
const sampleProjectUuid = '45afb680-d4e6-4e66-93ea-bcfa79eb8a87'
|
||||
|
||||
function create(title, { withMockCreds = true } = { withMockCreds: true }) {
|
||||
const result = t.create(title)
|
||||
if (withMockCreds) {
|
||||
result.before(mockSymfonyInsightCreds)
|
||||
result.finally(restore)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
create('live: valid project grade', { withMockCreds: false })
|
||||
.before(prepLiveTest)
|
||||
.get(`/symfony/i/grade/${sampleProjectUuid}.json`)
|
||||
.timeout(15000)
|
||||
.interceptIf(!realTokenExists, nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, platinumMockResponse)
|
||||
)
|
||||
.expectJSONTypes(
|
||||
Joi.object().keys({
|
||||
name: 'grade',
|
||||
value: Joi.equal(
|
||||
'platinum',
|
||||
'gold',
|
||||
'silver',
|
||||
'bronze',
|
||||
'no medal'
|
||||
).required(),
|
||||
})
|
||||
)
|
||||
|
||||
create('live: valid project violations', { withMockCreds: false })
|
||||
.before(prepLiveTest)
|
||||
.get(`/symfony/i/violations/${sampleProjectUuid}.json`)
|
||||
.timeout(15000)
|
||||
.interceptIf(!realTokenExists, nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, multipleViolations)
|
||||
)
|
||||
.expectJSONTypes(
|
||||
Joi.object().keys({
|
||||
name: 'violations',
|
||||
value: withRegex(
|
||||
/\d* critical|\d* critical, \d* major|\d* critical, \d* major, \d* minor|\d* critical, \d* major, \d* minor, \d* info|\d* critical, \d* minor|\d* critical, \d* info|\d* major|\d* major, \d* minor|\d* major, \d* minor, \d* info|\d* major, \d* info|\d* minor|\d* minor, \d* info/
|
||||
),
|
||||
})
|
||||
)
|
||||
|
||||
create('live: nonexistent project', { withMockCreds: false })
|
||||
.before(prepLiveTest)
|
||||
.get('/symfony/i/grade/45afb680-d4e6-4e66-93ea-bcfa79eb8a88.json')
|
||||
.interceptIf(!realTokenExists, nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get('/45afb680-d4e6-4e66-93ea-bcfa79eb8a88')
|
||||
.reply(404)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'symfony insight',
|
||||
value: 'project not found',
|
||||
})
|
||||
|
||||
create('404 project not found grade')
|
||||
.get(`/symfony/i/grade/${sampleProjectUuid}.json`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(404)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'symfony insight',
|
||||
value: 'project not found',
|
||||
})
|
||||
|
||||
create('401 not authorized grade')
|
||||
.get(`/symfony/i/grade/${sampleProjectUuid}.json`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(401)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'symfony insight',
|
||||
value: 'not authorized to access project',
|
||||
})
|
||||
|
||||
create('pending project grade')
|
||||
.get(`/symfony/i/grade/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, runningMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'grade',
|
||||
value: 'pending',
|
||||
color: 'lightgrey',
|
||||
})
|
||||
|
||||
create('platinum grade')
|
||||
.get(`/symfony/i/grade/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, platinumMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'grade',
|
||||
value: 'platinum',
|
||||
color: '#e5e4e2',
|
||||
})
|
||||
|
||||
create('gold grade')
|
||||
.get(`/symfony/i/grade/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, goldMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'grade',
|
||||
value: 'gold',
|
||||
color: '#ebc760',
|
||||
})
|
||||
|
||||
create('silver grade')
|
||||
.get(`/symfony/i/grade/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, silverMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'grade',
|
||||
value: 'silver',
|
||||
color: '#c0c0c0',
|
||||
})
|
||||
|
||||
create('bronze grade')
|
||||
.get(`/symfony/i/grade/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, bronzeMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'grade',
|
||||
value: 'bronze',
|
||||
color: '#c88f6a',
|
||||
})
|
||||
|
||||
create('no medal grade')
|
||||
.get(`/symfony/i/grade/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, noMedalMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'grade',
|
||||
value: 'no medal',
|
||||
color: 'red',
|
||||
})
|
||||
|
||||
create('zero violations')
|
||||
.get(`/symfony/i/violations/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, goldMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'violations',
|
||||
value: '0',
|
||||
color: 'brightgreen',
|
||||
})
|
||||
|
||||
create('critical violations')
|
||||
.get(`/symfony/i/violations/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, criticalViolation)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'violations',
|
||||
value: '1 critical',
|
||||
color: 'red',
|
||||
})
|
||||
|
||||
create('major violations')
|
||||
.get(`/symfony/i/violations/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, majorViolation)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'violations',
|
||||
value: '1 major',
|
||||
color: 'orange',
|
||||
})
|
||||
|
||||
create('minor violations')
|
||||
.get(`/symfony/i/violations/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.basicAuth({
|
||||
user: mockSymfonyUser,
|
||||
pass: mockSymfonyToken,
|
||||
})
|
||||
.reply(200, minorViolation)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'violations',
|
||||
value: '1 minor',
|
||||
color: 'yellow',
|
||||
})
|
||||
|
||||
create('info violations')
|
||||
.get(`/symfony/i/violations/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.basicAuth({
|
||||
user: mockSymfonyUser,
|
||||
pass: mockSymfonyToken,
|
||||
})
|
||||
.reply(200, infoViolation)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'violations',
|
||||
value: '1 info',
|
||||
color: 'yellowgreen',
|
||||
})
|
||||
|
||||
create('multiple violations grade')
|
||||
.get(`/symfony/i/violations/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.basicAuth({
|
||||
user: mockSymfonyUser,
|
||||
pass: mockSymfonyToken,
|
||||
})
|
||||
.reply(200, multipleViolations)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'violations',
|
||||
value: '1 critical, 1 info',
|
||||
color: 'red',
|
||||
})
|
||||
|
||||
create('auth missing', { withMockCreds: false })
|
||||
.before(setSymfonyInsightCredsToFalsy)
|
||||
.get(`/symfony/i/grade/${sampleProjectUuid}.json`)
|
||||
.expectJSON({
|
||||
name: 'symfony insight',
|
||||
value: 'required API tokens not found in config',
|
||||
})
|
||||
|
||||
// These tests ensure that the legacy badge path (/sensiolabs/i/projectUuid) still works
|
||||
create('legacy path: pending project grade')
|
||||
.get(`/sensiolabs/i/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, runningMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'grade',
|
||||
value: 'pending',
|
||||
color: 'lightgrey',
|
||||
})
|
||||
|
||||
create('legacy path: platinum grade')
|
||||
.get(`/sensiolabs/i/${sampleProjectUuid}.json?style=_shields_test`)
|
||||
.intercept(nock =>
|
||||
nock('https://insight.symfony.com/api/projects')
|
||||
.get(`/${sampleProjectUuid}`)
|
||||
.reply(200, platinumMockResponse)
|
||||
)
|
||||
.expectJSON({
|
||||
name: 'grade',
|
||||
value: 'platinum',
|
||||
color: '#e5e4e2',
|
||||
})
|
||||
@@ -3,6 +3,8 @@
|
||||
const sinon = require('sinon')
|
||||
const serverSecrets = require('../../lib/server-secrets')
|
||||
|
||||
const sampleProjectUuid = '45afb680-d4e6-4e66-93ea-bcfa79eb8a87'
|
||||
|
||||
function createMockResponse({ status = 'finished', grade, violations }) {
|
||||
let response = `
|
||||
<project>
|
||||
@@ -112,7 +114,21 @@ function prepLiveTest() {
|
||||
}
|
||||
}
|
||||
|
||||
function createTest(
|
||||
t,
|
||||
title,
|
||||
{ withMockCreds = true } = { withMockCreds: true }
|
||||
) {
|
||||
const result = t.create(title)
|
||||
if (withMockCreds) {
|
||||
result.before(mockSymfonyInsightCreds)
|
||||
result.finally(restore)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
sampleProjectUuid,
|
||||
runningMockResponse,
|
||||
platinumMockResponse,
|
||||
goldMockResponse,
|
||||
@@ -131,4 +147,5 @@ module.exports = {
|
||||
minorViolation,
|
||||
infoViolation,
|
||||
multipleViolations,
|
||||
createTest,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user