import { fireEvent, render, screen } from '@testing-library/react'; import React from 'react'; import { describe, expect, it, vi } from 'vitest'; import { IntelGpuContextValue, useIntelGpuContext } from '../api/IntelGpuDataContext'; import { GpuDevicePlugin, IntelGpuNode, IntelGpuPod } from '../api/k8s'; import OverviewPage from './OverviewPage'; vi.mock('@kinvolk/headlamp-plugin/lib/CommonComponents', () => ({ Loader: ({ title }: { title: string }) =>
{title}
, SectionBox: ({ title, children }: { title: string; children?: React.ReactNode }) => (

{title}

{children}
), SectionHeader: ({ title }: { title: string }) =>

{title}

, NameValueTable: ({ rows, }: { rows: Array<{ name: React.ReactNode; value: React.ReactNode }>; }) => (
{rows.map((r, i) => (
{r.name}
{r.value}
))}
), SimpleTable: ({ columns, data, }: { columns: Array<{ label: string; getter: (item: unknown) => React.ReactNode }>; data: unknown[]; }) => ( {columns.map(c => ( ))} {data.map((item, i) => ( {columns.map(c => ( ))} ))}
{c.label}
{c.getter(item)}
), StatusLabel: ({ status, children }: { status: string; children?: React.ReactNode }) => ( {children} ), PercentageBar: () =>
, })); vi.mock('../api/IntelGpuDataContext', () => ({ useIntelGpuContext: vi.fn(), })); function makeContext(overrides: Partial = {}): IntelGpuContextValue { return { devicePlugins: [], pluginInstalled: false, gpuNodes: [], gpuPods: [], pluginPods: [], crdAvailable: false, loading: false, error: null, refresh: vi.fn(), ...overrides, }; } describe('OverviewPage', () => { it('shows loader when loading=true', () => { vi.mocked(useIntelGpuContext).mockReturnValue(makeContext({ loading: true })); render(); expect(screen.getByTestId('loader')).toHaveTextContent('Loading Intel GPU data...'); }); it('shows "Plugin Not Detected" when not loading, no plugin installed, no nodes', () => { vi.mocked(useIntelGpuContext).mockReturnValue( makeContext({ loading: false, pluginInstalled: false, gpuNodes: [] }) ); render(); expect(screen.getByText('Plugin Not Detected')).toBeInTheDocument(); }); it('shows error content when error is set', () => { const errorMsg = 'something went wrong'; vi.mocked(useIntelGpuContext).mockReturnValue( makeContext({ loading: false, error: errorMsg, pluginInstalled: true }) ); render(); expect(screen.getByText(errorMsg)).toBeInTheDocument(); }); it('shows "Intel GPU — Overview" heading when gpuNodes present and pluginInstalled', () => { const node: IntelGpuNode = { metadata: { name: 'gpu-node-1', labels: { 'intel.feature.node.kubernetes.io/gpu': 'true' }, }, status: { capacity: { 'gpu.intel.com/i915': '1' }, allocatable: { 'gpu.intel.com/i915': '1' }, }, }; vi.mocked(useIntelGpuContext).mockReturnValue( makeContext({ loading: false, pluginInstalled: true, gpuNodes: [node] }) ); render(); expect(screen.getByText('Intel GPU — Overview')).toBeInTheDocument(); }); it('calls refresh() when refresh button is clicked', () => { const refresh = vi.fn(); vi.mocked(useIntelGpuContext).mockReturnValue( makeContext({ loading: false, pluginInstalled: true, refresh }) ); render(); fireEvent.click(screen.getByRole('button', { name: /refresh intel gpu data/i })); expect(refresh).toHaveBeenCalledTimes(1); }); it('shows CRD notice when crdAvailable=false and pluginInstalled=true', () => { vi.mocked(useIntelGpuContext).mockReturnValue( makeContext({ loading: false, pluginInstalled: true, crdAvailable: false }) ); render(); expect(screen.getByText('Notice')).toBeInTheDocument(); expect(screen.getByText(/GpuDevicePlugin CRD not found/)).toBeInTheDocument(); }); it('shows "Device Plugin Status" table when crdAvailable=true and devicePlugins present', () => { const plugin: GpuDevicePlugin = { kind: 'GpuDevicePlugin', metadata: { name: 'my-plugin', uid: 'uid-1' }, spec: { enableMonitoring: true, sharedDevNum: 2 }, status: { desiredNumberScheduled: 1, numberReady: 1 }, }; vi.mocked(useIntelGpuContext).mockReturnValue( makeContext({ loading: false, pluginInstalled: true, crdAvailable: true, devicePlugins: [plugin], }) ); render(); expect(screen.getByText('Device Plugin Status')).toBeInTheDocument(); expect(screen.getByText('my-plugin')).toBeInTheDocument(); }); it('shows "Plugin Daemon Pods" table when pluginPods present', () => { const pod: IntelGpuPod = { metadata: { name: 'plugin-pod-1', namespace: 'kube-system', uid: 'uid-pp-1' }, spec: { nodeName: 'node-1' }, status: { phase: 'Running' }, }; vi.mocked(useIntelGpuContext).mockReturnValue( makeContext({ loading: false, pluginInstalled: true, pluginPods: [pod] }) ); render(); expect(screen.getByText('Plugin Daemon Pods')).toBeInTheDocument(); expect(screen.getByText('plugin-pod-1')).toBeInTheDocument(); }); it('shows "Active GPU Pods" table when running GPU pods exist', () => { const pod: IntelGpuPod = { metadata: { name: 'workload-pod-1', namespace: 'default', uid: 'uid-wp-1' }, spec: { nodeName: 'gpu-node-1', containers: [ { name: 'main', resources: { requests: { 'gpu.intel.com/i915': '1' } }, }, ], }, status: { phase: 'Running' }, }; vi.mocked(useIntelGpuContext).mockReturnValue( makeContext({ loading: false, pluginInstalled: true, gpuPods: [pod] }) ); render(); expect(screen.getByText('Active GPU Pods')).toBeInTheDocument(); expect(screen.getByText('workload-pod-1')).toBeInTheDocument(); }); });