diff --git a/src/fixtures/pinpoint-npm-info.json b/src/fixtures/pinpoint-npm-info.json new file mode 100644 index 0000000..a70fb68 --- /dev/null +++ b/src/fixtures/pinpoint-npm-info.json @@ -0,0 +1,35 @@ +{ + "_id": "pinpoint", + "name": "pinpoint", + "description": "Pinpoint test fixture", + "homepage": "https://example.com/pinpoint", + "author": { + "name": "Fixture Author" + }, + "time": { + "created": "2016-01-01T00:00:00.000Z", + "modified": "2018-01-01T00:00:00.000Z" + }, + "maintainers": [ + { + "name": "fixture-maintainer" + } + ], + "dist-tags": { + "latest": "1.1.0" + }, + "versions": { + "not-a-version": { + "license": "SHOULD_NOT_BE_USED" + }, + "1.0.0": { + "license": "MIT" + }, + "1.1.0": { + "dependencies": { + "left-pad": "^1.3.0" + } + } + }, + "readme": "# Pinpoint\n\nFixture README" +} diff --git a/src/index.test.ts b/src/index.test.ts index c9eaf95..fa53926 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -1,11 +1,23 @@ import * as child_process from "child_process" import * as mockfs from "fs" -jest.mock("node-fetch", () => () => - Promise.resolve({ +jest.mock("node-fetch", () => (url: string) => { + const readFixture = (requestUrl: string) => { + const dep = requestUrl.split("/").pop() || "danger" + const fixturePath = `src/fixtures/${dep}-npm-info.json` + const fallbackFixturePath = "src/fixtures/danger-npm-info.json" + + try { + return JSON.parse(mockfs.readFileSync(fixturePath, "utf8")) + } catch (error) { + return JSON.parse(mockfs.readFileSync(fallbackFixturePath, "utf8")) + } + } + + return Promise.resolve({ ok: true, - json: () => Promise.resolve(JSON.parse(mockfs.readFileSync("src/fixtures/danger-npm-info.json", "utf8"))), + json: () => Promise.resolve(readFixture(url)), }) -) +}) import yarn, { _operateOnSingleDiff, @@ -155,6 +167,15 @@ describe("npm metadata", () => { const npmData = await getNPMMetadataForDep("danger") expect(_renderNPMTable({ usedInPackageJSONPaths: ["package.json"], npmData: npmData! })).toMatchSnapshot() }) + + it("Shows a version license when top-level license is missing", async () => { + expect.assertions(2) + const npmData = await getNPMMetadataForDep("pinpoint") + const rendered = _renderNPMTable({ usedInPackageJSONPaths: ["package.json"], npmData: npmData! }) + + expect(rendered).toContain("License: MIT") + expect(rendered).not.toContain("NO LICENSE FOUND") + }) }) describe("yarn metadata", () => { diff --git a/src/index.ts b/src/index.ts index 928387f..6eff0ba 100644 --- a/src/index.ts +++ b/src/index.ts @@ -171,6 +171,27 @@ export interface PartiallyRenderedNPMMetadata { readme: string } +const resolvePackageLicense = (npm: any): string | undefined => { + if (npm.license) { + return npm.license + } + + if (!npm.versions) { + return undefined + } + + const versionsWithLicenses = Object.keys(npm.versions).filter(version => semver.valid(version)).sort(semver.rcompare) + + for (const version of versionsWithLicenses) { + const versionMetadata = npm.versions[version] + if (versionMetadata && versionMetadata.license) { + return versionMetadata.license + } + } + + return undefined +} + export const getNPMMetadataForDep = async ( dep: string, npmRegistryUrl?: string, @@ -209,7 +230,7 @@ export const getNPMMetadataForDep = async ( tableDeets.push({ break: "row-break" }) // Left - const license = npm.license + const license = resolvePackageLicense(npm) if (license) { tableDeets.push({ name: "License", message: license }) } else {