From f66dbdcf355691947199c57aa0d544b5fdc00007 Mon Sep 17 00:00:00 2001 From: Oleg Valter Date: Tue, 10 Aug 2021 00:55:56 +0300 Subject: [PATCH] expanded validator, connected to index --- src/index.ts | 8 ++++ src/utils/validators.ts | 7 ++- test/index.spec.ts | 98 ++++++++++++++++++++++++++++++++++++----- test/utils.spec.ts | 14 +++--- 4 files changed, 109 insertions(+), 18 deletions(-) diff --git a/src/index.ts b/src/index.ts index 4972a65..5a99757 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,6 +12,7 @@ import { generateTampermonkeyHeaders } from "./generators/tampermonkey"; import { generateViolentMonkeyHeaders } from "./generators/violentmonkey"; import { scase } from "./utils/common"; import { getPackage } from "./utils/package"; +import { validateMatchHeaders } from "./utils/validators"; const names: UserScriptManagerName[] = [ "greasemonkey", @@ -35,6 +36,7 @@ export const generate = async ( output, spaces = 4, direct = false, + matches = [], ...rest }: GeneratorOptions ) => { @@ -52,10 +54,16 @@ export const generate = async ( return ""; } + const { invalid, status, valid } = validateMatchHeaders(matches); + if (!status) { + console.log(bgRed`Invalid @match headers:\n` + invalid.join("\n")); + } + const handler = managerTypeMap[type] as HeaderGenerator; const content = handler(parsedPackage, { ...rest, + matches: valid, spaces, packagePath, output, diff --git a/src/utils/validators.ts b/src/utils/validators.ts index 4f03736..0b61d38 100644 --- a/src/utils/validators.ts +++ b/src/utils/validators.ts @@ -1,5 +1,10 @@ export const validateMatchHeaders = (matches: string[]) => { const validationRegex = /^((?:https?|file|ftp|\*)(?=:\/\/)|(?:urn(?=:))):(?:\/\/)?(?:((?:\*||.+?)(?=\/|$)))?(\/\*|(?:.+?\*?)+)?|/; - return matches.every((match) => validationRegex.test(match)); + const invalid = matches.filter((match) => !validationRegex.test(match)); + return { + invalid, + status: !invalid.length, + valid: matches.filter((m) => !invalid.includes(m)), + }; }; diff --git a/test/index.spec.ts b/test/index.spec.ts index ad4699d..5792cfc 100644 --- a/test/index.spec.ts +++ b/test/index.spec.ts @@ -5,8 +5,15 @@ import { readFile, stat, unlink } from "fs/promises"; import { join } from "path"; import { promisify } from "util"; import { generate, GeneratorOptions } from "../src"; -import { GrantOptions, GreasemonkeyGrants } from "../src/generators"; -import { TampermonkeyGrants } from "../src/generators/tampermonkey/types"; +import { CommonGrantOptions } from "../src/generators"; +import { + GreasemonkeyGrantOptions, + GreasemonkeyGrants, +} from "../src/generators/greasemonkey/types"; +import { + TampermonkeyGrantOptions, + TampermonkeyGrants, +} from "../src/generators/tampermonkey/types"; import { getLongest } from "../src/utils/common"; use(cpr); @@ -19,7 +26,10 @@ describe("main", () => { const output = join(base, "/test/headers.js"); const entry = "./src/index.ts"; - const common: GeneratorOptions = { output, packagePath: pkg }; + const common: GeneratorOptions = { + output, + packagePath: pkg, + }; //@see https://developer.chrome.com/docs/extensions/mv2/match_patterns/ const allMatches: string[] = [ @@ -45,20 +55,34 @@ describe("main", () => { "window.onurlchange", ]; - const allGrantOptions: GrantOptions[] = [ + const grantsGM: GreasemonkeyGrants[] = [ + "GM.deleteValue", + "GM.getValue", + "GM.listValues", + "GM.setValue", + ]; + + const grantOptionsCommon: CommonGrantOptions[] = [ "get", "set", "list", "delete", "unsafe", + ]; + + const grantOptionsTM: TampermonkeyGrantOptions[] = [ + ...grantOptionsCommon, "close", "focus", "change", ]; - describe.skip("Greasemonkey", async () => { - //TODO: add once other commands ready - }); + const grantOptionsGM: GreasemonkeyGrantOptions[] = [ + ...grantOptionsCommon, + "clip", + "fetch", + "notify", + ]; describe("CLI Options", async function () { this.timeout(5e3); @@ -85,14 +109,14 @@ describe("main", () => { }); it("-g options should correctly add @grant", async () => { - const gOpts = allGrantOptions.map((g) => `-g "${g}"`).join(" "); + const gOpts = grantOptionsTM.map((g) => `-g "${g}"`).join(" "); const { stdout } = await aexec( `ts-node ${entry} tampermonkey ${gOpts} -p ${pkg} -o ${output} -d` ); const matched = stdout.match(/@grant\s+(.+)/g) || []; - expect(matched).length(allGrantOptions.length); + expect(matched).length(grantOptionsTM.length); const allAreTampermonkeyHeaders = matched.every((grant) => grantsTM.includes( @@ -152,7 +176,10 @@ describe("main", () => { describe("Tampermonkey", async () => { const artefacts: string[] = []; - const directCommon: GeneratorOptions = { ...common, direct: true }; + const directCommon: GeneratorOptions = { + ...common, + direct: true, + }; //make sure test output will be cleared beforeEach(() => artefacts.push(output)); @@ -180,11 +207,11 @@ describe("main", () => { it("@grant headers should be generated", async () => { const content = await generate("tampermonkey", { ...directCommon, - grants: allGrantOptions, + grants: grantOptionsTM, }); const matched = content.match(/@grant\s+(.+)/g) || []; - expect(matched).length(allGrantOptions.length); + expect(matched).length(grantOptionsTM.length); }); it("header names should be equally indented", async () => { @@ -206,6 +233,53 @@ describe("main", () => { }); }); + describe("Greasemonkey", async () => { + const artefacts: string[] = []; + + const directCommon: GeneratorOptions = { + ...common, + direct: true, + }; + + //make sure test output will be cleared + beforeEach(() => artefacts.push(output)); + + afterEach(() => { + Promise.all(artefacts.map(unlink)); + artefacts.length = 0; + }); + + it("headers are generated correctly", async () => { + const content = await generate("greasemonkey", directCommon); + expect(!!content).to.be.true; + }); + + it("@match headers should be generated", async () => { + const content = await generate("greasemonkey", { + ...directCommon, + matches: allMatches, + }); + + const matched = content.match(/@match\s+(.+)/g) || []; + expect(matched).length(allMatches.length); + }); + + it("@grant headers should be generated", async () => { + const content = await generate("greasemonkey", { + ...directCommon, + grants: grantOptionsGM, + }); + + const matched = content.match(/@grant\s+(.+)/g) || []; + expect(matched).length(grantOptionsGM.length); + + grantsGM.forEach((grant) => { + expect(new RegExp(`\\b${grant}\\b`, "m").test(grant)).to.be + .true; + }); + }); + }); + describe.skip("ViolentMonkey", async () => { //TODO: add once other commands ready }); diff --git a/test/utils.spec.ts b/test/utils.spec.ts index b16e9fc..a6c5cee 100644 --- a/test/utils.spec.ts +++ b/test/utils.spec.ts @@ -15,16 +15,20 @@ describe("validators", () => { ]; it("should correctly validate valid headers", () => { - const valid = validateMatchHeaders(sampleMatches); - expect(valid).to.be.true; + const { status, invalid } = validateMatchHeaders(sampleMatches); + expect(status).to.be.true; + expect(invalid).to.be.empty; }); it("should correctly validate invalid headers", () => { - const valid = validateMatchHeaders([ + const typo = "http//typo.ed/*"; + + const { status, invalid } = validateMatchHeaders([ ...sampleMatches, - "http//typo.ed/*", + typo, ]); - expect(valid).to.be.false; + expect(status).to.be.false; + expect(invalid).to.contain(typo); }); }); });