diff --git a/apps/admin/src/components/features/univ-apply-infos/univApplyInfoFields.test.ts b/apps/admin/src/components/features/univ-apply-infos/univApplyInfoFields.test.ts index 3ba02564..5a7cdd71 100644 --- a/apps/admin/src/components/features/univ-apply-infos/univApplyInfoFields.test.ts +++ b/apps/admin/src/components/features/univ-apply-infos/univApplyInfoFields.test.ts @@ -2,18 +2,20 @@ import { describe, expect, it } from "vitest"; import { findFieldByHeader, UNIV_APPLY_INFO_FIELDS } from "./univApplyInfoFields"; describe("univApplyInfoFields", () => { - it("contains only required system fields", () => { - expect(UNIV_APPLY_INFO_FIELDS.every((field) => field.required)).toBe(true); + it("marks only Korean university name as always required", () => { + const requiredFields = UNIV_APPLY_INFO_FIELDS.filter((field) => field.required).map((field) => field.field); + + expect(requiredFields).toEqual(["universityKoreanName"]); }); - it("matches required field labels and whitespace variants", () => { + it("matches supported field labels and whitespace variants", () => { expect(findFieldByHeader("국가 코드")).toBe("universityCountryCode"); expect(findFieldByHeader("국가코드")).toBe("universityCountryCode"); expect(findFieldByHeader("선발 인원")).toBe("studentCapacity"); expect(findFieldByHeader("파견 가능 학기")).toBe("semesterAvailableForDispatch"); }); - it("does not match optional headers that should be stored in extraInfo", () => { + it("does not match unsupported headers that should be stored in extraInfo", () => { const extraInfoHeaders = ["등록금유형", "지원사항", "전공사항", "영어강좌", "비고", "표기명"]; for (const header of extraInfoHeaders) { diff --git a/apps/admin/src/components/features/univ-apply-infos/univApplyInfoFields.ts b/apps/admin/src/components/features/univ-apply-infos/univApplyInfoFields.ts index 33abffb9..e5bef228 100644 --- a/apps/admin/src/components/features/univ-apply-infos/univApplyInfoFields.ts +++ b/apps/admin/src/components/features/univ-apply-infos/univApplyInfoFields.ts @@ -1,24 +1,24 @@ export const UNIV_APPLY_INFO_FIELDS = [ { field: "universityKoreanName", label: "대학명 (국문)", required: true, aliases: ["대학명", "학교명", "대학교명"] }, - { field: "universityEnglishName", label: "대학명 (영문)", required: true, aliases: ["영문명", "영어명"] }, - { field: "universityCountryCode", label: "국가", required: true, aliases: ["국가코드"] }, - { field: "studentCapacity", label: "선발 인원", required: true, aliases: ["인원", "모집인원", "정원", "모집정원"] }, + { field: "universityEnglishName", label: "대학명 (영문)", required: false, aliases: ["영문명", "영어명"] }, + { field: "universityCountryCode", label: "국가", required: false, aliases: ["국가코드"] }, + { field: "studentCapacity", label: "선발 인원", required: false, aliases: ["인원", "모집인원", "정원", "모집정원"] }, { field: "semesterAvailableForDispatch", label: "파견 가능 학기", - required: true, + required: false, aliases: ["파견가능학기", "파견학기"], }, - { field: "semesterRequirement", label: "최저 이수학기", required: true, aliases: ["학기요건", "재학학기"] }, - { field: "gpaRequirement", label: "최저 성적 요건", required: true, aliases: ["성적요건", "학점요건", "최소학점"] }, - { field: "gpaRequirementCriteria", label: "성적 기준", required: true, aliases: ["학점기준", "성적기준"] }, + { field: "semesterRequirement", label: "최저 이수학기", required: false, aliases: ["학기요건", "재학학기"] }, + { field: "gpaRequirement", label: "최저 성적 요건", required: false, aliases: ["성적요건", "학점요건", "최소학점"] }, + { field: "gpaRequirementCriteria", label: "성적 기준", required: false, aliases: ["학점기준", "성적기준"] }, { field: "detailsForLanguage", label: "어학 세부 요건", - required: true, + required: false, aliases: ["어학사항", "어학요건상세", "어학요건"], }, - { field: "detailsForAccommodation", label: "기숙사", required: true, aliases: ["숙소사항", "기숙사안내"] }, + { field: "detailsForAccommodation", label: "기숙사", required: false, aliases: ["숙소사항", "기숙사안내"] }, { field: "universityHomepageUrl", label: "관련 홈페이지", diff --git a/apps/admin/src/components/features/univ-apply-infos/univApplyInfoValidation.test.ts b/apps/admin/src/components/features/univ-apply-infos/univApplyInfoValidation.test.ts new file mode 100644 index 00000000..332a3fb2 --- /dev/null +++ b/apps/admin/src/components/features/univ-apply-infos/univApplyInfoValidation.test.ts @@ -0,0 +1,107 @@ +import { describe, expect, it } from "vitest"; +import type { PreviewRow } from "./univApplyInfoPreview"; +import { validatePreviewRows } from "./univApplyInfoValidation"; + +function makeRow(cellsByField: PreviewRow["cellsByField"]): PreviewRow { + return { + rowNumber: 1, + cellsByField, + }; +} + +describe("validatePreviewRows", () => { + it("requires Korean university name for every preview row", () => { + const rows = [ + makeRow({ + universityKoreanName: { + header: "대학명 (국문)", + field: "universityKoreanName", + value: " ", + }, + }), + ]; + + const errors = validatePreviewRows(rows); + + expect(errors.get("1:field:universityKoreanName")).toContain("필수"); + }); + + it("does not require conditional or nullable fields when they are not mapped", () => { + const rows = [ + makeRow({ + universityKoreanName: { + header: "대학명 (국문)", + field: "universityKoreanName", + value: "괌 대학", + }, + }), + ]; + + const errors = validatePreviewRows(rows); + + expect(errors.size).toBe(0); + }); + + it("does not require optional mapped field values or language test scores", () => { + const rows = [ + makeRow({ + universityKoreanName: { + header: "대학명 (국문)", + field: "universityKoreanName", + value: "괌 대학", + }, + universityEnglishName: { + header: "대학명 (영문)", + field: "universityEnglishName", + value: "", + }, + universityCountryCode: { + header: "국가", + field: "universityCountryCode", + value: "", + }, + studentCapacity: { + header: "선발 인원", + field: "studentCapacity", + value: "", + }, + TOEIC: { + header: "TOEIC", + field: "TOEIC", + value: "", + }, + }), + ]; + + const errors = validatePreviewRows(rows); + + expect(errors.size).toBe(0); + }); + + it("validates optional field constraints when values are present", () => { + const rows = [ + makeRow({ + universityKoreanName: { + header: "대학명 (국문)", + field: "universityKoreanName", + value: "괌 대학", + }, + universityCountryCode: { + header: "국가", + field: "universityCountryCode", + value: "없는 국가", + }, + studentCapacity: { + header: "선발 인원", + field: "studentCapacity", + value: "두 명", + }, + }), + ]; + + const errors = validatePreviewRows(rows); + + expect(errors.get("1:field:universityCountryCode")).toContain("유효하지 않은 국가 코드"); + expect(errors.get("1:field:studentCapacity")).toContain("정수"); + }); +});