Files
ComfyUI_frontend/tests-ui/tests/services/headerRegistry.test.ts
bymyself 0d6e5a75a9 feat: Add header registry infrastructure
- Create TypeScript interfaces for header providers
- Implement header registry with priority-based ordering
- Add network client adapters that integrate with the registry
- Add comprehensive unit tests

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-17 13:43:58 -07:00

254 lines
7.4 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest'
import { headerRegistry } from '@/services/headerRegistry'
import type {
HeaderProviderContext,
IHeaderProvider
} from '@/types/headerTypes'
describe('headerRegistry', () => {
beforeEach(() => {
headerRegistry.clear()
})
describe('registerHeaderProvider', () => {
it('should register a header provider', () => {
const provider: IHeaderProvider = {
provideHeaders: vi.fn().mockReturnValue({ 'X-Test': 'value' })
}
const registration = headerRegistry.registerHeaderProvider(provider)
expect(registration).toBeDefined()
expect(registration.id).toMatch(/^header-provider-\d+$/)
expect(headerRegistry.providerCount).toBe(1)
})
it('should return a disposable registration', () => {
const provider: IHeaderProvider = {
provideHeaders: vi.fn()
}
const registration = headerRegistry.registerHeaderProvider(provider)
expect(headerRegistry.providerCount).toBe(1)
registration.dispose()
expect(headerRegistry.providerCount).toBe(0)
})
it('should insert providers in priority order', async () => {
const provider1: IHeaderProvider = {
provideHeaders: vi.fn().mockReturnValue({ 'X-Priority': 'low' })
}
const provider2: IHeaderProvider = {
provideHeaders: vi.fn().mockReturnValue({ 'X-Priority': 'high' })
}
const provider3: IHeaderProvider = {
provideHeaders: vi.fn().mockReturnValue({ 'X-Priority': 'medium' })
}
headerRegistry.registerHeaderProvider(provider1, { priority: 1 })
headerRegistry.registerHeaderProvider(provider2, { priority: 10 })
headerRegistry.registerHeaderProvider(provider3, { priority: 5 })
const context: HeaderProviderContext = {
url: 'https://api.example.com',
method: 'GET'
}
const headers = await headerRegistry.getHeaders(context)
// Higher priority provider should override
expect(headers['X-Priority']).toBe('high')
})
})
describe('getHeaders', () => {
it('should combine headers from all providers', async () => {
const provider1: IHeaderProvider = {
provideHeaders: vi.fn().mockReturnValue({
'X-Header-1': 'value1',
'X-Common': 'provider1'
})
}
const provider2: IHeaderProvider = {
provideHeaders: vi.fn().mockReturnValue({
'X-Header-2': 'value2',
'X-Common': 'provider2'
})
}
headerRegistry.registerHeaderProvider(provider1, { priority: 1 })
headerRegistry.registerHeaderProvider(provider2, { priority: 2 })
const context: HeaderProviderContext = {
url: 'https://api.example.com',
method: 'GET'
}
const headers = await headerRegistry.getHeaders(context)
expect(headers).toEqual({
'X-Header-1': 'value1',
'X-Header-2': 'value2',
'X-Common': 'provider2' // Higher priority wins
})
})
it('should resolve function header values', async () => {
const provider: IHeaderProvider = {
provideHeaders: vi.fn().mockReturnValue({
'X-Static': 'static',
'X-Dynamic': () => 'dynamic',
'X-Async': async () => 'async-value'
})
}
headerRegistry.registerHeaderProvider(provider)
const context: HeaderProviderContext = {
url: 'https://api.example.com',
method: 'GET'
}
const headers = await headerRegistry.getHeaders(context)
expect(headers).toEqual({
'X-Static': 'static',
'X-Dynamic': 'dynamic',
'X-Async': 'async-value'
})
})
it('should handle async providers', async () => {
const provider: IHeaderProvider = {
provideHeaders: vi.fn().mockImplementation(async () => {
await new Promise((resolve) => setTimeout(resolve, 10))
return { 'X-Async': 'resolved' }
})
}
headerRegistry.registerHeaderProvider(provider)
const context: HeaderProviderContext = {
url: 'https://api.example.com',
method: 'GET'
}
const headers = await headerRegistry.getHeaders(context)
expect(headers).toEqual({ 'X-Async': 'resolved' })
})
it('should apply filters when provided', async () => {
const provider1: IHeaderProvider = {
provideHeaders: vi.fn().mockReturnValue({ 'X-Api': 'api-header' })
}
const provider2: IHeaderProvider = {
provideHeaders: vi.fn().mockReturnValue({ 'X-Other': 'other-header' })
}
// Only apply to API URLs
headerRegistry.registerHeaderProvider(provider1, {
filter: (ctx) => ctx.url.includes('/api/')
})
// Apply to all URLs
headerRegistry.registerHeaderProvider(provider2)
const apiContext: HeaderProviderContext = {
url: 'https://example.com/api/users',
method: 'GET'
}
const otherContext: HeaderProviderContext = {
url: 'https://example.com/assets/image.png',
method: 'GET'
}
const apiHeaders = await headerRegistry.getHeaders(apiContext)
const otherHeaders = await headerRegistry.getHeaders(otherContext)
expect(apiHeaders).toEqual({
'X-Api': 'api-header',
'X-Other': 'other-header'
})
expect(otherHeaders).toEqual({
'X-Other': 'other-header'
})
})
it('should continue with other providers if one fails', async () => {
const provider1: IHeaderProvider = {
provideHeaders: vi.fn().mockRejectedValue(new Error('Provider error'))
}
const provider2: IHeaderProvider = {
provideHeaders: vi.fn().mockReturnValue({ 'X-Header': 'value' })
}
headerRegistry.registerHeaderProvider(provider1)
headerRegistry.registerHeaderProvider(provider2)
const context: HeaderProviderContext = {
url: 'https://api.example.com',
method: 'GET'
}
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
const headers = await headerRegistry.getHeaders(context)
expect(headers).toEqual({ 'X-Header': 'value' })
expect(consoleSpy).toHaveBeenCalledWith(
expect.stringContaining('Error getting headers from provider'),
expect.any(Error)
)
consoleSpy.mockRestore()
})
})
describe('clear', () => {
it('should remove all providers', () => {
const provider1: IHeaderProvider = {
provideHeaders: vi.fn()
}
const provider2: IHeaderProvider = {
provideHeaders: vi.fn()
}
headerRegistry.registerHeaderProvider(provider1)
headerRegistry.registerHeaderProvider(provider2)
expect(headerRegistry.providerCount).toBe(2)
headerRegistry.clear()
expect(headerRegistry.providerCount).toBe(0)
})
})
describe('providerCount', () => {
it('should return the correct count of providers', () => {
expect(headerRegistry.providerCount).toBe(0)
const provider: IHeaderProvider = {
provideHeaders: vi.fn()
}
const reg1 = headerRegistry.registerHeaderProvider(provider)
expect(headerRegistry.providerCount).toBe(1)
const reg2 = headerRegistry.registerHeaderProvider(provider)
expect(headerRegistry.providerCount).toBe(2)
reg1.dispose()
expect(headerRegistry.providerCount).toBe(1)
reg2.dispose()
expect(headerRegistry.providerCount).toBe(0)
})
})
})