Common-color-tests (#23258)

This commit is contained in:
Wendelin 2024-12-12 14:44:17 +01:00 committed by GitHub
parent 145a536156
commit 27ce395d68
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 282 additions and 19 deletions

View File

@ -90,9 +90,9 @@ export const lab2rgb = (
x = Xn * lab_xyz(x); x = Xn * lab_xyz(x);
z = Zn * lab_xyz(z); z = Zn * lab_xyz(z);
const r = xyz_rgb(3.2404542 * x - 1.5371385 * y - 0.4985314 * z); // D65 -> sRGB const r = Math.round(xyz_rgb(3.2404542 * x - 1.5371385 * y - 0.4985314 * z)); // D65 -> sRGB
const g = xyz_rgb(-0.969266 * x + 1.8760108 * y + 0.041556 * z); const g = Math.round(xyz_rgb(-0.969266 * x + 1.8760108 * y + 0.041556 * z));
const b_ = xyz_rgb(0.0556434 * x - 0.2040259 * y + 1.0572252 * z); const b_ = Math.round(xyz_rgb(0.0556434 * x - 0.2040259 * y + 1.0572252 * z));
return [r, g, b_]; return [r, g, b_];
}; };

View File

@ -8,9 +8,9 @@ export const temperature2rgb = (
): [number, number, number] => { ): [number, number, number] => {
const value = temperature / 100; const value = temperature / 100;
return [ return [
temperatureRed(value), Math.round(temperatureRed(value)),
temperatureGreen(value), Math.round(temperatureGreen(value)),
temperatureBlue(value), Math.round(temperatureBlue(value)),
]; ];
}; };
@ -59,10 +59,10 @@ const matchMaxScale = (
}; };
export const mired2kelvin = (miredTemperature: number) => export const mired2kelvin = (miredTemperature: number) =>
Math.floor(1000000 / miredTemperature); miredTemperature === 0 ? 1000000 : Math.floor(1000000 / miredTemperature);
export const kelvin2mired = (kelvintTemperature: number) => export const kelvin2mired = (kelvinTemperature: number) =>
Math.floor(1000000 / kelvintTemperature); kelvinTemperature === 0 ? 1000000 : Math.floor(1000000 / kelvinTemperature);
export const rgbww2rgb = ( export const rgbww2rgb = (
rgbww: [number, number, number, number, number], rgbww: [number, number, number, number, number],

View File

@ -14,8 +14,8 @@ export const hexBlend = (c1: string, c2: string, blend = 50): string => {
c1 = expandHex(c1); c1 = expandHex(c1);
c2 = expandHex(c2); c2 = expandHex(c2);
for (let i = 0; i <= 5; i += 2) { for (let i = 0; i <= 5; i += 2) {
const h1 = parseInt(c1.substr(i, 2), 16); const h1 = parseInt(c1.substring(i, i + 2), 16);
const h2 = parseInt(c2.substr(i, 2), 16); const h2 = parseInt(c2.substring(i, i + 2), 16);
let hex = Math.floor(h2 + (h1 - h2) * (blend / 100)).toString(16); let hex = Math.floor(h2 + (h1 - h2) * (blend / 100)).toString(16);
while (hex.length < 2) hex = "0" + hex; while (hex.length < 2) hex = "0" + hex;
color += hex; color += hex;

View File

@ -1,12 +1,13 @@
// From https://github.com/gka/chroma.js // From https://github.com/gka/chroma.js
// Copyright (c) 2011-2019, Gregor Aisch // Copyright (c) 2011-2019, Gregor Aisch
export const labDarken = ( export type LabColor = [number, number, number];
lab: [number, number, number],
amount = 1
): [number, number, number] => [lab[0] - 18 * amount, lab[1], lab[2]];
export const labBrighten = ( export const labDarken = (lab: LabColor, amount = 1): LabColor => [
lab: [number, number, number], lab[0] - 18 * amount,
amount = 1 lab[1],
): [number, number, number] => labDarken(lab, -amount); lab[2],
];
export const labBrighten = (lab: LabColor, amount = 1): LabColor =>
labDarken(lab, -amount);

View File

@ -0,0 +1,35 @@
import { describe, test, expect } from "vitest";
import {
getColorByIndex,
getGraphColorByIndex,
COLORS,
} from "../../../src/common/color/colors";
import { theme2hex } from "../../../src/common/color/convert-color";
describe("getColorByIndex", () => {
test("return the correct color for a given index", () => {
expect(getColorByIndex(0)).toBe(COLORS[0]);
expect(getColorByIndex(10)).toBe(COLORS[10]);
});
test("wrap around if the index is greater than the length of COLORS", () => {
expect(getColorByIndex(COLORS.length)).toBe(COLORS[0]);
expect(getColorByIndex(COLORS.length + 4)).toBe(COLORS[4]);
});
});
describe("getGraphColorByIndex", () => {
test("return the correct theme color if it exists", () => {
const style = {
getPropertyValue: (prop) => (prop === "--graph-color-1" ? "#123456" : ""),
} as CSSStyleDeclaration;
expect(getGraphColorByIndex(0, style)).toBe(theme2hex("#123456"));
});
test("return the default color if the theme color does not exist", () => {
const style = {
getPropertyValue: () => "",
} as unknown as CSSStyleDeclaration;
expect(getGraphColorByIndex(0, style)).toBe(theme2hex(COLORS[0]));
});
});

View File

@ -0,0 +1,18 @@
import { describe, it, expect } from "vitest";
import {
computeCssColor,
THEME_COLORS,
} from "../../../src/common/color/compute-color";
describe("computeCssColor", () => {
it("should return CSS variable for theme colors", () => {
THEME_COLORS.forEach((color) => {
expect(computeCssColor(color)).toBe(`var(--${color}-color)`);
});
});
it("should return the input color if it is not a theme color", () => {
const nonThemeColor = "non-theme-color";
expect(computeCssColor(nonThemeColor)).toBe(nonThemeColor);
});
});

View File

@ -0,0 +1,54 @@
import { describe, it, expect } from "vitest";
import {
hex2rgb,
rgb2hex,
rgb2lab,
lab2rgb,
lab2hex,
rgb2hsv,
hsv2rgb,
rgb2hs,
hs2rgb,
theme2hex,
} from "../../../src/common/color/convert-color";
describe("Color Conversion Tests", () => {
it("should convert hex to rgb", () => {
expect(hex2rgb("#ffffff")).toEqual([255, 255, 255]);
expect(hex2rgb("#000000")).toEqual([0, 0, 0]);
});
it("should convert rgb to hex", () => {
expect(rgb2hex([255, 255, 255])).toBe("#ffffff");
expect(rgb2hex([0, 0, 0])).toBe("#000000");
});
it("should convert rgb to lab and back", () => {
const rgb: [number, number, number] = [12, 206, 7];
const lab = rgb2lab(rgb);
expect(lab2rgb(lab)).toEqual(rgb);
});
it("should convert lab to hex", () => {
const lab: [number, number, number] = [53.23288, 80.10933, 67.22006];
expect(lab2hex(lab)).toBe("#ff0000");
});
it("should convert rgb to hsv and back", () => {
const rgb: [number, number, number] = [255, 0, 0];
const hsv = rgb2hsv(rgb);
expect(hsv2rgb(hsv)).toEqual(rgb);
});
it("should convert rgb to hs and back", () => {
const rgb: [number, number, number] = [255, 0, 0];
const hs = rgb2hs(rgb);
expect(hs2rgb(hs)).toEqual([255, 0, 0]);
});
it("should convert theme color to hex", () => {
expect(theme2hex("red")).toBe("#ff0000");
expect(theme2hex("#ff0000")).toBe("#ff0000");
expect(theme2hex("unicorn")).toBe("unicorn");
});
});

View File

@ -0,0 +1,50 @@
import { describe, it, expect } from "vitest";
import {
temperature2rgb,
mired2kelvin,
kelvin2mired,
rgbww2rgb,
rgbw2rgb,
} from "../../../src/common/color/convert-light-color";
describe("temperature2rgb", () => {
it("should convert temperature to RGB", () => {
expect(temperature2rgb(6600)).toEqual([255, 255, 255]);
expect(temperature2rgb(6601)).toEqual([255, 252, 255]);
expect(temperature2rgb(1900)).toEqual([255, 132, 0]);
});
});
describe("mired2kelvin", () => {
it("should convert mired to kelvin", () => {
expect(mired2kelvin(20)).toBe(50000);
expect(mired2kelvin(0)).toBe(1000000);
});
});
describe("kelvin2mired", () => {
it("should convert kelvin to mired", () => {
expect(kelvin2mired(6500)).toBe(153);
expect(kelvin2mired(2700)).toBe(370);
expect(kelvin2mired(0)).toBe(1000000);
});
});
describe("rgbww2rgb", () => {
it("should convert RGBWW to RGB", () => {
expect(rgbww2rgb([255, 0, 0, 255, 0])).toEqual([255, 128, 126]);
expect(rgbww2rgb([0, 255, 0, 0, 255])).toEqual([154, 255, 53]);
expect(rgbww2rgb([255, 0, 0, 255, 128], 1000)).toEqual([255, 75, 25]);
expect(rgbww2rgb([255, 0, 0, 255, 128], undefined, 5000)).toEqual([
255, 102, 81,
]);
expect(rgbww2rgb([255, 0, 0, 255, 128], 3000, 4000)).toEqual([255, 98, 73]);
});
});
describe("rgbw2rgb", () => {
it("should convert RGBW to RGB", () => {
expect(rgbw2rgb([255, 0, 0, 255])).toEqual([255, 128, 128]);
expect(rgbw2rgb([0, 255, 0, 0])).toEqual([0, 255, 0]);
});
});

View File

@ -0,0 +1,30 @@
import { describe, it, expect } from "vitest";
import { expandHex, hexBlend } from "../../../src/common/color/hex";
describe("expandHex", () => {
it("should expand a 3-digit hex code to 6 digits", () => {
expect(expandHex("#abc")).toBe("aabbcc");
});
it("should return a 6-digit hex code unchanged", () => {
expect(expandHex("#abcdef")).toBe("abcdef");
});
});
describe("hexBlend", () => {
it("should blend two hex colors with default blend value", () => {
expect(hexBlend("#000000", "#ffffff")).toBe("#7f7f7f");
});
it("should blend two hex colors with a specified blend value", () => {
expect(hexBlend("#ff0000", "#0000ff", 25)).toBe("#3f00bf");
});
it("should return the first color if blend is 100", () => {
expect(hexBlend("#ff0000", "#0000ff", 100)).toBe("#ff0000");
});
it("should return the second color if blend is 0", () => {
expect(hexBlend("#ff0000", "#0000ff", 0)).toBe("#0000ff");
});
});

View File

@ -0,0 +1,34 @@
import { describe, it, expect } from "vitest";
import {
labDarken,
labBrighten,
type LabColor,
} from "../../../src/common/color/lab";
describe("labDarken", () => {
it("should darken the color by the default amount", () => {
const lab: LabColor = [50, 20, 30];
const result = labDarken(lab);
expect(result).toEqual([32, 20, 30]);
});
it("should darken the color by a specified amount", () => {
const lab: LabColor = [50, 20, 30];
const result = labDarken(lab, 2);
expect(result).toEqual([14, 20, 30]);
});
});
describe("labBrighten", () => {
it("should brighten the color by the default amount", () => {
const lab: LabColor = [50, 20, 30];
const result = labBrighten(lab);
expect(result).toEqual([68, 20, 30]);
});
it("should brighten the color by a specified amount", () => {
const lab: LabColor = [50, 20, 30];
const result = labBrighten(lab, 2);
expect(result).toEqual([86, 20, 30]);
});
});

View File

@ -0,0 +1,41 @@
import { describe, it, expect } from "vitest";
import {
luminosity,
rgbContrast,
getRGBContrastRatio,
} from "../../../src/common/color/rgb";
describe("luminosity", () => {
it("calculates the correct luminosity for black", () => {
expect(luminosity([0, 0, 0])).toBe(0);
});
it("calculates the correct luminosity for white", () => {
expect(luminosity([255, 255, 255])).toBe(1);
});
it("calculates the correct luminosity for red", () => {
expect(luminosity([255, 0, 0])).toBe(0.2126);
});
});
describe("rgbContrast", () => {
it("calculates the correct contrast ratio between black and white", () => {
expect(rgbContrast([0, 0, 0], [255, 255, 255])).toBe(21);
expect(rgbContrast([255, 255, 255], [0, 0, 0])).toBe(21);
});
it("calculates the correct contrast ratio between red and white", () => {
expect(rgbContrast([255, 0, 0], [255, 255, 255])).toBeCloseTo(4);
});
});
describe("getRGBContrastRatio", () => {
it("calculates the correct rounded contrast ratio between black and white", () => {
expect(getRGBContrastRatio([0, 0, 0], [255, 255, 255])).toBe(21);
});
it("calculates the correct rounded contrast ratio between red and white", () => {
expect(getRGBContrastRatio([255, 0, 0], [255, 255, 255])).toBe(4);
});
});