diff --git a/docs/exec-plans/active/2026-09-01-profile-room-request-polish/api-contract.md b/docs/exec-plans/active/2026-09-01-profile-room-request-polish/api-contract.md new file mode 100644 index 00000000..1a9f1797 --- /dev/null +++ b/docs/exec-plans/active/2026-09-01-profile-room-request-polish/api-contract.md @@ -0,0 +1,6 @@ +# API Contract + +- `PATCH /api/v1/user-profiles/me`의 기존 `statusMessage` 필드와 payload 형태를 그대로 사용한다. +- 최애곡 입력은 줄바꿈을 공백으로 정규화한 뒤 최대 40자까지만 전송한다. +- 방 수정과 노래 신청 endpoint, payload, cache invalidation에는 변경이 없다. +- `https://api.queuing.cc`의 일반적인 OpenAPI/Swagger 공개 경로는 2026-09-01 확인 시 모두 404였다. 따라서 새 서버 최대 길이를 추정해 타입을 바꾸지 않고, 기존 255자 프런트 계약보다 보수적인 40자 제한만 적용한다. diff --git a/docs/exec-plans/active/2026-09-01-profile-room-request-polish/change-summary.md b/docs/exec-plans/active/2026-09-01-profile-room-request-polish/change-summary.md new file mode 100644 index 00000000..b05837e0 --- /dev/null +++ b/docs/exec-plans/active/2026-09-01-profile-room-request-polish/change-summary.md @@ -0,0 +1,8 @@ +# Change Summary + +- 최애곡 상한을 40자로 늘리고 접근성 안내와 카운터를 같은 상수로 통일했다. +- 방·친구 공개 프로필의 두 줄 최애곡 경로에서 말줄임을 제거하고 최소 두 줄 공간을 확보했다. +- 방 편집 모달을 방 본문 셸과 같은 688px/550.4px 너비로 맞췄다. +- 방 편집 select·참여 제한·footer 액션이 density별 하나의 높이 변수를 공유하도록 정리했다. +- 노래 신청의 사연 문구와 검증 오류를 `노래 선정 이유`로 바꾸고 하단 액션에 pill hover/focus 배경을 추가했다. +- YouTube URL input 글자 크기를 normal/mobile/compact 각각의 label 크기와 맞췄다. diff --git a/docs/exec-plans/active/2026-09-01-profile-room-request-polish/delivery-state.md b/docs/exec-plans/active/2026-09-01-profile-room-request-polish/delivery-state.md new file mode 100644 index 00000000..c37e8ed7 --- /dev/null +++ b/docs/exec-plans/active/2026-09-01-profile-room-request-polish/delivery-state.md @@ -0,0 +1,12 @@ +# Delivery State + +- status: ready +- branch: dev +- base: main +- issue: +- pr: https://github.com/Queuing-org/frontend/pull/59 +- selected_skills: queuing-feature-delivery, queuing-orchestrator, queuing-api-boundary, queuing-ui-flow, frontend-architecture-guardrails, queuing-qa-reviewer, browser:control-in-app-browser +- local_qa: targeted 6 files/44 tests, lint, 152 files/650 tests, build, diff-check, fresh review passed +- ci: GitHub Actions lint/test/build, Vercel, Vercel Preview Comments, CodeRabbit passed +- review_threads: none at publication +- next_action: human review and optional authenticated browser pixel QA diff --git a/docs/exec-plans/active/2026-09-01-profile-room-request-polish/handoff.md b/docs/exec-plans/active/2026-09-01-profile-room-request-polish/handoff.md new file mode 100644 index 00000000..7a84ca42 --- /dev/null +++ b/docs/exec-plans/active/2026-09-01-profile-room-request-polish/handoff.md @@ -0,0 +1,10 @@ +# Handoff + +- Branch: `dev` +- Draft PR: #59 — https://github.com/Queuing-org/frontend/pull/59 +- Implementation, targeted tests, full lint/test/build, diff-check, fresh read-only QA are complete. +- Browser visual QA remains because no browser instance was available. +- Feature slices and verification documents are pushed to `dev`. +- Existing PR #58 merged before the latest push, so its metadata was restored to the merged scope and the new commits were published in Draft PR #59. +- GitHub Actions lint/test/build, Vercel, Vercel Preview Comments, and CodeRabbit checks passed. +- Next action: human review and optional authenticated browser pixel QA. diff --git a/docs/exec-plans/active/2026-09-01-profile-room-request-polish/plan.md b/docs/exec-plans/active/2026-09-01-profile-room-request-polish/plan.md new file mode 100644 index 00000000..bb485631 --- /dev/null +++ b/docs/exec-plans/active/2026-09-01-profile-room-request-polish/plan.md @@ -0,0 +1,59 @@ +# 프로필·방 편집·노래 신청 UI 후속 정리 + +## Scope + +- 설정 최애곡 입력 상한을 20자에서 40자로 늘리고 공개 프로필에서 말줄임 없이 여러 줄로 표시한다. +- 방 편집 모달 너비를 방 내부 메인 컨테이너 너비와 맞춘다. +- 방 편집 하단 삭제·완료 버튼 높이를 같은 화면의 드롭다운 높이와 맞춘다. +- 노래 신청의 `사연 (선택)` 문구를 `노래 선정 이유 (선택)`로 변경하고 하단 액션에 pill hover/focus 배경을 적용한다. +- YouTube URL 입력 글자 크기를 같은 필드의 라벨 크기와 맞춘다. +- `dev`에 커밋·푸시한다. 게시 중 PR #58이 먼저 병합되어 이번 변경은 새 Draft PR #59로 전달한다. + +## Selected Skills + +- `queuing-feature-delivery` +- `queuing-orchestrator` +- `queuing-api-boundary` +- `queuing-ui-flow` +- `frontend-architecture-guardrails` +- `queuing-qa-reviewer` + +## Ownership Decisions + +- 최애곡 입력 상한과 저장 전 정규화는 기존 settings form model/hook이 계속 소유한다. +- 프로필 줄바꿈은 공유 `UserProfileContent`가 소유해 방·친구 프로필에 동일하게 적용한다. +- 방 편집 치수는 `EditRoomFormModal.module.css`에서 방 메인 셸의 normal/compact 치수와 동일하게 관리한다. +- 노래 신청 문구와 입력/액션 표현은 add-track UI와 CSS module에서만 변경한다. + +## Commit Slices + +1. `fix(ui): 프로필과 방 편집 치수를 정리` +2. `fix(playlist): 노래 신청 문구와 입력 스타일 정리` +3. `docs(delivery): UI 후속 검증 기록` + +## Acceptance Criteria + +- 최애곡은 최대 40자까지 입력·저장 payload에 유지되고 카운터와 접근성 설명도 40자를 안내한다. +- 두 줄 프로필에서 최애곡은 말줄임표 없이 자연스럽게 줄바꿈되고 최소 두 줄 높이를 확보한다. +- 방 편집 모달은 normal 688px, compact 550.4px이며 좁은 화면에서는 기존 반응형 제한을 유지한다. +- 방 편집 삭제·완료 버튼은 normal 56px, compact 44.8px, mobile 52px로 같은 화면의 select 높이와 일치한다. +- 노래 신청 이유 문구, pill hover/focus, URL 입력·라벨 글자 크기가 회귀 테스트와 CSS 검토를 통과한다. +- `npm run lint`, `npm run test`, `npm run build`, `git diff --check`, fresh read-only QA가 통과한다. + +## Progress + +- [x] 요청과 관련 경계 확인 +- [x] 구현 및 대상 테스트 보강 +- [x] 전체 로컬 검증 +- [x] Fresh read-only QA +- [x] `dev` 커밋·푸시 및 Draft PR #59 게시 + +## Residual Risk + +- 배포 API의 공개 OpenAPI 경로가 404라 `statusMessage`의 현재 서버 최대 길이는 문서로 재검증하지 못했다. 프런트엔드의 과거 계약은 255자였고 이번 전송 형태는 변경하지 않는다. +- 실제 글자 폭은 언어와 글꼴에 따라 달라진다. 말줄임 대신 자연 줄바꿈을 사용해 제목 손실을 피한다. +- in-app Browser에 연결 가능한 브라우저 인스턴스가 없어 실제 화면 스크린샷 QA는 수행하지 못했다. + +## Publication Note + +- 기존 PR #58은 이번 커밋 push 전에 병합되었다. 병합된 PR의 제목·본문은 원래 범위로 복구하고, `origin/main..dev`의 새 커밋 3개를 Draft PR #59로 게시했다. diff --git a/docs/exec-plans/active/2026-09-01-profile-room-request-polish/qa-report.md b/docs/exec-plans/active/2026-09-01-profile-room-request-polish/qa-report.md new file mode 100644 index 00000000..1e4e58c1 --- /dev/null +++ b/docs/exec-plans/active/2026-09-01-profile-room-request-polish/qa-report.md @@ -0,0 +1,29 @@ +# QA Report + +## Automated Verification + +- targeted: 6 files / 44 tests passed +- `npm run lint`: passed +- `npm run test`: passed — 152 files / 650 tests +- `npm run build`: passed +- `git diff --check`: passed + +## Boundary Review + +- Fresh read-only reviewer: `pass`; blocking finding 없음. +- `statusMessage` payload key와 update mutation/cache 흐름은 변경하지 않고 최대 길이 정규화만 40자로 확장했다. +- 방 편집 modal normal/compact 너비는 방 메인 container 계산값과 일치한다. +- select·참여 제한·footer 버튼은 `--edit-room-control-height`를 공유해 normal/mobile/compact cascade가 일치한다. +- add-track API `story` key와 submit state는 유지하고 사용자 문구와 CSS interaction만 변경했다. +- YouTube URL input과 label은 normal 16px, mobile 20px, compact 12.8px로 일치한다. + +## Residual Risk + +- 배포 API의 공개 OpenAPI/Swagger 경로가 404라 `statusMessage`의 실제 서버 상한은 통합 확인이 남아 있다. 과거 프런트 계약은 255자였고 이번 상한은 40자다. +- in-app Browser에 사용 가능한 브라우저가 없어 computed layout과 실제 hover를 스크린샷으로 확인하지 못했다. CSS 소스·빌드·fresh review까지만 검증했다. + +## Publication + +- `dev` push passed. +- 기존 PR #58이 push 전에 병합되어 새 변경은 Draft PR #59로 게시했다. +- Draft PR #59 checks passed: GitHub Actions lint/test/build, Vercel, Vercel Preview Comments, CodeRabbit. diff --git a/docs/exec-plans/active/2026-09-01-profile-room-request-polish/request-summary.md b/docs/exec-plans/active/2026-09-01-profile-room-request-polish/request-summary.md new file mode 100644 index 00000000..cfac00a2 --- /dev/null +++ b/docs/exec-plans/active/2026-09-01-profile-room-request-polish/request-summary.md @@ -0,0 +1,6 @@ +# Request Summary + +- 프로필 최애곡이 20자 제한과 한 줄 높이 때문에 충분히 보이지 않는 문제를 개선한다. +- 방 편집창의 너비를 방 내부 컨테이너와 맞추고 하단 액션 높이를 드롭다운과 맞춘다. +- 노래 신청 사연 문구를 노래 선정 이유로 바꾸고 hover 배경을 pill 형태로 만든다. +- YouTube 링크 입력 글자 크기를 필드 라벨과 같게 만든다. diff --git a/docs/exec-plans/active/2026-09-01-profile-room-request-polish/ui-flow.md b/docs/exec-plans/active/2026-09-01-profile-room-request-polish/ui-flow.md new file mode 100644 index 00000000..c8ea6ed3 --- /dev/null +++ b/docs/exec-plans/active/2026-09-01-profile-room-request-polish/ui-flow.md @@ -0,0 +1,8 @@ +# UI Flow + +- 설정 최애곡 input과 카운터는 40자를 기준으로 동작하고 기존 즉시 draft/완료 저장 흐름을 유지한다. +- 방·친구 프로필의 최애곡은 공유 컴포넌트에서 말줄임 없이 줄바꿈하며 두 줄 분량의 기본 공간을 확보한다. +- 방 편집 모달은 방 메인 셸의 normal/compact 너비를 따르고 mobile에서는 기존 viewport 여백을 유지한다. +- 방 편집 footer 버튼은 각 density의 select 높이와 동일하다. +- 노래 신청 모달은 필드 라벨을 `노래 선정 이유 (선택)`로 표시하고 취소·큐잉 액션에 hover/focus-visible pill 배경을 제공한다. +- YouTube URL input은 normal/mobile/compact에서 각각 같은 화면의 label 글자 크기를 사용한다. diff --git a/docs/exec-plans/active/2026-09-01-room-self-participant-menu/api-contract.md b/docs/exec-plans/active/2026-09-01-room-self-participant-menu/api-contract.md new file mode 100644 index 00000000..9cf849ee --- /dev/null +++ b/docs/exec-plans/active/2026-09-01-room-self-participant-menu/api-contract.md @@ -0,0 +1,7 @@ +# Participant Identity Contract + +- `ROOM_JOINED.data.participant` is the authoritative identity for the current room session. +- Initial join and every reconnect join update the room screen's current participant state. +- Cursor participant pages remain the server-state source for the list. The current joined participant is prepended only when neither its `participantId` nor non-null `userSlug` is present. +- When a fetched page already contains the current user, the fetched participant object wins so refreshed nickname/profile fields are not replaced by stale join data. +- Room access tokens remain excluded from URLs, logs, and query keys; this change adds no endpoint or payload mutation. diff --git a/docs/exec-plans/active/2026-09-01-room-self-participant-menu/change-summary.md b/docs/exec-plans/active/2026-09-01-room-self-participant-menu/change-summary.md new file mode 100644 index 00000000..693ce153 --- /dev/null +++ b/docs/exec-plans/active/2026-09-01-room-self-participant-menu/change-summary.md @@ -0,0 +1,6 @@ +# Change Summary + +- 내 참가자 행을 목록 첫 번째로 정렬하고 `(나)` 표시를 추가했다. +- 내 더보기 메뉴에서 기존 Setting/Friends modal을 열도록 연결했다. +- 최초 입장과 reconnect의 `ROOM_JOINED` participant identity를 보존해 cursor page 밖의 자기 행도 보장했다. +- participant identity, virtual list/menu, mobile/desktop modal, room join/reconnect 회귀 테스트를 추가했다. diff --git a/docs/exec-plans/active/2026-09-01-room-self-participant-menu/delivery-state.md b/docs/exec-plans/active/2026-09-01-room-self-participant-menu/delivery-state.md new file mode 100644 index 00000000..5fcce655 --- /dev/null +++ b/docs/exec-plans/active/2026-09-01-room-self-participant-menu/delivery-state.md @@ -0,0 +1,12 @@ +# Delivery State + +- status: ci-pending +- branch: dev +- base: main +- issue: +- pr: https://github.com/Queuing-org/frontend/pull/59 +- selected_skills: queuing-feature-delivery, queuing-api-boundary, queuing-ui-flow, frontend-architecture-guardrails, queuing-qa-reviewer +- local_qa: lint, 660 tests, and production build passed; browser session unavailable +- ci: pending +- review_threads: not-checked +- next_action: inspect PR #59 CI and review feedback when requested diff --git a/docs/exec-plans/active/2026-09-01-room-self-participant-menu/handoff.md b/docs/exec-plans/active/2026-09-01-room-self-participant-menu/handoff.md new file mode 100644 index 00000000..86041e53 --- /dev/null +++ b/docs/exec-plans/active/2026-09-01-room-self-participant-menu/handoff.md @@ -0,0 +1,7 @@ +# Handoff + +- status: ci-pending +- completed: implementation, targeted tests, lint, full tests, build, final fresh QA pass, commit, push, Draft PR #59 update +- blocker: none +- next_action: inspect Draft PR #59 CI and review feedback when requested +- prohibited: do not force-push, merge, or mark the PR ready without explicit user request diff --git a/docs/exec-plans/active/2026-09-01-room-self-participant-menu/plan.md b/docs/exec-plans/active/2026-09-01-room-self-participant-menu/plan.md new file mode 100644 index 00000000..6cc6c26d --- /dev/null +++ b/docs/exec-plans/active/2026-09-01-room-self-participant-menu/plan.md @@ -0,0 +1,57 @@ +# Room Self Participant Menu + +## Scope + +- 현재 로그인 사용자를 참가자 목록 첫 행으로 안정 정렬한다. +- 내 닉네임 오른쪽, 방장 왕관 왼쪽에 `(나)`를 표시한다. +- 내 참가자 행의 더보기 메뉴에서 기존 Settings/Friends modal을 연다. + +## Acceptance Criteria + +- 정렬은 query data를 변경하지 않고 나머지 참가자 순서를 보존한다. +- `(나)`는 `#3c3c3c`이며 방장 행은 `닉네임 → (나) → 왕관` 순서다. +- 내 행 메뉴는 `Setting`, `Friends`만 표시하고 hover, focus, Escape, outside-click 동작은 기존 참가자 메뉴와 같다. +- 데스크톱 draggable panel과 모바일 참가자 탭 모두 같은 modal owner를 사용한다. +- 다른 참가자의 관리 액션과 참가자 DOM 상한은 회귀하지 않는다. + +## Decisions + +- 사용자가 선택한 대로 내 행은 첫 번째 정렬만 적용하고 scroll sticky는 적용하지 않는다. +- 현재 사용자는 `currentUser.slug`와 participant `userSlug`로 판별한다. +- modal visibility는 `RoomPlaybackJoinedContent`의 local state가 소유한다. +- 실제 `SettingsModal`, `FollowModal`은 draggable transform 밖에 렌더링한다. +- 비로그인 guest에는 자기 표시와 로그인 전용 메뉴를 추가하지 않는다. + +## Selected Skills + +- `queuing-feature-delivery` +- `queuing-api-boundary` +- `queuing-ui-flow` +- `frontend-architecture-guardrails` +- `queuing-qa-reviewer` + +## Commit Plan + +1. `feat(room): 참가자 목록에 내 메뉴와 모달 진입 추가` + +## Progress + +- [x] request와 현재 component/modal ownership 확인 +- [x] implementation 및 component tests +- [x] lint, test, build +- [x] fresh QA review — final pass +- [x] local commit +- [x] push, Draft PR #59 갱신 + +## Verification + +- `npm test -- src/features/room/page/hooks/useRoomRealtimeEvents.test.tsx src/features/room/page/ui/RoomPlaybackScreen.test.tsx src/features/room/page/ui/RoomPlaybackJoinedContent.test.tsx src/features/room/participants/model/participantIdentity.test.ts src/features/room/participants/ui/RoomParticipantList.test.tsx src/features/room/participants/ui/RoomParticipantsPanel.test.tsx` — 6 files, 50 tests passed +- `npm run lint` — passed +- `npm run test` — 153 files, 660 tests passed +- `npm run build` — passed +- local browser smoke — browser session unavailable; component integration tests cover mobile/desktop modal ownership + +## Residual Risk + +- 실제 로그인 방의 시각 smoke는 사용할 수 있는 browser session이 없어 자동 수행하지 못했다. +- modal close 후 원래 참가자 trigger로 focus를 복원하는 별도 계약은 기존 home modal에도 없어 이번 변경에서는 추가하지 않았다. diff --git a/docs/exec-plans/active/2026-09-01-room-self-participant-menu/qa-report.md b/docs/exec-plans/active/2026-09-01-room-self-participant-menu/qa-report.md new file mode 100644 index 00000000..75866f28 --- /dev/null +++ b/docs/exec-plans/active/2026-09-01-room-self-participant-menu/qa-report.md @@ -0,0 +1,37 @@ +# QA Report + +## Result + +- classification: pass +- reviewer: fresh read-only agent after two targeted fix rounds +- blocking findings: none + +## Findings Resolved + +1. 최초 참가자 cursor page에 현재 사용자가 없으면 자기 행이 사라지는 문제 + - `ROOM_JOINED.data.participant`를 화면 state에 보존하고 page 결과에 identity 중복 없이 포함했다. + - 101명 방에서 현재 참가자가 첫 page 밖인 화면 회귀 테스트를 추가했다. +2. reconnect `ROOM_JOINED`의 최신 참가자 객체를 버리는 문제 + - `useRoomRealtimeEvents`가 최신 participant를 화면 callback으로 전달한다. + - 변경된 participantId와 nickname을 저장하는 reconnect 회귀 테스트를 추가했다. + +## Boundary Review + +- 현재 사용자는 첫 행 정렬만 적용하며 sticky row를 만들지 않는다. +- `(나)` DOM 순서와 `#3c3c3c` 색상이 요청과 일치한다. +- self menu는 `Setting`, `Friends`만 제공하고 기존 viewport portal/focus shell을 사용한다. +- 기존 Settings/Friends modal을 draggable transform 밖의 room screen owner가 렌더링한다. +- 다른 참가자 관리 액션과 virtual DOM 24개 상한을 유지한다. + +## Verification + +- targeted: 6 files, 50 tests passed +- lint: passed +- full test: 153 files, 660 tests passed +- production build: passed +- browser smoke: unavailable because no browser session was connected + +## Residual Risk + +- 실제 로그인 방과 작은 모바일 실기기의 시각 smoke가 남아 있다. +- modal close 후 참가자 trigger focus 복원은 기존 home modal에도 없는 접근성 부채다. diff --git a/docs/exec-plans/active/2026-09-01-room-self-participant-menu/ui-flow.md b/docs/exec-plans/active/2026-09-01-room-self-participant-menu/ui-flow.md new file mode 100644 index 00000000..d941a866 --- /dev/null +++ b/docs/exec-plans/active/2026-09-01-room-self-participant-menu/ui-flow.md @@ -0,0 +1,15 @@ +# UI Flow + +1. 참가자 목록은 로그인한 현재 사용자 행을 첫 번째로 파생 정렬한다. +2. 내 행 hover 또는 keyboard focus 시 기존과 같은 더보기 trigger가 나타난다. +3. trigger를 열면 `Setting`, `Friends` menuitem만 표시된다. +4. menuitem 선택은 menu를 닫고 방 화면의 단일 modal state를 갱신한다. +5. 방 화면은 draggable widget 밖에서 기존 `SettingsModal` 또는 `FollowModal`을 렌더링한다. +6. modal close는 room modal state를 `null`로 되돌린다. + +## Ownership + +- 정렬과 열린 참가자 menu: `RoomParticipantList` +- 참가자 행 trigger와 self/member menu 선택: `RoomParticipantCard` +- Settings/Friends modal visibility: `RoomPlaybackJoinedContent` +- modal 내부 tab/form/follow state: 기존 modal component diff --git a/docs/exec-plans/active/README.md b/docs/exec-plans/active/README.md index 4f33775a..a6bab59e 100644 --- a/docs/exec-plans/active/README.md +++ b/docs/exec-plans/active/README.md @@ -1,5 +1,9 @@ # Active Execution Plans +- [2026-09-01-room-self-participant-menu](./2026-09-01-room-self-participant-menu/plan.md): ci-pending — Draft PR #59, 내 참가자 첫 행·`(나)`·Settings/Friends modal과 reconnect identity QA 통과 + +- [2026-09-01-profile-room-request-polish](./2026-09-01-profile-room-request-polish/plan.md): ready — Draft PR #59, 최애곡 두 줄 표시·방 편집 치수·노래 신청 문구와 hover/타이포 구현 및 로컬·CI QA 통과 + - [2026-09-01-automatic-replay-state](./2026-09-01-automatic-replay-state/plan.md): ci-pending — 자동 순환 상태를 59px 아이콘과 `100cqh` 기반 list viewport 중앙으로 교정하고 로컬 QA·fresh review 통과 - [2026-09-01-settings-badge-tooltip](./2026-09-01-settings-badge-tooltip/plan.md): ci-pending — Draft PR #58에 설정 칭호 acquisitionRate 정규화와 접근성 리스트박스·획득 상세 portal tooltip 게시 완료 diff --git a/src/features/playlist/add-track/hooks/useAddTrackAction.test.tsx b/src/features/playlist/add-track/hooks/useAddTrackAction.test.tsx index 7d547d1f..7cf28903 100644 --- a/src/features/playlist/add-track/hooks/useAddTrackAction.test.tsx +++ b/src/features/playlist/add-track/hooks/useAddTrackAction.test.tsx @@ -184,11 +184,11 @@ describe("useAddTrackAction", () => { expect(mocks.setError).toHaveBeenCalledWith( "story", - "사연은 30자 이하로 입력해주세요.", + "노래 선정 이유는 30자 이하로 입력해주세요.", ); expect(mocks.notify).toHaveBeenCalledWith({ dedupeKey: "add-track:room:story", - message: "사연은 30자 이하로 입력해주세요.", + message: "노래 선정 이유는 30자 이하로 입력해주세요.", tone: "error", }); }); diff --git a/src/features/playlist/add-track/hooks/useAddTrackAction.ts b/src/features/playlist/add-track/hooks/useAddTrackAction.ts index 4b95fc49..58bbef87 100644 --- a/src/features/playlist/add-track/hooks/useAddTrackAction.ts +++ b/src/features/playlist/add-track/hooks/useAddTrackAction.ts @@ -193,7 +193,7 @@ export function useAddTrackAction(slug: string, roomAccessToken: string) { const story = form.storyValue.trim(); if (story.length > ADD_TRACK_STORY_MAX_LENGTH) { - showError("story", "사연은 30자 이하로 입력해주세요."); + showError("story", "노래 선정 이유는 30자 이하로 입력해주세요."); return; } diff --git a/src/features/playlist/add-track/ui/AddTrackFormFields.test.tsx b/src/features/playlist/add-track/ui/AddTrackFormFields.test.tsx index 5e690f68..6cc0bc8f 100644 --- a/src/features/playlist/add-track/ui/AddTrackFormFields.test.tsx +++ b/src/features/playlist/add-track/ui/AddTrackFormFields.test.tsx @@ -19,6 +19,17 @@ function renderFields(errorField: "url" | "story") { } describe("AddTrackFormFields", () => { + it("신청 사연을 노래 선정 이유로 안내한다", () => { + renderFields("url"); + + expect(screen.getByText("노래 선정 이유 (선택)")).toBeInTheDocument(); + expect( + screen.getByPlaceholderText( + "이 노래를 선정한 이유나 전하고 싶은 말을 적어주세요", + ), + ).toBeInTheDocument(); + }); + it("URL 오류를 URL 입력의 aria-invalid와 SR 설명에 연결한다", () => { renderFields("url"); @@ -33,7 +44,7 @@ describe("AddTrackFormFields", () => { renderFields("story"); const textarea = screen.getByPlaceholderText( - "함께 듣고 싶은 이유나 전하고 싶은 말을 적어주세요", + "이 노래를 선정한 이유나 전하고 싶은 말을 적어주세요", ); expect(textarea).toHaveAttribute("aria-invalid", "true"); expect(textarea).toHaveAttribute("aria-describedby", "add-track-error"); diff --git a/src/features/playlist/add-track/ui/AddTrackFormFields.tsx b/src/features/playlist/add-track/ui/AddTrackFormFields.tsx index 1874755a..8fa863b3 100644 --- a/src/features/playlist/add-track/ui/AddTrackFormFields.tsx +++ b/src/features/playlist/add-track/ui/AddTrackFormFields.tsx @@ -55,7 +55,7 @@ export default function AddTrackFormFields({