forked from mirrored/github-readme-stats
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d656449265 | ||
|
|
10d8a68ab7 | ||
|
|
49c0e2da28 | ||
|
|
4a065a36b5 |
+32
-13
@@ -8,7 +8,36 @@ import {
|
|||||||
renderError,
|
renderError,
|
||||||
} from "../src/common/utils.js";
|
} from "../src/common/utils.js";
|
||||||
import { fetchStats } from "../src/fetchers/stats-fetcher.js";
|
import { fetchStats } from "../src/fetchers/stats-fetcher.js";
|
||||||
import { isLocaleAvailable } from "../src/translations.js";
|
import { validateQueryStringParams } from "../src/common/validate.js";
|
||||||
|
|
||||||
|
const QUERYSTRING_PARAMS_DATA_TYPE_MAP = new Map([
|
||||||
|
["username", "string"],
|
||||||
|
["hide", "enum-array"],
|
||||||
|
["hide_title", "boolean"],
|
||||||
|
["hide_border", "boolean"],
|
||||||
|
["card_width", "number"],
|
||||||
|
["hide_rank", "boolean"],
|
||||||
|
["show_icons", "boolean"],
|
||||||
|
["include_all_commits", "boolean"],
|
||||||
|
["line_height", "number"],
|
||||||
|
["title_color", "string"],
|
||||||
|
["ring_color", "string"],
|
||||||
|
["icon_color", "string"],
|
||||||
|
["text_color", "string"],
|
||||||
|
["text_bold", "boolean"],
|
||||||
|
["bg_color", "string"],
|
||||||
|
["theme", "enum"],
|
||||||
|
["cache_seconds", "number"],
|
||||||
|
["exclude_repo", "array"],
|
||||||
|
["custom_title", "string"],
|
||||||
|
["locale", "enum"],
|
||||||
|
["disable_animations", "boolean"],
|
||||||
|
["border_radius", "number"],
|
||||||
|
["border_color", "string"],
|
||||||
|
["number_format", "enum"],
|
||||||
|
["rank_icon", "enum"],
|
||||||
|
["show", "enum-array"],
|
||||||
|
]);
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const {
|
const {
|
||||||
@@ -53,19 +82,9 @@ export default async (req, res) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (locale && !isLocaleAvailable(locale)) {
|
|
||||||
return res.send(
|
|
||||||
renderError("Something went wrong", "Language not found", {
|
|
||||||
title_color,
|
|
||||||
text_color,
|
|
||||||
bg_color,
|
|
||||||
border_color,
|
|
||||||
theme,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
validateQueryStringParams(req.query, QUERYSTRING_PARAMS_DATA_TYPE_MAP);
|
||||||
|
|
||||||
const showStats = parseArray(show);
|
const showStats = parseArray(show);
|
||||||
const stats = await fetchStats(
|
const stats = await fetchStats(
|
||||||
username,
|
username,
|
||||||
|
|||||||
Vendored
+22
@@ -0,0 +1,22 @@
|
|||||||
|
export type DataTypes =
|
||||||
|
| "enum"
|
||||||
|
| "enum-array"
|
||||||
|
| "array"
|
||||||
|
| "string"
|
||||||
|
| "boolean"
|
||||||
|
| "number";
|
||||||
|
|
||||||
|
export function validateQueryStringParam(
|
||||||
|
expectedDataType: DateTypes,
|
||||||
|
param: string,
|
||||||
|
value: string,
|
||||||
|
): boolean;
|
||||||
|
|
||||||
|
export function validateQueryStringParams(
|
||||||
|
queryStringParams: object,
|
||||||
|
queryStringParamsDataTypeMap: Map<string, DataTypes>,
|
||||||
|
): void;
|
||||||
|
|
||||||
|
export class InvalidQueryStringParamsError extends Error {
|
||||||
|
constructor(message: string, secondaryMessage: string);
|
||||||
|
}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
import { availableLocales } from "../translations.js";
|
||||||
|
import { themes } from "../../themes/index.js";
|
||||||
|
import { parseArray } from "./utils.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for handling invalid query string param errors.
|
||||||
|
*/
|
||||||
|
export class InvalidQueryStringParamsError extends Error {
|
||||||
|
/**
|
||||||
|
* Constructor for InvalidQueryStringParamsError.
|
||||||
|
*
|
||||||
|
* @param {string} message - The error message.
|
||||||
|
* @param {string} secondaryMessage - The secondary error message.
|
||||||
|
*/
|
||||||
|
constructor(message, secondaryMessage) {
|
||||||
|
super(message);
|
||||||
|
this.secondaryMessage = secondaryMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const QUERYSTRING_PARAMS_ENUM_VALUES = {
|
||||||
|
hide: ["stars", "commits", "prs", "issues", "contribs"],
|
||||||
|
theme: Object.keys(themes),
|
||||||
|
locale: availableLocales,
|
||||||
|
number_format: ["short", "long"],
|
||||||
|
rank_icon: ["github", "percentile", "default"],
|
||||||
|
show: [
|
||||||
|
"reviews",
|
||||||
|
"discussions_started",
|
||||||
|
"discussions_answered",
|
||||||
|
"prs_merged",
|
||||||
|
"prs_merged_percentage",
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import("./validate").DataTypes} DataTypes The data types.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the secondary error message for an invalid query string param.
|
||||||
|
*
|
||||||
|
* @param {string} param - The invalid query string param.
|
||||||
|
* @param {Map<string, DataTypes>} queryStringParamsDataTypeMap - The query string params data type map.
|
||||||
|
* @returns {string} The secondary error message.
|
||||||
|
*/
|
||||||
|
const getInvalidQueryStringParamsErrorSecondaryMessage = (
|
||||||
|
param,
|
||||||
|
queryStringParamsDataTypeMap,
|
||||||
|
) => {
|
||||||
|
const expectedDataType = queryStringParamsDataTypeMap.get(param);
|
||||||
|
if (expectedDataType === "enum" || expectedDataType === "enum-array") {
|
||||||
|
return `Expected: ${QUERYSTRING_PARAMS_ENUM_VALUES[param].join(", ")}`;
|
||||||
|
} else if (expectedDataType === "number") {
|
||||||
|
return "Expected: a number";
|
||||||
|
} else if (expectedDataType === "boolean") {
|
||||||
|
return "Expected: true or false";
|
||||||
|
} else if (expectedDataType === "array") {
|
||||||
|
return "Expected: an array";
|
||||||
|
} else if (expectedDataType === "string") {
|
||||||
|
return "Expected: a string";
|
||||||
|
} else {
|
||||||
|
throw new Error("Unexpected behavior");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a query string param.
|
||||||
|
*
|
||||||
|
* @param {DataTypes} expectedDataType - The expected data type of the query string param.
|
||||||
|
* @param {string} param - The query string param.
|
||||||
|
* @param {string} value - The query string param value.
|
||||||
|
* @returns {boolean} Whether the query string param is valid.
|
||||||
|
*/
|
||||||
|
export const validateQueryStringParam = (expectedDataType, param, value) => {
|
||||||
|
if (expectedDataType === "enum") {
|
||||||
|
return QUERYSTRING_PARAMS_ENUM_VALUES[param].includes(value);
|
||||||
|
} else if (expectedDataType === "enum-array") {
|
||||||
|
return parseArray(value).every((value) =>
|
||||||
|
QUERYSTRING_PARAMS_ENUM_VALUES[param].includes(value),
|
||||||
|
);
|
||||||
|
} else if (expectedDataType === "number") {
|
||||||
|
return !isNaN(parseFloat(value));
|
||||||
|
} else if (expectedDataType === "boolean") {
|
||||||
|
return value === "true" || value === "false";
|
||||||
|
} else if (expectedDataType === "array") {
|
||||||
|
return Array.isArray(parseArray(value));
|
||||||
|
} else if (expectedDataType === "string") {
|
||||||
|
return typeof value === "string";
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the query string params.
|
||||||
|
* Throws an error if a query string param is invalid.
|
||||||
|
* Does not return anything.
|
||||||
|
*
|
||||||
|
* @param {object} queryStringParams - The query string params.
|
||||||
|
* @param {Map<string, DataTypes>} queryStringParamsDataTypeMap - The query string params data type map.
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
export const validateQueryStringParams = (
|
||||||
|
queryStringParams,
|
||||||
|
queryStringParamsDataTypeMap,
|
||||||
|
) => {
|
||||||
|
for (const [param, value] of Object.entries(queryStringParams)) {
|
||||||
|
const expectedDataType = queryStringParamsDataTypeMap.get(param);
|
||||||
|
if (!expectedDataType) {
|
||||||
|
// Absence of data type means that the query string param is not supported.
|
||||||
|
// Currently we allow addition of extra query string params.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (validateQueryStringParam(expectedDataType, param, value)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
throw new InvalidQueryStringParamsError(
|
||||||
|
`Invalid query string param \`${param}\` value: ${value}`,
|
||||||
|
getInvalidQueryStringParamsErrorSecondaryMessage(
|
||||||
|
param,
|
||||||
|
queryStringParamsDataTypeMap,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
+10
-6
@@ -6,6 +6,7 @@ import { calculateRank } from "../src/calculateRank.js";
|
|||||||
import { renderStatsCard } from "../src/cards/stats-card.js";
|
import { renderStatsCard } from "../src/cards/stats-card.js";
|
||||||
import { CONSTANTS, renderError } from "../src/common/utils.js";
|
import { CONSTANTS, renderError } from "../src/common/utils.js";
|
||||||
import { expect, it, describe, afterEach } from "@jest/globals";
|
import { expect, it, describe, afterEach } from "@jest/globals";
|
||||||
|
import { availableLocales } from "../src/translations.js";
|
||||||
|
|
||||||
const stats = {
|
const stats = {
|
||||||
name: "Anurag Hazra",
|
name: "Anurag Hazra",
|
||||||
@@ -140,8 +141,8 @@ describe("Test /api/", () => {
|
|||||||
{
|
{
|
||||||
username: "anuraghazra",
|
username: "anuraghazra",
|
||||||
hide: "issues,prs,contribs",
|
hide: "issues,prs,contribs",
|
||||||
show_icons: true,
|
show_icons: "true",
|
||||||
hide_border: true,
|
hide_border: "true",
|
||||||
line_height: 100,
|
line_height: 100,
|
||||||
title_color: "fff",
|
title_color: "fff",
|
||||||
icon_color: "fff",
|
icon_color: "fff",
|
||||||
@@ -270,8 +271,8 @@ describe("Test /api/", () => {
|
|||||||
{
|
{
|
||||||
username: "anuraghazra",
|
username: "anuraghazra",
|
||||||
hide: "issues,prs,contribs",
|
hide: "issues,prs,contribs",
|
||||||
show_icons: true,
|
show_icons: "true",
|
||||||
hide_border: true,
|
hide_border: "true",
|
||||||
line_height: 100,
|
line_height: 100,
|
||||||
title_color: "fff",
|
title_color: "fff",
|
||||||
ring_color: "0000ff",
|
ring_color: "0000ff",
|
||||||
@@ -318,7 +319,10 @@ describe("Test /api/", () => {
|
|||||||
|
|
||||||
expect(res.setHeader).toBeCalledWith("Content-Type", "image/svg+xml");
|
expect(res.setHeader).toBeCalledWith("Content-Type", "image/svg+xml");
|
||||||
expect(res.send).toBeCalledWith(
|
expect(res.send).toBeCalledWith(
|
||||||
renderError("Something went wrong", "Language not found"),
|
renderError(
|
||||||
|
"Invalid query string param `locale` value: asdf",
|
||||||
|
`Expected: ${availableLocales.join(", ")}`,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -328,7 +332,7 @@ describe("Test /api/", () => {
|
|||||||
.reply(200, { error: "Some test error message" });
|
.reply(200, { error: "Some test error message" });
|
||||||
|
|
||||||
const { req, res } = faker(
|
const { req, res } = faker(
|
||||||
{ username: "anuraghazra", include_all_commits: true },
|
{ username: "anuraghazra", include_all_commits: "true" },
|
||||||
data_stats,
|
data_stats,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,256 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
import { expect, it, describe } from "@jest/globals";
|
||||||
|
import {
|
||||||
|
validateQueryStringParam,
|
||||||
|
validateQueryStringParams,
|
||||||
|
InvalidQueryStringParamsError,
|
||||||
|
} from "../src/common/validate";
|
||||||
|
import { themes } from "../themes/index.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import("../src/common/validate").DataTypes} DataTypes The data types.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Map<string, DataTypes>} The query string params data type map.
|
||||||
|
*/
|
||||||
|
const QUERYSTRING_PARAMS_DATA_TYPE_MAP = new Map([
|
||||||
|
["username", "string"],
|
||||||
|
["hide", "enum-array"],
|
||||||
|
["hide_title", "boolean"],
|
||||||
|
["hide_border", "boolean"],
|
||||||
|
["card_width", "number"],
|
||||||
|
["hide_rank", "boolean"],
|
||||||
|
["show_icons", "boolean"],
|
||||||
|
["include_all_commits", "boolean"],
|
||||||
|
["line_height", "number"],
|
||||||
|
["title_color", "string"],
|
||||||
|
["ring_color", "string"],
|
||||||
|
["icon_color", "string"],
|
||||||
|
["text_color", "string"],
|
||||||
|
["text_bold", "boolean"],
|
||||||
|
["bg_color", "string"],
|
||||||
|
["theme", "enum"],
|
||||||
|
["cache_seconds", "number"],
|
||||||
|
["exclude_repo", "array"],
|
||||||
|
["custom_title", "string"],
|
||||||
|
["locale", "enum"],
|
||||||
|
["disable_animations", "boolean"],
|
||||||
|
["border_radius", "number"],
|
||||||
|
["border_color", "string"],
|
||||||
|
["number_format", "enum"],
|
||||||
|
["rank_icon", "enum"],
|
||||||
|
["show", "enum-array"],
|
||||||
|
]);
|
||||||
|
|
||||||
|
describe("test query string param validation", () => {
|
||||||
|
// Tests for `validateQueryStringParam` function.
|
||||||
|
it("should validate a string", () => {
|
||||||
|
expect(validateQueryStringParam("string", "username", "anuraghazra")).toBe(
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("should validate a boolean", () => {
|
||||||
|
expect(validateQueryStringParam("boolean", "hide_title", "true")).toBe(
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(validateQueryStringParam("boolean", "hide_title", "false")).toBe(
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(validateQueryStringParam("boolean", "hide_title", "invalid")).toBe(
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("should validate a number", () => {
|
||||||
|
expect(validateQueryStringParam("number", "card_width", "300")).toBe(true);
|
||||||
|
expect(validateQueryStringParam("number", "card_width", "300.000")).toBe(
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(validateQueryStringParam("number", "card_width", "invalid")).toBe(
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("should validate an enum", () => {
|
||||||
|
expect(validateQueryStringParam("enum", "theme", "dark")).toBe(true);
|
||||||
|
expect(validateQueryStringParam("enum", "theme", "merko")).toBe(true);
|
||||||
|
expect(validateQueryStringParam("enum", "theme", "invalid")).toBe(false);
|
||||||
|
|
||||||
|
expect(validateQueryStringParam("enum", "locale", "en")).toBe(true);
|
||||||
|
expect(validateQueryStringParam("enum", "locale", "invalid")).toBe(false);
|
||||||
|
|
||||||
|
expect(validateQueryStringParam("enum", "number_format", "short")).toBe(
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(validateQueryStringParam("enum", "number_format", "invalid")).toBe(
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(validateQueryStringParam("enum", "rank_icon", "github")).toBe(true);
|
||||||
|
expect(validateQueryStringParam("enum", "rank_icon", "invalid")).toBe(
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("should validate an enum-array", () => {
|
||||||
|
expect(
|
||||||
|
validateQueryStringParam("enum-array", "hide", "stars,commits,prs"),
|
||||||
|
).toBe(true);
|
||||||
|
expect(
|
||||||
|
validateQueryStringParam(
|
||||||
|
"enum-array",
|
||||||
|
"show",
|
||||||
|
"reviews,discussions_started",
|
||||||
|
),
|
||||||
|
).toBe(true);
|
||||||
|
expect(
|
||||||
|
validateQueryStringParam(
|
||||||
|
"enum-array",
|
||||||
|
"hide",
|
||||||
|
"stars,commits,prs,invalid",
|
||||||
|
),
|
||||||
|
).toBe(false);
|
||||||
|
expect(validateQueryStringParam("enum-array", "hide", "invalid")).toBe(
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("should validate an array", () => {
|
||||||
|
expect(
|
||||||
|
validateQueryStringParam("array", "exclude_repo", "repo1,repo2"),
|
||||||
|
).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Tests for `validateQueryStringParams` function.
|
||||||
|
it("should validate query string params", () => {
|
||||||
|
expect(
|
||||||
|
validateQueryStringParams(
|
||||||
|
{
|
||||||
|
username: "anuraghazra",
|
||||||
|
hide: "stars,commits,prs",
|
||||||
|
hide_title: "true",
|
||||||
|
hide_border: "true",
|
||||||
|
card_width: "300",
|
||||||
|
hide_rank: "true",
|
||||||
|
show_icons: "true",
|
||||||
|
include_all_commits: "true",
|
||||||
|
line_height: "25",
|
||||||
|
title_color: "fff",
|
||||||
|
ring_color: "fff",
|
||||||
|
icon_color: "fff",
|
||||||
|
text_color: "fff",
|
||||||
|
text_bold: "true",
|
||||||
|
bg_color: "fff",
|
||||||
|
theme: "dark",
|
||||||
|
cache_seconds: "300",
|
||||||
|
exclude_repo: "repo1,repo2",
|
||||||
|
custom_title: "My Custom Title",
|
||||||
|
locale: "en",
|
||||||
|
disable_animations: "true",
|
||||||
|
border_radius: "0",
|
||||||
|
number_format: "long",
|
||||||
|
border_color: "fff",
|
||||||
|
rank_icon: "github",
|
||||||
|
show: "reviews,discussions_started",
|
||||||
|
},
|
||||||
|
QUERYSTRING_PARAMS_DATA_TYPE_MAP,
|
||||||
|
),
|
||||||
|
// This function returns void on successful run and throws an error on invalid query string params.
|
||||||
|
).toBe(undefined);
|
||||||
|
});
|
||||||
|
it("should validate query string params with extra params", () => {
|
||||||
|
expect(
|
||||||
|
validateQueryStringParams(
|
||||||
|
{
|
||||||
|
username: "anuraghazra",
|
||||||
|
hide: "stars,commits,prs",
|
||||||
|
hide_title: "true",
|
||||||
|
hide_border: "true",
|
||||||
|
card_width: "300",
|
||||||
|
hide_rank: "true",
|
||||||
|
show_icons: "true",
|
||||||
|
include_all_commits: "true",
|
||||||
|
line_height: "25",
|
||||||
|
title_color: "fff",
|
||||||
|
ring_color: "fff",
|
||||||
|
icon_color: "fff",
|
||||||
|
text_color: "fff",
|
||||||
|
text_bold: "true",
|
||||||
|
bg_color: "fff",
|
||||||
|
theme: "dark",
|
||||||
|
cache_seconds: "300",
|
||||||
|
exclude_repo: "repo1,repo2",
|
||||||
|
custom_title: "My Custom Title",
|
||||||
|
locale: "en",
|
||||||
|
disable_animations: "true",
|
||||||
|
border_radius: "0",
|
||||||
|
number_format: "long",
|
||||||
|
border_color: "fff",
|
||||||
|
rank_icon: "github",
|
||||||
|
show: "reviews,discussions_started",
|
||||||
|
invalid: "invalid",
|
||||||
|
},
|
||||||
|
QUERYSTRING_PARAMS_DATA_TYPE_MAP,
|
||||||
|
),
|
||||||
|
// This function returns void on successful run and throws an error on invalid query string params.
|
||||||
|
).toBe(undefined);
|
||||||
|
});
|
||||||
|
it("should throw correct error on invalid boolean param", () => {
|
||||||
|
expect(() =>
|
||||||
|
validateQueryStringParams(
|
||||||
|
{
|
||||||
|
hide_title: "invalid",
|
||||||
|
},
|
||||||
|
QUERYSTRING_PARAMS_DATA_TYPE_MAP,
|
||||||
|
),
|
||||||
|
).toThrow(
|
||||||
|
new InvalidQueryStringParamsError(
|
||||||
|
"Invalid query string param `hide_title` value: invalid",
|
||||||
|
"Expected: true or false",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("should throw correct error on invalid number param", () => {
|
||||||
|
expect(() =>
|
||||||
|
validateQueryStringParams(
|
||||||
|
{
|
||||||
|
card_width: "invalid",
|
||||||
|
},
|
||||||
|
QUERYSTRING_PARAMS_DATA_TYPE_MAP,
|
||||||
|
),
|
||||||
|
).toThrow(
|
||||||
|
new InvalidQueryStringParamsError(
|
||||||
|
"Invalid query string param `card_width` value: invalid",
|
||||||
|
"Expected: a number",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("should throw correct error on invalid enum param", () => {
|
||||||
|
expect(() =>
|
||||||
|
validateQueryStringParams(
|
||||||
|
{
|
||||||
|
theme: "invalid",
|
||||||
|
},
|
||||||
|
QUERYSTRING_PARAMS_DATA_TYPE_MAP,
|
||||||
|
),
|
||||||
|
).toThrow(
|
||||||
|
new InvalidQueryStringParamsError(
|
||||||
|
"Invalid query string param `theme` value: invalid",
|
||||||
|
`Expected: ${Object.keys(themes).join(", ")}`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("should throw correct error on invalid enum-array param", () => {
|
||||||
|
expect(() =>
|
||||||
|
validateQueryStringParams(
|
||||||
|
{
|
||||||
|
hide: "commits,prs,invalid",
|
||||||
|
},
|
||||||
|
QUERYSTRING_PARAMS_DATA_TYPE_MAP,
|
||||||
|
),
|
||||||
|
).toThrow(
|
||||||
|
new InvalidQueryStringParamsError(
|
||||||
|
"Invalid query string param `hide` value: commits,prs,invalid",
|
||||||
|
"Expected: stars, commits, prs, issues, contribs",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user