puerto 0.15.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 { {{ pascal }}Error } from "../../domain/{{ kebab }}/errors";
import { {{ pascal }}Mother } from "../../test-support/{{ kebab }}";
import { createApiClient } from "../http/client";
import { {{ camel }}RepositoryHttp } from "./{{ kebab }}-repository-http";

/** A repository whose every request is answered with `status` and `body`. */
function answering(status: number, body?: unknown) {
  const requests: Request[] = [];
  const api = createApiClient({
    baseUrl: "http://localhost/api",
    fetch: async (request) => {
      requests.push(request);
      return body === undefined ? new Response(null, { status }) : Response.json(body, { status });
    },
  });
  return { repository: {{ camel }}RepositoryHttp(api), requests };
}

describe("{{ camel }}RepositoryHttp", () => {
  test("should ask for the page and return its {{ words_plural }}", async () => {
    // Arrange
    const {{ ident }} = {{ pascal }}Mother.random();
    const page = { items: [{{ ident }}], total: 21, limit: 20, offset: 20 };
    const { repository, requests } = answering(200, page);

    // Act
    const listed = await repository.list({ limit: 20, offset: 20 });

    // Assert
    expect(requests[0]?.url).toBe("http://localhost/api/{{ plural }}?limit=20&offset=20");
    expect(listed).toEqual(page);
  });

  test("should send the draft when creating {{ a_words }}", async () => {
    // Arrange
    const draft = {{ pascal }}Mother.draft();
    const { repository, requests } = answering(201, { id: crypto.randomUUID(), ...draft });

    // Act
    const created = await repository.create(draft);

    // Assert
    expect(requests[0]?.method).toBe("POST");
    expect(await requests[0]?.json()).toEqual(draft);
    expect(created).toMatchObject(draft);
  });

  test("should reject with the API's error code when the {{ words }} does not exist", async () => {
    // Arrange
    const code = "{{ snake }}.not_found";
    const { repository } = answering(404, { name: code, message: code });

    // Act
    const result = repository.get(crypto.randomUUID());

    // Assert
    await expect(result).rejects.toBeInstanceOf({{ pascal }}Error);
    await expect(result).rejects.toMatchObject({ code });
  });

  test("should resolve when the API deletes the {{ words }}", async () => {
    // Arrange
    const { repository, requests } = answering(204);

    // Act
    await repository.remove("42");

    // Assert
    expect(requests[0]?.url).toBe("http://localhost/api/{{ plural }}/42");
  });
});