diff --git a/core/ui/src/main/kotlin/com/afternote/core/ui/topbar/HomeTopBar.kt b/core/ui/src/main/kotlin/com/afternote/core/ui/topbar/HomeTopBar.kt
index 0e6c4c5742..8b24a9d6aa 100644
--- a/core/ui/src/main/kotlin/com/afternote/core/ui/topbar/HomeTopBar.kt
+++ b/core/ui/src/main/kotlin/com/afternote/core/ui/topbar/HomeTopBar.kt
@@ -13,11 +13,17 @@ import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.Role
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.afternote.core.ui.R
+/** 프로필 아이콘 앵커. 장식이라 semantics 이름이 없어 테스트가 이 태그로 존재 여부를 본다. */
+const val PROFILE_ICON_TEST_TAG = "home_top_bar_profile"
+
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HomeTopBar(
@@ -44,10 +50,13 @@ fun HomeTopBar(
.padding(end = 25.dp),
) {
if (showProfileIcon) {
+ // 목적지가 없어 어디서도 눌리지 않는다 — 장식이므로 이름을 붙이지 않는다.
+ // 이름을 주면 TalkBack 이 포커스 가능한 노드로 읽어, 사용자가 액션이 있다고
+ // 믿고 탭했다가 아무 반응도 얻지 못한다 (#613 리뷰).
Image(
painter = painterResource(R.drawable.core_ui_user),
contentDescription = null,
- modifier = Modifier.size(18.dp),
+ modifier = Modifier.size(18.dp).testTag(PROFILE_ICON_TEST_TAG),
)
Spacer(modifier = Modifier.width(15.dp))
@@ -55,11 +64,13 @@ fun HomeTopBar(
Image(
painter = painterResource(R.drawable.core_ui_settings),
- contentDescription = null,
+ // 유일하게 눌리는 액션인데 접근성 트리에 이름이 없었다 — 스크린리더가
+ // "버튼" 으로만 읽는다 (#613).
+ contentDescription = stringResource(R.string.core_ui_home_top_bar_setting),
modifier =
Modifier
.size(18.dp)
- .clickable { onSettingClick() },
+ .clickable(role = Role.Button) { onSettingClick() },
)
}
},
diff --git a/core/ui/src/main/res/values/strings.xml b/core/ui/src/main/res/values/strings.xml
index e30bac9ebe..caa01e4e4d 100644
--- a/core/ui/src/main/res/values/strings.xml
+++ b/core/ui/src/main/res/values/strings.xml
@@ -26,4 +26,6 @@
네트워크 연결 오류
인터넷 연결을 확인한 후 다시 시도해 주세요.
다시 시도하기
+
+ 설정
\ No newline at end of file
diff --git a/docs/qa/assumptions.md b/docs/qa/assumptions.md
index d975e56e8b..0e2a212d3c 100644
--- a/docs/qa/assumptions.md
+++ b/docs/qa/assumptions.md
@@ -259,6 +259,15 @@ Compose 테스트로 고정했다.
스키마에 `date` 없음, 보내도 무시됨을 실측). 날짜 선택이 표시 전용인 문제는 BE 계약
확장이나 기획 결정이 필요해 #1008 로 분리했다.
+## #613 — 수신자 홈 설정 진입 (판단 보류)
+
+- 시안(수신자 섹션 `4327:73626`)의 수신자 홈 헤더에는 **톱니만** 있고 프로필 아이콘이 없다.
+ 코드도 이미 `showProfileIcon = false` 라 1번 지적은 해소된 상태였고, 재발 방지 가드만 붙였다.
+- 톱니의 목적지는 확정하지 못했다. 같은 섹션의 「설정 메인」(`4327:75979`)은 회원 설정
+ 화면(프로필 수정·비밀번호 변경·로그아웃)을 그대로 복제한 것이라 **수신자 전용 설정
+ 시안은 없다**. 수신자는 X-Auth-Code 기반이라 로그아웃할 세션이 없다.
+- 현 배선은 회원 설정 그래프(`Route.Setting`)로 그대로 보낸다. 무엇을 남길지(고객지원만,
+ 인증 해제, 진입점 제거)는 기획·디자인 확정이 필요해 이번 PR 범위에서 제외했다.
## #793 — MEMORIES 카드 「그날의 기록 다시 읽기」 목적지 (임시 승계)
- **최종 목적지는 여전히 미확정이다.** Figma 카드 노드(`109:15028`)의 이 버튼에는 프로토타입
diff --git a/feature/receiver/presentation/src/test/kotlin/com/afternote/feature/receiver/presentation/home/ReceiverHomeHeaderTest.kt b/feature/receiver/presentation/src/test/kotlin/com/afternote/feature/receiver/presentation/home/ReceiverHomeHeaderTest.kt
new file mode 100644
index 0000000000..e5a603be18
--- /dev/null
+++ b/feature/receiver/presentation/src/test/kotlin/com/afternote/feature/receiver/presentation/home/ReceiverHomeHeaderTest.kt
@@ -0,0 +1,69 @@
+package com.afternote.feature.receiver.presentation.home
+
+import androidx.activity.ComponentActivity
+import androidx.compose.ui.test.assertHasClickAction
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.junit4.createAndroidComposeRule
+import androidx.compose.ui.test.onNodeWithContentDescription
+import androidx.compose.ui.test.onNodeWithTag
+import com.afternote.core.ui.R
+import com.afternote.core.ui.theme.AfternoteTheme
+import com.afternote.core.ui.topbar.PROFILE_ICON_TEST_TAG
+import com.afternote.feature.receiver.presentation.home.model.ReceiverHomeUiState
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.Config
+
+/**
+ * 수신자 홈 헤더가 수신자가 실제로 할 수 있는 액션만 두는지 (#613, 시안 4327:73626).
+ *
+ * 종전에는 회원 홈과 같은 상단바를 그대로 써서 프로필 아이콘이 함께 떴는데, 목적지가
+ * 없어 탭해도 아무 일도 없었다 — 접근성 트리에서도 clickable 이 아니라 사실상 장식이다.
+ * 시안의 수신자 홈에도 톱니 하나뿐이라 그 상태를 고정한다.
+ *
+ * 설정 아이콘의 이름도 함께 고정한다. 종전에는 둘 다 `contentDescription = null` 이라
+ * 스크린리더가 **유일하게 눌리는 액션**조차 읽어 주지 못했다. 프로필 아이콘은 반대로
+ * 이름을 두지 않는다 — 목적지가 없어 어디서도 눌리지 않는 장식이고, 이름을 주면 TalkBack 이
+ * 포커스 가능한 노드로 읽어 «눌러도 아무 일 없는 버튼» 이 된다 (리뷰 지적).
+ */
+@RunWith(RobolectricTestRunner::class)
+@Config(sdk = [35])
+class ReceiverHomeHeaderTest {
+ @get:Rule
+ val composeRule = createAndroidComposeRule()
+
+ @Test
+ fun `수신자 홈에는 프로필 아이콘이 없다`() {
+ composeRule.setContent {
+ AfternoteTheme {
+ ReceiverHomeScreen(
+ uiState = ReceiverHomeUiState.Loading,
+ onEvent = {},
+ actions = ReceiverHomeActions(),
+ )
+ }
+ }
+
+ // 프로필 아이콘은 목적지가 없는 장식이라 semantics 이름이 없다 — 테스트 태그로 본다.
+ composeRule.onNodeWithTag(PROFILE_ICON_TEST_TAG).assertDoesNotExist()
+ }
+
+ @Test
+ fun `설정 아이콘은 이름이 있고 눌린다`() {
+ var settingClicks = 0
+ composeRule.setContent {
+ AfternoteTheme {
+ ReceiverHomeScreen(
+ uiState = ReceiverHomeUiState.Loading,
+ onEvent = {},
+ actions = ReceiverHomeActions(onSettingClick = { settingClicks += 1 }),
+ )
+ }
+ }
+
+ val setting = composeRule.activity.getString(R.string.core_ui_home_top_bar_setting)
+ composeRule.onNodeWithContentDescription(setting).assertIsDisplayed().assertHasClickAction()
+ }
+}