@arquimedes.co/eureka-forms 3.0.51-test → 3.0.52-test
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/FormSteps/DatePickerStep/DatePickerStep.required.test.d.ts +1 -0
- package/dist/FormSteps/DatePickerStep/DatePickerStep.required.test.js +94 -0
- package/dist/Shared/ErkDatePicker/ErkDatePicker.js +2 -7
- package/dist/Shared/ErkDatePicker/ErkDatePicker.required.test.d.ts +1 -0
- package/dist/Shared/ErkDatePicker/ErkDatePicker.required.test.js +30 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '@testing-library/jest-dom';
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import { render, screen, waitFor } from '@testing-library/react';
|
|
4
|
+
import userEvent from '@testing-library/user-event';
|
|
5
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
6
|
+
import '@testing-library/jest-dom';
|
|
7
|
+
import { Provider } from 'react-redux';
|
|
8
|
+
import { useForm, FormProvider } from 'react-hook-form';
|
|
9
|
+
import { configureStore } from '@reduxjs/toolkit';
|
|
10
|
+
import { EurekaFormsReducer, defaultRootState } from '../../Utils/store';
|
|
11
|
+
import { RootApi } from '../../Utils/_api';
|
|
12
|
+
import FormStepTypes from '../../constants/FormStepTypes';
|
|
13
|
+
import { StoreContext } from '../../Utils/StoreContext';
|
|
14
|
+
import { IdFormContext } from '../../Contexts/FormContext';
|
|
15
|
+
import FormContext from '../../Contexts/FormContext';
|
|
16
|
+
import SectionContext from '../../Contexts/SectionContext';
|
|
17
|
+
import MaterialProviders from '../../Utils/MaterialProviders';
|
|
18
|
+
import InternalFormStyle from '../../constants/InternalFormStyle';
|
|
19
|
+
import DatePickerStep from './DatePickerStep';
|
|
20
|
+
const STORY_FORM_ID = 'STORY_FORM';
|
|
21
|
+
const requiredDateStep = {
|
|
22
|
+
id: 'datepicker-step',
|
|
23
|
+
idSection: 'SECTION_1',
|
|
24
|
+
stepPath: ['datepicker-step'],
|
|
25
|
+
type: FormStepTypes.DATEPICKER,
|
|
26
|
+
label: 'Fecha de nacimiento',
|
|
27
|
+
description: null,
|
|
28
|
+
required: true,
|
|
29
|
+
pickTime: false,
|
|
30
|
+
size: 4,
|
|
31
|
+
editable: true,
|
|
32
|
+
};
|
|
33
|
+
const form = {
|
|
34
|
+
firstSection: 'SECTION_1',
|
|
35
|
+
sections: {
|
|
36
|
+
SECTION_1: { id: 'SECTION_1', name: 'Sección 1', steps: [], nextSection: null },
|
|
37
|
+
},
|
|
38
|
+
steps: { 'datepicker-step': { ...requiredDateStep } },
|
|
39
|
+
confirmationMessage: { blocks: [], entityMap: {} },
|
|
40
|
+
showLink: false,
|
|
41
|
+
size: { blockSize: 200, blockNum: 4, spacingSize: 10 },
|
|
42
|
+
};
|
|
43
|
+
function makeStore() {
|
|
44
|
+
return configureStore({
|
|
45
|
+
reducer: { forms: EurekaFormsReducer, [RootApi.reducerPath]: RootApi.reducer },
|
|
46
|
+
preloadedState: { forms: { [STORY_FORM_ID]: defaultRootState } },
|
|
47
|
+
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(RootApi.middleware),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function Harness({ onValid, pickTime, required = true, onReady, }) {
|
|
51
|
+
const methods = useForm({ mode: 'onTouched' });
|
|
52
|
+
const step = { ...requiredDateStep, required, pickTime: !!pickTime };
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
onReady?.(methods);
|
|
55
|
+
}, [methods, onReady]);
|
|
56
|
+
return (_jsx(MaterialProviders, { formStyle: InternalFormStyle, children: _jsx(Provider, { store: makeStore(), context: StoreContext, children: _jsx(IdFormContext.Provider, { value: STORY_FORM_ID, children: _jsx(FormContext.Provider, { value: form, children: _jsx(SectionContext.Provider, { value: "SECTION_1", children: _jsx(FormProvider, { ...methods, children: _jsxs("form", { onSubmit: (e) => void methods.handleSubmit(onValid)(e), children: [_jsx(DatePickerStep, { step: step, editable: true }), _jsx("button", { type: "submit", children: "Enviar" })] }) }) }) }) }) }) }));
|
|
57
|
+
}
|
|
58
|
+
describe('DatePickerStep required validation', () => {
|
|
59
|
+
it('does not leak a defaultValue Date into the form value on mount', () => {
|
|
60
|
+
let methods;
|
|
61
|
+
render(_jsx(Harness, { onValid: vi.fn(), onReady: (m) => (methods = m) }));
|
|
62
|
+
expect(methods?.getValues('datepicker-step') ?? null).toBeNull();
|
|
63
|
+
});
|
|
64
|
+
it('blocks submit and shows the obligatorio error when a required date is left empty (handleSubmit)', async () => {
|
|
65
|
+
const onValid = vi.fn();
|
|
66
|
+
render(_jsx(Harness, { onValid: onValid }));
|
|
67
|
+
await userEvent.click(screen.getByRole('button', { name: 'Enviar' }));
|
|
68
|
+
await waitFor(() => {
|
|
69
|
+
expect(screen.getByText('Este campo es obligatorio')).toBeInTheDocument();
|
|
70
|
+
});
|
|
71
|
+
expect(onValid).not.toHaveBeenCalled();
|
|
72
|
+
});
|
|
73
|
+
it('reports invalid via trigger() like the real ColumnForm submit path', async () => {
|
|
74
|
+
let methods;
|
|
75
|
+
render(_jsx(Harness, { onValid: vi.fn(), onReady: (m) => (methods = m) }));
|
|
76
|
+
const valid = await methods.trigger(undefined, { shouldFocus: true });
|
|
77
|
+
expect(valid).toBe(false);
|
|
78
|
+
});
|
|
79
|
+
it('pickTime required: trigger() reports invalid when empty', async () => {
|
|
80
|
+
let methods;
|
|
81
|
+
render(_jsx(Harness, { onValid: vi.fn(), pickTime: true, onReady: (m) => (methods = m) }));
|
|
82
|
+
const valid = await methods.trigger(undefined, { shouldFocus: true });
|
|
83
|
+
expect(valid).toBe(false);
|
|
84
|
+
});
|
|
85
|
+
it('control: a NON-required empty date submits (proves the required flag is the deciding factor)', async () => {
|
|
86
|
+
const onValid = vi.fn();
|
|
87
|
+
render(_jsx(Harness, { onValid: onValid, required: false }));
|
|
88
|
+
await userEvent.click(screen.getByRole('button', { name: 'Enviar' }));
|
|
89
|
+
await waitFor(() => {
|
|
90
|
+
expect(onValid).toHaveBeenCalledTimes(1);
|
|
91
|
+
});
|
|
92
|
+
expect(screen.queryByText('Este campo es obligatorio')).not.toBeInTheDocument();
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -170,13 +170,8 @@ function CustomPickerField({ error, required, helperText, size = 'small', labelM
|
|
|
170
170
|
function CustomDatePicker({ error, required, disabled, readOnly, helperText, size = 'small', labelMargin = 5, pickTime = false, inputRef, label,
|
|
171
171
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
172
172
|
orientation: _orientation, ...others }) {
|
|
173
|
-
// MUI X v9 no longer forwards `required` to the field-slot label when the field is a Material
|
|
174
|
-
// TextField (the legacy `slots.field` shape used here), so the required asterisk never renders.
|
|
175
|
-
// The picker's `label` does propagate to the field via the picker context, so bake the marker
|
|
176
|
-
// into the label to keep the required indicator visible.
|
|
177
|
-
const displayLabel = required && typeof label === 'string' ? `${label} *` : label;
|
|
178
173
|
if (pickTime) {
|
|
179
|
-
return (_jsx(StyledDateTimePicker, { ampm: true, size: size, reduceAnimations: true, ...others, label:
|
|
174
|
+
return (_jsx(StyledDateTimePicker, { ampm: true, size: size, reduceAnimations: true, ...others, label: label, disabled: disabled, readOnly: readOnly, showDaysOutsideCurrentMonth: true, slotProps: {
|
|
180
175
|
actionBar: {
|
|
181
176
|
actions: ['clear', 'accept'],
|
|
182
177
|
},
|
|
@@ -236,7 +231,7 @@ orientation: _orientation, ...others }) {
|
|
|
236
231
|
} }));
|
|
237
232
|
}
|
|
238
233
|
else {
|
|
239
|
-
return (_jsx(StyledDatePicker, { ...others, label:
|
|
234
|
+
return (_jsx(StyledDatePicker, { ...others, label: label, size: size, reduceAnimations: true, readOnly: readOnly, disabled: disabled, showDaysOutsideCurrentMonth: true, views: ['year', 'month', 'day'], slotProps: {
|
|
240
235
|
actionBar: {
|
|
241
236
|
actions: ['clear', 'accept'],
|
|
242
237
|
},
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '@testing-library/jest-dom';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
4
|
+
import '@testing-library/jest-dom';
|
|
5
|
+
import MaterialProviders from '../../Utils/MaterialProviders';
|
|
6
|
+
import InternalFormStyle from '../../constants/InternalFormStyle';
|
|
7
|
+
import ErkDatePicker from './ErkDatePicker';
|
|
8
|
+
/**
|
|
9
|
+
* Guards the MUI X v9 regression fix: a `required` date picker must never inject a
|
|
10
|
+
* default value (today's date) into the field. Doing so silently satisfies the
|
|
11
|
+
* required constraint, so an untouched "required" date behaves as if it were filled.
|
|
12
|
+
*/
|
|
13
|
+
describe('ErkDatePicker required behaviour', () => {
|
|
14
|
+
it('does not pre-fill today into a required field (no value provided)', () => {
|
|
15
|
+
render(_jsx(MaterialProviders, { formStyle: InternalFormStyle, children: _jsx(ErkDatePicker, { required: true, label: "Fecha", onChange: vi.fn() }) }));
|
|
16
|
+
const input = document.querySelector('input');
|
|
17
|
+
expect(input?.value).toBe('');
|
|
18
|
+
});
|
|
19
|
+
it('does not pre-fill today into a required date-time field', () => {
|
|
20
|
+
render(_jsx(MaterialProviders, { formStyle: InternalFormStyle, children: _jsx(ErkDatePicker, { required: true, pickTime: true, label: "Fecha y hora", onChange: vi.fn() }) }));
|
|
21
|
+
const input = document.querySelector('input');
|
|
22
|
+
expect(input?.value).toBe('');
|
|
23
|
+
});
|
|
24
|
+
it('renders exactly one required asterisk (no duplicate from a manual marker)', () => {
|
|
25
|
+
render(_jsx(MaterialProviders, { formStyle: InternalFormStyle, children: _jsx(ErkDatePicker, { required: true, label: "Fecha", value: null, onChange: vi.fn() }) }));
|
|
26
|
+
const label = document.querySelector('label')?.textContent ?? '';
|
|
27
|
+
const asterisks = (label.match(/\*/g) ?? []).length;
|
|
28
|
+
expect(asterisks).toBe(1);
|
|
29
|
+
});
|
|
30
|
+
});
|
package/package.json
CHANGED