Skip to content
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

test: add missing utils tests #2199

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
13 changes: 8 additions & 5 deletions src/common/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ function kFormatter(num) {
*
* @param {string} hexColor String to check.
* @returns {boolean} True if the given string is a valid hex color.
*
* @description: Tests color codes without the hash (#) prefix.
*/
function isValidHexColor(hexColor) {
return new RegExp(
Expand Down Expand Up @@ -122,7 +124,8 @@ function clampValue(number, min, max) {
* @returns {boolean} True if the given string is a valid gradient.
*/
function isValidGradient(colors) {
return isValidHexColor(colors[1]) && isValidHexColor(colors[2]);
if (isNaN(colors[0])) return false;
return colors.slice(1).every((color) => isValidHexColor(color));
}

/**
Expand Down Expand Up @@ -170,8 +173,8 @@ function request(data, headers) {
* @param {object} props Function properties.
* @param {string[]} props.items Array of items to layout.
* @param {number} props.gap Gap between items.
* @param {number[]?=} props.sizes Array of sizes for each item.
* @param {"column" | "row"?=} props.direction Direction to layout items.
* @param {number[]?=} props.sizes Array of sizes for each item.
* @returns {string[]} Array of items with proper layout.
*/
function flexLayout({ items, gap, direction, sizes = [] }) {
Expand Down Expand Up @@ -379,12 +382,12 @@ function measureText(str, fontSize = 10) {
const lowercaseTrim = (name) => name.toLowerCase().trim();

/**
* Split array of languages in two columns.
* Split array of languages in columns.
*
* @template T Langauge object.
* @param {Array<T>} arr Array of languages.
* @param {number} perChunk Number of languages per column.
* @returns {Array<T>} Array of languages split in two columns.
* @returns {Array<T>} Array of languages split in columns.
*/
function chunkArray(arr, perChunk) {
return arr.reduce((resultArray, item, index) => {
Expand All @@ -408,7 +411,7 @@ function chunkArray(arr, perChunk) {
*/
function parseEmojis(str) {
if (!str) throw new Error("[parseEmoji]: str argument not provided");
return str.replace(/:\w+:/gm, (emoji) => {
return str.replace(/:[\w+-]+:/gm, (emoji) => {
return toEmoji.get(emoji) || "";
});
}
Expand Down
1 change: 1 addition & 0 deletions tests/card.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ describe("Card", () => {
"#fff",
);
});

it("should render gradient backgrounds", () => {
const { titleColor, textColor, iconColor, bgColor } = getCardColors({
title_color: "f00",
Expand Down
174 changes: 152 additions & 22 deletions tests/utils.test.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,25 @@
import { queryByTestId } from "@testing-library/dom";
import "@testing-library/jest-dom";
import {
chunkArray,
clampValue,
encodeHTML,
fallbackColor,
flexLayout,
getCardColors,
isValidGradient,
isValidHexColor,
kFormatter,
lowercaseTrim,
measureText,
parseArray,
parseBoolean,
parseEmojis,
renderError,
wrapTextMultiline,
} from "../src/common/utils.js";

describe("Test utils.js", () => {
it("should test kFormatter", () => {
expect(kFormatter(1)).toBe(1);
expect(kFormatter(-1)).toBe(-1);
expect(kFormatter(500)).toBe(500);
expect(kFormatter(1000)).toBe("1k");
expect(kFormatter(10000)).toBe("10k");
expect(kFormatter(12345)).toBe("12.3k");
expect(kFormatter(9900000)).toBe("9900k");
});

it("should test encodeHTML", () => {
expect(encodeHTML(`<html>hello world<,.#4^&^@%!))`)).toBe(
"&#60;html&#62;hello world&#60;,.#4^&#38;^@%!))",
);
});

it("should test renderError", () => {
document.body.innerHTML = renderError("Something went wrong");
expect(
Expand All @@ -44,6 +39,111 @@ describe("Test utils.js", () => {
).toHaveTextContent(/Secondary Message/gim);
});

it("should test encodeHTML", () => {
expect(encodeHTML(`<html>hello world<,.#4^&^@%!))`)).toBe(
"&#60;html&#62;hello world&#60;,.#4^&#38;^@%!))",
);
});

it("should test kFormatter", () => {
expect(kFormatter(1)).toBe(1);
expect(kFormatter(-1)).toBe(-1);
expect(kFormatter(500)).toBe(500);
expect(kFormatter(1000)).toBe("1k");
expect(kFormatter(10000)).toBe("10k");
expect(kFormatter(12345)).toBe("12.3k");
expect(kFormatter(9900000)).toBe("9900k");
});

it("should test isValidHexColor", () => {
expect(isValidHexColor("00f000")).toBe(true);
expect(isValidHexColor("00f0003f")).toBe(true);
expect(isValidHexColor("0f03")).toBe(true);
expect(isValidHexColor("0f0")).toBe(true);

expect(isValidHexColor("00f00X")).toBe(false);
expect(isValidHexColor("#")).toBe(false);
expect(isValidHexColor("")).toBe(false);
expect(isValidHexColor("0")).toBe(false);
expect(isValidHexColor("00")).toBe(false);
expect(isValidHexColor("00f00")).toBe(false);
expect(isValidHexColor("00f00")).toBe(false);
});

it("should test parseBoolean", () => {
expect(parseBoolean(true)).toBe(true);
expect(parseBoolean(false)).toBe(false);

expect(parseBoolean("true")).toBe(true);
expect(parseBoolean("false")).toBe(false);

expect(parseBoolean(undefined)).toBe(undefined);
});

it("should test parseArray", () => {
expect(parseArray("1")).toEqual(["1"]);
expect(parseArray("1,2,3")).toEqual(["1", "2", "3"]);
expect(parseArray("test")).toEqual(["test"]);
});

it("should test clampValue", () => {
expect(clampValue(1, 0, 2)).toBe(1);
expect(clampValue(1, 2, 3)).toBe(2);
expect(clampValue(1, 0, 0)).toBe(0);
expect(clampValue(1, 0, -1)).toBe(0);
});

it("should test isValidGradient", () => {
expect(isValidGradient(["90", "fff", "000"])).toBe(true);
expect(isValidGradient(["90", "fff", "000", "fff"])).toBe(true);

expect(isValidGradient(["fff", "fff", "fxf"])).toBe(false);
expect(isValidGradient(["90", "fff", "fxf"])).toBe(false);
expect(isValidGradient(["90", "fxf", ""])).toBe(false);
});

it("should test fallbackColor", () => {
expect(fallbackColor("fff", "000")).toBe("#fff");
expect(fallbackColor("fxf", "#000")).toBe("#000");
expect(fallbackColor("90,fff,000", "#000")).toStrictEqual([
"90",
"fff",
"000",
]);
expect(fallbackColor("90,fff,fxf", "#000")).toBe("#000");
});

it("should test flexLayout", () => {
const items = Array(2).fill(`<g></g>`);

const columnLayout = flexLayout({
items,
gap: 25,
direction: "column",
sizes: [],
});
expect(columnLayout[0]).toContain("translate(0, 0)");
expect(columnLayout[1]).toContain("translate(0, 25)");

const rowLayout = flexLayout({
items,
gap: 25,
direction: "row",
sizes: [],
});
expect(rowLayout[0]).toContain("translate(0, 0)");
expect(rowLayout[1]).toContain("translate(25, 0)");

const sizedLayout = flexLayout({
items,
gap: 25,
direction: "row",
sizes: [25, 0],
});
expect(sizedLayout[0]).toContain("translate(0, 0)");
expect(sizedLayout[1]).toContain("translate(50, 0)");
});

it("getCardColors: should return expected values", () => {
let colors = getCardColors({
title_color: "f00",
Expand Down Expand Up @@ -92,36 +192,66 @@ describe("Test utils.js", () => {
borderColor: "#e4e2e2",
});
});
});

describe("wrapTextMultiline", () => {
it("should not wrap small texts", () => {
it("wrapTextMultiline: should not wrap small texts", () => {
{
let multiLineText = wrapTextMultiline("Small text should not wrap");
expect(multiLineText).toEqual(["Small text should not wrap"]);
}
});
it("should wrap large texts", () => {

it("wrapTextMultiline: should wrap large texts", () => {
let multiLineText = wrapTextMultiline(
"Hello world long long long text",
20,
3,
);
expect(multiLineText).toEqual(["Hello world long", "long long text"]);
});
it("should wrap large texts and limit max lines", () => {

it("wrapTextMultiline: should wrap large texts and limit max lines", () => {
let multiLineText = wrapTextMultiline(
"Hello world long long long text",
10,
2,
);
expect(multiLineText).toEqual(["Hello", "world long..."]);
});
it("should wrap chinese by punctuation", () => {

it("wrapTextMultiline: should wrap chinese by punctuation", () => {
let multiLineText = wrapTextMultiline(
"专门为刚开始刷题的同学准备的算法基地,没有最细只有更细,立志用动画将晦涩难懂的算法说的通俗易懂!",
);
expect(multiLineText.length).toEqual(3);
expect(multiLineText[0].length).toEqual(18 * 8); // &#xxxxx; x 8
});

it("should test measureText", () => {
expect(measureText("test")).toEqual(16.078125);

expect(measureText("test", 12)).toEqual(19.293750000000003);
});

it("should test lowercaseTrim", () => {
expect(lowercaseTrim("test")).toEqual("test");
expect(lowercaseTrim(" test ")).toEqual("test");
expect(lowercaseTrim(" Test ")).toEqual("test");
});

it("should test chunkArray", () => {
expect(chunkArray([1, 2, 3], 1)).toEqual([[1], [2], [3]]);
expect(chunkArray([1, 2, 3, 4, 5], 2)).toEqual([[1, 2], [3, 4], [5]]);
expect(chunkArray([1, 2, 3, 4, 5, 6, 7], 3)).toEqual([
[1, 2, 3],
[4, 5, 6],
[7],
]);
});

it("should test parseEmojis", () => {
expect(parseEmojis("test")).toEqual("test");
expect(parseEmojis("test :smile:")).toEqual("test 😄");
expect(parseEmojis("test :smile: :+1:")).toEqual("test 😄 👍");
expect(parseEmojis("test :smile: :+1: :smile:")).toEqual("test 😄 👍 😄");
});
});