mirror of
https://github.com/portainer/portainer.git
synced 2025-07-25 00:09:40 +02:00
chore(app): Migrate helm templates list to react (#492)
This commit is contained in:
parent
58317edb6d
commit
993f69db37
11 changed files with 459 additions and 203 deletions
|
@ -0,0 +1,190 @@
|
|||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
|
||||
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
||||
import { withUserProvider } from '@/react/test-utils/withUserProvider';
|
||||
import { withTestRouter } from '@/react/test-utils/withRouter';
|
||||
import { UserViewModel } from '@/portainer/models/user';
|
||||
|
||||
import { HelmTemplatesList } from './HelmTemplatesList';
|
||||
import { Chart } from './HelmTemplatesListItem';
|
||||
|
||||
// Sample test data
|
||||
const mockCharts: Chart[] = [
|
||||
{
|
||||
name: 'test-chart-1',
|
||||
description: 'Test Chart 1 Description',
|
||||
annotations: {
|
||||
category: 'database',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'test-chart-2',
|
||||
description: 'Test Chart 2 Description',
|
||||
annotations: {
|
||||
category: 'database',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'nginx-chart',
|
||||
description: 'Nginx Web Server',
|
||||
annotations: {
|
||||
category: 'web',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const selectActionMock = vi.fn();
|
||||
|
||||
function renderComponent({
|
||||
loading = false,
|
||||
titleText = 'Test Helm Templates',
|
||||
charts = mockCharts,
|
||||
selectAction = selectActionMock,
|
||||
} = {}) {
|
||||
const user = new UserViewModel({ Username: 'user' });
|
||||
const Wrapped = withTestQueryProvider(
|
||||
withUserProvider(
|
||||
withTestRouter(() => (
|
||||
<HelmTemplatesList
|
||||
loading={loading}
|
||||
titleText={titleText}
|
||||
charts={charts}
|
||||
selectAction={selectAction}
|
||||
/>
|
||||
)),
|
||||
user
|
||||
)
|
||||
);
|
||||
return { ...render(<Wrapped />), user };
|
||||
}
|
||||
|
||||
describe('HelmTemplatesList', () => {
|
||||
beforeEach(() => {
|
||||
selectActionMock.mockClear();
|
||||
});
|
||||
|
||||
it('should display title and charts list', async () => {
|
||||
renderComponent();
|
||||
|
||||
// Check for the title
|
||||
expect(screen.getByText('Test Helm Templates')).toBeInTheDocument();
|
||||
|
||||
// Check for charts
|
||||
expect(screen.getByText('test-chart-1')).toBeInTheDocument();
|
||||
expect(screen.getByText('Test Chart 1 Description')).toBeInTheDocument();
|
||||
expect(screen.getByText('nginx-chart')).toBeInTheDocument();
|
||||
expect(screen.getByText('Nginx Web Server')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should call selectAction when a chart is clicked', async () => {
|
||||
renderComponent();
|
||||
|
||||
// Find the first chart item
|
||||
const firstChartItem = screen.getByText('test-chart-1').closest('button');
|
||||
expect(firstChartItem).not.toBeNull();
|
||||
|
||||
// Click on the chart item
|
||||
if (firstChartItem) {
|
||||
fireEvent.click(firstChartItem);
|
||||
}
|
||||
|
||||
// Check if selectAction was called with the correct chart
|
||||
expect(selectActionMock).toHaveBeenCalledWith(mockCharts[0]);
|
||||
});
|
||||
|
||||
it('should filter charts by text search', async () => {
|
||||
renderComponent();
|
||||
const user = userEvent.setup();
|
||||
|
||||
// Find search input and type "nginx"
|
||||
const searchInput = screen.getByPlaceholderText('Search...');
|
||||
await user.type(searchInput, 'nginx');
|
||||
|
||||
// Wait 300ms for debounce
|
||||
await new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve(undefined);
|
||||
}, 300);
|
||||
});
|
||||
|
||||
// Should show only nginx chart
|
||||
expect(screen.getByText('nginx-chart')).toBeInTheDocument();
|
||||
expect(screen.queryByText('test-chart-1')).not.toBeInTheDocument();
|
||||
expect(screen.queryByText('test-chart-2')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should filter charts by category', async () => {
|
||||
renderComponent();
|
||||
const user = userEvent.setup();
|
||||
|
||||
// Find the category select
|
||||
const categorySelect = screen.getByText('Select a category');
|
||||
await user.click(categorySelect);
|
||||
|
||||
// Select "web" category
|
||||
const webCategory = screen.getByText('web', {
|
||||
selector: '[tabindex="-1"]',
|
||||
});
|
||||
await user.click(webCategory);
|
||||
|
||||
// Should show only web category charts
|
||||
expect(screen.queryByText('nginx-chart')).toBeInTheDocument();
|
||||
expect(screen.queryByText('test-chart-1')).not.toBeInTheDocument();
|
||||
expect(screen.queryByText('test-chart-2')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show loading message when loading prop is true', async () => {
|
||||
renderComponent({ loading: true });
|
||||
|
||||
// Check for loading message
|
||||
expect(screen.getByText('Loading...')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText('Initial download of Helm charts can take a few minutes')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show empty message when no charts are available', async () => {
|
||||
renderComponent({ charts: [] });
|
||||
|
||||
// Check for empty message
|
||||
expect(screen.getByText('No helm charts available.')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show no results message when search has no matches', async () => {
|
||||
renderComponent();
|
||||
const user = userEvent.setup();
|
||||
|
||||
// Find search input and type text that won't match any charts
|
||||
const searchInput = screen.getByPlaceholderText('Search...');
|
||||
await user.type(searchInput, 'nonexistent chart');
|
||||
|
||||
// Wait 300ms for debounce
|
||||
await new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve(undefined);
|
||||
}, 300);
|
||||
});
|
||||
|
||||
// Check for no results message
|
||||
expect(screen.getByText('No Helm charts found')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should handle keyboard navigation and selection', async () => {
|
||||
renderComponent();
|
||||
const user = userEvent.setup();
|
||||
|
||||
// Find the first chart item
|
||||
const firstChartItem = screen.getByText('test-chart-1').closest('button');
|
||||
expect(firstChartItem).not.toBeNull();
|
||||
|
||||
// Focus and press Enter
|
||||
if (firstChartItem) {
|
||||
(firstChartItem as HTMLElement).focus();
|
||||
await user.keyboard('{Enter}');
|
||||
}
|
||||
|
||||
// Check if selectAction was called with the correct chart
|
||||
expect(selectActionMock).toHaveBeenCalledWith(mockCharts[0]);
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue