mirror of
https://github.com/lukaszraczylo/traefik-llmgateway.git
synced 2026-10-15 05:29:28 +00:00
fix(webui): shared sort header, coherent group sorting, real expand-state tests
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import {
|
||||
type ExpandState,
|
||||
clearExpandOverrides,
|
||||
computeExpandedProviders,
|
||||
toggleProviderExpand,
|
||||
} from './provider-expand'
|
||||
|
||||
/** newState is a fresh ExpandState — every test starts from an empty, un-searched panel. */
|
||||
function newState(): ExpandState {
|
||||
return { manuallyExpanded: new Set(), manuallyCollapsed: new Set() }
|
||||
}
|
||||
|
||||
describe('computeExpandedProviders', () => {
|
||||
it('returns manuallyExpanded verbatim when there is no active query', () => {
|
||||
const state = newState()
|
||||
state.manuallyExpanded.add('openai')
|
||||
expect(computeExpandedProviders(state, false, ['openai', 'anthropic'])).toEqual(new Set(['openai']))
|
||||
})
|
||||
|
||||
it('auto-expands every matching name while a query is active', () => {
|
||||
const state = newState()
|
||||
expect(computeExpandedProviders(state, true, ['openai', 'anthropic'])).toEqual(new Set(['openai', 'anthropic']))
|
||||
})
|
||||
|
||||
it('unions manuallyExpanded with matches while a query is active', () => {
|
||||
const state = newState()
|
||||
state.manuallyExpanded.add('gemini') // manually opened before the search started, does not match it
|
||||
expect(computeExpandedProviders(state, true, ['openai'])).toEqual(new Set(['gemini', 'openai']))
|
||||
})
|
||||
|
||||
it('suppresses an auto-match the user explicitly collapsed', () => {
|
||||
const state = newState()
|
||||
state.manuallyCollapsed.add('openai')
|
||||
expect(computeExpandedProviders(state, true, ['openai', 'anthropic'])).toEqual(new Set(['anthropic']))
|
||||
})
|
||||
})
|
||||
|
||||
describe('toggleProviderExpand', () => {
|
||||
it('opening (currentlyExpanded=false) adds to manuallyExpanded and clears any collapse override', () => {
|
||||
const state = newState()
|
||||
state.manuallyCollapsed.add('openai')
|
||||
toggleProviderExpand(state, 'openai', false)
|
||||
expect(state.manuallyExpanded.has('openai')).toBe(true)
|
||||
expect(state.manuallyCollapsed.has('openai')).toBe(false)
|
||||
})
|
||||
|
||||
it('closing (currentlyExpanded=true) removes from manuallyExpanded and adds a collapse override', () => {
|
||||
const state = newState()
|
||||
state.manuallyExpanded.add('openai')
|
||||
toggleProviderExpand(state, 'openai', true)
|
||||
expect(state.manuallyExpanded.has('openai')).toBe(false)
|
||||
expect(state.manuallyCollapsed.has('openai')).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('clearExpandOverrides', () => {
|
||||
it('drops manuallyCollapsed but leaves manuallyExpanded untouched', () => {
|
||||
const state = newState()
|
||||
state.manuallyExpanded.add('openai')
|
||||
state.manuallyCollapsed.add('anthropic')
|
||||
clearExpandOverrides(state)
|
||||
expect(state.manuallyCollapsed.size).toBe(0)
|
||||
expect(state.manuallyExpanded.has('openai')).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('the review-flagged sequence: an auto-matched (never manually opened) provider, clicked closed', () => {
|
||||
it('never enters manuallyExpanded, and stays collapsed after the query clears', () => {
|
||||
const state = newState()
|
||||
const matches = ['openai']
|
||||
|
||||
// 1. Search starts matching "openai" — it shows via auto-expand only,
|
||||
// manuallyExpanded is still empty.
|
||||
let expanded = computeExpandedProviders(state, true, matches)
|
||||
expect(expanded.has('openai')).toBe(true)
|
||||
expect(state.manuallyExpanded.has('openai')).toBe(false)
|
||||
|
||||
// 2. User clicks it closed while it's only auto-expanded. The RAW bug
|
||||
// this module exists to fix: reading manuallyExpanded.has('openai')
|
||||
// directly (false) would have ADDED it to manuallyExpanded instead
|
||||
// of suppressing the auto-expand. toggleProviderExpand takes the
|
||||
// EFFECTIVE current state (expanded.has('openai') === true) instead.
|
||||
toggleProviderExpand(state, 'openai', expanded.has('openai'))
|
||||
expect(state.manuallyExpanded.has('openai')).toBe(false)
|
||||
expect(state.manuallyCollapsed.has('openai')).toBe(true)
|
||||
|
||||
// 3. Still searching: the override suppresses the auto-expand.
|
||||
expanded = computeExpandedProviders(state, true, matches)
|
||||
expect(expanded.has('openai')).toBe(false)
|
||||
|
||||
// 4. Query clears: a stale override must never carry into a later,
|
||||
// unrelated search.
|
||||
clearExpandOverrides(state)
|
||||
expanded = computeExpandedProviders(state, false, [])
|
||||
expect(expanded.has('openai')).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('a provider manually opened before search, still matches, clicked closed during search', () => {
|
||||
it("the user's in-search click wins, and it stays closed after the query clears too", () => {
|
||||
const state = newState()
|
||||
state.manuallyExpanded.add('openai') // opened before any search existed
|
||||
const matches = ['openai']
|
||||
|
||||
let expanded = computeExpandedProviders(state, true, matches)
|
||||
expect(expanded.has('openai')).toBe(true)
|
||||
|
||||
toggleProviderExpand(state, 'openai', expanded.has('openai'))
|
||||
expect(state.manuallyExpanded.has('openai')).toBe(false)
|
||||
expect(state.manuallyCollapsed.has('openai')).toBe(true)
|
||||
|
||||
clearExpandOverrides(state)
|
||||
expanded = computeExpandedProviders(state, false, [])
|
||||
expect(expanded.has('openai')).toBe(false)
|
||||
})
|
||||
})
|
||||
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Pure expand/collapse state for OverviewView.vue's provider-model
|
||||
* accordion, extracted out of the component so the exact toggle sequence
|
||||
* a review flagged (see toggleProviderExpand's own comment) is checkable
|
||||
* in isolation, without mounting Vue.
|
||||
* a review flagged (see toggleProviderExpand's own comment) is tested in
|
||||
* isolation, without mounting Vue — see provider-expand.spec.ts (vitest),
|
||||
* which exercises this module directly, including the full flagged
|
||||
* sequence.
|
||||
*
|
||||
* Two sets track state:
|
||||
* - manuallyExpanded: providers the user explicitly opened, independent
|
||||
|
||||
Reference in New Issue
Block a user