@pattern-stack/frontend-patterns 0.0.1 → 0.0.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 (153) hide show
  1. package/README.md +6 -6
  2. package/package.json +3 -5
  3. package/src/App.css +0 -42
  4. package/src/App.tsx +0 -54
  5. package/src/__tests__/README.md +0 -221
  6. package/src/__tests__/atoms/hooks/simple-hooks.test.ts +0 -44
  7. package/src/__tests__/atoms/ui/button.test.tsx +0 -68
  8. package/src/__tests__/atoms/utils/simple.test.ts +0 -18
  9. package/src/__tests__/atoms/utils/utils.test.ts +0 -77
  10. package/src/__tests__/features/auth/simple-auth.test.tsx +0 -40
  11. package/src/__tests__/molecules/layout/simple-layout.test.tsx +0 -81
  12. package/src/__tests__/organisms/showcase/simple-showcase.test.tsx +0 -167
  13. package/src/__tests__/setup.ts +0 -51
  14. package/src/__tests__/utils.tsx +0 -123
  15. package/src/atoms/composed/Accordion/Accordion.tsx +0 -271
  16. package/src/atoms/composed/Accordion/index.ts +0 -1
  17. package/src/atoms/composed/Alert/Alert.tsx +0 -132
  18. package/src/atoms/composed/Alert/index.ts +0 -1
  19. package/src/atoms/composed/Breadcrumb/Breadcrumb.tsx +0 -83
  20. package/src/atoms/composed/Breadcrumb/index.ts +0 -1
  21. package/src/atoms/composed/Chart/Chart.tsx +0 -425
  22. package/src/atoms/composed/Chart/index.ts +0 -2
  23. package/src/atoms/composed/ColorSwatch/ColorSwatch.tsx +0 -72
  24. package/src/atoms/composed/ColorSwatch/index.ts +0 -1
  25. package/src/atoms/composed/DarkModeToggle.tsx +0 -66
  26. package/src/atoms/composed/DataBadge/DataBadge.tsx +0 -81
  27. package/src/atoms/composed/DataBadge/index.ts +0 -1
  28. package/src/atoms/composed/DataTable/DataTable.tsx +0 -394
  29. package/src/atoms/composed/DataTable/TableCellWithTooltip.tsx +0 -41
  30. package/src/atoms/composed/DataTable/index.ts +0 -2
  31. package/src/atoms/composed/DateTimePicker/DateTimePicker.tsx +0 -611
  32. package/src/atoms/composed/DateTimePicker/index.ts +0 -2
  33. package/src/atoms/composed/DetailedCard/DetailedCard.tsx +0 -181
  34. package/src/atoms/composed/DetailedCard/index.ts +0 -2
  35. package/src/atoms/composed/EmptyState/EmptyState.tsx +0 -90
  36. package/src/atoms/composed/EmptyState/index.ts +0 -1
  37. package/src/atoms/composed/FileUpload/FileUpload.tsx +0 -477
  38. package/src/atoms/composed/FileUpload/index.ts +0 -2
  39. package/src/atoms/composed/FormField/FormField.tsx +0 -92
  40. package/src/atoms/composed/FormField/index.ts +0 -1
  41. package/src/atoms/composed/GlobalSearch/GlobalSearch.tsx +0 -37
  42. package/src/atoms/composed/GlobalSearch/index.ts +0 -1
  43. package/src/atoms/composed/IconBadge/IconBadge.tsx +0 -95
  44. package/src/atoms/composed/IconBadge/index.ts +0 -2
  45. package/src/atoms/composed/Modal/Modal.tsx +0 -223
  46. package/src/atoms/composed/Modal/index.ts +0 -2
  47. package/src/atoms/composed/PaletteSwitcher.tsx +0 -386
  48. package/src/atoms/composed/ProgressBar/ProgressBar.tsx +0 -116
  49. package/src/atoms/composed/ProgressBar/index.ts +0 -1
  50. package/src/atoms/composed/StatCard/StatCard.tsx +0 -219
  51. package/src/atoms/composed/StatCard/index.ts +0 -1
  52. package/src/atoms/composed/StyleGuide.tsx +0 -717
  53. package/src/atoms/composed/Toast/Toast.tsx +0 -219
  54. package/src/atoms/composed/Toast/index.ts +0 -1
  55. package/src/atoms/composed/Tooltip/Tooltip.tsx +0 -213
  56. package/src/atoms/composed/Tooltip/index.ts +0 -1
  57. package/src/atoms/composed/UserAvatar/UserAvatar.tsx +0 -139
  58. package/src/atoms/composed/UserAvatar/index.ts +0 -1
  59. package/src/atoms/composed/UserMenu/UserMenu.tsx +0 -16
  60. package/src/atoms/composed/UserMenu/index.ts +0 -1
  61. package/src/atoms/composed/index.ts +0 -29
  62. package/src/atoms/hooks/useApi.ts +0 -80
  63. package/src/atoms/hooks/useHealth.ts +0 -17
  64. package/src/atoms/index.ts +0 -13
  65. package/src/atoms/services/api/client.ts +0 -134
  66. package/src/atoms/services/auth-service.ts +0 -248
  67. package/src/atoms/services/health.ts +0 -15
  68. package/src/atoms/services/index.ts +0 -3
  69. package/src/atoms/shared/config/constants.ts +0 -17
  70. package/src/atoms/shared/config/dashboard-sizes.ts +0 -111
  71. package/src/atoms/shared/config/environment.ts +0 -10
  72. package/src/atoms/shared/index.ts +0 -4
  73. package/src/atoms/shared/styles/color-palettes.css +0 -566
  74. package/src/atoms/types/auth.ts +0 -62
  75. package/src/atoms/types/generated.ts +0 -1469
  76. package/src/atoms/types/index.ts +0 -4
  77. package/src/atoms/types/loading.ts +0 -28
  78. package/src/atoms/ui/Badge.tsx +0 -30
  79. package/src/atoms/ui/ErrorBoundary.tsx +0 -59
  80. package/src/atoms/ui/Select.tsx +0 -53
  81. package/src/atoms/ui/Switch.tsx +0 -42
  82. package/src/atoms/ui/Tabs.tsx +0 -118
  83. package/src/atoms/ui/avatar.tsx +0 -48
  84. package/src/atoms/ui/button.tsx +0 -70
  85. package/src/atoms/ui/card.tsx +0 -76
  86. package/src/atoms/ui/dropdown-menu.tsx +0 -199
  87. package/src/atoms/ui/index.ts +0 -39
  88. package/src/atoms/ui/input.tsx +0 -23
  89. package/src/atoms/ui/label.tsx +0 -23
  90. package/src/atoms/ui/skeleton.tsx +0 -13
  91. package/src/atoms/ui/spinner.tsx +0 -49
  92. package/src/atoms/ui/table.tsx +0 -116
  93. package/src/atoms/utils/animations.ts +0 -135
  94. package/src/atoms/utils/tooltip-helpers.ts +0 -140
  95. package/src/atoms/utils/utils.ts +0 -9
  96. package/src/features/auth/components/LoginForm.tsx +0 -168
  97. package/src/features/auth/components/LogoutButton.tsx +0 -19
  98. package/src/features/auth/components/ProtectedRoute.tsx +0 -60
  99. package/src/features/auth/components/index.ts +0 -4
  100. package/src/features/auth/hooks/index.ts +0 -2
  101. package/src/features/auth/hooks/useAuth.tsx +0 -205
  102. package/src/features/auth/hooks/usePermissions.ts +0 -35
  103. package/src/features/auth/index.ts +0 -2
  104. package/src/features/index.ts +0 -2
  105. package/src/index.css +0 -704
  106. package/src/index.ts +0 -13
  107. package/src/main.tsx +0 -48
  108. package/src/molecules/.gitkeep +0 -0
  109. package/src/molecules/forms/FormGroup.tsx +0 -75
  110. package/src/molecules/forms/SearchInput.tsx +0 -259
  111. package/src/molecules/forms/index.ts +0 -4
  112. package/src/molecules/index.ts +0 -4
  113. package/src/molecules/layout/AppHeader/AppHeader.tsx +0 -42
  114. package/src/molecules/layout/AppHeader/index.ts +0 -1
  115. package/src/molecules/layout/AppLayout.tsx +0 -29
  116. package/src/molecules/layout/PageTemplate.tsx +0 -87
  117. package/src/molecules/layout/SectionHeader/SectionHeader.tsx +0 -87
  118. package/src/molecules/layout/SectionHeader/index.ts +0 -1
  119. package/src/molecules/layout/ShowcaseSection.tsx +0 -57
  120. package/src/molecules/layout/Sidebar.tsx +0 -144
  121. package/src/molecules/layout/SidebarButton/SidebarButton.tsx +0 -99
  122. package/src/molecules/layout/SidebarButton/index.ts +0 -1
  123. package/src/molecules/layout/SidebarContext.tsx +0 -31
  124. package/src/molecules/layout/index.ts +0 -7
  125. package/src/molecules/navigation/NavMenu.tsx +0 -188
  126. package/src/molecules/navigation/Pagination.tsx +0 -172
  127. package/src/molecules/navigation/index.ts +0 -4
  128. package/src/organisms/index.ts +0 -5
  129. package/src/organisms/showcase/ComponentShowcasePage.tsx +0 -2496
  130. package/src/organisms/showcase/index.ts +0 -1
  131. package/src/pages/AdminShowcase/AdminCRUDShowcase.tsx +0 -242
  132. package/src/pages/AdminShowcase/AdminDashboardShowcase.tsx +0 -171
  133. package/src/pages/AdminShowcase/AdminDetailShowcase.tsx +0 -385
  134. package/src/pages/AdminShowcase/index.tsx +0 -3
  135. package/src/pages/ComponentShowcase/BadgesShowcase.tsx +0 -188
  136. package/src/pages/ComponentShowcase/CardsShowcase.tsx +0 -392
  137. package/src/pages/ComponentShowcase/PalettesShowcase.tsx +0 -207
  138. package/src/pages/ComponentShowcase/StatesShowcase.tsx +0 -485
  139. package/src/pages/ComponentShowcase/TablesShowcase.tsx +0 -134
  140. package/src/pages/ComponentShowcase/TypographyShowcase.tsx +0 -255
  141. package/src/pages/ComponentShowcase/index.tsx +0 -188
  142. package/src/pages/index.ts +0 -2
  143. package/src/templates/AuthTemplate.tsx +0 -216
  144. package/src/templates/ComponentShowcaseTemplate.tsx +0 -173
  145. package/src/templates/DashboardTemplate.tsx +0 -232
  146. package/src/templates/DataTemplate.tsx +0 -319
  147. package/src/templates/admin/AdminCRUDTemplate.tsx +0 -630
  148. package/src/templates/admin/AdminDashboardTemplate.tsx +0 -351
  149. package/src/templates/admin/AdminDetailTemplate.tsx +0 -563
  150. package/src/templates/admin/index.ts +0 -29
  151. package/src/templates/factory.tsx +0 -169
  152. package/src/templates/index.ts +0 -37
  153. package/src/vite-env.d.ts +0 -1
package/README.md CHANGED
@@ -35,8 +35,8 @@ app.addRoutes("/reports", ReportsRoutes)
35
35
  ### Installation
36
36
 
37
37
  ```bash
38
- # Install from GitHub (requires built dist/ folder)
39
- npm install git+https://github.com/pattern-stack/frontend-patterns.git
38
+ # Install from NPM
39
+ npm install @pattern-stack/frontend-patterns
40
40
 
41
41
  # Or for local development/testing
42
42
  npm install file:../path/to/frontend-patterns
@@ -223,10 +223,10 @@ Check out the `examples/` directory for complete app implementations:
223
223
 
224
224
  ```bash
225
225
  # Pin to specific version for stability
226
- @pattern-stack/frontend-patterns @ git+https://github.com/pattern-stack/frontend-patterns.git@v1.2.0
226
+ npm install @pattern-stack/frontend-patterns@1.2.0
227
227
 
228
228
  # Use latest for new development
229
- @pattern-stack/frontend-patterns @ git+https://github.com/pattern-stack/frontend-patterns.git@main
229
+ npm install @pattern-stack/frontend-patterns@latest
230
230
  ```
231
231
 
232
232
  ### Version History
@@ -261,8 +261,8 @@ mkdir test-app && cd test-app
261
261
  npm init -y
262
262
  npm install react react-dom @types/react @types/react-dom
263
263
 
264
- # 3. Install the local template
265
- npm install file:../path/to/frontend-patterns
264
+ # 3. Install the template
265
+ npm install @pattern-stack/frontend-patterns
266
266
 
267
267
  # 4. Create test app
268
268
  cat > main.tsx << 'EOF'
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@pattern-stack/frontend-patterns",
3
3
  "description": "Production-ready React frontend template with atomic architecture patterns. Build ultra-lean applications by importing shared UI foundation patterns.",
4
4
  "private": false,
5
- "version": "0.0.1",
5
+ "version": "0.0.3",
6
6
  "keywords": [
7
7
  "react",
8
8
  "typescript",
@@ -33,12 +33,10 @@
33
33
  "import": "./dist/index.es.js",
34
34
  "require": "./dist/index.js"
35
35
  },
36
- "./styles": "./dist/frontend-patterns.css",
37
- "./src/*": "./src/*"
36
+ "./styles": "./dist/frontend-patterns.css"
38
37
  },
39
38
  "files": [
40
- "dist",
41
- "src"
39
+ "dist"
42
40
  ],
43
41
  "type": "module",
44
42
  "scripts": {
package/src/App.css DELETED
@@ -1,42 +0,0 @@
1
- #root {
2
- max-width: 1280px;
3
- margin: 0 auto;
4
- padding: 2rem;
5
- text-align: center;
6
- }
7
-
8
- .logo {
9
- height: 6em;
10
- padding: 1.5em;
11
- will-change: filter;
12
- transition: filter 300ms;
13
- }
14
- .logo:hover {
15
- filter: drop-shadow(0 0 2em #646cffaa);
16
- }
17
- .logo.react:hover {
18
- filter: drop-shadow(0 0 2em #61dafbaa);
19
- }
20
-
21
- @keyframes logo-spin {
22
- from {
23
- transform: rotate(0deg);
24
- }
25
- to {
26
- transform: rotate(360deg);
27
- }
28
- }
29
-
30
- @media (prefers-reduced-motion: no-preference) {
31
- a:nth-of-type(2) .logo {
32
- animation: logo-spin infinite 20s linear;
33
- }
34
- }
35
-
36
- .card {
37
- padding: 2em;
38
- }
39
-
40
- .read-the-docs {
41
- color: #888;
42
- }
package/src/App.tsx DELETED
@@ -1,54 +0,0 @@
1
- import { BrowserRouter, Routes, Route } from 'react-router-dom';
2
-
3
- // Atoms
4
- import { ErrorBoundary } from './atoms/ui';
5
-
6
- // Features
7
- import { ProtectedRoute } from './features/auth';
8
-
9
- // Organisms
10
- import { AppLayout } from './molecules/layout/AppLayout';
11
- import { ComponentShowcasePage } from './organisms/showcase';
12
-
13
- // Pages
14
- import {
15
- ComponentShowcase,
16
- AdminDashboardShowcase,
17
- AdminCRUDShowcase,
18
- AdminDetailShowcase
19
- } from './pages';
20
-
21
- function App() {
22
- return (
23
- <ErrorBoundary>
24
- <BrowserRouter>
25
- <Routes>
26
- <Route path="/" element={
27
- <ProtectedRoute>
28
- <AppLayout />
29
- </ProtectedRoute>
30
- }>
31
- {/* Default to Component Showcase */}
32
- <Route index element={<ErrorBoundary><ComponentShowcasePage /></ErrorBoundary>} />
33
-
34
- {/* Component Showcase - Complete with Navigation/Forms/Feedback */}
35
- <Route path="showcase" element={<ErrorBoundary><ComponentShowcasePage /></ErrorBoundary>} />
36
-
37
- {/* Template-driven Showcase (alternative version) */}
38
- <Route path="showcase-alt" element={<ErrorBoundary><ComponentShowcase /></ErrorBoundary>} />
39
-
40
- {/* Admin Template Showcases */}
41
- <Route path="admin/dashboard" element={<ErrorBoundary><AdminDashboardShowcase /></ErrorBoundary>} />
42
- <Route path="admin/users" element={<ErrorBoundary><AdminCRUDShowcase /></ErrorBoundary>} />
43
- <Route path="admin/user/:id" element={<ErrorBoundary><AdminDetailShowcase /></ErrorBoundary>} />
44
-
45
- {/* Fallback */}
46
- <Route path="*" element={<ErrorBoundary><ComponentShowcasePage /></ErrorBoundary>} />
47
- </Route>
48
- </Routes>
49
- </BrowserRouter>
50
- </ErrorBoundary>
51
- );
52
- }
53
-
54
- export default App;
@@ -1,221 +0,0 @@
1
- # Frontend Testing Strategy
2
-
3
- > Atomic design testing that mirrors your backend testing architecture
4
-
5
- ## 🏗️ Testing Architecture
6
-
7
- Our frontend tests follow the **same atomic structure** as your backend tests:
8
-
9
- ```
10
- src/__tests__/
11
- ├── atoms/ # Unit tests (like backend atoms/)
12
- │ ├── ui/ # UI component tests
13
- │ ├── business/ # Business component tests
14
- │ ├── hooks/ # React hooks tests
15
- │ ├── utils/ # Utility function tests
16
- │ └── services/ # API client tests
17
- ├── molecules/ # Component integration tests
18
- │ ├── forms/ # Form component tests
19
- │ ├── layout/ # Layout component tests
20
- │ └── navigation/ # Navigation tests
21
- ├── organisms/ # Page/complex component tests
22
- │ └── showcase/ # Full page tests
23
- ├── features/ # Feature integration tests
24
- │ └── auth/ # Auth system tests
25
- ├── setup.ts # Test setup (like conftest.py)
26
- └── utils.tsx # Test utilities (like pytest fixtures)
27
- ```
28
-
29
- ## 🧪 Testing Stack
30
-
31
- **Framework**: Vitest (Vite-native, fast)
32
- **React Testing**: @testing-library/react
33
- **User Interaction**: @testing-library/user-event
34
- **Environment**: jsdom (browser simulation)
35
- **Assertions**: jest-dom matchers
36
-
37
- ## 📋 Test Commands
38
-
39
- ```bash
40
- # Run all tests
41
- npm run test
42
-
43
- # Run with UI (visual test runner)
44
- npm run test:ui
45
-
46
- # Run once (CI mode)
47
- npm run test:run
48
-
49
- # Watch mode (development)
50
- npm run test:watch
51
-
52
- # Coverage report
53
- npm run test:coverage
54
-
55
- # Test by atomic level (like backend)
56
- npm run test:atoms # Unit tests
57
- npm run test:molecules # Component integration
58
- npm run test:organisms # Page tests
59
- npm run test:features # Feature integration
60
- ```
61
-
62
- ## 🎯 Testing Patterns
63
-
64
- ### Atoms (Unit Tests)
65
- ```typescript
66
- // UI Components
67
- describe('Button (Atom)', () => {
68
- it('renders with correct variant styles', () => {
69
- render(<Button variant="primary">Click me</Button>)
70
- expect(screen.getByRole('button')).toHaveClass('bg-primary')
71
- })
72
- })
73
-
74
- // Hooks
75
- describe('useApi (Atom)', () => {
76
- it('handles API calls correctly', async () => {
77
- const { result } = renderHook(() => useApiQuery(['test'], mockFn))
78
- await waitFor(() => expect(result.current.isSuccess).toBe(true))
79
- })
80
- })
81
-
82
- // Utils
83
- describe('cn utility (Atom)', () => {
84
- it('merges classes correctly', () => {
85
- expect(cn('px-4', 'py-2')).toBe('px-4 py-2')
86
- })
87
- })
88
- ```
89
-
90
- ### Molecules (Component Integration)
91
- ```typescript
92
- describe('AppHeader (Molecule)', () => {
93
- it('integrates auth, navigation, and UI atoms', () => {
94
- render(<AppHeader />)
95
- expect(screen.getByRole('banner')).toBeInTheDocument()
96
- expect(screen.getByTestId('user-menu')).toBeInTheDocument()
97
- })
98
- })
99
- ```
100
-
101
- ### Organisms (Page Tests)
102
- ```typescript
103
- describe('ComponentShowcasePage (Organism)', () => {
104
- it('renders complete page with all sections', () => {
105
- render(<ComponentShowcasePage />)
106
- expect(screen.getByRole('main')).toBeInTheDocument()
107
- // Test full page functionality
108
- })
109
- })
110
- ```
111
-
112
- ### Features (Integration Tests)
113
- ```typescript
114
- describe('useAuth (Feature)', () => {
115
- it('handles complete auth flow', async () => {
116
- const { result } = renderHook(() => useAuth())
117
- await act(() => result.current.login(credentials))
118
- expect(result.current.isAuthenticated).toBe(true)
119
- })
120
- })
121
- ```
122
-
123
- ## 🛠️ Test Utilities
124
-
125
- ### Setup (`setup.ts`)
126
- - Global test configuration
127
- - Mock browser APIs
128
- - Environment setup
129
- - Like your `conftest.py`
130
-
131
- ### Utils (`utils.tsx`)
132
- - Custom render with providers
133
- - Mock factories (users, API clients)
134
- - Test helpers and fixtures
135
- - Like your pytest fixtures
136
-
137
- ### Example Usage
138
- ```typescript
139
- import { render, createMockUser, createMockApiClient } from '../utils'
140
-
141
- describe('MyComponent', () => {
142
- it('works with test utilities', () => {
143
- const mockUser = createMockUser({ name: 'Test User' })
144
- const mockApi = createMockApiClient()
145
-
146
- render(<MyComponent />, {
147
- initialRoute: '/dashboard',
148
- queryClient: new QueryClient()
149
- })
150
- })
151
- })
152
- ```
153
-
154
- ## 🎨 Design System Testing
155
-
156
- Our tests enforce design system compliance:
157
-
158
- ```typescript
159
- it('uses design system classes only', () => {
160
- render(<Component />)
161
- const element = screen.getByRole('button')
162
-
163
- // ✅ Should use design system
164
- expect(element).toHaveClass('bg-primary')
165
-
166
- // ❌ Should NOT use hardcoded colors
167
- expect(element.className).not.toMatch(/bg-blue-\d+/)
168
- })
169
- ```
170
-
171
- ## 📊 Coverage Goals
172
-
173
- - **Atoms**: 90%+ (pure functions, UI components)
174
- - **Molecules**: 80%+ (component integration)
175
- - **Organisms**: 70%+ (complex pages)
176
- - **Features**: 85%+ (business logic)
177
-
178
- ## 🔄 CI/CD Integration
179
-
180
- Tests run in pre-commit hooks:
181
- ```bash
182
- npm run pre-commit # style:check + test:run + build
183
- ```
184
-
185
- ## 🚀 Running Tests
186
-
187
- ```bash
188
- # Development workflow
189
- npm run test:watch # Watch mode while coding
190
-
191
- # Before committing
192
- npm run test:run # Full test suite
193
- npm run test:coverage # Check coverage
194
-
195
- # Debugging specific areas
196
- npm run test:atoms # Just unit tests
197
- npm run test:features # Just integration tests
198
-
199
- # Visual debugging
200
- npm run test:ui # Vitest UI runner
201
- ```
202
-
203
- ## 🎯 Best Practices
204
-
205
- 1. **Mirror Backend Structure**: Tests follow atomic design
206
- 2. **Design System Compliance**: Test CSS class usage
207
- 3. **Integration Focus**: Test component interactions
208
- 4. **User-Centric**: Test user workflows, not implementation
209
- 5. **Mock External Dependencies**: API calls, localStorage, etc.
210
- 6. **Accessibility**: Test keyboard navigation, ARIA attributes
211
-
212
- ## 🔧 Configuration
213
-
214
- - **vitest.config.ts**: Main test configuration
215
- - **setup.ts**: Global test setup and mocks
216
- - **utils.tsx**: Reusable test utilities and providers
217
- - **package.json**: Test scripts and atomic-level commands
218
-
219
- ---
220
-
221
- **Result**: Frontend testing that mirrors your backend's atomic architecture with comprehensive coverage and design system enforcement! 🧪⚛️
@@ -1,44 +0,0 @@
1
- import { describe, it, expect } from 'vitest'
2
- import { renderHook } from '@testing-library/react'
3
- import { useState } from 'react'
4
-
5
- describe('Simple Hook Tests (Example)', () => {
6
- it('useState hook works correctly', () => {
7
- const { result } = renderHook(() => useState(0))
8
-
9
- const [count, setCount] = result.current
10
- expect(count).toBe(0)
11
-
12
- // Test that hook function is returned
13
- expect(typeof setCount).toBe('function')
14
- })
15
-
16
- it('useEffect-like behavior can be tested', () => {
17
- const { result, rerender } = renderHook(
18
- ({ initialValue }) => useState(initialValue),
19
- { initialProps: { initialValue: 10 } }
20
- )
21
-
22
- expect(result.current[0]).toBe(10)
23
-
24
- // Test re-render with new props
25
- rerender({ initialValue: 20 })
26
- // Note: useState doesn't re-initialize on prop changes, this is just testing the pattern
27
- expect(result.current[0]).toBe(10) // Still 10 because useState doesn't re-init
28
- })
29
-
30
- it('custom hook pattern testing', () => {
31
- const useCounter = (initial = 0) => {
32
- const [count, setCount] = useState(initial)
33
- const increment = () => setCount(c => c + 1)
34
- const decrement = () => setCount(c => c - 1)
35
- return { count, increment, decrement }
36
- }
37
-
38
- const { result } = renderHook(() => useCounter(5))
39
-
40
- expect(result.current.count).toBe(5)
41
- expect(typeof result.current.increment).toBe('function')
42
- expect(typeof result.current.decrement).toBe('function')
43
- })
44
- })
@@ -1,68 +0,0 @@
1
- import React from 'react'
2
- import { describe, it, expect } from 'vitest'
3
- import { render, screen, userEvent } from '../../utils'
4
- import { Button } from '../../../atoms/ui/button'
5
-
6
- describe('Button (Atom)', () => {
7
- it('renders with default variant', () => {
8
- render(<Button>Click me</Button>)
9
- const button = screen.getByRole('button', { name: /click me/i })
10
- expect(button).toBeInTheDocument()
11
- // The button uses gradient, so check for primary color reference
12
- expect(button.className).toContain('from-primary')
13
- })
14
-
15
- it('renders with different variants', () => {
16
- const { rerender } = render(<Button variant="secondary">Secondary</Button>)
17
- expect(screen.getByRole('button')).toHaveClass('bg-gray-100')
18
-
19
- rerender(<Button variant="destructive">Destructive</Button>)
20
- expect(screen.getByRole('button').className).toContain('from-destructive')
21
- })
22
-
23
- it('renders with different sizes', () => {
24
- const { rerender } = render(<Button size="sm">Small</Button>)
25
- expect(screen.getByRole('button')).toHaveClass('h-9')
26
-
27
- rerender(<Button size="lg">Large</Button>)
28
- expect(screen.getByRole('button')).toHaveClass('h-12')
29
- })
30
-
31
- it('handles click events', async () => {
32
- const user = userEvent.setup()
33
- const handleClick = vi.fn()
34
-
35
- render(<Button onClick={handleClick}>Click me</Button>)
36
-
37
- await user.click(screen.getByRole('button'))
38
- expect(handleClick).toHaveBeenCalledOnce()
39
- })
40
-
41
- it('is disabled when disabled prop is true', () => {
42
- render(<Button disabled>Disabled</Button>)
43
- const button = screen.getByRole('button')
44
- expect(button).toBeDisabled()
45
- expect(button).toHaveClass('disabled:pointer-events-none')
46
- })
47
-
48
- it('renders as child component when asChild is true', () => {
49
- render(
50
- <Button asChild>
51
- <a href="/test">Link button</a>
52
- </Button>
53
- )
54
-
55
- const link = screen.getByRole('link')
56
- expect(link).toBeInTheDocument()
57
- expect(link.className).toContain('from-primary')
58
- expect(link).toHaveAttribute('href', '/test')
59
- })
60
-
61
- it('forwards ref correctly', () => {
62
- const ref = React.createRef<HTMLButtonElement>()
63
- render(<Button ref={ref}>Button</Button>)
64
-
65
- expect(ref.current).toBeInstanceOf(HTMLButtonElement)
66
- expect(ref.current).toHaveTextContent('Button')
67
- })
68
- })
@@ -1,18 +0,0 @@
1
- import { describe, it, expect } from 'vitest'
2
-
3
- describe('Simple Test (Example)', () => {
4
- it('basic arithmetic works', () => {
5
- expect(2 + 2).toBe(4)
6
- })
7
-
8
- it('string manipulation works', () => {
9
- const str = 'hello world'
10
- expect(str.toUpperCase()).toBe('HELLO WORLD')
11
- })
12
-
13
- it('array operations work', () => {
14
- const arr = [1, 2, 3]
15
- expect(arr.length).toBe(3)
16
- expect(arr.includes(2)).toBe(true)
17
- })
18
- })
@@ -1,77 +0,0 @@
1
- import { describe, it, expect } from 'vitest'
2
- import { cn } from '../../../atoms/utils/utils'
3
-
4
- describe('Utils (Atoms)', () => {
5
- describe('cn (className utility)', () => {
6
- it('merges class names correctly', () => {
7
- const result = cn('px-4 py-2', 'bg-blue-500')
8
- expect(result).toBe('px-4 py-2 bg-blue-500')
9
- })
10
-
11
- it('handles conditional classes', () => {
12
- const isActive = true
13
- const isDisabled = false
14
-
15
- const result = cn(
16
- 'base-class',
17
- isActive && 'active-class',
18
- isDisabled && 'disabled-class'
19
- )
20
-
21
- expect(result).toBe('base-class active-class')
22
- })
23
-
24
- it('resolves conflicting Tailwind classes', () => {
25
- // tailwind-merge should resolve conflicts
26
- const result = cn('px-2 px-4') // px-4 should win
27
- expect(result).toBe('px-4')
28
- })
29
-
30
- it('handles arrays of classes', () => {
31
- const result = cn(['px-4', 'py-2'], ['bg-blue-500', 'text-white'])
32
- expect(result).toBe('px-4 py-2 bg-blue-500 text-white')
33
- })
34
-
35
- it('handles object syntax', () => {
36
- const result = cn({
37
- 'px-4': true,
38
- 'py-2': true,
39
- 'bg-red-500': false,
40
- 'bg-blue-500': true,
41
- })
42
- expect(result).toBe('px-4 py-2 bg-blue-500')
43
- })
44
-
45
- it('handles undefined and null values', () => {
46
- const result = cn('px-4', undefined, null, 'py-2')
47
- expect(result).toBe('px-4 py-2')
48
- })
49
-
50
- it('handles empty strings', () => {
51
- const result = cn('', 'px-4', '', 'py-2')
52
- expect(result).toBe('px-4 py-2')
53
- })
54
-
55
- it('maintains design system classes', () => {
56
- // Test that design system classes are preserved
57
- const result = cn('bg-primary text-primary-foreground', 'hover:bg-primary-hover')
58
- expect(result).toBe('bg-primary text-primary-foreground hover:bg-primary-hover')
59
- })
60
-
61
- it('works with status classes', () => {
62
- const status = 'success'
63
- const result = cn(
64
- 'base-class',
65
- status === 'success' && 'status-success',
66
- status === 'error' && 'status-error'
67
- )
68
- expect(result).toBe('base-class status-success')
69
- })
70
-
71
- it('works with category classes', () => {
72
- const category = 2
73
- const result = cn('base-class', `category-${category}`)
74
- expect(result).toBe('base-class category-2')
75
- })
76
- })
77
- })
@@ -1,40 +0,0 @@
1
- import React from 'react'
2
- import { describe, it, expect } from 'vitest'
3
- import { render, screen } from '../../utils'
4
-
5
- // Simple auth component for testing
6
- const AuthStatus = ({ isAuthenticated }: { isAuthenticated: boolean }) => (
7
- <div>
8
- {isAuthenticated ? (
9
- <span data-testid="authenticated">User is logged in</span>
10
- ) : (
11
- <span data-testid="not-authenticated">Please log in</span>
12
- )}
13
- </div>
14
- )
15
-
16
- describe('Auth Components (Feature)', () => {
17
- it('displays authenticated state correctly', () => {
18
- render(<AuthStatus isAuthenticated={true} />)
19
-
20
- expect(screen.getByTestId('authenticated')).toBeInTheDocument()
21
- expect(screen.getByText('User is logged in')).toBeInTheDocument()
22
- })
23
-
24
- it('displays unauthenticated state correctly', () => {
25
- render(<AuthStatus isAuthenticated={false} />)
26
-
27
- expect(screen.getByTestId('not-authenticated')).toBeInTheDocument()
28
- expect(screen.getByText('Please log in')).toBeInTheDocument()
29
- })
30
-
31
- it('toggles between states correctly', () => {
32
- const { rerender } = render(<AuthStatus isAuthenticated={false} />)
33
-
34
- expect(screen.getByText('Please log in')).toBeInTheDocument()
35
-
36
- rerender(<AuthStatus isAuthenticated={true} />)
37
-
38
- expect(screen.getByText('User is logged in')).toBeInTheDocument()
39
- })
40
- })