@constela/ui 0.2.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/LICENSE +21 -0
- package/README.md +160 -0
- package/components/alert/alert.constela.json +22 -0
- package/components/alert/alert.styles.json +14 -0
- package/components/alert/alert.test.ts +173 -0
- package/components/avatar/avatar.constela.json +32 -0
- package/components/avatar/avatar.styles.json +15 -0
- package/components/avatar/avatar.test.ts +197 -0
- package/components/badge/badge.constela.json +19 -0
- package/components/badge/badge.styles.json +16 -0
- package/components/badge/badge.test.ts +135 -0
- package/components/breadcrumb/breadcrumb.constela.json +17 -0
- package/components/breadcrumb/breadcrumb.styles.json +5 -0
- package/components/breadcrumb/breadcrumb.test.ts +149 -0
- package/components/button/README.md +164 -0
- package/components/button/button.constela.json +27 -0
- package/components/button/button.styles.json +25 -0
- package/components/button/button.test.ts +233 -0
- package/components/card/card.constela.json +21 -0
- package/components/card/card.styles.json +14 -0
- package/components/card/card.test.ts +154 -0
- package/components/checkbox/checkbox.constela.json +33 -0
- package/components/checkbox/checkbox.styles.json +15 -0
- package/components/checkbox/checkbox.test.ts +275 -0
- package/components/container/container.constela.json +21 -0
- package/components/container/container.styles.json +18 -0
- package/components/container/container.test.ts +164 -0
- package/components/dialog/dialog.constela.json +19 -0
- package/components/dialog/dialog.styles.json +5 -0
- package/components/dialog/dialog.test.ts +139 -0
- package/components/grid/grid.constela.json +23 -0
- package/components/grid/grid.styles.json +25 -0
- package/components/grid/grid.test.ts +193 -0
- package/components/input/input.constela.json +34 -0
- package/components/input/input.styles.json +19 -0
- package/components/input/input.test.ts +301 -0
- package/components/pagination/pagination.constela.json +22 -0
- package/components/pagination/pagination.styles.json +15 -0
- package/components/pagination/pagination.test.ts +170 -0
- package/components/popover/popover.constela.json +20 -0
- package/components/popover/popover.styles.json +16 -0
- package/components/popover/popover.test.ts +165 -0
- package/components/radio/radio.constela.json +31 -0
- package/components/radio/radio.styles.json +15 -0
- package/components/radio/radio.test.ts +253 -0
- package/components/select/select.constela.json +32 -0
- package/components/select/select.styles.json +15 -0
- package/components/select/select.test.ts +257 -0
- package/components/skeleton/skeleton.constela.json +24 -0
- package/components/skeleton/skeleton.styles.json +5 -0
- package/components/skeleton/skeleton.test.ts +164 -0
- package/components/stack/stack.constela.json +27 -0
- package/components/stack/stack.styles.json +33 -0
- package/components/stack/stack.test.ts +261 -0
- package/components/switch/switch.constela.json +29 -0
- package/components/switch/switch.styles.json +15 -0
- package/components/switch/switch.test.ts +224 -0
- package/components/tabs/tabs.constela.json +21 -0
- package/components/tabs/tabs.styles.json +14 -0
- package/components/tabs/tabs.test.ts +163 -0
- package/components/textarea/textarea.constela.json +34 -0
- package/components/textarea/textarea.styles.json +15 -0
- package/components/textarea/textarea.test.ts +290 -0
- package/components/toast/toast.constela.json +23 -0
- package/components/toast/toast.styles.json +17 -0
- package/components/toast/toast.test.ts +183 -0
- package/components/tooltip/tooltip.constela.json +21 -0
- package/components/tooltip/tooltip.styles.json +16 -0
- package/components/tooltip/tooltip.test.ts +164 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.js +83 -0
- package/package.json +39 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test suite for Tabs component
|
|
3
|
+
*
|
|
4
|
+
* @constela/ui Tabs component tests following TDD methodology.
|
|
5
|
+
* These tests verify the Tabs component structure, params, styles, and accessibility.
|
|
6
|
+
*
|
|
7
|
+
* Coverage:
|
|
8
|
+
* - Component structure validation
|
|
9
|
+
* - Params definition validation
|
|
10
|
+
* - Style preset validation
|
|
11
|
+
* - Accessibility attributes (role="tablist")
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { describe, it, expect, beforeAll } from 'vitest';
|
|
15
|
+
import {
|
|
16
|
+
loadComponentForTesting,
|
|
17
|
+
assertValidComponent,
|
|
18
|
+
assertValidStylePreset,
|
|
19
|
+
hasParams,
|
|
20
|
+
isOptionalParam,
|
|
21
|
+
hasParamType,
|
|
22
|
+
getRootTag,
|
|
23
|
+
hasVariants,
|
|
24
|
+
hasVariantOptions,
|
|
25
|
+
hasDefaultVariants,
|
|
26
|
+
hasSlot,
|
|
27
|
+
findPropInView,
|
|
28
|
+
hasRole,
|
|
29
|
+
type ComponentTestContext,
|
|
30
|
+
} from '../../tests/helpers/test-utils.js';
|
|
31
|
+
|
|
32
|
+
describe('Tabs Component', () => {
|
|
33
|
+
let ctx: ComponentTestContext;
|
|
34
|
+
|
|
35
|
+
beforeAll(() => {
|
|
36
|
+
ctx = loadComponentForTesting('tabs');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// ==================== Component Structure Tests ====================
|
|
40
|
+
|
|
41
|
+
describe('Component Structure', () => {
|
|
42
|
+
it('should have valid component structure', () => {
|
|
43
|
+
assertValidComponent(ctx.component);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should have div as root element', () => {
|
|
47
|
+
const rootTag = getRootTag(ctx.component);
|
|
48
|
+
expect(rootTag).toBe('div');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should have role="tablist" attribute', () => {
|
|
52
|
+
expect(hasRole(ctx.component.view, 'tablist')).toBe(true);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should contain a slot for tab items', () => {
|
|
56
|
+
expect(hasSlot(ctx.component.view)).toBe(true);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should have className using StyleExpr with tabsStyles preset', () => {
|
|
60
|
+
const className = findPropInView(ctx.component.view, 'className');
|
|
61
|
+
expect(className).not.toBeNull();
|
|
62
|
+
expect(className).toMatchObject({
|
|
63
|
+
expr: 'style',
|
|
64
|
+
preset: 'tabsStyles',
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// ==================== Params Validation Tests ====================
|
|
70
|
+
|
|
71
|
+
describe('Params Validation', () => {
|
|
72
|
+
const expectedParams = ['activeTab', 'variant'];
|
|
73
|
+
|
|
74
|
+
it('should have all expected params', () => {
|
|
75
|
+
expect(hasParams(ctx.component, expectedParams)).toBe(true);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe('param: activeTab', () => {
|
|
79
|
+
it('should be optional', () => {
|
|
80
|
+
expect(isOptionalParam(ctx.component, 'activeTab')).toBe(true);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('should have type string', () => {
|
|
84
|
+
expect(hasParamType(ctx.component, 'activeTab', 'string')).toBe(true);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe('param: variant', () => {
|
|
89
|
+
it('should be optional', () => {
|
|
90
|
+
expect(isOptionalParam(ctx.component, 'variant')).toBe(true);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('should have type string', () => {
|
|
94
|
+
expect(hasParamType(ctx.component, 'variant', 'string')).toBe(true);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// ==================== Style Preset Tests ====================
|
|
100
|
+
|
|
101
|
+
describe('Style Preset', () => {
|
|
102
|
+
it('should have valid style preset structure', () => {
|
|
103
|
+
const tabsStyles = ctx.styles['tabsStyles'];
|
|
104
|
+
expect(tabsStyles).toBeDefined();
|
|
105
|
+
assertValidStylePreset(tabsStyles);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('should have base classes for common tabs styles', () => {
|
|
109
|
+
const tabsStyles = ctx.styles['tabsStyles'];
|
|
110
|
+
expect(tabsStyles.base).toBeDefined();
|
|
111
|
+
expect(typeof tabsStyles.base).toBe('string');
|
|
112
|
+
expect(tabsStyles.base.length).toBeGreaterThan(0);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('variant options', () => {
|
|
116
|
+
const variantOptions = ['default', 'outline'];
|
|
117
|
+
|
|
118
|
+
it('should have variant variants', () => {
|
|
119
|
+
const tabsStyles = ctx.styles['tabsStyles'];
|
|
120
|
+
expect(hasVariants(tabsStyles, ['variant'])).toBe(true);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it.each(variantOptions)('should have %s variant option', (option) => {
|
|
124
|
+
const tabsStyles = ctx.styles['tabsStyles'];
|
|
125
|
+
expect(hasVariantOptions(tabsStyles, 'variant', [option])).toBe(true);
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
describe('default variants', () => {
|
|
130
|
+
it('should have default variant set to default', () => {
|
|
131
|
+
const tabsStyles = ctx.styles['tabsStyles'];
|
|
132
|
+
expect(hasDefaultVariants(tabsStyles, { variant: 'default' })).toBe(true);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// ==================== Accessibility Tests ====================
|
|
138
|
+
|
|
139
|
+
describe('Accessibility', () => {
|
|
140
|
+
it('should have role="tablist" for screen readers', () => {
|
|
141
|
+
const role = findPropInView(ctx.component.view, 'role');
|
|
142
|
+
expect(role).not.toBeNull();
|
|
143
|
+
expect(role).toMatchObject({
|
|
144
|
+
expr: 'lit',
|
|
145
|
+
value: 'tablist',
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// ==================== View Props Tests ====================
|
|
151
|
+
|
|
152
|
+
describe('View Props', () => {
|
|
153
|
+
it('should pass variant to StyleExpr', () => {
|
|
154
|
+
const className = findPropInView(ctx.component.view, 'className');
|
|
155
|
+
expect(className).toMatchObject({
|
|
156
|
+
expr: 'style',
|
|
157
|
+
props: expect.objectContaining({
|
|
158
|
+
variant: expect.objectContaining({ expr: 'param', name: 'variant' }),
|
|
159
|
+
}),
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"params": {
|
|
3
|
+
"value": { "type": "string", "required": false },
|
|
4
|
+
"placeholder": { "type": "string", "required": false },
|
|
5
|
+
"disabled": { "type": "boolean", "required": false },
|
|
6
|
+
"required": { "type": "boolean", "required": false },
|
|
7
|
+
"rows": { "type": "number", "required": false },
|
|
8
|
+
"name": { "type": "string", "required": false },
|
|
9
|
+
"id": { "type": "string", "required": false },
|
|
10
|
+
"ariaLabel": { "type": "string", "required": false },
|
|
11
|
+
"size": { "type": "string", "required": false }
|
|
12
|
+
},
|
|
13
|
+
"view": {
|
|
14
|
+
"kind": "element",
|
|
15
|
+
"tag": "textarea",
|
|
16
|
+
"props": {
|
|
17
|
+
"className": {
|
|
18
|
+
"expr": "style",
|
|
19
|
+
"preset": "textareaStyles",
|
|
20
|
+
"props": {
|
|
21
|
+
"size": { "expr": "param", "name": "size" }
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"value": { "expr": "param", "name": "value" },
|
|
25
|
+
"placeholder": { "expr": "param", "name": "placeholder" },
|
|
26
|
+
"disabled": { "expr": "param", "name": "disabled" },
|
|
27
|
+
"required": { "expr": "param", "name": "required" },
|
|
28
|
+
"rows": { "expr": "param", "name": "rows" },
|
|
29
|
+
"name": { "expr": "param", "name": "name" },
|
|
30
|
+
"id": { "expr": "param", "name": "id" },
|
|
31
|
+
"aria-label": { "expr": "param", "name": "ariaLabel" }
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"textareaStyles": {
|
|
3
|
+
"base": "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
4
|
+
"variants": {
|
|
5
|
+
"size": {
|
|
6
|
+
"default": "",
|
|
7
|
+
"sm": "min-h-[60px] text-xs",
|
|
8
|
+
"lg": "min-h-[120px] text-base"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"defaultVariants": {
|
|
12
|
+
"size": "default"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test suite for Textarea component
|
|
3
|
+
*
|
|
4
|
+
* @constela/ui Textarea component tests following TDD methodology.
|
|
5
|
+
* These tests verify the Textarea component structure, params, styles, and accessibility.
|
|
6
|
+
*
|
|
7
|
+
* Coverage:
|
|
8
|
+
* - Component structure validation
|
|
9
|
+
* - Params definition validation
|
|
10
|
+
* - Style preset validation
|
|
11
|
+
* - Accessibility attributes
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { describe, it, expect, beforeAll } from 'vitest';
|
|
15
|
+
import {
|
|
16
|
+
loadComponentForTesting,
|
|
17
|
+
assertValidComponent,
|
|
18
|
+
assertValidStylePreset,
|
|
19
|
+
hasParams,
|
|
20
|
+
isOptionalParam,
|
|
21
|
+
hasParamType,
|
|
22
|
+
getRootTag,
|
|
23
|
+
hasVariants,
|
|
24
|
+
hasVariantOptions,
|
|
25
|
+
hasDefaultVariants,
|
|
26
|
+
findPropInView,
|
|
27
|
+
type ComponentTestContext,
|
|
28
|
+
} from '../../tests/helpers/test-utils.js';
|
|
29
|
+
|
|
30
|
+
describe('Textarea Component', () => {
|
|
31
|
+
let ctx: ComponentTestContext;
|
|
32
|
+
|
|
33
|
+
beforeAll(() => {
|
|
34
|
+
ctx = loadComponentForTesting('textarea');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// ==================== Component Structure Tests ====================
|
|
38
|
+
|
|
39
|
+
describe('Component Structure', () => {
|
|
40
|
+
it('should have valid component structure', () => {
|
|
41
|
+
assertValidComponent(ctx.component);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should have textarea as root element', () => {
|
|
45
|
+
const rootTag = getRootTag(ctx.component);
|
|
46
|
+
expect(rootTag).toBe('textarea');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should have className using StyleExpr', () => {
|
|
50
|
+
const className = findPropInView(ctx.component.view, 'className');
|
|
51
|
+
expect(className).not.toBeNull();
|
|
52
|
+
// StyleExpr should have expr: 'style' and preset reference
|
|
53
|
+
expect(className).toMatchObject({
|
|
54
|
+
expr: 'style',
|
|
55
|
+
preset: 'textareaStyles',
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should support rows attribute', () => {
|
|
60
|
+
const rows = findPropInView(ctx.component.view, 'rows');
|
|
61
|
+
expect(rows).not.toBeNull();
|
|
62
|
+
// Should reference the rows param
|
|
63
|
+
expect(rows).toMatchObject({
|
|
64
|
+
expr: 'param',
|
|
65
|
+
name: 'rows',
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// ==================== Params Validation Tests ====================
|
|
71
|
+
|
|
72
|
+
describe('Params Validation', () => {
|
|
73
|
+
const expectedParams = [
|
|
74
|
+
'value',
|
|
75
|
+
'placeholder',
|
|
76
|
+
'disabled',
|
|
77
|
+
'required',
|
|
78
|
+
'rows',
|
|
79
|
+
'name',
|
|
80
|
+
'id',
|
|
81
|
+
'ariaLabel',
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
it('should have all expected params', () => {
|
|
85
|
+
expect(hasParams(ctx.component, expectedParams)).toBe(true);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe('param: value', () => {
|
|
89
|
+
it('should be optional', () => {
|
|
90
|
+
expect(isOptionalParam(ctx.component, 'value')).toBe(true);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('should have type string', () => {
|
|
94
|
+
expect(hasParamType(ctx.component, 'value', 'string')).toBe(true);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
describe('param: placeholder', () => {
|
|
99
|
+
it('should be optional', () => {
|
|
100
|
+
expect(isOptionalParam(ctx.component, 'placeholder')).toBe(true);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('should have type string', () => {
|
|
104
|
+
expect(hasParamType(ctx.component, 'placeholder', 'string')).toBe(true);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
describe('param: disabled', () => {
|
|
109
|
+
it('should be optional', () => {
|
|
110
|
+
expect(isOptionalParam(ctx.component, 'disabled')).toBe(true);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('should have type boolean', () => {
|
|
114
|
+
expect(hasParamType(ctx.component, 'disabled', 'boolean')).toBe(true);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
describe('param: required', () => {
|
|
119
|
+
it('should be optional', () => {
|
|
120
|
+
expect(isOptionalParam(ctx.component, 'required')).toBe(true);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('should have type boolean', () => {
|
|
124
|
+
expect(hasParamType(ctx.component, 'required', 'boolean')).toBe(true);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe('param: rows', () => {
|
|
129
|
+
it('should be optional', () => {
|
|
130
|
+
expect(isOptionalParam(ctx.component, 'rows')).toBe(true);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('should have type number', () => {
|
|
134
|
+
expect(hasParamType(ctx.component, 'rows', 'number')).toBe(true);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
describe('param: name', () => {
|
|
139
|
+
it('should be optional', () => {
|
|
140
|
+
expect(isOptionalParam(ctx.component, 'name')).toBe(true);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('should have type string', () => {
|
|
144
|
+
expect(hasParamType(ctx.component, 'name', 'string')).toBe(true);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe('param: id', () => {
|
|
149
|
+
it('should be optional', () => {
|
|
150
|
+
expect(isOptionalParam(ctx.component, 'id')).toBe(true);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('should have type string', () => {
|
|
154
|
+
expect(hasParamType(ctx.component, 'id', 'string')).toBe(true);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
describe('param: ariaLabel', () => {
|
|
159
|
+
it('should be optional', () => {
|
|
160
|
+
expect(isOptionalParam(ctx.component, 'ariaLabel')).toBe(true);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('should have type string', () => {
|
|
164
|
+
expect(hasParamType(ctx.component, 'ariaLabel', 'string')).toBe(true);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// ==================== Style Preset Tests ====================
|
|
170
|
+
|
|
171
|
+
describe('Style Preset', () => {
|
|
172
|
+
it('should have valid style preset structure', () => {
|
|
173
|
+
const textareaStyles = ctx.styles['textareaStyles'];
|
|
174
|
+
expect(textareaStyles).toBeDefined();
|
|
175
|
+
assertValidStylePreset(textareaStyles);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('should have base classes', () => {
|
|
179
|
+
const textareaStyles = ctx.styles['textareaStyles'];
|
|
180
|
+
expect(textareaStyles.base).toBeDefined();
|
|
181
|
+
expect(typeof textareaStyles.base).toBe('string');
|
|
182
|
+
expect(textareaStyles.base.length).toBeGreaterThan(0);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
describe('size options', () => {
|
|
186
|
+
const sizeOptions = ['default', 'sm', 'lg'];
|
|
187
|
+
|
|
188
|
+
it('should have size variants', () => {
|
|
189
|
+
const textareaStyles = ctx.styles['textareaStyles'];
|
|
190
|
+
expect(hasVariants(textareaStyles, ['size'])).toBe(true);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it.each(sizeOptions)('should have %s size option', (option) => {
|
|
194
|
+
const textareaStyles = ctx.styles['textareaStyles'];
|
|
195
|
+
expect(hasVariantOptions(textareaStyles, 'size', [option])).toBe(true);
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
describe('default variants', () => {
|
|
200
|
+
it('should have default size set to default', () => {
|
|
201
|
+
const textareaStyles = ctx.styles['textareaStyles'];
|
|
202
|
+
expect(hasDefaultVariants(textareaStyles, { size: 'default' })).toBe(true);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// ==================== Accessibility Tests ====================
|
|
208
|
+
|
|
209
|
+
describe('Accessibility', () => {
|
|
210
|
+
it('should support aria-label attribute', () => {
|
|
211
|
+
const ariaLabel = findPropInView(ctx.component.view, 'aria-label');
|
|
212
|
+
expect(ariaLabel).not.toBeNull();
|
|
213
|
+
// Should reference the ariaLabel param
|
|
214
|
+
expect(ariaLabel).toMatchObject({
|
|
215
|
+
expr: 'param',
|
|
216
|
+
name: 'ariaLabel',
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('should support disabled attribute', () => {
|
|
221
|
+
const disabled = findPropInView(ctx.component.view, 'disabled');
|
|
222
|
+
expect(disabled).not.toBeNull();
|
|
223
|
+
// Should reference the disabled param
|
|
224
|
+
expect(disabled).toMatchObject({
|
|
225
|
+
expr: 'param',
|
|
226
|
+
name: 'disabled',
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it('should support required attribute', () => {
|
|
231
|
+
const required = findPropInView(ctx.component.view, 'required');
|
|
232
|
+
expect(required).not.toBeNull();
|
|
233
|
+
// Should reference the required param
|
|
234
|
+
expect(required).toMatchObject({
|
|
235
|
+
expr: 'param',
|
|
236
|
+
name: 'required',
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
// ==================== View Props Tests ====================
|
|
242
|
+
|
|
243
|
+
describe('View Props', () => {
|
|
244
|
+
it('should pass value to textarea', () => {
|
|
245
|
+
const value = findPropInView(ctx.component.view, 'value');
|
|
246
|
+
expect(value).not.toBeNull();
|
|
247
|
+
expect(value).toMatchObject({
|
|
248
|
+
expr: 'param',
|
|
249
|
+
name: 'value',
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it('should pass placeholder to textarea', () => {
|
|
254
|
+
const placeholder = findPropInView(ctx.component.view, 'placeholder');
|
|
255
|
+
expect(placeholder).not.toBeNull();
|
|
256
|
+
expect(placeholder).toMatchObject({
|
|
257
|
+
expr: 'param',
|
|
258
|
+
name: 'placeholder',
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it('should pass name to textarea', () => {
|
|
263
|
+
const name = findPropInView(ctx.component.view, 'name');
|
|
264
|
+
expect(name).not.toBeNull();
|
|
265
|
+
expect(name).toMatchObject({
|
|
266
|
+
expr: 'param',
|
|
267
|
+
name: 'name',
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
it('should pass id to textarea', () => {
|
|
272
|
+
const id = findPropInView(ctx.component.view, 'id');
|
|
273
|
+
expect(id).not.toBeNull();
|
|
274
|
+
expect(id).toMatchObject({
|
|
275
|
+
expr: 'param',
|
|
276
|
+
name: 'id',
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it('should pass size to StyleExpr', () => {
|
|
281
|
+
const className = findPropInView(ctx.component.view, 'className');
|
|
282
|
+
expect(className).toMatchObject({
|
|
283
|
+
expr: 'style',
|
|
284
|
+
props: expect.objectContaining({
|
|
285
|
+
size: expect.objectContaining({ expr: 'param', name: 'size' }),
|
|
286
|
+
}),
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"params": {
|
|
3
|
+
"variant": { "type": "string", "required": false },
|
|
4
|
+
"title": { "type": "string", "required": false },
|
|
5
|
+
"description": { "type": "string", "required": false }
|
|
6
|
+
},
|
|
7
|
+
"view": {
|
|
8
|
+
"kind": "element",
|
|
9
|
+
"tag": "div",
|
|
10
|
+
"props": {
|
|
11
|
+
"role": { "expr": "lit", "value": "alert" },
|
|
12
|
+
"aria-live": { "expr": "lit", "value": "polite" },
|
|
13
|
+
"className": {
|
|
14
|
+
"expr": "style",
|
|
15
|
+
"preset": "toastStyles",
|
|
16
|
+
"props": {
|
|
17
|
+
"variant": { "expr": "param", "name": "variant" }
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"children": [{ "kind": "slot" }]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"toastStyles": {
|
|
3
|
+
"base": "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
|
|
4
|
+
"variants": {
|
|
5
|
+
"variant": {
|
|
6
|
+
"default": "border bg-background text-foreground",
|
|
7
|
+
"success": "border-green-500 bg-green-50 text-green-900 dark:bg-green-900 dark:text-green-50",
|
|
8
|
+
"error": "border-destructive bg-destructive text-destructive-foreground",
|
|
9
|
+
"warning": "border-yellow-500 bg-yellow-50 text-yellow-900 dark:bg-yellow-900 dark:text-yellow-50",
|
|
10
|
+
"info": "border-blue-500 bg-blue-50 text-blue-900 dark:bg-blue-900 dark:text-blue-50"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"defaultVariants": {
|
|
14
|
+
"variant": "default"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|