From 5e7aa068527dfbdfced603b3dc1abee1c36c8910 Mon Sep 17 00:00:00 2001 From: Oleg Valter Date: Wed, 11 Aug 2021 16:18:37 +0300 Subject: [PATCH] added required headers validation & tests --- src/utils/validators.ts | 32 +++++++++++++++++++++++++++++ test/utils.spec.ts | 45 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/src/utils/validators.ts b/src/utils/validators.ts index 0b61d38..0556dac 100644 --- a/src/utils/validators.ts +++ b/src/utils/validators.ts @@ -1,3 +1,8 @@ +import { valid } from "semver"; +import validator from "validator"; +import { PackageInfo } from "./package"; +import { RequiredOnly } from "./types"; + export const validateMatchHeaders = (matches: string[]) => { const validationRegex = /^((?:https?|file|ftp|\*)(?=:\/\/)|(?:urn(?=:))):(?:\/\/)?(?:((?:\*||.+?)(?=\/|$)))?(\/\*|(?:.+?\*?)+)?|/; @@ -8,3 +13,30 @@ export const validateMatchHeaders = (matches: string[]) => { valid: matches.filter((m) => !invalid.includes(m)), }; }; + +export const validateRequiredHeaders = (packageInfo: PackageInfo) => { + const required: (keyof RequiredOnly)[] = [ + "author", + "name", + "homepage", + "version", + "description", + ]; + const missing = required.filter((p) => !(p in packageInfo)); + + const { homepage, version } = packageInfo; + + const isValidVersion = !!valid(version); + const isValidHomepage = validator.isURL(homepage); + + const status = [isValidVersion, isValidHomepage, !missing.length].reduce( + (a, c) => a && c + ); + + return { + status, + isValidVersion, + isValidHomepage, + missing, + }; +}; diff --git a/test/utils.spec.ts b/test/utils.spec.ts index a6c5cee..f4bb49b 100644 --- a/test/utils.spec.ts +++ b/test/utils.spec.ts @@ -1,7 +1,15 @@ import { expect } from "chai"; -import { validateMatchHeaders } from "../src/utils/validators"; +import { join } from "path"; +import { getPackage } from "../src/utils/package"; +import { + validateMatchHeaders, + validateRequiredHeaders, +} from "../src/utils/validators"; describe("validators", () => { + const base = process.cwd(); + const pkg = join(base, "/package.json"); + describe("@match headers validator", () => { const sampleMatches: string[] = [ "http://*/foo*", @@ -31,4 +39,39 @@ describe("validators", () => { expect(invalid).to.contain(typo); }); }); + + describe("required package headers validator", () => { + it("should correctly validate package with required fields present", async () => { + const validPackage = await getPackage(pkg); + + const { status, missing } = validateRequiredHeaders(validPackage!); + + expect(status).to.be.true; + expect(missing).to.be.empty; + }); + + it("should correctly validate package with required fields absent", async () => { + const validPackage = await getPackage(pkg); + + const testInvalid = { ...validPackage }; + delete testInvalid.author; + delete testInvalid.name; + delete testInvalid.description; + + //@ts-expect-error + testInvalid.version = "gobblygook5.0"; + testInvalid.homepage = "alice in wonderland"; + + const { status, missing, isValidVersion, isValidHomepage } = + //@ts-expect-error + validateRequiredHeaders(testInvalid); + + expect(status).to.be.false; + expect(isValidVersion).to.be.false; + expect(isValidHomepage).to.be.false; + expect(missing).to.contain("author"); + expect(missing).to.contain("name"); + expect(missing).to.contain("description"); + }); + }); });