Skip to content

fix: add checks for preventing HSL colors from entering React state #9893

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Sep 27, 2023
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
Prev Previous commit
chore: add tests for colors
  • Loading branch information
Parkreiner committed Sep 27, 2023
commit f5fd404daf2ba14c0879eb8d6e46f8c96d709ac3
81 changes: 81 additions & 0 deletions site/src/utils/colors.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* Not testing hslToHex, because it's code directly copied from a reliable
* source
*/
import { isHslColor, isHexColor } from "./colors";

describe(`${isHslColor.name}`, () => {
it("Should reject obviously wrong or malformed inputs", () => {
const wrongInputs = [
"",
"Hi :)",
"hsl",
"#333",
"#444666",
"rgb(255, 300, 299)",
"hsl(255deg, 10%, 20%",
"hsv(255deg, 10%, 20%)",
"hsb(255deg, 10%, 20%)",
"hsl(0%, 10deg, 20)",
];

for (const str of wrongInputs) {
expect(isHslColor(str)).toBe(false);
}
});

it("Should allow strings with or without deg unit", () => {
const base = "hsl(200deg, 100%, 37%)";
expect(isHslColor(base)).toBe(true);

const withoutDeg = base.replace("deg", "");
expect(isHslColor(withoutDeg)).toBe(true);
});

it("Should not care about whether there are spaces separating the inner values", () => {
const inputs = [
"hsl(180deg,20%,97%)",
"hsl(180deg, 20%, 97%)",
"hsl(180deg, 20%, 97%)",
];

for (const str of inputs) {
expect(isHslColor(str)).toBe(true);
}
});

it("Should reject HSL strings that don't have percents for saturation/luminosity values", () => {
expect(isHslColor("hsl(20%, 45, 92)")).toBe(false);
});

it("Should catch HSL strings that follow the correct pattern, but have impossible values", () => {
const inputs = [
"hsl(360deg, 120%, 240%)", // Impossible hue
"hsl(100deg, 120%, 84%)", // Impossible saturation
"hsl(257, 12%, 110%)", // Impossible luminosity
"hsl(360deg, 120%, 240%)", // Impossible everything
];

for (const str of inputs) {
expect(isHslColor(str)).toBe(false);
}
});
});

describe(`${isHexColor.name}`, () => {
it("Should reject obviously wrong or malformed inputs", () => {
const inputs = ["", "#", "#bananas", "#ZZZZZZ", "AB179C", "#55555"];

for (const str of inputs) {
expect(isHexColor(str)).toBe(false);
}
});

it("Should be fully case-insensitive", () => {
const inputs = ["#aaaaaa", "#BBBBBB", "#CcCcCc"];

for (const str of inputs) {
expect(isHexColor(str)).toBe(true);
}
});
});
8 changes: 5 additions & 3 deletions site/src/utils/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ const hexMatcher = /^#[0-9A-Fa-f]{6}$/;
* Mainly here to validate input before sending it to the server.
*/
export function isHexColor(input: string): boolean {
return hexMatcher.test(input);
// Length check isn't necessary; it's just an fast way to validate before
// kicking things off to the slower regex check
return input.length === 7 && hexMatcher.test(input);
}

/**
Expand Down Expand Up @@ -41,7 +43,7 @@ export function isHslColor(input: string): boolean {
}

const hueN = Number(hue);
if (!Number.isInteger(hueN) || hueN < 0 || hueN >= 360) {
if (!Number.isInteger(hueN) || hueN < 0 || hueN > 359) {
return false;
}

Expand All @@ -50,7 +52,7 @@ export function isHslColor(input: string): boolean {
return false;
}

const lumN = Number(sat);
const lumN = Number(lum);
if (!Number.isInteger(lumN) || lumN < 0 || lumN > 100) {
return false;
}
Expand Down