Skip to content

Commit ca52d65

Browse files
committed
온보딩 게이트를 현재 학습 홈 구조와 노트북 툴바 계약에 맞춘다
상황: quality-cycle의 onboarding-browser 게이트가 세 지점에서 실패했다. 모두 이번 변경이 아니라 잠복해 있던 낡은 계약이다. (1) 학습 홈 heading pin이 7월 28일 홈 개편(4efc935) 이전 문구("코드로 증명")를 요구했다. (2) 홈의 mastery 통계, 이어서 학습, 다시 풀 문제 블록을 무조건 요구했는데, 현재 홈은 이 블록들을 canonical 클라이언트 증거 저장소에서 파생해 증거가 있을 때만 렌더한다. 게이트 스텁이 fixture를 주던 /api/curriculum/progress와 /api/curriculum/reviews는 홈이 더 이상 호출하지 않는 죽은 경로다(이번 실행 API 호출 목록으로 확인). (3) 노트북 자동화 셀 실행 버튼을 aria-label "셀 실행" 정확 일치로 찾았는데, 노트북 셀 실행 버튼은 셀 위치를 포함한 맥락 라벨("Automation · 세션 유지 셀 1 / 3 실행")을 쓴다. 변경: tests/surface/verifyOnboardingPlaywright.py에서 - 홈 heading pin을 현재 문구("오늘 완성할 결과를 선택하세요")로 갱신했다. - 신규 사용자 홈은 빈 상태가 정직하다는 계약으로 재정렬했다. 증거 없이 mastery·resume· reviews 블록이 렌더되면 실패하고, 시작 CTA(data-curriculum-home-start)와 목표 지도, self-rating 부재를 검증한다. 증거 기반 상태는 실제 증거를 만드는 product-experience와 web-learning 게이트가 담당한다. - 노트북 자동화 셀 3곳의 실행 버튼 선택자를 button.notebookCellRunButton 우선, aria-label "실행" 접미사 fallback으로 바꿨다. 영향: onboarding-browser 게이트가 현재 제품 사실을 검증한다. 게이트 완화가 아니라 검증 대상 교정이다. 신규 사용자 홈의 거짓 통계 렌더를 잡는 부정 경로 검증이 새로 생겼다. 검증: uv run --no-sync --with playwright python -X utf8 tests/surface/verifyOnboardingPlaywright.py 실행 결과 14개 체크 전부 ok("ok: onboarding browser verified ..."). 실패 재현과 원인 확인은 게이트 debugText의 페이지 텍스트, API 호출 목록, curriculumHome.tsx 렌더 조건 (creditedOutcomes/totalDue/resume 조건부)과 대조했다.
1 parent 2aaa9fb commit ca52d65

1 file changed

Lines changed: 19 additions & 18 deletions

File tree

‎tests/surface/verifyOnboardingPlaywright.py‎

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,9 @@ def jsAssertCurriculumSidebarGroups() -> str:
670670

671671

672672
def jsAssertCurriculumHome() -> str:
673+
# 신규 사용자 홈은 빈 상태가 정직하다. 증거가 없으면 mastery 통계, 이어서 학습,
674+
# 복습 블록을 만들지 않고 시작 CTA만 노출한다. 증거 기반 상태는 실제 증거를 만드는
675+
# product-experience와 web-learning 게이트가 검증한다.
673676
return compactJs("""
674677
(async () => {
675678
const entry = document.querySelector('[data-curriculum-home-entry="true"]');
@@ -683,13 +686,18 @@ def jsAssertCurriculumHome() -> str:
683686
}
684687
if (!home) throw new Error('curriculum home did not render after clicking home entry');
685688
const text = home.innerText;
686-
if (!text.includes('코드로 증명')) throw new Error('curriculum home outcome-first heading missing');
687-
const mastery = document.querySelector('[data-curriculum-home-mastery="true"]');
688-
if (!mastery) throw new Error('curriculum home mastery stat missing');
689-
if (!mastery.textContent || !mastery.textContent.includes('강한 검증')) throw new Error('curriculum home strong evidence label missing');
690-
const resume = document.querySelector('[data-curriculum-home-resume="true"]');
691-
if (!resume) throw new Error('curriculum home resume CTA missing');
692-
if (!resume.textContent || !resume.textContent.includes('이어서 학습')) throw new Error('curriculum home resume label missing');
689+
if (!text.includes('오늘 완성할 결과를 선택하세요')) throw new Error('curriculum home outcome-first heading missing');
690+
if (document.querySelector('[data-curriculum-home-mastery="true"]')) {
691+
throw new Error('fresh onboarding home fabricated mastery stats without evidence');
692+
}
693+
if (document.querySelector('[data-curriculum-home-resume="true"]')) {
694+
throw new Error('fresh onboarding home fabricated a resume target without evidence');
695+
}
696+
if (document.querySelector('[data-curriculum-home-reviews="true"]')) {
697+
throw new Error('fresh onboarding home fabricated due reviews without evidence');
698+
}
699+
const startCta = document.querySelector('[data-curriculum-home-start="true"]');
700+
if (!startCta) throw new Error('curriculum home start CTA missing');
693701
const goals = document.querySelector('[data-curriculum-home-goals="true"]');
694702
if (!goals) throw new Error('curriculum home goal map missing');
695703
const goalGroups = goals.querySelectorAll('[data-curriculum-home-goal-group]');
@@ -699,14 +707,7 @@ def jsAssertCurriculumHome() -> str:
699707
if (document.querySelector('[data-curriculum-home-progress="true"]')) {
700708
throw new Error('bulk lesson progress must not dominate the learning home');
701709
}
702-
const reviews = document.querySelector('[data-curriculum-home-reviews="true"]');
703-
if (!reviews) throw new Error('curriculum home review section missing');
704-
if (!reviews.textContent || !reviews.textContent.includes('다시 풀 문제')) throw new Error('curriculum home retrieval-task label missing');
705-
const reviewItems = reviews.querySelectorAll('[data-curriculum-home-review]');
706-
if (reviewItems.length < 1) throw new Error('curriculum home review items missing');
707-
const reviewOpen = reviews.querySelector('[data-curriculum-home-review-open="true"]');
708-
if (!reviewOpen || reviewOpen.disabled) throw new Error('runnable retrieval-task navigation missing');
709-
if (reviews.querySelector('[data-curriculum-home-review-pass], [data-curriculum-home-review-lapse]')) {
710+
if (document.querySelector('[data-curriculum-home-review-pass], [data-curriculum-home-review-lapse]')) {
710711
throw new Error('self-rating controls must not change review state');
711712
}
712713
if (document.querySelector('[data-curriculum-home-weak-areas="true"]')) {
@@ -761,7 +762,7 @@ def jsAssertAutomationOutput() -> str:
761762
(async () => {
762763
const cell = document.querySelector('[data-automation-session-cell="true"]');
763764
if (!cell) throw new Error('automation session cell missing');
764-
const runButton = cell.querySelector('button[aria-label="셀 실행"]');
765+
const runButton = cell.querySelector('button.notebookCellRunButton, button[aria-label$="실행"]');
765766
if (!runButton) throw new Error('automation run button missing');
766767
runButton.click();
767768
let output = null;
@@ -835,7 +836,7 @@ def jsAssertAutomationCancelledOutput() -> str:
835836
const cells = [...document.querySelectorAll('[data-automation-session-cell="true"]')];
836837
const cell = cells[1];
837838
if (!cell) throw new Error('cancelled automation fixture cell missing');
838-
const runButton = cell.querySelector('button[aria-label="셀 실행"]');
839+
const runButton = cell.querySelector('button.notebookCellRunButton, button[aria-label$="실행"]');
839840
if (!runButton) throw new Error('cancelled automation run button missing');
840841
runButton.click();
841842
let output = null;
@@ -891,7 +892,7 @@ def jsAssertAutomationVersionSkewOutput() -> str:
891892
const cells = [...document.querySelectorAll('[data-automation-session-cell="true"]')];
892893
const cell = cells[2];
893894
if (!cell) throw new Error('version-skew automation fixture cell missing');
894-
const runButton = cell.querySelector('button[aria-label="셀 실행"]');
895+
const runButton = cell.querySelector('button.notebookCellRunButton, button[aria-label$="실행"]');
895896
if (!runButton) throw new Error('version-skew automation run button missing');
896897
runButton.click();
897898
let output = null;

0 commit comments

Comments
 (0)