diff --git a/CHANGELOG.md b/CHANGELOG.md index 679a6202..3b7d2b4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,3 +11,4 @@ - [FE] `autoInfer.ts`에 대한 단위 테스트 및 UI 컴포넌트 단위 테스트를 추가하여 100% 테스트 커버리지를 유지합니다. - [FE] ⬇️ **DBML Export**: ERD 다이어그램을 DBML (Database Markup Language) 형식으로 내보낼 수 있는 기능을 추가했습니다. 상단의 DBML 버튼을 클릭하여 다운로드할 수 있습니다. - [FE] 📚 **Data Dictionary Export**: ERD 테이블/컬럼 메타데이터를 CSV 및 Markdown으로 내보내며, CSV formula injection과 Markdown 렌더링 escape를 적용했습니다. +- [FE] 🎨 **프로젝트 및 연결 생성 폼 엔터키 제출 지원**: 폼(`div` -> `form`) 요소를 통해 네이티브 HTML form 제출(Enter 키 동작)과 웹 접근성(WCAG 키보드 조작)을 개선했습니다. diff --git a/frontend/src/App.coverage.test.tsx b/frontend/src/App.coverage.test.tsx index 0b9a20aa..b7e554ec 100644 --- a/frontend/src/App.coverage.test.tsx +++ b/frontend/src/App.coverage.test.tsx @@ -347,20 +347,20 @@ describe('App orchestration coverage', () => { fireEvent.click(screen.getByRole('button', { name: '편집기' })) fireEvent.change(screen.getByLabelText('New project'), { target: { value: ' New ' } }) - fireEvent.click(screen.getByRole('button', { name: 'Create' })) + fireEvent.submit(screen.getByLabelText('New project').closest('form')!) await waitFor(() => expect(api.createProject).toHaveBeenCalledWith('New')) const dsn = screen.getByLabelText('Connection DSN') fireEvent.change(dsn, { target: { value: 'postgresql://[' } }) - fireEvent.click(screen.getByRole('button', { name: 'Save connection' })) + fireEvent.submit(screen.getByLabelText('Connection DSN').closest('form')!) expect(screen.getByRole('alert')).toHaveTextContent('Connection DSN must use') fireEvent.change(dsn, { target: { value: 'http://bad.example/db' } }) - fireEvent.click(screen.getByRole('button', { name: 'Save connection' })) + fireEvent.submit(screen.getByLabelText('Connection DSN').closest('form')!) expect(screen.getByRole('alert')).toHaveTextContent('Connection DSN must use') expect(dsn).toHaveValue('') fireEvent.change(dsn, { target: { value: 'postgresql://db.example/test' } }) - fireEvent.click(screen.getByRole('button', { name: 'Save connection' })) + fireEvent.submit(screen.getByLabelText('Connection DSN').closest('form')!) await waitFor(() => expect(api.createConnection).toHaveBeenCalledWith('p3', 'target-db', 'postgresql://db.example/test')) fireEvent.change(screen.getByLabelText('Schema filter (optional)'), { target: { value: ' public ' } }) @@ -682,7 +682,7 @@ describe('App orchestration coverage', () => { await renderReadyApp() fireEvent.click(screen.getByRole('button', { name: '편집기' })) fireEvent.change(screen.getByLabelText('Connection DSN'), { target: { value: 'postgresql://db.example/test' } }) - fireEvent.click(screen.getByRole('button', { name: 'Save connection' })) + fireEvent.submit(screen.getByLabelText('Connection DSN').closest('form')!) await waitFor(() => expect(api.createConnection).toHaveBeenCalled()) fireEvent.click(screen.getByRole('button', { name: 'Reverse engineer → snapshot' })) await waitFor(() => expect(api.createSnapshot).toHaveBeenCalledWith('p1', 'c2', undefined)) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 0fa62ede..cfaa34ee 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -939,7 +939,8 @@ export default function App() { setLayoutMessage("되돌렸습니다"); } - async function onCreateProject() { + async function handleProjectSubmit(e?: React.FormEvent) { + e?.preventDefault(); const nextProjectName = projectName.trim(); /* v8 ignore next -- the create control is disabled for both guard states */ if (!nextProjectName || isCreatingProject) return; @@ -954,7 +955,8 @@ export default function App() { } } - async function onCreateConnection() { + async function handleConnectionSubmit(e?: React.FormEvent) { + e?.preventDefault(); /* v8 ignore next -- the save control is disabled without a project or while saving */ if (!selectedProjectId || isCreatingConnection) return; const nextConnectionName = connName.trim(); @@ -1078,7 +1080,7 @@ export default function App() { -
프로젝트를 선택하면 해당 다이어그램 목록을 볼 수 있습니다.