WIP! A BB-style forum, on the ATmosphere! We're still working... we'll be back soon when we have something to show off!
node typescript hono htmx atproto

test(web): strengthen preview tests — add fallback test, fix semicolon sanitization assertion (ATB-59)

+24
+24
apps/web/src/routes/__tests__/admin-themes.test.tsx
··· 294 294 295 295 expect(res.status).toBe(200); 296 296 const html = await res.text(); 297 + // The injected declaration must not appear 297 298 expect(html).not.toContain("--injected"); 299 + // The entire dirty value must be dropped — not just the injected suffix 300 + // (a partial-strip bug would output '--color-bg: red' which looks safe) 301 + expect(html).not.toContain("--color-bg"); 298 302 }); 299 303 300 304 it("drops token values containing '}' (CSS block-escape injection prevention)", async () => { ··· 317 321 const html = await res.text(); 318 322 // The injected block-escape value must not appear 319 323 expect(html).not.toContain("red} body"); 324 + }); 325 + 326 + it("returns a fallback HTML fragment when no tokens are submitted (does not crash)", async () => { 327 + setupAuthenticatedSession([MANAGE_THEMES]); 328 + 329 + const routes = await loadThemeRoutes(); 330 + // POST with no body — parseBody() returns {} which produces an empty token map 331 + const res = await routes.request("/admin/themes/abc123/preview", { 332 + method: "POST", 333 + headers: { 334 + "content-type": "application/x-www-form-urlencoded", 335 + cookie: "atbb_session=token", 336 + }, 337 + }); 338 + 339 + // Must not crash — returns a valid HTML fragment 340 + expect(res.status).toBe(200); 341 + const html = await res.text(); 342 + expect(html).not.toContain("<html"); 343 + expect(html).toContain(".preview-pane-inner"); 320 344 }); 321 345 });