mirror of
https://github.com/portainer/portainer.git
synced 2025-07-25 00:09:40 +02:00
feat(helm): enhance helm chart install [r8s-341] (#766)
This commit is contained in:
parent
caac45b834
commit
a9061e5258
29 changed files with 864 additions and 562 deletions
174
app/react/kubernetes/helm/HelmTemplates/HelmInstallForm.test.tsx
Normal file
174
app/react/kubernetes/helm/HelmTemplates/HelmInstallForm.test.tsx
Normal file
|
@ -0,0 +1,174 @@
|
|||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { vi } from 'vitest';
|
||||
|
||||
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 { Chart } from '../types';
|
||||
|
||||
import { HelmInstallForm } from './HelmInstallForm';
|
||||
|
||||
const mockMutate = vi.fn();
|
||||
const mockNotifySuccess = vi.fn();
|
||||
const mockTrackEvent = vi.fn();
|
||||
const mockRouterGo = vi.fn();
|
||||
|
||||
// Mock the router hook to provide endpointId
|
||||
vi.mock('@uirouter/react', async (importOriginal: () => Promise<object>) => ({
|
||||
...(await importOriginal()),
|
||||
useCurrentStateAndParams: vi.fn(() => ({
|
||||
params: { endpointId: '1' },
|
||||
})),
|
||||
useRouter: vi.fn(() => ({
|
||||
stateService: {
|
||||
go: vi.fn((...args) => mockRouterGo(...args)),
|
||||
},
|
||||
})),
|
||||
}));
|
||||
|
||||
// Mock dependencies
|
||||
vi.mock('@/portainer/services/notifications', () => ({
|
||||
notifySuccess: vi.fn((title: string, text: string) =>
|
||||
mockNotifySuccess(title, text)
|
||||
),
|
||||
}));
|
||||
|
||||
vi.mock('../queries/useUpdateHelmReleaseMutation', () => ({
|
||||
useUpdateHelmReleaseMutation: vi.fn(() => ({
|
||||
mutateAsync: vi.fn((...args) => mockMutate(...args)),
|
||||
isLoading: false,
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock('../queries/useHelmRepositories', () => ({
|
||||
useHelmRepoVersions: vi.fn(() => ({
|
||||
data: [
|
||||
{ Version: '1.0.0', AppVersion: '1.0.0' },
|
||||
{ Version: '0.9.0', AppVersion: '0.9.0' },
|
||||
],
|
||||
isInitialLoading: false,
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock('./queries/useHelmChartValues', () => ({
|
||||
useHelmChartValues: vi.fn().mockReturnValue({
|
||||
data: { values: 'test-values' },
|
||||
isInitialLoading: false,
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock('@/react/hooks/useAnalytics', () => ({
|
||||
useAnalytics: vi.fn().mockReturnValue({
|
||||
trackEvent: vi.fn((...args) => mockTrackEvent(...args)),
|
||||
}),
|
||||
}));
|
||||
|
||||
// Sample test data
|
||||
const mockChart: Chart = {
|
||||
name: 'test-chart',
|
||||
description: 'Test Chart Description',
|
||||
repo: 'https://example.com',
|
||||
icon: 'test-icon-url',
|
||||
annotations: {
|
||||
category: 'database',
|
||||
},
|
||||
};
|
||||
|
||||
const mockRouterStateService = {
|
||||
go: vi.fn(),
|
||||
};
|
||||
|
||||
function renderComponent({
|
||||
selectedChart = mockChart,
|
||||
namespace = 'test-namespace',
|
||||
name = 'test-name',
|
||||
isAdmin = true,
|
||||
} = {}) {
|
||||
const user = new UserViewModel({ Username: 'user', Role: isAdmin ? 1 : 2 });
|
||||
|
||||
const Wrapped = withTestQueryProvider(
|
||||
withUserProvider(
|
||||
withTestRouter(() => (
|
||||
<HelmInstallForm
|
||||
selectedChart={selectedChart}
|
||||
namespace={namespace}
|
||||
name={name}
|
||||
/>
|
||||
)),
|
||||
user
|
||||
)
|
||||
);
|
||||
|
||||
return {
|
||||
...render(<Wrapped />),
|
||||
user,
|
||||
mockRouterStateService,
|
||||
};
|
||||
}
|
||||
|
||||
describe('HelmInstallForm', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should render the form with version selector and values editor', async () => {
|
||||
renderComponent();
|
||||
|
||||
expect(screen.getByText('Version')).toBeInTheDocument();
|
||||
expect(screen.getByText('Install')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should install helm chart when install button is clicked', async () => {
|
||||
const user = userEvent.setup();
|
||||
renderComponent();
|
||||
|
||||
const installButton = screen.getByText('Install');
|
||||
await user.click(installButton);
|
||||
|
||||
// Check mutate was called with correct values
|
||||
expect(mockMutate).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
name: 'test-name',
|
||||
repo: 'https://example.com',
|
||||
chart: 'test-chart',
|
||||
values: '',
|
||||
namespace: 'test-namespace',
|
||||
version: '1.0.0',
|
||||
}),
|
||||
expect.objectContaining({ onSuccess: expect.any(Function) })
|
||||
);
|
||||
});
|
||||
|
||||
it('should disable install button when namespace or name is undefined', () => {
|
||||
renderComponent({ namespace: '' });
|
||||
expect(screen.getByText('Install')).toBeDisabled();
|
||||
});
|
||||
|
||||
it('should call success handlers when installation succeeds', async () => {
|
||||
const user = userEvent.setup();
|
||||
renderComponent();
|
||||
|
||||
const installButton = screen.getByText('Install');
|
||||
await user.click(installButton);
|
||||
|
||||
// Get the onSuccess callback and call it
|
||||
const onSuccessCallback = mockMutate.mock.calls[0][1].onSuccess;
|
||||
onSuccessCallback();
|
||||
|
||||
// Check that success handlers were called
|
||||
expect(mockTrackEvent).toHaveBeenCalledWith('kubernetes-helm-install', {
|
||||
category: 'kubernetes',
|
||||
metadata: {
|
||||
'chart-name': 'test-chart',
|
||||
},
|
||||
});
|
||||
expect(mockNotifySuccess).toHaveBeenCalledWith(
|
||||
'Success',
|
||||
'Helm chart successfully installed'
|
||||
);
|
||||
expect(mockRouterGo).toHaveBeenCalledWith('kubernetes.applications');
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue