@lumx/react 3.10.0 → 3.10.1-alpha.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/_internal/index.d.ts +1 -1
- package/index.d.ts +13 -5
- package/index.js +217 -202
- package/index.js.map +1 -1
- package/package.json +3 -3
- package/src/components/autocomplete/Autocomplete.test.tsx +9 -2
- package/src/components/autocomplete/Autocomplete.tsx +3 -1
- package/src/components/autocomplete/AutocompleteMultiple.test.tsx +9 -2
- package/src/components/autocomplete/AutocompleteMultiple.tsx +3 -1
- package/src/components/avatar/Avatar.test.tsx +14 -4
- package/src/components/avatar/Avatar.tsx +3 -2
- package/src/components/button/Button.test.tsx +9 -3
- package/src/components/button/Button.tsx +3 -2
- package/src/components/button/IconButton.test.tsx +9 -3
- package/src/components/button/IconButton.tsx +13 -2
- package/src/components/checkbox/Checkbox.test.tsx +9 -3
- package/src/components/checkbox/Checkbox.tsx +4 -4
- package/src/components/chip/Chip.test.tsx +14 -4
- package/src/components/chip/Chip.tsx +3 -2
- package/src/components/comment-block/CommentBlock.test.tsx +9 -3
- package/src/components/comment-block/CommentBlock.tsx +3 -2
- package/src/components/date-picker/DatePickerField.test.tsx +9 -3
- package/src/components/dialog/Dialog.test.tsx +17 -4
- package/src/components/dialog/Dialog.tsx +61 -58
- package/src/components/divider/Divider.test.tsx +9 -3
- package/src/components/divider/Divider.tsx +4 -4
- package/src/components/drag-handle/DragHandle.test.tsx +38 -0
- package/src/components/drag-handle/DragHandle.tsx +3 -1
- package/src/components/expansion-panel/ExpansionPanel.test.tsx +12 -3
- package/src/components/expansion-panel/ExpansionPanel.tsx +4 -4
- package/src/components/flag/Flag.test.tsx +14 -4
- package/src/components/flag/Flag.tsx +4 -4
- package/src/components/icon/Icon.test.tsx +13 -4
- package/src/components/icon/Icon.tsx +13 -1
- package/src/components/image-block/ImageBlock.test.tsx +12 -4
- package/src/components/image-block/ImageBlock.tsx +3 -2
- package/src/components/input-helper/InputHelper.test.tsx +14 -4
- package/src/components/input-helper/InputHelper.tsx +3 -2
- package/src/components/input-label/InputLabel.test.tsx +14 -4
- package/src/components/input-label/InputLabel.tsx +4 -4
- package/src/components/lightbox/Lightbox.test.tsx +17 -6
- package/src/components/lightbox/Lightbox.tsx +8 -5
- package/src/components/link-preview/LinkPreview.test.tsx +9 -3
- package/src/components/link-preview/LinkPreview.tsx +3 -2
- package/src/components/mosaic/Mosaic.test.tsx +9 -3
- package/src/components/mosaic/Mosaic.tsx +4 -4
- package/src/components/navigation/Navigation.test.tsx +18 -9
- package/src/components/navigation/Navigation.tsx +13 -5
- package/src/components/navigation/NavigationItem.tsx +3 -3
- package/src/components/navigation/NavigationSection.tsx +4 -4
- package/src/components/notification/Notification.tsx +3 -2
- package/src/components/popover/Popover.test.tsx +18 -4
- package/src/components/popover/Popover.tsx +2 -1
- package/src/components/post-block/PostBlock.test.tsx +9 -3
- package/src/components/post-block/PostBlock.tsx +3 -2
- package/src/components/progress/Progress.tsx +3 -2
- package/src/components/progress/ProgressCircular.test.tsx +9 -16
- package/src/components/progress/ProgressCircular.tsx +3 -2
- package/src/components/progress/ProgressLinear.test.tsx +13 -18
- package/src/components/progress/ProgressLinear.tsx +4 -4
- package/src/components/radio-button/RadioButton.test.tsx +9 -3
- package/src/components/radio-button/RadioButton.tsx +4 -4
- package/src/components/select/Select.test.tsx +9 -3
- package/src/components/select/Select.tsx +27 -23
- package/src/components/select/SelectMultiple.test.tsx +9 -3
- package/src/components/select/SelectMultiple.tsx +109 -103
- package/src/components/select/WithSelectContext.tsx +8 -6
- package/src/components/side-navigation/SideNavigation.tsx +3 -1
- package/src/components/skeleton/SkeletonCircle.test.tsx +9 -3
- package/src/components/skeleton/SkeletonCircle.tsx +4 -4
- package/src/components/skeleton/SkeletonRectangle.test.tsx +9 -3
- package/src/components/skeleton/SkeletonRectangle.tsx +3 -2
- package/src/components/skeleton/SkeletonTypography.test.tsx +9 -3
- package/src/components/skeleton/SkeletonTypography.tsx +4 -4
- package/src/components/slider/Slider.test.tsx +9 -3
- package/src/components/slider/Slider.tsx +3 -2
- package/src/components/slideshow/Slides.tsx +3 -1
- package/src/components/slideshow/Slideshow.test.tsx +9 -3
- package/src/components/slideshow/Slideshow.tsx +3 -2
- package/src/components/slideshow/SlideshowControls.tsx +3 -2
- package/src/components/switch/Switch.test.tsx +9 -3
- package/src/components/switch/Switch.tsx +3 -2
- package/src/components/table/Table.test.tsx +9 -3
- package/src/components/table/Table.tsx +4 -4
- package/src/components/tabs/TabList.test.tsx +9 -3
- package/src/components/tabs/TabList.tsx +11 -2
- package/src/components/text-field/TextField.test.tsx +9 -3
- package/src/components/text-field/TextField.tsx +3 -2
- package/src/components/thumbnail/Thumbnail.test.tsx +9 -3
- package/src/components/thumbnail/Thumbnail.tsx +3 -2
- package/src/components/uploader/Uploader.test.tsx +9 -3
- package/src/components/uploader/Uploader.tsx +13 -2
- package/src/components/user-block/UserBlock.test.tsx +9 -3
- package/src/components/user-block/UserBlock.tsx +3 -2
- package/src/index.ts +1 -0
- package/src/testing/utils/ThemeSentinel.tsx +11 -0
- package/src/testing/utils/commonTestsSuiteRTL.tsx +190 -0
- package/src/utils/theme/ThemeContext.ts +16 -0
- package/src/utils/theme/invertTheme.ts +4 -0
- package/src/testing/utils/commonTestsSuiteRTL.ts +0 -64
- package/src/utils/ThemeContext.ts +0 -4
|
@@ -6,6 +6,7 @@ import { Comp, GenericProps, HasTheme, ValueOf } from '@lumx/react/utils/type';
|
|
|
6
6
|
import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
|
|
7
7
|
import { useBooleanState } from '@lumx/react/hooks/useBooleanState';
|
|
8
8
|
import { useId } from '@lumx/react/hooks/useId';
|
|
9
|
+
import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Uploader variants.
|
|
@@ -65,7 +66,6 @@ const CLASSNAME = getRootClassName(COMPONENT_NAME);
|
|
|
65
66
|
const DEFAULT_PROPS: Partial<UploaderProps> = {
|
|
66
67
|
aspectRatio: AspectRatio.horizontal,
|
|
67
68
|
size: Size.xl,
|
|
68
|
-
theme: Theme.light,
|
|
69
69
|
variant: UploaderVariant.square,
|
|
70
70
|
};
|
|
71
71
|
|
|
@@ -77,7 +77,18 @@ const DEFAULT_PROPS: Partial<UploaderProps> = {
|
|
|
77
77
|
* @return React element.
|
|
78
78
|
*/
|
|
79
79
|
export const Uploader: Comp<UploaderProps> = forwardRef((props, ref) => {
|
|
80
|
-
const
|
|
80
|
+
const defaultTheme = useTheme() || Theme.light;
|
|
81
|
+
const {
|
|
82
|
+
aspectRatio,
|
|
83
|
+
className,
|
|
84
|
+
label,
|
|
85
|
+
icon,
|
|
86
|
+
size,
|
|
87
|
+
theme = defaultTheme,
|
|
88
|
+
variant,
|
|
89
|
+
fileInputProps,
|
|
90
|
+
...forwardedProps
|
|
91
|
+
} = props;
|
|
81
92
|
// Adjust to square aspect ratio when using circle variants.
|
|
82
93
|
const adjustedAspectRatio = variant === UploaderVariant.circle ? AspectRatio.square : aspectRatio;
|
|
83
94
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
-
import { commonTestsSuiteRTL } from '@lumx/react/testing/utils';
|
|
3
|
+
import { commonTestsSuiteRTL, SetupRenderOptions } from '@lumx/react/testing/utils';
|
|
4
4
|
import { render, within } from '@testing-library/react';
|
|
5
5
|
import { getByClassName, queryByClassName } from '@lumx/react/testing/utils/queries';
|
|
6
6
|
import { Thumbnail } from '@lumx/react';
|
|
@@ -13,10 +13,10 @@ const CLASSNAME = UserBlock.className as string;
|
|
|
13
13
|
/**
|
|
14
14
|
* Mounts the component and returns common DOM elements / data needed in multiple tests further down.
|
|
15
15
|
*/
|
|
16
|
-
const setup = (propsOverride: Partial<UserBlockProps> = {}) => {
|
|
16
|
+
const setup = (propsOverride: Partial<UserBlockProps> = {}, { wrapper }: SetupRenderOptions = {}) => {
|
|
17
17
|
const props: UserBlockProps = { ...propsOverride };
|
|
18
18
|
|
|
19
|
-
render(<UserBlock {...props}
|
|
19
|
+
render(<UserBlock {...props} />, { wrapper });
|
|
20
20
|
const userBlock = getByClassName(document.body, CLASSNAME);
|
|
21
21
|
const name = queryByClassName(userBlock, `${CLASSNAME}__name`);
|
|
22
22
|
const avatar = queryByClassName(userBlock, `${CLASSNAME}__avatar`);
|
|
@@ -86,5 +86,11 @@ describe(`<${UserBlock.displayName}>`, () => {
|
|
|
86
86
|
forwardClassName: 'userBlock',
|
|
87
87
|
forwardAttributes: 'userBlock',
|
|
88
88
|
forwardRef: 'userBlock',
|
|
89
|
+
applyTheme: {
|
|
90
|
+
affects: [{ element: 'userBlock' }],
|
|
91
|
+
viaProp: true,
|
|
92
|
+
viaContext: true,
|
|
93
|
+
defaultTheme: 'light',
|
|
94
|
+
},
|
|
89
95
|
});
|
|
90
96
|
});
|
|
@@ -7,6 +7,7 @@ import { Avatar, ColorPalette, Link, Orientation, Size, Theme } from '@lumx/reac
|
|
|
7
7
|
import { Comp, GenericProps, HasTheme } from '@lumx/react/utils/type';
|
|
8
8
|
import { getRootClassName, handleBasicClasses } from '@lumx/react/utils/className';
|
|
9
9
|
|
|
10
|
+
import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
|
|
10
11
|
import { AvatarProps } from '../avatar/Avatar';
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -62,7 +63,6 @@ const CLASSNAME = getRootClassName(COMPONENT_NAME);
|
|
|
62
63
|
const DEFAULT_PROPS: Partial<UserBlockProps> = {
|
|
63
64
|
orientation: Orientation.horizontal,
|
|
64
65
|
size: Size.m,
|
|
65
|
-
theme: Theme.light,
|
|
66
66
|
};
|
|
67
67
|
|
|
68
68
|
/**
|
|
@@ -73,6 +73,7 @@ const DEFAULT_PROPS: Partial<UserBlockProps> = {
|
|
|
73
73
|
* @return React element.
|
|
74
74
|
*/
|
|
75
75
|
export const UserBlock: Comp<UserBlockProps, HTMLDivElement> = forwardRef((props, ref) => {
|
|
76
|
+
const defaultTheme = useTheme() || Theme.light;
|
|
76
77
|
const {
|
|
77
78
|
avatarProps,
|
|
78
79
|
className,
|
|
@@ -88,7 +89,7 @@ export const UserBlock: Comp<UserBlockProps, HTMLDivElement> = forwardRef((props
|
|
|
88
89
|
orientation,
|
|
89
90
|
simpleAction,
|
|
90
91
|
size,
|
|
91
|
-
theme,
|
|
92
|
+
theme = defaultTheme,
|
|
92
93
|
...forwardedProps
|
|
93
94
|
} = props;
|
|
94
95
|
let componentSize = size;
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useTheme } from '@lumx/react/utils/theme/ThemeContext';
|
|
3
|
+
|
|
4
|
+
const TEST_ID = 'theme-sentinel';
|
|
5
|
+
|
|
6
|
+
/** Test component used as sentinel to detect the value of the theme context */
|
|
7
|
+
export function ThemeSentinel() {
|
|
8
|
+
const theme = useTheme();
|
|
9
|
+
return <div data-testid={TEST_ID} className={`--theme-${theme}`} />;
|
|
10
|
+
}
|
|
11
|
+
ThemeSentinel.testId = TEST_ID;
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import isEmpty from 'lodash/isEmpty';
|
|
2
|
+
|
|
3
|
+
import { GenericProps } from '@lumx/react/utils/type';
|
|
4
|
+
import { queryByClassName } from '@lumx/react/testing/utils/queries';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { Theme } from '@lumx/react';
|
|
7
|
+
import { RenderOptions } from '@testing-library/react';
|
|
8
|
+
import { ThemeProvider } from '@lumx/react/utils/theme/ThemeContext';
|
|
9
|
+
import castArray from 'lodash/castArray';
|
|
10
|
+
import { invertTheme } from '@lumx/react/utils/theme/invertTheme';
|
|
11
|
+
|
|
12
|
+
interface CommonSetup {
|
|
13
|
+
props: GenericProps;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type AffectConfig<E> = { element: E; classModifier?: 'color' | 'theme'; inverted?: boolean };
|
|
17
|
+
type Not<E> = { not: E };
|
|
18
|
+
|
|
19
|
+
interface Options<S extends CommonSetup> {
|
|
20
|
+
baseClassName: string;
|
|
21
|
+
forwardClassName?: keyof S;
|
|
22
|
+
forwardAttributes?: keyof S;
|
|
23
|
+
forwardRef?: keyof S;
|
|
24
|
+
applyTheme?: {
|
|
25
|
+
/** Element(s) to which we apply the theme class */
|
|
26
|
+
affects: Array<AffectConfig<keyof S> | Not<AffectConfig<keyof S>>>;
|
|
27
|
+
/** Apply theme via theme prop */
|
|
28
|
+
viaProp: boolean;
|
|
29
|
+
/** Apply theme via theme context */
|
|
30
|
+
viaContext: boolean;
|
|
31
|
+
/** Apply a default theme if no prop or context was provided */
|
|
32
|
+
defaultTheme?: Theme;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type SetupRenderOptions = { wrapper?: RenderOptions['wrapper'] };
|
|
37
|
+
export type SetupFunction<S extends CommonSetup> = (
|
|
38
|
+
props?: GenericProps,
|
|
39
|
+
options?: SetupRenderOptions,
|
|
40
|
+
) => S | Promise<S>;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Common tests on components
|
|
44
|
+
* - Check base class name and class name forwarding
|
|
45
|
+
* - Check props forwarding
|
|
46
|
+
*/
|
|
47
|
+
export function commonTestsSuiteRTL<S extends CommonSetup>(setup: SetupFunction<S>, options: Options<S>): void {
|
|
48
|
+
if (isEmpty(options)) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const { baseClassName, forwardClassName, forwardAttributes, forwardRef, applyTheme } = options;
|
|
52
|
+
describe('Common tests suite', () => {
|
|
53
|
+
it('should render with base class name', async () => {
|
|
54
|
+
await setup();
|
|
55
|
+
expect(queryByClassName(document.body, baseClassName)).toBeInTheDocument();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
if (forwardClassName) {
|
|
59
|
+
it('should forward any CSS class', async () => {
|
|
60
|
+
const modifiedProps = {
|
|
61
|
+
className: 'component component--is-tested',
|
|
62
|
+
};
|
|
63
|
+
const wrappers = await setup(modifiedProps);
|
|
64
|
+
expect(wrappers[forwardClassName]).toHaveClass(modifiedProps.className);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (forwardAttributes) {
|
|
69
|
+
it('should forward any other prop', async () => {
|
|
70
|
+
const modifiedProps = {
|
|
71
|
+
winter: 'is coming',
|
|
72
|
+
};
|
|
73
|
+
const wrappers = await setup(modifiedProps);
|
|
74
|
+
expect(wrappers[forwardAttributes]).toHaveAttribute('winter', modifiedProps.winter);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (forwardRef) {
|
|
79
|
+
it('should forward ref', async () => {
|
|
80
|
+
const ref = React.createRef();
|
|
81
|
+
const wrappers = await setup({ ref });
|
|
82
|
+
expect(ref.current).toBe(wrappers[forwardRef]);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (applyTheme) {
|
|
87
|
+
describe('theme', () => {
|
|
88
|
+
const { affects, defaultTheme, viaProp, viaContext } = applyTheme;
|
|
89
|
+
const testElements = affects.map((configOrNot) => {
|
|
90
|
+
let shouldHaveModifier: boolean = true;
|
|
91
|
+
let config: AffectConfig<any>;
|
|
92
|
+
if ('not' in configOrNot) {
|
|
93
|
+
shouldHaveModifier = false;
|
|
94
|
+
config = configOrNot.not;
|
|
95
|
+
} else config = configOrNot;
|
|
96
|
+
|
|
97
|
+
const {
|
|
98
|
+
element,
|
|
99
|
+
classModifier = 'theme',
|
|
100
|
+
inverted = false,
|
|
101
|
+
}: AffectConfig<any> = typeof config === 'object' ? config : { element: config };
|
|
102
|
+
return {
|
|
103
|
+
element,
|
|
104
|
+
getExpectedClassModifier: (theme: Theme) =>
|
|
105
|
+
`--${classModifier}-${inverted ? invertTheme(theme) : theme}`,
|
|
106
|
+
shouldHaveModifier,
|
|
107
|
+
apply: shouldHaveModifier ? 'apply' : 'not apply',
|
|
108
|
+
};
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const expectTheme = (
|
|
112
|
+
wrappers: any,
|
|
113
|
+
{ element, getExpectedClassModifier, shouldHaveModifier }: any,
|
|
114
|
+
theme: Theme,
|
|
115
|
+
override: { shouldHaveModifier?: boolean } = {},
|
|
116
|
+
) => {
|
|
117
|
+
for (const wrapper of castArray(wrappers[element])) {
|
|
118
|
+
let expected: any = expect(wrapper.className);
|
|
119
|
+
if (override.shouldHaveModifier === false || !shouldHaveModifier) {
|
|
120
|
+
expected = expected.not;
|
|
121
|
+
}
|
|
122
|
+
expected.toContain(getExpectedClassModifier(theme));
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
if (defaultTheme) {
|
|
127
|
+
it.each(testElements)(
|
|
128
|
+
`should $apply default theme (${defaultTheme}) to \`$element\``,
|
|
129
|
+
async (affectedElement) => {
|
|
130
|
+
const wrappers = await setup();
|
|
131
|
+
expectTheme(wrappers, affectedElement, defaultTheme);
|
|
132
|
+
},
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Only the elements that are affected by theme
|
|
137
|
+
const affectedElements = testElements.filter((e) => e.shouldHaveModifier);
|
|
138
|
+
if (!defaultTheme && affectedElements.length) {
|
|
139
|
+
it.each(affectedElements)(
|
|
140
|
+
`should not apply default theme (${defaultTheme}) to \`$element\``,
|
|
141
|
+
async (affectedElement) => {
|
|
142
|
+
const wrappers = await setup();
|
|
143
|
+
expectTheme(wrappers, affectedElement, Theme.light, { shouldHaveModifier: false });
|
|
144
|
+
expectTheme(wrappers, affectedElement, Theme.dark, { shouldHaveModifier: false });
|
|
145
|
+
},
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (viaProp) {
|
|
150
|
+
const theme = invertTheme(defaultTheme || Theme.light);
|
|
151
|
+
it.each(testElements)(
|
|
152
|
+
`should $apply prop theme=${theme} to \`$element\``,
|
|
153
|
+
async (affectedElement) => {
|
|
154
|
+
const wrappers = await setup({ theme });
|
|
155
|
+
expectTheme(wrappers, affectedElement, theme);
|
|
156
|
+
},
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const contextTheme = invertTheme(defaultTheme || Theme.light);
|
|
161
|
+
it.each(testElements)(
|
|
162
|
+
`should $apply context theme=${contextTheme} to \`$element\``,
|
|
163
|
+
async (affectedElement) => {
|
|
164
|
+
const Wrapper = ({ children }: any) => (
|
|
165
|
+
<ThemeProvider value={contextTheme}>{children}</ThemeProvider>
|
|
166
|
+
);
|
|
167
|
+
const wrappers = await setup({}, { wrapper: Wrapper });
|
|
168
|
+
expectTheme(wrappers, affectedElement, contextTheme, {
|
|
169
|
+
shouldHaveModifier: !viaContext ? false : undefined,
|
|
170
|
+
});
|
|
171
|
+
},
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
if (viaProp && viaContext) {
|
|
175
|
+
const propTheme = invertTheme(contextTheme);
|
|
176
|
+
it.each(testElements)(
|
|
177
|
+
`should $apply prop theme=${propTheme} to \`$element\` overriding the context theme=${contextTheme}`,
|
|
178
|
+
async (affectedElement) => {
|
|
179
|
+
const Wrapper = ({ children }: any) => (
|
|
180
|
+
<ThemeProvider value={contextTheme}>{children}</ThemeProvider>
|
|
181
|
+
);
|
|
182
|
+
const wrappers = await setup({ theme: propTheme }, { wrapper: Wrapper });
|
|
183
|
+
expectTheme(wrappers, affectedElement, propTheme);
|
|
184
|
+
},
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Theme } from '@lumx/react';
|
|
3
|
+
|
|
4
|
+
type ThemeContextValue = Theme | undefined;
|
|
5
|
+
export const ThemeContext = React.createContext<ThemeContextValue>(undefined);
|
|
6
|
+
|
|
7
|
+
/** Provide a theme context to all children. */
|
|
8
|
+
export const ThemeProvider = ThemeContext.Provider as React.FC<{
|
|
9
|
+
value: ThemeContextValue;
|
|
10
|
+
children?: React.ReactNode;
|
|
11
|
+
}>;
|
|
12
|
+
|
|
13
|
+
/** Get the theme in the current context. */
|
|
14
|
+
export function useTheme(): ThemeContextValue {
|
|
15
|
+
return React.useContext(ThemeContext);
|
|
16
|
+
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import isEmpty from 'lodash/isEmpty';
|
|
2
|
-
|
|
3
|
-
import { GenericProps } from '@lumx/react/utils/type';
|
|
4
|
-
import { queryByClassName } from '@lumx/react/testing/utils/queries';
|
|
5
|
-
import React from 'react';
|
|
6
|
-
|
|
7
|
-
interface CommonSetup {
|
|
8
|
-
props: GenericProps;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
interface Options<S extends CommonSetup> {
|
|
12
|
-
baseClassName: string;
|
|
13
|
-
forwardClassName?: keyof S;
|
|
14
|
-
forwardAttributes?: keyof S;
|
|
15
|
-
forwardRef?: keyof S;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
type SetupFunction<S extends CommonSetup> = (props?: GenericProps) => S | Promise<S>;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Common tests on components
|
|
22
|
-
* - Check base class name and class name forwarding
|
|
23
|
-
* - Check props forwarding
|
|
24
|
-
*/
|
|
25
|
-
export function commonTestsSuiteRTL<S extends CommonSetup>(setup: SetupFunction<S>, options: Options<S>): void {
|
|
26
|
-
if (isEmpty(options)) {
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
const { baseClassName, forwardClassName, forwardAttributes, forwardRef } = options;
|
|
30
|
-
describe('Common tests suite', () => {
|
|
31
|
-
it('should render with base class name', async () => {
|
|
32
|
-
await setup();
|
|
33
|
-
expect(queryByClassName(document.body, baseClassName)).toBeInTheDocument();
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
if (forwardClassName) {
|
|
37
|
-
it('should forward any CSS class', async () => {
|
|
38
|
-
const modifiedProps = {
|
|
39
|
-
className: 'component component--is-tested',
|
|
40
|
-
};
|
|
41
|
-
const wrappers = await setup(modifiedProps);
|
|
42
|
-
expect(wrappers[forwardClassName]).toHaveClass(modifiedProps.className);
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (forwardAttributes) {
|
|
47
|
-
it('should forward any other prop', async () => {
|
|
48
|
-
const modifiedProps = {
|
|
49
|
-
winter: 'is coming',
|
|
50
|
-
};
|
|
51
|
-
const wrappers = await setup(modifiedProps);
|
|
52
|
-
expect(wrappers[forwardAttributes]).toHaveAttribute('winter', modifiedProps.winter);
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (forwardRef) {
|
|
57
|
-
it('should forward ref', async () => {
|
|
58
|
-
const ref = React.createRef();
|
|
59
|
-
const wrappers = await setup({ ref });
|
|
60
|
-
expect(ref.current).toBe(wrappers[forwardRef]);
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
}
|