@opensaas/stack-ui 0.1.7 → 0.3.0

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 (47) hide show
  1. package/.turbo/turbo-build.log +3 -2
  2. package/CHANGELOG.md +4 -0
  3. package/dist/components/AdminUI.d.ts +2 -1
  4. package/dist/components/AdminUI.d.ts.map +1 -1
  5. package/dist/components/AdminUI.js +2 -2
  6. package/dist/components/ItemFormClient.d.ts.map +1 -1
  7. package/dist/components/ItemFormClient.js +78 -60
  8. package/dist/components/Navigation.d.ts +2 -1
  9. package/dist/components/Navigation.d.ts.map +1 -1
  10. package/dist/components/Navigation.js +3 -2
  11. package/dist/components/UserMenu.d.ts +11 -0
  12. package/dist/components/UserMenu.d.ts.map +1 -0
  13. package/dist/components/UserMenu.js +18 -0
  14. package/dist/components/fields/TextField.d.ts +2 -1
  15. package/dist/components/fields/TextField.d.ts.map +1 -1
  16. package/dist/components/fields/TextField.js +4 -2
  17. package/dist/index.d.ts +2 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +1 -0
  20. package/dist/primitives/button.d.ts +1 -1
  21. package/dist/styles/globals.css +24 -0
  22. package/package.json +14 -5
  23. package/src/components/AdminUI.tsx +3 -0
  24. package/src/components/ItemFormClient.tsx +84 -62
  25. package/src/components/Navigation.tsx +9 -20
  26. package/src/components/UserMenu.tsx +44 -0
  27. package/src/components/fields/TextField.tsx +7 -2
  28. package/src/index.ts +2 -0
  29. package/tests/browser/README.md +154 -0
  30. package/tests/browser/fields/CheckboxField.browser.test.tsx +245 -0
  31. package/tests/browser/fields/SelectField.browser.test.tsx +263 -0
  32. package/tests/browser/fields/TextField.browser.test.tsx +204 -0
  33. package/tests/browser/fields/__screenshots__/CheckboxField.browser.test.tsx/CheckboxField--Browser--edit-mode-should-not-be-clickable-when-disabled-1.png +0 -0
  34. package/tests/browser/fields/__screenshots__/CheckboxField.browser.test.tsx/CheckboxField--Browser--edit-mode-should-toggle-state-with-multiple-clicks-1.png +0 -0
  35. package/tests/browser/fields/__screenshots__/TextField.browser.test.tsx/TextField--Browser--edit-mode-should-handle-special-characters-1.png +0 -0
  36. package/tests/browser/fields/__screenshots__/TextField.browser.test.tsx/TextField--Browser--edit-mode-should-support-copy-and-paste-1.png +0 -0
  37. package/tests/browser/primitives/Button.browser.test.tsx +122 -0
  38. package/tests/browser/primitives/Dialog.browser.test.tsx +279 -0
  39. package/tests/browser/primitives/__screenshots__/Button.browser.test.tsx/Button--Browser--should-not-trigger-click-when-disabled-1.png +0 -0
  40. package/tests/components/CheckboxField.test.tsx +130 -0
  41. package/tests/components/DeleteButton.test.tsx +331 -0
  42. package/tests/components/IntegerField.test.tsx +147 -0
  43. package/tests/components/ListTable.test.tsx +457 -0
  44. package/tests/components/ListViewClient.test.tsx +415 -0
  45. package/tests/components/SearchBar.test.tsx +254 -0
  46. package/tests/components/SelectField.test.tsx +192 -0
  47. package/vitest.config.ts +20 -0
@@ -0,0 +1,192 @@
1
+ import { describe, it, expect, vi } from 'vitest'
2
+ import { render, screen } from '@testing-library/react'
3
+ import { SelectField } from '../../src/components/fields/SelectField.js'
4
+
5
+ describe('SelectField', () => {
6
+ const mockOptions = [
7
+ { label: 'Draft', value: 'draft' },
8
+ { label: 'Published', value: 'published' },
9
+ { label: 'Archived', value: 'archived' },
10
+ ]
11
+
12
+ describe('edit mode', () => {
13
+ it('should render select with label', () => {
14
+ render(
15
+ <SelectField
16
+ name="status"
17
+ value=""
18
+ onChange={vi.fn()}
19
+ label="Status"
20
+ options={mockOptions}
21
+ />,
22
+ )
23
+
24
+ expect(screen.getByText('Status')).toBeInTheDocument()
25
+ // Select is rendered as a button with role combobox
26
+ expect(screen.getByRole('combobox')).toBeInTheDocument()
27
+ })
28
+
29
+ it('should display default placeholder when no value selected', () => {
30
+ render(
31
+ <SelectField
32
+ name="status"
33
+ value=""
34
+ onChange={vi.fn()}
35
+ label="Status"
36
+ options={mockOptions}
37
+ />,
38
+ )
39
+
40
+ // The component uses a hard-coded placeholder text
41
+ expect(screen.getByText('Select an option...')).toBeInTheDocument()
42
+ })
43
+
44
+ it('should display current selected value label', () => {
45
+ render(
46
+ <SelectField
47
+ name="status"
48
+ value="published"
49
+ onChange={vi.fn()}
50
+ label="Status"
51
+ options={mockOptions}
52
+ />,
53
+ )
54
+
55
+ // Should show the selected option label in the select trigger
56
+ expect(screen.getByText('Published')).toBeInTheDocument()
57
+ })
58
+
59
+ it('should show required indicator when required', () => {
60
+ render(
61
+ <SelectField
62
+ name="status"
63
+ value=""
64
+ onChange={vi.fn()}
65
+ label="Status"
66
+ options={mockOptions}
67
+ required
68
+ />,
69
+ )
70
+
71
+ expect(screen.getByText('*')).toBeInTheDocument()
72
+ })
73
+
74
+ it('should display error message', () => {
75
+ render(
76
+ <SelectField
77
+ name="status"
78
+ value=""
79
+ onChange={vi.fn()}
80
+ label="Status"
81
+ options={mockOptions}
82
+ error="Status is required"
83
+ />,
84
+ )
85
+
86
+ expect(screen.getByText('Status is required')).toBeInTheDocument()
87
+ })
88
+
89
+ it('should be disabled when disabled prop is true', () => {
90
+ render(
91
+ <SelectField
92
+ name="status"
93
+ value=""
94
+ onChange={vi.fn()}
95
+ label="Status"
96
+ options={mockOptions}
97
+ disabled
98
+ />,
99
+ )
100
+
101
+ const select = screen.getByRole('combobox')
102
+ expect(select).toBeDisabled()
103
+ })
104
+
105
+ it('should render select trigger element', () => {
106
+ render(
107
+ <SelectField
108
+ name="status"
109
+ value=""
110
+ onChange={vi.fn()}
111
+ label="Status"
112
+ options={mockOptions}
113
+ />,
114
+ )
115
+
116
+ // Select trigger should be present
117
+ const select = screen.getByRole('combobox')
118
+ expect(select).toBeInTheDocument()
119
+ })
120
+ })
121
+
122
+ describe('read mode', () => {
123
+ it('should render selected value as text', () => {
124
+ render(
125
+ <SelectField
126
+ name="status"
127
+ value="published"
128
+ onChange={vi.fn()}
129
+ label="Status"
130
+ options={mockOptions}
131
+ mode="read"
132
+ />,
133
+ )
134
+
135
+ expect(screen.getByText('Status')).toBeInTheDocument()
136
+ expect(screen.getByText('Published')).toBeInTheDocument()
137
+ expect(screen.queryByRole('combobox')).not.toBeInTheDocument()
138
+ })
139
+
140
+ it('should show dash when no value selected', () => {
141
+ render(
142
+ <SelectField
143
+ name="status"
144
+ value=""
145
+ onChange={vi.fn()}
146
+ label="Status"
147
+ options={mockOptions}
148
+ mode="read"
149
+ />,
150
+ )
151
+
152
+ expect(screen.getByText('-')).toBeInTheDocument()
153
+ })
154
+
155
+ it('should show dash for invalid value', () => {
156
+ render(
157
+ <SelectField
158
+ name="status"
159
+ value="invalid"
160
+ onChange={vi.fn()}
161
+ label="Status"
162
+ options={mockOptions}
163
+ mode="read"
164
+ />,
165
+ )
166
+
167
+ expect(screen.getByText('-')).toBeInTheDocument()
168
+ })
169
+ })
170
+
171
+ describe('edge cases', () => {
172
+ it('should handle empty options array', () => {
173
+ render(<SelectField name="status" value="" onChange={vi.fn()} label="Status" options={[]} />)
174
+
175
+ expect(screen.getByRole('combobox')).toBeInTheDocument()
176
+ })
177
+
178
+ it('should handle single option array', () => {
179
+ render(
180
+ <SelectField
181
+ name="status"
182
+ value=""
183
+ onChange={vi.fn()}
184
+ label="Status"
185
+ options={[{ label: 'Only Option', value: 'only' }]}
186
+ />,
187
+ )
188
+
189
+ expect(screen.getByRole('combobox')).toBeInTheDocument()
190
+ })
191
+ })
192
+ })
package/vitest.config.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { defineConfig } from 'vitest/config'
2
2
  import react from '@vitejs/plugin-react'
3
3
  import path from 'path'
4
+ import { playwright } from '@vitest/browser-playwright'
4
5
 
5
6
  export default defineConfig({
6
7
  plugins: [react()],
@@ -8,11 +9,30 @@ export default defineConfig({
8
9
  environment: 'happy-dom',
9
10
  globals: true,
10
11
  setupFiles: ['./tests/setup.ts'],
12
+ // Exclude browser tests from regular test runs
13
+ exclude: process.env.BROWSER_TEST === 'true' ? [] : ['**/browser/**'],
14
+ // Include only browser tests when in browser mode
15
+ include:
16
+ process.env.BROWSER_TEST === 'true'
17
+ ? ['tests/browser/**/*.test.{ts,tsx}']
18
+ : ['tests/**/*.test.{ts,tsx}', '!tests/browser/**'],
11
19
  coverage: {
12
20
  provider: 'v8',
13
21
  reporter: ['text', 'json', 'html', 'json-summary'],
14
22
  exclude: ['node_modules/', 'tests/', 'dist/', '**/*.d.ts', '**/*.config.*', '**/index.ts'],
15
23
  },
24
+ // Browser mode configuration
25
+ browser: {
26
+ enabled: process.env.BROWSER_TEST === 'true',
27
+ instances: [
28
+ {
29
+ browser: 'chromium',
30
+ },
31
+ ],
32
+ provider: playwright(),
33
+ headless: true,
34
+ screenshotFailures: true,
35
+ },
16
36
  },
17
37
  resolve: {
18
38
  alias: {