diff --git a/.github/workflows/jest.yml b/.github/workflows/jest.yml new file mode 100644 index 0000000..dd44139 --- /dev/null +++ b/.github/workflows/jest.yml @@ -0,0 +1,28 @@ +name: Jest Unit Testing (API Routes & Server Actions) + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + jest: + runs-on: ubuntu-latest + environment: testing + env: + DATABASE_URL: ${{ secrets.DATABASE_URL }} + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: '20' + + - name: Install dependencies + run: npm install + + - name: Run unit tests + run: npm run jest diff --git a/.github/workflows/vitest.yml b/.github/workflows/vitest.yml index 7be6cf8..94e3688 100644 --- a/.github/workflows/vitest.yml +++ b/.github/workflows/vitest.yml @@ -1,4 +1,4 @@ -name: Vitest Unit Test +name: Vitest Unit Testing (Components & Pages) on: push: diff --git a/.prettierrc b/.prettierrc index 977d0b9..7695265 100644 --- a/.prettierrc +++ b/.prettierrc @@ -3,7 +3,7 @@ "semi": true, "singleQuote": true, "trailingComma": "es5", - "printWidth": 60, + "printWidth": 80, "singleAttributePerLine": true, "plugins": ["prettier-plugin-tailwindcss"] } diff --git a/__tests__/unit_test/components/Avatar.test.tsx b/__tests__/unit_test/components/Avatar.test.tsx index 74e052e..eb84b1f 100644 --- a/__tests__/unit_test/components/Avatar.test.tsx +++ b/__tests__/unit_test/components/Avatar.test.tsx @@ -1,16 +1,5 @@ -import { - render, - screen, - fireEvent, - cleanup, -} from '@testing-library/react'; -import { - describe, - it, - expect, - vi, - afterEach, -} from 'vitest'; +import { render, screen, fireEvent, cleanup } from '@testing-library/react'; +import { describe, it, expect, vi, afterEach } from 'vitest'; import Avatar from '@/app/components/Avatar'; import React from 'react'; @@ -67,12 +56,10 @@ describe('', () => { }); it('should not have cursor-pointer class when onClick is not provided', () => { - render( - + render(); + expect(screen.getByAltText('Avatar')).not.toHaveProperty( + 'cursor-pointer' ); - expect( - screen.getByAltText('Avatar') - ).not.toHaveProperty('cursor-pointer'); }); it('should have cursor-pointer class when onClick is provided', () => { @@ -82,8 +69,8 @@ describe('', () => { onClick={() => {}} /> ); - expect( - screen.getByAltText('Avatar').className - ).include('cursor-pointer'); + expect(screen.getByAltText('Avatar').className).include( + 'cursor-pointer' + ); }); }); diff --git a/__tests__/unit_test/components/Button.test.tsx b/__tests__/unit_test/components/Button.test.tsx index e9c3a42..9ad98d3 100644 --- a/__tests__/unit_test/components/Button.test.tsx +++ b/__tests__/unit_test/components/Button.test.tsx @@ -1,15 +1,5 @@ -import { - render, - screen, - fireEvent, -} from '@testing-library/react'; -import { - describe, - it, - expect, - vi, - beforeEach, -} from 'vitest'; +import { render, screen, fireEvent } from '@testing-library/react'; +import { describe, it, expect, vi, beforeEach } from 'vitest'; import Button from '@/app/components/Button'; import { FaUser } from 'react-icons/fa'; import React from 'react'; @@ -30,9 +20,7 @@ describe(' @@ -48,13 +38,7 @@ vi.mock('@/app/components/comments/CommentBox', () => ({ })); vi.mock('@/app/components/comments/Comment', () => ({ - default: ({ - userName, - comment, - }: { - userName: string; - comment: string; - }) => ( + default: ({ userName, comment }: { userName: string; comment: string }) => (

{userName}

{comment}

@@ -105,9 +89,10 @@ describe('Comments', () => { ); expect(screen.getByText('comments')).toBeDefined(); - expect( - screen.getByAltText('avatar') - ).toHaveProperty('src', mockUser.image); + expect(screen.getByAltText('avatar')).toHaveProperty( + 'src', + mockUser.image + ); }); it('displays comments', () => { @@ -120,9 +105,7 @@ describe('Comments', () => { ); expect(screen.getByText('Test User')).toBeDefined(); - expect( - screen.getByText('This is a comment') - ).toBeDefined(); + expect(screen.getByText('This is a comment')).toBeDefined(); }); it('handles creating a comment', async () => { @@ -138,9 +121,9 @@ describe('Comments', () => { fireEvent.click(submitButton); await waitFor(() => { - expect( - mockOnCreateComment - ).toHaveBeenCalledWith('This is a new comment'); + expect(mockOnCreateComment).toHaveBeenCalledWith( + 'This is a new comment' + ); }); }); }); diff --git a/__tests__/unit_test/components/inputs/CategoryInput.test.tsx b/__tests__/unit_test/components/inputs/CategoryInput.test.tsx index df08c94..e2f9306 100644 --- a/__tests__/unit_test/components/inputs/CategoryInput.test.tsx +++ b/__tests__/unit_test/components/inputs/CategoryInput.test.tsx @@ -1,17 +1,6 @@ import React from 'react'; -import { - render, - screen, - fireEvent, - cleanup, -} from '@testing-library/react'; -import { - describe, - it, - expect, - vi, - afterEach, -} from 'vitest'; +import { render, screen, fireEvent, cleanup } from '@testing-library/react'; +import { describe, it, expect, vi, afterEach } from 'vitest'; import CategoryBox from '@/app/components/inputs/CategoryInput'; import { FaHome } from 'react-icons/fa'; @@ -51,11 +40,8 @@ describe('CategoryBox', () => { /> ); - const categoryBox = - container.firstChild as HTMLElement; - expect(categoryBox.className).toContain( - 'border-black' - ); + const categoryBox = container.firstChild as HTMLElement; + expect(categoryBox.className).toContain('border-black'); expect(categoryBox.className).toContain('selected'); }); @@ -69,14 +55,9 @@ describe('CategoryBox', () => { /> ); - const categoryBox = - container.firstChild as HTMLElement; - expect(categoryBox.className).toContain( - 'border-neutral-200' - ); - expect(categoryBox.className).not.toContain( - 'selected' - ); + const categoryBox = container.firstChild as HTMLElement; + expect(categoryBox.className).toContain('border-neutral-200'); + expect(categoryBox.className).not.toContain('selected'); }); it('calls onClick with the correct label when clicked', () => { @@ -88,8 +69,7 @@ describe('CategoryBox', () => { /> ); - const categoryBox = - screen.getByText('home').parentElement; + const categoryBox = screen.getByText('home').parentElement; fireEvent.click(categoryBox!); expect(mockOnClick).toHaveBeenCalledWith('Home'); diff --git a/__tests__/unit_test/components/inputs/Counter.test.tsx b/__tests__/unit_test/components/inputs/Counter.test.tsx index 83d6af5..bec9095 100644 --- a/__tests__/unit_test/components/inputs/Counter.test.tsx +++ b/__tests__/unit_test/components/inputs/Counter.test.tsx @@ -1,18 +1,6 @@ import React from 'react'; -import { - render, - screen, - fireEvent, - cleanup, -} from '@testing-library/react'; -import { - describe, - it, - expect, - vi, - beforeEach, - afterEach, -} from 'vitest'; +import { render, screen, fireEvent, cleanup } from '@testing-library/react'; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import Counter from '@/app/components/inputs/Counter'; describe('Counter', () => { @@ -37,9 +25,7 @@ describe('Counter', () => { ); expect(screen.getByText('Guests')).toBeDefined(); - expect( - screen.getByText('How many guests are coming?') - ).toBeDefined(); + expect(screen.getByText('How many guests are coming?')).toBeDefined(); expect(screen.getByText('2')).toBeDefined(); }); @@ -53,8 +39,7 @@ describe('Counter', () => { /> ); - const plusButton = - screen.getByTestId('AiOutlinePlus'); + const plusButton = screen.getByTestId('AiOutlinePlus'); fireEvent.click(plusButton.parentElement!); expect(mockOnChange).toHaveBeenCalledWith(3); @@ -70,9 +55,7 @@ describe('Counter', () => { /> ); - const minusButton = screen.getByTestId( - 'AiOutlineMinus' - ); + const minusButton = screen.getByTestId('AiOutlineMinus'); fireEvent.click(minusButton.parentElement!); expect(mockOnChange).toHaveBeenCalledWith(1); @@ -88,9 +71,7 @@ describe('Counter', () => { /> ); - const minusButton = screen.getByTestId( - 'AiOutlineMinus' - ); + const minusButton = screen.getByTestId('AiOutlineMinus'); fireEvent.click(minusButton.parentElement!); expect(mockOnChange).not.toHaveBeenCalled(); diff --git a/__tests__/unit_test/components/inputs/ImageUpload.test.tsx b/__tests__/unit_test/components/inputs/ImageUpload.test.tsx index f902d7e..790c290 100644 --- a/__tests__/unit_test/components/inputs/ImageUpload.test.tsx +++ b/__tests__/unit_test/components/inputs/ImageUpload.test.tsx @@ -1,39 +1,21 @@ import React from 'react'; -import { - render, - screen, - fireEvent, - cleanup, -} from '@testing-library/react'; -import { - describe, - it, - expect, - vi, - beforeEach, - afterEach, -} from 'vitest'; +import { render, screen, fireEvent, cleanup } from '@testing-library/react'; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import ImageUpload from '@/app/components/inputs/ImageUpload'; // Define types for CldUploadWidget type CldUploadWidgetProps = { onUpload: (result: any) => void; - children: (props: { - open: () => void; - }) => React.ReactNode; + children: (props: { open: () => void }) => React.ReactNode; }; // Mock next-cloudinary vi.mock('next-cloudinary', () => ({ - CldUploadWidget: ({ - onUpload, - children, - }: CldUploadWidgetProps) => { + CldUploadWidget: ({ onUpload, children }: CldUploadWidgetProps) => { const handleUpload = () => { onUpload({ info: { - secure_url: - 'https://example.com/newimage.jpg', + secure_url: 'https://example.com/newimage.jpg', }, }); }; @@ -65,9 +47,7 @@ describe('ImageUpload', () => { /> ); - expect( - screen.getByTestId('TbPhotoPlus') - ).toBeDefined(); + expect(screen.getByTestId('TbPhotoPlus')).toBeDefined(); expect(screen.queryByRole('img')).toBeNull(); }); @@ -79,9 +59,7 @@ describe('ImageUpload', () => { /> ); - expect( - screen.getByTestId('TbPhotoPlus') - ).toBeDefined(); + expect(screen.getByTestId('TbPhotoPlus')).toBeDefined(); expect(screen.getByRole('img')).toBeDefined(); expect(screen.getByRole('img')).toHaveProperty( 'src', @@ -97,9 +75,7 @@ describe('ImageUpload', () => { /> ); - fireEvent.click( - screen.getByTestId('TbPhotoPlus').parentElement! - ); + fireEvent.click(screen.getByTestId('TbPhotoPlus').parentElement!); expect(mockOnChange).toHaveBeenCalledWith( 'https://example.com/newimage.jpg' ); diff --git a/__tests__/unit_test/components/inputs/Input.test.tsx b/__tests__/unit_test/components/inputs/Input.test.tsx index 6f36def..5347bb7 100644 --- a/__tests__/unit_test/components/inputs/Input.test.tsx +++ b/__tests__/unit_test/components/inputs/Input.test.tsx @@ -1,26 +1,11 @@ import React from 'react'; -import { - render, - screen, - cleanup, -} from '@testing-library/react'; -import { - describe, - it, - expect, - vi, - afterEach, -} from 'vitest'; +import { render, screen, cleanup } from '@testing-library/react'; +import { describe, it, expect, vi, afterEach } from 'vitest'; import Input from '@/app/components/inputs/Input'; -import { - UseFormRegister, - FieldValues, - FieldErrors, -} from 'react-hook-form'; +import { UseFormRegister, FieldValues, FieldErrors } from 'react-hook-form'; describe('Input', () => { - const mockRegister: UseFormRegister = - vi.fn(); + const mockRegister: UseFormRegister = vi.fn(); const mockErrors: FieldErrors = {}; afterEach(() => { @@ -37,9 +22,7 @@ describe('Input', () => { /> ); - expect( - screen.getByLabelText('Test Input') - ).toBeDefined(); + expect(screen.getByLabelText('Test Input')).toBeDefined(); expect(screen.getByRole('textbox')).toBeDefined(); }); @@ -56,9 +39,7 @@ describe('Input', () => { const input = screen.getByRole('textbox'); expect(input.className).toContain('pl-9'); - expect( - screen.getByTestId('BiDollar') - ).toBeDefined(); + expect(screen.getByTestId('BiDollar')).toBeDefined(); }); it('shows error styling when there is an error', () => { @@ -78,12 +59,8 @@ describe('Input', () => { ); const input = screen.getByRole('textbox'); - expect(input.className).toContain( - 'border-rose-500' - ); - expect(input.className).toContain( - 'focus:border-rose-500' - ); + expect(input.className).toContain('border-rose-500'); + expect(input.className).toContain('focus:border-rose-500'); }); it('disables the input when disabled prop is true', () => { diff --git a/__tests__/unit_test/components/modals/ConfirmModal.test.tsx b/__tests__/unit_test/components/modals/ConfirmModal.test.tsx index 9bc076e..56cf363 100644 --- a/__tests__/unit_test/components/modals/ConfirmModal.test.tsx +++ b/__tests__/unit_test/components/modals/ConfirmModal.test.tsx @@ -5,14 +5,7 @@ import { act, cleanup, } from '@testing-library/react'; -import { - describe, - it, - expect, - vi, - beforeEach, - afterEach, -} from 'vitest'; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import ConfirmModal from '@/app/components/modals/ConfirmModal'; import React from 'react'; @@ -44,9 +37,7 @@ describe('', () => { onConfirm={mockOnConfirm} /> ); - expect( - screen.getAllByText('delete')[0] - ).toBeDefined(); + expect(screen.getAllByText('delete')[0]).toBeDefined(); }); it('renders the confirm title correctly', () => { @@ -57,9 +48,7 @@ describe('', () => { onConfirm={mockOnConfirm} /> ); - expect( - screen.getByText('confirm_title') - ).toBeDefined(); + expect(screen.getByText('confirm_title')).toBeDefined(); }); it('calls setIsOpen with false when close button is clicked', () => { @@ -70,9 +59,7 @@ describe('', () => { onConfirm={mockOnConfirm} /> ); - const closeButton = screen.getByTestId( - 'close-modal-button' - ); + const closeButton = screen.getByTestId('close-modal-button'); fireEvent.click(closeButton); // Wait for the setTimeout in handleClose @@ -91,8 +78,7 @@ describe('', () => { onConfirm={mockOnConfirm} /> ); - const confirmButton = - screen.getAllByText('delete')[1]; + const confirmButton = screen.getAllByText('delete')[1]; fireEvent.click(confirmButton); expect(mockOnConfirm).toHaveBeenCalledTimes(1); expect(mockSetIsOpen).toHaveBeenCalledWith(false); diff --git a/__tests__/unit_test/components/modals/DeleteRecipeModal.test.tsx b/__tests__/unit_test/components/modals/DeleteRecipeModal.test.tsx index a6e73a9..46683c1 100644 --- a/__tests__/unit_test/components/modals/DeleteRecipeModal.test.tsx +++ b/__tests__/unit_test/components/modals/DeleteRecipeModal.test.tsx @@ -5,14 +5,7 @@ import { act, cleanup, } from '@testing-library/react'; -import { - describe, - it, - expect, - vi, - beforeEach, - afterEach, -} from 'vitest'; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import ConfirmModal from '@/app/components/modals/ConfirmModal'; import React from 'react'; @@ -45,9 +38,7 @@ describe('', () => { /> ); // Using getAllByText and checking the first occurrence - expect( - screen.getAllByText('delete')[0] - ).toBeDefined(); + expect(screen.getAllByText('delete')[0]).toBeDefined(); }); it('renders the confirm title correctly', () => { @@ -58,9 +49,7 @@ describe('', () => { onConfirm={mockOnConfirm} /> ); - expect( - screen.getByText('confirm_title') - ).toBeDefined(); + expect(screen.getByText('confirm_title')).toBeDefined(); }); it('calls setIsOpen with false when close button is clicked', () => { @@ -71,9 +60,7 @@ describe('', () => { onConfirm={mockOnConfirm} /> ); - const closeButton = screen.getByTestId( - 'close-modal-button' - ); + const closeButton = screen.getByTestId('close-modal-button'); fireEvent.click(closeButton); // Wait for the setTimeout in handleClose @@ -92,8 +79,7 @@ describe('', () => { onConfirm={mockOnConfirm} /> ); - const confirmButton = - screen.getAllByText('delete')[1]; + const confirmButton = screen.getAllByText('delete')[1]; fireEvent.click(confirmButton); expect(mockOnConfirm).toHaveBeenCalledTimes(1); expect(mockSetIsOpen).toHaveBeenCalledWith(false); diff --git a/__tests__/unit_test/components/modals/LoginModal.test.tsx b/__tests__/unit_test/components/modals/LoginModal.test.tsx index abf91e2..cd0986c 100644 --- a/__tests__/unit_test/components/modals/LoginModal.test.tsx +++ b/__tests__/unit_test/components/modals/LoginModal.test.tsx @@ -6,14 +6,7 @@ import { waitFor, cleanup, } from '@testing-library/react'; -import { - vi, - describe, - it, - expect, - beforeEach, - afterEach, -} from 'vitest'; +import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest'; import LoginModal from '@/app/components/modals/LoginModal'; import { SignInResponse } from 'next-auth/react'; @@ -68,15 +61,9 @@ describe('LoginModal', () => { it('renders the login modal', () => { render(); - expect( - screen.getByText('welcome_back') - ).toBeDefined(); - expect( - screen.getByRole('textbox', { name: /email/i }) - ).toBeDefined(); - expect( - screen.getByLabelText(/password/i) - ).toBeDefined(); + expect(screen.getByText('welcome_back')).toBeDefined(); + expect(screen.getByRole('textbox', { name: /email/i })).toBeDefined(); + expect(screen.getByLabelText(/password/i)).toBeDefined(); expect( screen.getByRole('button', { name: /login_google/i, @@ -90,9 +77,7 @@ describe('LoginModal', () => { }); it('submits the form with valid credentials', async () => { - const signIn = vi.mocked( - await import('next-auth/react') - ).signIn; + const signIn = vi.mocked(await import('next-auth/react')).signIn; signIn.mockResolvedValue({ ok: true, error: null, @@ -105,32 +90,24 @@ describe('LoginModal', () => { fireEvent.change(screen.getByLabelText('email'), { target: { value: 'test@example.com' }, }); - fireEvent.change( - screen.getByLabelText('password'), - { target: { value: 'password123' } } - ); + fireEvent.change(screen.getByLabelText('password'), { + target: { value: 'password123' }, + }); fireEvent.click(screen.getByText('continue')); await waitFor(() => { - expect(signIn).toHaveBeenCalledWith( - 'credentials', - { - email: 'test@example.com', - password: 'password123', - redirect: false, - } - ); + expect(signIn).toHaveBeenCalledWith('credentials', { + email: 'test@example.com', + password: 'password123', + redirect: false, + }); }); }); it('displays success toast on successful login', async () => { - const signIn = vi.mocked( - await import('next-auth/react') - ).signIn; - const toast = vi.mocked( - await import('react-hot-toast') - ).toast; + const signIn = vi.mocked(await import('next-auth/react')).signIn; + const toast = vi.mocked(await import('react-hot-toast')).toast; signIn.mockResolvedValue({ ok: true, @@ -144,37 +121,27 @@ describe('LoginModal', () => { fireEvent.change(screen.getByLabelText('email'), { target: { value: 'test@example.com' }, }); - fireEvent.change( - screen.getByLabelText('password'), - { target: { value: 'password123' } } - ); + fireEvent.change(screen.getByLabelText('password'), { + target: { value: 'password123' }, + }); fireEvent.click(screen.getByText('continue')); await waitFor(() => { - expect(signIn).toHaveBeenCalledWith( - 'credentials', - { - email: 'test@example.com', - password: 'password123', - redirect: false, - } - ); + expect(signIn).toHaveBeenCalledWith('credentials', { + email: 'test@example.com', + password: 'password123', + redirect: false, + }); }); await waitFor(() => { - expect(toast.success).toHaveBeenCalledWith( - 'logged_in' - ); + expect(toast.success).toHaveBeenCalledWith('logged_in'); }); }); it('displays error toast on failed login', async () => { - const signIn = vi.mocked( - await import('next-auth/react') - ).signIn; - const toast = vi.mocked( - await import('react-hot-toast') - ).toast; + const signIn = vi.mocked(await import('next-auth/react')).signIn; + const toast = vi.mocked(await import('react-hot-toast')).toast; signIn.mockResolvedValue({ ok: false, @@ -188,24 +155,19 @@ describe('LoginModal', () => { fireEvent.change(screen.getByLabelText('email'), { target: { value: 'test@example.com' }, }); - fireEvent.change( - screen.getByLabelText('password'), - { target: { value: 'wrongpassword' } } - ); + fireEvent.change(screen.getByLabelText('password'), { + target: { value: 'wrongpassword' }, + }); fireEvent.click(screen.getByText('continue')); await waitFor(() => { - expect(toast.error).toHaveBeenCalledWith( - 'Invalid credentials' - ); + expect(toast.error).toHaveBeenCalledWith('Invalid credentials'); }); }); it('calls signIn with Google provider when Google button is clicked', async () => { - const signIn = vi.mocked( - await import('next-auth/react') - ).signIn; + const signIn = vi.mocked(await import('next-auth/react')).signIn; render(); fireEvent.click(screen.getByText('login_google')); @@ -214,9 +176,7 @@ describe('LoginModal', () => { }); it('calls signIn with GitHub provider when GitHub button is clicked', async () => { - const signIn = vi.mocked( - await import('next-auth/react') - ).signIn; + const signIn = vi.mocked(await import('next-auth/react')).signIn; render(); fireEvent.click(screen.getByText('login_github')); @@ -230,9 +190,7 @@ describe('LoginModal', () => { fireEvent.click(screen.getByText('create_account')); await waitFor(() => { - expect( - mockRegisterModalOpen - ).toHaveBeenCalled(); + expect(mockRegisterModalOpen).toHaveBeenCalled(); expect(mockLoginModalClose).toHaveBeenCalled(); }); }); diff --git a/__tests__/unit_test/components/modals/Modal.test.tsx b/__tests__/unit_test/components/modals/Modal.test.tsx index 78389e9..54fc386 100644 --- a/__tests__/unit_test/components/modals/Modal.test.tsx +++ b/__tests__/unit_test/components/modals/Modal.test.tsx @@ -5,14 +5,7 @@ import { act, cleanup, } from '@testing-library/react'; -import { - describe, - it, - expect, - vi, - beforeEach, - afterEach, -} from 'vitest'; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import Modal from '@/app/components/modals/Modal'; import React from 'react'; @@ -57,9 +50,7 @@ describe('', () => { title="Test Modal" /> ); - expect( - screen.getByText('Test Modal') - ).toBeDefined(); + expect(screen.getByText('Test Modal')).toBeDefined(); }); it('calls onClose when close button is clicked', () => { @@ -71,9 +62,7 @@ describe('', () => { actionLabel="Submit" /> ); - const closeButton = screen.getByTestId( - 'close-modal-button' - ); + const closeButton = screen.getByTestId('close-modal-button'); fireEvent.click(closeButton); // Wait for the setTimeout in handleClose @@ -132,9 +121,7 @@ describe('', () => { name: 'Cancel', }); fireEvent.click(cancelButton); - expect(mockSecondaryAction).toHaveBeenCalledTimes( - 1 - ); + expect(mockSecondaryAction).toHaveBeenCalledTimes(1); }); it('disables buttons when disabled prop is true', () => { @@ -169,9 +156,7 @@ describe('', () => { body={
Test Body Content
} /> ); - expect( - screen.getByText('Test Body Content') - ).toBeDefined(); + expect(screen.getByText('Test Body Content')).toBeDefined(); }); it('renders footer content when provided', () => { @@ -184,8 +169,6 @@ describe('', () => { footer={
Test Footer Content
} /> ); - expect( - screen.getByText('Test Footer Content') - ).toBeDefined(); + expect(screen.getByText('Test Footer Content')).toBeDefined(); }); }); diff --git a/__tests__/unit_test/components/modals/RecipeModal.test.tsx b/__tests__/unit_test/components/modals/RecipeModal.test.tsx index 98f5c92..00028cc 100644 --- a/__tests__/unit_test/components/modals/RecipeModal.test.tsx +++ b/__tests__/unit_test/components/modals/RecipeModal.test.tsx @@ -6,14 +6,7 @@ import { cleanup, waitFor, } from '@testing-library/react'; -import { - describe, - it, - expect, - vi, - beforeEach, - afterEach, -} from 'vitest'; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import RecipeModal from '@/app/components/modals/RecipeModal'; import { categories } from '@/app/components/navbar/Categories'; import { preparationMethods } from '@/app/components/modals/RecipeModal'; @@ -57,9 +50,7 @@ describe('', () => { it('renders the modal with initial step (CATEGORY)', () => { renderComponent(); - expect( - screen.getByText('title_category_recipe') - ).toBeDefined(); + expect(screen.getByText('title_category_recipe')).toBeDefined(); }); it('advances to next step (DESCRIPTION) when next button is clicked', async () => { @@ -72,9 +63,7 @@ describe('', () => { act(() => { fireEvent.click(nextButton); }); - expect( - screen.getByText('title_description') - ).toBeDefined(); + expect(screen.getByText('title_description')).toBeDefined(); }, { timeout: 4000 } ); @@ -90,19 +79,10 @@ describe('', () => { act(() => { fireEvent.click(nextButton); }); - expect( - screen.getByText('title_description') - ).toBeDefined(); - const backButton = screen.getByRole( - 'button', - { name: 'back' } - ); + expect(screen.getByText('title_description')).toBeDefined(); + const backButton = screen.getByRole('button', { name: 'back' }); fireEvent.click(backButton); - expect( - screen.getByText( - 'title_category_recipe' - ) - ).toBeDefined(); + expect(screen.getByText('title_category_recipe')).toBeDefined(); }, { timeout: 4000 } ); @@ -112,9 +92,7 @@ describe('', () => { renderComponent(); categories.forEach((category) => { expect( - screen.getByText( - category.label.toLowerCase() - ) + screen.getByText(category.label.toLowerCase()) ).toBeDefined(); }); }); @@ -126,9 +104,7 @@ describe('', () => { firstCategory.label.toLowerCase() ); fireEvent.click(categoryButton); - expect( - categoryButton.parentElement?.className - ).include('selected'); + expect(categoryButton.parentElement?.className).include('selected'); }); it('renders all preparation methods when method step is reached', () => { @@ -149,26 +125,18 @@ describe('', () => { waitFor( () => { act(() => { - fireEvent.click( - nextButton - ); + fireEvent.click(nextButton); }); // Move to STEPS step waitFor( () => { act(() => { - fireEvent.click( - nextButton - ); + fireEvent.click(nextButton); }); // Move to METHODS step - preparationMethods.forEach( - (method) => { - expect( - screen.getByText( - method.label - ) - ).toBeDefined(); - } - ); + preparationMethods.forEach((method) => { + expect( + screen.getByText(method.label) + ).toBeDefined(); + }); }, { timeout: 4000 } ); @@ -202,29 +170,20 @@ describe('', () => { waitFor( () => { act(() => { - fireEvent.click( - nextButton - ); + fireEvent.click(nextButton); }); // Move to STEPS step waitFor( () => { act(() => { - fireEvent.click( - nextButton - ); + fireEvent.click(nextButton); }); // Move to METHODS step const firstMethod = preparationMethods[0]; - const methodButton = - screen.getByText( - firstMethod.label - ); - fireEvent.click( - methodButton + const methodButton = screen.getByText( + firstMethod.label ); - expect( - methodButton - ).toHaveProperty( + fireEvent.click(methodButton); + expect(methodButton).toHaveProperty( 'selected' ); }, @@ -256,17 +215,13 @@ describe('', () => { act(() => { fireEvent.click(nextButton); }); // Move to INGREDIENTS step - const addButton = screen.getByRole( - 'button', - { name: '+' } - ); + const addButton = screen.getByRole('button', { + name: '+', + }); fireEvent.click(addButton); - const ingredientInputs = - screen.getAllByLabelText(''); - expect( - ingredientInputs.length - ).toBe(2); + const ingredientInputs = screen.getAllByLabelText(''); + expect(ingredientInputs.length).toBe(2); }, { timeout: 4000 } ); @@ -290,22 +245,17 @@ describe('', () => { act(() => { fireEvent.click(nextButton); }); // Move to INGREDIENTS step - const addButton = screen.getByRole( - 'button', - { name: '+' } - ); + const addButton = screen.getByRole('button', { + name: '+', + }); fireEvent.click(addButton); - const deleteButton = - screen.getAllByTestId( - 'remove-ingredient-button' - )[0]; + const deleteButton = screen.getAllByTestId( + 'remove-ingredient-button' + )[0]; fireEvent.click(deleteButton); - const ingredientInputs = - screen.getAllByLabelText(''); - expect( - ingredientInputs.length - ).toBe(1); + const ingredientInputs = screen.getAllByLabelText(''); + expect(ingredientInputs.length).toBe(1); }, { timeout: 4000 } ); @@ -333,24 +283,15 @@ describe('', () => { waitFor( () => { act(() => { - fireEvent.click( - nextButton - ); + fireEvent.click(nextButton); }); // Move to STEPS step - const addButton = - screen.getByRole( - 'button', - { name: '+' } - ); + const addButton = screen.getByRole('button', { + name: '+', + }); fireEvent.click(addButton); - const stepInputs = - screen.getAllByLabelText( - '' - ); - expect( - stepInputs.length - ).toBe(2); + const stepInputs = screen.getAllByLabelText(''); + expect(stepInputs.length).toBe(2); }, { timeout: 4000 } ); @@ -381,31 +322,20 @@ describe('', () => { waitFor( () => { act(() => { - fireEvent.click( - nextButton - ); + fireEvent.click(nextButton); }); // Move to STEPS step - const addButton = - screen.getByRole( - 'button', - { name: '+' } - ); + const addButton = screen.getByRole('button', { + name: '+', + }); fireEvent.click(addButton); const deleteButton = screen.getAllByTestId( 'remove-step-button' )[0]; - fireEvent.click( - deleteButton - ); + fireEvent.click(deleteButton); - const stepInputs = - screen.getAllByLabelText( - '' - ); - expect( - stepInputs.length - ).toBe(1); + const stepInputs = screen.getAllByLabelText(''); + expect(stepInputs.length).toBe(1); }, { timeout: 4000 } ); @@ -435,34 +365,23 @@ describe('', () => { waitFor( () => { act(() => { - fireEvent.click( - nextButton - ); + fireEvent.click(nextButton); }); // Move to STEPS step waitFor( () => { act(() => { - fireEvent.click( - nextButton - ); + fireEvent.click(nextButton); }); // Move to METHODS step waitFor( () => { act(() => { - fireEvent.click( - nextButton - ); + fireEvent.click(nextButton); }); // Move to IMAGES step const submitButton = - screen.getByRole( - 'button', - { - name: 'create', - } - ); - fireEvent.click( - submitButton - ); + screen.getByRole('button', { + name: 'create', + }); + fireEvent.click(submitButton); expect( screen.getByText( 'You must upload an image' diff --git a/__tests__/unit_test/components/modals/RegisterModal.test.tsx b/__tests__/unit_test/components/modals/RegisterModal.test.tsx index 3d7b714..5bcebc7 100644 --- a/__tests__/unit_test/components/modals/RegisterModal.test.tsx +++ b/__tests__/unit_test/components/modals/RegisterModal.test.tsx @@ -6,14 +6,7 @@ import { waitFor, cleanup, } from '@testing-library/react'; -import { - vi, - describe, - it, - expect, - beforeEach, - afterEach, -} from 'vitest'; +import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest'; import RegisterModal from '@/app/components/modals/RegisterModal'; import { signIn } from 'next-auth/react'; import axios from 'axios'; @@ -71,18 +64,10 @@ describe('RegisterModal', () => { it('renders the register modal', () => { render(); - expect( - screen.getByText('welcome_jorbites') - ).toBeDefined(); - expect( - screen.getByRole('textbox', { name: /email/i }) - ).toBeDefined(); - expect( - screen.getByRole('textbox', { name: /name/i }) - ).toBeDefined(); - expect( - screen.getByLabelText(/password/i) - ).toBeDefined(); + expect(screen.getByText('welcome_jorbites')).toBeDefined(); + expect(screen.getByRole('textbox', { name: /email/i })).toBeDefined(); + expect(screen.getByRole('textbox', { name: /name/i })).toBeDefined(); + expect(screen.getByLabelText(/password/i)).toBeDefined(); expect( screen.getByRole('button', { name: /login_google/i, @@ -106,35 +91,25 @@ describe('RegisterModal', () => { fireEvent.change(screen.getByLabelText('name'), { target: { value: 'testuser' }, }); - fireEvent.change( - screen.getByLabelText('password'), - { target: { value: 'password123' } } - ); + fireEvent.change(screen.getByLabelText('password'), { + target: { value: 'password123' }, + }); fireEvent.click(screen.getByText('continue')); await waitFor(() => { - expect(axios.post).toHaveBeenCalledWith( - '/api/register', - { - email: 'test@example.com', - name: 'testuser', - password: 'password123', - } - ); - expect(toast.success).toHaveBeenCalledWith( - 'Registered!' - ); - expect( - mockRegisterModalClose - ).toHaveBeenCalled(); + expect(axios.post).toHaveBeenCalledWith('/api/register', { + email: 'test@example.com', + name: 'testuser', + password: 'password123', + }); + expect(toast.success).toHaveBeenCalledWith('Registered!'); + expect(mockRegisterModalClose).toHaveBeenCalled(); }); }); it('displays error toast on failed registration', async () => { - (axios.post as any).mockRejectedValue( - 'Registration error' - ); + (axios.post as any).mockRejectedValue('Registration error'); render(); @@ -144,17 +119,14 @@ describe('RegisterModal', () => { fireEvent.change(screen.getByLabelText('name'), { target: { value: 'testuser' }, }); - fireEvent.change( - screen.getByLabelText('password'), - { target: { value: 'password123' } } - ); + fireEvent.change(screen.getByLabelText('password'), { + target: { value: 'password123' }, + }); fireEvent.click(screen.getByText('continue')); await waitFor(() => { - expect(toast.error).toHaveBeenCalledWith( - 'Registration error' - ); + expect(toast.error).toHaveBeenCalledWith('Registration error'); }); }); @@ -180,9 +152,7 @@ describe('RegisterModal', () => { fireEvent.click(screen.getByText('login')); await waitFor(() => { - expect( - mockRegisterModalClose - ).toHaveBeenCalled(); + expect(mockRegisterModalClose).toHaveBeenCalled(); expect(mockLoginModalOpen).toHaveBeenCalled(); }); }); diff --git a/__tests__/unit_test/components/modals/SettingsModal.test.tsx b/__tests__/unit_test/components/modals/SettingsModal.test.tsx index 50209f2..3fdfac6 100644 --- a/__tests__/unit_test/components/modals/SettingsModal.test.tsx +++ b/__tests__/unit_test/components/modals/SettingsModal.test.tsx @@ -1,17 +1,6 @@ import React from 'react'; -import { - render, - screen, - cleanup, -} from '@testing-library/react'; -import { - vi, - describe, - it, - expect, - beforeEach, - afterEach, -} from 'vitest'; +import { render, screen, cleanup } from '@testing-library/react'; +import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest'; import SettingsModal from '@/app/components/modals/SettingsModal'; import useSettingsModal from '@/app/hooks/useSettingsModal'; import { SafeUser } from '@/app/types'; @@ -28,28 +17,17 @@ vi.mock('@/app/components/settings/ThemeSelector', () => ({ default: () =>
ThemeSelector
, })); -vi.mock( - '@/app/components/settings/LanguageSelector', - () => ({ - default: () =>
LanguageSelector
, - }) -); +vi.mock('@/app/components/settings/LanguageSelector', () => ({ + default: () =>
LanguageSelector
, +})); -vi.mock( - '@/app/components/settings/EmailNotificationsSelector', - () => ({ - default: () => ( -
EmailNotificationsSelector
- ), - }) -); +vi.mock('@/app/components/settings/EmailNotificationsSelector', () => ({ + default: () =>
EmailNotificationsSelector
, +})); -vi.mock( - '@/app/components/settings/ChangeUserImage', - () => ({ - default: () =>
ChangeUserImageSelector
, - }) -); +vi.mock('@/app/components/settings/ChangeUserImage', () => ({ + default: () =>
ChangeUserImageSelector
, +})); const mockSettingsModalClose = vi.fn(); @@ -58,9 +36,7 @@ const mockUseSettingsModal = { onClose: mockSettingsModalClose, }; -(useSettingsModal as any).mockReturnValue( - mockUseSettingsModal -); +(useSettingsModal as any).mockReturnValue(mockUseSettingsModal); describe('SettingsModal', () => { beforeEach(() => { @@ -73,15 +49,9 @@ describe('SettingsModal', () => { it('renders the settings modal', () => { render(); - expect( - screen.getByText('set_your_preferences') - ).toBeDefined(); - expect( - screen.getByText('ThemeSelector') - ).toBeDefined(); - expect( - screen.getByText('LanguageSelector') - ).toBeDefined(); + expect(screen.getByText('set_your_preferences')).toBeDefined(); + expect(screen.getByText('ThemeSelector')).toBeDefined(); + expect(screen.getByText('LanguageSelector')).toBeDefined(); }); it('renders user-specific settings when currentUser is provided', () => { @@ -90,11 +60,7 @@ describe('SettingsModal', () => { name: 'Test User', } as SafeUser; render(); - expect( - screen.getByText('EmailNotificationsSelector') - ).toBeDefined(); - expect( - screen.getByText('ChangeUserImageSelector') - ).toBeDefined(); + expect(screen.getByText('EmailNotificationsSelector')).toBeDefined(); + expect(screen.getByText('ChangeUserImageSelector')).toBeDefined(); }); }); diff --git a/__tests__/unit_test/components/navbar/Categories.test.tsx b/__tests__/unit_test/components/navbar/Categories.test.tsx index ac3698c..cd15ded 100644 --- a/__tests__/unit_test/components/navbar/Categories.test.tsx +++ b/__tests__/unit_test/components/navbar/Categories.test.tsx @@ -1,24 +1,8 @@ import React from 'react'; -import { - cleanup, - render, - screen, -} from '@testing-library/react'; -import { - describe, - it, - expect, - vi, - beforeEach, - afterEach, -} from 'vitest'; -import Categories, { - categories, -} from '@/app/components/navbar/Categories'; -import { - usePathname, - useSearchParams, -} from 'next/navigation'; +import { cleanup, render, screen } from '@testing-library/react'; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; +import Categories, { categories } from '@/app/components/navbar/Categories'; +import { usePathname, useSearchParams } from 'next/navigation'; // Mock the next/navigation module vi.mock('next/navigation', () => ({ @@ -28,25 +12,15 @@ vi.mock('next/navigation', () => ({ // Mock the Container component vi.mock('@/app/components/Container', () => ({ - default: ({ - children, - }: { - children: React.ReactNode; - }) =>
{children}
, + default: ({ children }: { children: React.ReactNode }) => ( +
{children}
+ ), })); // Mock the CategoryBox component vi.mock('@/app/components/CategoryBox', () => ({ - default: ({ - label, - selected, - }: { - label: string; - selected: boolean; - }) => ( -
+ default: ({ label, selected }: { label: string; selected: boolean }) => ( +
{label} {selected ? '(selected)' : ''}
), @@ -90,9 +64,7 @@ describe('', () => { `category-box-${category.label.toLowerCase()}` ); expect(categoryBox).toBeDefined(); - expect(categoryBox.textContent?.trim()).toBe( - category.label - ); + expect(categoryBox.textContent?.trim()).toBe(category.label); }); }); @@ -104,11 +76,7 @@ describe('', () => { render(); - const selectedCategory = screen.getByTestId( - 'category-box-fruits' - ); - expect(selectedCategory.textContent).toBe( - 'Fruits (selected)' - ); + const selectedCategory = screen.getByTestId('category-box-fruits'); + expect(selectedCategory.textContent).toBe('Fruits (selected)'); }); }); diff --git a/__tests__/unit_test/components/navbar/Logo.test.tsx b/__tests__/unit_test/components/navbar/Logo.test.tsx index 69291cc..5eea3c3 100644 --- a/__tests__/unit_test/components/navbar/Logo.test.tsx +++ b/__tests__/unit_test/components/navbar/Logo.test.tsx @@ -1,18 +1,6 @@ import React from 'react'; -import { - render, - screen, - fireEvent, - cleanup, -} from '@testing-library/react'; -import { - describe, - it, - expect, - vi, - beforeEach, - afterEach, -} from 'vitest'; +import { render, screen, fireEvent, cleanup } from '@testing-library/react'; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import Logo from '@/app/components/navbar/Logo'; import { useRouter } from 'next/navigation'; @@ -58,25 +46,17 @@ describe('', () => { it('renders the logo with default light theme', () => { render(); - const logo = screen.getByAltText( - 'Logo' - ) as HTMLImageElement; + const logo = screen.getByAltText('Logo') as HTMLImageElement; expect(logo).toBeDefined(); expect(logo.src).toContain('/images/logo-nobg.png'); }); it('renders the logo with dark theme', () => { - vi.mocked(localStorage.getItem).mockReturnValue( - 'dark' - ); + vi.mocked(localStorage.getItem).mockReturnValue('dark'); render(); - const logo = screen.getByAltText( - 'Logo' - ) as HTMLImageElement; + const logo = screen.getByAltText('Logo') as HTMLImageElement; expect(logo).toBeDefined(); - expect(logo.src).toContain( - '/images/no_bg_white.png' - ); + expect(logo.src).toContain('/images/no_bg_white.png'); }); it('navigates to home page when clicked', () => { diff --git a/__tests__/unit_test/components/navbar/MenuItem.test.tsx b/__tests__/unit_test/components/navbar/MenuItem.test.tsx index 8a1f7ad..5584b85 100644 --- a/__tests__/unit_test/components/navbar/MenuItem.test.tsx +++ b/__tests__/unit_test/components/navbar/MenuItem.test.tsx @@ -1,17 +1,6 @@ import React from 'react'; -import { - render, - screen, - fireEvent, - cleanup, -} from '@testing-library/react'; -import { - describe, - it, - expect, - vi, - afterEach, -} from 'vitest'; +import { render, screen, fireEvent, cleanup } from '@testing-library/react'; +import { describe, it, expect, vi, afterEach } from 'vitest'; import MenuItem from '@/app/components/navbar/MenuItem'; describe('', () => { @@ -33,9 +22,7 @@ describe('', () => { render(); const menuItem = screen.getByText('Test Item'); fireEvent.click(menuItem); - expect(defaultProps.onClick).toHaveBeenCalledTimes( - 1 - ); + expect(defaultProps.onClick).toHaveBeenCalledTimes(1); }); it('has the correct CSS classes', () => { @@ -45,12 +32,8 @@ describe('', () => { expect(menuItem.className).contain('py-3'); expect(menuItem.className).contain('font-semibold'); expect(menuItem.className).contain('transition'); - expect(menuItem.className).contain( - 'hover:bg-neutral-100' - ); - expect(menuItem.className).contain( - 'hover:text-black' - ); + expect(menuItem.className).contain('hover:bg-neutral-100'); + expect(menuItem.className).contain('hover:text-black'); }); it('applies custom label', () => { diff --git a/__tests__/unit_test/components/navbar/Navbar.test.tsx b/__tests__/unit_test/components/navbar/Navbar.test.tsx index 5456211..9161a1d 100644 --- a/__tests__/unit_test/components/navbar/Navbar.test.tsx +++ b/__tests__/unit_test/components/navbar/Navbar.test.tsx @@ -1,34 +1,18 @@ import React from 'react'; -import { - render, - screen, - fireEvent, - cleanup, -} from '@testing-library/react'; -import { - describe, - it, - expect, - vi, - beforeEach, - afterEach, -} from 'vitest'; +import { render, screen, fireEvent, cleanup } from '@testing-library/react'; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import Navbar from '@/app/components/navbar/Navbar'; import { SafeUser } from '@/app/types'; // Mock the components used in Navbar vi.mock('@/app/components/Container', () => ({ - default: ({ - children, - }: { - children: React.ReactNode; - }) =>
{children}
, + default: ({ children }: { children: React.ReactNode }) => ( +
{children}
+ ), })); vi.mock('@/app/components/navbar/Categories', () => ({ - default: () => ( -
Categories
- ), + default: () =>
Categories
, })); vi.mock('@/app/components/navbar/Search', () => ({ @@ -45,8 +29,7 @@ vi.mock('@/app/components/navbar/Search', () => ({ vi.mock('@/app/components/navbar/UserMenu', () => ({ default: ({ currentUser }: { currentUser?: any }) => (
- UserMenu:{' '} - {currentUser ? 'Logged In' : 'Not Logged In'} + UserMenu: {currentUser ? 'Logged In' : 'Not Logged In'}
), })); @@ -66,24 +49,18 @@ describe('', () => { it('renders without crashing', () => { render(); - expect( - screen.getByTestId('container') - ).toBeDefined(); + expect(screen.getByTestId('container')).toBeDefined(); }); it('renders Search and UserMenu components', () => { render(); expect(screen.getByTestId('search')).toBeDefined(); - expect( - screen.getByTestId('user-menu') - ).toBeDefined(); + expect(screen.getByTestId('user-menu')).toBeDefined(); }); it('does not render Categories by default', () => { render(); - expect( - screen.queryByTestId('categories') - ).toBeNull(); + expect(screen.queryByTestId('categories')).toBeNull(); }); it('toggles Categories when Search is clicked', () => { @@ -91,14 +68,10 @@ describe('', () => { const search = screen.getByTestId('search'); fireEvent.click(search); - expect( - screen.getByTestId('categories') - ).toBeDefined(); + expect(screen.getByTestId('categories')).toBeDefined(); fireEvent.click(search); - expect( - screen.queryByTestId('categories') - ).toBeNull(); + expect(screen.queryByTestId('categories')).toBeNull(); }); it('passes currentUser to UserMenu', () => { @@ -117,23 +90,18 @@ describe('', () => { verified: false, }; render(); - expect( - screen.getByText('UserMenu: Logged In') - ).toBeDefined(); + expect(screen.getByText('UserMenu: Logged In')).toBeDefined(); }); it('shows UserMenu as not logged in when no user is provided', () => { render(); - expect( - screen.getByText('UserMenu: Not Logged In') - ).toBeDefined(); + expect(screen.getByText('UserMenu: Not Logged In')).toBeDefined(); }); it('applies correct CSS classes', () => { render(); const navbar = - screen.getByTestId('container').parentElement - ?.parentElement; + screen.getByTestId('container').parentElement?.parentElement; expect(navbar?.className).include('fixed'); expect(navbar?.className).include('z-10'); expect(navbar?.className).include('w-full'); diff --git a/__tests__/unit_test/components/navbar/Search.test.tsx b/__tests__/unit_test/components/navbar/Search.test.tsx index 7250f77..fc5c9e6 100644 --- a/__tests__/unit_test/components/navbar/Search.test.tsx +++ b/__tests__/unit_test/components/navbar/Search.test.tsx @@ -1,16 +1,5 @@ -import { - render, - screen, - fireEvent, - cleanup, -} from '@testing-library/react'; -import { - describe, - it, - expect, - vi, - afterEach, -} from 'vitest'; +import { render, screen, fireEvent, cleanup } from '@testing-library/react'; +import { describe, it, expect, vi, afterEach } from 'vitest'; import Search from '@/app/components/navbar/Search'; import React from 'react'; @@ -21,11 +10,7 @@ vi.mock('@/app/components/navbar/Logo', () => ({ // Mock the BiSearch icon vi.mock('react-icons/bi', () => ({ - BiSearch: () => ( -
- Search Icon -
- ), + BiSearch: () =>
Search Icon
, })); describe('', () => { @@ -35,25 +20,19 @@ describe('', () => { it('renders the Logo component', () => { render( {}} />); - expect( - screen.getByTestId('mock-logo') - ).toBeDefined(); + expect(screen.getByTestId('mock-logo')).toBeDefined(); }); it('renders the search icon', () => { render( {}} />); - expect( - screen.getByTestId('mock-search-icon') - ).toBeDefined(); + expect(screen.getByTestId('mock-search-icon')).toBeDefined(); }); it('calls onClick handler when search icon is clicked', () => { const handleClick = vi.fn(); render(); - const searchIcon = screen.getByTestId( - 'mock-search-icon' - ).parentElement; + const searchIcon = screen.getByTestId('mock-search-icon').parentElement; fireEvent.click(searchIcon!); expect(handleClick).toHaveBeenCalledTimes(1); @@ -62,38 +41,17 @@ describe('', () => { it('has the correct CSS classes for the search icon container', () => { render( {}} />); - const searchIconContainer = screen.getByTestId( - 'mock-search-icon' - ).parentElement; - expect(searchIconContainer?.className).contain( - 'max-w-[35px]' - ); - expect(searchIconContainer?.className).contain( - 'cursor-pointer' - ); - expect(searchIconContainer?.className).contain( - 'rounded-full' - ); - expect(searchIconContainer?.className).contain( - 'bg-green-450' - ); - expect(searchIconContainer?.className).contain( - 'p-2' - ); - expect(searchIconContainer?.className).contain( - 'text-white' - ); - expect(searchIconContainer?.className).contain( - 'shadow-sm' - ); - expect(searchIconContainer?.className).contain( - 'transition' - ); - expect(searchIconContainer?.className).contain( - 'hover:shadow-md' - ); - expect(searchIconContainer?.className).contain( - 'dark:text-dark' - ); + const searchIconContainer = + screen.getByTestId('mock-search-icon').parentElement; + expect(searchIconContainer?.className).contain('max-w-[35px]'); + expect(searchIconContainer?.className).contain('cursor-pointer'); + expect(searchIconContainer?.className).contain('rounded-full'); + expect(searchIconContainer?.className).contain('bg-green-450'); + expect(searchIconContainer?.className).contain('p-2'); + expect(searchIconContainer?.className).contain('text-white'); + expect(searchIconContainer?.className).contain('shadow-sm'); + expect(searchIconContainer?.className).contain('transition'); + expect(searchIconContainer?.className).contain('hover:shadow-md'); + expect(searchIconContainer?.className).contain('dark:text-dark'); }); }); diff --git a/__tests__/unit_test/components/navbar/UserMenu.test.tsx b/__tests__/unit_test/components/navbar/UserMenu.test.tsx index fd695fe..5c43e1c 100644 --- a/__tests__/unit_test/components/navbar/UserMenu.test.tsx +++ b/__tests__/unit_test/components/navbar/UserMenu.test.tsx @@ -1,17 +1,5 @@ -import { - render, - screen, - fireEvent, - cleanup, -} from '@testing-library/react'; -import { - describe, - it, - expect, - vi, - beforeEach, - afterEach, -} from 'vitest'; +import { render, screen, fireEvent, cleanup } from '@testing-library/react'; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import UserMenu from '@/app/components/navbar/UserMenu'; import React from 'react'; import { SafeUser } from '@/app/types'; @@ -51,9 +39,7 @@ vi.mock('react-i18next', () => ({ })); vi.mock('@/app/components/Avatar', () => ({ - default: () => ( -
Avatar
- ), + default: () =>
Avatar
, })); describe('', () => { @@ -82,25 +68,15 @@ describe('', () => { it('renders the post recipe button and avatar when user is logged in', () => { render(); - expect( - screen.getByText('post_recipe') - ).toBeDefined(); - expect( - screen.getByTestId('mock-avatar') - ).toBeDefined(); + expect(screen.getByText('post_recipe')).toBeDefined(); + expect(screen.getByTestId('mock-avatar')).toBeDefined(); }); it('opens the menu when avatar is clicked', () => { render(); - fireEvent.click( - screen.getByTestId('mock-avatar').parentElement! - ); - expect( - screen.getByText('my_profile') - ).toBeDefined(); - expect( - screen.getByText('my_favorites') - ).toBeDefined(); + fireEvent.click(screen.getByTestId('mock-avatar').parentElement!); + expect(screen.getByText('my_profile')).toBeDefined(); + expect(screen.getByText('my_favorites')).toBeDefined(); expect(screen.getByText('settings')).toBeDefined(); expect(screen.getByText('logout')).toBeDefined(); }); @@ -119,18 +95,14 @@ describe('', () => { it('renders login and signup options when user is not logged in', () => { render(); - fireEvent.click( - screen.getByTestId('mock-avatar').parentElement! - ); + fireEvent.click(screen.getByTestId('mock-avatar').parentElement!); expect(screen.getByText('login')).toBeDefined(); expect(screen.getByText('sign_up')).toBeDefined(); }); it('calls signOut when logout is clicked', () => { render(); - fireEvent.click( - screen.getByTestId('mock-avatar').parentElement! - ); + fireEvent.click(screen.getByTestId('mock-avatar').parentElement!); fireEvent.click(screen.getByText('logout')); expect(mockSignOut).toHaveBeenCalled(); }); diff --git a/__tests__/unit_test/components/recipes/DeleteRecipeModal.test.tsx b/__tests__/unit_test/components/recipes/DeleteRecipeModal.test.tsx index 0af73d9..0c7c02b 100644 --- a/__tests__/unit_test/components/recipes/DeleteRecipeModal.test.tsx +++ b/__tests__/unit_test/components/recipes/DeleteRecipeModal.test.tsx @@ -1,18 +1,6 @@ import React from 'react'; -import { - render, - screen, - fireEvent, - cleanup, -} from '@testing-library/react'; -import { - describe, - it, - expect, - vi, - beforeEach, - afterEach, -} from 'vitest'; +import { render, screen, fireEvent, cleanup } from '@testing-library/react'; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import DeleteRecipeButton from '@/app/components/recipes/DeleteRecipeButton'; // Mock the react-i18next module @@ -23,38 +11,25 @@ vi.mock('react-i18next', () => ({ })); // Mock the DeleteRecipeModal component -vi.mock( - '@/app/components/modals/DeleteRecipeModal', - () => ({ - default: ({ - open, - setIsOpen, - id, - }: { - open: boolean; - setIsOpen: (open: boolean) => void; - id: string; - }) => ( -
- {open && ( -
- Delete Recipe Modal for ID: {id} -
- )} -
- ), - }) -); - -// Mock the Button component -vi.mock('@/app/components/Button', () => ({ +vi.mock('@/app/components/modals/DeleteRecipeModal', () => ({ default: ({ - label, - onClick, + open, + setIsOpen, + id, }: { - label: string; - onClick: () => void; + open: boolean; + setIsOpen: (open: boolean) => void; + id: string; }) => ( +
+ {open &&
Delete Recipe Modal for ID: {id}
} +
+ ), +})); + +// Mock the Button component +vi.mock('@/app/components/Button', () => ({ + default: ({ label, onClick }: { label: string; onClick: () => void }) => (