diff --git a/libs/domains/service-settings/feature/src/lib/service-resources-settings/service-resources-settings/service-resources-settings.spec.tsx b/libs/domains/service-settings/feature/src/lib/service-resources-settings/service-resources-settings/service-resources-settings.spec.tsx index 2255f34e84c..fc3c026de81 100644 --- a/libs/domains/service-settings/feature/src/lib/service-resources-settings/service-resources-settings/service-resources-settings.spec.tsx +++ b/libs/domains/service-settings/feature/src/lib/service-resources-settings/service-resources-settings/service-resources-settings.spec.tsx @@ -1,7 +1,11 @@ import { applicationFactoryMock } from '@qovery/shared/factories' -import { renderWithProviders, screen } from '@qovery/shared/util-tests' +import { fireEvent, renderWithProviders, screen, waitFor } from '@qovery/shared/util-tests' import { ServiceResourcesSettings } from './service-resources-settings' +let mockAdvancedSettings: Record | undefined +const mockEditAdvancedSettings = jest.fn() +const mockEditService = jest.fn() + jest.mock('@tanstack/react-router', () => ({ ...jest.requireActual('@tanstack/react-router'), useParams: () => ({ @@ -13,15 +17,41 @@ jest.mock('@tanstack/react-router', () => ({ jest.mock('@qovery/domains/services/feature', () => ({ ...jest.requireActual('@qovery/domains/services/feature'), - useAdvancedSettings: () => ({ data: undefined }), - useEditAdvancedSettings: () => ({ mutateAsync: jest.fn(), isLoading: false }), - useEditService: () => ({ mutate: jest.fn(), isLoading: false }), - ApplicationSettingsResources: () =>
Resources form
, + useAdvancedSettings: () => ({ data: mockAdvancedSettings }), + useEditAdvancedSettings: () => ({ mutateAsync: mockEditAdvancedSettings, isLoading: false }), + useEditService: () => ({ mutate: mockEditService, isLoading: false }), + ApplicationSettingsResources: ({ displayStableNodepoolToggle }: { displayStableNodepoolToggle?: boolean }) => { + const { setValue, watch } = jest.requireActual('react-hook-form').useFormContext() + const runOnStableNodepool = watch('run_on_stable_nodepool') ?? false + + return ( +
+ Resources form + {displayStableNodepoolToggle && ( + <> + + + )} +
+ ) + }, })) describe('ServiceResourcesSettings', () => { const service = applicationFactoryMock(1)[0] + beforeEach(() => { + mockAdvancedSettings = undefined + mockEditAdvancedSettings.mockReset() + mockEditAdvancedSettings.mockResolvedValue(undefined) + mockEditService.mockReset() + }) + it('should render resources heading and save action', () => { renderWithProviders() @@ -35,4 +65,42 @@ describe('ServiceResourcesSettings', () => { expect(screen.getByTestId('application-settings-resources')).toBeInTheDocument() }) + + it('should render stable nodepool control in the resources form', async () => { + renderWithProviders() + + expect(screen.getByTestId('application-settings-resources')).toContainElement( + screen.getByText('Run on a stable nodepool') + ) + }) + + it('should remove stable nodepool advanced settings when toggle is disabled', async () => { + mockAdvancedSettings = { + 'deployment.affinity.node.required': { + 'karpenter.sh/capacity-type': 'on-demand', + 'karpenter.sh/nodepool': 'stable', + 'kubernetes.io/arch': 'arm64', + }, + } + + renderWithProviders() + + fireEvent.click(screen.getByText('Run on a stable nodepool')) + await waitFor(() => expect(screen.getByRole('button', { name: 'Save' })).toBeEnabled()) + fireEvent.click(screen.getByRole('button', { name: 'Save' })) + + await waitFor(() => { + expect(mockEditAdvancedSettings).toHaveBeenCalledWith({ + serviceId: service.id, + payload: { + serviceType: 'APPLICATION', + 'deployment.affinity.node.required': { + 'kubernetes.io/arch': 'arm64', + }, + 'hpa.cpu.average_utilization_percent': 60, + 'hpa.memory.average_utilization_percent': null, + }, + }) + }) + }) }) diff --git a/libs/domains/service-settings/feature/src/lib/service-resources-settings/service-resources-settings/service-resources-settings.tsx b/libs/domains/service-settings/feature/src/lib/service-resources-settings/service-resources-settings/service-resources-settings.tsx index 9337ba2a7ee..0b77a11741b 100644 --- a/libs/domains/service-settings/feature/src/lib/service-resources-settings/service-resources-settings/service-resources-settings.tsx +++ b/libs/domains/service-settings/feature/src/lib/service-resources-settings/service-resources-settings/service-resources-settings.tsx @@ -21,13 +21,16 @@ import { buildAutoscalingRequestFromForm, buildEditServicePayload, buildHpaAdvancedSettingsPayload, + buildStableNodepoolAdvancedSettingsPayload, loadHpaSettingsFromAdvancedSettings, + loadStableNodepoolFromAdvancedSettings, } from '@qovery/shared/util-services' type ServiceResourcesService = Exclude interface ServiceResourcesFormData extends ApplicationResourcesData { storage_gib?: number + run_on_stable_nodepool?: boolean } export interface ServiceResourcesSettingsProps { @@ -112,6 +115,7 @@ function getDefaultValues( }) .otherwise(() => undefined), ...loadHpaSettingsFromAdvancedSettings(advancedSettings), + run_on_stable_nodepool: loadStableNodepoolFromAdvancedSettings(advancedSettings), ...defaultInstances, } } @@ -147,6 +151,7 @@ function ServiceResourcesSettingsForm({ displayWarningCpu={displayWarningCpu} service={service} advancedSettings={advancedSettings} + displayStableNodepoolToggle />