Skip to content

Commit 61dd7a1

Browse files
committed
test(web,contracts): cover ChatFontSize schema + timeline CSS var wiring
Two focused additions guarding the chat font-size feature: - `packages/contracts/src/settings.test.ts` — new file, 11 tests. Covers `ChatFontSize` schema bounds (min 12 / max 24, rejects below, above, non-integer, non-numeric), `ClientSettingsSchema` decoding default behaviour for `chatFontSize`, and confirms both `DEFAULT_CLIENT_SETTINGS` and `DEFAULT_UNIFIED_SETTINGS` carry the default value 14. - `apps/web/src/components/chat/MessagesTimeline.test.tsx` — one new SSR-render test asserting that a `chatFontSize={20}` prop surfaces as `--chat-font-size:20px` on the list wrapper, pinning the contract between the prop and the CSS variable that drives every `text-chat-*` tier plus `.chat-markdown` scaling.
1 parent 1f9620d commit 61dd7a1

2 files changed

Lines changed: 98 additions & 0 deletions

File tree

apps/web/src/components/chat/MessagesTimeline.test.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,32 @@ describe("MessagesTimeline", () => {
161161
expect(markup).toContain("Work log");
162162
});
163163

164+
it("propagates chatFontSize as the --chat-font-size CSS variable on the list wrapper", async () => {
165+
const { MessagesTimeline } = await import("./MessagesTimeline");
166+
const markup = renderToStaticMarkup(
167+
<MessagesTimeline
168+
{...buildProps()}
169+
chatFontSize={20}
170+
timelineEntries={[
171+
{
172+
id: "entry-1",
173+
kind: "message",
174+
createdAt: "2026-03-17T19:12:28.000Z",
175+
message: {
176+
id: MessageId.make("message-1"),
177+
role: "user",
178+
text: "hi",
179+
createdAt: "2026-03-17T19:12:28.000Z",
180+
streaming: false,
181+
},
182+
},
183+
]}
184+
/>,
185+
);
186+
187+
expect(markup).toContain("--chat-font-size:20px");
188+
});
189+
164190
it("formats changed file paths from the workspace root", async () => {
165191
const { MessagesTimeline } = await import("./MessagesTimeline");
166192
const markup = renderToStaticMarkup(
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { describe, expect, it } from "vitest";
2+
import { Schema } from "effect";
3+
4+
import {
5+
ChatFontSize,
6+
CHAT_FONT_SIZE_MAX,
7+
CHAT_FONT_SIZE_MIN,
8+
ClientSettingsSchema,
9+
DEFAULT_CHAT_FONT_SIZE,
10+
DEFAULT_CLIENT_SETTINGS,
11+
DEFAULT_UNIFIED_SETTINGS,
12+
} from "./settings.ts";
13+
14+
const decodeChatFontSize = Schema.decodeUnknownSync(ChatFontSize);
15+
const decodeClientSettings = Schema.decodeUnknownSync(ClientSettingsSchema);
16+
17+
describe("ChatFontSize schema", () => {
18+
it("exposes the expected bounds and default", () => {
19+
expect(CHAT_FONT_SIZE_MIN).toBe(12);
20+
expect(CHAT_FONT_SIZE_MAX).toBe(24);
21+
expect(DEFAULT_CHAT_FONT_SIZE).toBe(14);
22+
});
23+
24+
it("accepts the default, min and max values", () => {
25+
expect(decodeChatFontSize(DEFAULT_CHAT_FONT_SIZE)).toBe(DEFAULT_CHAT_FONT_SIZE);
26+
expect(decodeChatFontSize(CHAT_FONT_SIZE_MIN)).toBe(CHAT_FONT_SIZE_MIN);
27+
expect(decodeChatFontSize(CHAT_FONT_SIZE_MAX)).toBe(CHAT_FONT_SIZE_MAX);
28+
});
29+
30+
it("rejects values below the minimum", () => {
31+
expect(() => decodeChatFontSize(CHAT_FONT_SIZE_MIN - 1)).toThrow();
32+
});
33+
34+
it("rejects values above the maximum", () => {
35+
expect(() => decodeChatFontSize(CHAT_FONT_SIZE_MAX + 1)).toThrow();
36+
});
37+
38+
it("rejects non-integer values", () => {
39+
expect(() => decodeChatFontSize(14.5)).toThrow();
40+
});
41+
42+
it("rejects non-numeric values", () => {
43+
expect(() => decodeChatFontSize("14")).toThrow();
44+
expect(() => decodeChatFontSize(null)).toThrow();
45+
});
46+
});
47+
48+
describe("ClientSettingsSchema chatFontSize decoding default", () => {
49+
it("fills in the default when chatFontSize is omitted from the input", () => {
50+
const parsed = decodeClientSettings({});
51+
expect(parsed.chatFontSize).toBe(DEFAULT_CHAT_FONT_SIZE);
52+
});
53+
54+
it("preserves a provided chatFontSize inside the valid range", () => {
55+
const parsed = decodeClientSettings({ chatFontSize: 20 });
56+
expect(parsed.chatFontSize).toBe(20);
57+
});
58+
59+
it("rejects a chatFontSize outside the valid range", () => {
60+
expect(() => decodeClientSettings({ chatFontSize: 100 })).toThrow();
61+
});
62+
});
63+
64+
describe("Default settings objects expose chatFontSize", () => {
65+
it("DEFAULT_CLIENT_SETTINGS carries the default chat font size", () => {
66+
expect(DEFAULT_CLIENT_SETTINGS.chatFontSize).toBe(DEFAULT_CHAT_FONT_SIZE);
67+
});
68+
69+
it("DEFAULT_UNIFIED_SETTINGS carries the default chat font size", () => {
70+
expect(DEFAULT_UNIFIED_SETTINGS.chatFontSize).toBe(DEFAULT_CHAT_FONT_SIZE);
71+
});
72+
});

0 commit comments

Comments
 (0)