chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
const mockRouter = {
|
||||
get: jest.fn(),
|
||||
post: jest.fn(),
|
||||
put: jest.fn(),
|
||||
patch: jest.fn(),
|
||||
delete: jest.fn()
|
||||
}
|
||||
|
||||
jest.mock(
|
||||
'express',
|
||||
() => ({
|
||||
Router: () => mockRouter
|
||||
}),
|
||||
{ virtual: true }
|
||||
)
|
||||
|
||||
jest.mock('../src/middleware/auth', () => ({
|
||||
authenticateAdmin: jest.fn((_req, _res, next) => next())
|
||||
}))
|
||||
|
||||
jest.mock('../src/services/apiKeyService', () => ({
|
||||
updateApiKey: jest.fn()
|
||||
}))
|
||||
|
||||
jest.mock('../src/models/redis', () => ({}))
|
||||
|
||||
jest.mock('../src/utils/logger', () => ({
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
info: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
success: jest.fn()
|
||||
}))
|
||||
|
||||
jest.mock('../src/utils/costCalculator', () => ({
|
||||
calculateCost: jest.fn(),
|
||||
formatCost: jest.fn()
|
||||
}))
|
||||
|
||||
jest.mock(
|
||||
'../config/config',
|
||||
() => ({
|
||||
system: {
|
||||
timezoneOffset: 8
|
||||
}
|
||||
}),
|
||||
{ virtual: true }
|
||||
)
|
||||
|
||||
jest.mock('../src/services/requestBodyRuleService', () => ({
|
||||
validateAndNormalizeRules: jest.fn()
|
||||
}))
|
||||
|
||||
const apiKeyService = require('../src/services/apiKeyService')
|
||||
const requestBodyRuleService = require('../src/services/requestBodyRuleService')
|
||||
require('../src/routes/admin/apiKeys')
|
||||
|
||||
function createResponse() {
|
||||
const res = {
|
||||
statusCode: 200,
|
||||
body: null,
|
||||
json: jest.fn((payload) => {
|
||||
res.body = payload
|
||||
return res
|
||||
}),
|
||||
status: jest.fn((code) => {
|
||||
res.statusCode = code
|
||||
return res
|
||||
})
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
function findPutHandler(path) {
|
||||
const route = mockRouter.put.mock.calls.find((call) => call[0] === path)
|
||||
return route?.[2]
|
||||
}
|
||||
|
||||
describe('admin api keys route payload rule updates', () => {
|
||||
beforeEach(() => {
|
||||
apiKeyService.updateApiKey.mockReset()
|
||||
apiKeyService.updateApiKey.mockResolvedValue()
|
||||
|
||||
requestBodyRuleService.validateAndNormalizeRules.mockReset()
|
||||
requestBodyRuleService.validateAndNormalizeRules.mockImplementation((rules) => ({
|
||||
valid: true,
|
||||
rules
|
||||
}))
|
||||
})
|
||||
|
||||
test('does not clear stored payload rules when the toggle is disabled without sending rules', async () => {
|
||||
const handler = findPutHandler('/api-keys/:keyId')
|
||||
const res = createResponse()
|
||||
|
||||
await handler(
|
||||
{
|
||||
params: { keyId: 'key-1' },
|
||||
body: {
|
||||
name: 'Renamed Key',
|
||||
enableOpenAIResponsesPayloadRules: false
|
||||
}
|
||||
},
|
||||
res
|
||||
)
|
||||
|
||||
expect(requestBodyRuleService.validateAndNormalizeRules).not.toHaveBeenCalled()
|
||||
|
||||
const updates = apiKeyService.updateApiKey.mock.calls[0][1]
|
||||
expect(updates).toEqual({
|
||||
name: 'Renamed Key',
|
||||
enableOpenAIResponsesPayloadRules: false
|
||||
})
|
||||
expect(updates).not.toHaveProperty('openaiResponsesPayloadRules')
|
||||
|
||||
expect(res.status).not.toHaveBeenCalled()
|
||||
expect(res.body).toEqual({
|
||||
success: true,
|
||||
message: 'API key updated successfully'
|
||||
})
|
||||
})
|
||||
|
||||
test('accepts payload rules even when the toggle is disabled', async () => {
|
||||
const handler = findPutHandler('/api-keys/:keyId')
|
||||
const res = createResponse()
|
||||
const rules = [{ path: 'model', valueType: 'string', value: 'gpt-5' }]
|
||||
|
||||
await handler(
|
||||
{
|
||||
params: { keyId: 'key-2' },
|
||||
body: {
|
||||
enableOpenAIResponsesPayloadRules: false,
|
||||
openaiResponsesPayloadRules: rules
|
||||
}
|
||||
},
|
||||
res
|
||||
)
|
||||
|
||||
expect(requestBodyRuleService.validateAndNormalizeRules).toHaveBeenCalledWith(rules)
|
||||
expect(apiKeyService.updateApiKey).toHaveBeenCalledWith('key-2', {
|
||||
enableOpenAIResponsesPayloadRules: false,
|
||||
openaiResponsesPayloadRules: rules
|
||||
})
|
||||
|
||||
expect(res.status).not.toHaveBeenCalled()
|
||||
expect(res.body.success).toBe(true)
|
||||
})
|
||||
|
||||
test('allows explicitly clearing payload rules with an empty array', async () => {
|
||||
const handler = findPutHandler('/api-keys/:keyId')
|
||||
const res = createResponse()
|
||||
|
||||
await handler(
|
||||
{
|
||||
params: { keyId: 'key-3' },
|
||||
body: {
|
||||
openaiResponsesPayloadRules: []
|
||||
}
|
||||
},
|
||||
res
|
||||
)
|
||||
|
||||
expect(requestBodyRuleService.validateAndNormalizeRules).toHaveBeenCalledWith([])
|
||||
expect(apiKeyService.updateApiKey).toHaveBeenCalledWith('key-3', {
|
||||
openaiResponsesPayloadRules: []
|
||||
})
|
||||
|
||||
expect(res.status).not.toHaveBeenCalled()
|
||||
expect(res.body.success).toBe(true)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user