create-fluxstack 1.8.1 → 1.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/.env.example +19 -0
  2. package/README.md +6 -3
  3. package/app/client/SIMPLIFICATION.md +140 -0
  4. package/app/client/frontend-only.ts +1 -1
  5. package/app/client/src/App.tsx +148 -283
  6. package/app/client/src/index.css +5 -20
  7. package/app/client/src/lib/eden-api.ts +53 -220
  8. package/app/client/src/main.tsx +2 -3
  9. package/app/server/controllers/users.controller.ts +57 -31
  10. package/app/server/index.ts +5 -2
  11. package/app/server/live/register-components.ts +18 -7
  12. package/app/server/routes/env-test.ts +53 -2
  13. package/app/server/routes/index.ts +1 -8
  14. package/app/server/routes/users.routes.ts +192 -91
  15. package/config/fluxstack.config.ts +2 -2
  16. package/config/plugins.config.ts +22 -1
  17. package/core/build/flux-plugins-generator.ts +5 -5
  18. package/core/build/live-components-generator.ts +15 -12
  19. package/core/cli/command-registry.ts +4 -14
  20. package/core/cli/commands/plugin-deps.ts +8 -8
  21. package/core/cli/generators/component.ts +3 -3
  22. package/core/cli/generators/controller.ts +4 -4
  23. package/core/cli/generators/index.ts +8 -8
  24. package/core/cli/generators/interactive.ts +4 -4
  25. package/core/cli/generators/plugin.ts +3 -3
  26. package/core/cli/generators/prompts.ts +1 -1
  27. package/core/cli/generators/route.ts +27 -11
  28. package/core/cli/generators/service.ts +5 -5
  29. package/core/cli/generators/template-engine.ts +1 -1
  30. package/core/cli/generators/types.ts +1 -1
  31. package/core/cli/index.ts +158 -193
  32. package/core/cli/plugin-discovery.ts +3 -3
  33. package/core/client/hooks/index.ts +2 -2
  34. package/core/client/hooks/state-validator.ts +1 -1
  35. package/core/client/hooks/useAuth.ts +1 -1
  36. package/core/client/hooks/useChunkedUpload.ts +1 -1
  37. package/core/client/hooks/useHybridLiveComponent.ts +1 -1
  38. package/core/client/hooks/useWebSocket.ts +1 -1
  39. package/core/config/env.ts +1 -1
  40. package/core/config/runtime-config.ts +5 -5
  41. package/core/config/schema.ts +9 -0
  42. package/core/framework/server.ts +30 -15
  43. package/core/framework/types.ts +2 -2
  44. package/core/live/ComponentRegistry.ts +1 -1
  45. package/core/plugins/built-in/live-components/commands/create-live-component.ts +1 -1
  46. package/core/plugins/built-in/live-components/index.ts +1 -1
  47. package/core/plugins/built-in/monitoring/index.ts +65 -161
  48. package/core/plugins/built-in/static/index.ts +18 -47
  49. package/core/plugins/built-in/swagger/index.ts +301 -231
  50. package/core/plugins/built-in/vite/index.ts +74 -109
  51. package/core/plugins/config.ts +2 -2
  52. package/core/plugins/dependency-manager.ts +2 -2
  53. package/core/plugins/discovery.ts +1 -1
  54. package/core/plugins/executor.ts +2 -2
  55. package/core/plugins/manager.ts +19 -4
  56. package/core/plugins/module-resolver.ts +1 -1
  57. package/core/plugins/registry.ts +3 -3
  58. package/core/plugins/types.ts +147 -5
  59. package/core/server/framework.ts +2 -2
  60. package/core/server/live/ComponentRegistry.ts +9 -26
  61. package/core/server/live/FileUploadManager.ts +1 -1
  62. package/core/server/live/auto-generated-components.ts +26 -0
  63. package/core/server/live/websocket-plugin.ts +211 -19
  64. package/core/server/middleware/errorHandling.ts +1 -1
  65. package/core/server/middleware/index.ts +4 -4
  66. package/core/server/plugins/database.ts +1 -2
  67. package/core/server/plugins/static-files-plugin.ts +259 -231
  68. package/core/server/plugins/swagger.ts +1 -1
  69. package/core/server/services/BaseService.ts +1 -1
  70. package/core/server/services/ServiceContainer.ts +1 -1
  71. package/core/server/services/index.ts +4 -4
  72. package/core/server/standalone.ts +16 -1
  73. package/core/testing/index.ts +1 -1
  74. package/core/testing/setup.ts +1 -1
  75. package/core/utils/logger/startup-banner.ts +7 -33
  76. package/core/utils/version.ts +6 -6
  77. package/create-fluxstack.ts +68 -25
  78. package/package.json +2 -2
  79. package/plugins/crypto-auth/index.ts +52 -47
  80. package/plugins/crypto-auth/server/AuthMiddleware.ts +1 -1
  81. package/plugins/crypto-auth/server/middlewares/helpers.ts +16 -1
  82. package/vitest.config.ts +11 -2
  83. package/app/client/src/App.css +0 -883
  84. package/app/client/src/components/ErrorBoundary.tsx +0 -107
  85. package/app/client/src/components/ErrorDisplay.css +0 -365
  86. package/app/client/src/components/ErrorDisplay.tsx +0 -258
  87. package/app/client/src/components/FluxStackConfig.tsx +0 -1321
  88. package/app/client/src/components/HybridLiveCounter.tsx +0 -140
  89. package/app/client/src/components/LiveClock.tsx +0 -286
  90. package/app/client/src/components/MainLayout.tsx +0 -388
  91. package/app/client/src/components/SidebarNavigation.tsx +0 -391
  92. package/app/client/src/components/StateDemo.tsx +0 -178
  93. package/app/client/src/components/SystemMonitor.tsx +0 -1044
  94. package/app/client/src/components/UserProfile.tsx +0 -809
  95. package/app/client/src/hooks/useAuth.ts +0 -39
  96. package/app/client/src/hooks/useNotifications.ts +0 -56
  97. package/app/client/src/lib/errors.ts +0 -340
  98. package/app/client/src/lib/hooks/useErrorHandler.ts +0 -258
  99. package/app/client/src/lib/index.ts +0 -45
  100. package/app/client/src/pages/ApiDocs.tsx +0 -182
  101. package/app/client/src/pages/CryptoAuthPage.tsx +0 -394
  102. package/app/client/src/pages/Demo.tsx +0 -174
  103. package/app/client/src/pages/HybridLive.tsx +0 -263
  104. package/app/client/src/pages/Overview.tsx +0 -155
  105. package/app/client/src/store/README.md +0 -43
  106. package/app/client/src/store/index.ts +0 -16
  107. package/app/client/src/store/slices/uiSlice.ts +0 -151
  108. package/app/client/src/store/slices/userSlice.ts +0 -161
  109. package/app/client/src/test/README.md +0 -257
  110. package/app/client/src/test/setup.ts +0 -70
  111. package/app/client/src/test/types.ts +0 -12
  112. package/app/server/live/CounterComponent.ts +0 -191
  113. package/app/server/live/FluxStackConfig.ts +0 -534
  114. package/app/server/live/SidebarNavigation.ts +0 -157
  115. package/app/server/live/SystemMonitor.ts +0 -595
  116. package/app/server/live/SystemMonitorIntegration.ts +0 -151
  117. package/app/server/live/UserProfileComponent.ts +0 -141
  118. package/app/server/middleware/auth.ts +0 -136
  119. package/app/server/middleware/errorHandling.ts +0 -252
  120. package/app/server/middleware/index.ts +0 -10
  121. package/app/server/middleware/rateLimit.ts +0 -193
  122. package/app/server/middleware/requestLogging.ts +0 -215
  123. package/app/server/middleware/validation.ts +0 -270
  124. package/app/server/routes/config.ts +0 -145
  125. package/app/server/routes/crypto-auth-demo.routes.ts +0 -167
  126. package/app/server/routes/example-with-crypto-auth.routes.ts +0 -235
  127. package/app/server/routes/exemplo-posts.routes.ts +0 -161
  128. package/app/server/routes/upload.ts +0 -92
  129. package/app/server/services/NotificationService.ts +0 -302
  130. package/app/server/services/UserService.ts +0 -222
  131. package/app/server/services/index.ts +0 -46
  132. package/app/server/types/index.ts +0 -1
@@ -1,151 +0,0 @@
1
- /**
2
- * UI Store with Zustand
3
- * Manages global UI state like modals, notifications, theme, etc.
4
- */
5
-
6
- import { create } from 'zustand'
7
- import { persist } from 'zustand/middleware'
8
-
9
- export interface Notification {
10
- id: string
11
- type: 'success' | 'error' | 'warning' | 'info'
12
- title: string
13
- message: string
14
- duration?: number
15
- timestamp: number
16
- }
17
-
18
- export interface Modal {
19
- id: string
20
- component: string
21
- props?: Record<string, any>
22
- closable?: boolean
23
- }
24
-
25
- interface UIState {
26
- // State
27
- theme: 'light' | 'dark' | 'system'
28
- sidebarOpen: boolean
29
- notifications: Notification[]
30
- modals: Modal[]
31
- loading: {
32
- global: boolean
33
- operations: Record<string, boolean>
34
- }
35
-
36
- // Actions
37
- setTheme: (theme: 'light' | 'dark' | 'system') => void
38
- toggleSidebar: () => void
39
- setSidebarOpen: (open: boolean) => void
40
-
41
- // Notifications
42
- addNotification: (notification: Omit<Notification, 'id' | 'timestamp'>) => void
43
- removeNotification: (id: string) => void
44
- clearNotifications: () => void
45
-
46
- // Modals
47
- openModal: (modal: Omit<Modal, 'id'>) => void
48
- closeModal: (id: string) => void
49
- closeAllModals: () => void
50
-
51
- // Loading
52
- setGlobalLoading: (loading: boolean) => void
53
- setOperationLoading: (operation: string, loading: boolean) => void
54
- clearOperationLoading: (operation: string) => void
55
- }
56
-
57
- export const useUIStore = create<UIState>()(
58
- persist(
59
- (set, get) => ({
60
- // Initial state
61
- theme: 'system',
62
- sidebarOpen: true,
63
- notifications: [],
64
- modals: [],
65
- loading: {
66
- global: false,
67
- operations: {}
68
- },
69
-
70
- // Theme actions
71
- setTheme: (theme) => set({ theme }),
72
-
73
- // Sidebar actions
74
- toggleSidebar: () => set((state) => ({ sidebarOpen: !state.sidebarOpen })),
75
- setSidebarOpen: (open) => set({ sidebarOpen: open }),
76
-
77
- // Notification actions
78
- addNotification: (notification) => {
79
- const newNotification: Notification = {
80
- ...notification,
81
- id: Math.random().toString(36).substr(2, 9),
82
- timestamp: Date.now()
83
- }
84
-
85
- set((state) => ({
86
- notifications: [...state.notifications, newNotification]
87
- }))
88
-
89
- // Auto-remove notification after duration
90
- if (notification.duration !== 0) {
91
- setTimeout(() => {
92
- get().removeNotification(newNotification.id)
93
- }, notification.duration || 5000)
94
- }
95
- },
96
-
97
- removeNotification: (id) => set((state) => ({
98
- notifications: state.notifications.filter(n => n.id !== id)
99
- })),
100
-
101
- clearNotifications: () => set({ notifications: [] }),
102
-
103
- // Modal actions
104
- openModal: (modal) => {
105
- const newModal: Modal = {
106
- ...modal,
107
- id: Math.random().toString(36).substr(2, 9)
108
- }
109
-
110
- set((state) => ({
111
- modals: [...state.modals, newModal]
112
- }))
113
- },
114
-
115
- closeModal: (id) => set((state) => ({
116
- modals: state.modals.filter(m => m.id !== id)
117
- })),
118
-
119
- closeAllModals: () => set({ modals: [] }),
120
-
121
- // Loading actions
122
- setGlobalLoading: (loading) => set((state) => ({
123
- loading: { ...state.loading, global: loading }
124
- })),
125
-
126
- setOperationLoading: (operation, loading) => set((state) => ({
127
- loading: {
128
- ...state.loading,
129
- operations: {
130
- ...state.loading.operations,
131
- [operation]: loading
132
- }
133
- }
134
- })),
135
-
136
- clearOperationLoading: (operation) => set((state) => {
137
- const { [operation]: _, ...operations } = state.loading.operations
138
- return {
139
- loading: { ...state.loading, operations }
140
- }
141
- })
142
- }),
143
- {
144
- name: 'ui-store',
145
- partialize: (state) => ({
146
- theme: state.theme,
147
- sidebarOpen: state.sidebarOpen
148
- })
149
- }
150
- )
151
- )
@@ -1,161 +0,0 @@
1
- /**
2
- * User Store
3
- * App-specific user store using FluxStack core
4
- */
5
-
6
- // Temporary direct implementation until module resolution is fixed
7
- import { create } from 'zustand'
8
- import { persist, createJSONStorage } from 'zustand/middleware'
9
-
10
- export interface BaseUser {
11
- id: string
12
- email: string
13
- name: string
14
- role: 'admin' | 'user'
15
- }
16
-
17
- // Type aliases for compatibility
18
- export type User = BaseUser
19
-
20
- export interface LoginCredentials {
21
- email: string
22
- password: string
23
- }
24
-
25
- export interface RegisterData {
26
- email: string
27
- password: string
28
- name: string
29
- }
30
-
31
- export interface BaseUserStore {
32
- currentUser: BaseUser | null
33
- isAuthenticated: boolean
34
- isLoading: boolean
35
- error: string | null
36
- login: (credentials: { email: string; password: string }) => Promise<void>
37
- register: (data: { email: string; password: string; name: string }) => Promise<void>
38
- logout: () => void
39
- updateProfile: (data: Partial<BaseUser>) => Promise<void>
40
- clearError: () => void
41
- setLoading: (loading: boolean) => void
42
- }
43
-
44
- // Create user store using Zustand directly (temporary)
45
- export const useUserStore = create<BaseUserStore>()(
46
- persist(
47
- (set, get) => ({
48
- currentUser: null,
49
- isAuthenticated: false,
50
- isLoading: false,
51
- error: null,
52
-
53
- login: async (credentials) => {
54
- set({ isLoading: true, error: null })
55
- try {
56
- const response = await fetch('/api/auth/login', {
57
- method: 'POST',
58
- headers: { 'Content-Type': 'application/json' },
59
- body: JSON.stringify(credentials)
60
- })
61
-
62
- if (!response.ok) {
63
- const error = await response.json()
64
- throw new Error(error.message || 'Login failed')
65
- }
66
-
67
- const { user } = await response.json()
68
- set({
69
- currentUser: user,
70
- isAuthenticated: true,
71
- isLoading: false
72
- })
73
- } catch (error) {
74
- set({
75
- error: error instanceof Error ? error.message : 'Login failed',
76
- isLoading: false
77
- })
78
- throw error
79
- }
80
- },
81
-
82
- register: async (data) => {
83
- set({ isLoading: true, error: null })
84
- try {
85
- const response = await fetch('/api/auth/register', {
86
- method: 'POST',
87
- headers: { 'Content-Type': 'application/json' },
88
- body: JSON.stringify(data)
89
- })
90
-
91
- if (!response.ok) {
92
- const error = await response.json()
93
- throw new Error(error.message || 'Registration failed')
94
- }
95
-
96
- const { user } = await response.json()
97
- set({
98
- currentUser: user,
99
- isAuthenticated: true,
100
- isLoading: false
101
- })
102
- } catch (error) {
103
- set({
104
- error: error instanceof Error ? error.message : 'Registration failed',
105
- isLoading: false
106
- })
107
- throw error
108
- }
109
- },
110
-
111
- logout: () => {
112
- fetch('/api/auth/logout', { method: 'POST' }).catch(console.error)
113
- set({
114
- currentUser: null,
115
- isAuthenticated: false,
116
- error: null
117
- })
118
- },
119
-
120
- updateProfile: async (data) => {
121
- const { currentUser } = get()
122
- if (!currentUser) {
123
- throw new Error('No user logged in')
124
- }
125
-
126
- set({ isLoading: true, error: null })
127
- try {
128
- const response = await fetch('/api/user/profile', {
129
- method: 'PUT',
130
- headers: { 'Content-Type': 'application/json' },
131
- body: JSON.stringify(data)
132
- })
133
-
134
- if (!response.ok) {
135
- const error = await response.json()
136
- throw new Error(error.message || 'Profile update failed')
137
- }
138
-
139
- const { user } = await response.json()
140
- set({
141
- currentUser: user,
142
- isLoading: false
143
- })
144
- } catch (error) {
145
- set({
146
- error: error instanceof Error ? error.message : 'Profile update failed',
147
- isLoading: false
148
- })
149
- throw error
150
- }
151
- },
152
-
153
- clearError: () => set({ error: null }),
154
- setLoading: (loading) => set({ isLoading: loading })
155
- }),
156
- {
157
- name: 'user-store',
158
- storage: createJSONStorage(() => localStorage)
159
- }
160
- )
161
- )
@@ -1,257 +0,0 @@
1
- # FluxStack Testing Guide
2
-
3
- Este guia explica como testar o sistema de estado baseado em Zustand no FluxStack.
4
-
5
- ## 🧪 **Estrutura de Testes**
6
-
7
- ```
8
- app/client/src/
9
- ├── store/
10
- │ ├── __tests__/
11
- │ │ ├── userSlice.test.ts # Testes do store de usuário
12
- │ │ └── uiSlice.test.ts # Testes do store de UI
13
- ├── hooks/
14
- │ ├── __tests__/
15
- │ │ ├── useAuth.test.ts # Testes do hook de auth
16
- │ │ └── useNotifications.test.ts # Testes do hook de notificações
17
- ├── components/
18
- │ └── __tests__/
19
- │ └── StateDemo.test.tsx # Testes de integração
20
- └── test/
21
- ├── setup.ts # Configuração global
22
- ├── types.ts # Tipos para testes
23
- └── README.md # Este arquivo
24
- ```
25
-
26
- ## 🔧 **Configuração**
27
-
28
- ### Dependências necessárias:
29
-
30
- ```json
31
- {
32
- "devDependencies": {
33
- "@testing-library/jest-dom": "^6.1.4",
34
- "@testing-library/react": "^13.4.0",
35
- "@testing-library/user-event": "^14.5.1",
36
- "jsdom": "^22.1.0",
37
- "vitest": "^0.34.6"
38
- }
39
- }
40
- ```
41
-
42
- ### Configuração do Vitest:
43
-
44
- O arquivo `vitest.config.ts` está configurado para:
45
- - Usar jsdom como ambiente
46
- - Configurar aliases para imports
47
- - Incluir setup global
48
- - Configurar coverage
49
-
50
- ## 🧪 **Testando Stores Zustand**
51
-
52
- ### Exemplo básico:
53
-
54
- ```typescript
55
- import { renderHook, act } from '@testing-library/react'
56
- import { useUserStore } from '../slices/userSlice'
57
-
58
- describe('useUserStore', () => {
59
- beforeEach(() => {
60
- // Reset store state
61
- useUserStore.setState({
62
- currentUser: null,
63
- isAuthenticated: false,
64
- isLoading: false,
65
- error: null
66
- })
67
- })
68
-
69
- it('should login successfully', async () => {
70
- const { result } = renderHook(() => useUserStore())
71
-
72
- await act(async () => {
73
- await result.current.login({
74
- email: 'test@example.com',
75
- password: 'password'
76
- })
77
- })
78
-
79
- expect(result.current.isAuthenticated).toBe(true)
80
- })
81
- })
82
- ```
83
-
84
- ### Padrões importantes:
85
-
86
- 1. **Reset do estado**: Sempre resetar o store antes de cada teste
87
- 2. **act()**: Usar `act()` para mudanças de estado assíncronas
88
- 3. **Mock de APIs**: Mockar fetch para testes isolados
89
-
90
- ## 🎯 **Testando Hooks Utilitários**
91
-
92
- ```typescript
93
- import { renderHook } from '@testing-library/react'
94
- import { useAuth } from '../useAuth'
95
-
96
- describe('useAuth', () => {
97
- it('should detect admin user', () => {
98
- // Set admin user in store
99
- useUserStore.setState({
100
- currentUser: { role: 'admin', /* ... */ },
101
- isAuthenticated: true
102
- })
103
-
104
- const { result } = renderHook(() => useAuth())
105
-
106
- expect(result.current.isAdmin).toBe(true)
107
- })
108
- })
109
- ```
110
-
111
- ## 🧩 **Testando Componentes com Estado**
112
-
113
- ```typescript
114
- import { render, screen, fireEvent } from '@testing-library/react'
115
- import { MyComponent } from '../MyComponent'
116
- import { useUIStore } from '../../store/slices/uiSlice'
117
-
118
- describe('MyComponent', () => {
119
- beforeEach(() => {
120
- // Reset stores
121
- useUIStore.setState({ /* initial state */ })
122
- })
123
-
124
- it('should update theme when button clicked', () => {
125
- render(<MyComponent />)
126
-
127
- fireEvent.click(screen.getByText('Dark Theme'))
128
-
129
- expect(screen.getByText('Current theme: dark')).toBeInTheDocument()
130
- })
131
- })
132
- ```
133
-
134
- ## 🔄 **Mocking APIs**
135
-
136
- ```typescript
137
- // Mock fetch globally
138
- global.fetch = vi.fn()
139
-
140
- beforeEach(() => {
141
- vi.resetAllMocks()
142
- })
143
-
144
- it('should handle API success', async () => {
145
- // Mock successful response
146
- ;(global.fetch as any).mockResolvedValueOnce({
147
- ok: true,
148
- json: async () => ({ user: mockUser })
149
- })
150
-
151
- // Test your component/hook
152
- })
153
- ```
154
-
155
- ## 📊 **Coverage**
156
-
157
- Execute testes com coverage:
158
-
159
- ```bash
160
- npm run test:coverage
161
- ```
162
-
163
- Isso gerará um relatório em `coverage/index.html`.
164
-
165
- ## 🎨 **Boas Práticas**
166
-
167
- ### 1. **Isolamento de Testes**
168
- - Sempre resetar stores antes de cada teste
169
- - Mockar APIs externas
170
- - Não depender de ordem de execução
171
-
172
- ### 2. **Testes Descritivos**
173
- ```typescript
174
- // ❌ Ruim
175
- it('should work', () => { /* ... */ })
176
-
177
- // ✅ Bom
178
- it('should login successfully with valid credentials', () => { /* ... */ })
179
- ```
180
-
181
- ### 3. **Arrange-Act-Assert**
182
- ```typescript
183
- it('should add notification', () => {
184
- // Arrange
185
- const { result } = renderHook(() => useNotifications())
186
-
187
- // Act
188
- act(() => {
189
- result.current.success('Title', 'Message')
190
- })
191
-
192
- // Assert
193
- expect(result.current.notifications).toHaveLength(1)
194
- })
195
- ```
196
-
197
- ### 4. **Testar Comportamentos, não Implementação**
198
- ```typescript
199
- // ❌ Ruim - testa implementação
200
- expect(mockSetState).toHaveBeenCalledWith({ loading: true })
201
-
202
- // ✅ Bom - testa comportamento
203
- expect(result.current.isLoading).toBe(true)
204
- ```
205
-
206
- ## 🚀 **Executando Testes**
207
-
208
- ```bash
209
- # Todos os testes
210
- npm run test:run
211
-
212
- # Modo watch
213
- npm run test:watch
214
-
215
- # Com UI
216
- npm run test:ui
217
-
218
- # Apenas stores
219
- npm run test:client -- store
220
-
221
- # Apenas hooks
222
- npm run test:client -- hooks
223
-
224
- # Apenas componentes
225
- npm run test:client -- components
226
- ```
227
-
228
- ## 🐛 **Debugging**
229
-
230
- ### Console logs em testes:
231
- ```typescript
232
- it('should debug state', () => {
233
- const { result } = renderHook(() => useUserStore())
234
-
235
- console.log('Current state:', result.current)
236
-
237
- // Seu teste aqui
238
- })
239
- ```
240
-
241
- ### Usando screen.debug():
242
- ```typescript
243
- it('should render correctly', () => {
244
- render(<MyComponent />)
245
-
246
- screen.debug() // Mostra o DOM atual
247
-
248
- // Seu teste aqui
249
- })
250
- ```
251
-
252
- ## 📝 **Exemplos Completos**
253
-
254
- Veja os arquivos de teste existentes para exemplos completos:
255
- - `store/__tests__/userSlice.test.ts` - Testes de store
256
- - `hooks/__tests__/useAuth.test.ts` - Testes de hooks
257
- - `components/__tests__/StateDemo.test.tsx` - Testes de integração
@@ -1,70 +0,0 @@
1
- /**
2
- * Test Setup
3
- * Global test configuration and mocks
4
- */
5
-
6
- import { expect, afterEach, vi } from 'vitest'
7
- import { cleanup } from '@testing-library/react'
8
- import * as matchers from '@testing-library/jest-dom/matchers'
9
-
10
- // Extend Vitest's expect with jest-dom matchers
11
- expect.extend(matchers)
12
-
13
- // Mock fetch with proper typing
14
- global.fetch = vi.fn() as any
15
-
16
- // Cleanup after each test case (e.g. clearing jsdom)
17
- afterEach(() => {
18
- cleanup()
19
- })
20
-
21
- // Mock window.matchMedia
22
- Object.defineProperty(window, 'matchMedia', {
23
- writable: true,
24
- value: vi.fn().mockImplementation(query => ({
25
- matches: false,
26
- media: query,
27
- onchange: null,
28
- addListener: vi.fn(), // deprecated
29
- removeListener: vi.fn(), // deprecated
30
- addEventListener: vi.fn(),
31
- removeEventListener: vi.fn(),
32
- dispatchEvent: vi.fn(),
33
- })),
34
- })
35
-
36
- // Mock window.ResizeObserver
37
- global.ResizeObserver = vi.fn().mockImplementation(() => ({
38
- observe: vi.fn(),
39
- unobserve: vi.fn(),
40
- disconnect: vi.fn(),
41
- }))
42
-
43
- // Mock localStorage
44
- const localStorageMock = {
45
- getItem: vi.fn(),
46
- setItem: vi.fn(),
47
- removeItem: vi.fn(),
48
- clear: vi.fn(),
49
- }
50
- vi.stubGlobal('localStorage', localStorageMock)
51
-
52
- // Mock sessionStorage
53
- const sessionStorageMock = {
54
- getItem: vi.fn(),
55
- setItem: vi.fn(),
56
- removeItem: vi.fn(),
57
- clear: vi.fn(),
58
- }
59
- vi.stubGlobal('sessionStorage', sessionStorageMock)
60
-
61
- // Mock console methods to reduce noise in tests
62
- global.console = {
63
- ...console,
64
- // Uncomment to ignore console logs in tests
65
- // log: vi.fn(),
66
- // debug: vi.fn(),
67
- // info: vi.fn(),
68
- // warn: vi.fn(),
69
- // error: vi.fn(),
70
- }
@@ -1,12 +0,0 @@
1
- /**
2
- * Test Types
3
- * Type definitions for testing utilities
4
- */
5
-
6
- import '@testing-library/jest-dom'
7
-
8
- declare global {
9
- namespace Vi {
10
- interface JestAssertion<T = any> extends jest.Matchers<void, T> {}
11
- }
12
- }