리팩터링
CI / test (push) Successful in 5m38s
CI / e2e (push) Has been skipped
CI / pr_and_merge (push) Successful in 1m12s

This commit is contained in:
2025-12-16 17:49:25 +09:00
parent 87cdc1868b
commit 7491dacba2
19 changed files with 1857 additions and 99 deletions
+161
View File
@@ -549,4 +549,165 @@ describe("/api/forms/submit", () => {
expect(sensitive.birthdate).toBe("1990-01-01");
});
});
describe("프로젝트 status 에 따른 제출 허용/차단", () => {
it("PUBLISHED 상태 프로젝트는 internal 모드 제출을 허용해야 한다", async () => {
inMemoryProjects.push({
id: "proj-published",
slug: "project-published",
userId: "owner-published",
status: "PUBLISHED",
});
const config: FormBlockProps = {
kind: "contact",
submitTarget: "internal",
successMessage: "ok",
errorMessage: "err",
fieldIds: [],
submitButtonId: null,
};
const formData = new FormData();
formData.append("email", "published@example.com");
formData.append("message", "message");
formData.append("__projectSlug", "project-published");
formData.append("__config", JSON.stringify(config));
const { POST: handleSubmit } = await import("@/app/api/forms/submit/route");
const res = await handleSubmit(
new Request(`${BASE_URL}/api/forms/submit`, {
method: "POST",
body: formData,
}),
);
expect(res.status).toBe(200);
const json = (await res.json()) as any;
expect(json.ok).toBe(true);
expect(inMemoryFormSubmissions.length).toBe(1);
const saved = inMemoryFormSubmissions[0] as any;
expect(saved.projectSlug).toBe("project-published");
expect(saved.projectId).toBe("proj-published");
expect(saved.userId).toBe("owner-published");
});
it("ARCHIVED 상태 프로젝트는 project_closed 로 제출을 차단해야 한다", async () => {
inMemoryProjects.push({
id: "proj-archived",
slug: "project-archived",
userId: "owner-archived",
status: "ARCHIVED",
});
const config: FormBlockProps = {
kind: "contact",
submitTarget: "internal",
successMessage: "ok",
errorMessage: "폼 제출이 중단된 프로젝트입니다.",
fieldIds: [],
submitButtonId: null,
};
const formData = new FormData();
formData.append("email", "archived@example.com");
formData.append("__projectSlug", "project-archived");
formData.append("__config", JSON.stringify(config));
const { POST: handleSubmit } = await import("@/app/api/forms/submit/route");
const res = await handleSubmit(
new Request(`${BASE_URL}/api/forms/submit`, {
method: "POST",
body: formData,
}),
);
expect(res.status).toBe(403);
const json = (await res.json()) as any;
expect(json.ok).toBe(false);
expect(json.error).toBe("project_closed");
expect(json.message).toBe(config.errorMessage);
expect(inMemoryFormSubmissions.length).toBe(0);
});
it("DRAFT 상태 프로젝트도 project_closed 로 제출을 차단해야 한다", async () => {
inMemoryProjects.push({
id: "proj-draft",
slug: "project-draft",
userId: "owner-draft",
status: "DRAFT",
});
const config: FormBlockProps = {
kind: "contact",
submitTarget: "internal",
successMessage: "ok",
errorMessage: "아직 공개되지 않은 프로젝트입니다.",
fieldIds: [],
submitButtonId: null,
};
const formData = new FormData();
formData.append("email", "draft@example.com");
formData.append("__projectSlug", "project-draft");
formData.append("__config", JSON.stringify(config));
const { POST: handleSubmit } = await import("@/app/api/forms/submit/route");
const res = await handleSubmit(
new Request(`${BASE_URL}/api/forms/submit`, {
method: "POST",
body: formData,
}),
);
expect(res.status).toBe(403);
const json = (await res.json()) as any;
expect(json.ok).toBe(false);
expect(json.error).toBe("project_closed");
expect(json.message).toBe(config.errorMessage);
expect(inMemoryFormSubmissions.length).toBe(0);
});
it("프로젝트를 찾지 못한 경우에는 기존처럼 projectSlug 만으로 제출을 허용해야 한다", async () => {
const config: FormBlockProps = {
kind: "contact",
submitTarget: "internal",
successMessage: "ok",
errorMessage: "err",
fieldIds: [],
submitButtonId: null,
};
const formData = new FormData();
formData.append("email", "unknown@example.com");
formData.append("__projectSlug", "missing-project");
formData.append("__config", JSON.stringify(config));
const { POST: handleSubmit } = await import("@/app/api/forms/submit/route");
const res = await handleSubmit(
new Request(`${BASE_URL}/api/forms/submit`, {
method: "POST",
body: formData,
}),
);
expect(res.status).toBe(200);
const json = (await res.json()) as any;
expect(json.ok).toBe(true);
expect(inMemoryFormSubmissions.length).toBe(1);
const saved = inMemoryFormSubmissions[0] as any;
expect(saved.projectSlug).toBe("missing-project");
expect(saved.projectId ?? null).toBeNull();
expect(saved.userId ?? null).toBeNull();
});
});
});