From 73dd167121ad6c01a4a4e80306d7cea97a052da6 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sun, 9 Aug 2026 09:08:49 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=A7=AA=20[testing=20improvement]=20Te?= =?UTF-8?q?st=20sanitizeTableName=20in=20securityUtils.ts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/erd/securityUtils.test.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 frontend/src/erd/securityUtils.test.ts diff --git a/frontend/src/erd/securityUtils.test.ts b/frontend/src/erd/securityUtils.test.ts new file mode 100644 index 000000000..a6fb14955 --- /dev/null +++ b/frontend/src/erd/securityUtils.test.ts @@ -0,0 +1,26 @@ +import { describe, it, expect } from 'vitest'; +import { sanitizeTableName } from './securityUtils'; + +describe('sanitizeTableName', () => { + it('should return the same string if it contains only alphanumeric characters and underscores', () => { + expect(sanitizeTableName('valid_table_name_1')).toBe('valid_table_name_1'); + }); + + it('should remove spaces', () => { + expect(sanitizeTableName('table name')).toBe('tablename'); + }); + + it('should remove special characters', () => { + expect(sanitizeTableName('table-name!')).toBe('tablename'); + expect(sanitizeTableName('table@name#$')).toBe('tablename'); + }); + + it('should handle empty strings', () => { + expect(sanitizeTableName('')).toBe(''); + }); + + it('should sanitize strings resembling SQL injection', () => { + expect(sanitizeTableName('users; DROP TABLE users;')).toBe('usersDROPTABLEusers'); + expect(sanitizeTableName('users" OR "1"="1')).toBe('usersOR11'); + }); +}); From 3dbe79babc37410c07f9d2839057af4fabaa4a01 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sun, 9 Aug 2026 09:49:24 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=A7=AA=20[testing=20improvement]=20Te?= =?UTF-8?q?st=20sanitizeTableName=20in=20securityUtils.ts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/App.coverage.test.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/src/App.coverage.test.tsx b/frontend/src/App.coverage.test.tsx index 0b9a20aa8..c9f1231bb 100644 --- a/frontend/src/App.coverage.test.tsx +++ b/frontend/src/App.coverage.test.tsx @@ -610,6 +610,7 @@ describe('App orchestration coverage', () => { it('logs auto-layout failures and preserves nodes added after the undo snapshot', async () => { await renderReadyApp() fireEvent.click(screen.getByRole('button', { name: '다이어그램' })) + await waitFor(() => expect(screen.queryAllByRole('button', { name: '열기' }).length).toBeGreaterThan(0)) vi.useFakeTimers() fireEvent.click(screen.getAllByRole('button', { name: '열기' })[0]!) await act(async () => { @@ -641,6 +642,7 @@ describe('App orchestration coverage', () => { .mockRejectedValueOnce(new Error('terminal refresh down')) await renderReadyApp() fireEvent.click(screen.getByRole('button', { name: '다이어그램' })) + await waitFor(() => expect(screen.queryAllByRole('button', { name: '열기' }).length).toBeGreaterThan(0)) vi.useFakeTimers() fireEvent.click(screen.getAllByRole('button', { name: '열기' })[0]!) await act(async () => { @@ -744,6 +746,7 @@ describe('App orchestration coverage', () => { })) await renderReadyApp() fireEvent.click(screen.getByRole('button', { name: '다이어그램' })) + await waitFor(() => expect(screen.queryAllByRole('button', { name: '열기' }).length).toBeGreaterThan(0)) vi.useFakeTimers() fireEvent.click(screen.getAllByRole('button', { name: '열기' })[0]!) await act(async () => { @@ -784,6 +787,7 @@ describe('App orchestration coverage', () => { }) await renderReadyApp() fireEvent.click(screen.getByRole('button', { name: '다이어그램' })) + await waitFor(() => expect(screen.queryAllByRole('button', { name: '열기' }).length).toBeGreaterThan(0)) vi.useFakeTimers() fireEvent.click(screen.getAllByRole('button', { name: '열기' })[0]!) await act(async () => {