diff --git a/resources/tester/test_est_progress_workflow.py b/resources/tester/test_est_progress_workflow.py index 565b9a03e..1af21d9e7 100644 --- a/resources/tester/test_est_progress_workflow.py +++ b/resources/tester/test_est_progress_workflow.py @@ -1,6 +1,15 @@ from test_est_rea_parity import run +def test_new_progress_name_avoids_existing_names_with_whitespace(): + result = run( + "math", + """[EstBusiness.newProgressName([{name:'2회 기성'},{name:' 1회 기성 '}]), + EstBusiness.newProgressName([{name:'2회 기성'}]),EstBusiness.newProgressName([])]""", + ) + assert result == ["3회 기성", "1회 기성", "1회 기성"] + + def test_progress_rejects_ambiguous_inputs_without_applying_them_to_multiple_rows(): result = run( "math", diff --git a/tools/est-test/PLAN.md b/tools/est-test/PLAN.md index 0fb27f7ae..c1ef75e9e 100644 --- a/tools/est-test/PLAN.md +++ b/tools/est-test/PLAN.md @@ -1,4 +1,7 @@ ## Codex · EST 독립 테스트 앱 (2026-11-04) +- [x] 기성 회차 이름 변경·추가 시 중복 방지 → 공백·기존 이름 충돌 시험. + - 자체 검증: 기성·업무 시험 22개 통과, Edge에서 공백 중복 이름 거부·새 이름 생성 확인. + - [x] 첨부파일 추가 전 256MB 저장 한도 확인 → 대형 파일 차단·기존 작업 보존 시험. - 자체 검증: UTF-8·base64 실제 저장 크기 일치·한도 계산 포함 4개 통과. Edge에서 초과 파일 읽기 전 차단·안내 확인. diff --git a/tools/est-test/native-actions.js b/tools/est-test/native-actions.js index acc3359b9..6619708ac 100644 --- a/tools/est-test/native-actions.js +++ b/tools/est-test/native-actions.js @@ -426,7 +426,7 @@ const EstActions = (() => { } else if (name === "add-round") { const next = { id: uid(), - name: `${project.progress.length + 1}회 기성`, + name: EstBusiness.newProgressName(project.progress), inputs: {}, approved: false, locked: false, diff --git a/tools/est-test/native-business-actions.js b/tools/est-test/native-business-actions.js index fb9927295..b8ec5ec0e 100644 --- a/tools/est-test/native-business-actions.js +++ b/tools/est-test/native-business-actions.js @@ -184,12 +184,15 @@ const EstBusinessActions = (() => { "기성 회차 이름", [{ name: "name", label: "회차 이름", value: round.name }], (values) => { + const name = values.name.trim(); if ( - !values.name.trim() || - project.progress.some((item) => item !== round && item.name === values.name) + !name || + project.progress.some( + (item) => item !== round && String(item.name || "").trim() === name, + ) ) throw Error("회차 이름은 비어 있거나 중복될 수 없습니다."); - EstApp.change(() => (round.name = values.name.trim()), false); + EstApp.change(() => (round.name = name), false); }, ); } else if (name === "fill-progress") { diff --git a/tools/est-test/native-business.js b/tools/est-test/native-business.js index b6c999b48..ec80225c8 100644 --- a/tools/est-test/native-business.js +++ b/tools/est-test/native-business.js @@ -315,6 +315,12 @@ const EstBusiness = (() => { function escalation(project) { return EstEscalation.calculate(project); } + function newProgressName(rounds) { + const names = new Set(rounds.map((round) => String(round.name || "").trim())); + let index = 1; + while (names.has(`${index}회 기성`)) index++; + return `${index}회 기성`; + } function newAnnualName(years) { const names = new Set(years.map((year) => String(year.name || "").trim())); for (const year of years) @@ -404,6 +410,7 @@ const EstBusiness = (() => { escalation, annual, newAnnualName, + newProgressName, rowKey, progressExclusions, moveEstimateRows,