From ec4eceb546d9e61080125deec945660b5f8d9950 Mon Sep 17 00:00:00 2001 From: maryia-deriv Date: Fri, 3 May 2024 12:48:14 +0300 Subject: [PATCH 1/5] test: routes.tsx in reports --- packages/reports/.eslintrc.js | 4 ++ packages/reports/jest.config.js | 1 + .../src/Containers/__tests__/routes.spec.tsx | 45 +++++++++++++++++++ packages/reports/src/Containers/routes.tsx | 4 +- 4 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 packages/reports/src/Containers/__tests__/routes.spec.tsx diff --git a/packages/reports/.eslintrc.js b/packages/reports/.eslintrc.js index 2513c12b8853..f363d6b74779 100644 --- a/packages/reports/.eslintrc.js +++ b/packages/reports/.eslintrc.js @@ -1,3 +1,4 @@ +const { rule } = require('postcss'); const webpackConfig = require('./build/webpack.config-test.js'); module.exports = { @@ -7,4 +8,7 @@ module.exports = { webpack: { config: webpackConfig({}) }, }, }, + rules: { + 'import/no-extraneous-dependencies': ['off', { devDependencies: ['**/*.spec.*', '**/*.test.*', '**/*.d.ts*'] }], + }, }; diff --git a/packages/reports/jest.config.js b/packages/reports/jest.config.js index babd5fc48328..3e462ee74ea3 100644 --- a/packages/reports/jest.config.js +++ b/packages/reports/jest.config.js @@ -8,6 +8,7 @@ module.exports = { '^_common/(.*)$': '/src/_common/$1', '^App/(.*)$': '/src/App/$1', '^Assets/(.*)$': '/src/Assets/$1', + '^Components/(.*)$': '/src/Components/$1', '^Constants/(.*)$': '/src/Constants/$1', '^Constants$': '/src/Constants/index.js', '^Documents/(.*)$': '/src/Documents/$1', diff --git a/packages/reports/src/Containers/__tests__/routes.spec.tsx b/packages/reports/src/Containers/__tests__/routes.spec.tsx new file mode 100644 index 000000000000..0805de96900a --- /dev/null +++ b/packages/reports/src/Containers/__tests__/routes.spec.tsx @@ -0,0 +1,45 @@ +import React from 'react'; +import { render, screen, waitFor } from '@testing-library/react'; +import { createMemoryHistory } from 'history'; +import { mockStore } from '@deriv/stores'; +import { Router } from 'react-router-dom'; +import { TCoreStores } from '@deriv/stores/types'; +import BinaryRoutes from '../../Components/Routes'; +import Routes from '../routes'; +import ReportsProviders from '../../reports-providers'; + +const mockedBinaryRoutes = 'BinaryRoutes'; +const mockedErrorComponent = 'ErrorComponent'; + +jest.mock('../../../src/Components/Routes', () => jest.fn(() => mockedBinaryRoutes)); +jest.mock('../../../src/Components/Errors', () => jest.fn(() => mockedErrorComponent)); + +describe('Routes', () => { + const history = createMemoryHistory(); + const store = mockStore({}); + + const renderMockedRoutes = ( + mockedStore: TCoreStores = store, + passthrough?: React.ComponentProps['passthrough'] + ) => { + return render( + + + + + + ); + }; + + it('should render BinaryRoutes', () => { + renderMockedRoutes(); + expect(screen.getByText(mockedBinaryRoutes)).toBeInTheDocument(); + }); + it('should render ErrorComponent', async () => { + renderMockedRoutes(mockStore({ common: { has_error: true } })); + expect(screen.queryByText(mockedBinaryRoutes)).not.toBeInTheDocument(); + await waitFor(() => { + expect(screen.getByText(mockedErrorComponent)).toBeInTheDocument(); + }); + }); +}); diff --git a/packages/reports/src/Containers/routes.tsx b/packages/reports/src/Containers/routes.tsx index 61c0b535cc17..67fe3e95aa56 100644 --- a/packages/reports/src/Containers/routes.tsx +++ b/packages/reports/src/Containers/routes.tsx @@ -1,11 +1,11 @@ import { observer, useStore } from '@deriv/stores'; -import { withRouter } from 'react-router'; +import { RouteComponentProps, withRouter } from 'react-router'; import React from 'react'; import BinaryRoutes from 'Components/Routes'; import ErrorComponent from 'Components/Errors'; import { TRoutes } from 'Types'; -const Routes = observer(({ passthrough }: TRoutes) => { +const Routes = observer(({ passthrough }: TRoutes & RouteComponentProps) => { const { client, common } = useStore(); const { is_logged_in, is_logging_in } = client; const { error, has_error } = common; From 7bcfb9e153cc07b994e6f04b066cadd7cc96e1ac Mon Sep 17 00:00:00 2001 From: maryia-deriv Date: Fri, 3 May 2024 16:48:27 +0300 Subject: [PATCH 2/5] test: routes-config --- .../__tests__/routes-config.spec.tsx | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 packages/reports/src/Constants/__tests__/routes-config.spec.tsx diff --git a/packages/reports/src/Constants/__tests__/routes-config.spec.tsx b/packages/reports/src/Constants/__tests__/routes-config.spec.tsx new file mode 100644 index 000000000000..8efe3bf2be58 --- /dev/null +++ b/packages/reports/src/Constants/__tests__/routes-config.spec.tsx @@ -0,0 +1,114 @@ +import React, { ComponentProps } from 'react'; +import { Router } from 'react-router'; +import { createMemoryHistory } from 'history'; +import { mockStore } from '@deriv/stores'; +import { routes } from '@deriv/shared'; +import { render, screen, waitFor } from '@testing-library/react'; +import BinaryRoutes from '../../Components/Routes'; +import ReportsProviders from '../../reports-providers'; +import getRoutesConfig from '../routes-config'; + +jest.mock('Modules/Page404', () => { + return { + __esModule: true, + default: () =>
Error 404
, + }; +}); + +jest.mock('../../Containers', () => { + return { + __esModule: true, + default: { + ...jest.requireActual('../../Containers').default, + OpenPositions: () =>
Open positions
, + ProfitTable: () =>
Trade table
, + Statement: () =>
Statement
, + }, + }; +}); + +describe('Routes Config', () => { + const history = createMemoryHistory(); + + // we need to render BinaryRoutes component that uses routes-config to test that lazy-loaded components are loaded + const MockBinaryRoutes = ({ is_logged_in, is_logging_in }: ComponentProps) => { + return ( + + + + + + ); + }; + + it('should return default routes config', () => { + const routesConfig = getRoutesConfig(); + expect(routesConfig).toHaveLength(2); + }); + it('should not render Reports / Open positions when a user is not logged in', async () => { + history.push(routes.positions); + render(); + await waitFor(() => { + expect(screen.queryByText('Reports')).not.toBeInTheDocument(); + expect(screen.queryByText('Open positions')).not.toBeInTheDocument(); + }); + }); + it('should render Loading component while a user is logging in', async () => { + history.push(routes.positions); + render(); + await waitFor(() => { + expect(screen.queryByText('Reports')).not.toBeInTheDocument(); + expect(screen.queryByText('Open positions')).not.toBeInTheDocument(); + expect(screen.getByTestId('dt_initial_loader')).toBeInTheDocument(); + }); + }); + it('should return routes with Reports / Open positions route', async () => { + const routesConfig = getRoutesConfig(); + expect(routesConfig?.[0]?.path).toBe(routes.reports); + expect(routesConfig?.[0]?.getTitle?.()).toBe('Reports'); + expect(routesConfig?.[0]?.is_authenticated).toBe(true); + expect(routesConfig?.[0].routes[0].path).toBe(routes.positions); + history.push(routes.positions); + render(); + await waitFor(() => { + expect(screen.getByText('Reports')).toBeInTheDocument(); + expect(screen.getByText('Open positions')).toBeInTheDocument(); + }); + }); + it('should return routes with Reports / Trade table route', async () => { + const routesConfig = getRoutesConfig(); + expect(routesConfig?.[0].routes[1].path).toBe(routes.profit); + expect(routesConfig?.[0].routes[1].getTitle()).toBe('Trade table'); + history.push(routes.profit); + render(); + await waitFor(() => { + expect(screen.getByText('Reports')).toBeInTheDocument(); + expect(screen.getByText('Trade table')).toBeInTheDocument(); + }); + }); + it('should return routes with Reports / Statement route', async () => { + const routesConfig = getRoutesConfig(); + expect(routesConfig?.[0].routes[2].path).toBe(routes.statement); + expect(routesConfig?.[0].routes[2].getTitle()).toBe('Statement'); + history.push(routes.statement); + render(); + await waitFor(() => { + expect(screen.getByText('Reports')).toBeInTheDocument(); + expect(screen.getByText('Statement')).toBeInTheDocument(); + }); + }); + it('should return routes with Page 404 and render it when the path does not exist', async () => { + const routesConfig = getRoutesConfig(); + expect(routesConfig?.[1]?.getTitle?.()).toBe('Error 404'); + history.push('/non-existent-path'); + render(); + await waitFor(() => { + expect(screen.getByText('Error 404')).toBeInTheDocument(); + }); + }); +}); From c93ea2313f86d834b8ba22acf05f5053d73f1844 Mon Sep 17 00:00:00 2001 From: maryia-deriv Date: Fri, 3 May 2024 17:20:15 +0300 Subject: [PATCH 3/5] refactor: test for routes-config --- .../__tests__/routes-config.spec.tsx | 88 +++++++------------ 1 file changed, 31 insertions(+), 57 deletions(-) diff --git a/packages/reports/src/Constants/__tests__/routes-config.spec.tsx b/packages/reports/src/Constants/__tests__/routes-config.spec.tsx index 8efe3bf2be58..872bf0621db8 100644 --- a/packages/reports/src/Constants/__tests__/routes-config.spec.tsx +++ b/packages/reports/src/Constants/__tests__/routes-config.spec.tsx @@ -1,5 +1,5 @@ -import React, { ComponentProps } from 'react'; -import { Router } from 'react-router'; +import React from 'react'; +import { RouteComponentProps, Router } from 'react-router'; import { createMemoryHistory } from 'history'; import { mockStore } from '@deriv/stores'; import { routes } from '@deriv/shared'; @@ -8,73 +8,44 @@ import BinaryRoutes from '../../Components/Routes'; import ReportsProviders from '../../reports-providers'; import getRoutesConfig from '../routes-config'; -jest.mock('Modules/Page404', () => { - return { - __esModule: true, - default: () =>
Error 404
, - }; -}); +jest.mock('Modules/Page404', () => ({ + __esModule: true, + default: () =>
Error 404
, +})); -jest.mock('../../Containers', () => { - return { - __esModule: true, - default: { - ...jest.requireActual('../../Containers').default, - OpenPositions: () =>
Open positions
, - ProfitTable: () =>
Trade table
, - Statement: () =>
Statement
, - }, - }; -}); +jest.mock('../../Containers', () => ({ + __esModule: true, + default: { + ...jest.requireActual('../../Containers').default, + OpenPositions: () =>
Open positions
, + ProfitTable: () =>
Trade table
, + Statement: () =>
Statement
, + }, +})); describe('Routes Config', () => { - const history = createMemoryHistory(); - // we need to render BinaryRoutes component that uses routes-config to test that lazy-loaded components are loaded - const MockBinaryRoutes = ({ is_logged_in, is_logging_in }: ComponentProps) => { - return ( - - - - - - ); - }; + const MockBinaryRoutes = ({ history }: Partial) => ( + + + + + + ); it('should return default routes config', () => { const routesConfig = getRoutesConfig(); expect(routesConfig).toHaveLength(2); }); - it('should not render Reports / Open positions when a user is not logged in', async () => { - history.push(routes.positions); - render(); - await waitFor(() => { - expect(screen.queryByText('Reports')).not.toBeInTheDocument(); - expect(screen.queryByText('Open positions')).not.toBeInTheDocument(); - }); - }); - it('should render Loading component while a user is logging in', async () => { - history.push(routes.positions); - render(); - await waitFor(() => { - expect(screen.queryByText('Reports')).not.toBeInTheDocument(); - expect(screen.queryByText('Open positions')).not.toBeInTheDocument(); - expect(screen.getByTestId('dt_initial_loader')).toBeInTheDocument(); - }); - }); it('should return routes with Reports / Open positions route', async () => { const routesConfig = getRoutesConfig(); expect(routesConfig?.[0]?.path).toBe(routes.reports); expect(routesConfig?.[0]?.getTitle?.()).toBe('Reports'); expect(routesConfig?.[0]?.is_authenticated).toBe(true); expect(routesConfig?.[0].routes[0].path).toBe(routes.positions); + const history = createMemoryHistory(); history.push(routes.positions); - render(); + render(); await waitFor(() => { expect(screen.getByText('Reports')).toBeInTheDocument(); expect(screen.getByText('Open positions')).toBeInTheDocument(); @@ -84,8 +55,9 @@ describe('Routes Config', () => { const routesConfig = getRoutesConfig(); expect(routesConfig?.[0].routes[1].path).toBe(routes.profit); expect(routesConfig?.[0].routes[1].getTitle()).toBe('Trade table'); + const history = createMemoryHistory(); history.push(routes.profit); - render(); + render(); await waitFor(() => { expect(screen.getByText('Reports')).toBeInTheDocument(); expect(screen.getByText('Trade table')).toBeInTheDocument(); @@ -95,18 +67,20 @@ describe('Routes Config', () => { const routesConfig = getRoutesConfig(); expect(routesConfig?.[0].routes[2].path).toBe(routes.statement); expect(routesConfig?.[0].routes[2].getTitle()).toBe('Statement'); + const history = createMemoryHistory(); history.push(routes.statement); - render(); + render(); await waitFor(() => { expect(screen.getByText('Reports')).toBeInTheDocument(); expect(screen.getByText('Statement')).toBeInTheDocument(); }); }); - it('should return routes with Page 404 and render it when the path does not exist', async () => { + it('should return routes with route for Page 404 which loads when the path does not exist', async () => { const routesConfig = getRoutesConfig(); expect(routesConfig?.[1]?.getTitle?.()).toBe('Error 404'); + const history = createMemoryHistory(); history.push('/non-existent-path'); - render(); + render(); await waitFor(() => { expect(screen.getByText('Error 404')).toBeInTheDocument(); }); From 78028fa26989dafb1446aa907cee8c3903ad2159 Mon Sep 17 00:00:00 2001 From: maryia-deriv Date: Fri, 3 May 2024 17:38:09 +0300 Subject: [PATCH 4/5] fix: remove extra async expect --- packages/reports/src/Containers/__tests__/routes.spec.tsx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/reports/src/Containers/__tests__/routes.spec.tsx b/packages/reports/src/Containers/__tests__/routes.spec.tsx index 0805de96900a..b6f2f9a615d4 100644 --- a/packages/reports/src/Containers/__tests__/routes.spec.tsx +++ b/packages/reports/src/Containers/__tests__/routes.spec.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { render, screen, waitFor } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import { createMemoryHistory } from 'history'; import { mockStore } from '@deriv/stores'; import { Router } from 'react-router-dom'; @@ -35,11 +35,9 @@ describe('Routes', () => { renderMockedRoutes(); expect(screen.getByText(mockedBinaryRoutes)).toBeInTheDocument(); }); - it('should render ErrorComponent', async () => { + it('should render ErrorComponent', () => { renderMockedRoutes(mockStore({ common: { has_error: true } })); expect(screen.queryByText(mockedBinaryRoutes)).not.toBeInTheDocument(); - await waitFor(() => { - expect(screen.getByText(mockedErrorComponent)).toBeInTheDocument(); - }); + expect(screen.getByText(mockedErrorComponent)).toBeInTheDocument(); }); }); From 980bef127ee29dde15532bc6b4817ddd8a499d37 Mon Sep 17 00:00:00 2001 From: maryia-deriv Date: Fri, 3 May 2024 17:45:25 +0300 Subject: [PATCH 5/5] refactor: packages/reports/src/Constants/__tests__/routes-config.spec.tsx --- .../__tests__/routes-config.spec.tsx | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/packages/reports/src/Constants/__tests__/routes-config.spec.tsx b/packages/reports/src/Constants/__tests__/routes-config.spec.tsx index 872bf0621db8..dd27d7e0ebd0 100644 --- a/packages/reports/src/Constants/__tests__/routes-config.spec.tsx +++ b/packages/reports/src/Constants/__tests__/routes-config.spec.tsx @@ -8,18 +8,24 @@ import BinaryRoutes from '../../Components/Routes'; import ReportsProviders from '../../reports-providers'; import getRoutesConfig from '../routes-config'; +const mockedError404 = 'Error 404'; +const mockedOpenPositions = 'Open positions'; +const mockedStatement = 'Statement'; +const mockedTradeTable = 'Trade table'; +const reportsPageTitle = 'Reports'; + jest.mock('Modules/Page404', () => ({ __esModule: true, - default: () =>
Error 404
, + default: () =>
{mockedError404}
, })); jest.mock('../../Containers', () => ({ __esModule: true, default: { ...jest.requireActual('../../Containers').default, - OpenPositions: () =>
Open positions
, - ProfitTable: () =>
Trade table
, - Statement: () =>
Statement
, + OpenPositions: () =>
{mockedOpenPositions}
, + ProfitTable: () =>
{mockedTradeTable}
, + Statement: () =>
{mockedStatement}
, }, })); @@ -40,49 +46,49 @@ describe('Routes Config', () => { it('should return routes with Reports / Open positions route', async () => { const routesConfig = getRoutesConfig(); expect(routesConfig?.[0]?.path).toBe(routes.reports); - expect(routesConfig?.[0]?.getTitle?.()).toBe('Reports'); + expect(routesConfig?.[0]?.getTitle?.()).toBe(reportsPageTitle); expect(routesConfig?.[0]?.is_authenticated).toBe(true); - expect(routesConfig?.[0].routes[0].path).toBe(routes.positions); + expect(routesConfig?.[0].routes?.[0].path).toBe(routes.positions); const history = createMemoryHistory(); history.push(routes.positions); render(); await waitFor(() => { - expect(screen.getByText('Reports')).toBeInTheDocument(); - expect(screen.getByText('Open positions')).toBeInTheDocument(); + expect(screen.getByText(reportsPageTitle)).toBeInTheDocument(); + expect(screen.getByText(mockedOpenPositions)).toBeInTheDocument(); }); }); it('should return routes with Reports / Trade table route', async () => { const routesConfig = getRoutesConfig(); - expect(routesConfig?.[0].routes[1].path).toBe(routes.profit); - expect(routesConfig?.[0].routes[1].getTitle()).toBe('Trade table'); + expect(routesConfig?.[0].routes?.[1].path).toBe(routes.profit); + expect(routesConfig?.[0].routes?.[1].getTitle()).toBe(mockedTradeTable); const history = createMemoryHistory(); history.push(routes.profit); render(); await waitFor(() => { - expect(screen.getByText('Reports')).toBeInTheDocument(); - expect(screen.getByText('Trade table')).toBeInTheDocument(); + expect(screen.getByText(reportsPageTitle)).toBeInTheDocument(); + expect(screen.getByText(mockedTradeTable)).toBeInTheDocument(); }); }); it('should return routes with Reports / Statement route', async () => { const routesConfig = getRoutesConfig(); - expect(routesConfig?.[0].routes[2].path).toBe(routes.statement); - expect(routesConfig?.[0].routes[2].getTitle()).toBe('Statement'); + expect(routesConfig?.[0].routes?.[2].path).toBe(routes.statement); + expect(routesConfig?.[0].routes?.[2].getTitle()).toBe(mockedStatement); const history = createMemoryHistory(); history.push(routes.statement); render(); await waitFor(() => { - expect(screen.getByText('Reports')).toBeInTheDocument(); - expect(screen.getByText('Statement')).toBeInTheDocument(); + expect(screen.getByText(reportsPageTitle)).toBeInTheDocument(); + expect(screen.getByText(mockedStatement)).toBeInTheDocument(); }); }); it('should return routes with route for Page 404 which loads when the path does not exist', async () => { const routesConfig = getRoutesConfig(); - expect(routesConfig?.[1]?.getTitle?.()).toBe('Error 404'); + expect(routesConfig?.[1]?.getTitle?.()).toBe(mockedError404); const history = createMemoryHistory(); history.push('/non-existent-path'); render(); await waitFor(() => { - expect(screen.getByText('Error 404')).toBeInTheDocument(); + expect(screen.getByText(mockedError404)).toBeInTheDocument(); }); }); });