diff --git a/app/components/atoms/LanguageProvider/actions.js b/app/components/atoms/LanguageProvider/actions.js index 487dfc4..8dfbef5 100644 --- a/app/components/atoms/LanguageProvider/actions.js +++ b/app/components/atoms/LanguageProvider/actions.js @@ -5,7 +5,11 @@ */ import { CHANGE_LOCALE } from './constants'; - +/** + * Changes the locale/language of the application. + * @param {string} languageLocale - The new locale/language to set. + * @returns {object} An action object with type 'CHANGE_LOCALE' and the new locale/language. + */ export function changeLocale(languageLocale) { return { type: CHANGE_LOCALE, diff --git a/app/components/atoms/LanguageProvider/index.js b/app/components/atoms/LanguageProvider/index.js index 421aa5d..ecde1bb 100644 --- a/app/components/atoms/LanguageProvider/index.js +++ b/app/components/atoms/LanguageProvider/index.js @@ -13,7 +13,14 @@ import { createSelector } from 'reselect'; import { IntlProvider } from 'react-intl'; import { makeSelectLocale } from './selectors'; - +/** + * Provides internationalization (i18n) support by wrapping components with an IntlProvider. + * @param {object} props - The props object containing component properties. + * @param {string} props.locale - The locale/language code for internationalization. + * @param {object} props.messages - An object containing locale-specific message translations. + * @param {React.ReactNode} props.children - The child elements/components to be wrapped and rendered. + * @returns {React.ReactNode} A JSX element wrapping the provided child components with IntlProvider. + */ export function LanguageProvider(props) { return ( ({ locale })); - +/** + * Generates and returns an object containing action dispatch functions. + * @param {function} dispatch - The Redux store's dispatch function. + * @returns {object} An object containing action dispatch functions wrapped for use in components. + */ function mapDispatchToProps(dispatch) { return { dispatch diff --git a/app/components/molecules/LogoWithInstructions/index.js b/app/components/molecules/LogoWithInstructions/index.js index 89bf929..fd8e329 100644 --- a/app/components/molecules/LogoWithInstructions/index.js +++ b/app/components/molecules/LogoWithInstructions/index.js @@ -28,7 +28,12 @@ const Instructions = styled(T)` margin-bottom: 5; font-style: italic; `; - +/** + * A component that displays a logo along with instructions. + * @param {object} props - The props object containing component properties. + * @param {string} props.instructions - The instructions text to display. + * @returns {React.ReactNode} JSX elements displaying the logo and instructions. + */ function LogoWithInstructions({ instructions }) { return ( diff --git a/app/components/organisms/SimpsonsLoveWednesday/index.js b/app/components/organisms/SimpsonsLoveWednesday/index.js index ffb6c5a..c13f512 100644 --- a/app/components/organisms/SimpsonsLoveWednesday/index.js +++ b/app/components/organisms/SimpsonsLoveWednesday/index.js @@ -18,7 +18,14 @@ const SeparatedView = styled.View` margin: 10px; } `; - +/** + * A component that displays Simpsons-themed content related to Wednesday, including instructions, character details, and error messages. + * @param {object} props - The props object containing component properties. + * @param {string} props.instructions - The instructions text to display. + * @param {object} props.user - The user object representing character details and quote. + * @param {string} props.userErrorMessage - The error message to display if user data retrieval fails. + * @returns {React.ReactNode} JSX elements displaying Simpsons-themed content based on provided props. + */ function SimpsonsLoveWednesday({ instructions, user, userErrorMessage }) { return ( <> diff --git a/app/rootSaga.js b/app/rootSaga.js index cf9fcec..a025ca9 100644 --- a/app/rootSaga.js +++ b/app/rootSaga.js @@ -1,7 +1,11 @@ import { fork } from 'redux-saga/effects'; import exampleSaga from '@scenes/ExampleScreen/saga'; import startupSaga from '@scenes/RootScreen/saga'; - +/** + * Root saga generator function that orchestrates other sagas. + * This function sets up and manages the execution of multiple sagas using fork effects. + * @returns {IterableIterator} An iterator for managing the execution of sagas. + */ export default function* root() { yield fork(exampleSaga); yield fork(startupSaga); diff --git a/app/scenes/ExampleScreen/saga.js b/app/scenes/ExampleScreen/saga.js index 964434c..a0eefa1 100644 --- a/app/scenes/ExampleScreen/saga.js +++ b/app/scenes/ExampleScreen/saga.js @@ -22,7 +22,11 @@ export function* fetchUser() { ); } } - +/** + * Saga responsible for managing user search requests and fetching user data. + * Watches for specific action types and triggers corresponding worker sagas. + * @returns {IterableIterator} An iterator for handling user search and data fetching. + */ export default function* searchListContainerSaga() { yield takeLatest(exampleScreenTypes.REQUEST_FETCH_USER, fetchUser); } diff --git a/app/scenes/RootScreen/index.js b/app/scenes/RootScreen/index.js index 0ac9212..1351e91 100644 --- a/app/scenes/RootScreen/index.js +++ b/app/scenes/RootScreen/index.js @@ -1,30 +1,23 @@ -import React, { Component } from 'react'; import { connect } from 'react-redux'; import { PropTypes } from 'prop-types'; -import { setTopLevelNavigator } from '@services/NavigationService'; import AppNavigator from '@navigators/AppNavigator'; import Container from '@atoms/Container'; - +import React, { useEffect } from 'react'; +import { setRefForTopLevelNavigtor } from '@app/services/NavigationService'; import { rootScreenActions } from './reducer'; -export class RootScreen extends Component { - componentDidMount() { - // Run the startup saga when the application is starting - this.props.startup(); - } - - setRefForTopLevelNavigtor = navigatorRef => { - setTopLevelNavigator(navigatorRef); - }; +const RootScreen = props => { + useEffect(() => { + // Run the startup function when the component mounts + props.startup(); + }, []); - render() { - return ( - - - - ); - } -} + return ( + + + + ); +}; RootScreen.propTypes = { startup: PropTypes.func @@ -33,5 +26,5 @@ RootScreen.propTypes = { const mapDispatchToProps = dispatch => ({ startup: () => dispatch(rootScreenActions.startup()) }); - export default connect(null, mapDispatchToProps)(RootScreen); +export { RootScreen as RootScreenTest }; diff --git a/app/scenes/RootScreen/tests/index.test.js b/app/scenes/RootScreen/tests/index.test.js index d363424..a93ddc6 100644 --- a/app/scenes/RootScreen/tests/index.test.js +++ b/app/scenes/RootScreen/tests/index.test.js @@ -6,26 +6,23 @@ import React from 'react'; import { renderWithIntl } from 'app/utils/testUtils'; -import { RootScreen as RootScreenTest } from '../index'; - +import { RootScreenTest } from '../index'; +export const setupJest = () => ({ submitSpy: jest.fn() }); describe(' container', () => { - let submitSpy; - - beforeAll(() => { - submitSpy = jest.fn(); - }); - it('should render and match the snapshot', () => { + const { submitSpy } = setupJest(); const baseElement = renderWithIntl(); expect(baseElement).toMatchSnapshot(); }); it('should call the startup prop on mount', () => { + const { submitSpy } = setupJest(); renderWithIntl(); expect(submitSpy).toHaveBeenCalled(); }); it('should not render rootSceen Container', () => { + const { submitSpy } = setupJest(); const { getByTestId } = renderWithIntl( ); diff --git a/app/scenes/RootScreen/tests/reducer.test.js b/app/scenes/RootScreen/tests/reducer.test.js index 40243db..90666cb 100644 --- a/app/scenes/RootScreen/tests/reducer.test.js +++ b/app/scenes/RootScreen/tests/reducer.test.js @@ -6,16 +6,15 @@ import { /* eslint-disable default-case, no-param-reassign */ describe('Tests for RootScreen reducers', () => { - let state; - beforeEach(() => { - state = initialState; - }); + const setupTests = () => ({ state: initialState }); it('should return the initial state', () => { + const { state } = setupTests(); expect(rootContainerReducer(undefined, {})).toEqual(state); }); it('should return the initial state when an action of type STARTUP is dispatched', () => { + const { state } = setupTests(); // since startup is called to initiate screen navigation the store should remain intact expect( rootContainerReducer(state, { @@ -23,4 +22,14 @@ describe('Tests for RootScreen reducers', () => { }) ).toEqual(state); }); + + it('should return the initial state when an action of type NONEXIST is dispatched', () => { + const { state } = setupTests(); + // since startup is called to initiate screen navigation the store should remain intact + expect( + rootContainerReducer(state, { + type: rootScreenTypes.NONEXIST + }) + ).toEqual(state); + }); }); diff --git a/app/themes/fonts.test.js b/app/themes/fonts.test.js index 09a97ce..29a48ac 100644 --- a/app/themes/fonts.test.js +++ b/app/themes/fonts.test.js @@ -1,59 +1,69 @@ import fonts from './fonts'; +const fontSizes = { + small: { + expectation: expect.arrayContaining([ + expect.stringContaining('font-size: 14px;') + ]) + }, + regular: { + expectation: expect.arrayContaining([ + expect.stringContaining('font-size: 17px;') + ]) + }, + big: { + expectation: expect.arrayContaining([ + expect.stringContaining('font-size: 20px;') + ]) + }, + large: { + expectation: expect.arrayContaining([ + expect.stringContaining('font-size: 24px;') + ]) + } +}; + +const fontWeights = { + light: { + expectation: expect.arrayContaining([ + expect.stringContaining('font-weight: light;') + ]) + }, + bold: { + expectation: expect.arrayContaining([ + expect.stringContaining('font-weight: bold;') + ]) + }, + normal: { + expectation: expect.arrayContaining([ + expect.stringContaining('font-weight: normal;') + ]) + } +}; describe('Tests for fonts', () => { it('should have the correct font-size', () => { - expect(fonts.size.small()).toEqual( - expect.arrayContaining([expect.stringContaining('font-size: 14px;')]) - ); - expect(fonts.size.regular()).toEqual( - expect.arrayContaining([expect.stringContaining('font-size: 17px;')]) - ); - expect(fonts.size.big()).toEqual( - expect.arrayContaining([expect.stringContaining('font-size: 20px;')]) - ); - expect(fonts.size.large()).toEqual( - expect.arrayContaining([expect.stringContaining('font-size: 24px;')]) - ); + expect(fonts.size.small()).toEqual(fontSizes.small.expectation); + expect(fonts.size.regular()).toEqual(fontSizes.regular.expectation); + expect(fonts.size.big()).toEqual(fontSizes.big.expectation); + expect(fonts.size.large()).toEqual(fontSizes.large.expectation); }); it('should have the correct font-weight', () => { - expect(fonts.weights.light()).toEqual( - expect.arrayContaining([expect.stringContaining('font-weight: light;')]) - ); - expect(fonts.weights.bold()).toEqual( - expect.arrayContaining([expect.stringContaining('font-weight: bold;')]) - ); - expect(fonts.weights.normal()).toEqual( - expect.arrayContaining([expect.stringContaining('font-weight: normal;')]) - ); + expect(fonts.weights.light()).toEqual(fontWeights.light.expectation); + expect(fonts.weights.bold()).toEqual(fontWeights.bold.expectation); + expect(fonts.weights.normal()).toEqual(fontWeights.normal.expectation); }); it('should have the correct font-weight and font-size', () => { - expect(fonts.style.heading()).toEqual( - expect.arrayContaining([expect.stringContaining('font-weight: bold;')]) - ); - expect(fonts.style.heading()).toEqual( - expect.arrayContaining([expect.stringContaining('font-size: 24px;')]) - ); + expect(fonts.style.heading()).toEqual(fontWeights.bold.expectation); + expect(fonts.style.heading()).toEqual(fontSizes.large.expectation); - expect(fonts.style.subheading()).toEqual( - expect.arrayContaining([expect.stringContaining('font-weight: bold;')]) - ); - expect(fonts.style.subheading()).toEqual( - expect.arrayContaining([expect.stringContaining('font-size: 20px;')]) - ); + expect(fonts.style.subheading()).toEqual(fontWeights.bold.expectation); + expect(fonts.style.subheading()).toEqual(fontSizes.big.expectation); - expect(fonts.style.standard()).toEqual( - expect.arrayContaining([expect.stringContaining('font-size: 17px;')]) - ); - expect(fonts.style.standard()).toEqual( - expect.arrayContaining([expect.stringContaining('font-weight: normal;')]) - ); + expect(fonts.style.standard()).toEqual(fontSizes.regular.expectation); + expect(fonts.style.standard()).toEqual(fontWeights.normal.expectation); - expect(fonts.style.subText()).toEqual( - expect.arrayContaining([expect.stringContaining('font-size: 14px;')]) - ); - expect(fonts.style.subText()).toEqual( - expect.arrayContaining([expect.stringContaining('font-weight: normal;')]) - ); + expect(fonts.style.subText()).toEqual(fontSizes.small.expectation); + expect(fonts.style.subText()).toEqual(fontWeights.normal.expectation); }); }); diff --git a/babel.config.js b/babel.config.js index 88d868c..aa61fec 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,3 +1,10 @@ +/** + * Configure Babel for Expo project with module resolution aliases. + * This function sets up Babel presets and plugins, including module resolution with aliases. + * @param {object} api - The Babel API object (optional, used for caching). + * @param {Function} api.cache - Function used for caching Babel configuration. + * @returns {object} Babel configuration object with presets and plugins. + */ module.exports = function(api = { cache: () => {} }) { api.cache(true); return {