feat: add allowed Linear API operations to MCP config
This commit is contained in:
@@ -0,0 +1,302 @@
|
||||
// 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 - simplified for default export
|
||||
jest.mock('winston', () => ({
|
||||
transports: {
|
||||
Console: jest.fn(),
|
||||
},
|
||||
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(() => ({})),
|
||||
errors: jest.fn(() => ({})),
|
||||
json: jest.fn(() => ({})),
|
||||
colorize: jest.fn(() => ({})),
|
||||
simple: jest.fn(() => ({})),
|
||||
combine: jest.fn((...args) => args[args.length - 1] || {}),
|
||||
printf: jest.fn(() => ({}))
|
||||
}
|
||||
}))
|
||||
|
||||
// Mock logger module to use the mocked winston
|
||||
jest.mock('./src/lib/logger', () => {
|
||||
const mockLogger = {
|
||||
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()
|
||||
}))
|
||||
}
|
||||
|
||||
return {
|
||||
__esModule: true,
|
||||
default: mockLogger,
|
||||
logger: mockLogger,
|
||||
createComponentLogger: jest.fn(() => mockLogger.child()),
|
||||
requestLogger: mockLogger.child(),
|
||||
apiLogger: mockLogger.child(),
|
||||
dbLogger: mockLogger.child(),
|
||||
authLogger: mockLogger.child(),
|
||||
errorLogger: mockLogger.child(),
|
||||
generateRequestId: jest.fn(() => 'test-request-id'),
|
||||
withTiming: jest.fn(async (operation, fn) => fn())
|
||||
}
|
||||
})
|
||||
|
||||
// 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')
|
||||
Reference in New Issue
Block a user