Give builder fields persistent labels, treat description as optional, and validate save-progress email with a real form.
Name stays required; description is a labelled optional textarea. Email uses native validity and form submit. Drop the dead workshop link and fix a few copy errors. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -11,6 +11,9 @@ describe("CommunityStructureSelectScreen", () => {
|
||||
expect(screen.getByText("Organization Type")).toBeInTheDocument();
|
||||
expect(screen.getByText("Scale")).toBeInTheDocument();
|
||||
expect(screen.getByText("Maturity")).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText(/Choose tags that describe your community/i),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.queryByAltText("Help")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1044,8 +1044,9 @@ describe("FinalReviewScreen — edit published title and description", () => {
|
||||
|
||||
fireEvent.click(await screen.findByTestId("rule-title-edit"));
|
||||
const dialog = await screen.findByRole("dialog");
|
||||
expect(within(dialog).getByText(/Community name/i)).toBeInTheDocument();
|
||||
const input = within(dialog).getByRole("textbox");
|
||||
const input = within(dialog).getByRole("textbox", {
|
||||
name: /Community name/i,
|
||||
});
|
||||
fireEvent.change(input, { target: { value: "Renamed Commons" } });
|
||||
fireEvent.click(within(dialog).getByRole("button", { name: "Save" }));
|
||||
|
||||
@@ -1076,10 +1077,9 @@ describe("FinalReviewScreen — edit published title and description", () => {
|
||||
|
||||
fireEvent.click(await screen.findByTestId("rule-description-edit"));
|
||||
const dialog = await screen.findByRole("dialog");
|
||||
expect(
|
||||
within(dialog).getByText(/Community description/i),
|
||||
).toBeInTheDocument();
|
||||
const input = within(dialog).getByRole("textbox");
|
||||
const input = within(dialog).getByRole("textbox", {
|
||||
name: /Community description/i,
|
||||
});
|
||||
fireEvent.change(input, { target: { value: "Updated copy" } });
|
||||
fireEvent.click(within(dialog).getByRole("button", { name: "Save" }));
|
||||
|
||||
|
||||
@@ -22,11 +22,9 @@ describe("InformationalScreen", () => {
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders workshop as a link (URL TBD) with underline per Figma", () => {
|
||||
it("does not offer a workshop link until a destination exists", () => {
|
||||
render(<InformationalScreen />);
|
||||
const workshop = screen.getByRole("link", { name: "workshop" });
|
||||
expect(workshop).toHaveAttribute("href", "#");
|
||||
expect(workshop.className).toMatch(/underline/);
|
||||
expect(screen.queryByRole("link", { name: "workshop" })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders first numbered list item title", () => {
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { describe, vi } from "vitest";
|
||||
import { describe, it, expect, vi } from "vitest";
|
||||
import {
|
||||
renderWithProviders as render,
|
||||
screen,
|
||||
} from "../utils/test-utils";
|
||||
import "@testing-library/jest-dom/vitest";
|
||||
import {
|
||||
componentTestSuite,
|
||||
type ComponentTestSuiteConfig,
|
||||
@@ -28,4 +33,19 @@ const config: ComponentTestSuiteConfig<Props> = {
|
||||
|
||||
describe("InputWithCounter", () => {
|
||||
componentTestSuite<Props>(config);
|
||||
|
||||
it("associates the visible label with the input", () => {
|
||||
render(
|
||||
<InputWithCounter
|
||||
label="Community name"
|
||||
placeholder="Enter a name"
|
||||
value=""
|
||||
onChange={vi.fn()}
|
||||
maxLength={50}
|
||||
/>,
|
||||
);
|
||||
expect(
|
||||
screen.getByRole("textbox", { name: "Community name" }),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -43,6 +43,16 @@ describe("TextArea appearance", () => {
|
||||
expect(textarea).toHaveClass("border-0");
|
||||
});
|
||||
|
||||
it("keeps a programmatic label when the visible header is off", () => {
|
||||
const { container } = renderWithProviders(
|
||||
<TextArea label="Community description" formHeader={false} value="" />,
|
||||
);
|
||||
expect(
|
||||
screen.getByRole("textbox", { name: "Community description" }),
|
||||
).toBeInTheDocument();
|
||||
expect(container.querySelector("label")).toHaveClass("sr-only");
|
||||
});
|
||||
|
||||
it("uses tertiary text in the embedded default state and primary on focus", () => {
|
||||
renderWithProviders(
|
||||
<TextArea label="Notes" value="Some text" appearance="embedded" />,
|
||||
|
||||
@@ -55,4 +55,30 @@ describe("TextInput (size tests)", () => {
|
||||
const input = container.querySelector("input");
|
||||
expect(input).toHaveAttribute("maxLength", "200");
|
||||
});
|
||||
|
||||
it("keeps a programmatic label when the visible header is off", () => {
|
||||
const { getByRole, container } = render(
|
||||
<TextInput label="Community name" formHeader={false} />,
|
||||
);
|
||||
expect(getByRole("textbox", { name: "Community name" })).toBeInTheDocument();
|
||||
expect(container.querySelector("label")).toHaveClass("sr-only");
|
||||
});
|
||||
|
||||
it("forwards autocomplete, inputMode, required, and form", () => {
|
||||
const { container } = render(
|
||||
<TextInput
|
||||
label="Email address"
|
||||
type="email"
|
||||
autoComplete="email"
|
||||
inputMode="email"
|
||||
required
|
||||
form="create-flow-community-save"
|
||||
/>,
|
||||
);
|
||||
const input = container.querySelector("input");
|
||||
expect(input).toHaveAttribute("autocomplete", "email");
|
||||
expect(input).toHaveAttribute("inputmode", "email");
|
||||
expect(input).toBeRequired();
|
||||
expect(input).toHaveAttribute("form", "create-flow-community-save");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@ import { describe, it, expect } from "vitest";
|
||||
import { renderWithProviders as render, screen } from "../utils/test-utils";
|
||||
import "@testing-library/jest-dom/vitest";
|
||||
import { CreateFlowTextFieldScreen } from "../../app/(app)/create/screens/text/CreateFlowTextFieldScreen";
|
||||
import { CREATE_FLOW_COMMUNITY_SAVE_FORM_ID } from "../../app/(app)/create/utils/createFlowPaths";
|
||||
|
||||
describe("CreateFlowTextFieldScreen (community name)", () => {
|
||||
it("renders main heading", () => {
|
||||
@@ -10,6 +11,7 @@ describe("CreateFlowTextFieldScreen (community name)", () => {
|
||||
messageNamespace="create.community.communityName"
|
||||
stateField="title"
|
||||
maxLength={48}
|
||||
required
|
||||
/>,
|
||||
);
|
||||
expect(
|
||||
@@ -19,19 +21,63 @@ describe("CreateFlowTextFieldScreen (community name)", () => {
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders description and text field", () => {
|
||||
it("renders description and a labelled text field", () => {
|
||||
render(
|
||||
<CreateFlowTextFieldScreen
|
||||
messageNamespace="create.community.communityName"
|
||||
stateField="title"
|
||||
maxLength={48}
|
||||
required
|
||||
/>,
|
||||
);
|
||||
expect(
|
||||
screen.getByText("This will be the name of your community"),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByPlaceholderText("Enter community name"),
|
||||
screen.getByText("This will be the name of your community."),
|
||||
).toBeInTheDocument();
|
||||
const input = screen.getByRole("textbox", { name: "Community name" });
|
||||
expect(input).toBeInTheDocument();
|
||||
expect(input).toHaveAttribute("placeholder", "Enter community name");
|
||||
expect(input).toBeRequired();
|
||||
});
|
||||
});
|
||||
|
||||
describe("CreateFlowTextFieldScreen (community description)", () => {
|
||||
it("uses a textarea and treats the field as optional", () => {
|
||||
render(
|
||||
<CreateFlowTextFieldScreen
|
||||
messageNamespace="create.community.communityContext"
|
||||
stateField="communityContext"
|
||||
maxLength={200}
|
||||
multiline
|
||||
/>,
|
||||
);
|
||||
expect(
|
||||
screen.getByText(/Optional\. Write a short paragraph/i),
|
||||
).toBeInTheDocument();
|
||||
const field = screen.getByRole("textbox", {
|
||||
name: "Community description",
|
||||
});
|
||||
expect(field.tagName).toBe("TEXTAREA");
|
||||
expect(field).not.toBeRequired();
|
||||
});
|
||||
});
|
||||
|
||||
describe("CreateFlowTextFieldScreen (save progress email)", () => {
|
||||
it("uses a labelled email field with native email attributes", () => {
|
||||
render(
|
||||
<CreateFlowTextFieldScreen
|
||||
messageNamespace="create.community.communitySave"
|
||||
stateField="communitySaveEmail"
|
||||
maxLength={254}
|
||||
inputType="email"
|
||||
showCharacterCount={false}
|
||||
/>,
|
||||
);
|
||||
const input = screen.getByRole("textbox", { name: "Email address" });
|
||||
expect(input).toHaveAttribute("type", "email");
|
||||
expect(input).toHaveAttribute("autocomplete", "email");
|
||||
expect(input).toHaveAttribute("inputmode", "email");
|
||||
expect(input).toHaveAttribute("name", "email");
|
||||
expect(input).toHaveAttribute("form", CREATE_FLOW_COMMUNITY_SAVE_FORM_ID);
|
||||
expect(input).toBeRequired();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -18,7 +18,7 @@ describe("CommunityUploadScreen", () => {
|
||||
expect(screen.getByRole("button", { name: "Upload" })).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText(
|
||||
/This photo be used as a profile picture for your group/i,
|
||||
/This photo will be used as a profile picture for your group/i,
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user