import { createRawSnippet } from "svelte"; import { describe, expect, it } from "vitest"; import Review from "../src/composites/Review.svelte"; import { review } from "../src/composites/review.variants"; import SocialContractFailures from "./fixtures/SocialContractFailures.svelte"; import SocialSurfacesConsumer from "./fixtures/SocialSurfacesConsumer.svelte"; import { expectLayoutReadiness } from "./layout-readiness"; import { classes, classesOf, render, rendered } from "./mount"; const body = createRawSnippet(() => ({ render: () => "

Clear and dependable.

" })); const actions = createRawSnippet(() => ({ render: () => '', })); describe("the deliberately failing Review fixture", () => { it("demonstrates a rating conveyed by colour alone", () => { const broken = rendered(render(SocialContractFailures, { failure: "colour-only-rating" })); const rating = broken.querySelector('[aria-label="Rating"]')!; expect(rating.textContent).toBe("★★★★★"); expect(rating.querySelector("input, meter, output")).toBeNull(); expect(rating.textContent).not.toMatch(/\d/); }); }); describe("Review", () => { it("composes canonical Card, MediaObject, Avatar, and Rating contracts", () => { const reviewElement = rendered(render(Review, { author: "Ada Lovelace", avatarFallback: "AL", rating: 4, maxRating: 5, datetime: "2026-08-08", time: "8 August 2026", children: body, actions, })); expect(reviewElement.tagName).toBe("ARTICLE"); expect(reviewElement.getAttribute("aria-label")).toBe("Review by Ada Lovelace"); expect(reviewElement.querySelector("[data-card]")).not.toBeNull(); expect(reviewElement.querySelector("[data-media-object]")).not.toBeNull(); expect(reviewElement.querySelector("[data-avatar]")?.getAttribute("aria-label")).toBe("Ada Lovelace"); expect(reviewElement.querySelector("time")?.dateTime).toBe("2026-08-08"); expect(reviewElement.querySelectorAll('[data-rating] input[type="radio"]')).toHaveLength(5); expect(reviewElement.querySelector("[data-rating] output")?.textContent).toContain("4 of 5"); }); it("conveys the score through symbols, text, and native state rather than colour alone", () => { const reviewElement = rendered(render(Review, { author: "Ada Lovelace", avatarFallback: "AL", rating: 4, maxRating: 5, children: body, })); const marks = [...reviewElement.querySelectorAll("[data-rating-mark]")]; const checked = reviewElement.querySelector('[data-rating] input:checked')!; expect(marks.map((mark) => mark.textContent)).toEqual(["★", "★", "★", "★", "☆"]); expect(checked.value).toBe("4"); expect(reviewElement.querySelector("[data-rating] output")?.textContent).toContain("4 of 5"); }); it("preserves caller-owned action focus and inherits every nested appearance axis", () => { const scope = rendered(render(SocialSurfacesConsumer)); const reviewElement = scope.querySelector("[data-review]")!; const action = reviewElement.querySelector("button")!; expect(classes(reviewElement)).toEqual(expect.objectContaining(classesOf(review().root()))); expect(classes(reviewElement.querySelector("[data-review-content]")!)) .toContain("gap-[var(--reddb-spatial-gap-md)]"); action.focus(); expect(document.activeElement).toBe(action); expect(reviewElement.hasAttribute("data-theme")).toBe(false); expect(reviewElement.hasAttribute("data-color-scheme")).toBe(false); expect(reviewElement.hasAttribute("data-density")).toBe(false); expect(reviewElement.hasAttribute("data-motion")).toBe(false); }); it("ships showcase, consumer, distributed export, and readiness evidence", () => { expectLayoutReadiness("review", "Review"); }); });