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({