Security hardening release addressing CodeQL and Dependabot alerts: - Fix stack trace exposure in error responses - Add SSRF protection with DNS resolution checking - Implement proper URL hostname validation (replaces substring matching) - Add centralized path sanitization to prevent path traversal - Fix ReDoS vulnerability in email validation regex - Improve HTML sanitization in validation utilities - Fix capability wildcard matching in auth utilities - Update glob dependency to address CVE - Add CodeQL suppression comments for verified false positives 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
117 lines
2.5 KiB
JavaScript
117 lines
2.5 KiB
JavaScript
// Optional: configure or set up a testing framework before each test.
|
|
// If you delete this file, remove `setupFilesAfterEnv` from `jest.config.js`
|
|
|
|
// Used for __tests__/testing-library.js
|
|
// Learn more: https://github.com/testing-library/jest-dom
|
|
import '@testing-library/jest-dom'
|
|
|
|
// Mock next/router
|
|
jest.mock('next/router', () => ({
|
|
useRouter() {
|
|
return {
|
|
route: '/',
|
|
pathname: '/',
|
|
query: '',
|
|
asPath: '',
|
|
push: jest.fn(),
|
|
pop: jest.fn(),
|
|
reload: jest.fn(),
|
|
back: jest.fn(),
|
|
prefetch: jest.fn().mockResolvedValue(undefined),
|
|
beforePopState: jest.fn(),
|
|
events: {
|
|
on: jest.fn(),
|
|
off: jest.fn(),
|
|
emit: jest.fn(),
|
|
},
|
|
isFallback: false,
|
|
}
|
|
},
|
|
}))
|
|
|
|
// Mock next/navigation
|
|
jest.mock('next/navigation', () => ({
|
|
useRouter() {
|
|
return {
|
|
push: jest.fn(),
|
|
replace: jest.fn(),
|
|
prefetch: jest.fn(),
|
|
back: jest.fn(),
|
|
forward: jest.fn(),
|
|
refresh: jest.fn(),
|
|
}
|
|
},
|
|
useSearchParams() {
|
|
return new URLSearchParams()
|
|
},
|
|
usePathname() {
|
|
return '/'
|
|
},
|
|
}))
|
|
|
|
// Mock IntersectionObserver
|
|
global.IntersectionObserver = class IntersectionObserver {
|
|
constructor() {}
|
|
disconnect() {}
|
|
observe() {}
|
|
unobserve() {}
|
|
}
|
|
|
|
// Mock ResizeObserver
|
|
global.ResizeObserver = class ResizeObserver {
|
|
constructor() {}
|
|
disconnect() {}
|
|
observe() {}
|
|
unobserve() {}
|
|
}
|
|
|
|
// Mock matchMedia
|
|
Object.defineProperty(window, 'matchMedia', {
|
|
writable: true,
|
|
value: jest.fn().mockImplementation(query => ({
|
|
matches: false,
|
|
media: query,
|
|
onchange: null,
|
|
addListener: jest.fn(), // deprecated
|
|
removeListener: jest.fn(), // deprecated
|
|
addEventListener: jest.fn(),
|
|
removeEventListener: jest.fn(),
|
|
dispatchEvent: jest.fn(),
|
|
})),
|
|
})
|
|
|
|
// Mock localStorage
|
|
const localStorageMock = {
|
|
getItem: jest.fn(),
|
|
setItem: jest.fn(),
|
|
removeItem: jest.fn(),
|
|
clear: jest.fn(),
|
|
}
|
|
global.localStorage = localStorageMock
|
|
|
|
// Mock sessionStorage
|
|
const sessionStorageMock = {
|
|
getItem: jest.fn(),
|
|
setItem: jest.fn(),
|
|
removeItem: jest.fn(),
|
|
clear: jest.fn(),
|
|
}
|
|
global.sessionStorage = sessionStorageMock
|
|
|
|
// Suppress console errors in tests unless needed
|
|
const originalError = console.error
|
|
beforeAll(() => {
|
|
console.error = (...args) => {
|
|
if (
|
|
typeof args[0] === 'string' &&
|
|
args[0].includes('Warning: ReactDOM.render is no longer supported')
|
|
) {
|
|
return
|
|
}
|
|
originalError.call(console, ...args)
|
|
}
|
|
})
|
|
|
|
afterAll(() => {
|
|
console.error = originalError
|
|
}) |