From 6c344b8de1c71abca7669bc8825cd3c3e7283bea Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Fri, 3 Oct 2025 11:48:45 +0530 Subject: [PATCH 1/9] [unit-testing] working on theme config testing --- package.json | 3 +- .../__test__/Card.test.tsx | 46 ----- .../__test__/Dialog.test.tsx | 158 ---------------- .../__test__/Divider.test.tsx | 54 +++++- .../__test__/Text.test.tsx | 169 ------------------ .../__test__/__snapshots__/Card.test.tsx.snap | 2 - .../__snapshots__/Divider.test.tsx.snap | 20 +-- .../examples/Alert.tsx | 2 +- .../src/components/Card/Card.tsx | 9 +- .../src/components/Card/CardHeader.tsx | 4 +- .../src/components/Divider/Divider.styles.ts | 11 +- .../SegmentedControl.styles.ts | 3 - .../SegmentedControl/SegmentedControlItem.tsx | 8 +- .../src/components/Typography/Text.styles.ts | 8 +- .../src/components/Typography/Text.tsx | 21 +-- .../src/components/Typography/Text.types.d.ts | 5 - .../libraries/themes/__test__/hooks.test.tsx | 50 +----- .../src/libraries/themes/hooks.ts | 11 -- .../src/libraries/themes/theme.d.ts | 10 +- 19 files changed, 76 insertions(+), 518 deletions(-) diff --git a/package.json b/package.json index 8c9c425..cd93ee1 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ "lint": "eslint .", "start": "react-native start", "test": "jest --coverage", - "sonar-scanner": "sonar-scanner" + "sonar-scanner": "sonar-scanner", + "type-check": "npx tsc --noEmit" }, "dependencies": { "lodash": "^4.17.21", diff --git a/src/packages/react-native-material-elements/__test__/Card.test.tsx b/src/packages/react-native-material-elements/__test__/Card.test.tsx index 5f0bff6..9ab885b 100644 --- a/src/packages/react-native-material-elements/__test__/Card.test.tsx +++ b/src/packages/react-native-material-elements/__test__/Card.test.tsx @@ -43,29 +43,6 @@ describe('Card Component', () => { expect(flattenedStyle.borderWidth).toEqual(0.5); expect(flattenedStyle.borderColor).toEqual(gray[500]); }); - - it('should apply the root style', () => { - const { getByTestId } = testRenderer( - - - , - ); - const card = getByTestId(mockCardTestId); - const flattenedStyle = StyleSheet.flatten(card.props.style); - expect(flattenedStyle.backgroundColor).toEqual('red'); - }); - - it('should combine the root style and component style', () => { - const { getByTestId } = testRenderer( - - - , - ); - const card = getByTestId(mockCardTestId); - const flattenedStyle = StyleSheet.flatten(card.props.style); - expect(flattenedStyle.backgroundColor).toEqual('red'); - expect(flattenedStyle.borderWidth).toEqual(2); - }); }); describe('CardHeader Component', () => { @@ -98,29 +75,6 @@ describe('CardHeader Component', () => { const flattenedStyle = StyleSheet.flatten(cardHeader.props.style); expect(flattenedStyle.backgroundColor).toEqual('red'); }); - - it('should apply the root style', () => { - const { getByTestId } = testRenderer( - - - , - ); - const cardHeader = getByTestId(mockCardHeaderTestId); - const flattenedStyle = StyleSheet.flatten(cardHeader.props.style); - expect(flattenedStyle.backgroundColor).toEqual('red'); - }); - - it('should combine the root style and component style', () => { - const { getByTestId } = testRenderer( - - - , - ); - const cardHeader = getByTestId(mockCardHeaderTestId); - const flattenedStyle = StyleSheet.flatten(cardHeader.props.style); - expect(flattenedStyle.backgroundColor).toEqual('red'); - expect(flattenedStyle.borderWidth).toEqual(2); - }); }); describe('CardContent Component', () => { diff --git a/src/packages/react-native-material-elements/__test__/Dialog.test.tsx b/src/packages/react-native-material-elements/__test__/Dialog.test.tsx index efb09c0..aa26a8b 100644 --- a/src/packages/react-native-material-elements/__test__/Dialog.test.tsx +++ b/src/packages/react-native-material-elements/__test__/Dialog.test.tsx @@ -300,164 +300,6 @@ const textTests = (Component: any, componentName: string) => { expect(caughtError?.message).toContain('maxLength props must be used with string'); }); - it('should apply the gutterBottomSpace property from theme provider', () => { - const { getByTestId } = testingRenderer( - - - Mock label - - , - ); - const text = getByTestId(mockTestId); - expect(text.props.style).toEqual(expect.objectContaining({ marginBottom: 20 })); - }); - - it('should override the root gutterBottomSpace property', () => { - const { getByTestId } = testingRenderer( - - - Mock label - - , - ); - const text = getByTestId(mockTestId); - expect(text.props.style).toEqual(expect.objectContaining({ marginBottom: 10 })); - }); - - it('should apply the maxLength property from theme provider', () => { - const { getByText } = testingRenderer( - - Sample Text - , - ); - expect(getByText('Sample Tex...')).toBeTruthy(); - }); - - it('should override the root maxLength property', () => { - const { getByText } = testingRenderer( - - Sample Text - , - ); - expect(getByText('Sampl...')).toBeTruthy(); - }); - - it('should apply the root errorColor property', () => { - const { getByTestId } = testingRenderer( - - - Sample Text - - , - ); - - const text = getByTestId(mockTestId); - expect(text.props.style).toEqual(expect.objectContaining({ color: 'green' })); - }); - - it('should override the root errorColor property', () => { - const { getByTestId } = testingRenderer( - - - Sample Text - - , - ); - - const text = getByTestId(mockTestId); - expect(text.props.style).toEqual(expect.objectContaining({ color: 'red' })); - }); - - it('should apply the root activeColor property', () => { - const { getByTestId } = testingRenderer( - - - Sample Text - - , - ); - - const text = getByTestId(mockTestId); - expect(text.props.style).toEqual(expect.objectContaining({ color: 'green' })); - }); - - it('should override the root activeColor property', () => { - const { getByTestId } = testingRenderer( - - - Sample Text - - , - ); - - const text = getByTestId(mockTestId); - expect(text.props.style).toEqual(expect.objectContaining({ color: 'red' })); - }); - - it('should override the root color property', () => { - const { getByTestId } = testingRenderer( - - - Sample Text - - , - ); - - const text = getByTestId(mockTestId); - expect(text.props.style).toEqual(expect.objectContaining({ color: 'red' })); - }); - - it('should apply the root styles', () => { - const { getByTestId } = testingRenderer( - - Sample text - , - ); - - const text = getByTestId(mockTestId); - expect(text.props.style).toEqual( - expect.objectContaining({ - fontSize: 20, - fontWeight: 'bold', - }), - ); - }); - - it('should merge the root styles and component styles', () => { - const { getByTestId } = testingRenderer( - - - Sample text - - , - ); - - const text = getByTestId(mockTestId); - expect(text.props.style).toEqual( - expect.objectContaining({ - fontSize: 20, - fontWeight: 'bold', - color: 'green', - }), - ); - }); - Object.entries(themeVariants).forEach(([variant, expectedStyle]) => { it(`should apply the '${variant}' text theme variant`, () => { const { getByTestId } = render( diff --git a/src/packages/react-native-material-elements/__test__/Divider.test.tsx b/src/packages/react-native-material-elements/__test__/Divider.test.tsx index b07baa3..325d0eb 100644 --- a/src/packages/react-native-material-elements/__test__/Divider.test.tsx +++ b/src/packages/react-native-material-elements/__test__/Divider.test.tsx @@ -1,7 +1,7 @@ import { render as testRenderer, waitFor } from '@testing-library/react-native'; import React from 'react'; -import { StyleSheet, View } from 'react-native'; -import { Divider, Text, ThemeProvider } from '../src'; +import { StyleSheet, useColorScheme, View } from 'react-native'; +import { Divider, gray, Text, ThemeProvider } from '../src'; import { spacing } from '../src/libraries/themes/v1/sizes'; import { render } from './test-utils'; @@ -9,7 +9,6 @@ describe('Divider Component', () => { const dividerMockTestId = 'divide-test-id'; const dividerStartLineTestId = 'divide-start-line-test-id'; const dividerEndLineTestId = 'divide-end-line-test-id'; - const mockTestLabel = 'test-label'; const mockRef = React.createRef(); @@ -251,4 +250,53 @@ describe('Divider Component', () => { expect(flattenedStyle.borderWidth).toEqual(2); expect(flattenedStyle.backgroundColor).toEqual('red'); }); + + it('should show smooth light background when theme mode is dark', () => { + (useColorScheme as jest.Mock).mockReturnValue('dark'); + const { getByTestId } = render(); + + const startLine = getByTestId(dividerStartLineTestId); + const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: gray[700] })); + + const endLine = getByTestId(dividerEndLineTestId); + const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: gray[700] })); + }); + + it('should show smooth dark background when theme mode is light', () => { + (useColorScheme as jest.Mock).mockReturnValue('light'); + const { getByTestId } = render(); + + const startLine = getByTestId(dividerStartLineTestId); + const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: gray[400] })); + + const endLine = getByTestId(dividerEndLineTestId); + const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: gray[400] })); + }); + + it('should render child component', () => { + const { getByText } = render( + + Hello + , + ); + + const text = getByText('Hello'); + expect(text).toBeDefined(); + }); + + it('should apply the spacing between start line child component and end line', () => { + const { getByTestId } = render( + + Hello + , + ); + + const divider = getByTestId(dividerMockTestId); + const flattenStyles = StyleSheet.flatten(divider.props.style); + expect(flattenStyles).toEqual(expect.objectContaining({ gap: 10 })); + }); }); diff --git a/src/packages/react-native-material-elements/__test__/Text.test.tsx b/src/packages/react-native-material-elements/__test__/Text.test.tsx index 88fcfb7..74de8c8 100644 --- a/src/packages/react-native-material-elements/__test__/Text.test.tsx +++ b/src/packages/react-native-material-elements/__test__/Text.test.tsx @@ -218,175 +218,6 @@ describe('Text Component', () => { expect(caughtError?.message).toContain('maxLength props must be used with string'); }); - it('should apply the gutterBottomSpace property from theme provider', () => { - const { getByTestId } = testingRenderer( - - - Mock label - - , - ); - const text = getByTestId(mockTestId); - expect(text.props.style).toEqual(expect.objectContaining({ marginBottom: 20 })); - }); - - it('should override the root gutterBottomSpace property', () => { - const { getByTestId } = testingRenderer( - - - Mock label - - , - ); - const text = getByTestId(mockTestId); - expect(text.props.style).toEqual(expect.objectContaining({ marginBottom: 10 })); - }); - - it('should apply the maxLength property from theme provider', () => { - const { getByText } = testingRenderer( - - Sample Text - , - ); - expect(getByText('Sample Tex...')).toBeTruthy(); - }); - - it('should override the root maxLength property', () => { - const { getByText } = testingRenderer( - - Sample Text - , - ); - expect(getByText('Sampl...')).toBeTruthy(); - }); - - it('should apply the root errorColor property', () => { - const { getByTestId } = testingRenderer( - - - Sample Text - - , - ); - - const text = getByTestId(mockTestId); - expect(text.props.style).toEqual(expect.objectContaining({ color: 'green' })); - }); - - it('should override the root errorColor property', () => { - const { getByTestId } = testingRenderer( - - - Sample Text - - , - ); - - const text = getByTestId(mockTestId); - expect(text.props.style).toEqual(expect.objectContaining({ color: 'red' })); - }); - - it('should apply the root activeColor property', () => { - const { getByTestId } = testingRenderer( - - - Sample Text - - , - ); - - const text = getByTestId(mockTestId); - expect(text.props.style).toEqual(expect.objectContaining({ color: 'green' })); - }); - - it('should override the root activeColor property', () => { - const { getByTestId } = testingRenderer( - - - Sample Text - - , - ); - - const text = getByTestId(mockTestId); - expect(text.props.style).toEqual(expect.objectContaining({ color: 'red' })); - }); - - it('should apply the root color property', () => { - const { getByTestId } = testingRenderer( - - Sample Text - , - ); - - const text = getByTestId(mockTestId); - expect(text.props.style).toEqual(expect.objectContaining({ color: 'green' })); - }); - - it('should override the root color property', () => { - const { getByTestId } = testingRenderer( - - - Sample Text - - , - ); - - const text = getByTestId(mockTestId); - expect(text.props.style).toEqual(expect.objectContaining({ color: 'red' })); - }); - - it('should apply the root styles', () => { - const { getByTestId } = testingRenderer( - - Sample text - , - ); - - const text = getByTestId(mockTestId); - expect(text.props.style).toEqual( - expect.objectContaining({ - fontSize: 20, - fontWeight: 'bold', - }), - ); - }); - - it('should merge the root styles and component styles', () => { - const { getByTestId } = testingRenderer( - - - Sample text - - , - ); - - const text = getByTestId(mockTestId); - expect(text.props.style).toEqual( - expect.objectContaining({ - fontSize: 20, - fontWeight: 'bold', - color: 'green', - }), - ); - }); - Object.entries(themeVariants).forEach(([variant, expectedStyle]) => { it(`should apply the '${variant}' text theme variant`, () => { const { getByTestId } = render( diff --git a/src/packages/react-native-material-elements/__test__/__snapshots__/Card.test.tsx.snap b/src/packages/react-native-material-elements/__test__/__snapshots__/Card.test.tsx.snap index 6eceae4..fc0777e 100644 --- a/src/packages/react-native-material-elements/__test__/__snapshots__/Card.test.tsx.snap +++ b/src/packages/react-native-material-elements/__test__/__snapshots__/Card.test.tsx.snap @@ -7,7 +7,6 @@ exports[`Card Component should render correctly 1`] = ` {}, {}, [ - undefined, undefined, {}, undefined, @@ -198,7 +197,6 @@ exports[`CardHeader Component should render correctly 1`] = ` {}, {}, [ - undefined, {}, undefined, ], diff --git a/src/packages/react-native-material-elements/__test__/__snapshots__/Divider.test.tsx.snap b/src/packages/react-native-material-elements/__test__/__snapshots__/Divider.test.tsx.snap index 0595078..200e700 100644 --- a/src/packages/react-native-material-elements/__test__/__snapshots__/Divider.test.tsx.snap +++ b/src/packages/react-native-material-elements/__test__/__snapshots__/Divider.test.tsx.snap @@ -23,12 +23,11 @@ exports[`Divider Component should render correctly 1`] = ` style={ [ { - "borderWidth": 0.5, + "borderBottomWidth": 0.5, + "borderTopWidth": 0.5, }, { "borderColor": "#616161", - "borderEndWidth": 0, - "borderStartWidth": 0, "flex": 1, }, undefined, @@ -40,12 +39,11 @@ exports[`Divider Component should render correctly 1`] = ` style={ [ { - "borderWidth": 0.5, + "borderBottomWidth": 0.5, + "borderTopWidth": 0.5, }, { "borderColor": "#616161", - "borderEndWidth": 0, - "borderStartWidth": 0, "flex": 1, }, undefined, @@ -79,12 +77,11 @@ exports[`Divider Component should render the children correctly 1`] = ` style={ [ { - "borderWidth": 0.5, + "borderBottomWidth": 0.5, + "borderTopWidth": 0.5, }, { "borderColor": "#616161", - "borderEndWidth": 0, - "borderStartWidth": 0, "flex": 1, }, undefined, @@ -102,12 +99,11 @@ exports[`Divider Component should render the children correctly 1`] = ` style={ [ { - "borderWidth": 0.5, + "borderBottomWidth": 0.5, + "borderTopWidth": 0.5, }, { "borderColor": "#616161", - "borderEndWidth": 0, - "borderStartWidth": 0, "flex": 1, }, undefined, diff --git a/src/packages/react-native-material-elements/examples/Alert.tsx b/src/packages/react-native-material-elements/examples/Alert.tsx index 146aa8a..4f0658b 100644 --- a/src/packages/react-native-material-elements/examples/Alert.tsx +++ b/src/packages/react-native-material-elements/examples/Alert.tsx @@ -15,7 +15,7 @@ function App(): React.JSX.Element { label="UNDO" labelColor={'white'} variation="text" - baseButtonStyles={{ paddingTop: 4, paddingBottom: 4 }} + style={{ paddingTop: 4, paddingBottom: 4 }} onPress={() => {}} square /> diff --git a/src/packages/react-native-material-elements/src/components/Card/Card.tsx b/src/packages/react-native-material-elements/src/components/Card/Card.tsx index 973f894..e519038 100644 --- a/src/packages/react-native-material-elements/src/components/Card/Card.tsx +++ b/src/packages/react-native-material-elements/src/components/Card/Card.tsx @@ -1,22 +1,17 @@ import React from 'react'; import { View } from 'react-native'; import { useRestyle } from '../../hooks'; -import { useThemeCardConfigSelector, useThemeColorsSelector } from '../../libraries'; +import { useThemeColorsSelector } from '../../libraries'; import { Box } from '../Box'; import { cardVariation } from './Card.styles'; import { CardProps } from './Card.types'; export const Card = React.forwardRef(({ children, variation, style, sx, ...props }, ref) => { const themeColors = useThemeColorsSelector(); - const cardThemeConfig = useThemeCardConfigSelector(); const { getStyleFromProps } = useRestyle(props); return ( - + {children} ); diff --git a/src/packages/react-native-material-elements/src/components/Card/CardHeader.tsx b/src/packages/react-native-material-elements/src/components/Card/CardHeader.tsx index 247a325..28fbd18 100644 --- a/src/packages/react-native-material-elements/src/components/Card/CardHeader.tsx +++ b/src/packages/react-native-material-elements/src/components/Card/CardHeader.tsx @@ -1,16 +1,14 @@ import React from 'react'; import { View } from 'react-native'; import { useRestyle } from '../../hooks'; -import { useThemeCardHeaderConfigSelector } from '../../libraries'; import { Box } from '../Box'; import { CardHeaderProps } from './Card.types'; export const CardHeader = React.forwardRef(({ children, sx, style, ...props }, ref) => { - const cardHeaderThemeConfig = useThemeCardHeaderConfigSelector(); const { getStyleFromProps } = useRestyle(props); return ( - + {children} ); diff --git a/src/packages/react-native-material-elements/src/components/Divider/Divider.styles.ts b/src/packages/react-native-material-elements/src/components/Divider/Divider.styles.ts index 6f0f210..a2360d4 100644 --- a/src/packages/react-native-material-elements/src/components/Divider/Divider.styles.ts +++ b/src/packages/react-native-material-elements/src/components/Divider/Divider.styles.ts @@ -10,7 +10,8 @@ export const styles = StyleSheet.create({ alignItems: 'center', }, line: { - borderWidth: 0.5, + borderTopWidth: 0.5, + borderBottomWidth: 0.5, }, }); @@ -52,14 +53,6 @@ export const dividerLineStyles = ({ break; } - if (isStartLine) { - baseStyles.borderEndWidth = 0; - baseStyles.borderStartWidth = 0; - } else { - baseStyles.borderStartWidth = 0; - baseStyles.borderEndWidth = 0; - } - return baseStyles; }; diff --git a/src/packages/react-native-material-elements/src/components/SegmentedControl/SegmentedControl.styles.ts b/src/packages/react-native-material-elements/src/components/SegmentedControl/SegmentedControl.styles.ts index 242b032..584bc78 100644 --- a/src/packages/react-native-material-elements/src/components/SegmentedControl/SegmentedControl.styles.ts +++ b/src/packages/react-native-material-elements/src/components/SegmentedControl/SegmentedControl.styles.ts @@ -16,9 +16,6 @@ export const styles = StyleSheet.create({ flex: 1, position: 'relative', }, - item: { - flex: 1, - }, baseButton: { flex: 1, height: '100%', diff --git a/src/packages/react-native-material-elements/src/components/SegmentedControl/SegmentedControlItem.tsx b/src/packages/react-native-material-elements/src/components/SegmentedControl/SegmentedControlItem.tsx index ac705bc..35a1bd2 100644 --- a/src/packages/react-native-material-elements/src/components/SegmentedControl/SegmentedControlItem.tsx +++ b/src/packages/react-native-material-elements/src/components/SegmentedControl/SegmentedControlItem.tsx @@ -71,13 +71,7 @@ export const SegmentedControlItem = ({ }, [data, headingStyles, segmentItemContainerStyles]); return ( - + {renderValue()} ); diff --git a/src/packages/react-native-material-elements/src/components/Typography/Text.styles.ts b/src/packages/react-native-material-elements/src/components/Typography/Text.styles.ts index 9eac2d0..5657676 100644 --- a/src/packages/react-native-material-elements/src/components/Typography/Text.styles.ts +++ b/src/packages/react-native-material-elements/src/components/Typography/Text.styles.ts @@ -25,9 +25,7 @@ export const generateTextStyles = ({ let baseColor: ColorValue | undefined; - if (themeComponentConfig?.color) { - baseColor = themeComponentConfig.color; - } else if (textThemeMode === 'light' || (!textThemeMode && themeMode === 'dark')) { + if (textThemeMode === 'light' || (!textThemeMode && themeMode === 'dark')) { baseColor = 'white'; } else if (textThemeMode === 'dark') { baseColor = 'black'; @@ -73,8 +71,6 @@ export const generateTextStyles = ({ if (activeColor) { textActiveColor = activeColor; - } else if (themeComponentConfig?.activeColor) { - textActiveColor = themeComponentConfig.activeColor; } else { textActiveColor = secondary[200]; } @@ -83,8 +79,6 @@ export const generateTextStyles = ({ if (errorColor) { textErrorColor = errorColor; - } else if (themeComponentConfig?.errorColor) { - textErrorColor = themeComponentConfig.errorColor; } else { textErrorColor = red[600]; } diff --git a/src/packages/react-native-material-elements/src/components/Typography/Text.tsx b/src/packages/react-native-material-elements/src/components/Typography/Text.tsx index 2bb5bad..2bf1da5 100644 --- a/src/packages/react-native-material-elements/src/components/Typography/Text.tsx +++ b/src/packages/react-native-material-elements/src/components/Typography/Text.tsx @@ -22,7 +22,6 @@ export const Text = React.forwardRef( mode, color, gutterBottomSpace = 10, - overrideRootGutterBottomConfig = false, disabled = false, ...props }, @@ -33,25 +32,16 @@ export const Text = React.forwardRef( const themeMode = useColorScheme(); const { getStyleFromProps } = useRestyle(props); - const hasMaxLength = maxLength ?? themeTextConfig?.maxLength; - - const themeGutterBottomSpace = () => { - if (overrideRootGutterBottomConfig) { - return gutterBottomSpace; - } - return themeTextConfig?.gutterBottomSpace ?? gutterBottomSpace; - }; - const renderedChildren = useMemo(() => { - if (hasMaxLength && typeof children !== 'string') { + if (maxLength && typeof children !== 'string') { throw new Error('maxLength props must be used with string'); } - if (typeof children === 'string' && hasMaxLength) { - return maxLengthUtile(children, hasMaxLength); + if (typeof children === 'string' && maxLength) { + return maxLengthUtile(children, maxLength); } return children; - }, [children, hasMaxLength]); + }, [children, maxLength]); return ( ( generateTextStyles({ variation, gutterBottom, - gutterBottomSpace: themeGutterBottomSpace(), + gutterBottomSpace: gutterBottomSpace, isActive, activeColor, disabled, @@ -73,7 +63,6 @@ export const Text = React.forwardRef( themeFonts: themeFontConfig, themeMode, }), - themeTextConfig?.style, getStyleFromProps(), style, ]} diff --git a/src/packages/react-native-material-elements/src/components/Typography/Text.types.d.ts b/src/packages/react-native-material-elements/src/components/Typography/Text.types.d.ts index 71424d8..55ee76d 100644 --- a/src/packages/react-native-material-elements/src/components/Typography/Text.types.d.ts +++ b/src/packages/react-native-material-elements/src/components/Typography/Text.types.d.ts @@ -41,11 +41,6 @@ export interface TextProps extends React.ComponentPropsWithRef, Sty */ gutterBottomSpace?: number; - /** - * Override the root gutter bottom spacing - */ - overrideRootGutterBottomConfig?: boolean; - /** * Maximum length of the text content. Used for truncating or limiting text length. */ diff --git a/src/packages/react-native-material-elements/src/libraries/themes/__test__/hooks.test.tsx b/src/packages/react-native-material-elements/src/libraries/themes/__test__/hooks.test.tsx index 8a06a83..9e2eabd 100644 --- a/src/packages/react-native-material-elements/src/libraries/themes/__test__/hooks.test.tsx +++ b/src/packages/react-native-material-elements/src/libraries/themes/__test__/hooks.test.tsx @@ -10,9 +10,6 @@ import { useLineHeightSelector, useThemeBadgeConfigSelector, useThemeButtonConfigSelector, - useThemeButtonGroupConfigSelector, - useThemeCardConfigSelector, - useThemeCardHeaderConfigSelector, useThemeCheckBoxConfigSelector, useThemeChipConfigSelector, useThemeColorsSelector, @@ -152,29 +149,6 @@ describe('Theme Hooks', () => { const { result } = renderHook(useThemeTextConfigSelector, { wrapper: ThemeWrapper }); expect(result.current).toEqual(undefined); }); - - it('should return the correct text component configuration from theme provider', () => { - const props: ThemeProviderProps = { - components: { - textProps: { - gutterBottomSpace: 10, - maxLength: 10, - errorColor: 'red', - activeColor: 'green', - color: 'green', - style: { fontWeight: '800', fontSize: 20 }, - }, - }, - children: mockChildren, - }; - - const { result } = renderHook(useThemeTextConfigSelector, { - wrapper: ThemeWrapper, - initialProps: props, - }); - - expect(result.current).toEqual(props.components!.textProps); - }); }); describe('useThemeBadgeConfigSelector', () => { @@ -220,7 +194,7 @@ describe('Theme Hooks', () => { labelColor: 'green', scaleAnimationValue: 100, rippleEdge: 'bottomRight', - baseButtonContainerStyle: { borderWidth: 100 }, + style: { borderWidth: 100 }, rippleProps: { rippleStyles: { backgroundColor: 'red' }, rippleAnimationStyles: { backgroundColor: 'red' }, @@ -253,7 +227,6 @@ describe('Theme Hooks', () => { style: { backgroundColor: 'red' }, disableRipple: true, rippleEdge: 'bottomRight', - baseButtonContainerStyle: { backgroundColor: 'red' }, }, }, children: mockChildren, @@ -268,27 +241,6 @@ describe('Theme Hooks', () => { }); }); - describe('useThemeButtonGroupConfigSelector', () => { - it('Should return undefined for the theme button group component configuration when the theme wrapper does not provide a component config.', () => { - const { result } = renderHook(useThemeButtonGroupConfigSelector, { wrapper: ThemeWrapper }); - expect(result.current).toEqual(undefined); - }); - }); - - describe('useThemeCardConfigSelector', () => { - it('Should return undefined for the theme card component configuration when the theme wrapper does not provide a component config.', () => { - const { result } = renderHook(useThemeCardConfigSelector, { wrapper: ThemeWrapper }); - expect(result.current).toEqual(undefined); - }); - }); - - describe('useThemeCardHeaderConfigSelector', () => { - it('Should return undefined for the theme card header component configuration when the theme wrapper does not provide a component config.', () => { - const { result } = renderHook(useThemeCardHeaderConfigSelector, { wrapper: ThemeWrapper }); - expect(result.current).toEqual(undefined); - }); - }); - describe('useThemeCheckBoxConfigSelector', () => { it('Should return undefined for the theme check box component configuration when the theme wrapper does not provide a component config.', () => { const { result } = renderHook(useThemeCheckBoxConfigSelector, { wrapper: ThemeWrapper }); diff --git a/src/packages/react-native-material-elements/src/libraries/themes/hooks.ts b/src/packages/react-native-material-elements/src/libraries/themes/hooks.ts index cfd948d..9967ae3 100644 --- a/src/packages/react-native-material-elements/src/libraries/themes/hooks.ts +++ b/src/packages/react-native-material-elements/src/libraries/themes/hooks.ts @@ -65,17 +65,6 @@ export const useThemeButtonConfigSelector = () => { export const useThemeIconButtonConfigSelector = () => { return useContextSelector(ThemeContext, values => values?.components?.iconButtonProps); }; -export const useThemeButtonGroupConfigSelector = () => { - return useContextSelector(ThemeContext, values => values?.components?.buttonGroupProps); -}; - -export const useThemeCardConfigSelector = () => { - return useContextSelector(ThemeContext, values => values?.components?.cardProps); -}; -export const useThemeCardHeaderConfigSelector = () => { - return useContextSelector(ThemeContext, values => values?.components?.cardHeaderProps); -}; - export const useThemeCheckBoxConfigSelector = () => { return useContextSelector(ThemeContext, values => values?.components?.checkBoxProps); }; diff --git a/src/packages/react-native-material-elements/src/libraries/themes/theme.d.ts b/src/packages/react-native-material-elements/src/libraries/themes/theme.d.ts index 4fd77d7..244db8e 100644 --- a/src/packages/react-native-material-elements/src/libraries/themes/theme.d.ts +++ b/src/packages/react-native-material-elements/src/libraries/themes/theme.d.ts @@ -1,6 +1,5 @@ import { ColorSchemeName } from 'react-native'; import { - ButtonGroupProps, DividerColorThemeConfig, DividerProps, IconInputProps, @@ -14,8 +13,6 @@ import { BadgeVariationThemeConfig, ButtonProps, ButtonVariations, - CardHeaderProps, - CardProps, CheckBoxProps, CheckBoxVariationThemeConfig, ChipColorThemeConfig, @@ -29,7 +26,6 @@ import { PaginationThemeConfig, TextFieldProps, TextFiledVariation, - TextProps, TextVariationThemeConfig, } from '../../components/types'; import { initialLightTheme } from './v1/colors'; @@ -142,14 +138,10 @@ type ChipVariationConfig = Partial< * These configurations allow for easy styling adjustments for various components. */ export type ThemeComponentConfig = { - textProps: Pick & - TextVariationThemeConfig; + textProps: TextVariationThemeConfig; badgeProps: Pick & BadgeVariationThemeConfig; buttonProps: ButtonThemeConfig & ButtonVariationConfig; iconButtonProps: IconButtonThemeConfig & IconButtonVariationsConfig; - buttonGroupProps: Pick; - cardProps?: Pick; - cardHeaderProps?: Pick; checkBoxProps?: Pick< CheckBoxProps, | 'checkBoxColor' From a7218d1160124930fcce6c3d6b18e7c922f89962 Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sat, 4 Oct 2025 12:48:14 +0530 Subject: [PATCH 2/9] [unit-testing] added theme config text component test cases --- .../__test__/V2ThemeContext.test.tsx | 279 +++++++++++++++++- .../src/components/Typography/Text.styles.ts | 11 + .../src/components/Typography/Text.types.d.ts | 6 +- 3 files changed, 290 insertions(+), 6 deletions(-) diff --git a/src/packages/react-native-material-elements/__test__/V2ThemeContext.test.tsx b/src/packages/react-native-material-elements/__test__/V2ThemeContext.test.tsx index e3a4912..4f691de 100644 --- a/src/packages/react-native-material-elements/__test__/V2ThemeContext.test.tsx +++ b/src/packages/react-native-material-elements/__test__/V2ThemeContext.test.tsx @@ -1,16 +1,18 @@ -import React from 'react'; -import { renderHook } from '@testing-library/react-native'; +import { renderHook, render as themeRender } from '@testing-library/react-native'; +import { StyleSheet } from 'react-native'; import { createColorShades, createTheme, createThemeDimensions, defaultLightTheme, + Text, themeDimensions, ThemeProvider, useTheme, } from '../src'; -import { render, ThemeWrapper } from './test-utils'; import { ThemeInterface, ThemeType } from '../src/libraries/types'; +import { render, ThemeWrapper } from './test-utils'; +import { TextVariationThemeConfig } from '../src/types'; describe('V2ThemeContext', () => { const mockLightColors = { 400: '#000000', '100': '#be3434', '200': '#2f63be' }; @@ -108,4 +110,275 @@ describe('V2ThemeContext', () => { consoleSpy.mockRestore(); }); }); + + describe('ThemeProvider component config', () => { + describe('textProps', () => { + const mockTextThemeConfig: TextVariationThemeConfig = { + body1: { fontSize: 10, fontWeight: '100' }, + body2: { fontSize: 15, fontWeight: '200' }, + h1: { fontSize: 20, fontWeight: '300' }, + h2: { fontSize: 30, fontWeight: '400' }, + h3: { fontSize: 40, fontWeight: '500' }, + h4: { fontSize: 50, fontWeight: '600' }, + h5: { fontSize: 60, fontWeight: '700' }, + h6: { fontSize: 70, fontWeight: '800' }, + }; + + it('should adopted theme text (body1) config', () => { + const { getByText } = themeRender( + + Hello + , + ); + + const text = getByText('Hello'); + const fattenStyles = StyleSheet.flatten(text.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ fontSize: 10, fontWeight: '100' })); + }); + + it('should should override theme text (body1) config', () => { + const { getByText } = themeRender( + + + Hello + + , + ); + + const text = getByText('Hello'); + const fattenStyles = StyleSheet.flatten(text.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ fontSize: 30, fontWeight: 200 })); + }); + + it('should adopted theme text (body2) config', () => { + const { getByText } = themeRender( + + Hello + , + ); + + const text = getByText('Hello'); + const fattenStyles = StyleSheet.flatten(text.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ fontSize: 15, fontWeight: '200' })); + }); + + it('should override theme text (body2) config', () => { + const { getByText } = themeRender( + + + Hello + + , + ); + + const text = getByText('Hello'); + const fattenStyles = StyleSheet.flatten(text.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ fontSize: 29, fontWeight: 300 })); + }); + + it('should adopted theme text (h1) config', () => { + const { getByText } = themeRender( + + Hello + , + ); + + const text = getByText('Hello'); + const fattenStyles = StyleSheet.flatten(text.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ fontSize: 20, fontWeight: '300' })); + }); + + it('should override theme text (h1) config', () => { + const { getByText } = themeRender( + + + Hello + + , + ); + + const text = getByText('Hello'); + const fattenStyles = StyleSheet.flatten(text.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ fontSize: 10, fontWeight: 100 })); + }); + + it('should adopted theme text (h2) config', () => { + const { getByText } = themeRender( + + Hello + , + ); + + const text = getByText('Hello'); + const fattenStyles = StyleSheet.flatten(text.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ fontSize: 30, fontWeight: '400' })); + }); + + it('should override theme text (h2) config', () => { + const { getByText } = themeRender( + + + Hello + + , + ); + + const text = getByText('Hello'); + const fattenStyles = StyleSheet.flatten(text.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ fontSize: 10, fontWeight: 200 })); + }); + + it('should adopted theme text (h3) config', () => { + const { getByText } = themeRender( + + Hello + , + ); + + const text = getByText('Hello'); + const fattenStyles = StyleSheet.flatten(text.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ fontSize: 40, fontWeight: '500' })); + }); + + it('should override theme text (h3) config', () => { + const { getByText } = themeRender( + + + Hello + + , + ); + + const text = getByText('Hello'); + const fattenStyles = StyleSheet.flatten(text.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ fontSize: 10, fontWeight: 200 })); + }); + + it('should adopted theme text (h4) config', () => { + const { getByText } = themeRender( + + Hello + , + ); + + const text = getByText('Hello'); + const fattenStyles = StyleSheet.flatten(text.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ fontSize: 50, fontWeight: '600' })); + }); + + it('should override theme text (h4) config', () => { + const { getByText } = themeRender( + + + Hello + + , + ); + + const text = getByText('Hello'); + const fattenStyles = StyleSheet.flatten(text.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ fontSize: 20, fontWeight: 900 })); + }); + + it('should adopted theme text (h5) config', () => { + const { getByText } = themeRender( + + Hello + , + ); + + const text = getByText('Hello'); + const fattenStyles = StyleSheet.flatten(text.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ fontSize: 60, fontWeight: '700' })); + }); + + it('should override theme text (h5) config', () => { + const { getByText } = themeRender( + + + Hello + + , + ); + + const text = getByText('Hello'); + const fattenStyles = StyleSheet.flatten(text.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ fontSize: 10, fontWeight: 300 })); + }); + + it('should adopted theme text (h6) config', () => { + const { getByText } = themeRender( + + Hello + , + ); + + const text = getByText('Hello'); + const fattenStyles = StyleSheet.flatten(text.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ fontSize: 70, fontWeight: '800' })); + }); + + it('should override theme text (h6) config', () => { + const { getByText } = themeRender( + + + Hello + + , + ); + + const text = getByText('Hello'); + const fattenStyles = StyleSheet.flatten(text.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ fontSize: 20, fontWeight: 200 })); + }); + }); + }); }); diff --git a/src/packages/react-native-material-elements/src/components/Typography/Text.styles.ts b/src/packages/react-native-material-elements/src/components/Typography/Text.styles.ts index 5657676..590d262 100644 --- a/src/packages/react-native-material-elements/src/components/Typography/Text.styles.ts +++ b/src/packages/react-native-material-elements/src/components/Typography/Text.styles.ts @@ -34,34 +34,44 @@ export const generateTextStyles = ({ const textColor = color ?? baseColor; let fontSize: number; + let fontWeight: TextStyle['fontWeight']; switch (variation) { case 'body1': fontSize = themeComponentConfig?.body1?.fontSize ?? themeFonts['text-2xl']; + fontWeight = themeComponentConfig?.body1?.fontWeight; break; case 'body2': fontSize = themeComponentConfig?.body2?.fontSize ?? themeFonts['text-3xl']; + fontWeight = themeComponentConfig?.body2?.fontWeight; break; case 'caption': fontSize = themeComponentConfig?.caption?.fontSize ?? themeFonts['text-sm']; + fontWeight = themeComponentConfig?.caption?.fontWeight; break; case 'h1': fontSize = themeComponentConfig?.h1?.fontSize ?? themeFonts['text-xl']; + fontWeight = themeComponentConfig?.h1?.fontWeight; break; case 'h2': fontSize = themeComponentConfig?.h2?.fontSize ?? themeFonts['text-lg']; + fontWeight = themeComponentConfig?.h2?.fontWeight; break; case 'h3': fontSize = themeComponentConfig?.h3?.fontSize ?? themeFonts['text-md']; + fontWeight = themeComponentConfig?.h3?.fontWeight; break; case 'h4': fontSize = themeComponentConfig?.h4?.fontSize ?? themeFonts['text-sm']; + fontWeight = themeComponentConfig?.h4?.fontWeight; break; case 'h5': fontSize = themeComponentConfig?.h5?.fontSize ?? themeFonts['text-xs']; + fontWeight = themeComponentConfig?.h5?.fontWeight; break; case 'h6': fontSize = themeComponentConfig?.h6?.fontSize ?? themeFonts['text-xxs']; + fontWeight = themeComponentConfig?.h6?.fontWeight; break; default: fontSize = themeFonts['text-sm']; @@ -86,6 +96,7 @@ export const generateTextStyles = ({ return { ...(textColor && { color: textColor }), ...(variation && { fontSize }), + ...(fontWeight && { fontWeight }), ...(gutterBottom && gutter('marginBottom', gutterBottomSpace)), ...(isActive && { color: textActiveColor }), ...(disabled && { opacity: 0.3 }), diff --git a/src/packages/react-native-material-elements/src/components/Typography/Text.types.d.ts b/src/packages/react-native-material-elements/src/components/Typography/Text.types.d.ts index 55ee76d..3c5fc27 100644 --- a/src/packages/react-native-material-elements/src/components/Typography/Text.types.d.ts +++ b/src/packages/react-native-material-elements/src/components/Typography/Text.types.d.ts @@ -1,5 +1,5 @@ import React from 'react'; -import { ColorSchemeName, ColorValue, Text } from 'react-native'; +import { ColorSchemeName, ColorValue, Text, TextStyle } from 'react-native'; import { BaseStyles, ElementTextStyleProps, StyledProps } from '../../libraries/style/styleTypes'; import { ThemeDimensions, WithThemeComponentConfig } from '../../libraries/themes/theme'; /** @@ -8,8 +8,8 @@ import { ThemeDimensions, WithThemeComponentConfig } from '../../libraries/theme */ export type TextVariation = 'body1' | 'body2' | 'caption' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; -type TextFontSize = { fontSize: number }; -export type TextVariationThemeConfig = Partial>; +type TextFontConfig = { fontSize: number; fontWeight?: TextStyle['fontWeight'] }; +export type TextVariationThemeConfig = Partial>; /** * Interface for the properties that can be passed to a text component. From 38ae5aada51647b7d153c5c956d12a8eceb402de Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sat, 4 Oct 2025 18:44:51 +0530 Subject: [PATCH 3/9] [unit-testing] Added badge component test cases --- .../__test__/V2ThemeContext.test.tsx | 298 ++++++++++++++++++ 1 file changed, 298 insertions(+) diff --git a/src/packages/react-native-material-elements/__test__/V2ThemeContext.test.tsx b/src/packages/react-native-material-elements/__test__/V2ThemeContext.test.tsx index 4f691de..da6468f 100644 --- a/src/packages/react-native-material-elements/__test__/V2ThemeContext.test.tsx +++ b/src/packages/react-native-material-elements/__test__/V2ThemeContext.test.tsx @@ -1,10 +1,13 @@ import { renderHook, render as themeRender } from '@testing-library/react-native'; import { StyleSheet } from 'react-native'; import { + Badge, createColorShades, createTheme, createThemeDimensions, defaultLightTheme, + Divider, + DividerColorThemeConfig, Text, themeDimensions, ThemeProvider, @@ -380,5 +383,300 @@ describe('V2ThemeContext', () => { expect(fattenStyles).toEqual(expect.objectContaining({ fontSize: 20, fontWeight: 200 })); }); }); + + describe('dividerProps', () => { + const startLineTestId = 'divider-start-line-testid'; + const endLineTestId = 'divider-end-line-testid'; + const dividerTestId = 'divider-testid'; + + const mockDividerColorThemeConfig: DividerColorThemeConfig = { + colors: { + primary: { + color: 'green', + }, + secondary: { + color: 'red', + }, + success: { + color: 'pink', + }, + error: { + color: 'blue', + }, + info: { + color: 'white', + }, + warning: { + color: 'pink', + }, + gray: { + color: 'gray', + }, + lightGray: { + color: 'green', + }, + }, + }; + + it('should adopted the theme lightGray color', () => { + const { getByTestId } = themeRender( + + + , + ); + + const startLine = getByTestId(startLineTestId); + const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'green' })); + + const endLine = getByTestId(endLineTestId); + const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'green' })); + }); + + it('should adopted the theme gray color', () => { + const { getByTestId } = themeRender( + + + , + ); + + const startLine = getByTestId(startLineTestId); + const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'gray' })); + + const endLine = getByTestId(endLineTestId); + const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'gray' })); + }); + + it('should adopted the theme warning color', () => { + const { getByTestId } = themeRender( + + + , + ); + + const startLine = getByTestId(startLineTestId); + const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'pink' })); + + const endLine = getByTestId(endLineTestId); + const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'pink' })); + }); + + it('should adopted the theme info color', () => { + const { getByTestId } = themeRender( + + + , + ); + + const startLine = getByTestId(startLineTestId); + const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'white' })); + + const endLine = getByTestId(endLineTestId); + const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'white' })); + }); + + it('should adopted the theme error color', () => { + const { getByTestId } = themeRender( + + + , + ); + + const startLine = getByTestId(startLineTestId); + const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'blue' })); + + const endLine = getByTestId(endLineTestId); + const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'blue' })); + }); + + it('should adopted the theme success color', () => { + const { getByTestId } = themeRender( + + + , + ); + + const startLine = getByTestId(startLineTestId); + const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'pink' })); + + const endLine = getByTestId(endLineTestId); + const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'pink' })); + }); + + it('should adopted the theme primary color', () => { + const { getByTestId } = themeRender( + + + , + ); + + const startLine = getByTestId(startLineTestId); + const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'green' })); + + const endLine = getByTestId(endLineTestId); + const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'green' })); + }); + + it('should adopted the theme secondary color', () => { + const { getByTestId } = themeRender( + + + , + ); + + const startLine = getByTestId(startLineTestId); + const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'red' })); + + const endLine = getByTestId(endLineTestId); + const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'red' })); + }); + + it('should adopted the theme startLineStyles', () => { + const { getByTestId } = themeRender( + + + , + ); + + const startLine = getByTestId(startLineTestId); + + const flattenStyles = StyleSheet.flatten(startLine.props.style); + expect(flattenStyles).toEqual(expect.objectContaining({ borderWidth: 10, borderRadius: 10 })); + }); + + it('should override the theme startLineStyles', () => { + const { getByTestId } = themeRender( + + + , + ); + + const startLine = getByTestId(startLineTestId); + + const flattenStyles = StyleSheet.flatten(startLine.props.style); + expect(flattenStyles).toEqual(expect.objectContaining({ borderWidth: 30, borderRadius: 50 })); + }); + + it('should adopted the theme endLineStyles', () => { + const { getByTestId } = themeRender( + + + , + ); + + const startLine = getByTestId(endLineTestId); + + const flattenStyles = StyleSheet.flatten(startLine.props.style); + expect(flattenStyles).toEqual(expect.objectContaining({ borderWidth: 10, borderRadius: 10 })); + }); + + it('should override the theme endLineStyles', () => { + const { getByTestId } = themeRender( + + + , + ); + + const startLine = getByTestId(endLineTestId); + + const flattenStyles = StyleSheet.flatten(startLine.props.style); + expect(flattenStyles).toEqual(expect.objectContaining({ borderWidth: 30, borderRadius: 50 })); + }); + + it('should adopted the theme borderColor', () => { + const { getByTestId } = themeRender( + + + , + ); + + const startLine = getByTestId(startLineTestId); + const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'red' })); + + const endLine = getByTestId(endLineTestId); + const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'red' })); + }); + + it('should override the theme borderColor', () => { + const { getByTestId } = themeRender( + + + , + ); + + const startLine = getByTestId(startLineTestId); + const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'green' })); + + const endLine = getByTestId(endLineTestId); + const endLineFlattenStyles = StyleSheet.flatten(startLine.props.style); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'green' })); + }); + + it('should adopted the theme styles', () => { + const { getByTestId } = themeRender( + + + , + ); + + const divider = getByTestId(dividerTestId); + const flattenStyles = StyleSheet.flatten(divider.props.style); + expect(flattenStyles).toEqual(expect.objectContaining({ borderWidth: 10 })); + }); + + it('should override the theme styles', () => { + const { getByTestId } = themeRender( + + + , + ); + + const divider = getByTestId(dividerTestId); + const flattenStyles = StyleSheet.flatten(divider.props.style); + expect(flattenStyles).toEqual(expect.objectContaining({ borderWidth: 100 })); + }); + }); + + describe('badgeProps', () => { + it('should adopted the theme config max prop', () => { + const { getByText } = themeRender( + + + , + ); + + const label = getByText('9+'); + expect(label).toBeDefined(); + }); + + it('should override the theme config max prop', () => { + const { getByText } = themeRender( + + + , + ); + + const label = getByText('19+'); + expect(label).toBeDefined(); + }); + }); }); }); From 7ca1374964d596b376f11c5ad6d6128c9981a4db Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sat, 4 Oct 2025 18:46:46 +0530 Subject: [PATCH 4/9] [unit-testing] added type check --- .github/workflows/type-check.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/type-check.yaml b/.github/workflows/type-check.yaml index 93d78aa..a8acd8b 100644 --- a/.github/workflows/type-check.yaml +++ b/.github/workflows/type-check.yaml @@ -7,7 +7,6 @@ on: types: [opened, synchronize, reopened] jobs: code-quality-check: - if: false name: Type Check runs-on: ubuntu-latest steps: From 58b9a3157c374a850b34a3df6dd400c0af7391fe Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sat, 4 Oct 2025 19:04:23 +0530 Subject: [PATCH 5/9] [unit-testing] updated the workflows --- .github/workflows/test-runner.yaml | 4 ++++ .github/workflows/type-check.yaml | 1 + 2 files changed, 5 insertions(+) diff --git a/.github/workflows/test-runner.yaml b/.github/workflows/test-runner.yaml index 5ddafe9..9fbffd1 100644 --- a/.github/workflows/test-runner.yaml +++ b/.github/workflows/test-runner.yaml @@ -21,4 +21,8 @@ jobs: - name: Run unit tests run: yarn run test --coverage --forceExit --maxWorkers=2 + continue-on-error: false + + - name: Run TypeScript type check + run: npx tsc --noEmit continue-on-error: false \ No newline at end of file diff --git a/.github/workflows/type-check.yaml b/.github/workflows/type-check.yaml index a8acd8b..93d78aa 100644 --- a/.github/workflows/type-check.yaml +++ b/.github/workflows/type-check.yaml @@ -7,6 +7,7 @@ on: types: [opened, synchronize, reopened] jobs: code-quality-check: + if: false name: Type Check runs-on: ubuntu-latest steps: From 1ae6923f9c9aea622f196e50e2c18e8b5287ccae Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sat, 4 Oct 2025 19:10:21 +0530 Subject: [PATCH 6/9] [unit-testing] Updated git workflows --- .github/workflows/code-check.yaml | 16 +++++++----- .github/workflows/lint.yml | 26 ------------------- .../{test-runner.yaml => sonar-qube.yaml} | 16 +++++------- .github/workflows/type-check.yaml | 24 ----------------- 4 files changed, 16 insertions(+), 66 deletions(-) delete mode 100644 .github/workflows/lint.yml rename .github/workflows/{test-runner.yaml => sonar-qube.yaml} (59%) delete mode 100644 .github/workflows/type-check.yaml diff --git a/.github/workflows/code-check.yaml b/.github/workflows/code-check.yaml index 7891ffa..4866103 100644 --- a/.github/workflows/code-check.yaml +++ b/.github/workflows/code-check.yaml @@ -1,4 +1,4 @@ -name: Code Quality Check +name: Code Check on: push: branches: @@ -7,7 +7,7 @@ on: types: [opened, synchronize, reopened] jobs: code-quality-check: - name: Checks code quality + name: Code check runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -19,8 +19,10 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: SonarCloud Scan - uses: sonarsource/sonarcloud-github-action@v2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} \ No newline at end of file + - name: Run ESLint + run: yarn run lint + continue-on-error: false + + - name: Run unit tests + run: yarn run test --coverage --forceExit --maxWorkers=2 + continue-on-error: false \ No newline at end of file diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index 0cb2386..0000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Lint -on: - push: - branches: - - master - pull_request: - types: [opened, synchronize, reopened] - -jobs: - eslint: - name: "Eslint check" - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Install dependencies - uses: ./.github/actions/install-dependencies - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Run ESLint - run: yarn run lint - continue-on-error: false \ No newline at end of file diff --git a/.github/workflows/test-runner.yaml b/.github/workflows/sonar-qube.yaml similarity index 59% rename from .github/workflows/test-runner.yaml rename to .github/workflows/sonar-qube.yaml index 9fbffd1..23d859d 100644 --- a/.github/workflows/test-runner.yaml +++ b/.github/workflows/sonar-qube.yaml @@ -1,4 +1,4 @@ -name: Test +name: Sonarqube on: push: branches: @@ -7,7 +7,7 @@ on: types: [opened, synchronize, reopened] jobs: code-quality-check: - name: Test Runner + name: Sonar code quality check runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -19,10 +19,8 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Run unit tests - run: yarn run test --coverage --forceExit --maxWorkers=2 - continue-on-error: false - - - name: Run TypeScript type check - run: npx tsc --noEmit - continue-on-error: false \ No newline at end of file + - name: SonarCloud Scan + uses: sonarsource/sonarcloud-github-action@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/type-check.yaml b/.github/workflows/type-check.yaml deleted file mode 100644 index 93d78aa..0000000 --- a/.github/workflows/type-check.yaml +++ /dev/null @@ -1,24 +0,0 @@ -name: TSC -on: - push: - branches: - - master - pull_request: - types: [opened, synchronize, reopened] -jobs: - code-quality-check: - if: false - name: Type Check - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Install dependencies - uses: ./.github/actions/install-dependencies - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Run TypeScript type check - run: npx tsc --noEmit - continue-on-error: false \ No newline at end of file From 51d0ec6158f786358519277fc4ccdb5ac607d73a Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sun, 5 Oct 2025 13:15:23 +0530 Subject: [PATCH 7/9] [unit-testing] Fixed divider component orientation and spacing issue --- .../__test__/Divider.test.tsx | 34 ++-- .../__test__/V2ThemeContext.test.tsx | 55 ++++--- .../__snapshots__/Divider.test.tsx.snap | 154 +++++++++--------- .../src/components/Divider/Divider.styles.ts | 49 ++++-- .../src/components/Divider/Divider.tsx | 55 ++++--- .../src/libraries/themes/theme.d.ts | 5 +- 6 files changed, 199 insertions(+), 153 deletions(-) diff --git a/src/packages/react-native-material-elements/__test__/Divider.test.tsx b/src/packages/react-native-material-elements/__test__/Divider.test.tsx index 325d0eb..eb43050 100644 --- a/src/packages/react-native-material-elements/__test__/Divider.test.tsx +++ b/src/packages/react-native-material-elements/__test__/Divider.test.tsx @@ -78,16 +78,16 @@ describe('Divider Component', () => { expect(divider.props.style).not.toHaveProperty('paddingLeft'); }); - it('should change the border of the divider component when passed the borderColor prop', () => { + it('should change the border of the divider component when passed the backgroundColor prop', () => { const { getByTestId } = render( - , + , ); const startLine = getByTestId(dividerStartLineTestId); const endLine = getByTestId(dividerStartLineTestId); const startLineFlattenedStyle = StyleSheet.flatten(startLine.props.style); const endLineFlattenedStyle = StyleSheet.flatten(endLine.props.style); - expect(startLineFlattenedStyle.borderColor).toEqual('red'); - expect(endLineFlattenedStyle.borderColor).toEqual('red'); + expect(startLineFlattenedStyle.backgroundColor).toEqual('red'); + expect(endLineFlattenedStyle.backgroundColor).toEqual('red'); }); it('should change the variant spacing of the divider component when passed the variantSpacing prop', () => { @@ -176,9 +176,9 @@ describe('Divider Component', () => { expect(flattenedStyle.borderWidth).toEqual(2); }); - it('should apply the root borderColor correctly', () => { + it('should apply the root backgroundColor correctly', () => { const { getByTestId } = testRenderer( - + , ); @@ -186,22 +186,22 @@ describe('Divider Component', () => { const endLine = getByTestId(dividerStartLineTestId); const startLineFlattenedStyle = StyleSheet.flatten(startLine.props.style); const endLineFlattenedStyle = StyleSheet.flatten(endLine.props.style); - expect(startLineFlattenedStyle.borderColor).toEqual('red'); - expect(endLineFlattenedStyle.borderColor).toEqual('red'); + expect(startLineFlattenedStyle.backgroundColor).toEqual('red'); + expect(endLineFlattenedStyle.backgroundColor).toEqual('red'); }); - it('should override the root borderColor correctly', () => { + it('should override the root backgroundColor correctly', () => { const { getByTestId } = testRenderer( - - + + , ); const startLine = getByTestId(dividerStartLineTestId); const endLine = getByTestId(dividerStartLineTestId); const startLineFlattenedStyle = StyleSheet.flatten(startLine.props.style); const endLineFlattenedStyle = StyleSheet.flatten(endLine.props.style); - expect(startLineFlattenedStyle.borderColor).toEqual('green'); - expect(endLineFlattenedStyle.borderColor).toEqual('green'); + expect(startLineFlattenedStyle.backgroundColor).toEqual('green'); + expect(endLineFlattenedStyle.backgroundColor).toEqual('green'); }); it('should apply the root variant spacing of the divider component correctly', () => { @@ -257,11 +257,11 @@ describe('Divider Component', () => { const startLine = getByTestId(dividerStartLineTestId); const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); - expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: gray[700] })); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: gray[700] })); const endLine = getByTestId(dividerEndLineTestId); const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); - expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: gray[700] })); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: gray[700] })); }); it('should show smooth dark background when theme mode is light', () => { @@ -270,11 +270,11 @@ describe('Divider Component', () => { const startLine = getByTestId(dividerStartLineTestId); const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); - expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: gray[400] })); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: gray[400] })); const endLine = getByTestId(dividerEndLineTestId); const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); - expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: gray[400] })); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: gray[400] })); }); it('should render child component', () => { diff --git a/src/packages/react-native-material-elements/__test__/V2ThemeContext.test.tsx b/src/packages/react-native-material-elements/__test__/V2ThemeContext.test.tsx index da6468f..3573349 100644 --- a/src/packages/react-native-material-elements/__test__/V2ThemeContext.test.tsx +++ b/src/packages/react-native-material-elements/__test__/V2ThemeContext.test.tsx @@ -21,6 +21,15 @@ describe('V2ThemeContext', () => { const mockLightColors = { 400: '#000000', '100': '#be3434', '200': '#2f63be' }; const mockDarkColors = { 400: '#a31a1a', '100': '#3464be', '200': '#76be2f' }; + beforeEach(() => { + jest.useFakeTimers(); + jest.clearAllMocks(); + }); + + afterEach(() => { + jest.clearAllTimers(); + }); + describe('createColorShades', () => { it('should customized the theme color shades', () => { const colors = createColorShades({ @@ -427,11 +436,11 @@ describe('V2ThemeContext', () => { const startLine = getByTestId(startLineTestId); const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); - expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'green' })); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'green' })); const endLine = getByTestId(endLineTestId); const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); - expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'green' })); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'green' })); }); it('should adopted the theme gray color', () => { @@ -443,11 +452,11 @@ describe('V2ThemeContext', () => { const startLine = getByTestId(startLineTestId); const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); - expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'gray' })); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'gray' })); const endLine = getByTestId(endLineTestId); const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); - expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'gray' })); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'gray' })); }); it('should adopted the theme warning color', () => { @@ -459,11 +468,11 @@ describe('V2ThemeContext', () => { const startLine = getByTestId(startLineTestId); const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); - expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'pink' })); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'pink' })); const endLine = getByTestId(endLineTestId); const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); - expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'pink' })); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'pink' })); }); it('should adopted the theme info color', () => { @@ -475,11 +484,11 @@ describe('V2ThemeContext', () => { const startLine = getByTestId(startLineTestId); const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); - expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'white' })); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'white' })); const endLine = getByTestId(endLineTestId); const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); - expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'white' })); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'white' })); }); it('should adopted the theme error color', () => { @@ -491,11 +500,11 @@ describe('V2ThemeContext', () => { const startLine = getByTestId(startLineTestId); const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); - expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'blue' })); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'blue' })); const endLine = getByTestId(endLineTestId); const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); - expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'blue' })); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'blue' })); }); it('should adopted the theme success color', () => { @@ -507,11 +516,11 @@ describe('V2ThemeContext', () => { const startLine = getByTestId(startLineTestId); const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); - expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'pink' })); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'pink' })); const endLine = getByTestId(endLineTestId); const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); - expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'pink' })); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'pink' })); }); it('should adopted the theme primary color', () => { @@ -523,11 +532,11 @@ describe('V2ThemeContext', () => { const startLine = getByTestId(startLineTestId); const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); - expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'green' })); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'green' })); const endLine = getByTestId(endLineTestId); const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); - expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'green' })); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'green' })); }); it('should adopted the theme secondary color', () => { @@ -539,11 +548,11 @@ describe('V2ThemeContext', () => { const startLine = getByTestId(startLineTestId); const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); - expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'red' })); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'red' })); const endLine = getByTestId(endLineTestId); const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); - expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'red' })); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'red' })); }); it('should adopted the theme startLineStyles', () => { @@ -600,34 +609,34 @@ describe('V2ThemeContext', () => { it('should adopted the theme borderColor', () => { const { getByTestId } = themeRender( - + , ); const startLine = getByTestId(startLineTestId); const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); - expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'red' })); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'red' })); const endLine = getByTestId(endLineTestId); const endLineFlattenStyles = StyleSheet.flatten(endLine.props.style); - expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'red' })); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'red' })); }); it('should override the theme borderColor', () => { const { getByTestId } = themeRender( - - + + , ); const startLine = getByTestId(startLineTestId); const startLineFlattenStyles = StyleSheet.flatten(startLine.props.style); - expect(startLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'green' })); + expect(startLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'green' })); const endLine = getByTestId(endLineTestId); const endLineFlattenStyles = StyleSheet.flatten(startLine.props.style); - expect(endLineFlattenStyles).toEqual(expect.objectContaining({ borderColor: 'green' })); + expect(endLineFlattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'green' })); }); it('should adopted the theme styles', () => { diff --git a/src/packages/react-native-material-elements/__test__/__snapshots__/Divider.test.tsx.snap b/src/packages/react-native-material-elements/__test__/__snapshots__/Divider.test.tsx.snap index 200e700..066e8ef 100644 --- a/src/packages/react-native-material-elements/__test__/__snapshots__/Divider.test.tsx.snap +++ b/src/packages/react-native-material-elements/__test__/__snapshots__/Divider.test.tsx.snap @@ -2,114 +2,110 @@ exports[`Divider Component should render correctly 1`] = ` - + > + + + `; exports[`Divider Component should render the children correctly 1`] = ` - - test-label - - + + + test-label + + + `; diff --git a/src/packages/react-native-material-elements/src/components/Divider/Divider.styles.ts b/src/packages/react-native-material-elements/src/components/Divider/Divider.styles.ts index a2360d4..abd2463 100644 --- a/src/packages/react-native-material-elements/src/components/Divider/Divider.styles.ts +++ b/src/packages/react-native-material-elements/src/components/Divider/Divider.styles.ts @@ -9,36 +9,41 @@ export const styles = StyleSheet.create({ flexDirection: 'row', alignItems: 'center', }, - line: { - borderTopWidth: 0.5, - borderBottomWidth: 0.5, - }, }); export const dividerLineStyles = ({ colors, mode, - borderColor, + backgroundColor, textAlign, lineType, color, themeColorSchemeConfig, + orientation, }: DividerLineStyles) => { - let borderColorValue: ColorValue; + let _backgroundColor: ColorValue; + const isVertical = orientation === 'vertical'; - if (borderColor) { - borderColorValue = borderColor; + if (backgroundColor) { + _backgroundColor = backgroundColor; } else if (color) { - borderColorValue = getVariant({ colors, variant: color, config: themeColorSchemeConfig }); + _backgroundColor = getVariant({ colors, variant: color, config: themeColorSchemeConfig }); } else if (mode === 'light') { - borderColorValue = gray[400]; + _backgroundColor = gray[400]; } else { - borderColorValue = gray[700]; + _backgroundColor = gray[700]; } let baseStyles: ViewStyle = { - borderColor: borderColorValue, + backgroundColor: _backgroundColor, }; + + if (isVertical) { + baseStyles.width = 0.6; + } else { + baseStyles.height = 0.6; + } + const isStartLine = lineType === 'start'; switch (textAlign) { @@ -63,19 +68,35 @@ export const dividerRootContainerStyles = ({ gap, hasChild, variantSpacing, + dividerLayout, }: DividerRootContainerStyles): ViewStyle => { const isVertical = orientation === 'vertical'; const defaultStyles: ViewStyle = isVertical ? { paddingHorizontal: 2, - alignSelf: 'auto', + alignSelf: 'flex-start', flexDirection: 'column', } : { paddingVertical: 2 }; const baseStyles: ViewStyle = { ...defaultStyles, gap: gap || hasChild ? 10 : 0 }; - const elementSpacing = variantSpacing ?? spacing.lg; + + let elementSpacing: number; + + if (variantSpacing) { + elementSpacing = variantSpacing; + } else { + if (dividerLayout) { + if (isVertical) { + elementSpacing = dividerLayout.height / 6; + } else { + elementSpacing = dividerLayout.width / 6; + } + } else { + elementSpacing = spacing.lg; + } + } switch (variant) { case 'middle': diff --git a/src/packages/react-native-material-elements/src/components/Divider/Divider.tsx b/src/packages/react-native-material-elements/src/components/Divider/Divider.tsx index 42bf9d8..c1edf0a 100644 --- a/src/packages/react-native-material-elements/src/components/Divider/Divider.tsx +++ b/src/packages/react-native-material-elements/src/components/Divider/Divider.tsx @@ -1,5 +1,15 @@ -import React, { useCallback, useMemo } from 'react'; -import { ColorSchemeName, ColorValue, StyleProp, useColorScheme, View, ViewProps, ViewStyle } from 'react-native'; +import React, { useCallback, useMemo, useState } from 'react'; +import { + ColorSchemeName, + ColorValue, + LayoutChangeEvent, + LayoutRectangle, + StyleProp, + useColorScheme, + View, + ViewProps, + ViewStyle, +} from 'react-native'; import { useRestyle } from '../../hooks'; import { useThemeColorsSelector, useThemeDividerConfigSelector, useThemeSpacingSelector } from '../../libraries'; import { StyledProps } from '../../libraries/style/styleTypes'; @@ -44,7 +54,7 @@ export interface DividerProps extends ViewProps, StyledProps { /** * The color of the divider line, defined by a color value. */ - borderColor?: ColorValue; + backgroundColor?: ColorValue; /** * Space between the divider line and any child elements. */ @@ -75,8 +85,11 @@ export interface DividerRootContainerStyles extends Pick { +export interface DividerLineStyles extends Pick { /** * Theme configuration for the divider line */ @@ -101,7 +114,7 @@ export const Divider = React.forwardRef( style, startLineStyles, endLineStyles, - borderColor, + backgroundColor, gap, variantSpacing, startLineTestId, @@ -121,8 +134,9 @@ export const Divider = React.forwardRef( const hasChild = Boolean(children); const dividerThemeConfig = useThemeDividerConfigSelector(); const { getStyleFromProps } = useRestyle(props); + const [dividerLayout, setDividerLayout] = useState(null); - const dividerBorderColor = borderColor ?? dividerThemeConfig?.borderColor; + const dividerBackgroundColor = backgroundColor ?? dividerThemeConfig?.backgroundColor; const dividerGap = gap ?? dividerThemeConfig?.gap; const dividerVariantSpacing = variantSpacing ?? dividerThemeConfig?.variantSpacing; @@ -136,35 +150,38 @@ export const Divider = React.forwardRef( gap: dividerGap, hasChild, variantSpacing: dividerVariantSpacing, + dividerLayout, }); - }, [themeSpacing, variant, orientation, dividerGap, hasChild, dividerVariantSpacing]); + }, [themeSpacing, variant, orientation, dividerGap, hasChild, dividerVariantSpacing, dividerLayout]); const lineStyles = useCallback( (lineType: LineType) => { return dividerLineStyles({ colors: themeColors, mode: colorScheme, - borderColor: dividerBorderColor, + backgroundColor: dividerBackgroundColor, textAlign, lineType, color, themeColorSchemeConfig: themeVariantColors, + orientation, }); }, - [dividerBorderColor, colorScheme, textAlign, color, themeColors, themeVariantColors], + [dividerBackgroundColor, colorScheme, textAlign, color, themeColors, themeVariantColors, orientation], ); + const onLayout = (event: LayoutChangeEvent) => { + const { layout } = event.nativeEvent; + setDividerLayout(layout); + }; + return ( - - - {children} - + + + + {children} + + ); }, diff --git a/src/packages/react-native-material-elements/src/libraries/themes/theme.d.ts b/src/packages/react-native-material-elements/src/libraries/themes/theme.d.ts index 244db8e..93d9b89 100644 --- a/src/packages/react-native-material-elements/src/libraries/themes/theme.d.ts +++ b/src/packages/react-native-material-elements/src/libraries/themes/theme.d.ts @@ -153,7 +153,10 @@ export type ThemeComponentConfig = { > & CheckBoxVariationThemeConfig; chipProps?: ChipThemeConfig & ChipVariationConfig; - dividerProps?: Pick & + dividerProps?: Pick< + DividerProps, + 'startLineStyles' | 'endLineStyles' | 'backgroundColor' | 'gap' | 'variantSpacing' | 'style' + > & DividerColorThemeConfig; listProps?: Pick; listItemProps?: Pick< From 03cf645ccbd1a146d848162153bb796b99766b3f Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sun, 5 Oct 2025 18:32:28 +0530 Subject: [PATCH 8/9] [unit-testing] Added theme badge config test cases --- .../__test__/V2ThemeContext.test.tsx | 250 +++++++++++++++++- 1 file changed, 249 insertions(+), 1 deletion(-) diff --git a/src/packages/react-native-material-elements/__test__/V2ThemeContext.test.tsx b/src/packages/react-native-material-elements/__test__/V2ThemeContext.test.tsx index 3573349..ffe311b 100644 --- a/src/packages/react-native-material-elements/__test__/V2ThemeContext.test.tsx +++ b/src/packages/react-native-material-elements/__test__/V2ThemeContext.test.tsx @@ -15,7 +15,7 @@ import { } from '../src'; import { ThemeInterface, ThemeType } from '../src/libraries/types'; import { render, ThemeWrapper } from './test-utils'; -import { TextVariationThemeConfig } from '../src/types'; +import { BadgeVariationThemeConfig, TextVariationThemeConfig } from '../src/types'; describe('V2ThemeContext', () => { const mockLightColors = { 400: '#000000', '100': '#be3434', '200': '#2f63be' }; @@ -665,6 +665,133 @@ describe('V2ThemeContext', () => { }); describe('badgeProps', () => { + const badgeTestId = 'badge-testid'; + + const mockDividerColorThemeConfig: BadgeVariationThemeConfig = { + colors: { + primary: { + color: 'green', + }, + secondary: { + color: 'red', + }, + success: { + color: 'pink', + }, + error: { + color: 'blue', + }, + info: { + color: 'white', + }, + warning: { + color: 'pink', + }, + gray: { + color: 'gray', + }, + lightGray: { + color: 'green', + }, + }, + }; + + it('should adopted theme lightGray color', () => { + const { getByTestId } = themeRender( + + + , + ); + + const badge = getByTestId(badgeTestId); + const fattenStyles = StyleSheet.flatten(badge.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'green' })); + }); + + it('should adopted theme gray color', () => { + const { getByTestId } = themeRender( + + + , + ); + + const badge = getByTestId(badgeTestId); + const fattenStyles = StyleSheet.flatten(badge.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'gray' })); + }); + + it('should adopted theme warning color', () => { + const { getByTestId } = themeRender( + + + , + ); + + const badge = getByTestId(badgeTestId); + const fattenStyles = StyleSheet.flatten(badge.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'pink' })); + }); + + it('should adopted theme info color', () => { + const { getByTestId } = themeRender( + + + , + ); + + const badge = getByTestId(badgeTestId); + const fattenStyles = StyleSheet.flatten(badge.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'white' })); + }); + + it('should adopted theme error color', () => { + const { getByTestId } = themeRender( + + + , + ); + + const badge = getByTestId(badgeTestId); + const fattenStyles = StyleSheet.flatten(badge.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'blue' })); + }); + + it('should adopted theme success color', () => { + const { getByTestId } = themeRender( + + + , + ); + + const badge = getByTestId(badgeTestId); + const fattenStyles = StyleSheet.flatten(badge.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'pink' })); + }); + + it('should adopted theme secondary color', () => { + const { getByTestId } = themeRender( + + + , + ); + + const badge = getByTestId(badgeTestId); + const fattenStyles = StyleSheet.flatten(badge.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'red' })); + }); + + it('should adopted theme primary color', () => { + const { getByTestId } = themeRender( + + + , + ); + + const badge = getByTestId(badgeTestId); + const fattenStyles = StyleSheet.flatten(badge.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ backgroundColor: 'green' })); + }); + it('should adopted the theme config max prop', () => { const { getByText } = themeRender( @@ -686,6 +813,127 @@ describe('V2ThemeContext', () => { const label = getByText('19+'); expect(label).toBeDefined(); }); + + it('should adopted the theme anchorOrigin prop with badge variant', () => { + const { getByTestId } = themeRender( + + + , + ); + + const badge = getByTestId(badgeTestId); + + const fattenStyles = StyleSheet.flatten(badge.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ top: -4, left: -4 })); + }); + + it('should override the theme anchorOrigin prop with badge variant', () => { + const { getByTestId } = themeRender( + + + , + ); + + const badge = getByTestId(badgeTestId); + + const fattenStyles = StyleSheet.flatten(badge.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ bottom: -4, right: -4 })); + }); + + it('should adopted the theme anchorOrigin prop with dot variant', () => { + const { getByTestId } = themeRender( + + + , + ); + + const badge = getByTestId(badgeTestId); + + const fattenStyles = StyleSheet.flatten(badge.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ top: 0, left: 0 })); + }); + + it('should override the theme anchorOrigin prop with dot variant', () => { + const { getByTestId } = themeRender( + + + , + ); + + const badge = getByTestId(badgeTestId); + + const fattenStyles = StyleSheet.flatten(badge.props.style); + expect(fattenStyles).toEqual(expect.objectContaining({ bottom: 0, right: 0 })); + }); + + it('should apply the theme badge style config', () => { + const { getByTestId } = themeRender( + + + , + ); + + const badge = getByTestId(badgeTestId); + const fattenStyles = StyleSheet.flatten(badge.props.style); + expect(fattenStyles).toEqual( + expect.objectContaining({ + borderRadius: 2, + backgroundColor: 'red', + borderWidth: 1, + borderColor: 'grey', + }), + ); + }); + + it('should merge the theme badge style config with badge component style prop', () => { + const { getByTestId } = themeRender( + + + , + ); + + const badge = getByTestId(badgeTestId); + const fattenStyles = StyleSheet.flatten(badge.props.style); + expect(fattenStyles).toEqual( + expect.objectContaining({ + borderRadius: 2, + backgroundColor: 'green', + borderWidth: 1, + borderColor: 'red', + }), + ); + }); }); }); }); From de6f580217e2c1630966afa4a88b0485ff5067fb Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sun, 5 Oct 2025 21:19:02 +0530 Subject: [PATCH 9/9] [unit-testing] Added icon input theme config test cases --- .../__test__/V2ThemeContext.test.tsx | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/packages/react-native-material-elements/__test__/V2ThemeContext.test.tsx b/src/packages/react-native-material-elements/__test__/V2ThemeContext.test.tsx index ffe311b..fb1e516 100644 --- a/src/packages/react-native-material-elements/__test__/V2ThemeContext.test.tsx +++ b/src/packages/react-native-material-elements/__test__/V2ThemeContext.test.tsx @@ -8,6 +8,7 @@ import { defaultLightTheme, Divider, DividerColorThemeConfig, + IconInput, Text, themeDimensions, ThemeProvider, @@ -124,6 +125,36 @@ describe('V2ThemeContext', () => { }); describe('ThemeProvider component config', () => { + const iconInputWrapperTestId = 'icon-input-test-id'; + + describe('iconInputProps', () => { + it('should adopted theme inputWrapperStyles prop', () => { + const { getByTestId } = themeRender( + + + , + ); + + const inputWrapper = getByTestId(`${iconInputWrapperTestId}-wrapper`); + const flattenStyles = StyleSheet.flatten(inputWrapper.props.style); + expect(flattenStyles).toEqual(expect.objectContaining({ width: 100, height: 100, backgroundColor: 'red' })); + }); + + it('should marge theme inputWrapperStyles prop and inputWrapperStyles component prop', () => { + const { getByTestId } = themeRender( + + + , + ); + + const inputWrapper = getByTestId(`${iconInputWrapperTestId}-wrapper`); + const flattenStyles = StyleSheet.flatten(inputWrapper.props.style); + expect(flattenStyles).toEqual(expect.objectContaining({ width: 10, backgroundColor: 'green' })); + }); + }); + describe('textProps', () => { const mockTextThemeConfig: TextVariationThemeConfig = { body1: { fontSize: 10, fontWeight: '100' },