/** * Property-based tests for saved response sidebar truncation. * * **Validates: Requirements 8.3** * * Property 5: Saved response sidebar truncation — for any question string * exceeding 80 characters, the text displayed in the sidebar SHALL be between * 75 and 85 characters long (inclusive). Strings ≤ 80 characters are returned * unchanged. */ import { describe, it, expect } from "vitest"; import * as fc from "fast-check"; import { truncateQuestion } from "./Sidebar"; // --------------------------------------------------------------------------- // Property 5: Saved response sidebar truncation // --------------------------------------------------------------------------- describe("Property 5: Saved response sidebar truncation", () => { /** * **Validates: Requirements 8.3** * * For any question string exceeding 80 characters, truncateQuestion returns * a string within [75, 85] characters long (inclusive). */ it("truncated text is within [75, 85] characters when original exceeds 80 characters", () => { fc.assert( fc.property( fc.string({ minLength: 81, maxLength: 500 }), (question) => { const truncated = truncateQuestion(question); expect(truncated.length).toBeGreaterThanOrEqual(75); expect(truncated.length).toBeLessThanOrEqual(85); } ) ); }); it("truncated text ends with ellipsis when original exceeds 80 characters", () => { fc.assert( fc.property( fc.string({ minLength: 81, maxLength: 500 }), (question) => { const truncated = truncateQuestion(question); expect(truncated.endsWith("\u2026")).toBe(true); } ) ); }); it("strings of 80 characters or fewer are returned unchanged", () => { fc.assert( fc.property( fc.string({ minLength: 0, maxLength: 80 }), (question) => { const truncated = truncateQuestion(question); expect(truncated).toBe(question); } ) ); }); it("truncated text is a prefix of the original (minus ellipsis)", () => { fc.assert( fc.property( fc.string({ minLength: 81, maxLength: 500 }), (question) => { const truncated = truncateQuestion(question); // Remove the trailing ellipsis to get the prefix const prefix = truncated.slice(0, -1); // The prefix must be a substring of the original starting at index 0 expect(question.startsWith(prefix.trimEnd())).toBe(true); } ) ); }); });