summaryrefslogtreecommitdiff
path: root/apps/web/src/__tests__/setup.ts
diff options
context:
space:
mode:
authornaoNao89 <90588855+naoNao89@users.noreply.github.com>2025-07-31 05:29:42 +0700
committernaoNao89 <90588855+naoNao89@users.noreply.github.com>2025-07-31 05:29:42 +0700
commita1d2fbd96bb6713c3172198d71e94274af409aee (patch)
treeb8bf5c16f221462272512377331204b6290607a9 /apps/web/src/__tests__/setup.ts
parente6e08057f510e70c956af0f0c08c6eef349edf3c (diff)
downloadopencut-a1d2fbd96bb6713c3172198d71e94274af409aee.tar.gz
[Editor] Prevent excessive project creation from invalid routes
Race conditions in useEffect hook caused navigation to invalid project IDs to create multiple 'Untitled Project' entries. Users reported accumulating 885+ projects due to this bug. This change adds global invalid project ID tracking across component remounts and prevents race conditions through: - Global invalidProjectIds Set in project store with tracking functions - isInitializingRef to prevent duplicate initialization attempts - Proper useEffect cleanup with cancellation tokens - Specific error handling for 'not found' vs recoverable errors - Removed problematic activeProject?.id dependency Testing: - Add comprehensive test suite (15 tests) with Vitest + React Testing Library - Include integration tests demonstrating bug and validating fix - Update CI pipeline to run automated tests Fixes #182
Diffstat (limited to 'apps/web/src/__tests__/setup.ts')
-rw-r--r--apps/web/src/__tests__/setup.ts65
1 files changed, 65 insertions, 0 deletions
diff --git a/apps/web/src/__tests__/setup.ts b/apps/web/src/__tests__/setup.ts
new file mode 100644
index 00000000..82176a41
--- /dev/null
+++ b/apps/web/src/__tests__/setup.ts
@@ -0,0 +1,65 @@
+import '@testing-library/jest-dom'
+
+// Mock Next.js router
+const mockRouter = {
+ push: vi.fn(),
+ replace: vi.fn(),
+ back: vi.fn(),
+ forward: vi.fn(),
+ refresh: vi.fn(),
+ prefetch: vi.fn(),
+}
+
+vi.mock('next/navigation', () => ({
+ useRouter: () => mockRouter,
+ usePathname: () => '/test',
+ useSearchParams: () => new URLSearchParams(),
+}))
+
+// Mock IndexedDB for storage tests
+const mockIndexedDB = {
+ open: vi.fn(),
+ deleteDatabase: vi.fn(),
+}
+
+Object.defineProperty(window, 'indexedDB', {
+ value: mockIndexedDB,
+ writable: true,
+})
+
+// Mock OPFS (Origin Private File System)
+Object.defineProperty(navigator, 'storage', {
+ value: {
+ getDirectory: vi.fn(),
+ },
+ writable: true,
+})
+
+// Global test utilities
+global.mockRouter = mockRouter
+
+// Suppress console logs during tests unless explicitly needed
+const originalConsoleLog = console.log
+const originalConsoleError = console.error
+const originalConsoleWarn = console.warn
+
+beforeEach(() => {
+ // Reset all mocks before each test
+ vi.clearAllMocks()
+
+ // Suppress console output unless VITEST_VERBOSE is set
+ if (!process.env.VITEST_VERBOSE) {
+ console.log = vi.fn()
+ console.error = vi.fn()
+ console.warn = vi.fn()
+ }
+})
+
+afterEach(() => {
+ // Restore console if it was mocked
+ if (!process.env.VITEST_VERBOSE) {
+ console.log = originalConsoleLog
+ console.error = originalConsoleError
+ console.warn = originalConsoleWarn
+ }
+})