@salutejs/sdds-api-tests 0.7.0-next-platform-ai.0 → 0.8.0-dev.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/package.json +17 -16
- package/script.mjs +43 -13
- package/src/components/Button/Button.api.test.tsx +28 -2
- package/src/components/Checkbox/Checkbox.api.test.tsx +1 -1
- package/src/components/Combobox/Combobox.api.test.tsx +409 -151
- package/src/components/InformationWrapper/InformationWrapper.api.test.tsx +171 -0
- package/src/components/Popover/Popover.api.test.tsx +172 -0
- package/src/components/Select/Select.api.test.tsx +2 -2
- package/src/components/Skeleton/Skeleton.api.test.tsx +220 -0
- package/src/components/TextField/TextField.api.test.tsx +1 -1
- package/src/components/Typography/Typography.api.test.tsx +1 -1
- package/tsconfig.json +1 -0
- package/tsconfig.typecheck.json +4 -0
- package/vitest.config.ts +0 -12
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { ComponentProps, ReactNode, CSSProperties, AriaRole } from 'react';
|
|
3
|
+
import { describe, it } from 'node:test';
|
|
4
|
+
import { expectTypeOf } from 'expect-type';
|
|
5
|
+
import { InformationWrapper } from '@salutejs/plasma-b2c';
|
|
6
|
+
|
|
7
|
+
type InformationWrapperProps = ComponentProps<typeof InformationWrapper>;
|
|
8
|
+
|
|
9
|
+
describe('Basics', () => {
|
|
10
|
+
it('Common', () => {
|
|
11
|
+
// Layout
|
|
12
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('children').toEqualTypeOf<ReactNode>();
|
|
13
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('label').toEqualTypeOf<string | undefined>();
|
|
14
|
+
expectTypeOf<InformationWrapperProps>()
|
|
15
|
+
.toHaveProperty('labelPlacement')
|
|
16
|
+
.toEqualTypeOf<'top' | 'left' | undefined>();
|
|
17
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('labelHtmlFor').toEqualTypeOf<string | undefined>();
|
|
18
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('titleCaption').toEqualTypeOf<ReactNode>();
|
|
19
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('leftHelper').toEqualTypeOf<ReactNode>();
|
|
20
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('rightHelper').toEqualTypeOf<ReactNode>();
|
|
21
|
+
|
|
22
|
+
// Form-related
|
|
23
|
+
expectTypeOf<InformationWrapperProps>()
|
|
24
|
+
.toHaveProperty('hasRequiredIndicator')
|
|
25
|
+
.toEqualTypeOf<boolean | undefined>();
|
|
26
|
+
expectTypeOf<InformationWrapperProps>()
|
|
27
|
+
.toHaveProperty('requiredIndicatorPlacement')
|
|
28
|
+
.toEqualTypeOf<'right' | 'left' | undefined>();
|
|
29
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('optional').toEqualTypeOf<boolean | undefined>();
|
|
30
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('optionalText').toEqualTypeOf<string | undefined>();
|
|
31
|
+
|
|
32
|
+
// State
|
|
33
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('disabled').toEqualTypeOf<boolean | undefined>();
|
|
34
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('readOnly').toEqualTypeOf<boolean | undefined>();
|
|
35
|
+
|
|
36
|
+
// Hint
|
|
37
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('hintText').toEqualTypeOf<string | undefined>();
|
|
38
|
+
expectTypeOf<InformationWrapperProps>()
|
|
39
|
+
.toHaveProperty('hintTrigger')
|
|
40
|
+
.toEqualTypeOf<'hover' | 'click' | undefined>();
|
|
41
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('hintOpened').toEqualTypeOf<boolean | undefined>();
|
|
42
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('hintTargetIcon').toEqualTypeOf<ReactNode>();
|
|
43
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('hintHasArrow').toEqualTypeOf<boolean | undefined>();
|
|
44
|
+
expectTypeOf<InformationWrapperProps>()
|
|
45
|
+
.toHaveProperty('hintOffset')
|
|
46
|
+
.toEqualTypeOf<[number, number] | undefined>();
|
|
47
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('hintWidth').toEqualTypeOf<string | undefined>();
|
|
48
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('hintContentLeft').toEqualTypeOf<ReactNode>();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('Variations', () => {
|
|
52
|
+
type View = NonNullable<InformationWrapperProps['view']>;
|
|
53
|
+
expectTypeOf<View>().toExtend<string>();
|
|
54
|
+
expectTypeOf<string>().not.toExtend<View>();
|
|
55
|
+
|
|
56
|
+
type Size = NonNullable<InformationWrapperProps['size']>;
|
|
57
|
+
expectTypeOf<Size>().toExtend<string>();
|
|
58
|
+
expectTypeOf<string>().not.toExtend<Size>();
|
|
59
|
+
|
|
60
|
+
type HintView = NonNullable<InformationWrapperProps['hintView']>;
|
|
61
|
+
expectTypeOf<HintView>().toExtend<string>();
|
|
62
|
+
expectTypeOf<string>().not.toExtend<HintView>();
|
|
63
|
+
|
|
64
|
+
type HintSize = NonNullable<InformationWrapperProps['hintSize']>;
|
|
65
|
+
expectTypeOf<HintSize>().toExtend<string>();
|
|
66
|
+
expectTypeOf<string>().not.toExtend<HintSize>();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('HTMLDivElement', () => {
|
|
70
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('id').toEqualTypeOf<string | undefined>();
|
|
71
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('className').toEqualTypeOf<string | undefined>();
|
|
72
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('style').toEqualTypeOf<CSSProperties | undefined>();
|
|
73
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('aria-label').toEqualTypeOf<string | undefined>();
|
|
74
|
+
expectTypeOf<InformationWrapperProps>().toHaveProperty('role').toEqualTypeOf<AriaRole | undefined>();
|
|
75
|
+
expectTypeOf<InformationWrapperProps>()
|
|
76
|
+
.toHaveProperty('onClick')
|
|
77
|
+
.toEqualTypeOf<React.MouseEventHandler<HTMLDivElement> | undefined>();
|
|
78
|
+
expectTypeOf<InformationWrapperProps>()
|
|
79
|
+
.toHaveProperty('onMouseEnter')
|
|
80
|
+
.toEqualTypeOf<React.MouseEventHandler<HTMLDivElement> | undefined>();
|
|
81
|
+
expectTypeOf<InformationWrapperProps>()
|
|
82
|
+
.toHaveProperty('onMouseLeave')
|
|
83
|
+
.toEqualTypeOf<React.MouseEventHandler<HTMLDivElement> | undefined>();
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
describe('Unions', () => {
|
|
88
|
+
it('HintProps', () => {
|
|
89
|
+
// Valid: with hintText, all hint-related props are available
|
|
90
|
+
expectTypeOf<InformationWrapperProps>({ hintText: 'Текст подсказки' });
|
|
91
|
+
expectTypeOf<InformationWrapperProps>({
|
|
92
|
+
hintText: 'Текст подсказки',
|
|
93
|
+
hintTrigger: 'hover',
|
|
94
|
+
hintHasArrow: true,
|
|
95
|
+
hintWidth: '10rem',
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Valid: without any hint props
|
|
99
|
+
expectTypeOf<InformationWrapperProps>({ label: 'Лейбл' });
|
|
100
|
+
|
|
101
|
+
// Неправильная работа юниона HintProps. Должна быть ошибка при передаче hint-пропсов без hintText.
|
|
102
|
+
// @ts-expect-error
|
|
103
|
+
expectTypeOf<InformationWrapperProps>({ hintTrigger: 'hover' });
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
describe('Examples', () => {
|
|
108
|
+
it('Basic', () => {
|
|
109
|
+
() => {
|
|
110
|
+
return (
|
|
111
|
+
<InformationWrapper label="Лейбл" labelPlacement="top">
|
|
112
|
+
<div />
|
|
113
|
+
</InformationWrapper>
|
|
114
|
+
);
|
|
115
|
+
};
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('With hint', () => {
|
|
119
|
+
() => {
|
|
120
|
+
return (
|
|
121
|
+
<InformationWrapper
|
|
122
|
+
label="Лейбл"
|
|
123
|
+
titleCaption="Подпись к полю"
|
|
124
|
+
leftHelper="Подсказка слева"
|
|
125
|
+
rightHelper="Подсказка справа"
|
|
126
|
+
hintText="Текст подсказки"
|
|
127
|
+
hintTrigger="hover"
|
|
128
|
+
hintHasArrow
|
|
129
|
+
hintWidth="10rem"
|
|
130
|
+
>
|
|
131
|
+
<div />
|
|
132
|
+
</InformationWrapper>
|
|
133
|
+
);
|
|
134
|
+
};
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('Required indicator', () => {
|
|
138
|
+
() => {
|
|
139
|
+
return (
|
|
140
|
+
<InformationWrapper
|
|
141
|
+
label="Лейбл"
|
|
142
|
+
hasRequiredIndicator
|
|
143
|
+
requiredIndicatorPlacement="right"
|
|
144
|
+
labelPlacement="top"
|
|
145
|
+
>
|
|
146
|
+
<div />
|
|
147
|
+
</InformationWrapper>
|
|
148
|
+
);
|
|
149
|
+
};
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('Optional', () => {
|
|
153
|
+
() => {
|
|
154
|
+
return (
|
|
155
|
+
<InformationWrapper label="Лейбл" optional optionalText="опционально">
|
|
156
|
+
<div />
|
|
157
|
+
</InformationWrapper>
|
|
158
|
+
);
|
|
159
|
+
};
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('Disabled', () => {
|
|
163
|
+
() => {
|
|
164
|
+
return (
|
|
165
|
+
<InformationWrapper label="Лейбл" disabled>
|
|
166
|
+
<div />
|
|
167
|
+
</InformationWrapper>
|
|
168
|
+
);
|
|
169
|
+
};
|
|
170
|
+
});
|
|
171
|
+
});
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import type { ComponentProps, ReactNode, CSSProperties, AriaRole, RefObject, SyntheticEvent, Ref } from 'react';
|
|
3
|
+
import { describe, it } from 'node:test';
|
|
4
|
+
import { expectTypeOf } from 'expect-type';
|
|
5
|
+
import { Popover } from '@salutejs/plasma-b2c';
|
|
6
|
+
import type { PopoverPlacement, PopoverTrigger } from '@salutejs/plasma-b2c';
|
|
7
|
+
|
|
8
|
+
type PopoverProps = ComponentProps<typeof Popover>;
|
|
9
|
+
|
|
10
|
+
describe('Basics', () => {
|
|
11
|
+
it('Common', () => {
|
|
12
|
+
// layout
|
|
13
|
+
expectTypeOf<PopoverProps>().toHaveProperty('target').toEqualTypeOf<ReactNode | Ref<HTMLElement> | undefined>();
|
|
14
|
+
expectTypeOf<PopoverProps>().toHaveProperty('offset').toEqualTypeOf<[number, number] | undefined>();
|
|
15
|
+
expectTypeOf<PopoverProps>()
|
|
16
|
+
.toHaveProperty('frame')
|
|
17
|
+
.toEqualTypeOf<string | RefObject<HTMLElement> | undefined>();
|
|
18
|
+
expectTypeOf<PopoverProps>().toHaveProperty('hasArrow').toEqualTypeOf<boolean | undefined>();
|
|
19
|
+
expectTypeOf<PopoverProps>().toHaveProperty('zIndex').toEqualTypeOf<string | undefined>();
|
|
20
|
+
expectTypeOf<PopoverProps>().toHaveProperty('preventOverflow').toEqualTypeOf<boolean | undefined>();
|
|
21
|
+
expectTypeOf<PopoverProps>().toHaveProperty('usePortal').toEqualTypeOf<boolean | undefined>();
|
|
22
|
+
expectTypeOf<PopoverProps>().toHaveProperty('animated').toEqualTypeOf<boolean | undefined>();
|
|
23
|
+
|
|
24
|
+
// state / behaviour
|
|
25
|
+
expectTypeOf<PopoverProps>().toHaveProperty('opened').toEqualTypeOf<boolean | undefined>();
|
|
26
|
+
expectTypeOf<PopoverProps>().toHaveProperty('trigger').toEqualTypeOf<PopoverTrigger | undefined>();
|
|
27
|
+
expectTypeOf<PopoverProps>().toHaveProperty('isFocusTrapped').toEqualTypeOf<boolean | undefined>();
|
|
28
|
+
expectTypeOf<PopoverProps>().toHaveProperty('closeOnEsc').toEqualTypeOf<boolean | undefined>();
|
|
29
|
+
expectTypeOf<PopoverProps>().toHaveProperty('closeOnOverlayClick').toEqualTypeOf<boolean | undefined>();
|
|
30
|
+
|
|
31
|
+
// content slots
|
|
32
|
+
expectTypeOf<PopoverProps>().toHaveProperty('children').toEqualTypeOf<ReactNode>();
|
|
33
|
+
|
|
34
|
+
// callbacks
|
|
35
|
+
expectTypeOf<PopoverProps>()
|
|
36
|
+
.toHaveProperty('onToggle')
|
|
37
|
+
.toEqualTypeOf<((isOpen: boolean, event: SyntheticEvent | Event) => void) | undefined>();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('Placement', () => {
|
|
41
|
+
type PlacementProp = NonNullable<PopoverProps['placement']>;
|
|
42
|
+
expectTypeOf<PlacementProp>().toExtend<string | readonly string[]>();
|
|
43
|
+
expectTypeOf<string>().not.toExtend<PlacementProp>();
|
|
44
|
+
|
|
45
|
+
// accepts known placement values
|
|
46
|
+
expectTypeOf<PopoverProps>({ placement: 'top' as PopoverPlacement });
|
|
47
|
+
expectTypeOf<PopoverProps>({ placement: 'bottom-start' as PopoverPlacement });
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('HTMLDivElement', () => {
|
|
51
|
+
expectTypeOf<PopoverProps>().toHaveProperty('id').toEqualTypeOf<string | undefined>();
|
|
52
|
+
expectTypeOf<PopoverProps>().toHaveProperty('className').toEqualTypeOf<string | undefined>();
|
|
53
|
+
expectTypeOf<PopoverProps>().toHaveProperty('style').toEqualTypeOf<CSSProperties | undefined>();
|
|
54
|
+
expectTypeOf<PopoverProps>().toHaveProperty('role').toEqualTypeOf<AriaRole | undefined>();
|
|
55
|
+
expectTypeOf<PopoverProps>().toHaveProperty('aria-label').toEqualTypeOf<string | undefined>();
|
|
56
|
+
expectTypeOf<PopoverProps>()
|
|
57
|
+
.toHaveProperty('onClick')
|
|
58
|
+
.toEqualTypeOf<React.MouseEventHandler<HTMLDivElement> | undefined>();
|
|
59
|
+
expectTypeOf<PopoverProps>()
|
|
60
|
+
.toHaveProperty('onMouseEnter')
|
|
61
|
+
.toEqualTypeOf<React.MouseEventHandler<HTMLDivElement> | undefined>();
|
|
62
|
+
expectTypeOf<PopoverProps>()
|
|
63
|
+
.toHaveProperty('onMouseLeave')
|
|
64
|
+
.toEqualTypeOf<React.MouseEventHandler<HTMLDivElement> | undefined>();
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe('Resizable', () => {
|
|
69
|
+
it('resizable prop accepts boolean', () => {
|
|
70
|
+
expectTypeOf<PopoverProps>({ resizable: true });
|
|
71
|
+
expectTypeOf<PopoverProps>({ resizable: false });
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('resizable prop accepts config object', () => {
|
|
75
|
+
expectTypeOf<PopoverProps>({
|
|
76
|
+
resizable: {
|
|
77
|
+
disabled: false,
|
|
78
|
+
directions: ['bottom-right'],
|
|
79
|
+
defaultSize: { width: 200, height: 100 },
|
|
80
|
+
minWidth: 100,
|
|
81
|
+
minHeight: 50,
|
|
82
|
+
maxWidth: 600,
|
|
83
|
+
maxHeight: 400,
|
|
84
|
+
iconSize: 's',
|
|
85
|
+
hiddenIcons: ['top-left'],
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('iconSize is narrowed', () => {
|
|
91
|
+
type ResizableObj = Extract<NonNullable<PopoverProps['resizable']>, object>;
|
|
92
|
+
expectTypeOf<ResizableObj>().toHaveProperty('iconSize').toEqualTypeOf<'xs' | 's' | 'm' | undefined>();
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe('Examples', () => {
|
|
97
|
+
it('Click trigger', () => {
|
|
98
|
+
() => {
|
|
99
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
100
|
+
return (
|
|
101
|
+
<Popover
|
|
102
|
+
opened={isOpen}
|
|
103
|
+
onToggle={(is) => setIsOpen(is)}
|
|
104
|
+
trigger="click"
|
|
105
|
+
placement="bottom"
|
|
106
|
+
hasArrow
|
|
107
|
+
target={<button type="button">Open</button>}
|
|
108
|
+
>
|
|
109
|
+
<div>Content</div>
|
|
110
|
+
</Popover>
|
|
111
|
+
);
|
|
112
|
+
};
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('Hover trigger with offset', () => {
|
|
116
|
+
() => {
|
|
117
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
118
|
+
return (
|
|
119
|
+
<Popover
|
|
120
|
+
opened={isOpen}
|
|
121
|
+
onToggle={(is) => setIsOpen(is)}
|
|
122
|
+
trigger="hover"
|
|
123
|
+
placement="top"
|
|
124
|
+
offset={[0, 8]}
|
|
125
|
+
closeOnEsc={false}
|
|
126
|
+
isFocusTrapped={false}
|
|
127
|
+
>
|
|
128
|
+
Content
|
|
129
|
+
</Popover>
|
|
130
|
+
);
|
|
131
|
+
};
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('Resizable', () => {
|
|
135
|
+
() => {
|
|
136
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
137
|
+
return (
|
|
138
|
+
<Popover
|
|
139
|
+
opened={isOpen}
|
|
140
|
+
onToggle={(is) => setIsOpen(is)}
|
|
141
|
+
trigger="click"
|
|
142
|
+
resizable={{ disabled: false, directions: ['bottom-right'], iconSize: 's' }}
|
|
143
|
+
onResizeStart={() => {}}
|
|
144
|
+
onResizeEnd={() => {}}
|
|
145
|
+
>
|
|
146
|
+
Content
|
|
147
|
+
</Popover>
|
|
148
|
+
);
|
|
149
|
+
};
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('Overlay click and frame', () => {
|
|
153
|
+
() => {
|
|
154
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
155
|
+
const ref = React.useRef<HTMLDivElement>(null);
|
|
156
|
+
return (
|
|
157
|
+
<div ref={ref}>
|
|
158
|
+
<Popover
|
|
159
|
+
opened={isOpen}
|
|
160
|
+
onToggle={(is) => setIsOpen(is)}
|
|
161
|
+
trigger="click"
|
|
162
|
+
closeOnOverlayClick
|
|
163
|
+
frame={ref}
|
|
164
|
+
animated
|
|
165
|
+
>
|
|
166
|
+
Content
|
|
167
|
+
</Popover>
|
|
168
|
+
</div>
|
|
169
|
+
);
|
|
170
|
+
};
|
|
171
|
+
});
|
|
172
|
+
});
|
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
RefObject,
|
|
10
10
|
} from 'react';
|
|
11
11
|
import { useRef, useState } from 'react';
|
|
12
|
-
import { describe, it } from '
|
|
12
|
+
import { describe, it } from 'node:test';
|
|
13
13
|
import { expectTypeOf } from 'expect-type';
|
|
14
14
|
import { Controller, useForm } from 'react-hook-form';
|
|
15
15
|
import { Button, Cell, Select } from '@salutejs/plasma-b2c';
|
|
@@ -51,7 +51,7 @@ describe('Basics', () => {
|
|
|
51
51
|
expectTypeOf<SelectProps>().toHaveProperty('listWidth').toEqualTypeOf<CSSProperties['width'] | undefined>();
|
|
52
52
|
expectTypeOf<SelectProps>()
|
|
53
53
|
.toHaveProperty('portal')
|
|
54
|
-
.toEqualTypeOf<string | RefObject<HTMLElement> | undefined>();
|
|
54
|
+
.toEqualTypeOf<string | RefObject<HTMLElement | null> | undefined>();
|
|
55
55
|
expectTypeOf<SelectProps>()
|
|
56
56
|
.toHaveProperty('renderValue')
|
|
57
57
|
.toEqualTypeOf<((item: ItemOption) => string) | undefined>();
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { ComponentProps, CSSProperties, AriaRole } from 'react';
|
|
3
|
+
import { describe, it } from 'node:test';
|
|
4
|
+
import { expectTypeOf } from 'expect-type';
|
|
5
|
+
import { LineSkeleton, RectSkeleton, TextSkeleton, withSkeleton } from '@salutejs/plasma-b2c';
|
|
6
|
+
import type { WithSkeletonProps } from '@salutejs/plasma-b2c';
|
|
7
|
+
|
|
8
|
+
type LineSkeletonProps = ComponentProps<typeof LineSkeleton>;
|
|
9
|
+
type RectSkeletonProps = ComponentProps<typeof RectSkeleton>;
|
|
10
|
+
type TextSkeletonProps = ComponentProps<typeof TextSkeleton>;
|
|
11
|
+
|
|
12
|
+
describe('LineSkeleton', () => {
|
|
13
|
+
it('Common', () => {
|
|
14
|
+
expectTypeOf<LineSkeletonProps>()
|
|
15
|
+
.toHaveProperty('animationType')
|
|
16
|
+
.toEqualTypeOf<'shimmer' | 'pulse' | undefined>();
|
|
17
|
+
expectTypeOf<LineSkeletonProps>()
|
|
18
|
+
.toHaveProperty('roundness')
|
|
19
|
+
.toEqualTypeOf<0 | 4 | 8 | 12 | 14 | 16 | 18 | 20 | 24 | 28 | 32 | 250 | undefined>();
|
|
20
|
+
expectTypeOf<LineSkeletonProps>().toHaveProperty('lighter').toEqualTypeOf<boolean | undefined>();
|
|
21
|
+
expectTypeOf<LineSkeletonProps>().toHaveProperty('customGradientColor').toEqualTypeOf<string | undefined>();
|
|
22
|
+
expectTypeOf<LineSkeletonProps>().toHaveProperty('customFadeInColor').toEqualTypeOf<string | undefined>();
|
|
23
|
+
expectTypeOf<LineSkeletonProps>().toHaveProperty('customFadeOutColor').toEqualTypeOf<string | undefined>();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('HTMLDivElement', () => {
|
|
27
|
+
expectTypeOf<LineSkeletonProps>().toHaveProperty('id').toEqualTypeOf<string | undefined>();
|
|
28
|
+
expectTypeOf<LineSkeletonProps>().toHaveProperty('className').toEqualTypeOf<string | undefined>();
|
|
29
|
+
expectTypeOf<LineSkeletonProps>().toHaveProperty('style').toEqualTypeOf<CSSProperties | undefined>();
|
|
30
|
+
expectTypeOf<LineSkeletonProps>().toHaveProperty('aria-label').toEqualTypeOf<string | undefined>();
|
|
31
|
+
expectTypeOf<LineSkeletonProps>().toHaveProperty('role').toEqualTypeOf<AriaRole | undefined>();
|
|
32
|
+
expectTypeOf<LineSkeletonProps>()
|
|
33
|
+
.toHaveProperty('onClick')
|
|
34
|
+
.toEqualTypeOf<React.MouseEventHandler<HTMLDivElement> | undefined>();
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
describe('RectSkeleton', () => {
|
|
39
|
+
it('Common', () => {
|
|
40
|
+
expectTypeOf<RectSkeletonProps>().toHaveProperty('width').toEqualTypeOf<string | number>();
|
|
41
|
+
expectTypeOf<RectSkeletonProps>().toHaveProperty('height').toEqualTypeOf<string | number>();
|
|
42
|
+
expectTypeOf<RectSkeletonProps>()
|
|
43
|
+
.toHaveProperty('animationType')
|
|
44
|
+
.toEqualTypeOf<'shimmer' | 'pulse' | undefined>();
|
|
45
|
+
expectTypeOf<RectSkeletonProps>()
|
|
46
|
+
.toHaveProperty('roundness')
|
|
47
|
+
.toEqualTypeOf<0 | 4 | 8 | 12 | 14 | 16 | 18 | 20 | 24 | 28 | 32 | 250 | undefined>();
|
|
48
|
+
expectTypeOf<RectSkeletonProps>().toHaveProperty('lighter').toEqualTypeOf<boolean | undefined>();
|
|
49
|
+
expectTypeOf<RectSkeletonProps>().toHaveProperty('customGradientColor').toEqualTypeOf<string | undefined>();
|
|
50
|
+
expectTypeOf<RectSkeletonProps>().toHaveProperty('customFadeInColor').toEqualTypeOf<string | undefined>();
|
|
51
|
+
expectTypeOf<RectSkeletonProps>().toHaveProperty('customFadeOutColor').toEqualTypeOf<string | undefined>();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('HTMLDivElement', () => {
|
|
55
|
+
expectTypeOf<RectSkeletonProps>().toHaveProperty('id').toEqualTypeOf<string | undefined>();
|
|
56
|
+
expectTypeOf<RectSkeletonProps>().toHaveProperty('className').toEqualTypeOf<string | undefined>();
|
|
57
|
+
expectTypeOf<RectSkeletonProps>().toHaveProperty('style').toEqualTypeOf<CSSProperties | undefined>();
|
|
58
|
+
expectTypeOf<RectSkeletonProps>().toHaveProperty('aria-label').toEqualTypeOf<string | undefined>();
|
|
59
|
+
expectTypeOf<RectSkeletonProps>().toHaveProperty('role').toEqualTypeOf<AriaRole | undefined>();
|
|
60
|
+
expectTypeOf<RectSkeletonProps>()
|
|
61
|
+
.toHaveProperty('onClick')
|
|
62
|
+
.toEqualTypeOf<React.MouseEventHandler<HTMLDivElement> | undefined>();
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe('TextSkeleton', () => {
|
|
67
|
+
it('Common', () => {
|
|
68
|
+
expectTypeOf<TextSkeletonProps>().toHaveProperty('lines').toEqualTypeOf<number>();
|
|
69
|
+
expectTypeOf<TextSkeletonProps>().toHaveProperty('width').toEqualTypeOf<string | number | undefined>();
|
|
70
|
+
expectTypeOf<TextSkeletonProps>()
|
|
71
|
+
.toHaveProperty('animationType')
|
|
72
|
+
.toEqualTypeOf<'shimmer' | 'pulse' | undefined>();
|
|
73
|
+
expectTypeOf<TextSkeletonProps>()
|
|
74
|
+
.toHaveProperty('roundness')
|
|
75
|
+
.toEqualTypeOf<0 | 4 | 8 | 12 | 14 | 16 | 18 | 20 | 24 | 28 | 32 | 250 | undefined>();
|
|
76
|
+
expectTypeOf<TextSkeletonProps>().toHaveProperty('lighter').toEqualTypeOf<boolean | undefined>();
|
|
77
|
+
expectTypeOf<TextSkeletonProps>().toHaveProperty('customGradientColor').toEqualTypeOf<string | undefined>();
|
|
78
|
+
expectTypeOf<TextSkeletonProps>().toHaveProperty('customFadeInColor').toEqualTypeOf<string | undefined>();
|
|
79
|
+
expectTypeOf<TextSkeletonProps>().toHaveProperty('customFadeOutColor').toEqualTypeOf<string | undefined>();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('HTMLDivElement', () => {
|
|
83
|
+
expectTypeOf<TextSkeletonProps>().toHaveProperty('id').toEqualTypeOf<string | undefined>();
|
|
84
|
+
expectTypeOf<TextSkeletonProps>().toHaveProperty('className').toEqualTypeOf<string | undefined>();
|
|
85
|
+
expectTypeOf<TextSkeletonProps>().toHaveProperty('style').toEqualTypeOf<CSSProperties | undefined>();
|
|
86
|
+
expectTypeOf<TextSkeletonProps>().toHaveProperty('aria-label').toEqualTypeOf<string | undefined>();
|
|
87
|
+
expectTypeOf<TextSkeletonProps>().toHaveProperty('role').toEqualTypeOf<AriaRole | undefined>();
|
|
88
|
+
expectTypeOf<TextSkeletonProps>()
|
|
89
|
+
.toHaveProperty('onClick')
|
|
90
|
+
.toEqualTypeOf<React.MouseEventHandler<HTMLDivElement> | undefined>();
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe('withSkeleton', () => {
|
|
95
|
+
it('Common', () => {
|
|
96
|
+
expectTypeOf<WithSkeletonProps>().toHaveProperty('skeleton').toEqualTypeOf<boolean | undefined>();
|
|
97
|
+
expectTypeOf<WithSkeletonProps>()
|
|
98
|
+
.toHaveProperty('animationConfig')
|
|
99
|
+
.toEqualTypeOf<
|
|
100
|
+
| { type: 'shimmer'; lighter?: boolean; customGradientColor?: string }
|
|
101
|
+
| { type: 'pulse'; customFadeInColor?: string; customFadeOutColor?: string }
|
|
102
|
+
| undefined
|
|
103
|
+
>();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('HTMLElement', () => {
|
|
107
|
+
expectTypeOf<WithSkeletonProps>().toHaveProperty('id').toEqualTypeOf<string | undefined>();
|
|
108
|
+
expectTypeOf<WithSkeletonProps>().toHaveProperty('className').toEqualTypeOf<string | undefined>();
|
|
109
|
+
expectTypeOf<WithSkeletonProps>().toHaveProperty('style').toEqualTypeOf<CSSProperties | undefined>();
|
|
110
|
+
expectTypeOf<WithSkeletonProps>().toHaveProperty('aria-label').toEqualTypeOf<string | undefined>();
|
|
111
|
+
expectTypeOf<WithSkeletonProps>().toHaveProperty('role').toEqualTypeOf<AriaRole | undefined>();
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('Unions', () => {
|
|
116
|
+
it('AnimationConfig', () => {
|
|
117
|
+
// shimmer — valid combinations
|
|
118
|
+
expectTypeOf<WithSkeletonProps>({ animationConfig: { type: 'shimmer' } });
|
|
119
|
+
expectTypeOf<WithSkeletonProps>({ animationConfig: { type: 'shimmer', lighter: true } });
|
|
120
|
+
expectTypeOf<WithSkeletonProps>({ animationConfig: { type: 'shimmer', customGradientColor: '#fff' } });
|
|
121
|
+
|
|
122
|
+
// pulse — valid combinations
|
|
123
|
+
expectTypeOf<WithSkeletonProps>({ animationConfig: { type: 'pulse' } });
|
|
124
|
+
expectTypeOf<WithSkeletonProps>({ animationConfig: { type: 'pulse', customFadeInColor: '#f00' } });
|
|
125
|
+
expectTypeOf<WithSkeletonProps>({
|
|
126
|
+
animationConfig: { type: 'pulse', customFadeInColor: '#f00', customFadeOutColor: '#0f0' },
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// shimmer with pulse-only field
|
|
130
|
+
// @ts-expect-error
|
|
131
|
+
expectTypeOf<WithSkeletonProps>({ animationConfig: { type: 'shimmer', customFadeInColor: '#f00' } });
|
|
132
|
+
|
|
133
|
+
// pulse with shimmer-only field
|
|
134
|
+
// @ts-expect-error
|
|
135
|
+
expectTypeOf<WithSkeletonProps>({ animationConfig: { type: 'pulse', lighter: true } });
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
describe('Examples', () => {
|
|
140
|
+
it('LineSkeleton', () => {
|
|
141
|
+
() => {
|
|
142
|
+
return (
|
|
143
|
+
<>
|
|
144
|
+
<LineSkeleton size="bodyM" />
|
|
145
|
+
<LineSkeleton size="h3" animationType="shimmer" roundness={16} />
|
|
146
|
+
<LineSkeleton
|
|
147
|
+
size="h3"
|
|
148
|
+
animationType="pulse"
|
|
149
|
+
customFadeInColor="#e0e0e0"
|
|
150
|
+
customFadeOutColor="#f5f5f5"
|
|
151
|
+
/>
|
|
152
|
+
<LineSkeleton
|
|
153
|
+
size="bodyS"
|
|
154
|
+
lighter
|
|
155
|
+
customGradientColor="linear-gradient(90deg, #eee 0%, #fff 50%, #eee 100%)"
|
|
156
|
+
/>
|
|
157
|
+
</>
|
|
158
|
+
);
|
|
159
|
+
};
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('RectSkeleton', () => {
|
|
163
|
+
() => {
|
|
164
|
+
return (
|
|
165
|
+
<>
|
|
166
|
+
<RectSkeleton width="12rem" height="8rem" />
|
|
167
|
+
<RectSkeleton width={128} height={128} roundness={8} />
|
|
168
|
+
<RectSkeleton width="4rem" height="4rem" animationType="pulse" />
|
|
169
|
+
</>
|
|
170
|
+
);
|
|
171
|
+
};
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('TextSkeleton', () => {
|
|
175
|
+
() => {
|
|
176
|
+
return (
|
|
177
|
+
<>
|
|
178
|
+
<TextSkeleton lines={3} size="bodyM" />
|
|
179
|
+
<TextSkeleton lines={5} size="textM" width={50} />
|
|
180
|
+
<TextSkeleton lines={3} animationType="shimmer" customGradientColor="linear-gradient()" />
|
|
181
|
+
</>
|
|
182
|
+
);
|
|
183
|
+
};
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('withSkeleton shimmer', () => {
|
|
187
|
+
() => {
|
|
188
|
+
const DivSkeleton = withSkeleton(
|
|
189
|
+
React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>((props, ref) => (
|
|
190
|
+
<div ref={ref} {...props} />
|
|
191
|
+
)),
|
|
192
|
+
);
|
|
193
|
+
return (
|
|
194
|
+
<DivSkeleton
|
|
195
|
+
skeleton
|
|
196
|
+
animationConfig={{
|
|
197
|
+
type: 'shimmer',
|
|
198
|
+
customGradientColor: 'linear-gradient(90deg, #eee, #fff, #eee)',
|
|
199
|
+
}}
|
|
200
|
+
/>
|
|
201
|
+
);
|
|
202
|
+
};
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('withSkeleton pulse', () => {
|
|
206
|
+
() => {
|
|
207
|
+
const DivSkeleton = withSkeleton(
|
|
208
|
+
React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>((props, ref) => (
|
|
209
|
+
<div ref={ref} {...props} />
|
|
210
|
+
)),
|
|
211
|
+
);
|
|
212
|
+
return (
|
|
213
|
+
<DivSkeleton
|
|
214
|
+
skeleton
|
|
215
|
+
animationConfig={{ type: 'pulse', customFadeInColor: '#e0e0e0', customFadeOutColor: '#f5f5f5' }}
|
|
216
|
+
/>
|
|
217
|
+
);
|
|
218
|
+
};
|
|
219
|
+
});
|
|
220
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import type { ComponentProps, ReactNode, CSSProperties, AriaRole, ReactElement, KeyboardEvent } from 'react';
|
|
3
3
|
import { useState } from 'react';
|
|
4
|
-
import { describe, it } from '
|
|
4
|
+
import { describe, it } from 'node:test';
|
|
5
5
|
import { expectTypeOf } from 'expect-type';
|
|
6
6
|
import { TextField } from '@salutejs/plasma-b2c';
|
|
7
7
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { createRef } from 'react';
|
|
2
2
|
import type { ComponentProps } from 'react';
|
|
3
|
-
import { describe, it } from '
|
|
3
|
+
import { describe, it } from 'node:test';
|
|
4
4
|
import { expectTypeOf } from 'expect-type';
|
|
5
5
|
import { TextL } from '@salutejs/plasma-b2c';
|
|
6
6
|
|
package/tsconfig.json
CHANGED