Skip to content

Commit 2aa06af

Browse files
upcoming: [DI-24238] - UI changes to Create/Edit form (linode#11963)
* upcoming: [DI-24238] - UI changes to Create/Edit form * upcoming: [DI-23238] - Added changeset --------- Co-authored-by: venkatmano-akamai <vmangalr@akamai.com>
1 parent 77d5135 commit 2aa06af

File tree

9 files changed

+100
-31
lines changed

9 files changed

+100
-31
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/manager": Upcoming Features
3+
---
4+
5+
UI bugfixes: Resetting Trigger Occurences, Resources values when service type is cleared, Disabling Trigger Occurences, Threshold values unless Service Type is selected. Added Max value for Trigger Occurences and Threshold TextField components ([#11963](https://github.com/linode/manager/pull/11963))

packages/manager/src/features/CloudPulse/Alerts/CreateAlert/CreateAlertDefinition.test.tsx

Lines changed: 79 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import * as React from 'react';
55
import { renderWithTheme } from 'src/utilities/testHelpers';
66

77
import { CreateAlertDefinition } from './CreateAlertDefinition';
8+
89
vi.mock('src/queries/cloudpulse/resources', () => ({
910
...vi.importActual('src/queries/cloudpulse/resources'),
1011
useResourcesQuery: queryMocks.useResourcesQuery,
@@ -16,12 +17,29 @@ vi.mock('@linode/queries', async (importOriginal) => ({
1617
}));
1718

1819
const queryMocks = vi.hoisted(() => ({
20+
useCloudPulseServiceTypes: vi.fn().mockReturnValue({}),
21+
useGetCloudPulseMetricDefinitionsByServiceType: vi.fn().mockReturnValue({}),
1922
useRegionsQuery: vi.fn(),
2023
useResourcesQuery: vi.fn(),
2124
}));
2225

26+
vi.mock('src/queries/cloudpulse/services', async () => {
27+
const actual = await vi.importActual('src/queries/cloudpulse/services');
28+
return {
29+
...actual,
30+
useCloudPullMetricDefinitionsByServiceType:
31+
queryMocks.useGetCloudPulseMetricDefinitionsByServiceType,
32+
useCloudPulseServiceTypes: queryMocks.useCloudPulseServiceTypes,
33+
};
34+
});
35+
2336
beforeEach(() => {
2437
Element.prototype.scrollIntoView = vi.fn();
38+
queryMocks.useGetCloudPulseMetricDefinitionsByServiceType.mockReturnValue({
39+
data: [],
40+
isError: false,
41+
isLoading: false,
42+
});
2543
queryMocks.useResourcesQuery.mockReturnValue({
2644
data: [],
2745
isError: false,
@@ -32,6 +50,12 @@ beforeEach(() => {
3250
isError: false,
3351
isFetching: false,
3452
});
53+
queryMocks.useCloudPulseServiceTypes.mockReturnValue({
54+
data: { data: [{ label: 'Linode', service_type: 'linode' }] },
55+
isError: false,
56+
isLoading: false,
57+
status: 'success',
58+
});
3559
});
3660

3761
describe('AlertDefinition Create', () => {
@@ -72,37 +96,72 @@ describe('AlertDefinition Create', () => {
7296
expect(specificInput).toHaveAttribute('value', 'text');
7397
});
7498

75-
it('should render client side validation errors', async () => {
99+
queryMocks.useGetCloudPulseMetricDefinitionsByServiceType.mockReturnValue({
100+
data: {
101+
data: [
102+
{
103+
available_aggregate_functions: ['min'],
104+
dimensions: [],
105+
is_alertable: true,
106+
label: 'CPU utilization',
107+
metric: 'system_cpu_utilization_percent',
108+
metric_type: 'gauge',
109+
scrape_interval: '2m',
110+
unit: 'percent',
111+
},
112+
],
113+
},
114+
});
115+
it('should render client side validation errors for threshold and trigger occurences text field', async () => {
116+
const user = userEvent.setup();
117+
const container = renderWithTheme(<CreateAlertDefinition />);
118+
119+
const serviceTypeInput = container.getByPlaceholderText('Select a Service');
120+
await user.click(serviceTypeInput);
121+
122+
await user.click(container.getByText('Linode'));
123+
124+
const dataFieldContainer = container.getByPlaceholderText(
125+
'Select a Data Field'
126+
);
127+
128+
await user.click(dataFieldContainer);
129+
await user.click(container.getByText('CPU utilization'));
130+
131+
const submitButton = container.getByText('Submit');
132+
133+
await user.click(submitButton);
134+
135+
expect(container.getAllByText('Enter a positive value.').length).toBe(2);
136+
137+
const thresholdInput = container.getByLabelText('Threshold');
138+
const triggerOccurrences = container.getByTestId('trigger-occurences');
139+
await user.clear(thresholdInput);
140+
await user.clear(within(triggerOccurrences).getByTestId('textfield-input'));
141+
await user.click(submitButton!);
142+
143+
expect(container.getAllByText('The value should be a number.').length).toBe(
144+
2
145+
);
146+
});
147+
148+
it('should render the client side validation error messages for the form', async () => {
76149
const errorMessage = 'This field is required.';
77150
const user = userEvent.setup();
78151
const container = renderWithTheme(<CreateAlertDefinition />);
79-
const input = container.getByLabelText('Threshold');
152+
153+
const submitButton = container.getByText('Submit');
154+
80155
await user.click(
81156
container.getByRole('button', { name: 'Add dimension filter' })
82157
);
83-
const submitButton = container.getByText('Submit');
158+
84159
await user.click(submitButton!);
85-
expect(container.getAllByText('This field is required.').length).toBe(11);
160+
expect(container.getAllByText(errorMessage).length).toBe(11);
86161
container.getAllByText(errorMessage).forEach((element) => {
87162
expect(element).toBeVisible();
88163
});
89164

90-
await user.clear(input);
91-
await user.type(input, '-3');
92-
await userEvent.click(submitButton!);
93-
94-
expect(
95-
await container.findByText("The value can't be negative.")
96-
).toBeVisible();
97-
98-
await user.clear(input);
99-
await user.type(input, 'sdgf');
100-
await userEvent.click(submitButton!);
101-
102-
expect(
103-
await container.findByText('The value should be a number.')
104-
).toBeInTheDocument();
105-
106165
expect(
107166
await container.findByText(
108167
'At least one notification channel is required.'

packages/manager/src/features/CloudPulse/Alerts/CreateAlert/CreateAlertDefinition.tsx

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -151,16 +151,9 @@ export const CreateAlertDefinition = () => {
151151

152152
const handleServiceTypeChange = React.useCallback(() => {
153153
// Reset the criteria to initial state
154-
setValue('rule_criteria.rules', [
155-
{
156-
aggregate_function: null,
157-
dimension_filters: [],
158-
metric: null,
159-
operator: null,
160-
threshold: 0,
161-
},
162-
]);
154+
setValue('rule_criteria.rules', [{ ...criteriaInitialValues }]);
163155
setValue('entity_ids', []);
156+
setValue('trigger_conditions', triggerConditionInitialValues);
164157
}, [setValue]);
165158

166159
React.useEffect(() => {

packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/Metric.test.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,9 @@ describe('Metric component tests', () => {
222222
),
223223
useFormOptions: {
224224
defaultValues: {
225+
rule_criteria: {
226+
rules: [mockData[0]],
227+
},
225228
serviceType: 'linode',
226229
},
227230
},

packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/Metric.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,10 @@ export const Metric = (props: MetricCriteriaProps) => {
263263
data-qa-metric-threshold={`${name}-threshold`}
264264
data-qa-threshold="threshold"
265265
data-testid="threshold"
266+
disabled={!metricWatcher}
266267
errorText={fieldState.error?.message}
267268
label="Threshold"
269+
max={Number.MAX_SAFE_INTEGER}
268270
min={0}
269271
name={`${name}.threshold`}
270272
noMarginTop

packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/TriggerConditions.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,10 @@ export const TriggerConditions = (props: TriggerConditionProps) => {
173173
}}
174174
data-qa-trigger-occurrences
175175
data-testid="trigger-occurences"
176+
disabled={!serviceTypeWatcher}
176177
errorText={fieldState.error?.message}
177178
label=""
179+
max={Number.MAX_SAFE_INTEGER}
178180
min={0}
179181
name={`${name}.trigger_occurrences`}
180182
noMarginTop

packages/manager/src/features/CloudPulse/Alerts/CreateAlert/GeneralInformation/ServiceTypeSelect.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export const CloudPulseServiceSelect = (
4040
string,
4141
AlertServiceType
4242
>[] => {
43-
return serviceOptions && serviceOptions.data.length > 0
43+
return serviceOptions?.data?.length
4444
? serviceOptions.data.map((service) => ({
4545
label: service.label,
4646
value: service.service_type as AlertServiceType,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/validation": Changed
3+
---
4+
5+
Validation message for threshold field in Metric Threshold ([#11963](https://github.com/linode/manager/pull/11963))

packages/validation/src/cloudpulse.schema.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const metricCriteria = object({
1414
operator: string().required(fieldErrorMessage),
1515
threshold: number()
1616
.required(fieldErrorMessage)
17-
.min(0, "The value can't be negative.")
17+
.positive("Enter a positive value.")
1818
.typeError('The value should be a number.'),
1919
dimension_filters: array().of(dimensionFilters).notRequired(),
2020
});

0 commit comments

Comments
 (0)