Resolved timing issues in DNS provider type selection E2E tests (Manual, Webhook, RFC2136, Script) caused by React re-render delays with conditional rendering. Changes: - Simplified field wait strategy in tests/dns-provider-types.spec.ts - Removed intermediate credentials-section wait - Use direct visibility check for provider-specific fields - Reduced timeout from 10s to 5s (sufficient for 2x safety margin) Technical Details: - Root cause: Tests attempted to find fields before React completed state update cycle (setState → re-render → conditional eval) - Firefox SpiderMonkey 2x slower than Chromium V8 (30-50ms vs 10-20ms) - Solution confirms full React cycle by waiting for actual target field Results: - 544/602 E2E tests passing (90%) - All DNS provider tests verified on Chromium - Backend coverage: 85.2% (meets ≥85% threshold) - TypeScript compilation clean - Zero ESLint errors introduced Documentation: - Updated CHANGELOG.md with fix entry - Created docs/reports/e2e_fix_v2_qa_report.md (detailed) - Created docs/reports/e2e_fix_v2_summary.md (quick reference) - Created docs/security/advisory_2026-02-01_base_image_cves.md (7 HIGH CVEs) Related: PR #583, CI run https://github.com/Wikid82/Charon/actions/runs/21558579945
90 lines
2.0 KiB
TypeScript
90 lines
2.0 KiB
TypeScript
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
|
import {
|
|
getPlugins,
|
|
getPlugin,
|
|
enablePlugin,
|
|
disablePlugin,
|
|
reloadPlugins,
|
|
type PluginInfo,
|
|
} from '../api/plugins'
|
|
|
|
/** Query key factory for plugins */
|
|
const queryKeys = {
|
|
all: ['plugins'] as const,
|
|
lists: () => [...queryKeys.all, 'list'] as const,
|
|
list: () => [...queryKeys.lists()] as const,
|
|
details: () => [...queryKeys.all, 'detail'] as const,
|
|
detail: (id: number) => [...queryKeys.details(), id] as const,
|
|
}
|
|
|
|
/**
|
|
* Hook for fetching all plugins.
|
|
* @returns Query result with plugins array
|
|
*/
|
|
export function usePlugins() {
|
|
return useQuery({
|
|
queryKey: queryKeys.list(),
|
|
queryFn: getPlugins,
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Hook for fetching a single plugin.
|
|
* @param id - Plugin ID
|
|
* @returns Query result with plugin data
|
|
*/
|
|
export function usePlugin(id: number) {
|
|
return useQuery({
|
|
queryKey: queryKeys.detail(id),
|
|
queryFn: () => getPlugin(id),
|
|
enabled: id > 0,
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Hook for enabling a plugin.
|
|
* @returns Mutation function for enabling plugins
|
|
*/
|
|
export function useEnablePlugin() {
|
|
const queryClient = useQueryClient()
|
|
|
|
return useMutation({
|
|
mutationFn: (id: number) => enablePlugin(id),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: queryKeys.list() })
|
|
},
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Hook for disabling a plugin.
|
|
* @returns Mutation function for disabling plugins
|
|
*/
|
|
export function useDisablePlugin() {
|
|
const queryClient = useQueryClient()
|
|
|
|
return useMutation({
|
|
mutationFn: (id: number) => disablePlugin(id),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: queryKeys.list() })
|
|
},
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Hook for reloading all plugins.
|
|
* @returns Mutation function for reloading plugins
|
|
*/
|
|
export function useReloadPlugins() {
|
|
const queryClient = useQueryClient()
|
|
|
|
return useMutation({
|
|
mutationFn: reloadPlugins,
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: queryKeys.list() })
|
|
},
|
|
})
|
|
}
|
|
|
|
export type { PluginInfo }
|