159 lines
4.7 KiB
TypeScript
159 lines
4.7 KiB
TypeScript
import { render, screen, waitFor } from '@testing-library/react';
|
|
import userEvent from '@testing-library/user-event';
|
|
import { http, HttpResponse } from 'msw';
|
|
import { vi } from 'vitest';
|
|
|
|
import { server } from '@/setup-tests/server';
|
|
import { withTestQueryProvider } from '@/react/test-utils/withTestQuery';
|
|
import { withTestRouter } from '@/react/test-utils/withRouter';
|
|
import { withUserProvider } from '@/react/test-utils/withUserProvider';
|
|
import { createMockStack } from '@/react-tools/test-mocks';
|
|
import { notifyError, notifySuccess } from '@/portainer/services/notifications';
|
|
import { confirmStackUpdate } from '@/react/common/stacks/common/confirm-stack-update';
|
|
|
|
import { EditGitSettingsModal } from './EditGitSettingsModal';
|
|
|
|
vi.mock('@/react/hooks/useEnvironmentId', () => ({
|
|
useEnvironmentId: vi.fn(() => 1),
|
|
}));
|
|
|
|
vi.mock('@/react/common/stacks/common/confirm-stack-update', () => ({
|
|
confirmStackUpdate: vi.fn(),
|
|
}));
|
|
|
|
vi.mock('@/portainer/services/notifications', () => ({
|
|
notifyError: vi.fn(),
|
|
notifySuccess: vi.fn(),
|
|
}));
|
|
|
|
const mockStack = createMockStack({
|
|
Id: 1,
|
|
EndpointId: 1,
|
|
GitConfig: {
|
|
URL: 'https://github.com/test/repo',
|
|
ReferenceName: 'main',
|
|
ConfigFilePath: 'docker-compose.yml',
|
|
ConfigHash: '',
|
|
TLSSkipVerify: false,
|
|
},
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
describe('EditGitSettingsModal', () => {
|
|
test('saves settings only (no redeploy) — calls POST /stacks/{id}/git and shows success notification', async () => {
|
|
const onClose = vi.fn();
|
|
let settingsApiCalled = false;
|
|
let redeployApiCalled = false;
|
|
|
|
server.use(
|
|
http.post('/api/stacks/:id/git', () => {
|
|
settingsApiCalled = true;
|
|
return HttpResponse.json({});
|
|
}),
|
|
http.put('/api/stacks/:id/git/redeploy', () => {
|
|
redeployApiCalled = true;
|
|
return HttpResponse.json({});
|
|
})
|
|
);
|
|
|
|
const user = userEvent.setup();
|
|
renderComponent(onClose);
|
|
|
|
await user.click(screen.getByRole('button', { name: /save settings/i }));
|
|
|
|
await waitFor(() => {
|
|
expect(settingsApiCalled).toBe(true);
|
|
expect(redeployApiCalled).toBe(false);
|
|
expect(notifySuccess).toHaveBeenCalledWith(
|
|
'Success',
|
|
'Stack settings saved successfully'
|
|
);
|
|
expect(onClose).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
test('saves settings and redeploys when Redeploy is checked and confirmed — calls both endpoints and shows deploy success notification', async () => {
|
|
const onClose = vi.fn();
|
|
let settingsApiCalled = false;
|
|
let redeployApiCalled = false;
|
|
|
|
vi.mocked(confirmStackUpdate).mockResolvedValue({
|
|
repullImageAndRedeploy: false,
|
|
});
|
|
|
|
server.use(
|
|
http.post('/api/stacks/:id/git', () => {
|
|
settingsApiCalled = true;
|
|
return HttpResponse.json({});
|
|
}),
|
|
http.put('/api/stacks/:id/git/redeploy', () => {
|
|
redeployApiCalled = true;
|
|
return HttpResponse.json({});
|
|
})
|
|
);
|
|
|
|
const user = userEvent.setup();
|
|
renderComponent(onClose);
|
|
|
|
await user.click(screen.getByRole('checkbox', { name: /redeploy/i }));
|
|
await user.click(screen.getByRole('button', { name: /save settings/i }));
|
|
|
|
await waitFor(() => {
|
|
expect(confirmStackUpdate).toHaveBeenCalled();
|
|
expect(settingsApiCalled).toBe(true);
|
|
expect(redeployApiCalled).toBe(true);
|
|
expect(notifySuccess).toHaveBeenCalledWith(
|
|
'Success',
|
|
'Stack deployed successfully'
|
|
);
|
|
expect(onClose).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
test('shows error notification when settings save succeeds but redeploy fails', async () => {
|
|
const onClose = vi.fn();
|
|
|
|
vi.mocked(confirmStackUpdate).mockResolvedValue({
|
|
repullImageAndRedeploy: false,
|
|
});
|
|
|
|
server.use(
|
|
http.post('/api/stacks/:id/git', () => HttpResponse.json({})),
|
|
http.put('/api/stacks/:id/git/redeploy', () =>
|
|
HttpResponse.json({ message: 'Redeploy failed' }, { status: 500 })
|
|
)
|
|
);
|
|
|
|
const user = userEvent.setup();
|
|
renderComponent(onClose);
|
|
|
|
await user.click(screen.getByRole('checkbox', { name: /redeploy/i }));
|
|
await user.click(screen.getByRole('button', { name: /save settings/i }));
|
|
|
|
await waitFor(() => {
|
|
expect(notifyError).toHaveBeenCalledWith(
|
|
'Failure',
|
|
expect.any(Error),
|
|
'Stack settings saved but redeploy failed'
|
|
);
|
|
expect(onClose).toHaveBeenCalled();
|
|
});
|
|
});
|
|
});
|
|
|
|
function renderComponent(onClose = vi.fn()) {
|
|
server.use(
|
|
http.post('/api/gitops/repo/refs', () => HttpResponse.json([])),
|
|
http.post('/api/gitops/repo/files/search', () => HttpResponse.json([]))
|
|
);
|
|
|
|
const Wrapped = withTestQueryProvider(
|
|
withTestRouter(withUserProvider(EditGitSettingsModal))
|
|
);
|
|
|
|
return render(<Wrapped stack={mockStack} onClose={onClose} />);
|
|
}
|