From e989ab7800469db44b446c92594116cec7f91010 Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sat, 20 Sep 2025 19:29:27 +0530 Subject: [PATCH 01/26] Updated the actions node version --- .github/actions/install-dependencies/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/install-dependencies/action.yml b/.github/actions/install-dependencies/action.yml index cbf0328..b9bc5f2 100644 --- a/.github/actions/install-dependencies/action.yml +++ b/.github/actions/install-dependencies/action.yml @@ -6,7 +6,7 @@ runs: - name: Setup Node.js uses: actions/setup-node@v3 with: - node-version: 22.9.0 + node-version: 20 cache: 'yarn' - name: Install dependencies From c84a6bb41409730315ac1454c5e14356fe94cea4 Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sat, 20 Sep 2025 20:09:00 +0530 Subject: [PATCH 02/26] Added otp input test cases --- jest.config.js | 3 +++ .../__test__/OtpInput.test.tsx | 18 ++++++++++++++++++ .../__test__/styleGenerator.test.ts | 10 ++++++++++ .../ActivityIndicator.types.d.ts | 2 +- .../src/components/Alert/Alert.tsx | 4 ++-- .../src/components/Menu/Menu.tsx | 2 +- .../src/components/Progress/Progress.tsx | 2 +- .../SegmentedControlContainer.tsx | 4 ++-- .../src/components/TextField/OtpInput.tsx | 2 +- .../src/utils/styleGenerator.ts | 4 +++- 10 files changed, 42 insertions(+), 9 deletions(-) diff --git a/jest.config.js b/jest.config.js index 735f6a7..53c0f4a 100644 --- a/jest.config.js +++ b/jest.config.js @@ -17,6 +17,9 @@ module.exports = { '.enum.ts', '/config/', '/coverage/', + '.eslintrc.js', + '.prettierrc.js', + 'babel.config.js', ], coverageReporters: ['html', 'text', 'lcov', 'text-summary'], diff --git a/src/packages/react-native-material-elements/__test__/OtpInput.test.tsx b/src/packages/react-native-material-elements/__test__/OtpInput.test.tsx index 8831992..a68c669 100644 --- a/src/packages/react-native-material-elements/__test__/OtpInput.test.tsx +++ b/src/packages/react-native-material-elements/__test__/OtpInput.test.tsx @@ -3,6 +3,8 @@ import { OTPInput } from '../src'; import { fireEvent, render } from './test-utils'; describe('OTP Component', () => { + const mockOtpInputTestId = 'mock-otp-input-test-id'; + beforeEach(() => { jest.clearAllMocks(); }); @@ -93,4 +95,20 @@ describe('OTP Component', () => { expect(input.props.value).toBe(''); }); }); + + it('should set the default values', () => { + const { getByTestId } = render(); + + const firstInput = getByTestId(`${mockOtpInputTestId}-0`); + expect(firstInput).toBeDefined(); + expect(firstInput.props.value).toEqual('1'); + + const secondInput = getByTestId(`${mockOtpInputTestId}-1`); + expect(secondInput).toBeDefined(); + expect(secondInput.props.value).toEqual('2'); + + const thirdInput = getByTestId(`${mockOtpInputTestId}-2`); + expect(thirdInput).toBeDefined(); + expect(thirdInput.props.value).toEqual('3'); + }); }); diff --git a/src/packages/react-native-material-elements/__test__/styleGenerator.test.ts b/src/packages/react-native-material-elements/__test__/styleGenerator.test.ts index 6bcb53d..fda0d09 100644 --- a/src/packages/react-native-material-elements/__test__/styleGenerator.test.ts +++ b/src/packages/react-native-material-elements/__test__/styleGenerator.test.ts @@ -76,5 +76,15 @@ describe('Style Utilities', () => { expect(result).toEqual({}); consoleSpy.mockRestore(); }); + + it('should warn in the console if the styles property not valid', () => { + const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(); + const args: StylePalette = { unknown: undefined } as any; + const result = generateElementStyles(args); + + expect(consoleSpy).toHaveBeenCalledWith('Invalid element property name: undefined, and value: undefined'); + expect(result).toEqual({}); + consoleSpy.mockRestore(); + }); }); }); diff --git a/src/packages/react-native-material-elements/src/components/ActivityIndicator/ActivityIndicator.types.d.ts b/src/packages/react-native-material-elements/src/components/ActivityIndicator/ActivityIndicator.types.d.ts index b01345b..2735b19 100644 --- a/src/packages/react-native-material-elements/src/components/ActivityIndicator/ActivityIndicator.types.d.ts +++ b/src/packages/react-native-material-elements/src/components/ActivityIndicator/ActivityIndicator.types.d.ts @@ -1,6 +1,6 @@ import React from 'react'; import { ActivityIndicator } from 'react-native'; -import { Theme } from '../../libraries/themes/types'; +import { Theme } from '../../libraries/types'; import { VariantTypes } from '../../utils'; export interface ActivityIndicatorProps extends React.ComponentPropsWithRef { diff --git a/src/packages/react-native-material-elements/src/components/Alert/Alert.tsx b/src/packages/react-native-material-elements/src/components/Alert/Alert.tsx index 25c6e34..9b088bc 100644 --- a/src/packages/react-native-material-elements/src/components/Alert/Alert.tsx +++ b/src/packages/react-native-material-elements/src/components/Alert/Alert.tsx @@ -1,13 +1,13 @@ import React, { useMemo } from 'react'; import { ColorSchemeName, StyleSheet, TextStyle, useColorScheme, View, ViewStyle } from 'react-native'; +import { ThemedIconProp, useThemedProps } from '../../hooks'; import { useThemeColorsSelector } from '../../libraries'; -import { Theme } from '../../libraries/themes/types'; +import { Theme } from '../../libraries/types'; import { VariantTypes } from '../../utils'; import { Box } from '../Box'; import { BoxProps } from '../types'; import { Text } from '../Typography'; import { getAlertContainerStyles, getAlertTitleStyles } from './utils'; -import { ThemedIconProp, useThemedProps } from '../../hooks'; export interface AlertProps extends BoxProps { /** Main title text displayed in the alert */ diff --git a/src/packages/react-native-material-elements/src/components/Menu/Menu.tsx b/src/packages/react-native-material-elements/src/components/Menu/Menu.tsx index 9c5b82a..c7ec7fc 100644 --- a/src/packages/react-native-material-elements/src/components/Menu/Menu.tsx +++ b/src/packages/react-native-material-elements/src/components/Menu/Menu.tsx @@ -12,7 +12,7 @@ import { import { useRestyle } from '../../hooks'; import { useThemeColorsSelector } from '../../libraries'; import { StyledProps } from '../../libraries/style/styleTypes'; -import { Theme } from '../../libraries/themes/types'; +import { Theme } from '../../libraries/types'; import { MeasureElementRect, PortalProps } from '../../types'; import { screenHeight, screenWidth } from '../../utils'; import { Portal } from '../Portal'; diff --git a/src/packages/react-native-material-elements/src/components/Progress/Progress.tsx b/src/packages/react-native-material-elements/src/components/Progress/Progress.tsx index 9f81da3..c6f65c9 100644 --- a/src/packages/react-native-material-elements/src/components/Progress/Progress.tsx +++ b/src/packages/react-native-material-elements/src/components/Progress/Progress.tsx @@ -3,7 +3,7 @@ import { Animated, ColorValue, DimensionValue, I18nManager, LayoutChangeEvent, S import { useRestyle } from '../../hooks'; import { useThemeColorsSelector } from '../../libraries'; import { StyledProps } from '../../libraries/style/styleTypes'; -import { Theme } from '../../libraries/themes/types'; +import { Theme } from '../../libraries/types'; import { VariantTypes } from '../../utils'; import { AnimatedView } from '../Box'; import { getProgressBarContainerStyles, getProgressBarIndicatorStyles } from './utils'; diff --git a/src/packages/react-native-material-elements/src/components/SegmentedControl/SegmentedControlContainer.tsx b/src/packages/react-native-material-elements/src/components/SegmentedControl/SegmentedControlContainer.tsx index 2a50ac7..aa16ab4 100644 --- a/src/packages/react-native-material-elements/src/components/SegmentedControl/SegmentedControlContainer.tsx +++ b/src/packages/react-native-material-elements/src/components/SegmentedControl/SegmentedControlContainer.tsx @@ -1,10 +1,10 @@ import React from 'react'; import { View, ViewProps } from 'react-native'; +import { useRestyle } from '../../hooks'; import { useThemeColorsSelector } from '../../libraries'; import { StyledProps } from '../../libraries/style/styleTypes'; -import { Theme } from '../../libraries/themes/types'; +import { Theme } from '../../libraries/types'; import { generateSegmentContainerStyle, styles } from './SegmentedControl.styles'; -import { useRestyle } from '../../hooks'; export interface SegmentedControlContainerProps extends ViewProps, StyledProps {} export interface GenerateSegmentContainerStyle { diff --git a/src/packages/react-native-material-elements/src/components/TextField/OtpInput.tsx b/src/packages/react-native-material-elements/src/components/TextField/OtpInput.tsx index e6375eb..5e6c79c 100644 --- a/src/packages/react-native-material-elements/src/components/TextField/OtpInput.tsx +++ b/src/packages/react-native-material-elements/src/components/TextField/OtpInput.tsx @@ -11,7 +11,7 @@ import { ViewStyle, } from 'react-native'; import { useThemeColorsSelector } from '../../libraries'; -import { Theme } from '../../libraries/themes/types'; +import { Theme } from '../../libraries/types'; import { VariantTypes } from '../../utils'; import { getOtpInputStyles } from './TextField.style'; diff --git a/src/packages/react-native-material-elements/src/utils/styleGenerator.ts b/src/packages/react-native-material-elements/src/utils/styleGenerator.ts index b1c58ce..3b8a57c 100644 --- a/src/packages/react-native-material-elements/src/utils/styleGenerator.ts +++ b/src/packages/react-native-material-elements/src/utils/styleGenerator.ts @@ -40,7 +40,9 @@ export const generateElementStyles = (args: StylePalette) => { for (let property of keys) { const elementPropertyName = property as keyof typeof styles; if (args[elementPropertyName] === undefined) { - console.warn(`Invalid element property name: ${String(args[elementPropertyName])}`); + console.warn( + `Invalid element property name: ${args[elementPropertyName]}, and value: ${String(args[elementPropertyName])}`, + ); continue; } nativeStyles = { From 025c253b6503688ecacca3fb6b6ae611935a53fe Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sat, 20 Sep 2025 20:19:19 +0530 Subject: [PATCH 03/26] [workflow/test] Added sonar check --- .github/workflows/code-check.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/code-check.yaml b/.github/workflows/code-check.yaml index 1ee050a..01bb995 100644 --- a/.github/workflows/code-check.yaml +++ b/.github/workflows/code-check.yaml @@ -21,4 +21,10 @@ jobs: - name: Run unit tests run: yarn run test --coverage --forceExit --maxWorkers=2 - continue-on-error: false \ No newline at end of file + continue-on-error: false + + - name: SonarCloud Scan + uses: SonarSource/sonarcloud-github-action@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} \ No newline at end of file From 05f2687eab17f5fe52e5476c23ff748b7d4db2db Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sat, 20 Sep 2025 23:04:30 +0530 Subject: [PATCH 04/26] [workflow/test] Working on test cases --- package.json | 10 +- .../__test__/InputLabel.test.tsx | 25 +++ .../__test__/OtpInput.test.tsx | 48 ++++- .../__test__/SegmentedControl.test.tsx | 89 ++++++++ .../__test__/Skeleton.test.tsx | 44 ++++ .../__test__/Snackbar.test.tsx | 8 +- .../__test__/Switch.test.tsx | 68 +++++- .../__test__/TextFieldEndAdornment.test.tsx | 39 +++- .../SegmentedControl.test.tsx.snap | 197 ++++++++++++++++++ .../__snapshots__/Snackbar.test.tsx.snap | 3 + .../__test__/utils.test.ts | 5 + .../examples/SegmentedControl.tsx | 4 +- .../package.json | 60 +----- yarn.lock | 100 +-------- 14 files changed, 530 insertions(+), 170 deletions(-) create mode 100644 src/packages/react-native-material-elements/__test__/InputLabel.test.tsx create mode 100644 src/packages/react-native-material-elements/__test__/SegmentedControl.test.tsx create mode 100644 src/packages/react-native-material-elements/__test__/Skeleton.test.tsx create mode 100644 src/packages/react-native-material-elements/__test__/__snapshots__/SegmentedControl.test.tsx.snap create mode 100644 src/packages/react-native-material-elements/__test__/__snapshots__/Snackbar.test.tsx.snap diff --git a/package.json b/package.json index d45a51a..ce01b23 100644 --- a/package.json +++ b/package.json @@ -10,16 +10,11 @@ "test": "jest --coverage" }, "dependencies": { - "@hookform/resolvers": "^5.1.1", - "@testing-library/react-native": "^12.9.0", "lodash": "^4.17.21", "react": "18.3.1", - "react-hook-form": "^7.58.0", "react-native": "0.76.3", - "react-native-phone-number-input": "^2.1.0", "react-native-vector-icons": "^10.2.0", - "use-context-selector": "^2.0.0", - "yup": "^1.6.1" + "use-context-selector": "^2.0.0" }, "devDependencies": { "@babel/core": "^7.25.2", @@ -43,7 +38,8 @@ "jest": "^29.6.3", "prettier": "2.8.8", "react-test-renderer": "18.2.0", - "typescript": "5.0.4" + "typescript": "5.0.4", + "@testing-library/react-native": "^12.9.0" }, "engines": { "node": ">=18" diff --git a/src/packages/react-native-material-elements/__test__/InputLabel.test.tsx b/src/packages/react-native-material-elements/__test__/InputLabel.test.tsx new file mode 100644 index 0000000..7437c34 --- /dev/null +++ b/src/packages/react-native-material-elements/__test__/InputLabel.test.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { Animated } from 'react-native'; +import { gray, InputLabel } from '../src'; +import { fireEvent, render } from './test-utils'; + +describe('InputLabel', () => { + it('updates textLayoutRect state when onLayout is called', () => { + const { getByText } = render(); + + const textElement = getByText('Test Label'); + + fireEvent(textElement, 'layout', { + nativeEvent: { + layout: { + x: 0, + y: 0, + width: 100, + height: 20, + }, + }, + }); + + expect(textElement.props.style).toEqual({ color: gray[800], fontSize: 14 }); + }); +}); diff --git a/src/packages/react-native-material-elements/__test__/OtpInput.test.tsx b/src/packages/react-native-material-elements/__test__/OtpInput.test.tsx index a68c669..198e306 100644 --- a/src/packages/react-native-material-elements/__test__/OtpInput.test.tsx +++ b/src/packages/react-native-material-elements/__test__/OtpInput.test.tsx @@ -5,6 +5,8 @@ import { fireEvent, render } from './test-utils'; describe('OTP Component', () => { const mockOtpInputTestId = 'mock-otp-input-test-id'; + const mockOnChange = jest.fn(); + beforeEach(() => { jest.clearAllMocks(); }); @@ -25,7 +27,6 @@ describe('OTP Component', () => { }); it('calls onChange with the correct OTP value', () => { - const mockOnChange = jest.fn(); const { getByTestId } = render(); const firstInput = getByTestId('otp-input-0'); @@ -111,4 +112,49 @@ describe('OTP Component', () => { expect(thirdInput).toBeDefined(); expect(thirdInput.props.value).toEqual('3'); }); + + it('ignores text input when length > 1', () => { + const { getByTestId } = render(); + const firstInput = getByTestId('otp-input-0'); + + fireEvent.changeText(firstInput, '12'); + + expect(mockOnChange).not.toHaveBeenCalled(); + expect(firstInput.props.value).toBe(''); + }); + + it('calls onChange when a single character is entered', () => { + const { getByTestId } = render(); + const firstInput = getByTestId('otp-input-0'); + + fireEvent.changeText(firstInput, '1'); + + expect(mockOnChange).toHaveBeenCalledWith('1'); + expect(firstInput.props.value).toBe('1'); + }); + + it('throws error when defaultValue length > OTP length', () => { + const spy = jest.spyOn(console, 'error').mockImplementation(); + expect(() => render()).toThrow( + 'Default value must be equal or less then otp length', + ); + spy.mockRestore(); + }); + + it('applies defaultValue when valid', () => { + const { getByTestId } = render(); + expect(getByTestId('otp-input-0').props.value).toBe('1'); + expect(getByTestId('otp-input-1').props.value).toBe('2'); + expect(getByTestId('otp-input-2').props.value).toBe(''); + expect(getByTestId('otp-input-3').props.value).toBe(''); + }); + + it('focus handler is called on focus event', () => { + const { getByTestId } = render(); + const secondInput = getByTestId('otp-input-1'); + + fireEvent(secondInput, 'focus'); + + expect(secondInput.props.selectTextOnFocus).toBe(true); + }); }); diff --git a/src/packages/react-native-material-elements/__test__/SegmentedControl.test.tsx b/src/packages/react-native-material-elements/__test__/SegmentedControl.test.tsx new file mode 100644 index 0000000..b49d539 --- /dev/null +++ b/src/packages/react-native-material-elements/__test__/SegmentedControl.test.tsx @@ -0,0 +1,89 @@ +import { SegmentedControl } from '../src'; +import { SegmentedControlContainer } from '../src/components/SegmentedControl/SegmentedControlContainer'; +import { SegmentedControlItem } from '../src/components/SegmentedControl/SegmentedControlItem'; +import { fireEvent, render } from './test-utils'; + +describe('SegmentedControl component', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should render correctly with default props', () => { + const { toJSON } = render(); + expect(toJSON()).toMatchSnapshot(); + }); +}); + +describe('SegmentedControlContainer component', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should render correctly with default props', () => { + const { toJSON } = render(); + expect(toJSON()).toMatchSnapshot(); + }); +}); + +describe('SegmentedControlItem component', () => { + const mockTestId = 'segmented-item-test-id'; + + const mockOnPress = jest.fn(); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should render correctly with default props', () => { + const { toJSON } = render(); + expect(toJSON()).toMatchSnapshot(); + }); + + it('should render the data when data passed as string', () => { + const { getByText } = render(); + + const text = getByText('First'); + expect(text).toBeDefined(); + }); + + it('should render the data when data passed as number', () => { + const { getByText } = render(); + + const text = getByText('1000'); + expect(text).toBeDefined(); + }); + + it('should called the onPress function when click on the SegmentedControlItem', () => { + const { getByTestId } = render(); + + const item = getByTestId(mockTestId); + + fireEvent(item, 'press', { nativeEvent: {} }); + + expect(mockOnPress).toHaveBeenCalledTimes(1); + }); + + it('should called the onPress function with string data when click on the SegmentedControlItem', () => { + const { getByTestId } = render(); + + const item = getByTestId(mockTestId); + + fireEvent(item, 'press', { nativeEvent: {} }); + + expect(mockOnPress).toHaveBeenCalledTimes(1); + expect(mockOnPress).toHaveBeenCalledWith('data', 0); + }); + + it('should called the onPress function with object data when click on the SegmentedControlItem', () => { + const { getByTestId } = render( + , + ); + + const item = getByTestId(mockTestId); + + fireEvent(item, 'press', { nativeEvent: {} }); + + expect(mockOnPress).toHaveBeenCalledTimes(1); + expect(mockOnPress).toHaveBeenCalledWith({ title: 'label' }, 0); + }); +}); diff --git a/src/packages/react-native-material-elements/__test__/Skeleton.test.tsx b/src/packages/react-native-material-elements/__test__/Skeleton.test.tsx new file mode 100644 index 0000000..b83c709 --- /dev/null +++ b/src/packages/react-native-material-elements/__test__/Skeleton.test.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import { Animated } from 'react-native'; +import { gray, Skeleton } from '../src'; +import { render } from './test-utils'; + +describe('Skeleton component', () => { + let colorSchemeSpy: jest.SpyInstance; + + beforeEach(() => { + jest.clearAllMocks(); + colorSchemeSpy = jest.spyOn(require('react-native'), 'useColorScheme'); + }); + + afterEach(() => { + colorSchemeSpy.mockRestore(); + }); + + it('renders with default background in light mode', () => { + colorSchemeSpy.mockReturnValue('light'); + const { getByTestId } = render(); + const skeleton = getByTestId('skeleton'); + expect(skeleton.props.style.backgroundColor).toBe(gray[400]); + }); + + it('renders with default background in dark mode', () => { + colorSchemeSpy.mockReturnValue('dark'); + const { getByTestId } = render(); + const skeleton = getByTestId('skeleton'); + expect(skeleton.props.style.backgroundColor).toBe(gray[800]); + }); + + it('uses the custom backgroundColor when provided', () => { + colorSchemeSpy.mockReturnValue('light'); + const { getByTestId } = render(); + const skeleton = getByTestId('skeleton'); + expect(skeleton.props.style.backgroundColor).toBe('red'); + }); + + it('starts shimmer animation on mount', () => { + const loopSpy = jest.spyOn(Animated, 'loop'); + render(); + expect(loopSpy).toHaveBeenCalled(); + }); +}); diff --git a/src/packages/react-native-material-elements/__test__/Snackbar.test.tsx b/src/packages/react-native-material-elements/__test__/Snackbar.test.tsx index c4b2348..224e10d 100644 --- a/src/packages/react-native-material-elements/__test__/Snackbar.test.tsx +++ b/src/packages/react-native-material-elements/__test__/Snackbar.test.tsx @@ -1,11 +1,17 @@ import { DeviceEventEmitter } from 'react-native'; -import { HIDE_SNACK_BAR_MESSAGE, SHOW_SNACK_BAR_MESSAGE, snackbar, SnackbarProperties } from '../src'; +import { HIDE_SNACK_BAR_MESSAGE, SHOW_SNACK_BAR_MESSAGE, Snackbar, snackbar, SnackbarProperties } from '../src'; +import { render } from './test-utils'; describe('snackbar utils', () => { beforeEach(() => { jest.clearAllMocks(); }); + it('should render with default props', () => { + const { toJSON } = render(); + expect(toJSON()).toMatchSnapshot(); + }); + it('should called the snack bar show method with config', () => { snackbar.show({} as any); expect(DeviceEventEmitter.emit).toHaveBeenCalled(); diff --git a/src/packages/react-native-material-elements/__test__/Switch.test.tsx b/src/packages/react-native-material-elements/__test__/Switch.test.tsx index 94b955b..71add79 100644 --- a/src/packages/react-native-material-elements/__test__/Switch.test.tsx +++ b/src/packages/react-native-material-elements/__test__/Switch.test.tsx @@ -1,15 +1,28 @@ import React from 'react'; +import { View } from 'react-native'; import { + getSwitchSizes, Switch, + SWITCH_CONTAINER_ANDROID_MODE_HEIGHT_LARGE, + SWITCH_CONTAINER_ANDROID_MODE_HEIGHT_MEDIUM, + SWITCH_CONTAINER_ANDROID_MODE_HEIGHT_SMALL, + SWITCH_CONTAINER_ANDROID_MODE_WIDTH_LARGE, + SWITCH_CONTAINER_ANDROID_MODE_WIDTH_MEDIUM, + SWITCH_CONTAINER_ANDROID_MODE_WIDTH_SMALL, SWITCH_CONTAINER_HEIGHT_LARGE, SWITCH_CONTAINER_HEIGHT_MEDIUM, SWITCH_CONTAINER_HEIGHT_SMALL, SWITCH_CONTAINER_WIDTH_LARGE, SWITCH_CONTAINER_WIDTH_MEDIUM, SWITCH_CONTAINER_WIDTH_SMALL, + SWITCH_THUMB_HEIGHT_LARGE, + SWITCH_THUMB_HEIGHT_MEDIUM, + SWITCH_THUMB_HEIGHT_SMALL, + SWITCH_THUMB_WIDTH_LARGE, + SWITCH_THUMB_WIDTH_MEDIUM, + SWITCH_THUMB_WIDTH_SMALL, } from '../src'; import { fireEvent, render, waitFor } from './test-utils'; -import { View } from 'react-native'; describe('Switch Component', () => { const switchMockTestId = 'switch-test-id'; @@ -73,3 +86,56 @@ describe('Switch Component', () => { expect(switchComponent.props.style.height).toBe(SWITCH_CONTAINER_HEIGHT_SMALL); }); }); + +describe('getSwitchSizes', () => { + const sizes = ['small', 'medium', 'large'] as const; + const types = ['ios', 'android'] as const; + + sizes.forEach(size => { + types.forEach(type => { + it(`returns correct styles for size=${size} and type=${type}`, () => { + const { thumbStyles, thumbContainerStyles } = getSwitchSizes({ size, type }); + + // check thumb styles + if (size === 'small') { + expect(thumbStyles.width).toBe(SWITCH_THUMB_WIDTH_SMALL); + expect(thumbStyles.height).toBe(SWITCH_THUMB_HEIGHT_SMALL); + } + if (size === 'medium') { + expect(thumbStyles.width).toBe(SWITCH_THUMB_WIDTH_MEDIUM); + expect(thumbStyles.height).toBe(SWITCH_THUMB_HEIGHT_MEDIUM); + } + if (size === 'large') { + expect(thumbStyles.width).toBe(SWITCH_THUMB_WIDTH_LARGE); + expect(thumbStyles.height).toBe(SWITCH_THUMB_HEIGHT_LARGE); + } + + // check container styles + if (size === 'small') { + expect(thumbContainerStyles.width).toBe( + type === 'android' ? SWITCH_CONTAINER_ANDROID_MODE_WIDTH_SMALL : SWITCH_CONTAINER_WIDTH_SMALL, + ); + expect(thumbContainerStyles.height).toBe( + type === 'android' ? SWITCH_CONTAINER_ANDROID_MODE_HEIGHT_SMALL : SWITCH_CONTAINER_HEIGHT_SMALL, + ); + } + if (size === 'medium') { + expect(thumbContainerStyles.width).toBe( + type === 'android' ? SWITCH_CONTAINER_ANDROID_MODE_WIDTH_MEDIUM : SWITCH_CONTAINER_WIDTH_MEDIUM, + ); + expect(thumbContainerStyles.height).toBe( + type === 'android' ? SWITCH_CONTAINER_ANDROID_MODE_HEIGHT_MEDIUM : SWITCH_CONTAINER_HEIGHT_MEDIUM, + ); + } + if (size === 'large') { + expect(thumbContainerStyles.width).toBe( + type === 'android' ? SWITCH_CONTAINER_ANDROID_MODE_WIDTH_LARGE : SWITCH_CONTAINER_WIDTH_LARGE, + ); + expect(thumbContainerStyles.height).toBe( + type === 'android' ? SWITCH_CONTAINER_ANDROID_MODE_HEIGHT_LARGE : SWITCH_CONTAINER_HEIGHT_LARGE, + ); + } + }); + }); + }); +}); diff --git a/src/packages/react-native-material-elements/__test__/TextFieldEndAdornment.test.tsx b/src/packages/react-native-material-elements/__test__/TextFieldEndAdornment.test.tsx index f199cdf..0962fa9 100644 --- a/src/packages/react-native-material-elements/__test__/TextFieldEndAdornment.test.tsx +++ b/src/packages/react-native-material-elements/__test__/TextFieldEndAdornment.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Text } from '../src'; +import { ActivityIndicator, Text } from '../src'; import TextFieldEndAdornment from '../src/components/TextField/TextFieldEndAdornment'; import { render } from './test-utils'; @@ -31,4 +31,41 @@ describe('TextFieldEndAdornment', () => { const loaderComponent = getByTestId(mockLoadingIndicatorTestId); expect(loaderComponent).toBeDefined(); }); + + it('should render the loading indicator when loading prop passed', () => { + const { getByTestId } = render(); + + const loader = getByTestId('loader'); + expect(loader).toBeDefined(); + }); + + it('renders ActivityIndicator when loading=true and showLoadingIndicatorWhenFocused=false', () => { + const { getByTestId, UNSAFE_getByType } = render( + , + ); + + const container = getByTestId('endAdornment'); + expect(container).toBeTruthy(); + expect(UNSAFE_getByType(ActivityIndicator)).toBeTruthy(); + }); + + it('renders ActivityIndicator when loading=true, showLoadingIndicatorWhenFocused=true, and isFocused=true', () => { + const { getByTestId, UNSAFE_getByType } = render( + , + ); + + const container = getByTestId('endAdornment'); + expect(container).toBeTruthy(); + expect(UNSAFE_getByType(ActivityIndicator)).toBeTruthy(); + }); + + it('returns null when no loading and no endAdornment', () => { + const { toJSON } = render(); + expect(toJSON()).toBeNull(); + }); + + it('returns null when showLoadingIndicatorWhenFocused=true but not focused', () => { + const { toJSON } = render(); + expect(toJSON()).toBeNull(); + }); }); diff --git a/src/packages/react-native-material-elements/__test__/__snapshots__/SegmentedControl.test.tsx.snap b/src/packages/react-native-material-elements/__test__/__snapshots__/SegmentedControl.test.tsx.snap new file mode 100644 index 0000000..4b6247c --- /dev/null +++ b/src/packages/react-native-material-elements/__test__/__snapshots__/SegmentedControl.test.tsx.snap @@ -0,0 +1,197 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SegmentedControl component should render correctly with default props 1`] = ` + + + + + + + + + + +`; + +exports[`SegmentedControlContainer component should render correctly with default props 1`] = ` + +`; + +exports[`SegmentedControlItem component should render correctly with default props 1`] = ` + + + + + +`; diff --git a/src/packages/react-native-material-elements/__test__/__snapshots__/Snackbar.test.tsx.snap b/src/packages/react-native-material-elements/__test__/__snapshots__/Snackbar.test.tsx.snap new file mode 100644 index 0000000..55f3d0f --- /dev/null +++ b/src/packages/react-native-material-elements/__test__/__snapshots__/Snackbar.test.tsx.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`snackbar utils should render with default props 1`] = `null`; diff --git a/src/packages/react-native-material-elements/__test__/utils.test.ts b/src/packages/react-native-material-elements/__test__/utils.test.ts index 49995c2..980a103 100644 --- a/src/packages/react-native-material-elements/__test__/utils.test.ts +++ b/src/packages/react-native-material-elements/__test__/utils.test.ts @@ -154,6 +154,11 @@ describe('merge utility', () => { const result = merge(componentStyles, themeComponentStyles); expect(result).toEqual({ backgroundColor: 'green', borderWidth: 10, borderRadius: 100, marginTop: 10, top: 200, right: 10 }); }); + + it('merges when both param1 and param2 are truthy non-array, non-object values', () => { + const result = merge('hello' as any, 123 as any); + expect(result).toEqual({ 0: 'h', 1: 'e', 2: 'l', 3: 'l', 4: 'o' }); + }); }); describe('getVariant', () => { diff --git a/src/packages/react-native-material-elements/examples/SegmentedControl.tsx b/src/packages/react-native-material-elements/examples/SegmentedControl.tsx index ded237e..392defd 100644 --- a/src/packages/react-native-material-elements/examples/SegmentedControl.tsx +++ b/src/packages/react-native-material-elements/examples/SegmentedControl.tsx @@ -10,9 +10,9 @@ function App(): React.JSX.Element { setIndex(['One', 'Two', 'Three', 'Four', 'Five'].findIndex(e => e === value) + 1)} + onChange={(_, index) => setIndex(index)} /> diff --git a/src/packages/react-native-material-elements/package.json b/src/packages/react-native-material-elements/package.json index 426abea..e54ef74 100644 --- a/src/packages/react-native-material-elements/package.json +++ b/src/packages/react-native-material-elements/package.json @@ -15,11 +15,6 @@ "url": "https://github.com/material-elements/react-native-material-elements/issues" }, "homepage": "https://github.com/material-elements/react-native-material-elements", - "scripts": { - "build": "babel src --out-dir lib", - "lint": "eslint .", - "test": "jest --coverage" - }, "dependencies": { "lodash": ">=4.17.0", "react": "*", @@ -28,60 +23,9 @@ }, "keywords": [ "react native material ui", - "react native material components", - "material design for react native", - "react native material library", - "react native material kit", - "react native material elements library", - "material theme react native", - "react native material buttons", - "material input react native", - "react native ui kit material", - "react native material card components", - "react-native", - "ios", - "android", - "ui-components", - "typescript", - "component-library", - "mobile", - "user-interface", - "modern-design", - "responsive", - "native", - "cross-platform", - "customizable", - "animations", - "styled-components", - "accessibility", - "design-system", - "lightweight", - "performance", - "developer-friendly", - "mobile-app", - "visual-design", - "material-elements" + "react native", + "react native ui" ], - "devDependencies": { - "@babel/runtime": "^7.20.0", - "@react-native/babel-preset": "0.74.81", - "@react-native/eslint-config": "0.74.81", - "@react-native/metro-config": "0.74.81", - "@react-native/typescript-config": "0.74.81", - "@testing-library/react-hooks": "^8.0.1", - "@types/jest": "^29.5.12", - "@types/lodash": "*", - "@types/react": "^18.2.6", - "@types/react-native-material-ripple": "^0.9.6", - "babel-jest": "^29.6.3", - "eslint": "^8.19.0", - "jest": "^29.6.3", - "prettier": "2.8.8", - "react-native-builder-bob": "^0.23.2", - "typescript": "5.0.4", - "@types/react-test-renderer": "^18.0.0", - "react-test-renderer": "18.2.0" - }, "engines": { "node": ">=18" } diff --git a/yarn.lock b/yarn.lock index e922df7..c3b2df5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1069,15 +1069,6 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@callstack/react-theme-provider@3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@callstack/react-theme-provider/-/react-theme-provider-3.0.3.tgz#f964dda28cd6e731c3fbcf916b0579c6f9fb2db7" - integrity sha512-B+9JBK7zsND/AdVkjwHvbb4cR05fJofLFG30hOeoXke8WkKAWN36yFljauAhI8qwlXlGFGZMYE1wQvsqBSccrA== - dependencies: - "@types/hoist-non-react-statics" "^3.3.1" - deepmerge "^3.2.0" - hoist-non-react-statics "^3.3.0" - "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.6.1" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.6.1.tgz#e4c58fdcf0696e7a5f19c30201ed43123ab15abc" @@ -1885,13 +1876,6 @@ dependencies: "@types/node" "*" -"@types/hoist-non-react-statics@^3.3.1": - version "3.3.7" - resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.7.tgz#306e3a3a73828522efa1341159da4846e7573a6c" - integrity sha512-PQTyIulDkIDro8P+IHbKCsw7U2xxBYflVzW/FgWdCAePD9xGSidgA76/GeJ6lBKoblyhf9pBY763gbrN+1dI8g== - dependencies: - hoist-non-react-statics "^3.3.0" - "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.6" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" @@ -2949,11 +2933,6 @@ deep-is@^0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== -deepmerge@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-3.3.0.tgz#d3c47fd6f3a93d517b14426b0628a17b0125f5f7" - integrity sha512-GRQOafGHwMHpjPx9iCvTgpu9NojZ49q794EEL94JVEw6VaeA8XTUyBKvAkOOjBX9oJNiV6G3P+T+tihFjo2TqA== - deepmerge@^4.2.2, deepmerge@^4.3.0: version "4.3.1" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" @@ -3654,11 +3633,6 @@ functions-have-names@^1.2.3: resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== -fuse.js@3.4.5: - version "3.4.5" - resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-3.4.5.tgz#8954fb43f9729bd5dbcb8c08f251db552595a7a6" - integrity sha512-s9PGTaQIkT69HaeoTVjwGsLfb8V8ScJLx5XGFcKHg0MqLUH/UZ4EKOtqtXX9k7AFqCGxD1aJmYb8Q5VYDibVRQ== - gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -3770,11 +3744,6 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -google-libphonenumber@^3.2.10: - version "3.2.42" - resolved "https://registry.yarnpkg.com/google-libphonenumber/-/google-libphonenumber-3.2.42.tgz#deac6d626bb57540449a844154d84e91d8da7df1" - integrity sha512-60jm6Lu72WmlUJXUBJmmuZlHG2vDJ2gQ9pL5gcFsSe1Q4eigsm0Z1ayNHjMgqGUl0zey8JqKtO4QCHPV+5LCNQ== - gopd@^1.0.1, gopd@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" @@ -3866,13 +3835,6 @@ hermes-parser@0.25.1: dependencies: hermes-estree "0.25.1" -hoist-non-react-statics@^3.3.0: - version "3.3.2" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" - integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== - dependencies: - react-is "^16.7.0" - html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -4861,11 +4823,6 @@ lodash.throttle@^4.1.1: resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== -lodash.toarray@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561" - integrity sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw== - lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" @@ -5217,13 +5174,6 @@ mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -modal-react-native-web@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/modal-react-native-web/-/modal-react-native-web-0.2.0.tgz#5daaa76213218fd25df739a267b11aed37e8c0c2" - integrity sha512-sC0/jL3ZL4bGtv1VS43TnrH7/FHUqgb7IU3VYWNDzuR223fYlpG5Gc974GsTP172Vi+lnnBL/G70xONmaggxeQ== - dependencies: - warning "^4.0.1" - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -5266,13 +5216,6 @@ node-dir@^0.1.17: dependencies: minimatch "^3.0.2" -node-emoji@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.10.0.tgz#8886abd25d9c7bb61802a658523d1f8d2a89b2da" - integrity sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw== - dependencies: - lodash.toarray "^4.4.0" - node-fetch@^2.2.0: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" @@ -5648,15 +5591,6 @@ prompts@^2.0.1, prompts@^2.4.2: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@15.7.2: - version "15.7.2" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" - integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.8.1" - prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" @@ -5698,11 +5632,6 @@ range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -react-async-hook@3.6.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/react-async-hook/-/react-async-hook-3.6.1.tgz#aed3e492d87319392865c83ed7cef3609e2a7fef" - integrity sha512-YWBB2feVQF79t5u2raMPHlZ8975Jds+guCvkWVC4kRLDlSCouLsYpQm4DGSqPeHvoHYVVcDfqNayLZAXQmnxnw== - react-devtools-core@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-5.3.2.tgz#d5df92f8ef2a587986d094ef2c47d84cf4ae46ec" @@ -5728,7 +5657,7 @@ react-hook-form@^7.58.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== -react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.1: +react-is@^16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -5738,26 +5667,6 @@ react-is@^17.0.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== -react-native-country-picker-modal@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/react-native-country-picker-modal/-/react-native-country-picker-modal-2.0.0.tgz#005421303349a81fedf5975e465405bb4b7312d5" - integrity sha512-p0wfkKx1mOCEkn3Qm2/FA8TrxSdUw/nqaCcT6KYvIGmPtPdia1Ce+iWh5G0j2hZcDs6yJSkYAx+7lrZ0HwixAw== - dependencies: - "@callstack/react-theme-provider" "3.0.3" - fuse.js "3.4.5" - modal-react-native-web "0.2.0" - node-emoji "1.10.0" - prop-types "15.7.2" - react-async-hook "3.6.1" - -react-native-phone-number-input@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/react-native-phone-number-input/-/react-native-phone-number-input-2.1.0.tgz#e9743d391d438d33b91ae3d03482b291b3d20ea5" - integrity sha512-EItzeDH6QUw6Kd1uwqFgcUl1YstxULB1M3HuCMHTvHVLoPE3ddjiuHyx+EHs0+4FcZtaXLQzLuC4cC/c4XIEuA== - dependencies: - google-libphonenumber "^3.2.10" - react-native-country-picker-modal "^2.0.0" - react-native-vector-icons@^10.2.0: version "10.2.0" resolved "https://registry.yarnpkg.com/react-native-vector-icons/-/react-native-vector-icons-10.2.0.tgz#f438f2ca16f7d6be658fd6ec8f0d2b7e2132b91c" @@ -6761,13 +6670,6 @@ walker@^1.0.7, walker@^1.0.8: dependencies: makeerror "1.0.12" -warning@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" - integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== - dependencies: - loose-envify "^1.0.0" - wcwidth@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" From 8bd033134ade36ccaa2338273898083acb3264e1 Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sat, 20 Sep 2025 23:13:02 +0530 Subject: [PATCH 05/26] [workflow/test] remove unused test cases --- .eslintrc.js | 2 +- .vscode/settings.json | 6 +- package.json | 5 +- .../TextInputFormValidation01.test.tsx | 76 ---------- yarn.lock | 133 +++++++++++------- 5 files changed, 95 insertions(+), 127 deletions(-) delete mode 100644 src/packages/react-native-material-elements/__test__/TextInputFormValidation01.test.tsx diff --git a/.eslintrc.js b/.eslintrc.js index 187894b..c6ead11 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,4 +1,4 @@ module.exports = { root: true, - extends: '@react-native', + extends: ['@react-native', 'plugin:testing-library/react'], }; diff --git a/.vscode/settings.json b/.vscode/settings.json index b6a51e5..8cb6c44 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,7 @@ { - "cSpell.words": ["Cocoapods"] + "cSpell.words": ["Cocoapods"], + "sonarlint.connectedMode.project": { + "connectionId": "material-elements", + "projectKey": "material-elements_react-native-material-elements" + } } diff --git a/package.json b/package.json index ce01b23..347b7c4 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "@react-native/metro-config": "0.76.3", "@react-native/typescript-config": "0.76.3", "@testing-library/react-hooks": "^8.0.1", + "@testing-library/react-native": "^12.9.0", "@types/jest": "^29.5.14", "@types/lodash": "^4.17.13", "@types/react": "^18.2.6", @@ -35,11 +36,11 @@ "@types/react-test-renderer": "^18.0.0", "babel-jest": "^29.6.3", "eslint": "^8.19.0", + "eslint-plugin-testing-library": "^7.8.0", "jest": "^29.6.3", "prettier": "2.8.8", "react-test-renderer": "18.2.0", - "typescript": "5.0.4", - "@testing-library/react-native": "^12.9.0" + "typescript": "5.0.4" }, "engines": { "node": ">=18" diff --git a/src/packages/react-native-material-elements/__test__/TextInputFormValidation01.test.tsx b/src/packages/react-native-material-elements/__test__/TextInputFormValidation01.test.tsx deleted file mode 100644 index 6dd8728..0000000 --- a/src/packages/react-native-material-elements/__test__/TextInputFormValidation01.test.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import React from 'react'; -import { fireEvent, waitFor } from '@testing-library/react-native'; -import { TextInputFormValidation01 } from '../examples/form-validation/TextInputFormValidation01'; -import { render } from './test-utils'; - -describe('TextInputFormValidation01', () => { - const submitButtonLabel = 'Save'; - - beforeAll(() => { - jest.useFakeTimers(); - }); - - afterAll(() => { - jest.useRealTimers(); - }); - - it('renders input and button', () => { - const { getByPlaceholderText, getByText } = render(); - expect(getByPlaceholderText('Email')).toBeTruthy(); - expect(getByText(submitButtonLabel)).toBeTruthy(); - }); - - it('shows error message when email is empty', async () => { - const { getByText } = render(); - const saveButton = getByText(submitButtonLabel); - - fireEvent.press(saveButton, { nativeEvent: {} }); - - await waitFor(() => { - expect(getByText(/email/i)).toBeTruthy(); - }); - }); - - it('shows error message when email is invalid', async () => { - const { getByPlaceholderText, getByText } = render(); - const emailInput = getByPlaceholderText('Email'); - const saveButton = getByText(submitButtonLabel); - - fireEvent.changeText(emailInput, 'invalid-email'); - fireEvent.press(saveButton, { nativeEvent: {} }); - - await waitFor(() => { - expect(getByText(/email must be a valid/i)).toBeTruthy(); - }); - }); - - it('shows error message when email is invalid 2', async () => { - const { getByPlaceholderText, getByText } = render(); - const emailInput = getByPlaceholderText('Email'); - const saveButton = getByText(submitButtonLabel); - - fireEvent.changeText(emailInput, 123); - fireEvent.press(saveButton, { nativeEvent: {} }); - - await waitFor(() => { - expect(getByText(/email must be a valid/i)).toBeTruthy(); - }); - }); - - it('submits form when email is valid', async () => { - const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); - const { getByPlaceholderText, getByText } = render(); - - const emailInput = getByPlaceholderText('Email'); - const saveButton = getByText(submitButtonLabel); - - fireEvent.changeText(emailInput, 'test@example.com'); - fireEvent.press(saveButton, { nativeEvent: {} }); - - await waitFor(() => { - expect(consoleSpy).toHaveBeenCalledWith({ email: 'test@example.com' }); - }); - - consoleSpy.mockRestore(); - }); -}); diff --git a/yarn.lock b/yarn.lock index c3b2df5..f9ea7a6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1076,6 +1076,13 @@ dependencies: eslint-visitor-keys "^3.4.3" +"@eslint-community/eslint-utils@^4.7.0": + version "4.9.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz#7308df158e064f0dd8b8fdb58aa14fa2a7f913b3" + integrity sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g== + dependencies: + eslint-visitor-keys "^3.4.3" + "@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.1": version "4.12.1" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" @@ -1113,13 +1120,6 @@ dependencies: "@hapi/hoek" "^9.0.0" -"@hookform/resolvers@^5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-5.1.1.tgz#91074ba4fb749cc74e6465e75d38256146b0c4ab" - integrity sha512-J/NVING3LMAEvexJkyTLjruSm7aOFx7QX21pzkiJfMoNG0wl5aFEjLTl7ay7IQb9EWY6AkrBy7tHL2Alijpdcg== - dependencies: - "@standard-schema/utils" "^0.3.0" - "@humanwhocodes/config-array@^0.13.0": version "0.13.0" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748" @@ -1814,11 +1814,6 @@ dependencies: "@sinonjs/commons" "^3.0.0" -"@standard-schema/utils@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@standard-schema/utils/-/utils-0.3.0.tgz#3d5e608f16c2390c10528e98e59aef6bf73cae7b" - integrity sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g== - "@testing-library/react-hooks@^8.0.1": version "8.0.1" resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-8.0.1.tgz#0924bbd5b55e0c0c0502d1754657ada66947ca12" @@ -2024,6 +2019,15 @@ "@typescript-eslint/visitor-keys" "7.18.0" debug "^4.3.4" +"@typescript-eslint/project-service@8.44.0": + version "8.44.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.44.0.tgz#89060651dcecde946e758441fe94dceb6f769a29" + integrity sha512-ZeaGNraRsq10GuEohKTo4295Z/SuGcSq2LzfGlqiuEvfArzo/VRrT0ZaJsVPuKZ55lVbNk8U6FcL+ZMH8CoyVA== + dependencies: + "@typescript-eslint/tsconfig-utils" "^8.44.0" + "@typescript-eslint/types" "^8.44.0" + debug "^4.3.4" + "@typescript-eslint/scope-manager@5.62.0": version "5.62.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" @@ -2040,6 +2044,19 @@ "@typescript-eslint/types" "7.18.0" "@typescript-eslint/visitor-keys" "7.18.0" +"@typescript-eslint/scope-manager@8.44.0", "@typescript-eslint/scope-manager@^8.15.0": + version "8.44.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.44.0.tgz#c37f1e786fd0e5b40607985c769a61c24c761c26" + integrity sha512-87Jv3E+al8wpD+rIdVJm/ItDBe/Im09zXIjFoipOjr5gHUhJmTzfFLuTJ/nPTMc2Srsroy4IBXwcTCHyRR7KzA== + dependencies: + "@typescript-eslint/types" "8.44.0" + "@typescript-eslint/visitor-keys" "8.44.0" + +"@typescript-eslint/tsconfig-utils@8.44.0", "@typescript-eslint/tsconfig-utils@^8.44.0": + version "8.44.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.44.0.tgz#8c0601372bf889f0663a08df001ad666442aa3a8" + integrity sha512-x5Y0+AuEPqAInc6yd0n5DAcvtoQ/vyaGwuX5HE9n6qAefk1GaedqrLQF8kQGylLUb9pnZyLf+iEiL9fr8APDtQ== + "@typescript-eslint/type-utils@7.18.0": version "7.18.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz#2165ffaee00b1fbbdd2d40aa85232dab6998f53b" @@ -2060,6 +2077,11 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.18.0.tgz#b90a57ccdea71797ffffa0321e744f379ec838c9" integrity sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ== +"@typescript-eslint/types@8.44.0", "@typescript-eslint/types@^8.44.0": + version "8.44.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.44.0.tgz#4b9154ab164a0beff22d3217ff0fdc8d10bce924" + integrity sha512-ZSl2efn44VsYM0MfDQe68RKzBz75NPgLQXuGypmym6QVOWL5kegTZuZ02xRAT9T+onqvM6T8CdQk0OwYMB6ZvA== + "@typescript-eslint/typescript-estree@5.62.0": version "5.62.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" @@ -2087,6 +2109,22 @@ semver "^7.6.0" ts-api-utils "^1.3.0" +"@typescript-eslint/typescript-estree@8.44.0": + version "8.44.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.44.0.tgz#e23e9946c466cf5f53b7e46ecdd9789fd8192daa" + integrity sha512-lqNj6SgnGcQZwL4/SBJ3xdPEfcBuhCG8zdcwCPgYcmiPLgokiNDKlbPzCwEwu7m279J/lBYWtDYL+87OEfn8Jw== + dependencies: + "@typescript-eslint/project-service" "8.44.0" + "@typescript-eslint/tsconfig-utils" "8.44.0" + "@typescript-eslint/types" "8.44.0" + "@typescript-eslint/visitor-keys" "8.44.0" + debug "^4.3.4" + fast-glob "^3.3.2" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^2.1.0" + "@typescript-eslint/utils@7.18.0": version "7.18.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.18.0.tgz#bca01cde77f95fc6a8d5b0dbcbfb3d6ca4be451f" @@ -2111,6 +2149,16 @@ eslint-scope "^5.1.1" semver "^7.3.7" +"@typescript-eslint/utils@^8.15.0": + version "8.44.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.44.0.tgz#2c0650a1e8a832ed15658e7ca3c7bd2818d92c7c" + integrity sha512-nktOlVcg3ALo0mYlV+L7sWUD58KG4CMj1rb2HUVOO4aL3K/6wcD+NERqd0rrA5Vg06b42YhF6cFxeixsp9Riqg== + dependencies: + "@eslint-community/eslint-utils" "^4.7.0" + "@typescript-eslint/scope-manager" "8.44.0" + "@typescript-eslint/types" "8.44.0" + "@typescript-eslint/typescript-estree" "8.44.0" + "@typescript-eslint/visitor-keys@5.62.0": version "5.62.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" @@ -2127,6 +2175,14 @@ "@typescript-eslint/types" "7.18.0" eslint-visitor-keys "^3.4.3" +"@typescript-eslint/visitor-keys@8.44.0": + version "8.44.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.44.0.tgz#0d9d5647e005c2ff8acc391d1208ab37d08850aa" + integrity sha512-zaz9u8EJ4GBmnehlrpoKvj/E3dNbuQ7q0ucyZImm3cLqJ8INTc970B1qEqDX/Rzq65r3TvVTN7kHWPBoyW7DWw== + dependencies: + "@typescript-eslint/types" "8.44.0" + eslint-visitor-keys "^4.2.1" + "@ungap/structured-clone@^1.2.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" @@ -3291,6 +3347,14 @@ eslint-plugin-react@^7.30.1: string.prototype.matchall "^4.0.12" string.prototype.repeat "^1.0.0" +eslint-plugin-testing-library@^7.8.0: + version "7.8.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-7.8.0.tgz#f18b95ad9710c32a7630c48fdfcba826e7c5d06a" + integrity sha512-zmu9xtpULN5KCtJBABBmXK3jfKZej2ZJ6QzCX4MtywP3UTJ7yn/Zful8Kn5mUiOCxX6KBt0to3OZf7Usuhtvfg== + dependencies: + "@typescript-eslint/scope-manager" "^8.15.0" + "@typescript-eslint/utils" "^8.15.0" + eslint-scope@5.1.1, eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -3317,6 +3381,11 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== +eslint-visitor-keys@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" + integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== + eslint@^8.19.0: version "8.57.1" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.1.tgz#7df109654aba7e3bbe5c8eae533c5e461d3c6ca9" @@ -5600,11 +5669,6 @@ prop-types@^15.7.2, prop-types@^15.8.1: object-assign "^4.1.1" react-is "^16.13.1" -property-expr@^2.0.5: - version "2.0.6" - resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.6.tgz#f77bc00d5928a6c748414ad12882e83f24aec1e8" - integrity sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA== - punycode@^2.1.0: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" @@ -5647,11 +5711,6 @@ react-error-boundary@^3.1.0: dependencies: "@babel/runtime" "^7.12.5" -react-hook-form@^7.58.0: - version "7.58.0" - resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.58.0.tgz#4d23308b587d637effe4e581f410e1ca8c434bef" - integrity sha512-zGijmEed35oNfOfy7ub99jfjkiLhHwA3dl5AgyKdWC6QQzhnc7tkWewSa+T+A2EpLrc6wo5DUoZctS9kufWJjA== - "react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^18.0.0, react-is@^18.2.0: version "18.3.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" @@ -6430,11 +6489,6 @@ throat@^5.0.0: resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== -tiny-case@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tiny-case/-/tiny-case-1.0.3.tgz#d980d66bc72b5d5a9ca86fb7c9ffdb9c898ddd03" - integrity sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q== - tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" @@ -6452,11 +6506,6 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== -toposort@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330" - integrity sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg== - tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -6467,6 +6516,11 @@ ts-api-utils@^1.3.0: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.4.3.tgz#bfc2215fe6528fecab2b0fba570a2e8a4263b064" integrity sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw== +ts-api-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz#595f7094e46eed364c13fd23e75f9513d29baf91" + integrity sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ== + tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" @@ -6511,11 +6565,6 @@ type-fest@^0.7.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== -type-fest@^2.19.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" - integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== - typed-array-buffer@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536" @@ -6902,13 +6951,3 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -yup@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/yup/-/yup-1.6.1.tgz#8defcff9daaf9feac178029c0e13b616563ada4b" - integrity sha512-JED8pB50qbA4FOkDol0bYF/p60qSEDQqBD0/qeIrUCG1KbPBIQ776fCUNb9ldbPcSTxA69g/47XTo4TqWiuXOA== - dependencies: - property-expr "^2.0.5" - tiny-case "^1.0.3" - toposort "^2.0.2" - type-fest "^2.19.0" From 878782bbfbf2c970d469931d6d6f09ad2a5858b8 Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sat, 20 Sep 2025 23:20:49 +0530 Subject: [PATCH 06/26] [workflow/test] Added lint workflow --- .github/workflows/lint.yml | 21 +++++++++++++++++++ .../SegmentedControl/SegmentedControlItem.tsx | 2 +- .../src/components/Skeleton/Skeleton.tsx | 2 +- .../components/TextField/TextField.style.ts | 1 - .../src/components/TextField/TextField.tsx | 10 ++++++--- 5 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..cf31d44 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,21 @@ +name: Lint +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize, reopened] + +jobs: + eslint: + name: "Es lint check" + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Run ESLint + run: yarn run lint + continue-on-error: false \ No newline at end of file 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 81d553b..ac705bc 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 @@ -68,7 +68,7 @@ export const SegmentedControlItem = ({ ); } return null; - }, [data, headingStyles]); + }, [data, headingStyles, segmentItemContainerStyles]); return ( = ({ backgroundColor, animationDu }), ]), ).start(); - }, []); + }, [animationDuration, shimmerAnim]); const opacity = shimmerAnim.interpolate({ inputRange: [0, 1], diff --git a/src/packages/react-native-material-elements/src/components/TextField/TextField.style.ts b/src/packages/react-native-material-elements/src/components/TextField/TextField.style.ts index e2572dc..83d55ae 100644 --- a/src/packages/react-native-material-elements/src/components/TextField/TextField.style.ts +++ b/src/packages/react-native-material-elements/src/components/TextField/TextField.style.ts @@ -2,7 +2,6 @@ import { ColorValue, StyleProp, TextStyle, ViewStyle } from 'react-native'; import { Theme } from '../../libraries/themes/theme'; import { getVariant, screenWidth } from '../../utils'; import { - INPUT_DEFAULT_BORDER_RADIUS, INPUT_DEFAULT_BORDER_WIDTH, INPUT_DEFAULT_HEIGHT, INPUT_LARGE_HEIGHT, diff --git a/src/packages/react-native-material-elements/src/components/TextField/TextField.tsx b/src/packages/react-native-material-elements/src/components/TextField/TextField.tsx index f023c3a..fdd45cf 100644 --- a/src/packages/react-native-material-elements/src/components/TextField/TextField.tsx +++ b/src/packages/react-native-material-elements/src/components/TextField/TextField.tsx @@ -101,9 +101,13 @@ export const TextField = React.forwardRef( const shouldApplySquareShape = square ?? textFieldThemeConfig?.square ?? false; const getTextFiledHeight = () => { - if (height) return height; - else if (isOutlined && textFieldOutlinedHeight) return textFieldOutlinedHeight; - else if (!isOutlined && textFieldFieldHeight) return textFieldFieldHeight; + if (height) { + return height; + } else if (isOutlined && textFieldOutlinedHeight) { + return textFieldOutlinedHeight; + } else if (!isOutlined && textFieldFieldHeight) { + return textFieldFieldHeight; + } return textFieldThemeConfig?.height; }; From 7b984502b3ea6f0e976a775f8fc035f11027d42e Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sat, 20 Sep 2025 23:22:28 +0530 Subject: [PATCH 07/26] [workflow/test] updated workflow --- .github/actions/install-dependencies/action.yml | 8 ++++++++ .github/workflows/lint.yml | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/.github/actions/install-dependencies/action.yml b/.github/actions/install-dependencies/action.yml index b9bc5f2..293f0c4 100644 --- a/.github/actions/install-dependencies/action.yml +++ b/.github/actions/install-dependencies/action.yml @@ -9,6 +9,14 @@ runs: node-version: 20 cache: 'yarn' + - name: Cache node modules + uses: actions/cache@v3 + with: + path: node_modules + key: ${{ runner.os }}-node-${{ hashFiles('yarn.lock') }} + restore-keys: | + ${{ runner.os }}-node- + - name: Install dependencies run: yarn install shell: bash \ No newline at end of file diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index cf31d44..240988c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -16,6 +16,11 @@ jobs: 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 From 915ffd1ead0fa4828860714236d9e262c312a9e0 Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sun, 21 Sep 2025 00:34:06 +0530 Subject: [PATCH 08/26] [workflow/test] Added eslint config = --- .eslintignore | 6 ++++++ .eslintrc.js | 18 ++++++++++++++++++ .prettierrc.js | 4 +++- metro.config.js | 2 +- package.json | 1 + .../.prettierrc.js | 9 --------- .../babel.config.js | 3 --- .../src/components/Button/Button.types.d.ts | 2 +- .../src/components/CheckBox/CheckBox.tsx | 1 + yarn.lock | 5 +++++ 10 files changed, 36 insertions(+), 15 deletions(-) create mode 100644 .eslintignore delete mode 100644 src/packages/react-native-material-elements/.prettierrc.js delete mode 100644 src/packages/react-native-material-elements/babel.config.js diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..f56f9f2 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,6 @@ +node_modules/ +examples/ +__test__/ + +.github +coverage/ diff --git a/.eslintrc.js b/.eslintrc.js index c6ead11..5aa518c 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,4 +1,22 @@ module.exports = { root: true, extends: ['@react-native', 'plugin:testing-library/react'], + ignorePatterns: ['*.js', '*.ts', '*.tsx', 'jest.*', 'metro.config.js', '.eslintrc.js'], + overrides: [ + { + files: ['src/**/*.{js,jsx,ts,tsx}'], + rules: { + 'object-curly-spacing': ['error', 'always'], + 'unused-imports/no-unused-imports': 'error', + }, + }, + ], + env: { jest: true }, + parserOptions: { + sourceType: 'module', + useJSXTextNode: true, + tsconfigRootDir: __dirname, + project: './tsconfig.json', + }, + plugins: ['unused-imports'], }; diff --git a/.prettierrc.js b/.prettierrc.js index 2b54074..1f01b43 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -1,7 +1,9 @@ module.exports = { arrowParens: 'avoid', bracketSameLine: true, - bracketSpacing: false, + bracketSpacing: true, singleQuote: true, trailingComma: 'all', + tabWidth: 2, + printWidth: 130, }; diff --git a/metro.config.js b/metro.config.js index 9d41685..72fcb3c 100644 --- a/metro.config.js +++ b/metro.config.js @@ -1,4 +1,4 @@ -const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config'); +const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config'); /** * Metro configuration diff --git a/package.json b/package.json index 347b7c4..bf00d93 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "babel-jest": "^29.6.3", "eslint": "^8.19.0", "eslint-plugin-testing-library": "^7.8.0", + "eslint-plugin-unused-imports": "^4.2.0", "jest": "^29.6.3", "prettier": "2.8.8", "react-test-renderer": "18.2.0", diff --git a/src/packages/react-native-material-elements/.prettierrc.js b/src/packages/react-native-material-elements/.prettierrc.js deleted file mode 100644 index 1f01b43..0000000 --- a/src/packages/react-native-material-elements/.prettierrc.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - arrowParens: 'avoid', - bracketSameLine: true, - bracketSpacing: true, - singleQuote: true, - trailingComma: 'all', - tabWidth: 2, - printWidth: 130, -}; diff --git a/src/packages/react-native-material-elements/babel.config.js b/src/packages/react-native-material-elements/babel.config.js deleted file mode 100644 index f7b3da3..0000000 --- a/src/packages/react-native-material-elements/babel.config.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - presets: ['module:@react-native/babel-preset'], -}; diff --git a/src/packages/react-native-material-elements/src/components/Button/Button.types.d.ts b/src/packages/react-native-material-elements/src/components/Button/Button.types.d.ts index f7f63e3..42964e7 100644 --- a/src/packages/react-native-material-elements/src/components/Button/Button.types.d.ts +++ b/src/packages/react-native-material-elements/src/components/Button/Button.types.d.ts @@ -2,7 +2,7 @@ import React from 'react'; import { ActivityIndicatorProps, ColorValue, TextStyle, TouchableWithoutFeedback, ViewProps, ViewStyle } from 'react-native'; import { ThemedIconProp } from '../../hooks'; import { BaseStyles, StyledProps } from '../../libraries/style/styleTypes'; -import { Theme, ThemeDimensions } from '../../libraries/themes/theme'; +import { Theme } from '../../libraries/themes/theme'; import { VariantTypes } from '../../utils'; import { RipplePosition, RippleProps } from '../Ripple/Ripple.types'; diff --git a/src/packages/react-native-material-elements/src/components/CheckBox/CheckBox.tsx b/src/packages/react-native-material-elements/src/components/CheckBox/CheckBox.tsx index 00f11cf..452c172 100644 --- a/src/packages/react-native-material-elements/src/components/CheckBox/CheckBox.tsx +++ b/src/packages/react-native-material-elements/src/components/CheckBox/CheckBox.tsx @@ -165,6 +165,7 @@ export const CheckBox = React.forwardRef( }, [isChecked, variant, themeColors, checkBoxColorValue, themeVariantColors, size]); return ( + // eslint-disable-next-line react-native/no-inline-styles {shouldRenderAdornment && renderAdornment()} diff --git a/yarn.lock b/yarn.lock index f9ea7a6..45a60c2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3355,6 +3355,11 @@ eslint-plugin-testing-library@^7.8.0: "@typescript-eslint/scope-manager" "^8.15.0" "@typescript-eslint/utils" "^8.15.0" +eslint-plugin-unused-imports@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.2.0.tgz#d83b23be66ae7713734c884df95988f039eb8362" + integrity sha512-hLbJ2/wnjKq4kGA9AUaExVFIbNzyxYdVo49QZmKCnhk5pc9wcYRbfgLHvWJ8tnsdcseGhoUAddm9gn/lt+d74w== + eslint-scope@5.1.1, eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" From 8c8bf38dc13b8ce90be71e540cf61e9ec0c6630c Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sun, 21 Sep 2025 00:44:29 +0530 Subject: [PATCH 09/26] [workflow/test] Added sonar config --- .eslintrc.js | 18 ++++++++---------- App.tsx | 7 ++----- Component.tsx | 4 ++-- index.js | 4 ++-- sonar-project.properties | 11 +++++++++++ 5 files changed, 25 insertions(+), 19 deletions(-) create mode 100644 sonar-project.properties diff --git a/.eslintrc.js b/.eslintrc.js index 5aa518c..1f1f398 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,16 +1,7 @@ module.exports = { root: true, extends: ['@react-native', 'plugin:testing-library/react'], - ignorePatterns: ['*.js', '*.ts', '*.tsx', 'jest.*', 'metro.config.js', '.eslintrc.js'], - overrides: [ - { - files: ['src/**/*.{js,jsx,ts,tsx}'], - rules: { - 'object-curly-spacing': ['error', 'always'], - 'unused-imports/no-unused-imports': 'error', - }, - }, - ], + ignorePatterns: ['.eslintrc.js', '**/*.test.tsx', '**/*.test.ts'], env: { jest: true }, parserOptions: { sourceType: 'module', @@ -19,4 +10,11 @@ module.exports = { project: './tsconfig.json', }, plugins: ['unused-imports'], + rules: { + 'object-curly-spacing': ['error', 'always'], + 'unused-imports/no-unused-imports': 'error', + complexity: ['error', 8], + 'import/extensions': 0, + 'react/jsx-filename-extension': [2, { extensions: ['.tsx'] }], + }, }; diff --git a/App.tsx b/App.tsx index 5e12a59..486e2a3 100644 --- a/App.tsx +++ b/App.tsx @@ -1,9 +1,6 @@ import React from 'react'; -import {SafeAreaView, ScrollView} from 'react-native'; -import { - Container, - ThemeProvider, -} from './src/packages/react-native-material-elements'; +import { SafeAreaView, ScrollView } from 'react-native'; +import { Container, ThemeProvider } from './src/packages/react-native-material-elements'; function App(): React.JSX.Element { return ( diff --git a/Component.tsx b/Component.tsx index f747502..f71a970 100644 --- a/Component.tsx +++ b/Component.tsx @@ -1,8 +1,8 @@ import React from 'react'; -import {Box, useTheme} from './src/packages/react-native-material-elements/src'; +import { Box, useTheme } from './src/packages/react-native-material-elements/src'; export const Component = () => { - const {theme} = useTheme(); + const { theme } = useTheme(); console.log(theme.colors.scan); diff --git a/index.js b/index.js index a850d03..9b73932 100644 --- a/index.js +++ b/index.js @@ -2,8 +2,8 @@ * @format */ -import {AppRegistry} from 'react-native'; +import { AppRegistry } from 'react-native'; import App from './App'; -import {name as appName} from './app.json'; +import { name as appName } from './app.json'; AppRegistry.registerComponent(appName, () => App); diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..3a7d756 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,11 @@ +sonar.projectKey=material-elements_react-native-material-elements +sonar.organization=material-elements + +sonar.coverage.exclusions=**/android/**/*.*,**/ios/**/*.*,**/*.test.ts,**/*test.ts,**/*.test.tsx,**/*test.tsx,**/tests/**,**/specs/** + +sonar.exclusions=**/android/**/*.*,**/ios/**/*.* + +sonar.javascript.file.suffixes=.js,.jsx +sonar.typescript.file.suffixes=.ts,.tsx + +sonar.javascript.lcov.reportPaths=coverage/lcov.info \ No newline at end of file From 3786b18d25cb579a3a1e3c1835156b66076d6c3e Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sun, 21 Sep 2025 00:47:52 +0530 Subject: [PATCH 10/26] [workflow/test] updated sonar qube config --- sonar-project.properties | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sonar-project.properties b/sonar-project.properties index 3a7d756..7806df6 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,10 +1,13 @@ sonar.projectKey=material-elements_react-native-material-elements sonar.organization=material-elements -sonar.coverage.exclusions=**/android/**/*.*,**/ios/**/*.*,**/*.test.ts,**/*test.ts,**/*.test.tsx,**/*test.tsx,**/tests/**,**/specs/** - +# Exclude test files from analysis +sonar.exclusions=**/__tests__/**,**/*.test.{js,ts,tsx},**/*.spec.{js,ts,tsx} sonar.exclusions=**/android/**/*.*,**/ios/**/*.* +# Optionally exclude from coverage calculation +sonar.coverage.exclusions=**/__tests__/**,**/*.test.{js,ts,tsx},**/*.spec.{js,ts,tsx} + sonar.javascript.file.suffixes=.js,.jsx sonar.typescript.file.suffixes=.ts,.tsx From 3dc99c8df3c7e6d35d14b8be02d07cc267aad3cf Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sun, 21 Sep 2025 00:56:04 +0530 Subject: [PATCH 11/26] [workflow/test] Updated the jest config file for testing --- .sonarlint/Ffi_staticLib.json | 5 +++++ jest.config.js | 16 +++------------- 2 files changed, 8 insertions(+), 13 deletions(-) create mode 100644 .sonarlint/Ffi_staticLib.json diff --git a/.sonarlint/Ffi_staticLib.json b/.sonarlint/Ffi_staticLib.json new file mode 100644 index 0000000..45fb956 --- /dev/null +++ b/.sonarlint/Ffi_staticLib.json @@ -0,0 +1,5 @@ +{ + "sonarCloudOrganization": "material-elements", + "projectKey": "material-elements_react-native-material-elements", + "region": "EU" +} diff --git a/jest.config.js b/jest.config.js index 53c0f4a..38d4df2 100644 --- a/jest.config.js +++ b/jest.config.js @@ -24,27 +24,17 @@ module.exports = { coverageReporters: ['html', 'text', 'lcov', 'text-summary'], - moduleFileExtensions: [ - 'ts', - 'tsx', - 'js', - 'jsx', - 'json', - 'node', - 'mjs', - 'svg', - 'png', - ], + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node', 'mjs', 'svg', 'png'], testEnvironment: 'node', setupFiles: ['./jest.setup.ts'], coverageThreshold: { global: { - branches: 80, + statements: 80, + branches: 70, functions: 80, lines: 80, - statements: 80, }, }, }; From a270b6d9dda56d29bc78362fe6a4fbf6ff157cd4 Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sun, 21 Sep 2025 01:12:10 +0530 Subject: [PATCH 12/26] [workflow/test] Updated the sonar config --- .github/workflows/code-check.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/code-check.yaml b/.github/workflows/code-check.yaml index 01bb995..685e783 100644 --- a/.github/workflows/code-check.yaml +++ b/.github/workflows/code-check.yaml @@ -25,6 +25,9 @@ jobs: - name: SonarCloud Scan uses: SonarSource/sonarcloud-github-action@master + with: + organization: material-elements + projectKey: material-elements_react-native-material-elements env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} \ No newline at end of file From 363419926224d22072f121e8ea35a3543461a2c6 Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sun, 21 Sep 2025 01:15:40 +0530 Subject: [PATCH 13/26] [workflow/test] Updated the sonar config --- .github/workflows/code-check.yaml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/code-check.yaml b/.github/workflows/code-check.yaml index 685e783..2b49635 100644 --- a/.github/workflows/code-check.yaml +++ b/.github/workflows/code-check.yaml @@ -24,10 +24,7 @@ jobs: continue-on-error: false - name: SonarCloud Scan - uses: SonarSource/sonarcloud-github-action@master - with: - organization: material-elements - projectKey: material-elements_react-native-material-elements + uses: sonarsource/sonarcloud-github-action@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} \ No newline at end of file From fdca8908df50ed1cf7f2c31b0ab1b76cb2026fa0 Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sun, 21 Sep 2025 01:22:22 +0530 Subject: [PATCH 14/26] [workflow/test] Updated jest config --- jest.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jest.config.js b/jest.config.js index 38d4df2..dbaecd4 100644 --- a/jest.config.js +++ b/jest.config.js @@ -32,7 +32,7 @@ module.exports = { coverageThreshold: { global: { statements: 80, - branches: 70, + branches: 80, functions: 80, lines: 80, }, From 99e291d574361da28cc9fc258fdee40692ecdea3 Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sun, 21 Sep 2025 15:11:27 +0530 Subject: [PATCH 15/26] [workflow/test] Updated test cases --- .eslintrc.js | 2 +- .github/workflows/lint.yml | 2 +- .../__test__/BaseButton.test.tsx | 8 + .../__test__/DropDown.test.tsx | 220 ++++++++++++- .../__test__/Text.test.tsx | 9 +- .../__snapshots__/Accordion.test.tsx.snap | 2 +- .../__snapshots__/Alert.test.tsx.snap | 2 +- .../__snapshots__/AppBar.test.tsx.snap | 2 +- .../__snapshots__/Avatar.test.tsx.snap | 2 +- .../__snapshots__/Backdrop.test.tsx.snap | 2 +- .../BackgroundFill.test.tsx.snap | 2 +- .../__snapshots__/Badge.test.tsx.snap | 2 +- .../__snapshots__/BaseButton.test.tsx.snap | 2 +- .../__test__/__snapshots__/Box.test.tsx.snap | 2 +- .../__snapshots__/Button.test.tsx.snap | 2 +- .../__snapshots__/ButtonGroup.test.tsx.snap | 2 +- .../__test__/__snapshots__/Card.test.tsx.snap | 2 +- .../__snapshots__/CheckBox.test.tsx.snap | 2 +- .../__test__/__snapshots__/Chip.test.tsx.snap | 2 +- .../__snapshots__/Container.test.tsx.snap | 2 +- .../__snapshots__/Dialog.test.tsx.snap | 2 +- .../__snapshots__/Divider.test.tsx.snap | 2 +- .../__snapshots__/DropDown.test.tsx.snap | 288 +++++++++++++++++- .../__test__/__snapshots__/Grid.test.tsx.snap | 2 +- .../__snapshots__/IconButton.test.tsx.snap | 2 +- .../__snapshots__/IconInput.test.tsx.snap | 2 +- .../__snapshots__/ImageList.test.tsx.snap | 2 +- .../__test__/__snapshots__/List.test.tsx.snap | 2 +- .../__test__/__snapshots__/Menu.test.tsx.snap | 2 +- .../ModalContainer.test.tsx.snap | 2 +- .../__snapshots__/OtpInput.test.tsx.snap | 2 +- .../__snapshots__/Pagination.test.tsx.snap | 2 +- .../QuantityStepper.test.tsx.snap | 2 +- .../__snapshots__/Radio.test.tsx.snap | 2 +- .../__snapshots__/Stack.test.tsx.snap | 2 +- .../__snapshots__/Switch.test.tsx.snap | 2 +- .../__test__/__snapshots__/Text.test.tsx.snap | 11 +- .../__snapshots__/TextField.test.tsx.snap | 2 +- .../TextFieldEndAdornment.test.tsx.snap | 2 +- .../useThemedProps.test.tsx.snap | 2 +- .../src/components/Button/BaseButton.tsx | 3 +- .../src/components/DropDown/DropDown.tsx | 21 +- 42 files changed, 583 insertions(+), 47 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 1f1f398..b3eca8f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,7 +1,7 @@ module.exports = { root: true, extends: ['@react-native', 'plugin:testing-library/react'], - ignorePatterns: ['.eslintrc.js', '**/*.test.tsx', '**/*.test.ts'], + ignorePatterns: ['.eslintrc.js', '**/*.test.tsx', '**/*.test.ts', '**/*.config.js'], env: { jest: true }, parserOptions: { sourceType: 'module', diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 240988c..0cb2386 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -8,7 +8,7 @@ on: jobs: eslint: - name: "Es lint check" + name: "Eslint check" runs-on: ubuntu-latest steps: diff --git a/src/packages/react-native-material-elements/__test__/BaseButton.test.tsx b/src/packages/react-native-material-elements/__test__/BaseButton.test.tsx index 9ec81e6..105d21c 100644 --- a/src/packages/react-native-material-elements/__test__/BaseButton.test.tsx +++ b/src/packages/react-native-material-elements/__test__/BaseButton.test.tsx @@ -69,4 +69,12 @@ describe('Base button component', () => { expect(mockOnPress).toHaveBeenCalled(); expect(mockOnPress).toHaveBeenCalledTimes(1); }); + + it('should called the onLongPress function', () => { + jest.useFakeTimers(); + const { getByTestId } = render(); + const button = getByTestId(mockTestId); + fireEvent(button, 'longPress', { nativeEvent: {} }); + expect(mockOnLongPress).toHaveBeenCalled(); + }); }); diff --git a/src/packages/react-native-material-elements/__test__/DropDown.test.tsx b/src/packages/react-native-material-elements/__test__/DropDown.test.tsx index f5dc74c..db60a29 100644 --- a/src/packages/react-native-material-elements/__test__/DropDown.test.tsx +++ b/src/packages/react-native-material-elements/__test__/DropDown.test.tsx @@ -1,9 +1,11 @@ import React from 'react'; -import { DropDown, Text } from '../src'; +import * as RN from 'react-native'; +import { DropDown, DropDownListContainer, gray, Text } from '../src'; import { fireEvent, render, waitFor } from './test-utils'; describe('DropDown Component', () => { const mockInputWrapperTouchTestId = 'input-wrapper-touch-test-id'; + const mockInputTestId = 'input-test-id'; beforeEach(() => { jest.clearAllMocks(); @@ -42,4 +44,220 @@ describe('DropDown Component', () => { expect(mockOnDropDownClicked).toHaveBeenCalled(); expect(mockOnDropDownClicked).toHaveBeenCalledTimes(1); }); + + it('should render the input component', () => { + const { getByTestId } = render(); + + const input = getByTestId(mockInputTestId); + expect(input).toBeDefined(); + }); + + it('should render icon input component when variation prop passed as icon', () => { + const { getByTestId } = render(); + + const input = getByTestId(mockInputTestId); + expect(input).toBeDefined(); + }); + + it('should show empty value when input component mount', () => { + const { getByTestId } = render(); + + const input = getByTestId(mockInputTestId); + expect(input.props.value).toEqual(''); + }); + + it('should not render any input component when invalid variation prop passed', () => { + const { queryByTestId } = render(); + + const input = queryByTestId(mockInputTestId); + expect(input).toBeNull(); + }); + + it('should show the selected list item title', () => { + const { getByTestId } = render( + , + ); + + const input = getByTestId(mockInputTestId); + + expect(input.props.value).toEqual('first_item'); + }); + + it('should show the multiselect message', () => { + const { getByTestId } = render( + , + ); + + const input = getByTestId(mockInputTestId); + + expect(input.props.value).toEqual('Selected items 1'); + }); +}); + +describe('DropDownListContainer component', () => { + const mockListItemTestId = 'mock-list-item-test-id'; + + const mockOnItemClickedHandler = jest.fn(); + const mockOnCloseHandler = jest.fn(); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should render properly with default props', () => { + const { toJSON } = render( + , + ); + + expect(toJSON()).toMatchSnapshot(); + }); + + it('should render the list item', () => { + const { getByTestId } = render( + , + ); + + const listItem = getByTestId(mockListItemTestId); + expect(listItem).toBeDefined(); + }); + + it('should called the onItemClicked when onItemClicked props will passed and user tap on the list item', () => { + const { getByTestId } = render( + , + ); + + const listItem = getByTestId(mockListItemTestId); + + fireEvent(listItem, 'press', { nativeEvent: {} }); + + expect(mockOnItemClickedHandler).toHaveBeenCalledTimes(1); + expect(mockOnItemClickedHandler).toHaveBeenCalledWith({ id: '1', title: 'first_item' }); + }); + + it('should show the gray[900] color for title text', () => { + const { getByText } = render( + , + ); + + const title = getByText('first_item'); + expect(title).toBeDefined(); + expect(title.props.style.color).toEqual(gray[900]); + }); + + it('should show the gray[50] color for title text if item is selected', () => { + const { getByText } = render( + , + ); + + const title = getByText('first_item'); + expect(title).toBeDefined(); + expect(title.props.style.color).toEqual(gray[50]); + }); + + it('should show the light color of the title text when color scheme is dark', () => { + jest.spyOn(RN, 'useColorScheme').mockReturnValue('dark'); + + const { getByText } = render( + , + ); + + const title = getByText('first_item'); + expect(title).toBeDefined(); + expect(title.props.style.color).toEqual(gray[900]); + }); + + it('should show the listItemEndAdornment item when list items is isSelected', () => { + const { getByText } = render( + Hello} + displaySelectedAdornment + showSelectedItem + />, + ); + + const listItemEndAdornment = getByText('Hello'); + expect(listItemEndAdornment).toBeDefined(); + }); + + it('should render the search bar component', () => { + const { toJSON, getByPlaceholderText } = render( + , + ); + + expect(toJSON()).toMatchSnapshot(); + + const search = getByPlaceholderText('Search'); + expect(search).toBeDefined(); + }); + + it('should call the onClose function when press on item', () => { + const { getByText } = render( + , + ); + + const title = getByText('first_item'); + fireEvent(title, 'press', { nativeEvent: {} }); + expect(mockOnCloseHandler).toHaveBeenCalled(); + expect(mockOnCloseHandler).toHaveBeenCalledTimes(1); + }); }); 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 2ecb24f..1c0e15b 100644 --- a/src/packages/react-native-material-elements/__test__/Text.test.tsx +++ b/src/packages/react-native-material-elements/__test__/Text.test.tsx @@ -1,7 +1,7 @@ import { render as testingRenderer, waitFor } from '@testing-library/react-native'; import React from 'react'; import { Text as RnText, StyleSheet } from 'react-native'; -import { red, secondary, Text, ThemeProvider } from '../src'; +import { FormHelperText, red, secondary, Text, ThemeProvider } from '../src'; import { TextVariation, TextVariationThemeConfig } from '../src/components/types'; import { render } from './test-utils'; @@ -397,3 +397,10 @@ describe('Text Component', () => { }); }); }); + +describe('FormHelperText component', () => { + it('should render correct', () => { + const { toJSON } = render(Hello); + expect(toJSON()).toMatchSnapshot(); + }); +}); diff --git a/src/packages/react-native-material-elements/__test__/__snapshots__/Accordion.test.tsx.snap b/src/packages/react-native-material-elements/__test__/__snapshots__/Accordion.test.tsx.snap index 57da541..75932e2 100644 --- a/src/packages/react-native-material-elements/__test__/__snapshots__/Accordion.test.tsx.snap +++ b/src/packages/react-native-material-elements/__test__/__snapshots__/Accordion.test.tsx.snap @@ -1,4 +1,4 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Accordion Component should render correctly 1`] = ` diff --git a/src/packages/react-native-material-elements/__test__/__snapshots__/Backdrop.test.tsx.snap b/src/packages/react-native-material-elements/__test__/__snapshots__/Backdrop.test.tsx.snap index c0cede1..ea33268 100644 --- a/src/packages/react-native-material-elements/__test__/__snapshots__/Backdrop.test.tsx.snap +++ b/src/packages/react-native-material-elements/__test__/__snapshots__/Backdrop.test.tsx.snap @@ -1,4 +1,4 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Backdrop should render correctly 1`] = ` `; + +exports[`DropDownListContainer component should render properly with default props 1`] = ` + + + + + + + + + +`; + +exports[`DropDownListContainer component should render the search bar component 1`] = ` + + + + + + + + + + + + + + + + +`; diff --git a/src/packages/react-native-material-elements/__test__/__snapshots__/Grid.test.tsx.snap b/src/packages/react-native-material-elements/__test__/__snapshots__/Grid.test.tsx.snap index 798d05e..3165976 100644 --- a/src/packages/react-native-material-elements/__test__/__snapshots__/Grid.test.tsx.snap +++ b/src/packages/react-native-material-elements/__test__/__snapshots__/Grid.test.tsx.snap @@ -1,4 +1,4 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Grid component should render correctly 1`] = ` diff --git a/src/packages/react-native-material-elements/__test__/__snapshots__/ImageList.test.tsx.snap b/src/packages/react-native-material-elements/__test__/__snapshots__/ImageList.test.tsx.snap index 0e2fb90..f4a9c6e 100644 --- a/src/packages/react-native-material-elements/__test__/__snapshots__/ImageList.test.tsx.snap +++ b/src/packages/react-native-material-elements/__test__/__snapshots__/ImageList.test.tsx.snap @@ -1,4 +1,4 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Jest Snapshot v1, https://goo.gl/fbAQLP exports[`ImageList Component should render correctly with default props 1`] = ` diff --git a/src/packages/react-native-material-elements/__test__/__snapshots__/Text.test.tsx.snap b/src/packages/react-native-material-elements/__test__/__snapshots__/Text.test.tsx.snap index 3e27089..c4bbf3b 100644 --- a/src/packages/react-native-material-elements/__test__/__snapshots__/Text.test.tsx.snap +++ b/src/packages/react-native-material-elements/__test__/__snapshots__/Text.test.tsx.snap @@ -1,4 +1,13 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`FormHelperText component should render correct 1`] = ` + + Hello + +`; exports[`Text Component should match the snapshot with default props 1`] = ` `; diff --git a/src/packages/react-native-material-elements/src/components/Button/BaseButton.tsx b/src/packages/react-native-material-elements/src/components/Button/BaseButton.tsx index debe33e..1426dc8 100644 --- a/src/packages/react-native-material-elements/src/components/Button/BaseButton.tsx +++ b/src/packages/react-native-material-elements/src/components/Button/BaseButton.tsx @@ -72,7 +72,7 @@ export const BaseButton = React.forwardRef( }; const buttonLongPressHandler = (event: GestureResponderEvent) => { - if (onLongPressHandler && typeof onLongPressHandler === 'function' && !disabled) { + if (onLongPressHandler && !disabled) { const { locationX, locationY } = event.nativeEvent; if (rippleRef.current && buttonLayoutRectangle) { if (rippleEdge) { @@ -81,6 +81,7 @@ export const BaseButton = React.forwardRef( rippleRef.current.startRipple(locationX, locationY); } } + onLongPressHandler(event); } }; diff --git a/src/packages/react-native-material-elements/src/components/DropDown/DropDown.tsx b/src/packages/react-native-material-elements/src/components/DropDown/DropDown.tsx index d3c324d..53835be 100644 --- a/src/packages/react-native-material-elements/src/components/DropDown/DropDown.tsx +++ b/src/packages/react-native-material-elements/src/components/DropDown/DropDown.tsx @@ -144,6 +144,11 @@ export interface DropDownListContainerProps> * The 'children' prop is omitted to prevent accidental overrides of the search input itself. */ searchContainerProps?: Omit; + + /** + * Dropdown list item test id + */ + listItemTestId?: string; } /** @@ -297,14 +302,14 @@ export const DropDown = ({ }; const renderInput = useCallback(() => { - let value = ''; + let value: string; if (multiselect) { value = multiselectMessage ?? `Selected items ${hasListSelectedItems ? selectedListItems?.length : selectedItems.length}`; } else if (hasListSelectedItems && selectedListItems?.length) { value = selectedListItems?.[0]?.title; } else { - value = selectedItems?.[0]?.title; + value = selectedItems?.[0]?.title ?? ''; } const commonProps: TextFieldProps = { @@ -386,7 +391,7 @@ export const DropDown = ({ ); }; -const DropDownListContainer = ({ +export const DropDownListContainer = ({ style, open, data, @@ -410,6 +415,7 @@ const DropDownListContainer = ({ searchProps, searchContainerProps, maxHeight, + listItemTestId, ...props }: DropDownListContainerProps) => { const flatListRef = useRef(null); @@ -419,18 +425,18 @@ const DropDownListContainer = ({ const itemOnPressHandler = (item: DropDownData) => { if (!multiselect) { - if (!!onClose && typeof onClose === 'function') { + if (onClose) { onClose(); setFilteredData(null); } } - if (!!onItemClicked && typeof onItemClicked === 'function') { + if (onItemClicked) { onItemClicked(item); } }; const searchHandler = (searchString: string) => { - if (searchString) { + if (searchString && Array.isArray(data) && data.length) { const newData = (data as unknown as Array).filter(item => item.title.toLowerCase().includes(searchString.toLowerCase()), ); @@ -479,7 +485,8 @@ const DropDownListContainer = ({ onPress={() => itemOnPressHandler(item)} endAdornment={endAdornment} actionType="root" - style={[{ minHeight: listItemMinHeight }]}> + style={[{ minHeight: listItemMinHeight }]} + testID={listItemTestId}> Date: Sun, 21 Sep 2025 15:17:46 +0530 Subject: [PATCH 16/26] [workflow/test] Added test runner yaml file --- .github/workflows/code-check.yaml | 4 ---- .github/workflows/test-runner.yaml | 24 ++++++++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/test-runner.yaml diff --git a/.github/workflows/code-check.yaml b/.github/workflows/code-check.yaml index 2b49635..7891ffa 100644 --- a/.github/workflows/code-check.yaml +++ b/.github/workflows/code-check.yaml @@ -19,10 +19,6 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Run unit tests - run: yarn run test --coverage --forceExit --maxWorkers=2 - continue-on-error: false - - name: SonarCloud Scan uses: sonarsource/sonarcloud-github-action@v2 env: diff --git a/.github/workflows/test-runner.yaml b/.github/workflows/test-runner.yaml new file mode 100644 index 0000000..81ee5cd --- /dev/null +++ b/.github/workflows/test-runner.yaml @@ -0,0 +1,24 @@ +name: Test Runner +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize, reopened] +jobs: + code-quality-check: + name: Test Runner + 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 unit tests + run: yarn run test --coverage --forceExit --maxWorkers=2 + continue-on-error: false \ No newline at end of file From 096b621970d9aab80040a550d2ad3b6b5eb2cb8d Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sun, 21 Sep 2025 15:25:51 +0530 Subject: [PATCH 17/26] [workflow/test] added type check actions --- .github/workflows/type-check.yaml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/type-check.yaml diff --git a/.github/workflows/type-check.yaml b/.github/workflows/type-check.yaml new file mode 100644 index 0000000..295b2d8 --- /dev/null +++ b/.github/workflows/type-check.yaml @@ -0,0 +1,23 @@ +name: Type Check +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize, reopened] +jobs: + code-quality-check: + 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 7664618b10b7813add165d6b62b8d1115e983b9a Mon Sep 17 00:00:00 2001 From: Dee <86516056+dheeraj1429@users.noreply.github.com> Date: Sun, 21 Sep 2025 15:33:33 +0530 Subject: [PATCH 18/26] [workflow/test] Fixed the types, Added code check action --- .github/workflows/codeql.yml | 30 ++++++++++ .../__test__/createThemeDimensions.test.ts | 2 +- .../__test__/useThemedProps.test.tsx | 2 +- .../examples/Badge.tsx | 19 +------ .../TextInputFormValidation01.tsx | 56 ------------------- .../examples/form-validation/index.ts | 1 - .../src/hooks/useThemedProps.ts | 2 +- tsconfig.json | 3 +- 8 files changed, 37 insertions(+), 78 deletions(-) create mode 100644 .github/workflows/codeql.yml delete mode 100644 src/packages/react-native-material-elements/examples/form-validation/TextInputFormValidation01.tsx delete mode 100644 src/packages/react-native-material-elements/examples/form-validation/index.ts diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..b709582 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,30 @@ +name: "CodeQL Analysis" + +on: + push: + branches: [ main ] + pull_request: + branches: + - master + schedule: + - cron: '0 0 * * 0' + +jobs: + codeql: + name: Analyze + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: typescript, javascript + + - name: Autobuild + uses: github/codeql-action/autobuild@v3 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 diff --git a/src/packages/react-native-material-elements/__test__/createThemeDimensions.test.ts b/src/packages/react-native-material-elements/__test__/createThemeDimensions.test.ts index 44e33e5..3c15644 100644 --- a/src/packages/react-native-material-elements/__test__/createThemeDimensions.test.ts +++ b/src/packages/react-native-material-elements/__test__/createThemeDimensions.test.ts @@ -1,5 +1,5 @@ import { createThemeDimensions, themeDimensions } from '../src'; -import { CreateThemeDimensions } from '../src/libraries/themes/types'; +import { CreateThemeDimensions } from '../src/libraries/types'; describe('createThemeDimensions', () => { it('should merge custom and default theme dimensions', () => { diff --git a/src/packages/react-native-material-elements/__test__/useThemedProps.test.tsx b/src/packages/react-native-material-elements/__test__/useThemedProps.test.tsx index ed8f77a..4ec93a8 100644 --- a/src/packages/react-native-material-elements/__test__/useThemedProps.test.tsx +++ b/src/packages/react-native-material-elements/__test__/useThemedProps.test.tsx @@ -3,8 +3,8 @@ import React, { isValidElement } from 'react'; import { Text, View } from 'react-native'; import { useThemedProps } from '../src/hooks'; import { render, ThemeWrapper } from './test-utils'; -import { Theme } from '../src/libraries/themes/types'; import { green } from '../src'; +import { Theme } from '../src/libraries/types'; describe('useThemedProps', () => { it('should match icon component snapshot correctly', () => { diff --git a/src/packages/react-native-material-elements/examples/Badge.tsx b/src/packages/react-native-material-elements/examples/Badge.tsx index 5a8070f..c3a4531 100644 --- a/src/packages/react-native-material-elements/examples/Badge.tsx +++ b/src/packages/react-native-material-elements/examples/Badge.tsx @@ -125,14 +125,7 @@ export const Ex8: React.FC = () => { const { theme } = useTheme(); return ( - + { const { theme } = useTheme(); return ( - console.log(event), - }}> + ({ - defaultValues: { - email: '', - }, - resolver: yupResolver(validations), - }); - - const submitHandler = function (data: FormState) { - console.log(data); - }; - - return ( - - ( - - - {errors?.email?.message ? ( - - {errors.email.message} - - ) : null} - - )} - /> -