Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history

visual-coherence.test.tsx

Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.

visual-coherence.test.tsxBlame185 lines · 1 contributor
c63b860Claude1/**
2 * Block O3 — visual coherence tests.
3 *
4 * Asserts the design-token + component contract introduced by the O3
5 * pass.
6 *
7 * NOTE: This test runs WITHOUT mock pollution — no `mock.module()`,
8 * no shared global state, no DB. It only hits in-process HTTP routes
9 * via `app.request()` and renders the canonical components directly
10 * to strings via hono/jsx's built-in stringifier.
11 */
12
13import { describe, it, expect } from "bun:test";
14import app from "../app";
15import { Card } from "../views/ui";
16import { Layout } from "../views/layout";
17
18// hono/jsx exposes a stringifier on every node.
19async function renderToString(node: any): Promise<string> {
20 if (node && typeof node.toString === "function") {
21 return String(await node.toString());
22 }
23 return String(node);
24}
25
26describe("O3 — design token aliases in master CSS", () => {
27 it("layout.tsx exposes the --space-* alias scale", async () => {
28 const res = await app.request("/");
29 const body = await res.text();
30 expect(body).toContain("--space-1:");
31 expect(body).toContain("--space-2:");
32 expect(body).toContain("--space-3:");
33 expect(body).toContain("--space-4:");
34 expect(body).toContain("--space-6:");
35 expect(body).toContain("--space-8:");
36 });
37
38 it("layout.tsx exposes the --radius-* alias scale", async () => {
39 const res = await app.request("/");
40 const body = await res.text();
41 expect(body).toContain("--radius-sm:");
42 expect(body).toContain("--radius-md:");
43 expect(body).toContain("--radius-lg:");
44 expect(body).toContain("--radius-full:");
45 });
46
47 it("layout.tsx exposes the --font-size-* alias scale", async () => {
48 const res = await app.request("/");
49 const body = await res.text();
50 expect(body).toContain("--font-size-xs:");
51 expect(body).toContain("--font-size-sm:");
52 expect(body).toContain("--font-size-base:");
53 expect(body).toContain("--font-size-lg:");
54 expect(body).toContain("--font-size-xl:");
55 });
56
57 it("layout.tsx exposes the --leading-* aliases", async () => {
58 const res = await app.request("/");
59 const body = await res.text();
60 expect(body).toContain("--leading-tight:");
61 expect(body).toContain("--leading-normal:");
62 expect(body).toContain("--leading-loose:");
63 });
64
65 it("layout.tsx exposes the --z-* index scale", async () => {
66 const res = await app.request("/");
67 const body = await res.text();
68 expect(body).toContain("--z-nav:");
69 expect(body).toContain("--z-modal:");
70 expect(body).toContain("--z-toast:");
71 });
72
73 it("ships the notice / email-preview / code-block utility classes", async () => {
74 const res = await app.request("/");
75 const body = await res.text();
76 expect(body).toContain(".notice");
77 expect(body).toContain(".notice-warn");
78 expect(body).toContain(".email-preview");
79 expect(body).toContain(".code-block");
80 });
81});
82
83describe("O3 — site-wide footer renders on every page", () => {
84 // /explore queries the DB which is not available in the unit-test
85 // process. Footer presence is well-covered by the other four pages.
86 const PAGES = ["/", "/help", "/status", "/pricing"];
87
88 for (const path of PAGES) {
89 it(`GET ${path} includes the canonical footer`, async () => {
90 const res = await app.request(path);
91 expect(res.status).toBeLessThan(500);
92 const body = await res.text();
93 expect(body).toContain("<footer");
94 expect(body.toLowerCase()).toContain("gluecron");
95 });
96 }
97});
98
99describe("O3 — Card component padding + variant props", () => {
100 it("renders without props (legacy default)", async () => {
101 const html = await renderToString(<Card>hello</Card>);
102 expect(html).toContain('class="card"');
103 expect(html).toContain("hello");
104 });
105
106 it('supports padding="none"', async () => {
107 const html = await renderToString(<Card padding="none">x</Card>);
108 expect(html).toContain("card-p-none");
109 });
110
111 it('supports padding="sm"', async () => {
112 const html = await renderToString(<Card padding="sm">x</Card>);
113 expect(html).toContain("card-p-sm");
114 });
115
116 it('supports padding="md"', async () => {
117 const html = await renderToString(<Card padding="md">x</Card>);
118 expect(html).toContain("card-p-md");
119 });
120
121 it('supports padding="lg"', async () => {
122 const html = await renderToString(<Card padding="lg">x</Card>);
123 expect(html).toContain("card-p-lg");
124 });
125
126 it('supports variant="elevated"', async () => {
127 const html = await renderToString(<Card variant="elevated">x</Card>);
128 expect(html).toContain("card-elevated");
129 });
130
131 it('supports variant="gradient"', async () => {
132 const html = await renderToString(<Card variant="gradient">x</Card>);
133 expect(html).toContain("card-gradient");
134 });
135
136 it("composes padding and variant together", async () => {
137 const html = await renderToString(
138 <Card padding="lg" variant="elevated">x</Card>
139 );
140 expect(html).toContain("card-p-lg");
141 expect(html).toContain("card-elevated");
142 });
143});
144
145describe("O3 — flag-gated footer banner", () => {
146 it("does NOT render the .footer-banner stripe when siteBannerText is empty", async () => {
147 const html = await renderToString(
148 <Layout title="t">
149 <p>body</p>
150 </Layout>
151 );
152 expect(html).not.toContain('class="footer-banner');
153 });
154
155 it("renders the .footer-banner stripe when siteBannerText is non-empty", async () => {
156 const html = await renderToString(
157 <Layout title="t" siteBannerText="Scheduled maintenance tonight">
158 <p>body</p>
159 </Layout>
160 );
161 expect(html).toContain("footer-banner");
162 expect(html).toContain("Scheduled maintenance tonight");
163 });
164
165 it("honours the siteBannerLevel modifier", async () => {
166 const html = await renderToString(
167 <Layout title="t" siteBannerText="x" siteBannerLevel="warn">
168 <p>body</p>
169 </Layout>
170 );
171 expect(html).toContain("footer-banner-warn");
172 });
173});
174
175describe("O3 — no critical page leaks a banner stripe by default", () => {
176 const PAGES = ["/", "/help", "/pricing"];
177
178 for (const path of PAGES) {
179 it(`GET ${path} does not render the footer-banner stripe by default`, async () => {
180 const res = await app.request(path);
181 const body = await res.text();
182 expect(body).not.toContain('class="footer-banner');
183 });
184 }
185});