Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

104 checkout page #113

Merged
merged 1 commit into from
Jul 23, 2024
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
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
"axios": "^1.7.2",
"axios-mock-adapter": "^1.22.0",
"chart.js": "^4.4.3",
"chart.js": "^4.4.3",
"date-fns": "^3.6.0",
"cloudinary": "^2.2.0",
"cloudinary-core": "^2.13.1",
"date-fns": "^3.6.0",
Expand Down
1 change: 1 addition & 0 deletions public/icons/address.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/icons/card.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/icons/ccv.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/icons/date.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/icons/location.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/icons/user.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
125 changes: 125 additions & 0 deletions public/momo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/unionpay.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
60 changes: 60 additions & 0 deletions src/__test__/Checkout/cardInput.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { render, screen, fireEvent } from '@testing-library/react';
import { describe, it, expect, vi } from 'vitest';
import CardInput from '@/components/Checkout/CardInput';

describe('CardInput Component', () => {
it('renders CardInput component and types into card number input', () => {
const mockSaveCard = vi.fn();
render(<CardInput saveCard={mockSaveCard} />);
const cardNumberInput = screen.getByPlaceholderText('Card Number');
fireEvent.change(cardNumberInput, {
target: { value: '4111111111111111' },
});
expect(cardNumberInput).toHaveValue('4111111111111111');
});

it('detects Visa card type correctly', () => {
const mockSaveCard = vi.fn();
render(<CardInput saveCard={mockSaveCard} />);
const cardNumberInput = screen.getByPlaceholderText('Card Number');
fireEvent.change(cardNumberInput, {
target: { value: '4111111111111111' },
});
expect(screen.getByAltText('visa')).toBeInTheDocument();
});

test('detects Mastercard card type correctly', () => {
const mockSaveCard = vi.fn();
render(<CardInput saveCard={mockSaveCard} />);
const cardNumberInput = screen.getByPlaceholderText('Card Number');
fireEvent.change(cardNumberInput, {
target: { value: '5105105105105100' },
});
expect(screen.getByAltText('mastercard')).toBeInTheDocument();
});

test('shows error for invalid card type', () => {
const mockSaveCard = vi.fn();
render(<CardInput saveCard={mockSaveCard} />);
const cardNumberInput = screen.getByPlaceholderText('Card Number');
fireEvent.change(cardNumberInput, {
target: { value: '1234567890123456' },
});
expect(screen.getByText('Invalid Card')).toBeInTheDocument();
});
test('handles expiry date change correctly', () => {
const mockSaveCard = vi.fn();
render(<CardInput saveCard={mockSaveCard} />);
const expiryDateInput = screen.getByPlaceholderText('Expiry MM/YY');
fireEvent.change(expiryDateInput, { target: { value: '12/34' } });
expect(expiryDateInput).toHaveValue('12/34');
});

test('shows error for invalid expiry date', () => {
const mockSaveCard = vi.fn();
render(<CardInput saveCard={mockSaveCard} />);
const expiryDateInput = screen.getByPlaceholderText('Expiry MM/YY');
fireEvent.change(expiryDateInput, { target: { value: '19/11' } });
expect(screen.getByText('Invalid Expiry Date')).toBeInTheDocument();
});
});
143 changes: 143 additions & 0 deletions src/__test__/Checkout/checkout.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import { configureStore } from '@reduxjs/toolkit';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import checkoutReducer, {
placeOrder,
getOrders,
makePayment,
updateDeliveryInfo,
updateCouponCode,
} from '@/features/Checkout/checkoutSlice';
import Order from '@/interfaces/order';

// Create mock for axios
const mock = new MockAdapter(axios);

// Configure mock store with the checkout reducer
const store = configureStore({
reducer: {
checkout: checkoutReducer,
},
});

describe('checkoutSlice', () => {
beforeEach(() => {
mock.reset();
});

it('should handle initial state', () => {
expect(store.getState().checkout).toEqual({
checkout: {
id: 31,
totalAmount: 160,
status: 'Pending',
couponCode: '',
deliveryInfo: {
address: '123 Main St',
city: 'Anytown',
zip: '12345',
},
country: 'US',
paymentInfo: null,
trackingNumber: 'Tr280585',
createdAt: '2024-07-22T01:48:05.301Z',
updatedAt: '2024-07-22T11:01:20.291Z',
paid: true,
orderDetails: [
{
id: 41,
quantity: 2,
price: 160,
},
],
},
loading: false,
paying: false,
error: null,
});
});

it('placeOrder updates state on fulfilled', async () => {
const order = {
deliveryInfo: {
address: '123 Main St',
city: 'Anytown',
zip: '12345',
},
couponCode: 'string',
email: 'string',
firstName: 'string',
lastName: 'string',
};

mock.onPost('/checkout').reply(200, { order });

await store.dispatch(placeOrder(order));

expect(store.getState().checkout.checkout.deliveryInfo).toEqual(
expect.objectContaining(order.deliveryInfo)
);
expect(store.getState().checkout.checkout.status).toEqual('Pending');
});

it('getOrders updates state on fulfilled', async () => {
const orders: Order[] = [
{
country: 'US',
couponCode: '',
createdAt: '2024-07-22T01:48:05.301Z',
deliveryInfo: {
address: '123 Main St',
city: 'Anytown',
zip: '12345',
},
id: 31,
orderDetails: [
{
id: 41,
price: 160,
quantity: 2,
},
],
paid: true,
paymentInfo: null,
status: 'Pending',
totalAmount: 160,
trackingNumber: 'Tr280585',
updatedAt: '2024-07-22T11:01:20.291Z',
},
];

mock.onGet('/checkout/getall-order').reply(200, orders);

await store.dispatch(getOrders());

expect(store.getState().checkout.checkout).toEqual(
expect.objectContaining(orders[0])
);
});

it('makePayment updates state on fulfilled', async () => {
mock.onPost('/buyer/payment').reply(200, { success: true });

await store.dispatch(makePayment(31));

expect(store.getState().checkout.paying).toEqual(true);
});

it('updateDeliveryInfo updates delivery info', () => {
const deliveryInfo = { address: '456 Main St' };
store.dispatch(updateDeliveryInfo(deliveryInfo));

expect(store.getState().checkout.checkout.deliveryInfo).toEqual(
expect.objectContaining(deliveryInfo)
);
});

it('updateCouponCode updates coupon code', () => {
const couponCode = 'NEWYEAR';
store.dispatch(updateCouponCode(couponCode));

expect(store.getState().checkout.checkout.couponCode).toEqual(couponCode);
});
});
10 changes: 5 additions & 5 deletions src/__test__/Orders/Orders.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ const mockOrders: Order[] = [
updatedAt: '2023-07-17T00:00:00Z',
status: 'Pending',
totalAmount: 100,
deliveryInfo:
'{"address": "123 Main St", "city": "Anytown", "country": "USA"}',
country: 'USA',
deliveryInfo: { address: '123 Main St', city: 'Anytown', zip: '12345' },
paymentInfo: null,
createdAt: '',
paid: false,
Expand All @@ -26,8 +26,8 @@ const mockOrders: Order[] = [
updatedAt: '2023-07-16T00:00:00Z',
status: 'Completed',
totalAmount: 200,
deliveryInfo:
'{"address": "456 Elm St", "city": "Othertown", "country": "USA"}',
country: 'USA',
deliveryInfo: { address: '123 Main St', city: 'Anytown', zip: '12345' },
paymentInfo: null,
createdAt: '',
paid: false,
Expand Down Expand Up @@ -168,6 +168,6 @@ describe('Orders Component', () => {
</Provider>
);
const rows = screen.getAllByRole('row');
expect(rows.length).toBe(11); //
expect(rows.length).toBe(6); //
});
});
Loading
Loading