277 lines
7.5 KiB
JavaScript
Executable File
277 lines
7.5 KiB
JavaScript
Executable File
// No need to require jest - it's available globally in Jest test files
|
|
|
|
// JEST MOCKS - must be set up before importing any modules that use them
|
|
|
|
// Mock MongoDB - fix MongoClient to work properly
|
|
const mockAdmin = {
|
|
ping: jest.fn().mockResolvedValue({ ok: 1 })
|
|
}
|
|
|
|
const mockDb = {
|
|
collection: jest.fn().mockReturnValue({
|
|
findOne: jest.fn().mockResolvedValue(null),
|
|
replaceOne: jest.fn().mockResolvedValue({ acknowledged: true }),
|
|
find: jest.fn(() => ({
|
|
toArray: jest.fn().mockResolvedValue([])
|
|
})),
|
|
insertOne: jest.fn().mockResolvedValue({ acknowledged: true, insertedId: 'test-id' }),
|
|
insertMany: jest.fn().mockResolvedValue({ acknowledged: true, insertedIds: { 0: 'test-id' } }),
|
|
updateOne: jest.fn().mockResolvedValue({ acknowledged: true, matchedCount: 1, modifiedCount: 1 }),
|
|
updateMany: jest.fn().mockResolvedValue({ acknowledged: true, matchedCount: 2, modifiedCount: 2 }),
|
|
deleteOne: jest.fn().mockResolvedValue({ acknowledged: true, deletedCount: 1 }),
|
|
deleteMany: jest.fn().mockResolvedValue({ acknowledged: true, deletedCount: 2 }),
|
|
bulkWrite: jest.fn().mockResolvedValue({ acknowledged: true, insertedCount: 0, matchedCount: 0, modifiedCount: 0, deletedCount: 0, upsertedCount: 0, upsertedIds: {} })
|
|
}),
|
|
admin: jest.fn().mockReturnValue(mockAdmin)
|
|
}
|
|
|
|
const mockClient = {
|
|
connect: jest.fn().mockResolvedValue({}),
|
|
close: jest.fn().mockResolvedValue(undefined),
|
|
db: jest.fn().mockImplementation((dbName) => mockDb)
|
|
}
|
|
|
|
jest.mock('mongodb', () => ({
|
|
MongoClient: jest.fn().mockImplementation(() => mockClient)
|
|
}))
|
|
|
|
// Mock environment variables for tests
|
|
process.env.MONGODB_URI = 'mongodb://localhost:27017/test'
|
|
process.env.MONGODB_DB = 'test'
|
|
|
|
// Mock Winston logger - will be overridden by individual test files if needed
|
|
jest.mock('winston', () => ({
|
|
transports: {
|
|
Console: jest.fn().mockImplementation(() => ({ name: 'console' })),
|
|
File: jest.fn().mockImplementation(() => ({ name: 'file' }))
|
|
},
|
|
createLogger: jest.fn(() => ({
|
|
info: jest.fn(),
|
|
warn: jest.fn(),
|
|
error: jest.fn(),
|
|
debug: jest.fn(),
|
|
log: jest.fn(),
|
|
child: jest.fn(() => ({
|
|
info: jest.fn(),
|
|
warn: jest.fn(),
|
|
error: jest.fn(),
|
|
debug: jest.fn(),
|
|
log: jest.fn(),
|
|
isLevelEnabled: jest.fn().mockReturnValue(true),
|
|
levels: { error: 0, warn: 1, info: 2, debug: 3 }
|
|
})),
|
|
isLevelEnabled: jest.fn().mockReturnValue(true),
|
|
levels: { error: 0, warn: 1, info: 2, debug: 3 }
|
|
})),
|
|
format: {
|
|
timestamp: jest.fn().mockReturnValue('timestamp-format'),
|
|
errors: jest.fn().mockReturnValue('errors-format'),
|
|
json: jest.fn().mockReturnValue('json-format'),
|
|
colorize: jest.fn().mockReturnValue('colorize-format'),
|
|
simple: jest.fn().mockReturnValue('simple-format'),
|
|
combine: jest.fn().mockReturnValue('combined-format'),
|
|
printf: jest.fn().mockReturnValue('printf-format')
|
|
}
|
|
}))
|
|
|
|
// Mock winston-loki
|
|
jest.mock('winston-loki', () => jest.fn().mockImplementation(() => ({ name: 'loki' })))
|
|
|
|
// Let individual test files handle their own logger mocks
|
|
// This allows for more specific testing of the logger module itself
|
|
|
|
// Mock Next.js Response objects
|
|
global.Response = class Response {
|
|
constructor(body, init) {
|
|
this.body = body
|
|
this.status = init?.status || 200
|
|
this.statusText = init?.statusText || ''
|
|
this.headers = new Map()
|
|
|
|
if (init?.headers) {
|
|
Object.entries(init.headers).forEach(([key, value]) => {
|
|
this.headers.set(key.toLowerCase(), value)
|
|
})
|
|
}
|
|
}
|
|
|
|
json() {
|
|
return Promise.resolve(JSON.parse(this.body || '{}'))
|
|
}
|
|
|
|
headers = {
|
|
get: (key) => this.headers.get(key.toLowerCase())
|
|
}
|
|
}
|
|
|
|
global.NextResponse = {
|
|
json: (data, init) => {
|
|
return new Response(JSON.stringify(data), {
|
|
status: init?.status || 200,
|
|
headers: init?.headers || {}
|
|
})
|
|
}
|
|
}
|
|
|
|
// Mock Next.js NextResponse properly
|
|
jest.mock('next/server', () => ({
|
|
NextResponse: {
|
|
json: jest.fn((data, init) => {
|
|
return new Response(JSON.stringify(data), {
|
|
status: init?.status || 200,
|
|
headers: init?.headers || {}
|
|
})
|
|
})
|
|
},
|
|
NextRequest: jest.fn()
|
|
}))
|
|
|
|
// Ensure process.env is available in tests
|
|
if (!global.process.env) {
|
|
global.process.env = {}
|
|
}
|
|
|
|
// Logger will be mocked by the winston mock above
|
|
|
|
// Mock Loki transport
|
|
jest.mock('winston-loki', () => jest.fn(() => ({
|
|
log: jest.fn(),
|
|
close: jest.fn()
|
|
})))
|
|
|
|
// Mock Next.js router
|
|
jest.mock('next/router', () => ({
|
|
useRouter: () => ({
|
|
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(),
|
|
},
|
|
}),
|
|
}))
|
|
|
|
// Mock Next.js navigation
|
|
jest.mock('next/navigation', () => ({
|
|
useRouter: () => ({
|
|
push: jest.fn(),
|
|
replace: jest.fn(),
|
|
refresh: jest.fn(),
|
|
back: jest.fn(),
|
|
forward: jest.fn(),
|
|
prefetch: jest.fn(),
|
|
}),
|
|
useSearchParams: () => new URLSearchParams(),
|
|
usePathname: () => '/',
|
|
}))
|
|
|
|
// Mock Response constructor for Next.js API routes
|
|
global.Response = class MockResponse {
|
|
constructor(body, options = {}) {
|
|
this.body = body
|
|
this.status = options.status || 200
|
|
this.statusText = options.statusText || 'OK'
|
|
this.headers = new Map([
|
|
['content-type', options.headers?.['content-type'] || 'application/json'],
|
|
...Object.entries(options.headers || {})
|
|
])
|
|
|
|
// Next.js Response.json() method
|
|
this.json = jest.fn(() => {
|
|
try {
|
|
return JSON.parse(body || '{}')
|
|
} catch {
|
|
return body
|
|
}
|
|
})
|
|
|
|
this.text = jest.fn(() => Promise.resolve(body || ''))
|
|
this.arrayBuffer = jest.fn(() => Promise.resolve(new ArrayBuffer(0)))
|
|
}
|
|
|
|
get(name) {
|
|
return this.headers.get(name.toLowerCase())
|
|
}
|
|
|
|
set(name, value) {
|
|
this.headers.set(name.toLowerCase(), value)
|
|
}
|
|
|
|
clone() {
|
|
return { ...this }
|
|
}
|
|
}
|
|
|
|
// Mock Request constructor for Next.js API routes
|
|
global.Request = class MockRequest {
|
|
constructor(url, options = {}) {
|
|
this.url = url
|
|
this.method = options.method || 'GET'
|
|
this.headers = new Map([
|
|
['content-type', 'application/json'],
|
|
...Object.entries(options.headers || {})
|
|
])
|
|
this.body = options.body || null
|
|
}
|
|
|
|
json() {
|
|
return Promise.resolve(this.body ? JSON.parse(this.body) : {})
|
|
}
|
|
|
|
text() {
|
|
return Promise.resolve(this.body || '')
|
|
}
|
|
|
|
get(name) {
|
|
return this.headers.get(name.toLowerCase())
|
|
}
|
|
}
|
|
|
|
// Mock NextResponse for API routes
|
|
global.NextResponse = {
|
|
json: jest.fn((data, options = {}) => {
|
|
return new global.Response(JSON.stringify(data), {
|
|
status: options.status || 200,
|
|
headers: {
|
|
'content-type': 'application/json',
|
|
...options.headers
|
|
}
|
|
})
|
|
}),
|
|
redirect: jest.fn((url, status = 302) => ({
|
|
url,
|
|
status,
|
|
headers: new Map([['location', url]])
|
|
})),
|
|
rewrite: jest.fn((url) => ({
|
|
url,
|
|
status: 200
|
|
}))
|
|
}
|
|
|
|
// Set up environment variables for tests
|
|
process.env.MONGODB_URI = 'mongodb://localhost:27017/test'
|
|
process.env.MONGODB_DB = 'test'
|
|
process.env.LOKI_HOST = 'http://loki:3100'
|
|
process.env.NODE_ENV = 'test'
|
|
process.env.NEXT_PUBLIC_CONTACT_EMAIL = 'info@mozdit.hu'
|
|
process.env.NEXT_PUBLIC_SITE_URL = 'https://localhost:3000'
|
|
process.env.npm_package_version = '1.0.0'
|
|
process.env.PACKAGE_VERSION = '1.0.0'
|
|
|
|
// Set up cleanup for consistent testing
|
|
afterEach(() => {
|
|
jest.clearAllMocks()
|
|
})
|
|
|
|
// Import React Testing Library DOM (using require for Jest setup files)
|
|
require('@testing-library/jest-dom') |