feat(core): add content controller with tests (articles CRUD)

This commit is contained in:
2026-04-06 14:30:34 +02:00
parent b920da1e8f
commit acf6ed20bc
2 changed files with 94 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
import { z } from "zod";
import { InputParseError } from "@/entities/errors/common.js";
import type { Article } from "@/entities/models/article.js";
import { createArticleUseCase } from "@/application/use-cases/content/create-article.use-case.js";
import { getArticlesUseCase } from "@/application/use-cases/content/get-articles.use-case.js";
const createInputSchema = z.object({
title: z.string().min(1).max(255),
content: z.string(),
authorId: z.string(),
slug: z.string().optional(),
});
const getInputSchema = z.object({
status: z.string().optional(),
authorId: z.string().optional(),
limit: z.number().optional(),
offset: z.number().optional(),
});
export async function createArticleController(
input: Partial<z.infer<typeof createInputSchema>>
): Promise<Article> {
const { data, error: inputParseError } = createInputSchema.safeParse(input);
if (inputParseError) {
throw new InputParseError("Invalid data", { cause: inputParseError });
}
return await createArticleUseCase(data);
}
export async function getArticlesController(
input: Partial<z.infer<typeof getInputSchema>>
): Promise<Article[]> {
const { data, error: inputParseError } = getInputSchema.safeParse(input);
if (inputParseError) {
throw new InputParseError("Invalid data", { cause: inputParseError });
}
return await getArticlesUseCase(data);
}

View File

@@ -0,0 +1,50 @@
import "reflect-metadata";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import {
destroyContainer,
initializeContainer,
} from "@/di/container.js";
import {
createArticleController,
getArticlesController,
} from "@/interface-adapters/controllers/content/articles.controller.js";
import { InputParseError } from "@/entities/errors/common.js";
beforeEach(() => {
initializeContainer();
});
afterEach(() => {
destroyContainer();
});
describe("createArticleController", () => {
it("creates an article with valid input", async () => {
const result = await createArticleController({
title: "Test Article",
content: "Some content",
authorId: "1",
});
expect(result.title).toBe("Test Article");
expect(result.slug).toBe("test-article");
});
it("throws InputParseError for missing title", async () => {
await expect(
createArticleController({ content: "content", authorId: "1" } as any)
).rejects.toBeInstanceOf(InputParseError);
});
});
describe("getArticlesController", () => {
it("returns articles", async () => {
await createArticleController({
title: "Article",
content: "Content",
authorId: "1",
});
const result = await getArticlesController({});
expect(result).toHaveLength(1);
});
});