diff --git a/.jules/palette.md b/.jules/palette.md index bd0f73248..be35271c6 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -57,3 +57,6 @@ ## 2026-07-30 - Add window.confirm for destructive actions **Learning:** Destructive actions like deleting groups and edge relationships previously occurred immediately without user confirmation. **Action:** Always wrap delete operations with window.confirm() dialogs and ensure corresponding tests successfully mock window.confirm. +## 2026-08-25 - [Table Modal Action Context] +**Learning:** 모달 창 내의 액션 버튼(예: '복제', '테이블 삭제')이 단순히 동작 이름만 가지고 있으면, 스크린 리더 사용자는 어떤 대상을 복제하거나 삭제하는지 맥락을 잃을 수 있습니다. +**Action:** 현재 선택된 컨텍스트(예: 테이블 이름)를 포함하는 명시적인 `aria-label`을 액션 버튼에 추가하여, 시각적 정보 없이도 동작의 대상을 명확히 알 수 있도록 합니다. diff --git a/frontend/src/components/modals/EditTableModal.test.tsx b/frontend/src/components/modals/EditTableModal.test.tsx index 1a8c9af5e..cd52e9d0f 100644 --- a/frontend/src/components/modals/EditTableModal.test.tsx +++ b/frontend/src/components/modals/EditTableModal.test.tsx @@ -44,6 +44,8 @@ describe('EditTableModal', () => { expect(screen.getByRole('textbox', { name: 'test_col 데이터 타입' })).toBeInTheDocument(); expect(screen.getByRole('checkbox', { name: 'test_col PK 설정' })).toBeInTheDocument(); expect(screen.getByRole('checkbox', { name: 'test_col NN 설정' })).toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'test_table 테이블 삭제' })).toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'test_table 테이블 복제' })).toBeInTheDocument(); }); it('returns null if not open or no editingNode', () => { @@ -170,7 +172,7 @@ describe('EditTableModal', () => { render(); const user = userEvent.setup(); - await user.click(screen.getByRole('button', { name: '복제' })); + await user.click(screen.getByRole('button', { name: 'test_table 테이블 복제' })); expect(setNodesMock).toHaveBeenCalled(); expect(onEditTableCancelMock).toHaveBeenCalled(); diff --git a/frontend/src/components/modals/EditTableModal.tsx b/frontend/src/components/modals/EditTableModal.tsx index 998929d44..153407008 100644 --- a/frontend/src/components/modals/EditTableModal.tsx +++ b/frontend/src/components/modals/EditTableModal.tsx @@ -191,6 +191,7 @@ export function EditTableModal({ type="button" onClick={onDeleteTable} style={{ color: "#b91c1c", borderColor: "#fca5a5" }} + aria-label={`${editingNode.data.title} 테이블 삭제`} > 테이블 삭제 @@ -218,6 +219,7 @@ export function EditTableModal({ onEditTableCancel(); }} style={{ color: "#034ea2", borderColor: "#93c5fd" }} + aria-label={`${editingNode.data.title} 테이블 복제`} > 복제 diff --git a/frontend/src/components/modals/ModalCoverage.test.tsx b/frontend/src/components/modals/ModalCoverage.test.tsx index 8732f7efa..1553eb059 100644 --- a/frontend/src/components/modals/ModalCoverage.test.tsx +++ b/frontend/src/components/modals/ModalCoverage.test.tsx @@ -183,8 +183,8 @@ describe('modal behavior coverage', () => { expect(deleteEditing(tableNode)?.data.columns).toHaveLength(1) fireEvent.submit(document.getElementById('editTableForm')!) - fireEvent.click(screen.getByRole('button', { name: '테이블 삭제' })) - fireEvent.click(screen.getByRole('button', { name: '복제' })) + fireEvent.click(screen.getByRole('button', { name: 'public.users 테이블 삭제' })) + fireEvent.click(screen.getByRole('button', { name: 'public.users 테이블 복제' })) const duplicate = setNodes.mock.calls[2]?.[0] as (nodes: Node[]) => Node[] const duplicated = duplicate([tableNode])[1]! expect(duplicated).toMatchObject({