From fef51d8e48ddbfd39db5d03d540d68ec72ee6bcd Mon Sep 17 00:00:00 2001 From: Cristiano Ventura Date: Tue, 4 Feb 2025 18:26:16 -0800 Subject: [PATCH] internal(Thresholds): Validate and save to Generator file (#446) --- src/schemas/generator/v1/thresholds.ts | 4 +++- src/store/generator/selectors.ts | 3 ++- src/store/generator/slices/thresholds.ts | 20 +++---------------- src/test/factories/generator.ts | 4 +--- src/types/thresholds.ts | 2 ++ .../TestOptions/Thresholds/ThresholdRow.tsx | 20 +++++++++++++++++-- .../TestOptions/Thresholds/Thresholds.tsx | 10 +++++++--- .../Thresholds/Thresholds.utils.ts | 7 +++++-- 8 files changed, 41 insertions(+), 29 deletions(-) diff --git a/src/schemas/generator/v1/thresholds.ts b/src/schemas/generator/v1/thresholds.ts index 4628445b..46cc2c02 100644 --- a/src/schemas/generator/v1/thresholds.ts +++ b/src/schemas/generator/v1/thresholds.ts @@ -44,7 +44,9 @@ export const ThresholdSchema = z.object({ url: z.string().optional(), statistic: ThresholdStatisticSchema, condition: ThresholdConditionSchema, - value: z.number({ message: 'Invalid value' }), + value: z + .number({ message: 'Invalid value' }) + .min(0, { message: 'Invalid value' }), stopTest: z.boolean().default(false), }) diff --git a/src/store/generator/selectors.ts b/src/store/generator/selectors.ts index a3be2a41..5bfc5bf5 100644 --- a/src/store/generator/selectors.ts +++ b/src/store/generator/selectors.ts @@ -49,6 +49,7 @@ export function selectGeneratorData(state: GeneratorStore): GeneratorFileData { allowlist, includeStaticAssets, scriptName, + thresholds, } = state return { @@ -66,7 +67,7 @@ export function selectGeneratorData(state: GeneratorStore): GeneratorFileData { allowlist, includeStaticAssets, scriptName, - thresholds: [], + thresholds, } } diff --git a/src/store/generator/slices/thresholds.ts b/src/store/generator/slices/thresholds.ts index 615adcb1..12b05fd8 100644 --- a/src/store/generator/slices/thresholds.ts +++ b/src/store/generator/slices/thresholds.ts @@ -6,9 +6,7 @@ interface State { } interface Actions { - addThreshold: (threshold: Threshold) => void - updateThreshold: (threshold: Threshold) => void - deleteThreshold: (id: string) => void + setThresholds: (thresholds: Threshold[]) => void } export type ThresholdSliceStore = State & Actions @@ -17,20 +15,8 @@ export const createThresholdSlice: ImmerStateCreator = ( set ) => ({ thresholds: [], - addThreshold: (threshold) => + setThresholds: (thresholds: Threshold[]) => set((state) => { - state.thresholds.push(threshold) - }), - updateThreshold(threshold) { - set((state) => { - const index = state.thresholds.findIndex((t) => t.id === threshold.id) - if (index !== -1) { - state.thresholds[index] = threshold - } - }) - }, - deleteThreshold: (id) => - set((state) => { - state.thresholds = state.thresholds.filter((t) => t.id !== id) + state.thresholds = thresholds }), }) diff --git a/src/test/factories/generator.ts b/src/test/factories/generator.ts index 6487be69..249456d7 100644 --- a/src/test/factories/generator.ts +++ b/src/test/factories/generator.ts @@ -94,9 +94,7 @@ export function createGeneratorState( setVus: vi.fn(), thresholds: [], - addThreshold: vi.fn(), - updateThreshold: vi.fn(), - deleteThreshold: vi.fn(), + setThresholds: vi.fn(), ...state, } diff --git a/src/types/thresholds.ts b/src/types/thresholds.ts index 88267c82..a8d43dff 100644 --- a/src/types/thresholds.ts +++ b/src/types/thresholds.ts @@ -3,8 +3,10 @@ import { ThresholdDataSchema, ThresholdMetricSchema, ThresholdSchema, + ThresholdStatisticSchema, } from '@/schemas/generator' export type Threshold = z.infer export type ThresholdData = z.infer export type ThresholdMetric = z.infer +export type ThresholdStatstic = z.infer diff --git a/src/views/Generator/TestOptions/Thresholds/ThresholdRow.tsx b/src/views/Generator/TestOptions/Thresholds/ThresholdRow.tsx index a2778e01..aeda35d1 100644 --- a/src/views/Generator/TestOptions/Thresholds/ThresholdRow.tsx +++ b/src/views/Generator/TestOptions/Thresholds/ThresholdRow.tsx @@ -1,5 +1,5 @@ import { FieldGroup, ControlledSelect } from '@/components/Form' -import { ThresholdData } from '@/types/thresholds' +import { Threshold, ThresholdData } from '@/types/thresholds' import { TrashIcon } from '@radix-ui/react-icons' import { Table, TextField, Checkbox, IconButton, Flex } from '@radix-ui/themes' import { @@ -17,6 +17,7 @@ import { import { useThresholdURLOptions } from './Thresholds.hooks' import { css } from '@emotion/react' import { useTheme } from '@/hooks/useTheme' +import { useEffect } from 'react' type ThresholdRowProps = { index: number @@ -30,12 +31,26 @@ export function ThresholdRow({ field, index, remove }: ThresholdRowProps) { formState: { errors }, control, watch, + setValue, } = useFormContext() const urlOptions = useThresholdURLOptions() - const threshold = watch('thresholds')[index] + const threshold = watch('thresholds')[index] as Threshold const theme = useTheme() + // Handle selected statistic when the metric field changes + useEffect(() => { + const availableStatistics = getStatisticOptions(threshold.metric).map( + (option) => option.value + ) + if (!availableStatistics.includes(threshold.statistic)) { + const newStatistic = availableStatistics[0] + if (newStatistic) { + setValue(`thresholds.${index}.statistic`, newStatistic) + } + } + }, [threshold.metric, threshold.statistic, index, setValue]) + return ( @@ -115,6 +130,7 @@ export function ThresholdRow({ field, index, remove }: ThresholdRowProps) { name={`thresholds.${index}.stopTest`} render={({ field }) => ( diff --git a/src/views/Generator/TestOptions/Thresholds/Thresholds.tsx b/src/views/Generator/TestOptions/Thresholds/Thresholds.tsx index 9f9ab089..ea75a3ba 100644 --- a/src/views/Generator/TestOptions/Thresholds/Thresholds.tsx +++ b/src/views/Generator/TestOptions/Thresholds/Thresholds.tsx @@ -11,6 +11,7 @@ import { Table } from '@/components/Table' export function Thresholds() { const thresholds = useGeneratorStore((store) => store.thresholds) + const setThresholds = useGeneratorStore((store) => store.setThresholds) const formMethods = useForm<{ thresholds: Threshold[] }>({ resolver: zodResolver(ThresholdDataSchema), @@ -41,9 +42,12 @@ export function Thresholds() { }) } - const onSubmit = useCallback((data: ThresholdData) => { - console.log('onSubmit', data) - }, []) + const onSubmit = useCallback( + (data: ThresholdData) => { + setThresholds(data.thresholds) + }, + [setThresholds] + ) // Submit onChange useEffect(() => { diff --git a/src/views/Generator/TestOptions/Thresholds/Thresholds.utils.ts b/src/views/Generator/TestOptions/Thresholds/Thresholds.utils.ts index 595776da..cbaa19ce 100644 --- a/src/views/Generator/TestOptions/Thresholds/Thresholds.utils.ts +++ b/src/views/Generator/TestOptions/Thresholds/Thresholds.utils.ts @@ -1,5 +1,5 @@ import { ThresholdMetricSchema } from '@/schemas/generator' -import { ThresholdMetric } from '@/types/thresholds' +import { ThresholdMetric, ThresholdStatstic } from '@/types/thresholds' import { exhaustive } from '@/utils/typescript' type ThresholdMetricMap = { @@ -92,7 +92,10 @@ export const THRESHOLD_CONDITIONS_OPTIONS = [ { label: '!==', value: '!==' }, ] -export const getStatisticOptions = (metricName: ThresholdMetric) => { +type StatisticOption = { label: string; value: ThresholdStatstic } +export const getStatisticOptions = ( + metricName: ThresholdMetric +): Array => { const { type } = metricsMap[metricName] switch (type) {