portainer/app/react/kubernetes/helm/HelmApplicationView/ChartActions/UpgradeButton.test.tsx

218 lines
5.6 KiB
TypeScript

import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { vi } from 'vitest';
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
import { withTestRouter } from '@/react/test-utils/withRouter';
import { withUserProvider } from '@/react/test-utils/withUserProvider';
import {
useHelmRepoVersions,
ChartVersion,
} from '../../queries/useHelmRepoVersions';
import { HelmRelease } from '../../types';
import { openUpgradeHelmModal } from './UpgradeHelmModal';
import { UpgradeButton } from './UpgradeButton';
// Mock the upgrade modal function
vi.mock('./UpgradeHelmModal', () => ({
openUpgradeHelmModal: vi.fn(() => Promise.resolve(undefined)),
}));
// Mock the notifications service
vi.mock('@/portainer/services/notifications', () => ({
notifySuccess: vi.fn(),
}));
vi.mock('../../queries/useHelmRegistries', () => ({
useHelmRegistries: vi.fn(() => ({
data: ['repo1', 'repo2'],
isInitialLoading: false,
isError: false,
})),
}));
vi.mock('../../queries/useHelmRepoVersions', () => ({
useHelmRepoVersions: vi.fn(),
}));
// Mock the useHelmRelease hook
vi.mock('../queries/useHelmRelease', () => ({
useHelmRelease: vi.fn(() => ({
data: '1.0.0',
})),
}));
// Mock the useUpdateHelmReleaseMutation hook
vi.mock('../../queries/useUpdateHelmReleaseMutation', () => ({
useUpdateHelmReleaseMutation: vi.fn(() => ({
mutate: vi.fn(),
isLoading: false,
})),
}));
function renderButton(props = {}) {
const defaultProps = {
environmentId: 1,
releaseName: 'test-release',
namespace: 'default',
release: {
name: 'test-release',
chart: {
metadata: {
name: 'test-chart',
version: '1.0.0',
},
},
values: {
userSuppliedValues: '{}',
},
manifest: '',
} as HelmRelease,
updateRelease: vi.fn(),
...props,
};
const Wrapped = withTestQueryProvider(
withUserProvider(withTestRouter(UpgradeButton))
);
return render(<Wrapped {...defaultProps} />);
}
describe('UpgradeButton', () => {
beforeEach(() => {
// Set up default mock return values
vi.mocked(useHelmRepoVersions).mockReturnValue({
data: [
{ Version: '1.0.0', Repo: 'stable' },
{ Version: '1.1.0', Repo: 'stable' },
],
isInitialLoading: false,
isError: false,
isFetching: false,
refetch: vi.fn(() => Promise.resolve([])),
});
});
test('should display the upgrade button', () => {
renderButton();
const button = screen.getByRole('button', { name: /Upgrade/i });
expect(button).toBeInTheDocument();
});
test('should be disabled when no versions are available', () => {
const data: ChartVersion[] = [];
vi.mocked(useHelmRepoVersions).mockReturnValue({
data,
isInitialLoading: false,
isError: false,
isFetching: false,
refetch: vi.fn(() => Promise.resolve([])),
});
renderButton();
const button = screen.getByRole('button', { name: /Upgrade/i });
expect(button).toBeDisabled();
});
test('should show loading state when checking for versions', () => {
vi.mocked(useHelmRepoVersions).mockReturnValue({
data: [],
isInitialLoading: true,
isError: false,
isFetching: true,
refetch: vi.fn(() => Promise.resolve([])),
});
renderButton();
expect(
screen.getByText('Checking for new versions...')
).toBeInTheDocument();
});
test('should show "No versions available" when no versions are found', () => {
const data: ChartVersion[] = [];
vi.mocked(useHelmRepoVersions).mockReturnValue({
data,
isInitialLoading: false,
isError: false,
isFetching: false,
refetch: vi.fn(() => Promise.resolve([])),
});
renderButton();
expect(screen.getByText('No versions available')).toBeInTheDocument();
});
test('should open upgrade modal when clicked', async () => {
const user = userEvent.setup();
const mockRelease = {
name: 'test-release',
chart: {
metadata: {
name: 'test-chart',
version: '1.0.0',
},
},
values: {
userSuppliedValues: '{}',
},
manifest: '',
} as HelmRelease;
vi.mocked(useHelmRepoVersions).mockReturnValue({
data: [
{ Version: '1.0.0', Repo: 'stable' },
{ Version: '1.1.0', Repo: 'stable' },
],
isInitialLoading: false,
isError: false,
isFetching: false,
refetch: vi.fn(() => Promise.resolve([])),
});
renderButton({ release: mockRelease });
const button = screen.getByRole('button', { name: /Upgrade/i });
await user.click(button);
await waitFor(() => {
expect(openUpgradeHelmModal).toHaveBeenCalledWith(
expect.objectContaining({
name: 'test-release',
chart: 'test-chart',
namespace: 'default',
values: '{}',
version: '1.0.0',
}),
expect.arrayContaining([
{ Version: '1.0.0', Repo: 'stable' },
{ Version: '1.1.0', Repo: 'stable' },
])
);
});
});
test('should not execute the upgrade if modal is cancelled', async () => {
const mockUpdateRelease = vi.fn();
vi.mocked(openUpgradeHelmModal).mockResolvedValueOnce(undefined);
const user = userEvent.setup();
renderButton({ updateRelease: mockUpdateRelease });
const button = screen.getByRole('button', { name: /Upgrade/i });
await user.click(button);
await waitFor(() => {
expect(openUpgradeHelmModal).toHaveBeenCalled();
});
expect(mockUpdateRelease).not.toHaveBeenCalled();
});
});