Skip to content

Commit ed515fa

Browse files
committed
Add base tests
1 parent c284983 commit ed515fa

File tree

11 files changed

+4210
-189
lines changed

11 files changed

+4210
-189
lines changed
Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Check Next.js
1+
name: CI
22

33
on:
44
push:
@@ -9,8 +9,8 @@ on:
99
- main
1010

1111
jobs:
12-
build:
13-
name: Build
12+
ci:
13+
name: All
1414
runs-on: ubuntu-latest
1515

1616
steps:
@@ -25,7 +25,23 @@ jobs:
2525
- name: Install dependencies
2626
run: npm ci
2727

28-
- name: Build the app
28+
- name: Type check
29+
run: npx tsc --noEmit
30+
31+
- name: Lint
32+
run: npm run lint
33+
34+
- name: Run tests
35+
run: npm run test
36+
37+
- name: Build app
2938
env:
3039
DATABASE_URL: ${{ secrets.DATABASE_URL }}
3140
run: npm run build
41+
42+
# Optional: Playwright E2E tests
43+
- name: Install Playwright deps
44+
run: npx playwright install --with-deps
45+
46+
- name: Run E2E tests
47+
run: npx playwright test

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,16 @@ npx prisma migrate dev --name init
8080
```
8181
Note that your local database will be made of synthetic data, not real users. This is fine for development and testing.
8282

83-
Start the development server:
83+
Make sure the tests pass:
84+
```bash
85+
npm run test
86+
```
8487

88+
Start the development server:
8589
```bash
8690
npm run dev
8791
```
8892

89-
Once the server is running, visit http://localhost:3000 to start using the app. Now you can start contributing by
90-
making changes and submitting pull requests!
93+
Once the server is running, visit http://localhost:3000 to start using the app. Now you can start contributing by making changes and submitting pull requests!
9194

9295
See [development.md](docs/development.md) for additional instructions, such as adding new profile features.

__mocks__/fileMock.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Mock for file imports (images, etc.)
2+
module.exports = 'test-file-stub';

__mocks__/styleMock.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Mock for CSS imports
2+
module.exports = {};

jest.config.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
const nextJest = require('next/jest');
2+
3+
const createJestConfig = nextJest({
4+
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
5+
dir: './',
6+
});
7+
8+
// Add any custom config to be passed to Jest
9+
const customJestConfig = {
10+
// Add more setup options before each test is run
11+
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
12+
// if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work
13+
moduleDirectories: ['node_modules', '<rootDir>/'],
14+
testEnvironment: 'jest-environment-jsdom',
15+
moduleNameMapper: {
16+
// Handle module aliases (this will be automatically configured for you soon)
17+
'^@/components/(.*)$': '<rootDir>/components/$1',
18+
'^@/app/(.*)$': '<rootDir>/app/$1',
19+
'^@/lib/(.*)$': '<rootDir>/lib/$1',
20+
'^@/types/(.*)$': '<rootDir>/types/$1',
21+
'^.+\\.(css|sass|scss)$': '<rootDir>/__mocks__/styleMock.js',
22+
'^.+\\.(jpg|jpeg|png|gif|webp|avif|svg)$': '<rootDir>/__mocks__/fileMock.js',
23+
},
24+
// Don't ignore node_modules by default
25+
transformIgnorePatterns: [
26+
'/node_modules/(?!(@upstash|@radix-ui|@hookform|@auth|@aws-sdk|@emotion|@mui|@prisma|@radix-ui|@react-email|@supabase|@types|@upstash|next-auth|react-markdown|rehype-raw|remark-gfm|uuid|react-syntax-highlighter)/)',
27+
],
28+
// Add more configuration options as needed
29+
// transform: {
30+
// // Use babel-jest to transpile tests with the next/babel preset
31+
// // https://jestjs.io/docs/configuration#transform-objectstring-pathtotransformer--pathtotransformer-object
32+
// '^.+\\.(js|jsx|ts|tsx)$': ['babel-jest', { presets: ['next/babel'] }],
33+
// },
34+
// testPathIgnorePatterns: ['<rootDir>/node_modules/', '<rootDir>/.next/'],
35+
// testEnvironment: 'jsdom',
36+
// transform: {
37+
// // Use babel-jest to transpile tests with the next/babel preset
38+
// // https://jestjs.io/docs/configuration#transform-objectstring-pathtotransformer--pathtotransformer-object
39+
// '^.+\\.(js|jsx|ts|tsx)$': ['babel-jest', { presets: ['next/babel'] }],
40+
// },
41+
// transformIgnorePatterns: [
42+
// '/node_modules/(?!(react-syntax-highlighter|@heroicons|@aws-sdk|@radix-ui|@emotion|@mui|@prisma|@radix-ui|@react-email|@supabase|@types|@upstash|next-auth|react-markdown|rehype-raw|remark-gfm|uuid)/)',
43+
// ],
44+
};
45+
46+
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
47+
module.exports = createJestConfig(customJestConfig);

jest.setup.d.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// This file extends the global Jest namespace with custom matchers from @testing-library/jest-dom
2+
import '@testing-library/jest-dom';
3+
4+
declare global {
5+
namespace jest {
6+
interface Matchers<R> {
7+
toBeInTheDocument(): R;
8+
toHaveClass(...classes: string[]): R;
9+
// Add other custom matchers you use from @testing-library/jest-dom
10+
}
11+
}
12+
}
13+
14+
export {};

jest.setup.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Learn more: https://github.com/testing-library/jest-dom
2+
import '@testing-library/jest-dom';
3+
4+
// Mock next/navigation
5+
jest.mock('next/navigation', () => ({
6+
useRouter() {
7+
return {
8+
prefetch: () => null,
9+
push: jest.fn(),
10+
};
11+
},
12+
useSearchParams() {
13+
return {
14+
get: jest.fn(),
15+
};
16+
},
17+
usePathname() {
18+
return '';
19+
},
20+
}));
21+
22+
// Mock next-auth
23+
jest.mock('next-auth/react', () => ({
24+
useSession: jest.fn(() => ({
25+
data: null,
26+
status: 'unauthenticated',
27+
})),
28+
signIn: jest.fn(),
29+
signOut: jest.fn(),
30+
getSession: jest.fn(),
31+
}));
32+
33+
// Mock next/head
34+
jest.mock('next/head', () => {
35+
return {
36+
__esModule: true,
37+
default: ({
38+
children,
39+
} /*: {
40+
children: Array<React.ReactElement>;
41+
}*/) => <>{children}</>,
42+
};
43+
});
44+
45+
// Mock next-themes
46+
jest.mock('next-themes', () => ({
47+
useTheme: () => ({
48+
setTheme: jest.fn(),
49+
theme: 'light',
50+
systemTheme: 'light',
51+
}),
52+
ThemeProvider: ({ children }) => (
53+
<div>{children}</div>
54+
),
55+
}));

lib/client/LoadingSpinner.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,14 @@ import React from "react";
44

55
export default function LoadingSpinner() {
66
return (
7-
<div className="flex items-center justify-center min-h-screen ">
8-
<div className="w-12 h-12 border-4 border-gray-300 border-t-gray-800 rounded-full animate-spin" />
7+
<div
8+
data-testid="spinner-container"
9+
className="flex items-center justify-center min-h-screen"
10+
>
11+
<div
12+
data-testid="spinner"
13+
className="w-12 h-12 border-4 border-gray-300 border-t-gray-800 rounded-full animate-spin"
14+
/>
915
</div>
1016
);
1117
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { render, screen } from '@testing-library/react';
2+
import LoadingSpinner from '../LoadingSpinner';
3+
4+
describe('LoadingSpinner', () => {
5+
it('renders a loading spinner', () => {
6+
render(<LoadingSpinner />);
7+
8+
// Check if the spinner container is rendered with the correct classes
9+
const spinnerContainer = screen.getByTestId('spinner-container');
10+
expect(spinnerContainer).toBeInTheDocument();
11+
expect(spinnerContainer).toHaveClass('flex', 'items-center', 'justify-center', 'min-h-screen');
12+
13+
// Check if the spinner has the correct classes
14+
const spinner = screen.getByTestId('spinner');
15+
expect(spinner).toHaveClass('w-12', 'h-12', 'border-4', 'border-gray-300', 'border-t-gray-800', 'rounded-full', 'animate-spin');
16+
});
17+
});

0 commit comments

Comments
 (0)