Add comprehensive test suite infrastructure

- Create backend xUnit test project with Moq and FluentAssertions
- Add test utilities: TestDataFactory, MockHttpContext, TestUserClaims
- Create AuthControllerTests with comprehensive auth scenarios
- Install Jest and React Testing Library for frontend
- Configure jest.config.ts and jest.setup.ts with Next.js support
- Add test scripts to package.json
This commit is contained in:
Denis Urs Rudolph
2026-04-05 22:16:44 +02:00
parent 32bfbcadb1
commit 571fe5bc7c
19 changed files with 11224 additions and 1 deletions
+37
View File
@@ -0,0 +1,37 @@
import type { Config } from 'jest';
import nextJest from 'next/jest.js';
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './',
});
// Add any custom config to be passed to Jest
const config: Config = {
coverageProvider: 'v8',
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
},
testPathIgnorePatterns: [
'<rootDir>/node_modules/',
'<rootDir>/.next/',
],
collectCoverageFrom: [
'src/**/*.{js,jsx,ts,tsx}',
'!src/**/*.d.ts',
'!src/**/*.stories.{js,jsx,ts,tsx}',
],
coverageThreshold: {
global: {
branches: 0,
functions: 0,
lines: 0,
statements: 0,
},
},
};
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
export default createJestConfig(config);
+62
View File
@@ -0,0 +1,62 @@
import '@testing-library/jest-dom';
// Mock Next.js router
jest.mock('next/navigation', () => ({
useRouter() {
return {
route: '/',
pathname: '/',
query: {},
asPath: '/',
push: jest.fn(),
replace: jest.fn(),
reload: jest.fn(),
back: jest.fn(),
prefetch: jest.fn(),
beforePopState: jest.fn(),
events: {
on: jest.fn(),
off: jest.fn(),
emit: jest.fn(),
},
isFallback: false,
isLocaleDomain: false,
isReady: true,
isPreview: false,
};
},
useSearchParams() {
return {
get: jest.fn(),
getAll: jest.fn(),
has: jest.fn(),
entries: jest.fn(),
keys: jest.fn(),
values: jest.fn(),
forEach: jest.fn(),
};
},
usePathname() {
return '/';
},
}));
// Mock window.matchMedia
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation(query => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn(),
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});
// Clean up after each test
afterEach(() => {
jest.clearAllMocks();
});
+9924
View File
File diff suppressed because it is too large Load Diff
+11 -1
View File
@@ -6,7 +6,10 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "eslint"
"lint": "eslint",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage"
},
"dependencies": {
"next": "16.2.2",
@@ -15,12 +18,19 @@
},
"devDependencies": {
"@tailwindcss/postcss": "^4",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^14.6.1",
"@types/jest": "^30.0.0",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
"eslint-config-next": "16.2.2",
"jest": "^30.3.0",
"tailwindcss": "^4",
"ts-jest": "^29.4.9",
"typescript": "^5"
},
"ignoreScripts": [