@aiready/components 0.13.22 → 0.14.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.
@@ -0,0 +1,100 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { render, screen, fireEvent } from '@testing-library/react';
3
+ import { Select } from '../select';
4
+
5
+ describe('Select', () => {
6
+ const options = [
7
+ { value: 'option1', label: 'Option 1' },
8
+ { value: 'option2', label: 'Option 2' },
9
+ { value: 'option3', label: 'Option 3' },
10
+ ];
11
+
12
+ const defaultProps = {
13
+ options,
14
+ onChange: vi.fn(),
15
+ };
16
+
17
+ beforeEach(() => {
18
+ vi.clearAllMocks();
19
+ });
20
+
21
+ it('should render a select element', () => {
22
+ render(<Select {...defaultProps} />);
23
+ expect(screen.getByRole('combobox')).toBeInTheDocument();
24
+ });
25
+
26
+ it('should render all options', () => {
27
+ render(<Select {...defaultProps} />);
28
+ expect(screen.getByText('Option 1')).toBeInTheDocument();
29
+ expect(screen.getByText('Option 2')).toBeInTheDocument();
30
+ expect(screen.getByText('Option 3')).toBeInTheDocument();
31
+ });
32
+
33
+ it('should apply custom className', () => {
34
+ const { container } = render(
35
+ <Select {...defaultProps} className="custom-class" />
36
+ );
37
+ expect(container.firstChild).toHaveClass('custom-class');
38
+ });
39
+
40
+ it('should render placeholder when provided', () => {
41
+ render(<Select {...defaultProps} placeholder="Select an option" />);
42
+ expect(screen.getByText('Select an option')).toBeInTheDocument();
43
+ });
44
+
45
+ it('should call onChange when option is selected', () => {
46
+ render(<Select {...defaultProps} />);
47
+ fireEvent.change(screen.getByRole('combobox'), {
48
+ target: { value: 'option2' },
49
+ });
50
+ expect(defaultProps.onChange).toHaveBeenCalledWith('option2');
51
+ });
52
+
53
+ it('should disable specific options', () => {
54
+ const optionsWithDisabled = [
55
+ { value: 'option1', label: 'Option 1' },
56
+ { value: 'option2', label: 'Option 2', disabled: true },
57
+ ];
58
+ render(<Select {...defaultProps} options={optionsWithDisabled} />);
59
+ expect(screen.getByText('Option 2')).toBeDisabled();
60
+ });
61
+
62
+ it('should be disabled when disabled prop is set', () => {
63
+ render(<Select {...defaultProps} disabled />);
64
+ expect(screen.getByRole('combobox')).toBeDisabled();
65
+ });
66
+
67
+ it('should forward ref', () => {
68
+ const ref = { current: null };
69
+ render(<Select {...defaultProps} ref={ref} />);
70
+ expect(ref.current).not.toBeNull();
71
+ });
72
+
73
+ it('should spread additional props', () => {
74
+ const { container } = render(
75
+ <Select {...defaultProps} data-testid="select" />
76
+ );
77
+ expect(container.firstChild).toHaveAttribute('data-testid', 'select');
78
+ });
79
+
80
+ it('should have default styling classes', () => {
81
+ const { container } = render(<Select {...defaultProps} />);
82
+ expect(container.firstChild).toHaveClass(
83
+ 'flex',
84
+ 'h-10',
85
+ 'w-full',
86
+ 'rounded-md'
87
+ );
88
+ });
89
+
90
+ it('should handle value prop', () => {
91
+ render(<Select {...defaultProps} value="option2" />);
92
+ expect(screen.getByRole('combobox')).toHaveValue('option2');
93
+ });
94
+
95
+ it('should disable placeholder option', () => {
96
+ render(<Select {...defaultProps} placeholder="Select an option" />);
97
+ const placeholderOption = screen.getByText('Select an option');
98
+ expect(placeholderOption).toBeDisabled();
99
+ });
100
+ });
@@ -0,0 +1,72 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { render } from '@testing-library/react';
3
+ import { Separator } from '../separator';
4
+
5
+ describe('Separator', () => {
6
+ it('should render a separator', () => {
7
+ const { container } = render(<Separator />);
8
+ expect(container.firstChild).toBeInTheDocument();
9
+ });
10
+
11
+ it('should apply custom className', () => {
12
+ const { container } = render(<Separator className="custom-class" />);
13
+ expect(container.firstChild).toHaveClass('custom-class');
14
+ });
15
+
16
+ it('should render with horizontal orientation by default', () => {
17
+ const { container } = render(<Separator />);
18
+ expect(container.firstChild).toHaveClass('h-[1px]', 'w-full');
19
+ });
20
+
21
+ it('should render with vertical orientation', () => {
22
+ const { container } = render(<Separator orientation="vertical" />);
23
+ expect(container.firstChild).toHaveClass('h-full', 'w-[1px]');
24
+ });
25
+
26
+ it('should have role="none" when decorative is true', () => {
27
+ const { container } = render(<Separator decorative />);
28
+ expect(container.firstChild).toHaveAttribute('role', 'none');
29
+ });
30
+
31
+ it('should have role="separator" when decorative is false', () => {
32
+ const { container } = render(<Separator decorative={false} />);
33
+ expect(container.firstChild).toHaveAttribute('role', 'separator');
34
+ });
35
+
36
+ it('should have aria-orientation attribute', () => {
37
+ const { container } = render(<Separator orientation="horizontal" />);
38
+ expect(container.firstChild).toHaveAttribute(
39
+ 'aria-orientation',
40
+ 'horizontal'
41
+ );
42
+ });
43
+
44
+ it('should have aria-orientation vertical for vertical separator', () => {
45
+ const { container } = render(<Separator orientation="vertical" />);
46
+ expect(container.firstChild).toHaveAttribute(
47
+ 'aria-orientation',
48
+ 'vertical'
49
+ );
50
+ });
51
+
52
+ it('should have shrink-0 class', () => {
53
+ const { container } = render(<Separator />);
54
+ expect(container.firstChild).toHaveClass('shrink-0');
55
+ });
56
+
57
+ it('should have bg-border class', () => {
58
+ const { container } = render(<Separator />);
59
+ expect(container.firstChild).toHaveClass('bg-border');
60
+ });
61
+
62
+ it('should forward ref', () => {
63
+ const ref = { current: null };
64
+ render(<Separator ref={ref} />);
65
+ expect(ref.current).not.toBeNull();
66
+ });
67
+
68
+ it('should spread additional props', () => {
69
+ const { container } = render(<Separator data-testid="separator" />);
70
+ expect(container.firstChild).toHaveAttribute('data-testid', 'separator');
71
+ });
72
+ });
@@ -0,0 +1,197 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { Stack } from '../stack';
4
+
5
+ describe('Stack', () => {
6
+ it('should render children content', () => {
7
+ render(
8
+ <Stack>
9
+ <div>Item 1</div>
10
+ <div>Item 2</div>
11
+ </Stack>
12
+ );
13
+ expect(screen.getByText('Item 1')).toBeInTheDocument();
14
+ expect(screen.getByText('Item 2')).toBeInTheDocument();
15
+ });
16
+
17
+ it('should apply custom className', () => {
18
+ const { container } = render(
19
+ <Stack className="custom-class">
20
+ <div>Content</div>
21
+ </Stack>
22
+ );
23
+ expect(container.firstChild).toHaveClass('custom-class');
24
+ });
25
+
26
+ it('should render with vertical direction by default', () => {
27
+ const { container } = render(
28
+ <Stack>
29
+ <div>Content</div>
30
+ </Stack>
31
+ );
32
+ expect(container.firstChild).toHaveClass('flex-col');
33
+ });
34
+
35
+ it('should render with horizontal direction', () => {
36
+ const { container } = render(
37
+ <Stack direction="horizontal">
38
+ <div>Content</div>
39
+ </Stack>
40
+ );
41
+ expect(container.firstChild).toHaveClass('flex-row');
42
+ });
43
+
44
+ it('should render with default md spacing', () => {
45
+ const { container } = render(
46
+ <Stack>
47
+ <div>Content</div>
48
+ </Stack>
49
+ );
50
+ expect(container.firstChild).toHaveClass('gap-4');
51
+ });
52
+
53
+ it('should render with xs spacing', () => {
54
+ const { container } = render(
55
+ <Stack spacing="xs">
56
+ <div>Content</div>
57
+ </Stack>
58
+ );
59
+ expect(container.firstChild).toHaveClass('gap-1');
60
+ });
61
+
62
+ it('should render with sm spacing', () => {
63
+ const { container } = render(
64
+ <Stack spacing="sm">
65
+ <div>Content</div>
66
+ </Stack>
67
+ );
68
+ expect(container.firstChild).toHaveClass('gap-2');
69
+ });
70
+
71
+ it('should render with lg spacing', () => {
72
+ const { container } = render(
73
+ <Stack spacing="lg">
74
+ <div>Content</div>
75
+ </Stack>
76
+ );
77
+ expect(container.firstChild).toHaveClass('gap-6');
78
+ });
79
+
80
+ it('should render with xl spacing', () => {
81
+ const { container } = render(
82
+ <Stack spacing="xl">
83
+ <div>Content</div>
84
+ </Stack>
85
+ );
86
+ expect(container.firstChild).toHaveClass('gap-8');
87
+ });
88
+
89
+ it('should render with default stretch alignment', () => {
90
+ const { container } = render(
91
+ <Stack>
92
+ <div>Content</div>
93
+ </Stack>
94
+ );
95
+ expect(container.firstChild).toHaveClass('items-stretch');
96
+ });
97
+
98
+ it('should render with start alignment', () => {
99
+ const { container } = render(
100
+ <Stack align="start">
101
+ <div>Content</div>
102
+ </Stack>
103
+ );
104
+ expect(container.firstChild).toHaveClass('items-start');
105
+ });
106
+
107
+ it('should render with center alignment', () => {
108
+ const { container } = render(
109
+ <Stack align="center">
110
+ <div>Content</div>
111
+ </Stack>
112
+ );
113
+ expect(container.firstChild).toHaveClass('items-center');
114
+ });
115
+
116
+ it('should render with end alignment', () => {
117
+ const { container } = render(
118
+ <Stack align="end">
119
+ <div>Content</div>
120
+ </Stack>
121
+ );
122
+ expect(container.firstChild).toHaveClass('items-end');
123
+ });
124
+
125
+ it('should render with default start justify', () => {
126
+ const { container } = render(
127
+ <Stack>
128
+ <div>Content</div>
129
+ </Stack>
130
+ );
131
+ expect(container.firstChild).toHaveClass('justify-start');
132
+ });
133
+
134
+ it('should render with center justify', () => {
135
+ const { container } = render(
136
+ <Stack justify="center">
137
+ <div>Content</div>
138
+ </Stack>
139
+ );
140
+ expect(container.firstChild).toHaveClass('justify-center');
141
+ });
142
+
143
+ it('should render with end justify', () => {
144
+ const { container } = render(
145
+ <Stack justify="end">
146
+ <div>Content</div>
147
+ </Stack>
148
+ );
149
+ expect(container.firstChild).toHaveClass('justify-end');
150
+ });
151
+
152
+ it('should render with between justify', () => {
153
+ const { container } = render(
154
+ <Stack justify="between">
155
+ <div>Content</div>
156
+ </Stack>
157
+ );
158
+ expect(container.firstChild).toHaveClass('justify-between');
159
+ });
160
+
161
+ it('should render with around justify', () => {
162
+ const { container } = render(
163
+ <Stack justify="around">
164
+ <div>Content</div>
165
+ </Stack>
166
+ );
167
+ expect(container.firstChild).toHaveClass('justify-around');
168
+ });
169
+
170
+ it('should have flex class', () => {
171
+ const { container } = render(
172
+ <Stack>
173
+ <div>Content</div>
174
+ </Stack>
175
+ );
176
+ expect(container.firstChild).toHaveClass('flex');
177
+ });
178
+
179
+ it('should forward ref', () => {
180
+ const ref = { current: null };
181
+ render(
182
+ <Stack ref={ref}>
183
+ <div>Content</div>
184
+ </Stack>
185
+ );
186
+ expect(ref.current).not.toBeNull();
187
+ });
188
+
189
+ it('should spread additional props', () => {
190
+ const { container } = render(
191
+ <Stack data-testid="stack">
192
+ <div>Content</div>
193
+ </Stack>
194
+ );
195
+ expect(container.firstChild).toHaveAttribute('data-testid', 'stack');
196
+ });
197
+ });
@@ -0,0 +1,85 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { render, screen, fireEvent } from '@testing-library/react';
3
+ import { Switch } from '../switch';
4
+
5
+ describe('Switch', () => {
6
+ it('should render a switch', () => {
7
+ render(<Switch />);
8
+ expect(screen.getByRole('checkbox')).toBeInTheDocument();
9
+ });
10
+
11
+ it('should render with a label', () => {
12
+ render(<Switch label="Toggle me" />);
13
+ expect(screen.getByText('Toggle me')).toBeInTheDocument();
14
+ });
15
+
16
+ it('should not render label when not provided', () => {
17
+ const { container } = render(<Switch />);
18
+ expect(container.querySelector('span')).not.toBeInTheDocument();
19
+ });
20
+
21
+ it('should apply custom className', () => {
22
+ const { container } = render(<Switch className="custom-class" />);
23
+ expect(container.querySelector('.custom-class')).toBeInTheDocument();
24
+ });
25
+
26
+ it('should handle checked state', () => {
27
+ render(<Switch checked readOnly />);
28
+ expect(screen.getByRole('checkbox')).toBeChecked();
29
+ });
30
+
31
+ it('should handle unchecked state', () => {
32
+ render(<Switch checked={false} readOnly />);
33
+ expect(screen.getByRole('checkbox')).not.toBeChecked();
34
+ });
35
+
36
+ it('should call onChange when clicked', () => {
37
+ const handleChange = vi.fn();
38
+ render(<Switch onChange={handleChange} />);
39
+ fireEvent.click(screen.getByRole('checkbox'));
40
+ expect(handleChange).toHaveBeenCalledTimes(1);
41
+ });
42
+
43
+ it('should call onCheckedChange when clicked', () => {
44
+ const handleCheckedChange = vi.fn();
45
+ render(<Switch onCheckedChange={handleCheckedChange} />);
46
+ fireEvent.click(screen.getByRole('checkbox'));
47
+ expect(handleCheckedChange).toHaveBeenCalledTimes(1);
48
+ expect(handleCheckedChange).toHaveBeenCalledWith(true);
49
+ });
50
+
51
+ it('should call onCheckedChange with false when unchecking', () => {
52
+ const handleCheckedChange = vi.fn();
53
+ render(<Switch checked onCheckedChange={handleCheckedChange} />);
54
+ fireEvent.click(screen.getByRole('checkbox'));
55
+ expect(handleCheckedChange).toHaveBeenCalledWith(false);
56
+ });
57
+
58
+ it('should be disabled when disabled prop is set', () => {
59
+ render(<Switch disabled />);
60
+ expect(screen.getByRole('checkbox')).toBeDisabled();
61
+ });
62
+
63
+ it('should forward ref', () => {
64
+ const ref = { current: null };
65
+ render(<Switch ref={ref} />);
66
+ expect(ref.current).not.toBeNull();
67
+ });
68
+
69
+ it('should use provided id', () => {
70
+ render(<Switch id="custom-id" label="Test" />);
71
+ const checkbox = screen.getByRole('checkbox');
72
+ expect(checkbox).toHaveAttribute('id', 'custom-id');
73
+ });
74
+
75
+ it('should generate unique id when not provided', () => {
76
+ render(<Switch label="Test" />);
77
+ const checkbox = screen.getByRole('checkbox');
78
+ expect(checkbox).toHaveAttribute('id');
79
+ });
80
+
81
+ it('should have sr-only class on input', () => {
82
+ render(<Switch />);
83
+ expect(screen.getByRole('checkbox')).toHaveClass('sr-only');
84
+ });
85
+ });
@@ -0,0 +1,96 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { render, screen, fireEvent } from '@testing-library/react';
3
+ import { Textarea } from '../textarea';
4
+
5
+ describe('Textarea', () => {
6
+ it('should render a textarea element', () => {
7
+ render(<Textarea />);
8
+ expect(screen.getByRole('textbox')).toBeInTheDocument();
9
+ });
10
+
11
+ it('should apply custom className', () => {
12
+ const { container } = render(<Textarea className="custom-class" />);
13
+ expect(container.firstChild).toHaveClass('custom-class');
14
+ });
15
+
16
+ it('should handle placeholder text', () => {
17
+ render(<Textarea placeholder="Enter text" />);
18
+ expect(screen.getByPlaceholderText('Enter text')).toBeInTheDocument();
19
+ });
20
+
21
+ it('should forward ref', () => {
22
+ const ref = { current: null };
23
+ render(<Textarea ref={ref} />);
24
+ expect(ref.current).not.toBeNull();
25
+ });
26
+
27
+ it('should be disabled when disabled prop is set', () => {
28
+ render(<Textarea disabled />);
29
+ expect(screen.getByRole('textbox')).toBeDisabled();
30
+ });
31
+
32
+ it('should handle value prop', () => {
33
+ render(<Textarea value="test value" readOnly />);
34
+ expect(screen.getByRole('textbox')).toHaveValue('test value');
35
+ });
36
+
37
+ it('should spread additional props', () => {
38
+ const { container } = render(<Textarea data-testid="textarea" />);
39
+ expect(container.firstChild).toHaveAttribute('data-testid', 'textarea');
40
+ });
41
+
42
+ it('should call onChange when text is entered', () => {
43
+ const handleChange = vi.fn();
44
+ render(<Textarea onChange={handleChange} />);
45
+ fireEvent.change(screen.getByRole('textbox'), {
46
+ target: { value: 'new text' },
47
+ });
48
+ expect(handleChange).toHaveBeenCalledTimes(1);
49
+ });
50
+
51
+ it('should have default styling classes', () => {
52
+ const { container } = render(<Textarea />);
53
+ expect(container.firstChild).toHaveClass(
54
+ 'flex',
55
+ 'min-h-[80px]',
56
+ 'w-full',
57
+ 'rounded-md'
58
+ );
59
+ });
60
+
61
+ it('should render as a textarea element', () => {
62
+ render(<Textarea />);
63
+ expect(screen.getByRole('textbox').tagName).toBe('TEXTAREA');
64
+ });
65
+
66
+ it('should support rows attribute', () => {
67
+ render(<Textarea rows={5} />);
68
+ expect(screen.getByRole('textbox')).toHaveAttribute('rows', '5');
69
+ });
70
+
71
+ it('should support maxLength attribute', () => {
72
+ render(<Textarea maxLength={100} />);
73
+ expect(screen.getByRole('textbox')).toHaveAttribute('maxlength', '100');
74
+ });
75
+
76
+ it('should have border-input class', () => {
77
+ const { container } = render(<Textarea />);
78
+ expect(container.firstChild).toHaveClass('border-input');
79
+ });
80
+
81
+ it('should have focus ring classes', () => {
82
+ const { container } = render(<Textarea />);
83
+ expect(container.firstChild).toHaveClass(
84
+ 'focus-visible:ring-2',
85
+ 'focus-visible:ring-ring'
86
+ );
87
+ });
88
+
89
+ it('should have disabled styling classes', () => {
90
+ const { container } = render(<Textarea disabled />);
91
+ expect(container.firstChild).toHaveClass(
92
+ 'disabled:cursor-not-allowed',
93
+ 'disabled:opacity-50'
94
+ );
95
+ });
96
+ });