diff --git a/jest.config.ts b/jest.config.ts index a68f0ee..1eb1cbf 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -5,6 +5,7 @@ import type { Config } from "jest" import nextJest from "next/jest.js" +// import "@testing-library/jest-dom" const createJestConfig = nextJest({ // Provide the path to your Next.js app to load next.config.js and .env files in your test environment diff --git a/package-lock.json b/package-lock.json index 550f923..10516a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11405,9 +11405,9 @@ } }, "node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", + "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index ac303b4..6264a93 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "start": "next start", "lint": "next lint", "test": "jest test", + "test:watch": "jest --watch", "e2e_test": "npx playwright test", "e2e_report": "npx playwright show-report", "e2e_ui": "npx playwright test --ui" diff --git a/src/__tests__/component/books/library/BookLibrary.test.tsx b/src/__tests__/component/books/library/BookLibrary.test.tsx new file mode 100644 index 0000000..06b779d --- /dev/null +++ b/src/__tests__/component/books/library/BookLibrary.test.tsx @@ -0,0 +1,50 @@ +import BookLibrary from "@/components/books/library/BookLibrary" +import { useGetQuery } from "@/hooks/fetch-hooks/useGetQuery" +import { Genre } from "@/types/Genre" +import { render } from "@testing-library/react" +import "@testing-library/jest-dom" + +jest.mock("@/hooks/fetch-hooks/useGetQuery") + +const mockUseGetQuery = jest.mocked(useGetQuery) + +describe("tests the book library page", () => { + beforeEach(() => { + jest.clearAllMocks() + }) + + test("renders book data successfully", () => { + const mockBookData = [ + { + author: "testAuthor", + genre: [Genre.ACTION], + pages: 500, + title: "test", + yearPublished: 1900, + _id: "dfgdfgfd", + read: true, + }, + { + author: "testAuthor2", + genre: [Genre.ACTION], + pages: 500, + title: "test2", + yearPublished: 1900, + _id: "dfgdfgfd222", + read: true, + }, + ] + + mockUseGetQuery.mockReturnValue({ + data: mockBookData, + isLoading: false, + isError: false, + error: null, + }) + + const { getByRole } = render() + + expect(getByRole("heading", { name: /^test$/i })).toBeInTheDocument() + expect(getByRole("heading", { name: /^test2$/i })).toBeInTheDocument() + }) +}) diff --git a/src/__tests__/component/books/library/single-book/AdminViewLeftSide.test.tsx b/src/__tests__/component/books/library/single-book/AdminViewLeftSide.test.tsx new file mode 100644 index 0000000..faeae68 --- /dev/null +++ b/src/__tests__/component/books/library/single-book/AdminViewLeftSide.test.tsx @@ -0,0 +1,116 @@ +import AdminViewLeftSide from "@/components/books/library/single-book/AdminViewLeftSide" +import { Genre } from "@/types/Genre" +import { render, fireEvent } from "@testing-library/react" +import StoreProvider from "@/store/StoreProvider" +import { NotificationProvider } from "@/context/NotificationProvider" +import QueryProvider from "@/query/QueryProvider" +import "@testing-library/jest-dom" + +beforeAll(() => { + Object.defineProperty(window, "matchMedia", { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, // Default to desktop/mobile layout state + media: query, + onchange: null, + })), + }) +}) + +describe("Left side of Admin view of Single book component", () => { + test("all book edit and delete buttons render for admin user", () => { + const props = { + bookData: { + author: "testAuthor", + genre: [Genre.ACTION], + pages: 500, + title: "test", + yearPublished: 1900, + _id: "dfgdfgfd", + }, + bookId: "dfgdfgfd", + } + const { getByRole } = render( + + + + + + + , + ) + const deleteBookButton = getByRole("button", { name: /delete book/i }) + const editTitleButton = getByRole("button", { name: /edit title/i }) + const editImageButton = getByRole("button", { name: /change image/i }) + + expect(deleteBookButton).toBeDefined() + expect(editTitleButton).toBeDefined() + expect(editImageButton).toBeDefined() + }) + test("book card renders correct information", () => { + const props = { + bookData: { + author: "testAuthor", + genre: [Genre.ACTION], + pages: 500, + title: "test", + yearPublished: 1900, + dateOfMeeting: "2026-04-11T22:00:00.000Z", + actualDateOfMeeting: "2026-04-11T22:00:00.000Z", + reviewImageURL: "https://res.cloudinary.com", + totalScore: 9.5, + _id: "dfgdfgfd", + }, + bookId: "dfgdfgfd", + } + const { getByText, getByRole } = render( + + + + + + + , + ) + + const cardImg = getByRole("img", { name: /test book cover/i }) + const cardCertImg = getByRole("img", { name: /worm badge certification/i }) + + const cardScore = getByText("9.5/10") + + expect(cardImg).toBeDefined() + expect(cardCertImg).toBeDefined() + expect(cardImg).toHaveAttribute( + "src", + "/_next/image?url=https%3A%2F%2Fres.cloudinary.com&w=1080&q=75", + ) + expect(cardScore).toBeDefined() + }) + test("edit title button when click show book edit input", () => { + const props = { + bookData: { + author: "testAuthor", + genre: [Genre.ACTION], + pages: 500, + title: "test", + yearPublished: 1900, + _id: "dfgdfgfd", + }, + bookId: "dfgdfgfd", + } + const { getByRole } = render( + + + + + + + , + ) + const editTitleButton = getByRole("button", { name: /edit title/i }) + + fireEvent.click(editTitleButton) + expect(getByRole("textbox")).toBeInTheDocument() + expect(getByRole("textbox")).toHaveValue("test") + }) +}) diff --git a/src/__tests__/component/books/library/single-book/AdminViewRightSide.test.tsx b/src/__tests__/component/books/library/single-book/AdminViewRightSide.test.tsx new file mode 100644 index 0000000..2d1b034 --- /dev/null +++ b/src/__tests__/component/books/library/single-book/AdminViewRightSide.test.tsx @@ -0,0 +1,47 @@ +import { Genre } from "@/types/Genre" +import { render } from "@testing-library/react" +import StoreProvider from "@/store/StoreProvider" +import { NotificationProvider } from "@/context/NotificationProvider" +import QueryProvider from "@/query/QueryProvider" +import AdminViewRightSide from "@/components/books/library/single-book/AdminViewRightSide" + +describe("Right side of Admin view of Single book component", () => { + test("all book edit and delete buttons render for admin user", () => { + const props = { + bookData: { + author: "testAuthor", + genre: [Genre.ACTION], + pages: 500, + title: "test", + yearPublished: 1900, + _id: "dfgdfgfd", + }, + bookId: "dfgdfgfd", + } + const { getByRole } = render( + + + + + + + , + ) + + const editBookButton = getByRole("button", { name: /edit author/i }) + const editBookYear = getByRole("button", { name: /edit year/i }) + const editBookPages = getByRole("button", { name: /edit genre/i }) + const editBookGenre = getByRole("button", { name: /edit genre/i }) + const editBookDate = getByRole("button", { name: /edit date/i }) + const editActualBookDate = getByRole("button", { + name: /edit actual date/i, + }) + + expect(editBookButton).toBeDefined() + expect(editBookYear).toBeDefined() + expect(editBookPages).toBeDefined() + expect(editBookGenre).toBeDefined() + expect(editBookDate).toBeDefined() + expect(editActualBookDate).toBeDefined() + }) +}) diff --git a/src/__tests__/component/brothers/library/BrothersLibrary.test.tsx b/src/__tests__/component/brothers/library/BrothersLibrary.test.tsx new file mode 100644 index 0000000..7b6bdb7 --- /dev/null +++ b/src/__tests__/component/brothers/library/BrothersLibrary.test.tsx @@ -0,0 +1,79 @@ +import BrotherLibrary from "@/components/brothers/library/BrothersLibrary" +import { useGetQuery } from "@/hooks/fetch-hooks/useGetQuery" +import { Genre } from "@/types/Genre" +import { render } from "@testing-library/react" +import "@testing-library/jest-dom" +import QueryProvider from "@/query/QueryProvider" +import StoreProvider from "@/store/StoreProvider" +import { NotificationProvider } from "@/context/NotificationProvider" + +jest.mock("@/hooks/fetch-hooks/useGetQuery") + +const mockGetQuery = jest.mocked(useGetQuery) + +describe("mocks the brother library component", () => { + beforeEach(() => jest.clearAllMocks()) + + test("component loads brothers data", () => { + const mockBrotherData = [ + { + userInfo: { + books: { + booksCommented: [""], + booksScored: [""], + comments: [""], + score: [0], + }, + favGenre: [Genre.ACTION], + profileURL: "", + residence: { + country: "", + city: "", + }, + }, + username: "test", + _id: "testid", + lastLoggedIn: "", + }, + { + userInfo: { + books: { + booksCommented: [""], + booksScored: [""], + comments: [""], + score: [0], + }, + favGenre: [Genre.ACTION], + profileURL: "", + residence: { + country: "", + city: "", + }, + }, + username: "test2", + _id: "testid2", + lastLoggedIn: "", + }, + ] + + mockGetQuery.mockReturnValue({ + data: mockBrotherData, + isLoading: false, + isError: false, + error: null, + }) + + const { getByRole } = render( + + + + + + + , + ) + + expect(getByRole("heading", { name: /^test$/i })).toBeInTheDocument() + expect(getByRole("heading", { name: /^test2$/i })).toBeInTheDocument() + }) +}) diff --git a/src/__tests__/unit/find-functions/findBook.test.tsx b/src/__tests__/unit/find-functions/findBook.test.tsx index 248a22f..383c580 100644 --- a/src/__tests__/unit/find-functions/findBook.test.tsx +++ b/src/__tests__/unit/find-functions/findBook.test.tsx @@ -39,7 +39,7 @@ describe("book functions that return a key value given its parameters", () => { const expectedDateOfMeeting = "Thu Nov 17 2025 15:56:20 GMT+0100 (Mitteleuropäische Normalzeit)" expect(findDateOfMeeting(bookTitle, mockBookArray)).toBe( - expectedDateOfMeeting + expectedDateOfMeeting, ) }) })