Files
Charon/frontend/src/api/plugins.ts
T
GitHub Actions db48daf0e8 test: fix E2E timing for DNS provider field visibility
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
2026-02-01 14:17:58 +00:00

77 lines
2.2 KiB
TypeScript

import client from './client'
/** Plugin status types */
export type PluginStatus = 'pending' | 'loaded' | 'error'
/** Plugin information */
export interface PluginInfo {
id: number
uuid: string
name: string
type: string
enabled: boolean
status: PluginStatus
error?: string
version?: string
author?: string
is_built_in: boolean
description?: string
documentation_url?: string
loaded_at?: string
created_at: string
updated_at: string
}
/**
* Fetches all plugins (built-in and external).
* @returns Promise resolving to array of plugin info
* @throws {AxiosError} If the request fails
*/
export async function getPlugins(): Promise<PluginInfo[]> {
const response = await client.get<PluginInfo[]>('/admin/plugins')
return response.data
}
/**
* Fetches a single plugin by ID.
* @param id - The plugin ID
* @returns Promise resolving to the plugin info
* @throws {AxiosError} If not found or request fails
*/
export async function getPlugin(id: number): Promise<PluginInfo> {
const response = await client.get<PluginInfo>(`/admin/plugins/${id}`)
return response.data
}
/**
* Enables a disabled plugin.
* @param id - The plugin ID
* @returns Promise resolving to success message
* @throws {AxiosError} If not found or request fails
*/
export async function enablePlugin(id: number): Promise<{ message: string }> {
const response = await client.post<{ message: string }>(`/admin/plugins/${id}/enable`)
return response.data
}
/**
* Disables an active plugin.
* @param id - The plugin ID
* @returns Promise resolving to success message
* @throws {AxiosError} If not found, in use, or request fails
*/
export async function disablePlugin(id: number): Promise<{ message: string }> {
const response = await client.post<{ message: string }>(`/admin/plugins/${id}/disable`)
return response.data
}
/**
* Reloads all plugins from the plugin directory.
* @returns Promise resolving to success message and count
* @throws {AxiosError} If request fails
*/
export async function reloadPlugins(): Promise<{ message: string; count: number }> {
const response = await client.post<{ message: string; count: number }>('/admin/plugins/reload')
return response.data
}