import dayjs from "dayjs"; import libxmljs from "libxmljs2"; import { ColorOverridingIcon, HOLI_COLORS, Icon, makeFestive, SvgIcon, Transformation, } from "../src/icon"; describe("SvgIcon", () => { const xmlTidy = (xml: string) => libxmljs.parseXmlString(xml, { noblanks: true, net: false }).toString(); const svgIcon24 = ` `; const svgIcon128 = ` `; describe("with no transformation", () => { it("should be the same", () => { expect(new SvgIcon(svgIcon24).toString()).toEqual(xmlTidy(svgIcon24)); }); }); describe("with a view port increase", () => { describe("of 50%", () => { describe("when the viewPort is of size 0 0 24 24", () => { it("should resize the viewPort", () => { expect( new SvgIcon(svgIcon24) .with({ viewPortIncreasePercent: 50 }) .toString() ).toEqual( xmlTidy(` `) ); }); }); describe("when the viewPort is of size 0 0 128 128", () => { it("should resize the viewPort", () => { expect( new SvgIcon(svgIcon128) .with({ viewPortIncreasePercent: 50 }) .toString() ).toEqual( xmlTidy(` `) ); }); }); }); describe("of 0%", () => { it("should do nothing", () => { expect( new SvgIcon(svgIcon24).with({ viewPortIncreasePercent: 0 }).toString() ).toEqual(xmlTidy(svgIcon24)); }); }); }); describe("background color", () => { describe("with no viewPort increase", () => { it("should add a rectangle the same size as the original viewPort", () => { expect( new SvgIcon(svgIcon24).with({ backgroundColor: "red" }).toString() ).toEqual( xmlTidy(` `) ); }); }); describe("with a viewPort increase", () => { it("should add a rectangle the same size as the original viewPort", () => { expect( new SvgIcon(svgIcon24) .with({ backgroundColor: "pink", viewPortIncreasePercent: 50 }) .toString() ).toEqual( xmlTidy(` `) ); }); }); describe("of undefined", () => { it("should not do anything", () => { expect( new SvgIcon(svgIcon24) .with({ backgroundColor: undefined }) .toString() ).toEqual( xmlTidy(` `) ); }); }); describe("multiple times", () => { it("should use the most recent", () => { expect( new SvgIcon(svgIcon24) .with({ backgroundColor: "green" }) .with({ backgroundColor: "red" }) .toString() ).toEqual( xmlTidy(` `) ); }); }); }); describe("foreground color", () => { describe("with no viewPort increase", () => { it("should add a rectangle the same size as the original viewPort", () => { expect( new SvgIcon(svgIcon24).with({ foregroundColor: "red" }).toString() ).toEqual( xmlTidy(` `) ); }); }); describe("with a viewPort increase", () => { it("should add a rectangle the same size as the original viewPort", () => { expect( new SvgIcon(svgIcon24) .with({ foregroundColor: "pink", viewPortIncreasePercent: 50 }) .toString() ).toEqual( xmlTidy(` `) ); }); }); describe("of undefined", () => { it("should not do anything", () => { expect( new SvgIcon(svgIcon24) .with({ foregroundColor: undefined }) .toString() ).toEqual( xmlTidy(` `) ); }); }); describe("mutliple times", () => { it("should use the most recent", () => { expect( new SvgIcon(svgIcon24) .with({ foregroundColor: "blue" }) .with({ foregroundColor: "red" }) .toString() ).toEqual( xmlTidy(` `) ); }); }); }); }); class DummyIcon implements Icon { transformation: Partial; constructor(transformation: Partial) { this.transformation = transformation; } public with = (newTransformation: Partial) => new DummyIcon({ ...this.transformation, ...newTransformation }); public toString = () => JSON.stringify(this); } describe("ColorOverridingIcon", () => { describe("when the rule matches", () => { const icon = new DummyIcon({ backgroundColor: "black", foregroundColor: "black", }); const overriding = new ColorOverridingIcon( icon, () => true, () => ({ backgroundColor: "blue", foregroundColor: "red" }) ); describe("with", () => { it("should be the with of the underlieing icon with the overriden colors", () => { const result = overriding.with({ viewPortIncreasePercent: 99, backgroundColor: "shouldBeIgnored", foregroundColor: "shouldBeIgnored", }) as DummyIcon; expect(result.transformation).toEqual({ viewPortIncreasePercent: 99, backgroundColor: "blue", foregroundColor: "red", }); }); }); describe("toString", () => { it("should be the toString of the underlieing icon with the overriden colors", () => { expect(overriding.toString()).toEqual( new DummyIcon({ backgroundColor: "blue", foregroundColor: "red", }).toString() ); }); }); }); describe("when the rule doesnt match", () => { const icon = new DummyIcon({ backgroundColor: "black", foregroundColor: "black", }); const overriding = new ColorOverridingIcon( icon, () => false, () => ({ backgroundColor: "blue", foregroundColor: "red" }) ); describe("with", () => { it("should use the provided transformation", () => { const result = overriding.with({ viewPortIncreasePercent: 88, backgroundColor: "shouldBeUsed", foregroundColor: "shouldBeUsed", }) as DummyIcon; expect(result.transformation).toEqual({ viewPortIncreasePercent: 88, backgroundColor: "shouldBeUsed", foregroundColor: "shouldBeUsed", }); }); }); describe("toString", () => { it("should be the toString of the unchanged icon", () => { expect(overriding.toString()).toEqual(icon.toString()); }); }); }); }); describe("makeFestive", () => { const icon = new DummyIcon({ backgroundColor: "black", foregroundColor: "black", }); let now = dayjs(); const festiveIcon = makeFestive(icon, { now: () => now }) describe("on a non special day", () => { beforeEach(() => { now = dayjs("2022/10/12"); }); it("should use the given colors", () => { const result = festiveIcon.with({ viewPortIncreasePercent: 88, backgroundColor: "shouldBeUsed", foregroundColor: "shouldBeUsed", }) as DummyIcon; expect(result.transformation).toEqual({ viewPortIncreasePercent: 88, backgroundColor: "shouldBeUsed", foregroundColor: "shouldBeUsed", }); }); }); describe("on christmas day", () => { beforeEach(() => { now = dayjs("2022/12/25"); }); it("should use the given colors", () => { const result = festiveIcon.with({ viewPortIncreasePercent: 25, backgroundColor: "shouldNotBeUsed", foregroundColor: "shouldNotBeUsed", }) as DummyIcon; expect(result.transformation).toEqual({ viewPortIncreasePercent: 25, backgroundColor: "green", foregroundColor: "red", }); }); }); describe("on halloween", () => { beforeEach(() => { now = dayjs("2022/10/31"); }); it("should use the given colors", () => { const result = festiveIcon.with({ viewPortIncreasePercent: 12, backgroundColor: "shouldNotBeUsed", foregroundColor: "shouldNotBeUsed", }) as DummyIcon; expect(result.transformation).toEqual({ viewPortIncreasePercent: 12, backgroundColor: "orange", foregroundColor: "black", }); }); }); describe("on cny", () => { beforeEach(() => { now = dayjs("2022/02/01"); }); it("should use the given colors", () => { const result = festiveIcon.with({ viewPortIncreasePercent: 12, backgroundColor: "shouldNotBeUsed", foregroundColor: "shouldNotBeUsed", }) as DummyIcon; expect(result.transformation).toEqual({ viewPortIncreasePercent: 12, backgroundColor: "red", foregroundColor: "yellow", }); }); }); describe("on holi", () => { beforeEach(() => { now = dayjs("2022/03/18"); }); it("should use the given colors", () => { const result = festiveIcon.with({ viewPortIncreasePercent: 12, backgroundColor: "shouldNotBeUsed", foregroundColor: "shouldNotBeUsed", }) as DummyIcon; expect(result.transformation.viewPortIncreasePercent).toEqual(12); expect(HOLI_COLORS.includes(result.transformation.backgroundColor!)).toEqual(true); expect(HOLI_COLORS.includes(result.transformation.foregroundColor!)).toEqual(true); expect(result.transformation.backgroundColor).not.toEqual(result.transformation.foregroundColor); }); }); });