From 9057e0601ed1887b703ed53f2dd8e55258103f09 Mon Sep 17 00:00:00 2001 From: Amir Ali Date: Fri, 30 May 2025 13:14:54 +0330 Subject: [PATCH 1/7] chore: update tsconfig.json to include path mapping for aliases --- tsconfig.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index 847a630..ffddf3a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,7 +23,10 @@ { "name": "next" } - ] + ], + "paths": { + "@/*": ["./*"] + } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.mjs", "jest.config.js", ".next/types/**/*.ts", "eslint.config.mjs"], "exclude": ["node_modules"] From 6f765521e6e876df9826ed77888e2390e9c2e3ed Mon Sep 17 00:00:00 2001 From: Amir Ali Date: Fri, 30 May 2025 13:15:11 +0330 Subject: [PATCH 2/7] chore: add test watch and coverage scripts to package.json --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index 6539722..0c0179e 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,8 @@ "test-storybook": "cross-env FORCE_COLOR=1 test-storybook", "build-storybook": "cross-env FORCE_COLOR=1 storybook build", "test": "cross-env FORCE_COLOR=1 jest --passWithNoTests", + "test:watch": "cross-env FORCE_COLOR=1 jest --watch", + "test:coverage": "cross-env FORCE_COLOR=1 jest --coverage", "e2e:headless": "playwright test", "e2e:ui": "playwright test --ui", "format": "prettier --write \"**/*.{ts,tsx,md}\"", From c8d0f30e798bd76bb8a2e03212abca94f19ed835 Mon Sep 17 00:00:00 2001 From: Amir Ali Date: Fri, 30 May 2025 13:16:23 +0330 Subject: [PATCH 3/7] test: add mock for ResizeObserver to support unit tests --- jest.setup.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/jest.setup.js b/jest.setup.js index 401f198..9597f0e 100644 --- a/jest.setup.js +++ b/jest.setup.js @@ -1,2 +1,10 @@ // Learn more: https://github.com/testing-library/jest-dom import "@testing-library/jest-dom" + +class ResizeObserverMock { + observe() {} + unobserve() {} + disconnect() {} +} + +global.ResizeObserver = ResizeObserverMock; \ No newline at end of file From ab141acce6eeeb5330d1cf4c3a9a6feac29d7f9f Mon Sep 17 00:00:00 2001 From: Amir Ali Date: Fri, 30 May 2025 13:17:04 +0330 Subject: [PATCH 4/7] test: add unit tests for Button component --- __tests__/components/button.spec.tsx | 58 ++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 __tests__/components/button.spec.tsx diff --git a/__tests__/components/button.spec.tsx b/__tests__/components/button.spec.tsx new file mode 100644 index 0000000..257a8e3 --- /dev/null +++ b/__tests__/components/button.spec.tsx @@ -0,0 +1,58 @@ +import { render, screen } from "@testing-library/react" + +import { Button } from "@/components/Button/Button" + +describe("Button component", () => { + it("renders with default intent and size", () => { + render() + const btn = screen.getByRole("link", { name: /default button/i }) + expect(btn).toBeInTheDocument() + expect(btn).toHaveClass("bg-blue-400") + expect(btn).toHaveClass("text-lg") + }) + + it("renders secondary intent correctly", () => { + render() + const btn = screen.getByRole("link", { name: /secondary button/i }) + expect(btn).toHaveClass("bg-transparent") + expect(btn).toHaveClass("text-blue-400") + }) + + it("renders small size correctly", () => { + render() + const btn = screen.getByRole("link", { name: /small button/i }) + expect(btn).toHaveClass("text-sm") + expect(btn).toHaveClass("min-w-20") + }) + + it("applies underline when underline prop is true", () => { + render() + const btn = screen.getByRole("link", { name: /underlined button/i }) + expect(btn).toHaveClass("underline") + }) + + it("does not apply underline class when underline prop is false or omitted", () => { + render() + const btn = screen.getByRole("link", { name: /no underline/i }) + expect(btn).not.toHaveClass("underline") + }) + + it("merges custom className with variant classes", () => { + render() + const btn = screen.getByRole("link", { name: /custom class button/i }) + expect(btn).toHaveClass("custom-class") + expect(btn).toHaveClass("bg-blue-400") + }) + + it("forwards href and other props correctly", () => { + render() + const btn = screen.getByRole("link", { name: /link button/i }) + expect(btn).toHaveAttribute("href", "/test") + expect(btn).toHaveAttribute("rel", "noopener noreferrer") + }) + + it("renders children inside the anchor tag", () => { + render() + expect(screen.getByText("Click Me")).toBeInTheDocument() + }) +}) From 332cdc573f4ec6d759d98ba53ae1b9de4e408beb Mon Sep 17 00:00:00 2001 From: Amir Ali Date: Fri, 30 May 2025 13:17:11 +0330 Subject: [PATCH 5/7] test: add unit tests for Tooltip component --- __tests__/components/tooltip.spec.tsx | 65 +++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 __tests__/components/tooltip.spec.tsx diff --git a/__tests__/components/tooltip.spec.tsx b/__tests__/components/tooltip.spec.tsx new file mode 100644 index 0000000..e74c9db --- /dev/null +++ b/__tests__/components/tooltip.spec.tsx @@ -0,0 +1,65 @@ +import { fireEvent, render, screen, waitFor } from "@testing-library/react" + +import { Tooltip } from "@/components/Tooltip/Tooltip" + +describe("Tooltip", () => { + it("should render tooltip content when open is true", () => { + render( + +
Hover me
+
+ ) + + expect(screen.getByText("Hover me")).toBeInTheDocument() + + const tooltipContent = document.querySelector('[data-radix-popper-content-wrapper]') + expect(tooltipContent).toBeInTheDocument() + expect(tooltipContent).toHaveTextContent("Click me") + }) + + it("should not render tooltip content when open is false or undefined", () => { + render( + +
Hover me
+
+ ) + + expect(screen.getByText("Hover me")).toBeInTheDocument() + const tooltipContent = document.querySelector('[data-radix-popper-content-wrapper]') + expect(tooltipContent).not.toBeInTheDocument() + }) + + it("calls onOpenChange when tooltip open state changes", async () => { + const handleOpenChange = jest.fn() + + render( + + + + ) + + expect(screen.queryByText("Controlled")).not.toBeInTheDocument() + + fireEvent.mouseOver(screen.getByText("Hover me")) + + expect(screen.queryByText("Controlled")).not.toBeInTheDocument() + + handleOpenChange(true) + + expect(handleOpenChange).toHaveBeenCalledWith(true) + }) + + it("renders arrow when withArrow is true", () => { + const { container } = render( + + + + ) + + console.log(container.innerHTML) + + const arrow = document.querySelector('svg') + expect(arrow).toBeInTheDocument() + }) + +}) From 6957f30817251bcca10800ab410a1fc28bd94cf6 Mon Sep 17 00:00:00 2001 From: Amir Ali Date: Fri, 30 May 2025 13:17:17 +0330 Subject: [PATCH 6/7] test: add unit tests for Home component --- __tests__/pages/home.spec.tsx | 64 +++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 __tests__/pages/home.spec.tsx diff --git a/__tests__/pages/home.spec.tsx b/__tests__/pages/home.spec.tsx new file mode 100644 index 0000000..b215861 --- /dev/null +++ b/__tests__/pages/home.spec.tsx @@ -0,0 +1,64 @@ +import { render, screen } from "@testing-library/react" + +import Home, { metadata } from "@/app/page" +import { LP_GRID_ITEMS } from "lp-items" + +describe("Home", () => { + beforeEach(() => { + render() + }) + + it("renders the main heading", () => { + expect(screen.getByText("Next.js Enterprise Boilerplate")).toBeInTheDocument() + }) + + it("renders the description paragraph", () => { + expect(screen.getByText(/Jumpstart your enterprise project/)).toBeInTheDocument() + }) + + it("renders both buttons with correct text and links", () => { + const getStartedButton = screen.getByText("Get started") + const deployNowButton = screen.getByText("Deploy Now") + + expect(getStartedButton).toBeInTheDocument() + expect(deployNowButton).toBeInTheDocument() + expect(getStartedButton.closest('a')).toHaveAttribute('href', 'https://github.com/Blazity/next-enterprise') + expect(deployNowButton.closest('a')).toHaveAttribute('href', 'https://vercel.com/new/git/external?repository-url=https://github.com/Blazity/next-enterprise') + }) + + it("renders all grid items with their content", () => { + LP_GRID_ITEMS.forEach((item) => { + expect(screen.getByText(item.title)).toBeInTheDocument() + expect(screen.getByText(item.description)).toBeInTheDocument() + }) + }) + + it("renders grid items in the correct structure", () => { + const gridItems = screen.getAllByRole('heading', { level: 3 }) + expect(gridItems).toHaveLength(LP_GRID_ITEMS.length) + + gridItems.forEach((item) => { + const parent = item.closest('div') + expect(parent).toHaveClass('flex', 'flex-col', 'items-center', 'justify-center', 'text-center') + }) + }) + + it("has correct metadata configuration", () => { + expect(metadata).toEqual({ + title: "Next.js Enterprise Boilerplate", + twitter: { + card: "summary_large_image", + }, + openGraph: { + url: "https://next-enterprise.vercel.app/", + images: [ + { + width: 1200, + height: 630, + url: "https://raw.githubusercontent.com/Blazity/next-enterprise/main/.github/assets/project-logo.png", + }, + ], + }, + }) + }) +}) \ No newline at end of file From 6965ffb8920f3539d9607b507f7da41fadd146f6 Mon Sep 17 00:00:00 2001 From: Amir Ali Date: Fri, 30 May 2025 13:17:26 +0330 Subject: [PATCH 7/7] fix: update import path for Tailwind CSS in layout.tsx --- app/layout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/layout.tsx b/app/layout.tsx index a872374..0650f20 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,4 +1,4 @@ -import "styles/tailwind.css" +import "@/styles/tailwind.css" export default function RootLayout({ children }: { children: React.ReactNode }) { return (