import { expect, test } from "bun:test"; import { createElement } from "react"; import { renderToStaticMarkup } from "react-dom/server"; import { QuestionView } from "./question-view"; import type { AddOptionResult } from "./question-view"; import { AUTH } from "./question-view.test-fixtures"; // Six deferred original contracts, using main's current anatomy and canonical statuses. function save(markup: string): string { let button = markup.match(/]*>Save<\/button>/)?.[0]; if (!button) throw new Error("The real Save control is missing"); return button; } test("a discarded multi-card names the questions set aside", () => { let markup = renderToStaticMarkup(createElement(QuestionView, { definition: { questions: [AUTH.questions[0], { id: "scope", header: "Scope", question: "What belongs in the first cut?", multiple: true, options: [{ id: "anchors", label: "Anchors", description: "" }], }], }, drafts: {}, resolver: "ben", status: "discarded", })); expect(markup).toContain( "Discarded by @ben — What auth system should we use?, What belongs in the first cut?", ); expect(markup.split("@ben")).toHaveLength(2); expect(markup).not.toContain('type="radio"'); }); test("a discarded single card does not repeat its title", () => { let markup = renderToStaticMarkup(createElement(QuestionView, { definition: AUTH, drafts: {}, resolver: "ben", status: "discarded", })); expect(markup).toContain("Discarded by @ben"); expect(markup.split(AUTH.questions[0].question)).toHaveLength(2); expect(markup).not.toContain("Cancelled"); }); test("a single decision renders the card anatomy", () => { let markup = renderToStaticMarkup(createElement(QuestionView, { definition: AUTH, drafts: { q: { mode: "choices", choice: "b", options: { a: false, b: false }, custom: "" } }, onSubmit: () => {}, onDiscard: () => {}, onAddOption: async (): Promise => ({ ok: true }), collaborators: [{ client: "ben-browser", handle: "ben", question: "q" }], aside: createElement("span", {}, "Opened by @ana"), })); let choices = markup.match(/]*>[\s\S]*?<\/label>/g) ?? []; expect(markup).toContain('title="Decision"'); expect(markup).toMatch(/]*>]*>What auth system should we use\?<\/span><\/h4>/); expect(markup).toContain('
'); expect(choices).toHaveLength(2); expect(choices[0]).not.toContain('checked=""'); expect(choices[1]).toMatch(/checked=""[\s\S]*GitHub Apps/); expect(markup).toMatch( /]*class="[^"]*question-add"[^>]*>[\s\S]*?Add an option<\/span><\/button>/, ); expect(markup).toContain(">Discard<"); expect(save(markup)).not.toContain('disabled=""'); expect(markup).toContain('aria-label="Editing this question"'); expect(markup).toContain("@ben"); expect(markup).toContain("Opened by @ana"); expect(markup).not.toContain("Write a custom answer"); expect(markup).not.toContain(" { let drafts = {}; let markup = renderToStaticMarkup(createElement(QuestionView, { definition: AUTH, drafts, onSubmit: () => {}, suggested: { optionId: "b", revision: 7 }, })); let choices = markup.match(/]*>[\s\S]*?<\/label>/g) ?? []; expect(choices[1]).toMatch(/checked=""[\s\S]*GitHub Apps[\s\S]*from chat/); expect(save(markup)).not.toContain('disabled=""'); expect(drafts).toEqual({}); }); test("a linked decision keeps its heading outside the related-prose button", () => { let markup = renderToStaticMarkup(createElement(QuestionView, { definition: AUTH, drafts: {}, places: { q: 2 }, onQuestionSelect() {}, })); let button = markup.match(/]*data-ace-question-id="q"[^>]*>[\s\S]*?<\/button>/)?.[0]; expect(markup).toMatch(/]*>]*data-ace-question-id="q"/); expect(button).toBeDefined(); expect(button).not.toMatch(/ { let markup = renderToStaticMarkup(createElement(QuestionView, { definition: AUTH, drafts: { q: { mode: "choices", choice: null, options: { a: false, b: false }, custom: "" } }, onSubmit: () => {}, })); expect(save(markup)).toContain('disabled=""'); });