puerto 0.19.0

Puerto — Rust full-stack DDD framework CLI. Scaffolds Clean Architecture projects with auto-wired DI, SQLx support, and zero manual wiring. Formerly puerto-framework.
import { describe, expect, test } from "bun:test";
import { fireEvent, screen, waitFor } from "@testing-library/react";
import { {{ pascal }}Error } from "../../../../domain/{{ kebab }}/errors";
import type { {{ pascal }}Draft } from "../../../../domain/{{ kebab }}/model";
import { fake{{ pascal }}Repository, {{ pascal }}Mother } from "../../../../test-support/{{ kebab }}";
import { renderScreen } from "../../../../test-support/render";
{%- if fill_helpers %}
import { {{ fill_helpers | join(sep=", ") }} } from "../../../shared/forms";
{%- endif %}
import { {{ pascal }}FormContainer } from "./{{ kebab }}-form-container";

function type(label: string, value: string) {
  fireEvent.change(screen.getByLabelText(label), { target: { value } });
}

/** Fills the empty form with `draft`, the way a user would. */
async function fillIn(draft: {{ pascal }}Draft) {
  await screen.findByText("Save");
{%- for f in fields %}
{%- if f.input == "checkbox" %}
  if (draft.{{ f.camel }}) fireEvent.click(screen.getByLabelText("{{ f.label }}"));
{%- else %}
  type("{{ f.label }}", {{ f.draft_to_form }});
{%- endif %}
{%- endfor %}
}

describe("{{ pascal }}FormContainer", () => {
  test("should create the {{ words }} from what was typed and show it", async () => {
    // Arrange
    const draft = {{ pascal }}Mother.draft();
    const {{ camel }}Repository = fake{{ pascal }}Repository();
    const { history } = renderScreen(<{{ pascal }}FormContainer />, { {{ camel }}Repository });
    await fillIn(draft);

    // Act
    fireEvent.click(screen.getByText("Save"));

    // Assert
    await waitFor(() => expect(history.at(-1)).toStartWith("/{{ plural }}/"));
    const {
      items: [created],
    } = await {{ camel }}Repository.list({ limit: 1, offset: 0 });
    expect(created).toMatchObject(draft);
    expect(history.at(-1)).toBe(`/{{ plural }}/${created?.id}`);
  });

  test("should save the edited {{ words }} when an existing one is submitted", async () => {
    // Arrange
    const seeded = {{ pascal }}Mother.random();
    const {{ camel }}Repository = fake{{ pascal }}Repository([seeded]);
    const { history } = renderScreen(<{{ pascal }}FormContainer id={seeded.id} />, {
      {{ camel }}Repository,
    });

    // Act
    fireEvent.click(await screen.findByText("Save"));

    // Assert
    await waitFor(() => expect(history.at(-1)).toBe(`/{{ plural }}/${seeded.id}`));
    expect(await {{ camel }}Repository.get(seeded.id)).toEqual(seeded);
  });

  test("should show the code itself when the API answers one the form does not know", async () => {
    // Arrange
    const code = "{{ snake }}.validation_error.invalid";
    const {{ camel }}Repository = {
      ...fake{{ pascal }}Repository(),
      create: () => Promise.reject(new {{ pascal }}Error(code)),
    };
    renderScreen(<{{ pascal }}FormContainer />, { {{ camel }}Repository });
    await fillIn({{ pascal }}Mother.draft());

    // Act
    fireEvent.click(screen.getByText("Save"));

    // Assert
    expect((await screen.findByRole("alert")).textContent).toBe(code);
  });

  test("should say a {{ words }} with these values exists when the API answers a duplicate", async () => {
    // Arrange
    const {{ camel }}Repository = {
      ...fake{{ pascal }}Repository(),
      create: () => Promise.reject(new {{ pascal }}Error("{{ snake }}.duplicate")),
    };
    renderScreen(<{{ pascal }}FormContainer />, { {{ camel }}Repository });
    await fillIn({{ pascal }}Mother.draft());

    // Act
    fireEvent.click(screen.getByText("Save"));

    // Assert
    expect((await screen.findByRole("alert")).textContent).toBe(
      "{{ duplicate_text }}",
    );
  });
{%- if field_problem %}

  test("should show the message under its input when the API rejects one field", async () => {
    // Arrange
    const {{ camel }}Repository = {
      ...fake{{ pascal }}Repository(),
      create: () => Promise.reject(new {{ pascal }}Error("{{ field_problem.code }}")),
    };
    renderScreen(<{{ pascal }}FormContainer />, { {{ camel }}Repository });
    await fillIn({{ pascal }}Mother.draft());

    // Act
    fireEvent.click(screen.getByText("Save"));

    // Assert
    expect(await screen.findByText("{{ field_problem.text }}")).toBeTruthy();
    const input = screen.getByLabelText("{{ field_problem.label }}");
    expect(input.getAttribute("aria-invalid")).toBe("true");
    expect(screen.queryByRole("alert")).toBeNull();
  });
{%- endif %}
});