test: add Vitest infrastructure (config, setup, mocks, fixtures)
Adds test harness for the suite: - vitest.config.ts: happy-dom env, @/* alias, v8 coverage with 70% thresholds - setup.ts: env vars, global next/headers and next/navigation mocks - tsconfig.json: IDE alias resolution for test/ - __mocks__/prisma.ts: centralised Prisma mock auto-registered via vi.mock - fixtures/users.ts, fixtures/orders.ts: typed test data
This commit is contained in:
@@ -0,0 +1,81 @@
|
|||||||
|
import { vi } from 'vitest'
|
||||||
|
|
||||||
|
export const prisma = {
|
||||||
|
user: {
|
||||||
|
findUnique: vi.fn(),
|
||||||
|
findMany: vi.fn(),
|
||||||
|
create: vi.fn(),
|
||||||
|
update: vi.fn(),
|
||||||
|
delete: vi.fn(),
|
||||||
|
count: vi.fn(),
|
||||||
|
},
|
||||||
|
session: {
|
||||||
|
create: vi.fn(),
|
||||||
|
findUnique: vi.fn(),
|
||||||
|
delete: vi.fn(),
|
||||||
|
deleteMany: vi.fn(),
|
||||||
|
},
|
||||||
|
loginAttempt: {
|
||||||
|
count: vi.fn(),
|
||||||
|
create: vi.fn(),
|
||||||
|
deleteMany: vi.fn(),
|
||||||
|
},
|
||||||
|
order: {
|
||||||
|
create: vi.fn(),
|
||||||
|
update: vi.fn(),
|
||||||
|
findUnique: vi.fn(),
|
||||||
|
findMany: vi.fn(),
|
||||||
|
count: vi.fn(),
|
||||||
|
},
|
||||||
|
orderItem: {
|
||||||
|
create: vi.fn(),
|
||||||
|
findMany: vi.fn(),
|
||||||
|
},
|
||||||
|
payment: {
|
||||||
|
create: vi.fn(),
|
||||||
|
update: vi.fn(),
|
||||||
|
updateMany: vi.fn(),
|
||||||
|
findFirst: vi.fn(),
|
||||||
|
findMany: vi.fn(),
|
||||||
|
},
|
||||||
|
product: {
|
||||||
|
findUnique: vi.fn(),
|
||||||
|
findMany: vi.fn(),
|
||||||
|
create: vi.fn(),
|
||||||
|
update: vi.fn(),
|
||||||
|
delete: vi.fn(),
|
||||||
|
count: vi.fn(),
|
||||||
|
},
|
||||||
|
productType: {
|
||||||
|
findUnique: vi.fn(),
|
||||||
|
findMany: vi.fn(),
|
||||||
|
create: vi.fn(),
|
||||||
|
update: vi.fn(),
|
||||||
|
delete: vi.fn(),
|
||||||
|
},
|
||||||
|
category: {
|
||||||
|
findUnique: vi.fn(),
|
||||||
|
findMany: vi.fn(),
|
||||||
|
create: vi.fn(),
|
||||||
|
update: vi.fn(),
|
||||||
|
delete: vi.fn(),
|
||||||
|
},
|
||||||
|
review: {
|
||||||
|
findMany: vi.fn(),
|
||||||
|
create: vi.fn(),
|
||||||
|
update: vi.fn(),
|
||||||
|
delete: vi.fn(),
|
||||||
|
count: vi.fn(),
|
||||||
|
},
|
||||||
|
auditLog: {
|
||||||
|
create: vi.fn(),
|
||||||
|
findMany: vi.fn(),
|
||||||
|
},
|
||||||
|
siteSettings: {
|
||||||
|
findMany: vi.fn(),
|
||||||
|
upsert: vi.fn(),
|
||||||
|
},
|
||||||
|
$transaction: vi.fn((fn: (tx: unknown) => unknown) => fn(prisma)),
|
||||||
|
}
|
||||||
|
|
||||||
|
vi.mock('@/lib/prisma', () => ({ prisma }))
|
||||||
Vendored
+53
@@ -0,0 +1,53 @@
|
|||||||
|
import { mockUser } from './users'
|
||||||
|
|
||||||
|
export const mockOrder = {
|
||||||
|
id: 'order-1',
|
||||||
|
userId: mockUser.id,
|
||||||
|
status: 'PENDING' as const,
|
||||||
|
grandTotal: 2999,
|
||||||
|
currency: 'EUR',
|
||||||
|
createdAt: new Date('2024-01-01'),
|
||||||
|
updatedAt: new Date('2024-01-01'),
|
||||||
|
user: mockUser,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mockPayment = {
|
||||||
|
id: 'payment-1',
|
||||||
|
orderId: mockOrder.id,
|
||||||
|
provider: 'stripe',
|
||||||
|
providerPaymentId: 'pi_test_123',
|
||||||
|
status: 'pending',
|
||||||
|
amount: 2999,
|
||||||
|
currency: 'EUR',
|
||||||
|
rawPayload: {},
|
||||||
|
createdAt: new Date('2024-01-01'),
|
||||||
|
updatedAt: new Date('2024-01-01'),
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mockStripeCheckoutEvent = {
|
||||||
|
type: 'checkout.session.completed',
|
||||||
|
data: {
|
||||||
|
object: {
|
||||||
|
metadata: { orderId: mockOrder.id },
|
||||||
|
payment_intent: 'pi_test_123',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mockStripePaymentSucceededEvent = {
|
||||||
|
type: 'payment_intent.succeeded',
|
||||||
|
data: {
|
||||||
|
object: {
|
||||||
|
id: 'pi_test_123',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mockStripePaymentFailedEvent = {
|
||||||
|
type: 'payment_intent.payment_failed',
|
||||||
|
data: {
|
||||||
|
object: {
|
||||||
|
id: 'pi_test_123',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
Vendored
+27
@@ -0,0 +1,27 @@
|
|||||||
|
export const mockUser = {
|
||||||
|
id: 'user-1',
|
||||||
|
email: 'test@example.com',
|
||||||
|
name: 'Test User',
|
||||||
|
passwordHash: '$2a$12$hashedpassword',
|
||||||
|
role: 'CUSTOMER' as const,
|
||||||
|
mustChangePassword: false,
|
||||||
|
createdAt: new Date('2024-01-01'),
|
||||||
|
updatedAt: new Date('2024-01-01'),
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mockAdmin = {
|
||||||
|
...mockUser,
|
||||||
|
id: 'admin-1',
|
||||||
|
email: 'admin@example.com',
|
||||||
|
name: 'Admin User',
|
||||||
|
role: 'ADMIN' as const,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mockSession = {
|
||||||
|
id: 'session-1',
|
||||||
|
userId: mockUser.id,
|
||||||
|
tokenHash: 'abc123hash',
|
||||||
|
expiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000),
|
||||||
|
createdAt: new Date('2024-01-01'),
|
||||||
|
user: mockUser,
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import '@testing-library/jest-dom'
|
||||||
|
import { vi } from 'vitest'
|
||||||
|
|
||||||
|
// Env vars necessarie per i test
|
||||||
|
process.env.STRIPE_SECRET_KEY = 'sk_test_mock'
|
||||||
|
process.env.STRIPE_WEBHOOK_SECRET = 'whsec_test_mock'
|
||||||
|
process.env.SMTP_HOST = 'localhost'
|
||||||
|
process.env.SMTP_PORT = '1025'
|
||||||
|
process.env.APP_URL = 'http://localhost'
|
||||||
|
process.env.DATABASE_URL = 'postgresql://test:test@localhost:5432/test'
|
||||||
|
process.env.NODE_ENV = 'test'
|
||||||
|
process.env.AUTH_SECRET = 'test-secret-32-chars-minimum-ok!'
|
||||||
|
|
||||||
|
// Mock di next/headers (cookies() lancia fuori dal runtime Next.js)
|
||||||
|
vi.mock('next/headers', () => {
|
||||||
|
const mockCookieStore = {
|
||||||
|
get: vi.fn(),
|
||||||
|
set: vi.fn(),
|
||||||
|
delete: vi.fn(),
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
cookies: vi.fn(() => mockCookieStore),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Mock di next/navigation
|
||||||
|
vi.mock('next/navigation', () => ({
|
||||||
|
useRouter: vi.fn(() => ({ push: vi.fn(), replace: vi.fn() })),
|
||||||
|
usePathname: vi.fn(() => '/'),
|
||||||
|
redirect: vi.fn(),
|
||||||
|
}))
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"extends": "../app/tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["../app/src/*"]
|
||||||
|
},
|
||||||
|
"types": ["vitest/globals", "@testing-library/jest-dom"]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"./**/*.ts",
|
||||||
|
"./**/*.tsx"
|
||||||
|
],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { defineConfig } from 'vitest/config'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
test: {
|
||||||
|
environment: 'happy-dom',
|
||||||
|
globals: true,
|
||||||
|
setupFiles: [path.resolve(__dirname, 'setup.ts')],
|
||||||
|
include: [
|
||||||
|
'../test/unit/**/*.{test,spec}.{ts,tsx}',
|
||||||
|
'../test/integration/**/*.{test,spec}.{ts,tsx}',
|
||||||
|
'../test/components/**/*.{test,spec}.{ts,tsx}',
|
||||||
|
],
|
||||||
|
exclude: ['**/node_modules/**'],
|
||||||
|
coverage: {
|
||||||
|
provider: 'v8',
|
||||||
|
reporter: ['text', 'html', 'lcov'],
|
||||||
|
include: ['src/**/*.ts', 'src/**/*.tsx'],
|
||||||
|
exclude: [
|
||||||
|
'src/app/layout.tsx',
|
||||||
|
'src/lib/prisma.ts',
|
||||||
|
'src/**/*.d.ts',
|
||||||
|
],
|
||||||
|
thresholds: { lines: 70, functions: 70 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': path.resolve(__dirname, '../app/src'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
esbuild: {
|
||||||
|
jsx: 'automatic',
|
||||||
|
jsxImportSource: 'react',
|
||||||
|
},
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user