From eb3d45873f8d7ab5c05c4d50ca9b17ef67e561e5 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Fri, 14 Aug 2026 01:58:08 +0000 Subject: [PATCH 1/2] feat(ui): add window.confirm to table deletion --- .jules/palette.md | 3 ++ .../components/modals/EditTableModal.test.tsx | 48 +++++++++++++++++++ .../src/components/modals/EditTableModal.tsx | 5 +- .../components/modals/ModalCoverage.test.tsx | 1 + 4 files changed, 56 insertions(+), 1 deletion(-) diff --git a/.jules/palette.md b/.jules/palette.md index bd0f73248..6ea1bb420 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-06-20 - Confirm destructive actions like table deletion +**Learning:** Destructive actions such as deleting a table require explicit user confirmation to prevent accidental data loss. +**Action:** Always wrap delete operations with window.confirm() dialogs and ensure corresponding tests successfully mock window.confirm. diff --git a/frontend/src/components/modals/EditTableModal.test.tsx b/frontend/src/components/modals/EditTableModal.test.tsx index 1a8c9af5e..c492797b6 100644 --- a/frontend/src/components/modals/EditTableModal.test.tsx +++ b/frontend/src/components/modals/EditTableModal.test.tsx @@ -46,6 +46,54 @@ describe('EditTableModal', () => { expect(screen.getByRole('checkbox', { name: 'test_col NN 설정' })).toBeInTheDocument(); }); + it('deletes a table when 테이블 삭제 is clicked and confirmed', async () => { + const onDeleteTableMock = vi.fn(); + const editingNode = { + id: 'table-1', + type: 'table', + position: { x: 0, y: 0 }, + data: { + title: 'test_table', + comment: '', + columns: [] + } + }; + + vi.spyOn(window, 'confirm').mockReturnValue(true); + + render(); + + const user = userEvent.setup(); + await user.click(screen.getByRole('button', { name: '테이블 삭제' })); + + expect(window.confirm).toHaveBeenCalledWith("'test_table' 테이블을 삭제하시겠습니까?"); + expect(onDeleteTableMock).toHaveBeenCalled(); + }); + + it('does not delete a table when 테이블 삭제 is clicked and canceled', async () => { + const onDeleteTableMock = vi.fn(); + const editingNode = { + id: 'table-1', + type: 'table', + position: { x: 0, y: 0 }, + data: { + title: 'test_table', + comment: '', + columns: [] + } + }; + + vi.spyOn(window, 'confirm').mockReturnValue(false); + + render(); + + const user = userEvent.setup(); + await user.click(screen.getByRole('button', { name: '테이블 삭제' })); + + expect(window.confirm).toHaveBeenCalled(); + expect(onDeleteTableMock).not.toHaveBeenCalled(); + }); + it('returns null if not open or no editingNode', () => { const { container } = render(); expect(container.firstChild).toBeNull(); diff --git a/frontend/src/components/modals/EditTableModal.tsx b/frontend/src/components/modals/EditTableModal.tsx index 998929d44..cfb61d1b1 100644 --- a/frontend/src/components/modals/EditTableModal.tsx +++ b/frontend/src/components/modals/EditTableModal.tsx @@ -189,7 +189,10 @@ export function EditTableModal({