Skip to content

Commit 976029c

Browse files
authored
Shared configs/workflows/loader (#149)
* use the loader in build * add Logos tests
1 parent a25ba12 commit 976029c

File tree

5 files changed

+353
-1
lines changed

5 files changed

+353
-1
lines changed

apps/nutritionfacts/.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ lerna-debug.log*
1010
node_modules
1111
dist-ssr
1212
dist
13-
coverage
13+
coverage/*
14+
!coverage.yml
1415
*.local
1516

1617
.idea
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
coverage:
2+
totals:
3+
statements: 23.12%
4+
branches: 14.9%
5+
functions: 20.83%
6+
lines: 23.95%
7+
total: 20.7%
8+
src:
9+
totals:
10+
statements: 45.63%
11+
branches: 44.17%
12+
functions: 43.75%
13+
lines: 45.63%
14+
"App.tsx":
15+
statements: 0%
16+
branches: 0%
17+
functions: 0%
18+
lines: 0%
19+
uncovered_line_numbers: "16-64"
20+
Components:
21+
Export:
22+
"ControlButton.tsx":
23+
statements: 0%
24+
branches: 0%
25+
functions: 0%
26+
lines: 0%
27+
uncovered_line_numbers: "13-22"
28+
"Embed.tsx":
29+
statements: 0%
30+
branches: 0%
31+
functions: 0%
32+
lines: 0%
33+
uncovered_line_numbers: "7-67"
34+
"Link.tsx":
35+
statements: 0%
36+
branches: 0%
37+
functions: 0%
38+
lines: 0%
39+
uncovered_line_numbers: "6-40"
40+
Layout:
41+
"Divider.tsx":
42+
statements: 0%
43+
branches: 100%
44+
functions: 0%
45+
lines: 0%
46+
uncovered_line_numbers: "3-4"
47+
"NutritionFactsForm.tsx":
48+
statements: 0%
49+
branches: 0%
50+
functions: 0%
51+
lines: 0%
52+
uncovered_line_numbers: "21-76"
53+
"Presets.tsx":
54+
statements: 0%
55+
branches: 0%
56+
functions: 0%
57+
lines: 0%
58+
uncovered_line_numbers: "22-118"
59+
"extendedNutritionFacts.tsx":
60+
statements: 0%
61+
branches: 0%
62+
functions: 0%
63+
lines: 0%
64+
uncovered_line_numbers: "4-32"
65+
"getLayoutFromParams.ts":
66+
statements: 0%
67+
branches: 0%
68+
functions: 0%
69+
lines: 0%
70+
uncovered_line_numbers: "4-19"
71+
"Main.tsx":
72+
statements: 87.5%
73+
branches: 83.33%
74+
functions: 100%
75+
lines: 87.5%
76+
uncovered_line_numbers: "26"
77+
assets:
78+
"Layout.ts":
79+
statements: 100%
80+
branches: 100%
81+
functions: 100%
82+
lines: 100%
83+
"Logos.tsx":
84+
statements: 100%
85+
branches: 100%
86+
functions: 100%
87+
lines: 100%
88+
"colors.ts":
89+
statements: 100%
90+
branches: 100%
91+
functions: 100%
92+
lines: 100%
93+
"consts.tsx":
94+
statements: 80%
95+
branches: 33.33%
96+
functions: 0%
97+
lines: 80%
98+
uncovered_line_numbers: "64"
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
import { describe, it, expect, vi, beforeEach } from "vitest";
2+
import {
3+
CanvasBug,
4+
IgniteBug,
5+
InstructureBug,
6+
MasteryBug,
7+
StudioBug,
8+
ParchmentBug,
9+
} from "./Logos";
10+
import { render } from "@testing-library/react";
11+
import { InlineSVG } from "@instructure/ui";
12+
13+
// Mock InlineSVG to inspect props and children
14+
vi.mock("@instructure/ui", async (orig) => {
15+
const mod = await orig();
16+
// Define InlineSVGMock inside the factory to avoid hoisting issues
17+
const InlineSVGMock = vi.fn(({ children, ...props }) => (
18+
<svg data-testid="inline-svg" {...props}>
19+
{children}
20+
</svg>
21+
));
22+
return {
23+
...(typeof mod === "object" && mod !== null ? mod : {}),
24+
InlineSVG: InlineSVGMock,
25+
};
26+
});
27+
28+
// Mock useId to return a stable value for IgniteBug
29+
vi.mock("react", async (orig) => {
30+
const mod = await orig();
31+
return {
32+
...(typeof mod === "object" && mod !== null ? mod : {}),
33+
useId: () => "testid",
34+
};
35+
});
36+
37+
const InlineSVGMock = InlineSVG as unknown as ReturnType<typeof vi.fn>;
38+
39+
describe("Logo Bug Components", () => {
40+
beforeEach(() => {
41+
InlineSVGMock.mockClear();
42+
});
43+
44+
const logoCases = [
45+
{
46+
name: "CanvasBug",
47+
Component: CanvasBug,
48+
expected: {
49+
title: "Canvas",
50+
viewBox: "0 0 59.68 59.68",
51+
},
52+
},
53+
{
54+
name: "MasteryBug",
55+
Component: MasteryBug,
56+
expected: {
57+
title: "Mastery",
58+
viewBox: "0 0 70.82 53.92",
59+
},
60+
},
61+
{
62+
name: "StudioBug",
63+
Component: StudioBug,
64+
expected: {
65+
title: "Studio",
66+
viewBox: "0 0 135.85 118.73",
67+
},
68+
},
69+
{
70+
name: "ParchmentBug",
71+
Component: ParchmentBug,
72+
expected: {
73+
title: "Parchment",
74+
viewBox: "0 0 70.82 53.92",
75+
},
76+
},
77+
];
78+
79+
logoCases.forEach(({ name, Component, expected }) => {
80+
it(`${name} renders with default props`, () => {
81+
render(<Component />);
82+
expect(InlineSVGMock).toHaveBeenCalledWith(
83+
expect.objectContaining({
84+
title: expected.title,
85+
viewBox: expected.viewBox,
86+
}),
87+
undefined,
88+
);
89+
});
90+
91+
it(`${name} passes color prop and wraps children in <g fill>`, () => {
92+
const { getAllByTestId } = render(<Component color="#123456" />);
93+
const svg = getAllByTestId("inline-svg").pop();
94+
if (!svg) throw new Error("SVG not found");
95+
const g = svg.querySelector("g[fill='#123456']");
96+
expect(g).not.toBeNull();
97+
});
98+
});
99+
100+
it("InstructureBug renders with default props", () => {
101+
render(<InstructureBug />);
102+
expect(InlineSVGMock).toHaveBeenCalledWith(
103+
expect.objectContaining({
104+
title: "Instructure",
105+
viewBox: "0 0 53.42 53.42",
106+
}),
107+
undefined,
108+
);
109+
});
110+
111+
it("InstructureBug renders with color and custom fills", () => {
112+
const { getAllByTestId } = render(<InstructureBug color="#abc" />);
113+
const svg = getAllByTestId("inline-svg").pop();
114+
expect(svg).toBeTruthy();
115+
if (!svg) throw new Error("SVG not found");
116+
const rects = svg.querySelectorAll("rect");
117+
expect(rects.length).toBeGreaterThan(0);
118+
expect(rects[0].getAttribute("stroke")).toBe("#0E1721");
119+
expect(rects[1].getAttribute("fill")).toBe("#0E1721");
120+
const path = svg.querySelector("path");
121+
expect(path).not.toBeNull();
122+
if (!path) throw new Error("path not found");
123+
expect(path.getAttribute("fill")).toBe("#D42E21");
124+
});
125+
126+
it("IgniteBug renders with default props (no color)", () => {
127+
render(<IgniteBug />);
128+
const call = InlineSVGMock.mock.calls[0][0];
129+
expect(call.title).toBe("IgniteAI");
130+
expect(call.viewBox).toBe("0 0 1920 1920");
131+
});
132+
133+
it("IgniteBug renders with color and gradients/defs", () => {
134+
const { getAllByTestId } = render(<IgniteBug color="#f00" />);
135+
const svg = getAllByTestId("inline-svg").pop();
136+
expect(svg).toBeTruthy();
137+
if (!svg) throw new Error("SVG not found");
138+
const defs = svg.querySelector("defs");
139+
expect(defs).not.toBeNull();
140+
if (!defs) throw new Error("defs not found");
141+
const grad = defs.querySelector("linearGradient#paint0_linear_testid");
142+
expect(grad).not.toBeNull();
143+
const clip = defs.querySelector("clipPath#clip0_testid");
144+
expect(clip).not.toBeNull();
145+
const g = svg.querySelector("g[clip-path='url(#clip0_testid)']");
146+
expect(g).not.toBeNull();
147+
});
148+
149+
it("All logo bug components render without crashing", () => {
150+
expect(() => {
151+
render(<CanvasBug />);
152+
render(<MasteryBug />);
153+
render(<StudioBug />);
154+
render(<ParchmentBug />);
155+
render(<IgniteBug />);
156+
render(<InstructureBug />);
157+
}).not.toThrow();
158+
});
159+
});

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"devDependencies": {
33
"@biomejs/biome": "^2.2.6",
44
"@instructure/browserslist-config-instui": "^11.0.1",
5+
"@testing-library/react": "^16.3.0",
56
"@types/react": "^19.2.2",
67
"@types/react-dom": "^19.2.2",
78
"@typescript/native-preview": "7.0.0-dev.20251019.1",

0 commit comments

Comments
 (0)