Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions e-commerce-app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 11 additions & 1 deletion e-commerce-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
"@mui/material": "^5.14.4",
"@reduxjs/toolkit": "^1.9.5",
"classnames": "^2.3.2",
"history": "^5.3.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-error-boundary": "^4.0.11",
"react-hook-form": "^7.45.4",
"react-redux": "^8.1.2",
"react-router-dom": "^6.14.2",
Expand All @@ -24,7 +26,7 @@
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --coverage",
"test": "react-scripts test --coverage --watchAll",
"eject": "react-scripts eject",
"lint": "eslint src/**/*.{js,jsx,ts,tsx}",
"lint:fix": "eslint --fix src/**/*.{js,jsx,ts,tsx}",
Expand All @@ -38,6 +40,12 @@
"react-app/jest"
]
},
"jest": {
"collectCoverageFrom": [
"src/**/*.{js,jsx,ts,tsx}",
"!src/**/*.test.{js,jsx,ts,tsx}"
]
},
"browserslist": {
"production": [
">0.2%",
Expand All @@ -59,11 +67,13 @@
"@types/react": "^18.2.18",
"@types/react-dom": "^18.2.7",
"@types/react-router-dom": "^5.3.3",
"@types/redux-mock-store": "^1.0.3",
"eslint": "^8.46.0",
"eslint-config-prettier": "^8.9.0",
"eslint-plugin-prettier": "^5.0.0",
"husky": "^8.0.3",
"prettier": "^3.0.0",
"redux-mock-store": "^1.5.4",
"sass": "^1.66.1"
}
}
2 changes: 1 addition & 1 deletion e-commerce-app/src/components/BasketEmpty/BasketEmpty.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const BasketEmpty = (): JSX.Element => {
const navigate = useNavigate();
return (
<>
<Box className="cart-empty">
<Box className="cart-empty" data-testid="start-shopping-button">
<Typography variant="h5" mt="5%">
Your cart is empty
</Typography>
Expand Down
2 changes: 1 addition & 1 deletion e-commerce-app/src/components/Footer/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Box } from '@mui/material';

export const Footer: React.FC = () => {
return (
<Box className={styles.footer} component="footer">
<Box data-testid="footer" className={styles.footer} component="footer">
<Container maxWidth="lg">
<Grid container className={styles.footer_container} spacing={5} mt={5}>
<Grid item xs={12} sm={4}>
Expand Down
2 changes: 1 addition & 1 deletion e-commerce-app/src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const Header: React.FC = () => {
};

return (
<AppBar position="sticky" color="default">
<AppBar data-testid="header" position="sticky" color="default">
<Container maxWidth="xl">
<Toolbar disableGutters>
<Link to={'/'}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,6 @@ const UserPersonalAddAddress = (): JSX.Element => {
};

const submitForm: SubmitHandler<IAddAddressForm> = (data) => {
console.log('Submit, errors: ', errors);
console.log(data);
const addressObject: IUpdateMyCustomerActionAddAddress = {
action: 'addAddress',
address: {
Expand Down
3 changes: 2 additions & 1 deletion e-commerce-app/src/pages/AboutPage/AboutPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const AboutPage: React.FC = () => {
backgroundSize: 'cover',
backgroundPosition: 'top',
}}

>
<Box
sx={{
Expand All @@ -45,7 +46,7 @@ export const AboutPage: React.FC = () => {
We&apos;re on a mission to complete <br /> eCommerce Application successfully.
</Typography>
<Stack sx={{ pb: 2 }} direction="row" justifyContent="center">
<Link href="https://rs.school/" target="_blank">
<Link data-testid="rs-school-link" href="https://rs.school/" target="_blank">
<img src={RSlogo} alt="RSlogo" width={70} />
</Link>
</Stack>
Expand Down
2 changes: 1 addition & 1 deletion e-commerce-app/src/pages/RootPage/RootPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Box, Stack } from '@mui/material';

const RootPage = (): JSX.Element => {
return (
<Stack spacing={5} minHeight={'100vh'}>
<Stack data-testid="header" spacing={5} minHeight={'100vh'}>
<Header />
<Box flexGrow={1}>
<Container maxWidth={'xl'}>
Expand Down
26 changes: 26 additions & 0 deletions e-commerce-app/src/tests/AboutPage.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Provider } from 'react-redux';
import { store } from '../store/store';
import { AboutPage } from '../pages/AboutPage/AboutPage';
import { render, screen } from '@testing-library/react';

describe('AboutPage component', () => {
test('renders component without errors', () => {
render(
<Provider store={store}>
<AboutPage />
</Provider>,
);

expect(screen.getByText('About Us')).toBeInTheDocument();
expect(
screen.getByText("We're on a mission to complete eCommerce Application successfully."),
).toBeInTheDocument();

const githubLinks = screen.getAllByRole('link');
githubLinks.forEach((link) => {
expect(link).toBeInTheDocument();
expect(link).toHaveAttribute('href');
expect(link).toHaveAttribute('target', '_blank');
});
});
});
42 changes: 42 additions & 0 deletions e-commerce-app/src/tests/BasketEmpty.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { render, screen, fireEvent } from '@testing-library/react';
import BasketEmpty from '../components/BasketEmpty/BasketEmpty';
import { MemoryRouter } from 'react-router-dom';
import { createMemoryHistory } from 'history';

describe('BasketEmpty component', () => {
test('renders the empty cart message', () => {
render(
<MemoryRouter>
<BasketEmpty />
</MemoryRouter>,
);

const emptyCartMessage = screen.getByText(/Your cart is empty/i);
expect(emptyCartMessage).toBeInTheDocument();
});

test('renders the start shopping button', () => {
render(
<MemoryRouter>
<BasketEmpty />
</MemoryRouter>,
);

const startShoppingButton = screen.getByRole('button', { name: /Start shopping/i });
expect(startShoppingButton).toBeInTheDocument();
});

test('clicking the start shopping button navigates to /products', () => {
const history = createMemoryHistory();
render(
<MemoryRouter>
<BasketEmpty />
</MemoryRouter>,
);

const startShoppingButton = screen.getByRole('button', { name: /Start shopping/i });
fireEvent.click(startShoppingButton);

expect(history.location.pathname).toBe('/');
});
});
46 changes: 46 additions & 0 deletions e-commerce-app/src/tests/BasketPage.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { render, screen, waitFor } from '@testing-library/react';
import { Provider } from 'react-redux';
import { store } from '../store/store';
import { BasketPage } from '../pages/BasketPage/BasketPage';
import { MemoryRouter } from 'react-router-dom';

describe('BasketPage component', () => {
test('renders BasketFull when there are items in the cart', async () => {
jest.mock('../api/cartApi', () => ({
getTotalQuantityLineItemsInCart: jest.fn().mockReturnValue(2),
}));

render(
<Provider store={store}>
<MemoryRouter>
<BasketPage />
</MemoryRouter>
</Provider>,
);

await waitFor(() => {
expect(screen.queryByText(/Shopping cart/)).toBeInTheDocument();
expect(screen.queryByText(/Loading.../)).toBeNull();
});
});

test('renders BasketEmpty when there are no items in the cart', async () => {
jest.mock('../api/cartApi', () => ({
getTotalQuantityLineItemsInCart: jest.fn().mockReturnValue(0),
}));

render(
<Provider store={store}>
<MemoryRouter>
<BasketPage />
</MemoryRouter>
</Provider>,
);

await waitFor(() => {
expect(screen.getByText('Your cart is empty')).toBeInTheDocument();
expect(screen.queryByText(/Continue shopping/)).toBeNull();
expect(screen.getByText(/Shopping cart/)).toBeInTheDocument();
});
});
});
16 changes: 16 additions & 0 deletions e-commerce-app/src/tests/EmptyProducts.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { render } from '@testing-library/react';
import { EmptyProducts } from '../components/ProductsList/EmptyProducts';

describe('EmptyProducts Component', () => {
it('should render empty product message and image', () => {
const { getByText, getByAltText } = render(<EmptyProducts />);

const emptyMessage = getByText(
'This is an empty product list. There are no products available!',
);
expect(emptyMessage).toBeInTheDocument();

const emptyImage = getByAltText('home-icon');
expect(emptyImage).toBeInTheDocument();
});
});
8 changes: 8 additions & 0 deletions e-commerce-app/src/tests/Footer.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { render } from '@testing-library/react';
import { Footer } from '../components/Footer/Footer';

describe('Footer component', () => {
test('renders component without errors', () => {
render(<Footer />);
});
});
30 changes: 30 additions & 0 deletions e-commerce-app/src/tests/HomePage.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { render } from '@testing-library/react';
import { Provider } from 'react-redux';
import configureStore from 'redux-mock-store';
import { HomePage } from '../pages/HomePage/HomePage';

describe('HomePage Component', () => {
const mockStore = configureStore([]);
const store = mockStore({
user: {
email: 'test@example.com',
},
});

it('should render without errors', () => {
const { getByText, getAllByText } = render(
<Provider store={store}>
<HomePage />
</Provider>,
);

expect(getByText(/Hello, test@example\.com Can I call you a Friend\?/i)).toBeInTheDocument();
expect(getByText(/Active Promo Codes/i)).toBeInTheDocument();

const promoCodes = getAllByText(/Coupon Code #[0-9]+/i);
expect(promoCodes.length).toBeGreaterThan(0);

const promoCodeNumbers = getAllByText(/XXX-XXX-XX/i);
expect(promoCodeNumbers.length).toBeGreaterThan(0);
});
});
Loading