mirror of
https://github.com/portainer/portainer.git
synced 2025-07-19 13:29:41 +02:00
fix(k8s-services): avoid rerendering services table [r8s-387] (#832)
This commit is contained in:
parent
8d29b5ae71
commit
303047656e
9 changed files with 216 additions and 99 deletions
|
@ -0,0 +1,148 @@
|
|||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { HttpResponse } from 'msw';
|
||||
|
||||
import { withTestRouter } from '@/react/test-utils/withRouter';
|
||||
import { withUserProvider } from '@/react/test-utils/withUserProvider';
|
||||
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||
import { createMockUsers } from '@/react-tools/test-mocks';
|
||||
import { server, http } from '@/setup-tests/server';
|
||||
|
||||
import { ServicesDatatable } from './ServicesDatatable';
|
||||
|
||||
vi.mock('@/react/hooks/useEnvironmentId', () => ({
|
||||
useEnvironmentId: () => 1,
|
||||
}));
|
||||
|
||||
vi.mock('@/portainer/services/notifications', () => ({
|
||||
notifyError: vi.fn(),
|
||||
notifySuccess: vi.fn(),
|
||||
}));
|
||||
function createMockServices(count: number) {
|
||||
return Array.from({ length: count }, (_, i) => {
|
||||
let namespace = 'default';
|
||||
if (i % 3 === 0) {
|
||||
namespace = 'kube-system';
|
||||
} else if (i % 2 !== 0) {
|
||||
namespace = 'my-namespace';
|
||||
}
|
||||
|
||||
let type = 'ClusterIP';
|
||||
if (i % 4 === 1) {
|
||||
type = 'NodePort';
|
||||
} else if (i % 4 === 2) {
|
||||
type = 'LoadBalancer';
|
||||
} else if (i % 4 === 3) {
|
||||
type = 'ExternalName';
|
||||
}
|
||||
|
||||
return {
|
||||
UID: `service-${i}`,
|
||||
Name: `service-${i}`,
|
||||
Namespace: namespace,
|
||||
Type: type,
|
||||
Ports: [{ Port: 80 + i, TargetPort: 8080 + i, Protocol: 'TCP' }],
|
||||
Selector: { app: `app-${i}` },
|
||||
CreationTimestamp: new Date(Date.now() - i * 1000 * 60).toISOString(),
|
||||
ApplicationOwner: '',
|
||||
Applications: [{ Name: `app-${i}` }],
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const mockServices = createMockServices(4);
|
||||
|
||||
const mockNamespaces = [
|
||||
{
|
||||
Name: 'default',
|
||||
IsSystem: false,
|
||||
Status: 'Active',
|
||||
CreationTimestamp: '2024-01-01T00:00:00Z',
|
||||
},
|
||||
{
|
||||
Name: 'kube-system',
|
||||
IsSystem: true,
|
||||
Status: 'Active',
|
||||
CreationTimestamp: '2024-01-01T00:00:00Z',
|
||||
},
|
||||
{
|
||||
Name: 'my-namespace',
|
||||
IsSystem: false,
|
||||
Status: 'Active',
|
||||
CreationTimestamp: '2024-01-01T00:00:00Z',
|
||||
},
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
server.use(
|
||||
http.get('/api/kubernetes/1/services', () =>
|
||||
HttpResponse.json(mockServices)
|
||||
),
|
||||
http.get('/api/kubernetes/1/namespaces', () =>
|
||||
HttpResponse.json(mockNamespaces)
|
||||
)
|
||||
);
|
||||
});
|
||||
const mockUser = {
|
||||
...createMockUsers(1)[0],
|
||||
PortainerAuthorizations: {
|
||||
K8sAccessSystemNamespaces: true,
|
||||
K8sServiceW: true,
|
||||
},
|
||||
};
|
||||
|
||||
function createTestComponent() {
|
||||
return withTestRouter(
|
||||
withUserProvider(withTestQueryProvider(ServicesDatatable), mockUser),
|
||||
{
|
||||
route: '/kubernetes/services',
|
||||
stateConfig: [
|
||||
{
|
||||
name: 'kubernetes.services',
|
||||
url: '/kubernetes/services',
|
||||
params: { endpointId: '1' },
|
||||
},
|
||||
],
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
describe('ServicesDatatable', () => {
|
||||
it('renders services data correctly', async () => {
|
||||
const TestComponent = createTestComponent();
|
||||
render(<TestComponent />);
|
||||
|
||||
expect(await screen.findByText('service-1')).toBeInTheDocument();
|
||||
expect(screen.getByText('service-2')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should filter system resources correctly when toggled', async () => {
|
||||
const TestComponent = createTestComponent();
|
||||
render(<TestComponent />);
|
||||
|
||||
const settingsButton = screen.getByRole('button', { name: /settings/i });
|
||||
await userEvent.click(settingsButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByText('service-0')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
const systemToggle = await screen.findByTestId('show-system-resources');
|
||||
await userEvent.click(systemToggle);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByText('service-0')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
expect(screen.getByText('service-3')).toBeInTheDocument();
|
||||
expect(screen.getByText('service-1')).toBeInTheDocument();
|
||||
expect(screen.getByText('service-2')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show loading state when data is loading', async () => {
|
||||
const TestComponent = createTestComponent();
|
||||
render(<TestComponent />);
|
||||
|
||||
expect(screen.getByText('Loading...')).toBeInTheDocument();
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue