@moontra/moonui 3.2.0 → 3.4.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.
- package/dist/chunk-VXDFZPDA.global.js +33 -0
- package/dist/{chunk-X5ULQZNC.global.js.map → chunk-VXDFZPDA.global.js.map} +1 -1
- package/dist/index.d.mts +47 -3
- package/dist/index.d.ts +47 -3
- package/dist/index.global.js +41 -19
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +216 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +208 -22
- package/dist/index.mjs.map +1 -1
- package/dist/lib/theme.global.js +30 -6
- package/dist/lib/theme.global.js.map +1 -1
- package/package.json +2 -1
- package/src/components/ui/__tests__/button-group.test.tsx +183 -0
- package/src/components/ui/__tests__/checkbox.test.tsx +16 -12
- package/src/components/ui/__tests__/color-picker.test.tsx +147 -331
- package/src/components/ui/__tests__/radio-group.test.tsx +60 -0
- package/src/components/ui/__tests__/slider.test.tsx +96 -0
- package/src/components/ui/__tests__/toggle-group.test.tsx +323 -0
- package/src/components/ui/button-group.tsx +125 -0
- package/src/components/ui/checkbox.tsx +20 -18
- package/src/components/ui/color-picker.tsx +12 -0
- package/src/components/ui/index.ts +30 -0
- package/src/components/ui/radio-group.tsx +47 -8
- package/src/components/ui/slider.tsx +56 -2
- package/src/components/ui/toggle-group.tsx +97 -0
- package/dist/chunk-X5ULQZNC.global.js +0 -33
|
@@ -1,365 +1,181 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* ColorPicker / SimpleColorPicker / GradientPicker testleri.
|
|
3
|
+
*
|
|
4
|
+
* ─── BU DOSYA NEDEN BAŞTAN YAZILDI (issue #263) ──────────────────────────────
|
|
5
|
+
* Önceki hâli var olmayan bir API'ye yazılmıştı: `color` / `onColorChange`
|
|
6
|
+
* prop'ları, `data-testid="color-display"`, `"color-area"`, `"opacity-slider"`
|
|
7
|
+
* gibi test-id'ler ve "Eyedropper", "Color Stops", "Add Stop", "Enter color..."
|
|
8
|
+
* gibi metinler. Bunların HİÇBİRİ kaynakta geçmiyordu (10/10 işaret için grep
|
|
9
|
+
* sonucu 0) — dolayısıyla 30 testin 22'si sürekli kırmızıydı ve dosya hiçbir
|
|
10
|
+
* regresyonu yakalayamıyordu.
|
|
11
|
+
*
|
|
12
|
+
* Gerçek API:
|
|
13
|
+
* ColorPicker { value, onChange, size, shape, showInput, showPresets,
|
|
14
|
+
* presets, allowOpacity, format, disableCopy, triggerMode,
|
|
15
|
+
* disabled, className }
|
|
16
|
+
* SimpleColorPicker { value, onChange, colors, size, className }
|
|
17
|
+
* GradientPicker { value: { start, end, angle }, onChange, className }
|
|
18
|
+
*/
|
|
19
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
2
20
|
import { ColorPicker, SimpleColorPicker, GradientPicker } from '../color-picker';
|
|
3
21
|
import '@testing-library/jest-dom';
|
|
4
22
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
fireEvent.click(button);
|
|
30
|
-
|
|
31
|
-
await waitFor(() => {
|
|
32
|
-
expect(screen.getByRole('dialog')).toBeInTheDocument();
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('calls onColorChange when color is selected', async () => {
|
|
37
|
-
const mockOnChange = jest.fn();
|
|
38
|
-
render(<ColorPicker color="#ffffff" onColorChange={mockOnChange} />);
|
|
39
|
-
|
|
40
|
-
const button = screen.getByRole('button');
|
|
41
|
-
fireEvent.click(button);
|
|
42
|
-
|
|
43
|
-
await waitFor(() => {
|
|
44
|
-
const colorArea = screen.getByTestId('color-area');
|
|
45
|
-
fireEvent.click(colorArea);
|
|
46
|
-
expect(mockOnChange).toHaveBeenCalled();
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('handles HSL color format', () => {
|
|
51
|
-
const mockOnChange = jest.fn();
|
|
52
|
-
render(<ColorPicker color="hsl(120, 100%, 50%)" onColorChange={mockOnChange} />);
|
|
53
|
-
|
|
54
|
-
expect(screen.getByText('hsl(120, 100%, 50%)')).toBeInTheDocument();
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('handles RGB color format', () => {
|
|
58
|
-
const mockOnChange = jest.fn();
|
|
59
|
-
render(<ColorPicker color="rgb(255, 0, 0)" onColorChange={mockOnChange} />);
|
|
60
|
-
|
|
61
|
-
expect(screen.getByText('rgb(255, 0, 0)')).toBeInTheDocument();
|
|
62
|
-
});
|
|
23
|
+
/** ColorPicker'ı render edip Popover panelini açar. */
|
|
24
|
+
function renderOpen(props: Partial<React.ComponentProps<typeof ColorPicker>> = {}) {
|
|
25
|
+
const utils = render(<ColorPicker {...props} />);
|
|
26
|
+
fireEvent.click(screen.getByRole('button', { name: 'Pick a color' }));
|
|
27
|
+
return utils;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Radix TabsTrigger seçimi `onMouseDown` üzerinden yapar — `fireEvent.click`
|
|
32
|
+
* mouseDown üretmediği için sekme DEĞİŞMEZ (ölçülerek doğrulandı).
|
|
33
|
+
*/
|
|
34
|
+
function activateTab(name: string) {
|
|
35
|
+
fireEvent.mouseDown(screen.getByRole('tab', { name }));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
describe('ColorPicker', () => {
|
|
39
|
+
it('tetikleyici buton erişilebilir ad taşır ve seçili rengi gösterir', () => {
|
|
40
|
+
render(<ColorPicker value="#ff0000" />);
|
|
41
|
+
|
|
42
|
+
const trigger = screen.getByRole('button', { name: 'Pick a color' });
|
|
43
|
+
expect(trigger).toBeInTheDocument();
|
|
44
|
+
// Renk arka planda taşınır (buton içeriği sr-only metinden ibarettir).
|
|
45
|
+
expect(trigger).toHaveStyle({ backgroundColor: '#ff0000' });
|
|
46
|
+
});
|
|
63
47
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const button = screen.getByRole('button');
|
|
69
|
-
fireEvent.click(button);
|
|
70
|
-
|
|
71
|
-
await waitFor(() => {
|
|
72
|
-
expect(screen.getByText('Opacity')).toBeInTheDocument();
|
|
73
|
-
const opacitySlider = screen.getByTestId('opacity-slider');
|
|
74
|
-
expect(opacitySlider).toBeInTheDocument();
|
|
75
|
-
});
|
|
76
|
-
});
|
|
48
|
+
it('disabled iken tetikleyici devre dışıdır', () => {
|
|
49
|
+
render(<ColorPicker value="#ffffff" disabled />);
|
|
50
|
+
expect(screen.getByRole('button', { name: 'Pick a color' })).toBeDisabled();
|
|
51
|
+
});
|
|
77
52
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
async open() {
|
|
83
|
-
return { sRGBHex: '#ff0000' };
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
});
|
|
53
|
+
it('özel className tetikleyiciye uygulanır', () => {
|
|
54
|
+
render(<ColorPicker value="#ffffff" className="custom-class" />);
|
|
55
|
+
expect(screen.getByRole('button', { name: 'Pick a color' })).toHaveClass('custom-class');
|
|
56
|
+
});
|
|
87
57
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const button = screen.getByRole('button');
|
|
92
|
-
fireEvent.click(button);
|
|
93
|
-
|
|
94
|
-
await waitFor(() => {
|
|
95
|
-
expect(screen.getByText('Eyedropper')).toBeInTheDocument();
|
|
96
|
-
});
|
|
97
|
-
});
|
|
58
|
+
it('tıklanınca panel açılır ve üç sekme sunar', () => {
|
|
59
|
+
renderOpen({ value: '#ffffff' });
|
|
98
60
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const button = screen.getByRole('button');
|
|
104
|
-
expect(button).toBeDisabled();
|
|
105
|
-
});
|
|
61
|
+
expect(screen.getByRole('tab', { name: 'Picker' })).toBeInTheDocument();
|
|
62
|
+
expect(screen.getByRole('tab', { name: 'Sliders' })).toBeInTheDocument();
|
|
63
|
+
expect(screen.getByRole('tab', { name: 'Input' })).toBeInTheDocument();
|
|
106
64
|
});
|
|
107
65
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const mockOnChange = jest.fn();
|
|
111
|
-
render(<SimpleColorPicker color="#ffffff" onColorChange={mockOnChange} />);
|
|
112
|
-
|
|
113
|
-
expect(screen.getByRole('button')).toBeInTheDocument();
|
|
114
|
-
|
|
115
|
-
// Check for preset color buttons
|
|
116
|
-
const colorButtons = screen.getAllByRole('button');
|
|
117
|
-
expect(colorButtons.length).toBeGreaterThan(1);
|
|
118
|
-
});
|
|
66
|
+
it('Input sekmesinde hex girişi bulunur', () => {
|
|
67
|
+
renderOpen({ value: '#ff0000' });
|
|
119
68
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const selectedButton = screen.getByRole('button', { pressed: true });
|
|
125
|
-
expect(selectedButton).toHaveStyle('background-color: #ff0000');
|
|
126
|
-
});
|
|
69
|
+
activateTab('Input');
|
|
70
|
+
expect(screen.getByPlaceholderText('#000000')).toBeInTheDocument();
|
|
71
|
+
});
|
|
127
72
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const colorButtons = screen.getAllByRole('button');
|
|
133
|
-
fireEvent.click(colorButtons[1]); // Click second color button
|
|
134
|
-
|
|
135
|
-
expect(mockOnChange).toHaveBeenCalled();
|
|
136
|
-
});
|
|
73
|
+
it('hex girişine geçerli değer yazılınca onChange tetiklenir', () => {
|
|
74
|
+
const onChange = jest.fn();
|
|
75
|
+
renderOpen({ value: '#ff0000', onChange });
|
|
137
76
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
expect(screen.getByPlaceholderText('Enter color...')).toBeInTheDocument();
|
|
77
|
+
activateTab('Input');
|
|
78
|
+
fireEvent.change(screen.getByPlaceholderText('#000000'), {
|
|
79
|
+
target: { value: '#00ff00' },
|
|
143
80
|
});
|
|
144
81
|
|
|
145
|
-
|
|
146
|
-
const mockOnChange = jest.fn();
|
|
147
|
-
render(<SimpleColorPicker color="#ffffff" onColorChange={mockOnChange} />);
|
|
148
|
-
|
|
149
|
-
const input = screen.getByPlaceholderText('Enter color...');
|
|
150
|
-
fireEvent.change(input, { target: { value: '#ff0000' } });
|
|
151
|
-
fireEvent.blur(input);
|
|
152
|
-
|
|
153
|
-
expect(mockOnChange).toHaveBeenCalledWith('#ff0000');
|
|
154
|
-
});
|
|
82
|
+
expect(onChange).toHaveBeenCalledWith('#00ff00');
|
|
155
83
|
});
|
|
156
84
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
render(<GradientPicker gradient="linear-gradient(to right, #ff0000, #0000ff)" onGradientChange={mockOnChange} />);
|
|
161
|
-
|
|
162
|
-
expect(screen.getByRole('button')).toBeInTheDocument();
|
|
163
|
-
expect(screen.getByText('linear-gradient(to right, #ff0000, #0000ff)')).toBeInTheDocument();
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
it('opens gradient picker when button is clicked', async () => {
|
|
167
|
-
const mockOnChange = jest.fn();
|
|
168
|
-
render(<GradientPicker gradient="linear-gradient(to right, #ff0000, #0000ff)" onGradientChange={mockOnChange} />);
|
|
169
|
-
|
|
170
|
-
const button = screen.getByRole('button');
|
|
171
|
-
fireEvent.click(button);
|
|
172
|
-
|
|
173
|
-
await waitFor(() => {
|
|
174
|
-
expect(screen.getByRole('dialog')).toBeInTheDocument();
|
|
175
|
-
});
|
|
176
|
-
});
|
|
85
|
+
it('preset swatch tıklanınca o renkle onChange tetiklenir', () => {
|
|
86
|
+
const onChange = jest.fn();
|
|
87
|
+
renderOpen({ value: '#ffffff', onChange, presets: ['#ef4444', '#22c55e'] });
|
|
177
88
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
const button = screen.getByRole('button');
|
|
183
|
-
fireEvent.click(button);
|
|
184
|
-
|
|
185
|
-
await waitFor(() => {
|
|
186
|
-
expect(screen.getByText('Linear')).toBeInTheDocument();
|
|
187
|
-
expect(screen.getByText('Radial')).toBeInTheDocument();
|
|
188
|
-
});
|
|
189
|
-
});
|
|
89
|
+
fireEvent.click(screen.getByRole('button', { name: 'Select color #22c55e' }));
|
|
90
|
+
expect(onChange).toHaveBeenCalledWith('#22c55e');
|
|
91
|
+
});
|
|
190
92
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
93
|
+
it('preset swatch butonları erişilebilir ad taşır', () => {
|
|
94
|
+
// Regresyon: swatch'ın tek içeriği arka plan rengiydi; aria-label olmadan
|
|
95
|
+
// ekran okuyucu yalnızca "button" diyordu.
|
|
96
|
+
renderOpen({ value: '#ef4444', presets: ['#ef4444', '#22c55e'] });
|
|
97
|
+
|
|
98
|
+
expect(screen.getByRole('button', { name: 'Select color #ef4444' })).toHaveAttribute(
|
|
99
|
+
'aria-pressed',
|
|
100
|
+
'true'
|
|
101
|
+
);
|
|
102
|
+
expect(screen.getByRole('button', { name: 'Select color #22c55e' })).toHaveAttribute(
|
|
103
|
+
'aria-pressed',
|
|
104
|
+
'false'
|
|
105
|
+
);
|
|
106
|
+
});
|
|
202
107
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
fireEvent.click(button);
|
|
209
|
-
|
|
210
|
-
await waitFor(() => {
|
|
211
|
-
const addButton = screen.getByText('Add Stop');
|
|
212
|
-
fireEvent.click(addButton);
|
|
213
|
-
expect(mockOnChange).toHaveBeenCalled();
|
|
214
|
-
});
|
|
215
|
-
});
|
|
108
|
+
it('showPresets=false iken preset bölümü render edilmez', () => {
|
|
109
|
+
renderOpen({ value: '#ffffff', showPresets: false, presets: ['#ef4444'] });
|
|
110
|
+
expect(screen.queryByRole('button', { name: 'Select color #ef4444' })).not.toBeInTheDocument();
|
|
111
|
+
});
|
|
112
|
+
});
|
|
216
113
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
const button = screen.getByRole('button');
|
|
222
|
-
fireEvent.click(button);
|
|
223
|
-
|
|
224
|
-
await waitFor(() => {
|
|
225
|
-
const directionSelect = screen.getByText('to right');
|
|
226
|
-
fireEvent.click(directionSelect);
|
|
227
|
-
|
|
228
|
-
const toBottomOption = screen.getByText('to bottom');
|
|
229
|
-
fireEvent.click(toBottomOption);
|
|
230
|
-
|
|
231
|
-
expect(mockOnChange).toHaveBeenCalled();
|
|
232
|
-
});
|
|
233
|
-
});
|
|
114
|
+
describe('SimpleColorPicker', () => {
|
|
115
|
+
it('verilen renkler için birer swatch render eder', () => {
|
|
116
|
+
render(<SimpleColorPicker value="#ffffff" colors={['#ef4444', '#22c55e', '#3b82f6']} />);
|
|
117
|
+
expect(screen.getAllByRole('button')).toHaveLength(3);
|
|
234
118
|
});
|
|
235
119
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
const button = screen.getByRole('button');
|
|
242
|
-
fireEvent.keyDown(button, { key: 'Enter' });
|
|
243
|
-
|
|
244
|
-
await waitFor(() => {
|
|
245
|
-
expect(screen.getByRole('dialog')).toBeInTheDocument();
|
|
246
|
-
});
|
|
247
|
-
});
|
|
120
|
+
it('swatch tıklanınca o renkle onChange tetiklenir', () => {
|
|
121
|
+
const onChange = jest.fn();
|
|
122
|
+
render(
|
|
123
|
+
<SimpleColorPicker value="#ffffff" onChange={onChange} colors={['#ef4444', '#22c55e']} />
|
|
124
|
+
);
|
|
248
125
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
const button = screen.getByRole('button');
|
|
254
|
-
fireEvent.click(button);
|
|
255
|
-
|
|
256
|
-
await waitFor(() => {
|
|
257
|
-
expect(screen.getByRole('dialog')).toBeInTheDocument();
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
fireEvent.click(document.body);
|
|
261
|
-
|
|
262
|
-
await waitFor(() => {
|
|
263
|
-
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
|
|
264
|
-
});
|
|
265
|
-
});
|
|
126
|
+
fireEvent.click(screen.getByRole('button', { name: 'Select color #22c55e' }));
|
|
127
|
+
expect(onChange).toHaveBeenCalledWith('#22c55e');
|
|
128
|
+
});
|
|
266
129
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
await waitFor(() => {
|
|
281
|
-
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
|
|
282
|
-
});
|
|
283
|
-
});
|
|
130
|
+
it('seçili swatch aria-pressed ile işaretlenir', () => {
|
|
131
|
+
render(<SimpleColorPicker value="#ef4444" colors={['#ef4444', '#22c55e']} />);
|
|
132
|
+
|
|
133
|
+
expect(screen.getByRole('button', { name: 'Select color #ef4444' })).toHaveAttribute(
|
|
134
|
+
'aria-pressed',
|
|
135
|
+
'true'
|
|
136
|
+
);
|
|
137
|
+
expect(screen.getByRole('button', { name: 'Select color #22c55e' })).toHaveAttribute(
|
|
138
|
+
'aria-pressed',
|
|
139
|
+
'false'
|
|
140
|
+
);
|
|
141
|
+
});
|
|
284
142
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
expect(button).toHaveClass('custom-class');
|
|
291
|
-
});
|
|
143
|
+
it('onChange verilmese de tıklama hata vermez', () => {
|
|
144
|
+
render(<SimpleColorPicker value="#ffffff" colors={['#ef4444']} />);
|
|
145
|
+
expect(() =>
|
|
146
|
+
fireEvent.click(screen.getByRole('button', { name: 'Select color #ef4444' }))
|
|
147
|
+
).not.toThrow();
|
|
292
148
|
});
|
|
149
|
+
});
|
|
293
150
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
const mockOnChange = jest.fn();
|
|
297
|
-
render(<ColorPicker color="#ffffff" onColorChange={mockOnChange} />);
|
|
298
|
-
|
|
299
|
-
const button = screen.getByRole('button');
|
|
300
|
-
expect(button).toHaveAttribute('aria-haspopup', 'dialog');
|
|
301
|
-
expect(button).toHaveAttribute('aria-expanded', 'false');
|
|
302
|
-
});
|
|
151
|
+
describe('GradientPicker', () => {
|
|
152
|
+
const gradient = { start: '#ff0000', end: '#0000ff', angle: 90 };
|
|
303
153
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
render(<ColorPicker color="#ffffff" onColorChange={mockOnChange} />);
|
|
307
|
-
|
|
308
|
-
const button = screen.getByRole('button');
|
|
309
|
-
fireEvent.click(button);
|
|
310
|
-
|
|
311
|
-
await waitFor(() => {
|
|
312
|
-
expect(button).toHaveAttribute('aria-expanded', 'true');
|
|
313
|
-
});
|
|
314
|
-
});
|
|
154
|
+
it('başlangıç/bitiş rengi ve açı alanlarını render eder', () => {
|
|
155
|
+
render(<GradientPicker value={gradient} />);
|
|
315
156
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
const button = screen.getByRole('button');
|
|
321
|
-
expect(button).toHaveAttribute('aria-label', 'Open color picker');
|
|
322
|
-
});
|
|
157
|
+
expect(screen.getByText('Start Color')).toBeInTheDocument();
|
|
158
|
+
expect(screen.getByText('End Color')).toBeInTheDocument();
|
|
159
|
+
expect(screen.getByText('Angle')).toBeInTheDocument();
|
|
160
|
+
});
|
|
323
161
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
const button = screen.getByRole('button');
|
|
329
|
-
expect(button).toHaveAttribute('aria-describedby');
|
|
330
|
-
expect(screen.getByText('#ff0000')).toBeInTheDocument();
|
|
331
|
-
});
|
|
162
|
+
it('başlangıç ve bitiş için birer ColorPicker tetikleyicisi sunar', () => {
|
|
163
|
+
render(<GradientPicker value={gradient} />);
|
|
164
|
+
expect(screen.getAllByRole('button', { name: 'Pick a color' })).toHaveLength(2);
|
|
332
165
|
});
|
|
333
166
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
render(
|
|
339
|
-
<form>
|
|
340
|
-
<ColorPicker color="#ffffff" onColorChange={mockOnChange} required />
|
|
341
|
-
</form>
|
|
342
|
-
);
|
|
343
|
-
|
|
344
|
-
const button = screen.getByRole('button');
|
|
345
|
-
expect(button).toBeValid();
|
|
346
|
-
});
|
|
167
|
+
it('başlangıç rengi değişince onChange tüm gradient nesnesiyle çağrılır', () => {
|
|
168
|
+
const onChange = jest.fn();
|
|
169
|
+
render(<GradientPicker value={gradient} onChange={onChange} />);
|
|
347
170
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
const resetButton = screen.getByText('Reset');
|
|
359
|
-
fireEvent.click(resetButton);
|
|
360
|
-
|
|
361
|
-
// Form reset should trigger appropriate behavior
|
|
362
|
-
expect(screen.getAllByRole('button')).toHaveLength(2);
|
|
363
|
-
});
|
|
171
|
+
// İlk tetikleyici "Start Color"; panelden bir preset seçilir.
|
|
172
|
+
fireEvent.click(screen.getAllByRole('button', { name: 'Pick a color' })[0]);
|
|
173
|
+
const swatch = screen.getAllByRole('button', { name: /^Select color / })[0];
|
|
174
|
+
const picked = swatch.getAttribute('aria-label')!.replace('Select color ', '');
|
|
175
|
+
fireEvent.click(swatch);
|
|
176
|
+
|
|
177
|
+
expect(onChange).toHaveBeenCalledWith(
|
|
178
|
+
expect.objectContaining({ start: picked, end: gradient.end, angle: gradient.angle })
|
|
179
|
+
);
|
|
364
180
|
});
|
|
365
|
-
});
|
|
181
|
+
});
|
|
@@ -552,4 +552,64 @@ describe('RadioGroup Components', () => {
|
|
|
552
552
|
expect(option2).toBeDisabled()
|
|
553
553
|
})
|
|
554
554
|
})
|
|
555
|
+
|
|
556
|
+
describe('Uncontrolled mod ve klavye focus izi', () => {
|
|
557
|
+
it('defaultValue ile uncontrolled çalışır', () => {
|
|
558
|
+
render(
|
|
559
|
+
<RadioGroup defaultValue="option2">
|
|
560
|
+
<RadioGroupItem value="option1" data-testid="r1" />
|
|
561
|
+
<RadioGroupItem value="option2" data-testid="r2" />
|
|
562
|
+
</RadioGroup>
|
|
563
|
+
)
|
|
564
|
+
|
|
565
|
+
expect(screen.getByTestId('r2')).toBeChecked()
|
|
566
|
+
expect(screen.getByTestId('r1')).not.toBeChecked()
|
|
567
|
+
|
|
568
|
+
// Tüketici onValueChange vermeden de seçim değişebilmeli.
|
|
569
|
+
fireEvent.click(screen.getByTestId('r1'))
|
|
570
|
+
expect(screen.getByTestId('r1')).toBeChecked()
|
|
571
|
+
expect(screen.getByTestId('r2')).not.toBeChecked()
|
|
572
|
+
})
|
|
573
|
+
|
|
574
|
+
it('controlled mod defaultValue tarafından ezilmez', () => {
|
|
575
|
+
render(
|
|
576
|
+
<RadioGroup value="option1" defaultValue="option2">
|
|
577
|
+
<RadioGroupItem value="option1" data-testid="r1" />
|
|
578
|
+
<RadioGroupItem value="option2" data-testid="r2" />
|
|
579
|
+
</RadioGroup>
|
|
580
|
+
)
|
|
581
|
+
|
|
582
|
+
expect(screen.getByTestId('r1')).toBeChecked()
|
|
583
|
+
expect(screen.getByTestId('r2')).not.toBeChecked()
|
|
584
|
+
})
|
|
585
|
+
|
|
586
|
+
it('uncontrolled modda onValueChange yine de çağrılır', () => {
|
|
587
|
+
const onValueChange = jest.fn()
|
|
588
|
+
render(
|
|
589
|
+
<RadioGroup defaultValue="option1" onValueChange={onValueChange}>
|
|
590
|
+
<RadioGroupItem value="option1" data-testid="r1" />
|
|
591
|
+
<RadioGroupItem value="option2" data-testid="r2" />
|
|
592
|
+
</RadioGroup>
|
|
593
|
+
)
|
|
594
|
+
|
|
595
|
+
fireEvent.click(screen.getByTestId('r2'))
|
|
596
|
+
expect(onValueChange).toHaveBeenCalledWith('option2')
|
|
597
|
+
})
|
|
598
|
+
|
|
599
|
+
it('gizli input peer sınıfını taşır — focus izi görünür label\'a taşınabilsin', () => {
|
|
600
|
+
render(
|
|
601
|
+
<RadioGroup>
|
|
602
|
+
<RadioGroupItem value="option1" data-testid="r1" />
|
|
603
|
+
</RadioGroup>
|
|
604
|
+
)
|
|
605
|
+
|
|
606
|
+
// Gerçekte odaklanan eleman sr-only input; `peer` olmadan görünür label
|
|
607
|
+
// hiçbir focus izi gösteremez (klavye kullanıcısı nerede olduğunu göremez).
|
|
608
|
+
const input = screen.getByTestId('r1')
|
|
609
|
+
expect(input).toHaveClass('peer', 'sr-only')
|
|
610
|
+
|
|
611
|
+
const label = input.parentElement?.querySelector('label')
|
|
612
|
+
expect(label?.className).toContain('peer-focus-visible:ring-2')
|
|
613
|
+
})
|
|
614
|
+
})
|
|
555
615
|
})
|