Skip to content

Commit 403aa63

Browse files
Merge pull request #29 from Eric-Zhang-Developer/test/basic-unit-and-integration-tests
Test/basic unit and integration tests
2 parents b18a1e8 + 0cea689 commit 403aa63

File tree

9 files changed

+3441
-425
lines changed

9 files changed

+3441
-425
lines changed

package-lock.json

Lines changed: 3278 additions & 419 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
"dev": "next dev --turbopack",
77
"build": "next build --turbopack",
88
"start": "next start",
9-
"lint": "eslint"
9+
"lint": "eslint",
10+
"test": "vitest",
11+
"test:watch": "vitest --watch"
1012
},
1113
"dependencies": {
1214
"@supabase/ssr": "^0.7.0",
@@ -21,12 +23,19 @@
2123
"devDependencies": {
2224
"@eslint/eslintrc": "^3",
2325
"@tailwindcss/postcss": "^4.1.14",
26+
"@testing-library/jest-dom": "^6.9.1",
27+
"@testing-library/react": "^16.3.0",
28+
"@testing-library/user-event": "^14.6.1",
2429
"@types/node": "^20",
2530
"@types/react": "^19",
2631
"@types/react-dom": "^19",
32+
"@vitejs/plugin-react": "^5.1.0",
33+
"@vitest/coverage-v8": "^4.0.4",
2734
"eslint": "^9",
2835
"eslint-config-next": "15.5.3",
36+
"jsdom": "^27.0.1",
2937
"tailwindcss": "^4.1.14",
30-
"typescript": "^5"
38+
"typescript": "^5",
39+
"vitest": "^4.0.4"
3140
}
3241
}

postcss.config.mjs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
import tailwindcssPostcss from "@tailwindcss/postcss";
2+
13
const config = {
2-
plugins: ["@tailwindcss/postcss"],
4+
plugins: [tailwindcssPostcss()],
35
};
46

57
export default config;

src/app/__tests__/page.test.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { vi } from "vitest";
2+
import { render, screen } from "@testing-library/react";
3+
import { describe, it, expect } from "vitest";
4+
import LandingPage from "../page";
5+
6+
//mock next/font/google to fix "SyntaxError: [vite] The requested module '/node_modules/next/font/google/index.js' does not provide an export named 'Cinzel'"
7+
vi.mock("next/font/google", () => ({
8+
Cinzel: () => ({
9+
className: "mock-cinzel-font",
10+
style: {},
11+
}),
12+
}));
13+
14+
describe("Landing Page Tests", () => {
15+
it("should render the welcome heading on load", () => {
16+
render(<LandingPage />);
17+
expect(screen.getByText(/Welcome to/i)).toBeInTheDocument();
18+
});
19+
20+
it("should render the Code Quest logo on load", () => {
21+
render(<LandingPage />);
22+
expect(screen.getByAltText("CodeQuest Logo")).toBeInTheDocument();
23+
});
24+
25+
it("should render the start journey button on load", () => {
26+
render(<LandingPage />);
27+
expect(screen.getByRole("link", { name: /Start Your Journey/i })).toBeInTheDocument();
28+
});
29+
});
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { vi } from "vitest";
2+
import { render, screen } from "@testing-library/react";
3+
import { describe, it, expect, beforeEach } from "vitest";
4+
import DashboardPage from "../page";
5+
6+
// Mock next/navigation to prevent redirect calls
7+
vi.mock("next/navigation", () => ({
8+
redirect: vi.fn(),
9+
}));
10+
11+
// Mock Supabase server client to return a fake authenticated user
12+
vi.mock("../../../lib/supabase/server", () => ({
13+
createClient: vi.fn(async () => ({
14+
auth: {
15+
getUser: vi.fn(async () => ({
16+
data: {
17+
user: {
18+
19+
id: "test-user-id",
20+
},
21+
},
22+
})),
23+
signOut: vi.fn(),
24+
},
25+
})),
26+
}));
27+
28+
describe("Dashboard Page Tests", () => {
29+
beforeEach(() => {
30+
vi.clearAllMocks();
31+
});
32+
33+
it("should render the dashboard heading", async () => {
34+
const page = await DashboardPage();
35+
render(page);
36+
expect(screen.getByText("Dashboard")).toBeInTheDocument();
37+
});
38+
39+
it("should display the user email", async () => {
40+
const page = await DashboardPage();
41+
render(page);
42+
expect(screen.getByText("[email protected]")).toBeInTheDocument();
43+
});
44+
45+
it("should render the home link", async () => {
46+
const page = await DashboardPage();
47+
render(page);
48+
expect(screen.getByRole("link", { name: /Go home/i })).toBeInTheDocument();
49+
});
50+
51+
it("should render the logout button", async () => {
52+
const page = await DashboardPage();
53+
render(page);
54+
expect(screen.getByRole("button", { name: /Log out/i })).toBeInTheDocument();
55+
});
56+
57+
it("should render the tutorial link", async () => {
58+
const page = await DashboardPage();
59+
render(page);
60+
expect(screen.getByRole("link", { name: /Hello World Tutorial/i })).toBeInTheDocument();
61+
});
62+
});

src/app/page.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import Link from "next/link";
44
import Image from "next/image";
5-
import "./globals.css";
65
import { Cinzel } from "next/font/google";
76

87
//font for words
@@ -19,7 +18,6 @@ export default function LandingPage() {
1918
bg-[url('/gemininight3.png')] bg-cover bg-center bg-no-repeat text-white overflow-hidden
2019
"
2120
>
22-
2321
{/*welcome text*/}
2422
<div className="relative z-10 max-w-xl text-center">
2523
<h1
@@ -42,7 +40,7 @@ export default function LandingPage() {
4240
drop-shadow(0 0 10px #a5f3fc)
4341
drop-shadow(0 0 20px #93c5fd)
4442
drop-shadow(0 0 30px #60a5fa)
45-
`
43+
`,
4644
}}
4745
/>
4846
</div>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { vi } from "vitest";
2+
import { render, screen } from "@testing-library/react";
3+
import { describe, it, expect } from "vitest";
4+
import TutorialHelloWorld from "../page";
5+
6+
// Mock the BackToDashBoardLink component
7+
vi.mock("@/components/back-to-dashboard-link", () => ({
8+
default: () => <div data-testid="back-to-dashboard-link">Back to Dashboard</div>,
9+
}));
10+
11+
// Mock react-youtube
12+
vi.mock("react-youtube", () => ({
13+
default: ({ videoId }: { videoId: string }) => (
14+
<div data-testid="youtube-player" data-videoid={videoId}>
15+
YouTube Player
16+
</div>
17+
),
18+
}));
19+
20+
describe("Tutorial Hello World Page Tests", () => {
21+
it("should render the main quest heading", () => {
22+
render(<TutorialHelloWorld />);
23+
expect(
24+
screen.getByRole("heading", { name: /Quest: The Oracle's First Greeting/i })
25+
).toBeInTheDocument();
26+
});
27+
28+
it("should render the back to dashboard link", () => {
29+
render(<TutorialHelloWorld />);
30+
expect(screen.getByTestId("back-to-dashboard-link")).toBeInTheDocument();
31+
});
32+
33+
it("should render the YouTube video component", () => {
34+
render(<TutorialHelloWorld />);
35+
const youtubePlayer = screen.getByTestId("youtube-player");
36+
expect(youtubePlayer).toBeInTheDocument();
37+
expect(youtubePlayer).toHaveAttribute("data-videoid", "hp4pYFASTrc");
38+
});
39+
});

src/setupTests.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import "@testing-library/jest-dom";

vitest.config.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { defineConfig } from "vitest/config";
2+
import react from "@vitejs/plugin-react";
3+
4+
export default defineConfig({
5+
plugins: [react()],
6+
test: {
7+
globals: true,
8+
environment: "jsdom",
9+
setupFiles: "./src/setupTests.ts",
10+
css: true,
11+
},
12+
resolve: {
13+
alias: {
14+
"@": "/src",
15+
},
16+
},
17+
});

0 commit comments

Comments
 (0)