Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

handle null licenses in crates.io response schema, run [crates] #7074

Merged
merged 4 commits into from
Sep 27, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions services/crates/crates-base.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const crateSchema = Joi.object({
.items(
Joi.object({
downloads: nonNegativeInteger,
license: Joi.string().required(),
license: Joi.string().required().allow(null),
})
)
.min(1)
Expand All @@ -25,7 +25,7 @@ const versionSchema = Joi.object({
version: Joi.object({
downloads: nonNegativeInteger,
num: Joi.string().required(),
license: Joi.string().required(),
license: Joi.string().required().allow(null),
}).required(),
}).required()

Expand Down
9 changes: 2 additions & 7 deletions services/crates/crates-downloads.tester.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { ServiceTester } from '../tester.js'
import { isMetric } from '../test-validators.js'

export const t = new ServiceTester({
id: 'crates',
title: 'crates.io',
pathPrefix: '/crates',
})
import { createServiceTester } from '../tester.js'
export const t = await createServiceTester()

t.create('total downloads')
.get('/d/libc.json')
Expand Down
39 changes: 21 additions & 18 deletions services/crates/crates-license.service.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { InvalidResponse } from '../index.js'
import { BaseCratesService, keywords } from './crates-base.js'

export default class CratesLicense extends BaseCratesService {
Expand All @@ -21,28 +22,30 @@ export default class CratesLicense extends BaseCratesService {
},
]

static render({ license }) {
return {
label: 'license',
message: license,
color: 'blue',
}
static defaultBadgeData = { label: 'license', color: 'blue' }

static render({ license: message }) {
return { message }
}

async handle({ crate, version }) {
const json = await this.fetch({ crate, version })
static transform({ errors, version, versions }) {
// crates.io returns a 200 response with an errors object in
// error scenarios, e.g. https://crates.io/api/v1/crates/libc/0.1
if (errors) {
throw new InvalidResponse({ prettyMessage: errors[0].detail })
}

if (json.errors) {
/* a call like
https://crates.io/api/v1/crates/libc/0.1
or
https://crates.io/api/v1/crates/libc/0.1.76
returns a 200 OK with an errors object */
return { message: json.errors[0].detail }
const license = version ? version.license : versions[0].license
if (!license) {
throw new InvalidResponse({ prettyMessage: 'invalid null license' })
}

return this.constructor.render({
license: json.version ? json.version.license : json.versions[0].license,
})
return { license }
}

async handle({ crate, version }) {
const json = await this.fetch({ crate, version })
const { license } = this.constructor.transform(json)
return this.constructor.render({ license })
}
}
27 changes: 27 additions & 0 deletions services/crates/crates-license.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { expect } from 'chai'
import { InvalidResponse } from '../index.js'
import CratesLicense from './crates-license.service.js'

describe('CratesLicense', function () {
it('throws InvalidResponse on error response', function () {
expect(() =>
CratesLicense.transform({ errors: [{ detail: 'invalid semver' }] })
)
.to.throw(InvalidResponse)
.with.property('prettyMessage', 'invalid semver')
})

it('throws InvalidResponse on null license with specific version', function () {
expect(() =>
CratesLicense.transform({ version: { num: '1.2.3', license: null } })
)
.to.throw(InvalidResponse)
.with.property('prettyMessage', 'invalid null license')
})

it('throws InvalidResponse on null license with latest version', function () {
expect(() => CratesLicense.transform({ versions: [{ license: null }] }))
.to.throw(InvalidResponse)
.with.property('prettyMessage', 'invalid null license')
})
})
chris48s marked this conversation as resolved.
Show resolved Hide resolved
19 changes: 11 additions & 8 deletions services/crates/crates-license.tester.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { ServiceTester } from '../tester.js'

export const t = new ServiceTester({
id: 'crates',
title: 'crates.io',
pathPrefix: '/crates/l',
})
import { createServiceTester } from '../tester.js'
export const t = await createServiceTester()

t.create('license')
.get('/libc.json')
Expand All @@ -16,4 +11,12 @@ t.create('license (with version)')

t.create('license (not found)')
.get('/not-a-real-package.json')
.expectBadge({ label: 'crates.io', message: 'not found' })
.expectBadge({ label: 'license', message: 'not found' })

t.create('license (null licenses in history)')
.get('/stun.json')
chris48s marked this conversation as resolved.
Show resolved Hide resolved
.expectBadge({ label: 'license', message: 'MIT/Apache-2.0' })

t.create('license (version with null license)')
.get('/stun/0.0.1.json')
.expectBadge({ label: 'license', message: 'invalid null license' })