mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-29 18:52:19 +00:00
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>
This commit is contained in:
253
tests-ui/tests/services/headerRegistry.test.ts
Normal file
253
tests-ui/tests/services/headerRegistry.test.ts
Normal file
@@ -0,0 +1,253 @@
|
||||
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)
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user