From 392fb9bcca42113ac44adcd8835a399565956f73 Mon Sep 17 00:00:00 2001 From: Prakash Maity Date: Wed, 7 Aug 2024 21:50:11 +0530 Subject: [PATCH] fix(testAdded) --- jest.config.ts | 18 ++++++++++ package.json | 8 ++++- .../(dashboard)/{review => (review)}/page.tsx | 0 src/app/(dashboard)/products/page.tsx | 2 +- src/services/api/__mocks__/axiosInstance.ts | 7 ++++ src/services/api/loginApi.test.ts | 33 +++++++++++++++++++ src/services/api/productApi.test.ts | 29 ++++++++++++++++ .../{home.services.ts => api/productsApi.ts} | 6 ++-- 8 files changed, 98 insertions(+), 5 deletions(-) create mode 100644 jest.config.ts rename src/app/(dashboard)/{review => (review)}/page.tsx (100%) create mode 100644 src/services/api/__mocks__/axiosInstance.ts create mode 100644 src/services/api/loginApi.test.ts create mode 100644 src/services/api/productApi.test.ts rename src/services/{home.services.ts => api/productsApi.ts} (61%) diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 0000000..14de0c6 --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,18 @@ +import type { Config } from 'jest'; +import nextJest from 'next/jest.js'; + +const createJestConfig = nextJest({ + // Provide the path to your Next.js app to load next.config.js and .env files in your test environment + dir: './', +}); + +// Add any custom config to be passed to Jest +const config: Config = { + coverageProvider: 'v8', + testEnvironment: 'jsdom', + // Add more setup options before each test is run + // setupFilesAfterEnv: ['/jest.setup.ts'], +}; + +// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async +export default createJestConfig(config); diff --git a/package.json b/package.json index 30d4e32..b0ee3fd 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,9 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "next lint", + "test": "jest", + "test:watch": "jest --watch" }, "dependencies": { "@emotion/cache": "^11.13.1", @@ -27,12 +29,14 @@ "react-redux": "^9.1.2", "redux-persist": "^6.0.0", "sass": "^1.77.8", + "ts-node": "^10.9.2", "zod": "^3.23.8" }, "devDependencies": { "@testing-library/jest-dom": "^6.4.8", "@testing-library/react": "^16.0.0", "@testing-library/user-event": "^14.5.2", + "@types/jest": "^29.5.12", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", @@ -40,6 +44,8 @@ "eslint": "^8", "eslint-config-next": "14.2.5", "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "ts-jest": "^29.2.4", "typescript": "^5" } } diff --git a/src/app/(dashboard)/review/page.tsx b/src/app/(dashboard)/(review)/page.tsx similarity index 100% rename from src/app/(dashboard)/review/page.tsx rename to src/app/(dashboard)/(review)/page.tsx diff --git a/src/app/(dashboard)/products/page.tsx b/src/app/(dashboard)/products/page.tsx index 2b1f49d..cad954a 100644 --- a/src/app/(dashboard)/products/page.tsx +++ b/src/app/(dashboard)/products/page.tsx @@ -4,7 +4,7 @@ import React from "react"; import CardHeader from "@mui/material/CardHeader"; import CardContent from "@mui/material/CardContent"; import TitleHeader from "@/components/titleHeader/titleHeader"; -import homeServices from "@/services/home.services"; +import homeServices from "@/services/api/productsApi"; const HomePage = async () => { const data = await homeServices.getProducts(); diff --git a/src/services/api/__mocks__/axiosInstance.ts b/src/services/api/__mocks__/axiosInstance.ts new file mode 100644 index 0000000..7a674a0 --- /dev/null +++ b/src/services/api/__mocks__/axiosInstance.ts @@ -0,0 +1,7 @@ +// __mocks__/axiosInstance.ts +import axios from 'axios'; +import MockAdapter from 'axios-mock-adapter'; + +const mock = new MockAdapter(axios); + +export default mock; diff --git a/src/services/api/loginApi.test.ts b/src/services/api/loginApi.test.ts new file mode 100644 index 0000000..37a6c7c --- /dev/null +++ b/src/services/api/loginApi.test.ts @@ -0,0 +1,33 @@ +import axiosInstance from '../axios/axiosInstance'; +import { loginApi } from './loginApi'; + +jest.mock('../axios/axiosInstance'); + +describe('login API', () => { + it('should return token on successful login', async () => { + const mockResponse = { + data: { + token: 'fake-token', + }, + }; + (axiosInstance.post as jest.Mock).mockResolvedValue(mockResponse); + + const data = { username: 'emilys', password: 'emilyspass' }; + const result = await loginApi(data); + + expect(result).toEqual(mockResponse.data); + expect(axiosInstance.post).toHaveBeenCalledWith('/auth/login', data); + }); + + it('should throw an error on failed login', async () => { + const errorMessage = 'Invalid credentials'; + (axiosInstance.post as jest.Mock).mockRejectedValue( + new Error(errorMessage) + ); + + const data = { username: 'test@example.com', password: 'wrongpassword' }; + + await expect(loginApi(data)).rejects.toThrow(errorMessage); + expect(axiosInstance.post).toHaveBeenCalledWith('/auth/login', data); + }); +}); diff --git a/src/services/api/productApi.test.ts b/src/services/api/productApi.test.ts new file mode 100644 index 0000000..9b9c194 --- /dev/null +++ b/src/services/api/productApi.test.ts @@ -0,0 +1,29 @@ +import axios from 'axios'; +import homeServices from './productsApi'; + +jest.mock('axios'); + +describe('homeServices.getProducts', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + test('should return data on successful API call', async () => { + const mockData = { products: [{ id: 1, name: 'Product 1' }] }; + (axios.get as jest.Mock).mockResolvedValue({ data: mockData }); + + const result = await homeServices.getProducts(); + + expect(result).toEqual(mockData); + expect(axios.get).toHaveBeenCalledWith('https://dummyjson.com/products'); + }); + + test('should throw generic error message on non-Axios error', async () => { + (axios.get as jest.Mock).mockRejectedValue(new Error('Non-Axios error')); + + await expect(homeServices.getProducts()).rejects.toThrow( + 'Something went wrong. Please try again.' + ); + expect(axios.get).toHaveBeenCalledWith('https://dummyjson.com/products'); + }); +}); diff --git a/src/services/home.services.ts b/src/services/api/productsApi.ts similarity index 61% rename from src/services/home.services.ts rename to src/services/api/productsApi.ts index 6596c5e..e041450 100644 --- a/src/services/home.services.ts +++ b/src/services/api/productsApi.ts @@ -1,16 +1,16 @@ -import axios, { isAxiosError } from "axios"; +import axios, { isAxiosError } from 'axios'; /** Product List Home Page */ const homeServices = { getProducts: async () => { try { - const res = await axios.get("https://dummyjson.com/products"); + const res = await axios.get('https://dummyjson.com/products'); return res.data; } catch (error: any) { if (isAxiosError(error)) { throw new Error(error.response?.data.message); } - throw new Error("Something went wrong. Please try again."); + throw new Error('Something went wrong. Please try again.'); } }, };