Skip to content

Commit

Permalink
Merge branch 'develop' into feat-integrate-payments
Browse files Browse the repository at this point in the history
  • Loading branch information
EddyShimwa committed Jul 26, 2024
2 parents c3a4e84 + 362caba commit d38dbda
Show file tree
Hide file tree
Showing 17 changed files with 999 additions and 231 deletions.
6 changes: 6 additions & 0 deletions package-lock.json

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

22 changes: 22 additions & 0 deletions src/__test__/Cart/Cart.test.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { configureStore } from '@reduxjs/toolkit';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { Provider } from 'react-redux';
import { render, screen } from '@testing-library/react';
import cartReducer, {
fetchCartItems,
addCartItem,
updateCartItemQuantity,
removeCartItem,
} from '@/features/Cart/cartSlice';
import CartItem from '@/components/Cart/CartItem';

describe('cartSlice', () => {
let store = configureStore({ reducer: { cartItems: cartReducer } });
Expand Down Expand Up @@ -79,3 +82,22 @@ describe('cartSlice', () => {
expect(state.error).toBeNull();
});
});

describe('Cart component', () => {
const store = configureStore({
reducer: {},
});

it('renders cart item', async () => {
render(
<Provider store={store}>
<CartItem id={1} price={100} name="Test Product" quantity={3} />
</Provider>
);

expect(screen.getByText('$300')).toBeInTheDocument();
expect(screen.getByText('Test Product')).toBeInTheDocument();
expect(screen.getByText('Size')).toBeInTheDocument();

Check failure on line 100 in src/__test__/Cart/Cart.test.tsx

View workflow job for this annotation

GitHub Actions / build (20.x)

src/__test__/Cart/Cart.test.tsx > Cart component > renders cart item

TestingLibraryElementError: Unable to find an element with the text: Size. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible. Ignored nodes: comments, script, style <body> <div> <div class="flex items-center border-b border-gray-400 pt-8 pb-4 h-max max-w-screen-md" > <img alt="Product" class="w-48 h-32 object-cover rounded-md" /> <div class="flex flex-col flex-grow w-full justify-between px-8" > <span class="font-bold text-2xl" > Test Product </span> <div class="flex justify-between" > <div class="flex items-start gap-4 py-2 flex-col text-gary-600 text-sm" > <span class="text-gray-600 text-center" > Quantity </span> <div class="flex items-center space-x-2" > <button class="px-3 py-1 bg-gray-100 rounded-md" type="button" > - </button> <span> 3 </span> <button class="px-3 py-1 bg-gray-100 rounded-md" type="button" > + </button> </div> </div> </div> </div> <div class="flex flex-col gap-6 py-4 items-end w-64 justify-between" > <button class="text-red-500 text-lg font-medium" type="button" > Remove </button> <span class="font-bold text-xl mt-4" > $ 300 </span> </div> </div> </div> </body> ❯ Object.getElementError node_modules/@testing-library/dom/dist/config.js:37:19 ❯ node_modules/@testing-library/dom/dist/query-helpers.js:76:38 ❯ node_modules/@testing-library/dom/dist/query-helpers.js:52:17 ❯ node_modules/@testing-library/dom/dist/query-helpers.js:95:19 ❯ src/__test__/Cart/Cart.test.tsx:100:19
expect(screen.getByText('3')).toBeInTheDocument();
});
});
148 changes: 148 additions & 0 deletions src/__test__/dashBoard/Categories.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { Provider } from 'react-redux';
import { configureStore } from '@reduxjs/toolkit';
import { MemoryRouter } from 'react-router-dom';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import Category from '@/components/dashBoard/Category';
import categoriesReducer from '@/features/Products/categorySlice';

const renderWithProviders = (ui: React.ReactElement) => {
const store = configureStore({ reducer: { categories: categoriesReducer } });
return render(
<Provider store={store}>
<MemoryRouter>{ui}</MemoryRouter>
</Provider>
);
};

describe('Category Component', () => {
let mock: MockAdapter;

beforeEach(() => {
mock = new MockAdapter(axios);
});

afterEach(() => {
mock.restore();
});

it('should render the component with initial state', () => {
renderWithProviders(<Category />);
expect(screen.getByText(/Categories/i)).toBeInTheDocument();
});

it('renders Categories component with category icons', async () => {
mock.onGet('/api/categories').reply(200, [
{
id: 1,
name: 'Category 1',
description: 'Description 1',
icon: 'https://example.com/icon1.png',
},
{
id: 2,
name: 'Category 2',
description: 'Description 2',
icon: 'https://example.com/icon2.png',
},
]);

renderWithProviders(<Category />);

const icons = await screen.findAllByRole('img');
icons.forEach((icon) => {
expect(icon).toHaveAttribute('alt');
});
});

it('paginates categories', async () => {
mock.onGet('/api/categories').reply(
200,
Array.from({ length: 20 }, (_, i) => ({
id: i + 1,
name: `Category ${i + 1}`,
description: `Description ${i + 1}`,
icon: `https://example.com/icon${i + 1}.png`,
}))
);

renderWithProviders(<Category />);

const nextPageButton = await screen.findByRole('button', { name: /next/i });
fireEvent.click(nextPageButton);
expect(nextPageButton).toBeInTheDocument();
});

it('should render the component with initial state', async () => {
renderWithProviders(<Category />);
await waitFor(() =>
expect(screen.getByText(/Categories/i)).toBeInTheDocument()
);
});

it('paginates categories', async () => {
mock.onGet('/api/categories').reply(
200,
Array.from({ length: 20 }, (_, i) => ({
id: i + 1,
name: `Category ${i + 1}`,
description: `Description ${i + 1}`,
icon: `https://example.com/icon${i + 1}.png`,
}))
);

renderWithProviders(<Category />);

const nextPageButton = await screen.findByRole('button', { name: /next/i });
fireEvent.click(nextPageButton);
expect(nextPageButton).toBeInTheDocument();
});

it('should display validation errors if form is submitted with invalid data', async () => {
renderWithProviders(<Category />);

// Open the form
fireEvent.click(screen.getByText(/Add Category/i));

// Trigger form submission
fireEvent.click(screen.getByText(/Save/i));

// Wait for validation errors to appear
await waitFor(() => {
expect(screen.getByText(/Name/i)).toBeInTheDocument();
expect(screen.getByText(/Icon/i)).toBeInTheDocument();
expect(screen.getByText(/Description/i)).toBeInTheDocument();
});
});

it('should submit form and handle API response', async () => {
mock.onPost(`${import.meta.env.VITE_BASE_URL}/category/`).reply(201);

renderWithProviders(<Category />);

// Open the form
fireEvent.click(screen.getByText(/Add Category/i));

// Fill out the form
fireEvent.change(screen.getByPlaceholderText(/Name of the category/i), {
target: { value: 'New Category' },
});
fireEvent.change(
screen.getByPlaceholderText(/Description of the category/i),
{
target: { value: 'Category description' },
}
);
fireEvent.change(screen.getByPlaceholderText(/URL of the category icon/i), {
target: { value: 'https://example.com/icon.png' },
});

fireEvent.click(screen.getByText(/Save/i));

await waitFor(() => {
expect(mock.history.post.length).toBe(1);
});
});
});
46 changes: 16 additions & 30 deletions src/__test__/dashBoard/Seller.test.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import axios from 'axios';
import { Provider } from 'react-redux';
import { MemoryRouter } from 'react-router-dom';
import { describe, it, expect } from 'vitest';
import { describe, it, expect, beforeEach } from 'vitest';
import MockAdapter from 'axios-mock-adapter';
import { render, screen, fireEvent } from '@testing-library/react';
import { render, screen, waitFor } from '@testing-library/react';
import { configureStore } from '@reduxjs/toolkit';
import Seller from '@/pages/Seller';
import productReducer from '@/app/Dashboard/AllProductSlices';
Expand Down Expand Up @@ -82,42 +82,25 @@ describe('Seller Component', () => {
expect(screen.getByText('Sellers')).toBeInTheDocument();
});

it('should display elements of the table', () => {
renderWithProviders(<Seller />);

expect(screen.getByText(/Image/)).toBeInTheDocument();
expect(screen.getByText(/First Name/)).toBeInTheDocument();
expect(screen.getByText(/Last Name/)).toBeInTheDocument();
expect(screen.getByText(/Email/)).toBeInTheDocument();
expect(screen.getByText(/Items Count/)).toBeInTheDocument();
expect(screen.getByText(/Date/)).toBeInTheDocument();
expect(screen.getByText(/Status/)).toBeInTheDocument();
expect(screen.getByText(/Action/)).toBeInTheDocument();
});

it('should filter sellers by search term', async () => {
// Mock API response
it('should display elements of the table', async () => {
mock
.onGet(`${import.meta.env.VITE_BASE_URL}/user/getAllUsers`)
.reply(200, { users: mockBuyers });

// Render component
renderWithProviders(<Seller />);

// Dispatch fetchBuyers to populate the state
await store.dispatch(fetchBuyers() as any);

// Perform search action
const searchInput = screen.getByPlaceholderText('Search Seller');
fireEvent.change(searchInput, { target: { value: 'Vendor1' } });

// Check filtered results
expect(screen.getByText('Vendor1')).toBeInTheDocument();
expect(screen.queryByText('Customer1')).not.toBeInTheDocument();
await waitFor(() => {
expect(screen.getByText('Name')).toBeInTheDocument();
expect(screen.getByText('Email')).toBeInTheDocument();
expect(screen.getByText('Items')).toBeInTheDocument();
expect(screen.getByText('Date')).toBeInTheDocument();
expect(screen.getByText('Status')).toBeInTheDocument();
expect(screen.getByText('Action')).toBeInTheDocument();
});
});

it('should handle loading state', async () => {
// Mock API response
mock
.onGet(`${import.meta.env.VITE_BASE_URL}/user/getAllUsers`)
.reply(200, { users: mockBuyers });
Expand All @@ -137,7 +120,10 @@ describe('Seller Component', () => {

renderWithProviders(<Seller />);
await store.dispatch(fetchBuyers() as any);
expect(screen.queryByText('Vendor1')).toBeNull();
expect(screen.queryByText('Customer1')).toBeNull();

await waitFor(() => {
expect(screen.queryByText('Vendor1')).toBeNull();
expect(screen.queryByText('Customer1')).toBeNull();
});
});
});
Loading

0 comments on commit d38dbda

Please sign in to comment.