import { render, screen } from '@testing-library/react';
import React from 'react';
import { describe, expect, it, vi } from 'vitest';
import { IntelGpuContextValue, useIntelGpuContext } from '../api/IntelGpuDataContext';
import { IntelGpuPod } from '../api/k8s';
import PodsPage from './PodsPage';
vi.mock('@kinvolk/headlamp-plugin/lib/CommonComponents', () => ({
Loader: ({ title }: { title: string }) =>
{title}
,
SectionBox: ({ title, children }: { title: string; children?: React.ReactNode }) => (
),
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 => (
| {c.label} |
))}
{data.map((item, i) => (
{columns.map(c => (
| {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,
};
}
function makeRunningPod(name: string): IntelGpuPod {
return {
metadata: { name, namespace: 'default', uid: `uid-${name}` },
spec: {
nodeName: 'gpu-node-1',
containers: [
{
name: 'main',
resources: { requests: { 'gpu.intel.com/i915': '1' } },
},
],
},
status: { phase: 'Running' },
};
}
function makePendingPod(name: string): IntelGpuPod {
return {
metadata: { name, namespace: 'default', uid: `uid-${name}` },
spec: {
containers: [
{
name: 'main',
resources: { requests: { 'gpu.intel.com/i915': '1' } },
},
],
},
status: {
phase: 'Pending',
containerStatuses: [
{
name: 'main',
ready: false,
restartCount: 0,
state: { waiting: { reason: 'Unschedulable' } },
},
],
},
};
}
describe('PodsPage', () => {
it('shows loader when loading=true', () => {
vi.mocked(useIntelGpuContext).mockReturnValue(makeContext({ loading: true }));
render();
expect(screen.getByTestId('loader')).toHaveTextContent('Loading GPU pod data...');
});
it('shows "No GPU Pods Found" when gpuPods is empty', () => {
vi.mocked(useIntelGpuContext).mockReturnValue(makeContext({ loading: false, gpuPods: [] }));
render();
expect(screen.getByText('No GPU Pods Found')).toBeInTheDocument();
});
it('shows summary section with total count when pods present', () => {
const pods = [makeRunningPod('pod-1'), makeRunningPod('pod-2')];
vi.mocked(useIntelGpuContext).mockReturnValue(makeContext({ loading: false, gpuPods: pods }));
render();
expect(screen.getByText('Summary')).toBeInTheDocument();
// 'Total GPU Pods' label is present; '2' appears in multiple places (row value + status label)
expect(screen.getByText('Total GPU Pods')).toBeInTheDocument();
expect(screen.getAllByText('2').length).toBeGreaterThanOrEqual(1);
});
it('shows "Attention: Pending GPU Pods" section when pending pods exist', () => {
const pods = [makePendingPod('pending-pod-1')];
vi.mocked(useIntelGpuContext).mockReturnValue(makeContext({ loading: false, gpuPods: pods }));
render();
expect(screen.getByText('Attention: Pending GPU Pods')).toBeInTheDocument();
// Pod name appears in both the main "All GPU Pods" table and the pending attention table
expect(screen.getAllByText('pending-pod-1').length).toBeGreaterThanOrEqual(1);
});
it('shows error section when error is set', () => {
vi.mocked(useIntelGpuContext).mockReturnValue(
makeContext({ loading: false, error: 'pod list failed', gpuPods: [] })
);
render();
expect(screen.getByText('pod list failed')).toBeInTheDocument();
});
it('shows "All GPU Pods" table with pod name when pods present', () => {
const pods = [makeRunningPod('my-workload')];
vi.mocked(useIntelGpuContext).mockReturnValue(makeContext({ loading: false, gpuPods: pods }));
render();
expect(screen.getByText('All GPU Pods')).toBeInTheDocument();
expect(screen.getByText('my-workload')).toBeInTheDocument();
});
});