Repository navigation
fix(receiver): 남기지 않은 계정 정보에 마스킹을 그리지 않는다 (closes 619) [base: develop] - #1169
Conversation
서버는 수신자 상세(`GET receiver-auth/after-notes/{id}`)에 credentials 를 내려주지
않는다. 그런데 presentation 매퍼가 `orEmpty()` 로 빈 문자열을 채운 탓에 화면이
«가려진 값이 있다» 는 마스킹을 그렸고, 수신자는 «표시» 를 눌러 빈 값을 확인하고서야
아무것도 전달되지 않았음을 알았다.
부재를 폴백이 아니라 타입으로 옮긴다.
- ReceivedAccountCredentialsUiModel 을 nullable 로 두고, 아이디·비밀번호가 모두
없으면(공백뿐인 값 포함) 모델 자체를 만들지 않는다. 이 타입이 존재하면 최소 한쪽에는
값이 있다는 뜻이다.
- 화면은 값이 있을 때만 마스킹과 표시 토글을 붙인다. 자격증명이 통째로 없으면 안내
문구를, 한쪽만 없으면 그 행에만 부재를 명시한다.
- 문구는 afternote 모듈이 아니라 receiver 모듈 strings.xml 에 둔다 (#1066 방향).
검증 — 매퍼 계약 테스트 5건 신설, 스크린샷 baseline 을 부재·부분 부재·온전 3상태로
확장(docker/amd64 재생성, validate 42 tests 0 failures).
세 baseline 중 자격증명 부재 판만 `ReceivedSocialNetworkDetailContent()` 기본값을 써서 서비스명까지 빈 화면을 찍고 있었다. **제목이 빈 애프터노트는 실재하지 않는다** — 에디터 검증(TITLE_REQUIRED) · 서버 `@NotBlank` · DB `nullable = false` 로 3중 강제된다(BE Afternote.java·AfternoteCreateRequest.java 실코드 확인). 도달 불가능한 상태를 baseline 으로 고정하면 리뷰어가 현실에 없는 화면을 본다. 서비스명을 채워 세 판을 «같은 애프터노트의 자격증명 상태만 다른» 비교로 맞춘다. 처리방법·남기신 말씀이 빈 것은 그대로 둔다 — 서버가 둘 다 선택 항목으로 정의해 실제로 도달하는 상태다. 검증 — docker/amd64 재생성 후 validate 통과(update·validate 마커 exit 0).
|
이 PR 은
|
충돌 1건 — `ReceivedAfternoteDetailSuccessMapper` 의 SOCIAL 매핑에서 develop 의 #1177 (제목 nullable 제거)과 이 브랜치의 #619(자격증명 부재 표현)가 같은 줄을 건드렸다. 둘 다 같은 방향의 «폴백 대신 타입» 이라 양쪽을 그대로 살린다. serviceName = title, // develop: title 이 non-null 로 좁혀짐 credentials = credentials.toUiModelOrNull(), // #619: 부재를 nullable 로 표현 `title.orEmpty()` 는 도메인 모델이 `String` 이 되면서 불필요해졌다. 검증 — 매퍼 계약 테스트 5건 · ktlint · :app:compileDebugUnitTestKotlin · :app:compileDebugAndroidTestKotlin · :konsist:test 전부 BUILD SUCCESSFUL.
|
충돌은 이후 라벨이 스테일로 남아 오탐이 이어져 직접 뗐습니다. 뗄 때 실측 근거는 이렇습니다.
🤖 Addressed by Claude Code |
|
❌ Screenshot test fail — baseline 과 CI rendered PNG 차이. 📦 Artifact: https://github.com/Afternote/Afternote-FE/actions/runs/32950736093 (페이지 하단 Artifacts → 🔍 확인 위치 (artifact zip 내부):
📝 조치 가이드:
CI ↔ 로컬 환경 차이는 본 워크플로의 container 단계가 root fix 한다 (README 의 "Compose Preview Screenshot Testing (docker baseline)" 섹션 참조). |
|
이 PR 의 변경 때문이 아니라 원인은 각각 green 이던 두 PR 의 조합입니다 — #1174(lineBreak)가 그 시점 baseline 4장만 갱신했고, #1164(fontScale 1.5 축)의 같은 일괄 머지로
이 PR 자체는 로컬 실측에서 전 모듈 유닛 테스트 BUILD SUCCESSFUL 이고, 병합 전 docker 사이클에서 🤖 Addressed by Claude Code |
충돌 1건 — receiver `strings.xml` 끝에 develop 의 #620(수신자 열람 화면에서 발신자용 UI 제거)과 이 브랜치의 #619 가 각각 문자열을 덧붙여 위치가 겹쳤다. 내용이 부딪힌 게 아니므로 양쪽을 모두 남기고 블록 순서만 정리한다. 검증 — :feature:receiver:presentation:testDebugUnitTest · ktlintCheck · :app:compileDebugUnitTestKotlin 전부 BUILD SUCCESSFUL. develop 이 이 브랜치의 baseline 3장(SocialNetworkReceivedDetail)은 건드리지 않았다.
서버는 수신자 상세(
GET receiver-auth/after-notes/{id})에credentials를 내려주지 않는다. 그런데 presentation 매퍼가orEmpty()로 빈 문자열을 채워, 화면이 없는 비밀번호에••••••••마스킹과 「표시」 토글을 그렸다. 수신자는 가려진 값이 있다고 믿고 「표시」 를 눌렀지만 드러나는 건 빈 문자열이었다.Closes #619
무엇을 바꿨나
부재를 폴백이 아니라 타입으로 옮겼다.
accountId: String = ""·password: String = ""credentials: ReceivedAccountCredentialsUiModel?(내부 두 필드도 각각 nullable)credentials?.id.orEmpty()null로 접고, 양쪽 다 없으면 모델 자체를 만들지 않는다ReceivedAccountCredentialsUiModel이 존재하면 최소 한쪽에는 값이 있다 — 이 불변식을 매퍼가 지킨다. 덕분에 화면에는 "빈 문자열인데 값인 척" 하는 상태가 도달할 수 없다.문구는 afternote 모듈이 아니라 receiver 모듈
strings.xml에 뒀다 (#1066 리소스 정리 방향).화면
스크린샷 baseline 을 세 상태로 확장했다. 왼쪽이 이 PR 이 고치는 상태다.
마스킹·토글 없음
그 행의 토글만 사라짐
(회귀 없음)
검증
:feature:receiver:presentation:ktlintCheck:app:compileDebugUnitTestKotlin:konsist:test·:app:compileDebugAndroidTestKotlinupdateDebugScreenshotTestBUILD SUCCESSFULvalidateDebugScreenshotTest리뷰어에게
receiver_detail_account_absent한 줄이면 된다.credentials를 안 준다」 는 BE 쪽 별도 등록 건이다. 서버가 나중에 필드를 주더라도 「발신자가 계정을 안 남긴 경우」 는 계속 존재하므로 이 처리는 그대로 유효하다.credentials가 없다는 사실은 이슈 본문에 실기기 실측 기록(응답 JSON)이 이미 있다.