@wix/patterns-fields 1.107.0 → 1.109.0
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/cjs/components/address/input/address-input.st.css.js +3 -3
- package/dist/cjs/components/address/input/address-input.st.css.js.map +1 -1
- package/dist/cjs/components/audio/actions/actions-menu/actions-menu.st.css.js +3 -3
- package/dist/cjs/components/audio/actions/actions-menu/actions-menu.st.css.js.map +1 -1
- package/dist/cjs/components/audio/audio-field/form-audio-field.st.css.js +4 -4
- package/dist/cjs/components/audio/audio-field/form-audio-field.st.css.js.map +1 -1
- package/dist/cjs/components/audio/audio-player/audio-player.st.css.js +2 -2
- package/dist/cjs/components/audio/audio-player/audio-player.st.css.js.map +1 -1
- package/dist/cjs/components/color-view/cell-color-view.st.css.js +3 -3
- package/dist/cjs/components/color-view/cell-color-view.st.css.js.map +1 -1
- package/dist/cjs/components/color-view/color-view.st.css.js +4 -4
- package/dist/cjs/components/color-view/color-view.st.css.js.map +1 -1
- package/dist/cjs/components/date-input/cell-date-input.js +21 -2
- package/dist/cjs/components/date-input/cell-date-input.js.map +1 -1
- package/dist/cjs/components/date-input/date-picker-internals.js +93 -3
- package/dist/cjs/components/date-input/date-picker-internals.js.map +1 -1
- package/dist/cjs/components/date-input/form-date-input.driver.js +2 -0
- package/dist/cjs/components/date-input/form-date-input.driver.js.map +1 -1
- package/dist/cjs/components/date-input/form-date-input.js +23 -6
- package/dist/cjs/components/date-input/form-date-input.js.map +1 -1
- package/dist/cjs/components/date-input/use-field-value-replacement.js +48 -0
- package/dist/cjs/components/date-input/use-field-value-replacement.js.map +1 -0
- package/dist/cjs/components/datetime-input/form-date-time.driver.js +3 -0
- package/dist/cjs/components/datetime-input/form-date-time.driver.js.map +1 -1
- package/dist/cjs/components/datetime-input/form-date-time.js +61 -24
- package/dist/cjs/components/datetime-input/form-date-time.js.map +1 -1
- package/dist/cjs/components/delete-dialog/delete-dialog.st.css.js +3 -3
- package/dist/cjs/components/delete-dialog/delete-dialog.st.css.js.map +1 -1
- package/dist/cjs/components/document/form-document-field.st.css.js +7 -7
- package/dist/cjs/components/document/form-document-field.st.css.js.map +1 -1
- package/dist/cjs/components/exclamation/exclamation.st.css.js +5 -5
- package/dist/cjs/components/exclamation/exclamation.st.css.js.map +1 -1
- package/dist/cjs/components/highlighted-text/highlighted-text.st.css.js +5 -5
- package/dist/cjs/components/highlighted-text/highlighted-text.st.css.js.map +1 -1
- package/dist/cjs/components/image/thumbnail-replace-overlay.st.css.js +3 -3
- package/dist/cjs/components/image/thumbnail-replace-overlay.st.css.js.map +1 -1
- package/dist/cjs/components/media-control/cell-media-edit-shell.st.css.js +2 -2
- package/dist/cjs/components/media-control/cell-media-edit-shell.st.css.js.map +1 -1
- package/dist/cjs/components/media-control/paste-url-button.st.css.js +4 -4
- package/dist/cjs/components/media-control/paste-url-button.st.css.js.map +1 -1
- package/dist/cjs/components/media-gallery/form-media-gallery-field.st.css.js +10 -10
- package/dist/cjs/components/media-gallery/form-media-gallery-field.st.css.js.map +1 -1
- package/dist/cjs/components/media-image/media-image.st.css.js +4 -4
- package/dist/cjs/components/media-image/media-image.st.css.js.map +1 -1
- package/dist/cjs/components/media-image/overlays/overlay.st.css.js +3 -3
- package/dist/cjs/components/media-image/overlays/overlay.st.css.js.map +1 -1
- package/dist/cjs/components/media-tag/web-media-tag/media-tag.st.css.js +2 -2
- package/dist/cjs/components/media-tag/web-media-tag/media-tag.st.css.js.map +1 -1
- package/dist/cjs/components/multi-document/cell-multi-document-edit.st.css.js +3 -3
- package/dist/cjs/components/multi-document/cell-multi-document-edit.st.css.js.map +1 -1
- package/dist/cjs/components/multi-document/multi-document-input/form-multi-document.st.css.js +5 -5
- package/dist/cjs/components/multi-document/multi-document-input/form-multi-document.st.css.js.map +1 -1
- package/dist/cjs/components/reference/cell-multi-reference-input.st.css.js +2 -2
- package/dist/cjs/components/reference/cell-multi-reference-input.st.css.js.map +1 -1
- package/dist/cjs/components/reference/cell-reference-input.st.css.js +3 -3
- package/dist/cjs/components/reference/cell-reference-input.st.css.js.map +1 -1
- package/dist/cjs/components/rich-content/rich-content-input/default-value-input/rich-content-default-value-input.st.css.js +4 -4
- package/dist/cjs/components/rich-content/rich-content-input/default-value-input/rich-content-default-value-input.st.css.js.map +1 -1
- package/dist/cjs/components/rich-content/rich-content-input/form-input/rich-content-form-input.st.css.js +3 -3
- package/dist/cjs/components/rich-content/rich-content-input/form-input/rich-content-form-input.st.css.js.map +1 -1
- package/dist/cjs/components/rich-content/rich-content-input/form-read-only-input/rich-content-form-read-only-input.st.css.js +2 -2
- package/dist/cjs/components/rich-content/rich-content-input/form-read-only-input/rich-content-form-read-only-input.st.css.js.map +1 -1
- package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/fullscreen-modal/fullscreen-modal.st.css.js +3 -3
- package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/fullscreen-modal/fullscreen-modal.st.css.js.map +1 -1
- package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/publish-loader/publish-loader.st.css.js +3 -3
- package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/publish-loader/publish-loader.st.css.js.map +1 -1
- package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/toggle-fullscreen-button/toggle-fullscreen-button.st.css.js +2 -2
- package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/toggle-fullscreen-button/toggle-fullscreen-button.st.css.js.map +1 -1
- package/dist/cjs/components/rich-content/rich-content-input/rich-content-editor/rich-content-editor.st.css.js +7 -7
- package/dist/cjs/components/rich-content/rich-content-input/rich-content-editor/rich-content-editor.st.css.js.map +1 -1
- package/dist/cjs/components/rich-content/rich-content-input/rich-content-editor/rich-content-toolbar.st.css.js +5 -5
- package/dist/cjs/components/rich-content/rich-content-input/rich-content-editor/rich-content-toolbar.st.css.js.map +1 -1
- package/dist/cjs/components/rich-content/rich-content-input/rich-content-viewer/rich-content-viewer.st.css.js +4 -4
- package/dist/cjs/components/rich-content/rich-content-input/rich-content-viewer/rich-content-viewer.st.css.js.map +1 -1
- package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/rich-editor.st.css.js +18 -18
- package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/rich-editor.st.css.js.map +1 -1
- package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/rich-text-editor.st.css.js +4 -4
- package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/rich-text-editor.st.css.js.map +1 -1
- package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.js +18 -18
- package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.js.map +1 -1
- package/dist/cjs/components/text/form-short-text.js +1 -1
- package/dist/cjs/components/text/form-short-text.js.map +1 -1
- package/dist/cjs/components/text/text-view.st.css.js +3 -3
- package/dist/cjs/components/text/text-view.st.css.js.map +1 -1
- package/dist/cjs/styles.global.css +1 -1
- package/dist/esm/components/address/input/address-input.st.css.js +2 -2
- package/dist/esm/components/audio/actions/actions-menu/actions-menu.st.css.js +2 -2
- package/dist/esm/components/audio/actions/actions-menu/actions-menu.st.css.js.map +1 -1
- package/dist/esm/components/audio/audio-field/form-audio-field.st.css.js +2 -2
- package/dist/esm/components/audio/audio-field/form-audio-field.st.css.js.map +1 -1
- package/dist/esm/components/audio/audio-player/audio-player.st.css.js +2 -2
- package/dist/esm/components/color-view/cell-color-view.st.css.js +2 -2
- package/dist/esm/components/color-view/cell-color-view.st.css.js.map +1 -1
- package/dist/esm/components/color-view/color-view.st.css.js +2 -2
- package/dist/esm/components/color-view/color-view.st.css.js.map +1 -1
- package/dist/esm/components/date-input/cell-date-input.js +21 -2
- package/dist/esm/components/date-input/cell-date-input.js.map +1 -1
- package/dist/esm/components/date-input/date-picker-internals.js +67 -0
- package/dist/esm/components/date-input/date-picker-internals.js.map +1 -1
- package/dist/esm/components/date-input/form-date-input.driver.js +2 -0
- package/dist/esm/components/date-input/form-date-input.driver.js.map +1 -1
- package/dist/esm/components/date-input/form-date-input.js +25 -4
- package/dist/esm/components/date-input/form-date-input.js.map +1 -1
- package/dist/esm/components/date-input/use-field-value-replacement.js +48 -0
- package/dist/esm/components/date-input/use-field-value-replacement.js.map +1 -0
- package/dist/esm/components/datetime-input/form-date-time.driver.js +3 -0
- package/dist/esm/components/datetime-input/form-date-time.driver.js.map +1 -1
- package/dist/esm/components/datetime-input/form-date-time.js +51 -21
- package/dist/esm/components/datetime-input/form-date-time.js.map +1 -1
- package/dist/esm/components/delete-dialog/delete-dialog.st.css.js +2 -2
- package/dist/esm/components/delete-dialog/delete-dialog.st.css.js.map +1 -1
- package/dist/esm/components/document/form-document-field.st.css.js +2 -2
- package/dist/esm/components/exclamation/exclamation.st.css.js +2 -2
- package/dist/esm/components/highlighted-text/highlighted-text.st.css.js +3 -3
- package/dist/esm/components/image/thumbnail-replace-overlay.st.css.js +2 -2
- package/dist/esm/components/media-control/cell-media-edit-shell.st.css.js +2 -2
- package/dist/esm/components/media-control/cell-media-edit-shell.st.css.js.map +1 -1
- package/dist/esm/components/media-control/paste-url-button.st.css.js +2 -2
- package/dist/esm/components/media-gallery/form-media-gallery-field.st.css.js +2 -2
- package/dist/esm/components/media-image/media-image.st.css.js +3 -3
- package/dist/esm/components/media-image/overlays/overlay.st.css.js +2 -2
- package/dist/esm/components/media-tag/web-media-tag/media-tag.st.css.js +2 -2
- package/dist/esm/components/multi-document/cell-multi-document-edit.st.css.js +2 -2
- package/dist/esm/components/multi-document/multi-document-input/form-multi-document.st.css.js +2 -2
- package/dist/esm/components/multi-document/multi-document-input/form-multi-document.st.css.js.map +1 -1
- package/dist/esm/components/reference/cell-multi-reference-input.st.css.js +2 -2
- package/dist/esm/components/reference/cell-reference-input.st.css.js +2 -2
- package/dist/esm/components/reference/cell-reference-input.st.css.js.map +1 -1
- package/dist/esm/components/rich-content/rich-content-input/default-value-input/rich-content-default-value-input.st.css.js +2 -2
- package/dist/esm/components/rich-content/rich-content-input/default-value-input/rich-content-default-value-input.st.css.js.map +1 -1
- package/dist/esm/components/rich-content/rich-content-input/form-input/rich-content-form-input.st.css.js +2 -2
- package/dist/esm/components/rich-content/rich-content-input/form-read-only-input/rich-content-form-read-only-input.st.css.js +2 -2
- package/dist/esm/components/rich-content/rich-content-input/form-read-only-input/rich-content-form-read-only-input.st.css.js.map +1 -1
- package/dist/esm/components/rich-content/rich-content-input/rich-content-common/fullscreen-modal/fullscreen-modal.st.css.js +2 -2
- package/dist/esm/components/rich-content/rich-content-input/rich-content-common/publish-loader/publish-loader.st.css.js +2 -2
- package/dist/esm/components/rich-content/rich-content-input/rich-content-common/toggle-fullscreen-button/toggle-fullscreen-button.st.css.js +2 -2
- package/dist/esm/components/rich-content/rich-content-input/rich-content-editor/rich-content-editor.st.css.js +2 -2
- package/dist/esm/components/rich-content/rich-content-input/rich-content-editor/rich-content-toolbar.st.css.js +2 -2
- package/dist/esm/components/rich-content/rich-content-input/rich-content-viewer/rich-content-viewer.st.css.js +2 -2
- package/dist/esm/components/rich-text/rich-text-input/rich-text-editor/rich-editor.st.css.js +2 -2
- package/dist/esm/components/rich-text/rich-text-input/rich-text-editor/rich-text-editor.st.css.js +2 -2
- package/dist/esm/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.js +2 -2
- package/dist/esm/components/text/form-short-text.js +1 -1
- package/dist/esm/components/text/form-short-text.js.map +1 -1
- package/dist/esm/components/text/text-view.st.css.js +2 -2
- package/dist/esm/components/text/text-view.st.css.js.map +1 -1
- package/dist/esm/styles.global.css +1 -1
- package/dist/types/components/audio/actions/actions-menu/actions-menu.st.css.d.ts.map +1 -1
- package/dist/types/components/audio/audio-field/form-audio-field.st.css.d.ts.map +1 -1
- package/dist/types/components/color-view/cell-color-view.st.css.d.ts.map +1 -1
- package/dist/types/components/color-view/color-view.st.css.d.ts.map +1 -1
- package/dist/types/components/date-input/cell-date-input.d.ts +4 -0
- package/dist/types/components/date-input/cell-date-input.d.ts.map +1 -1
- package/dist/types/components/date-input/date-picker-internals.d.ts +11 -1
- package/dist/types/components/date-input/date-picker-internals.d.ts.map +1 -1
- package/dist/types/components/date-input/form-date-input.d.ts.map +1 -1
- package/dist/types/components/date-input/form-date-input.driver.d.ts +2 -0
- package/dist/types/components/date-input/form-date-input.driver.d.ts.map +1 -1
- package/dist/types/components/date-input/use-field-value-replacement.d.ts +3 -0
- package/dist/types/components/date-input/use-field-value-replacement.d.ts.map +1 -0
- package/dist/types/components/datetime-input/form-date-time.d.ts.map +1 -1
- package/dist/types/components/datetime-input/form-date-time.driver.d.ts +3 -0
- package/dist/types/components/datetime-input/form-date-time.driver.d.ts.map +1 -1
- package/dist/types/components/delete-dialog/delete-dialog.st.css.d.ts.map +1 -1
- package/dist/types/components/media-control/cell-media-edit-shell.st.css.d.ts.map +1 -1
- package/dist/types/components/multi-document/multi-document-input/form-multi-document.st.css.d.ts.map +1 -1
- package/dist/types/components/reference/cell-reference-input.st.css.d.ts.map +1 -1
- package/dist/types/components/rich-content/rich-content-input/default-value-input/rich-content-default-value-input.st.css.d.ts.map +1 -1
- package/dist/types/components/rich-content/rich-content-input/form-read-only-input/rich-content-form-read-only-input.st.css.d.ts.map +1 -1
- package/dist/types/components/text/text-view.st.css.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/__tests__/components/date-input/cell-date-input.spec.tsx +100 -0
- package/src/__tests__/components/date-input/date-picker-internals.spec.tsx +69 -0
- package/src/__tests__/components/date-input/form-date-input.spec.tsx +141 -0
- package/src/__tests__/components/datetime-input/form-date-time.spec.tsx +194 -0
- package/src/__tests__/components/text/form-short-text.spec.tsx +27 -0
- package/src/__tests__/form-field.driver.tsx +31 -3
- package/src/__tests__/hooks/use-field-value-replacement.spec.tsx +68 -0
- package/src/components/address/input/address-input.st.css.ts +2 -2
- package/src/components/audio/actions/actions-menu/actions-menu.st.css.ts +2 -2
- package/src/components/audio/audio-field/form-audio-field.st.css.ts +2 -2
- package/src/components/audio/audio-player/audio-player.st.css.ts +2 -2
- package/src/components/color-view/cell-color-view.st.css.ts +2 -2
- package/src/components/color-view/color-view.st.css.ts +2 -2
- package/src/components/date-input/cell-date-input.tsx +28 -0
- package/src/components/date-input/date-picker-internals.ts +104 -3
- package/src/components/date-input/form-date-input.driver.ts +2 -0
- package/src/components/date-input/form-date-input.tsx +25 -3
- package/src/components/date-input/use-field-value-replacement.ts +63 -0
- package/src/components/datetime-input/form-date-time.driver.ts +3 -0
- package/src/components/datetime-input/form-date-time.tsx +55 -33
- package/src/components/delete-dialog/delete-dialog.st.css.ts +2 -2
- package/src/components/document/form-document-field.st.css.ts +2 -2
- package/src/components/exclamation/exclamation.st.css.ts +2 -2
- package/src/components/highlighted-text/highlighted-text.st.css.ts +3 -3
- package/src/components/image/thumbnail-replace-overlay.st.css.ts +2 -2
- package/src/components/media-control/cell-media-edit-shell.st.css.ts +2 -2
- package/src/components/media-control/paste-url-button.st.css.ts +2 -2
- package/src/components/media-gallery/form-media-gallery-field.st.css.ts +2 -2
- package/src/components/media-image/media-image.st.css.ts +3 -3
- package/src/components/media-image/overlays/overlay.st.css.ts +2 -2
- package/src/components/media-tag/web-media-tag/media-tag.st.css.ts +2 -2
- package/src/components/multi-document/cell-multi-document-edit.st.css.ts +2 -2
- package/src/components/multi-document/multi-document-input/form-multi-document.st.css.ts +2 -2
- package/src/components/reference/cell-multi-reference-input.st.css.ts +2 -2
- package/src/components/reference/cell-reference-input.st.css.ts +2 -2
- package/src/components/rich-content/rich-content-input/default-value-input/rich-content-default-value-input.st.css.ts +2 -2
- package/src/components/rich-content/rich-content-input/form-input/rich-content-form-input.st.css.ts +2 -2
- package/src/components/rich-content/rich-content-input/form-read-only-input/rich-content-form-read-only-input.st.css.ts +2 -2
- package/src/components/rich-content/rich-content-input/rich-content-common/fullscreen-modal/fullscreen-modal.st.css.ts +2 -2
- package/src/components/rich-content/rich-content-input/rich-content-common/publish-loader/publish-loader.st.css.ts +2 -2
- package/src/components/rich-content/rich-content-input/rich-content-common/toggle-fullscreen-button/toggle-fullscreen-button.st.css.ts +2 -2
- package/src/components/rich-content/rich-content-input/rich-content-editor/rich-content-editor.st.css.ts +2 -2
- package/src/components/rich-content/rich-content-input/rich-content-editor/rich-content-toolbar.st.css.ts +2 -2
- package/src/components/rich-content/rich-content-input/rich-content-viewer/rich-content-viewer.st.css.ts +2 -2
- package/src/components/rich-text/rich-text-input/rich-text-editor/rich-editor.st.css.ts +2 -2
- package/src/components/rich-text/rich-text-input/rich-text-editor/rich-text-editor.st.css.ts +2 -2
- package/src/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.ts +2 -2
- package/src/components/text/form-short-text.tsx +1 -1
- package/src/components/text/text-view.st.css.ts +2 -2
- package/src/styles.global.css +1 -1
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import '../../../testkit/test-polyfills';
|
|
2
|
+
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { fireEvent, render } from '@testing-library/react';
|
|
5
|
+
|
|
6
|
+
import { CellDateInput } from '../../../components/date-input/cell-date-input';
|
|
7
|
+
|
|
8
|
+
const setup = (value: Date | null = new Date(2024, 0, 15)) => {
|
|
9
|
+
const onChange = jest.fn();
|
|
10
|
+
const onEmpty = jest.fn();
|
|
11
|
+
const onEnter = jest.fn();
|
|
12
|
+
const { container } = render(
|
|
13
|
+
<CellDateInput
|
|
14
|
+
value={value}
|
|
15
|
+
onChange={onChange}
|
|
16
|
+
onEmpty={onEmpty}
|
|
17
|
+
onEnter={onEnter}
|
|
18
|
+
/>,
|
|
19
|
+
);
|
|
20
|
+
const input = container.querySelector('input')!;
|
|
21
|
+
return { input, onChange, onEmpty, onEnter };
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
describe('CellDateInput', () => {
|
|
25
|
+
it('reports an emptied input through onEmpty instead of emitting a date', () => {
|
|
26
|
+
const { input, onChange, onEmpty } = setup();
|
|
27
|
+
|
|
28
|
+
fireEvent.change(input, { target: { value: '' } });
|
|
29
|
+
|
|
30
|
+
expect(onEmpty).toHaveBeenCalledTimes(1);
|
|
31
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('reports Enter on an emptied input through onEnter with null', () => {
|
|
35
|
+
const { input, onChange, onEnter } = setup();
|
|
36
|
+
|
|
37
|
+
fireEvent.change(input, { target: { value: '' } });
|
|
38
|
+
fireEvent.keyDown(input, { key: 'Enter' });
|
|
39
|
+
|
|
40
|
+
expect(onEnter).toHaveBeenCalledWith(null);
|
|
41
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('reports Enter on a typed date through onEnter with the date', () => {
|
|
45
|
+
const { input, onEnter } = setup();
|
|
46
|
+
|
|
47
|
+
fireEvent.change(input, { target: { value: '02/20/2024' } });
|
|
48
|
+
fireEvent.keyDown(input, { key: 'Enter' });
|
|
49
|
+
|
|
50
|
+
expect(onEnter).toHaveBeenCalledWith(new Date(2024, 1, 20));
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe('with onEnter and no onEmpty', () => {
|
|
54
|
+
const setupEnterOnly = () => {
|
|
55
|
+
const onEnter = jest.fn();
|
|
56
|
+
const { container } = render(
|
|
57
|
+
<CellDateInput value={new Date(2024, 0, 15)} onEnter={onEnter} />,
|
|
58
|
+
);
|
|
59
|
+
const input = container.querySelector('input')!;
|
|
60
|
+
return { input, onEnter };
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
it('reports Enter on a typed date through onEnter with the date', () => {
|
|
64
|
+
const { input, onEnter } = setupEnterOnly();
|
|
65
|
+
|
|
66
|
+
fireEvent.change(input, { target: { value: '02/20/2024' } });
|
|
67
|
+
fireEvent.keyDown(input, { key: 'Enter' });
|
|
68
|
+
|
|
69
|
+
expect(onEnter).toHaveBeenCalledWith(new Date(2024, 1, 20));
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('reports Enter on an emptied input through onEnter with null', () => {
|
|
73
|
+
const { input, onEnter } = setupEnterOnly();
|
|
74
|
+
|
|
75
|
+
fireEvent.change(input, { target: { value: '' } });
|
|
76
|
+
fireEvent.keyDown(input, { key: 'Enter' });
|
|
77
|
+
|
|
78
|
+
expect(onEnter).toHaveBeenCalledWith(null);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('emits a typed date through onChange', () => {
|
|
83
|
+
const { input, onChange, onEmpty } = setup();
|
|
84
|
+
|
|
85
|
+
fireEvent.change(input, { target: { value: '02/20/2024' } });
|
|
86
|
+
|
|
87
|
+
expect(onChange).toHaveBeenCalledWith(new Date(2024, 1, 20));
|
|
88
|
+
expect(onEmpty).not.toHaveBeenCalled();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('emits a day picked from the calendar while the input is empty', () => {
|
|
92
|
+
const { input, onChange, onEmpty } = setup(null);
|
|
93
|
+
|
|
94
|
+
fireEvent.click(input);
|
|
95
|
+
fireEvent.click(document.querySelector('[data-date]')!);
|
|
96
|
+
|
|
97
|
+
expect(onChange).toHaveBeenCalledWith(expect.any(Date));
|
|
98
|
+
expect(onEmpty).not.toHaveBeenCalled();
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import '../../../testkit/test-polyfills';
|
|
2
|
+
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { act, fireEvent, render } from '@testing-library/react';
|
|
5
|
+
import { DatePicker } from '@wix/design-system';
|
|
6
|
+
|
|
7
|
+
import { onSameDayCalendarPick } from '../../../components/date-input/date-picker-internals';
|
|
8
|
+
|
|
9
|
+
const setup = () => {
|
|
10
|
+
const onChange = jest.fn();
|
|
11
|
+
const onPick = jest.fn();
|
|
12
|
+
const pickerRef = React.createRef<DatePicker>();
|
|
13
|
+
render(
|
|
14
|
+
<DatePicker
|
|
15
|
+
ref={pickerRef}
|
|
16
|
+
value={new Date(2024, 0, 15, 3, 30)}
|
|
17
|
+
onChange={onChange}
|
|
18
|
+
/>,
|
|
19
|
+
);
|
|
20
|
+
const undo = onSameDayCalendarPick(pickerRef.current, onPick);
|
|
21
|
+
const clickDay = (day: number) => {
|
|
22
|
+
act(() => {
|
|
23
|
+
pickerRef.current!.openCalendar();
|
|
24
|
+
});
|
|
25
|
+
fireEvent.click(
|
|
26
|
+
document.querySelector(
|
|
27
|
+
`[data-outsideday='false'][data-date='2024-0-${day}']`,
|
|
28
|
+
)!,
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
return { onChange, onPick, undo, clickDay };
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
describe('onSameDayCalendarPick', () => {
|
|
35
|
+
it('reports a pick of the value day, which WDS skips', () => {
|
|
36
|
+
const { onChange, onPick, clickDay } = setup();
|
|
37
|
+
|
|
38
|
+
clickDay(15);
|
|
39
|
+
|
|
40
|
+
expect(onPick).toHaveBeenCalledTimes(1);
|
|
41
|
+
expect(onPick).toHaveBeenCalledWith(new Date(2024, 0, 15, 12));
|
|
42
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('does not report a pick of another day, which WDS sends to onChange', () => {
|
|
46
|
+
const { onChange, onPick, clickDay } = setup();
|
|
47
|
+
|
|
48
|
+
clickDay(20);
|
|
49
|
+
|
|
50
|
+
expect(onPick).not.toHaveBeenCalled();
|
|
51
|
+
expect(onChange).toHaveBeenCalledWith(new Date(2024, 0, 20, 3, 30));
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('stops reporting once undone', () => {
|
|
55
|
+
const { onPick, undo, clickDay } = setup();
|
|
56
|
+
|
|
57
|
+
undo();
|
|
58
|
+
clickDay(15);
|
|
59
|
+
|
|
60
|
+
expect(onPick).not.toHaveBeenCalled();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('does nothing without a picker', () => {
|
|
64
|
+
const onPick = jest.fn();
|
|
65
|
+
|
|
66
|
+
expect(() => onSameDayCalendarPick(null, onPick)()).not.toThrow();
|
|
67
|
+
expect(onPick).not.toHaveBeenCalled();
|
|
68
|
+
});
|
|
69
|
+
});
|
|
@@ -22,6 +22,147 @@ const setup = (
|
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
describe('FormDateInput field', () => {
|
|
25
|
+
it.each(['reset', 'setValue'] as const)(
|
|
26
|
+
'clears stale errors on %s, even when restoring the same value',
|
|
27
|
+
async (method) => {
|
|
28
|
+
const driver = setup({ initialValue: '2026-09-16' });
|
|
29
|
+
const initialText = await driver.tk.getValue();
|
|
30
|
+
await driver.tk.enterText('not-a-date');
|
|
31
|
+
await driver.tk.blur();
|
|
32
|
+
await driver.submit();
|
|
33
|
+
expect(driver.onSubmit).not.toHaveBeenCalled();
|
|
34
|
+
|
|
35
|
+
await driver[method]('2026-09-16');
|
|
36
|
+
expect(await driver.tk.getValue()).toBe(initialText);
|
|
37
|
+
expect(await driver.tk.hasError()).toBe(false);
|
|
38
|
+
await driver.submit();
|
|
39
|
+
expect(driver.onSubmit).toHaveBeenCalledTimes(1);
|
|
40
|
+
expect(driver.onSubmit.mock.calls[0][0][driver.field.id]).toBe(
|
|
41
|
+
'2026-09-16',
|
|
42
|
+
);
|
|
43
|
+
},
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
it.each(['reset', 'setValue'] as const)(
|
|
47
|
+
'shows and submits an externally replaced date via %s',
|
|
48
|
+
async (method) => {
|
|
49
|
+
const driver = setup({ initialValue: '2026-09-16' });
|
|
50
|
+
const initialText = await driver.tk.getValue();
|
|
51
|
+
await driver.tk.enterText('not-a-date');
|
|
52
|
+
await driver.tk.blur();
|
|
53
|
+
|
|
54
|
+
await driver[method]('2026-09-18');
|
|
55
|
+
expect(await driver.tk.getValue()).not.toBe(initialText);
|
|
56
|
+
expect(await driver.tk.getValue()).not.toBe('not-a-date');
|
|
57
|
+
expect(await driver.tk.hasError()).toBe(false);
|
|
58
|
+
await driver.submit();
|
|
59
|
+
expect(driver.onSubmit.mock.calls[0][0][driver.field.id]).toBe(
|
|
60
|
+
'2026-09-18',
|
|
61
|
+
);
|
|
62
|
+
},
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
it('keeps the error when another field is replaced or removed', async () => {
|
|
66
|
+
const driver = setup({ initialValue: '2026-09-16' });
|
|
67
|
+
await driver.tk.enterText('not-a-date');
|
|
68
|
+
await driver.tk.blur();
|
|
69
|
+
await driver.setValue('2026-09-18', 'anotherField');
|
|
70
|
+
await driver.unregister('anotherField');
|
|
71
|
+
await driver.submit();
|
|
72
|
+
expect(driver.onSubmit).not.toHaveBeenCalled();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it.each([false, true])(
|
|
76
|
+
'resets invalid input to an empty value (required=%s)',
|
|
77
|
+
async (required) => {
|
|
78
|
+
const driver = setup({
|
|
79
|
+
field: makeField({ type: 'DATE', validation: { required } }),
|
|
80
|
+
});
|
|
81
|
+
await driver.tk.enterText('not-a-date');
|
|
82
|
+
await driver.tk.blur();
|
|
83
|
+
await driver.reset(null);
|
|
84
|
+
expect(await driver.tk.getValue()).toBe('');
|
|
85
|
+
await driver.submit();
|
|
86
|
+
expect(driver.onSubmit).toHaveBeenCalledTimes(required ? 0 : 1);
|
|
87
|
+
if (!required) {
|
|
88
|
+
expect(driver.onSubmit.mock.calls[0][0][driver.field.id]).toBeNull();
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
it.each([false, true])(
|
|
94
|
+
'blocks submit for invalid text over a valid date (required=%s)',
|
|
95
|
+
async (required) => {
|
|
96
|
+
const driver = setup({
|
|
97
|
+
field: makeField({ type: 'DATE', validation: { required } }),
|
|
98
|
+
initialValue: '2026-09-16',
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
await driver.tk.enterText('not-a-date');
|
|
102
|
+
await driver.tk.blur();
|
|
103
|
+
expect(await driver.tk.hasError()).toBe(true);
|
|
104
|
+
|
|
105
|
+
await driver.submit();
|
|
106
|
+
|
|
107
|
+
expect(driver.onSubmit).not.toHaveBeenCalled();
|
|
108
|
+
},
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
it('allows submit after correcting an invalid date', async () => {
|
|
112
|
+
const driver = setup({ initialValue: '2026-09-16' });
|
|
113
|
+
await driver.tk.enterText('not-a-date');
|
|
114
|
+
await driver.tk.blur();
|
|
115
|
+
await driver.submit();
|
|
116
|
+
expect(driver.onSubmit).not.toHaveBeenCalled();
|
|
117
|
+
|
|
118
|
+
await driver.tk.enterText('09/17/2026');
|
|
119
|
+
await driver.tk.blur();
|
|
120
|
+
await driver.submit();
|
|
121
|
+
|
|
122
|
+
expect(await driver.tk.hasError()).toBe(false);
|
|
123
|
+
expect(driver.onSubmit.mock.calls[0][0][driver.field.id]).toBe(
|
|
124
|
+
'2026-09-17',
|
|
125
|
+
);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it.each([false, true])(
|
|
129
|
+
'handles clearing an invalid date (required=%s)',
|
|
130
|
+
async (required) => {
|
|
131
|
+
const driver = setup({
|
|
132
|
+
field: makeField({ type: 'DATE', validation: { required } }),
|
|
133
|
+
initialValue: '2026-09-16',
|
|
134
|
+
});
|
|
135
|
+
await driver.tk.enterText('not-a-date');
|
|
136
|
+
await driver.tk.blur();
|
|
137
|
+
await driver.tk.enterText('');
|
|
138
|
+
await driver.tk.blur();
|
|
139
|
+
await driver.submit();
|
|
140
|
+
|
|
141
|
+
expect(await driver.tk.hasError()).toBe(required);
|
|
142
|
+
expect(driver.onSubmit).toHaveBeenCalledTimes(required ? 0 : 1);
|
|
143
|
+
if (!required) {
|
|
144
|
+
expect(driver.onSubmit.mock.calls[0][0][driver.field.id]).toBeNull();
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
it('allows submit after replacing invalid text with a calendar selection', async () => {
|
|
150
|
+
const driver = setup({ initialValue: '2026-09-16' });
|
|
151
|
+
await driver.tk.enterText('not-a-date');
|
|
152
|
+
await driver.tk.blur();
|
|
153
|
+
await driver.submit();
|
|
154
|
+
expect(driver.onSubmit).not.toHaveBeenCalled();
|
|
155
|
+
|
|
156
|
+
await driver.tk.calendarPopover.open();
|
|
157
|
+
await driver.tk.selectDate(new Date(2026, 8, 17));
|
|
158
|
+
await driver.submit();
|
|
159
|
+
|
|
160
|
+
expect(await driver.tk.hasError()).toBe(false);
|
|
161
|
+
expect(driver.onSubmit.mock.calls[0][0][driver.field.id]).toBe(
|
|
162
|
+
'2026-09-17',
|
|
163
|
+
);
|
|
164
|
+
});
|
|
165
|
+
|
|
25
166
|
it('renders the field displayName as the label', async () => {
|
|
26
167
|
const driver = setup();
|
|
27
168
|
|
|
@@ -22,6 +22,200 @@ const setup = (
|
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
describe('FormDateTime field', () => {
|
|
25
|
+
it.each(['reset', 'setValue'] as const)(
|
|
26
|
+
'clears stale errors on %s, even when restoring the same value',
|
|
27
|
+
async (method) => {
|
|
28
|
+
const driver = setup({ initialValue: '2026-09-16T12:00:00.000Z' });
|
|
29
|
+
const initialText = await driver.tk.getDateText();
|
|
30
|
+
await driver.tk.enterTimeText('not-a-time');
|
|
31
|
+
await driver.tk.blurTime();
|
|
32
|
+
await driver.tk.enterDateText('not-a-date');
|
|
33
|
+
await driver.tk.blurDate();
|
|
34
|
+
await driver.submit();
|
|
35
|
+
expect(driver.onSubmit).not.toHaveBeenCalled();
|
|
36
|
+
|
|
37
|
+
await driver[method]('2026-09-16T12:00:00.000Z');
|
|
38
|
+
expect(await driver.tk.getDateText()).toBe(initialText);
|
|
39
|
+
expect(await driver.tk.dateHasError()).toBe(false);
|
|
40
|
+
expect(await driver.tk.timeHasError()).toBe(false);
|
|
41
|
+
await driver.submit();
|
|
42
|
+
expect(driver.onSubmit).toHaveBeenCalledTimes(1);
|
|
43
|
+
expect(driver.onSubmit.mock.calls[0][0][driver.field.id]).toBe(
|
|
44
|
+
'2026-09-16T12:00:00.000Z',
|
|
45
|
+
);
|
|
46
|
+
},
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
it.each(['reset', 'setValue'] as const)(
|
|
50
|
+
'shows and submits an externally replaced date via %s',
|
|
51
|
+
async (method) => {
|
|
52
|
+
const driver = setup({ initialValue: '2026-09-16T12:00:00.000Z' });
|
|
53
|
+
const initialText = await driver.tk.getDateText();
|
|
54
|
+
await driver.tk.enterTimeText('not-a-time');
|
|
55
|
+
await driver.tk.blurTime();
|
|
56
|
+
await driver.tk.enterDateText('not-a-date');
|
|
57
|
+
await driver.tk.blurDate();
|
|
58
|
+
|
|
59
|
+
await driver[method]('2026-09-18T12:00:00.000Z');
|
|
60
|
+
expect(await driver.tk.getDateText()).not.toBe(initialText);
|
|
61
|
+
expect(await driver.tk.getDateText()).not.toBe('not-a-date');
|
|
62
|
+
expect(await driver.tk.dateHasError()).toBe(false);
|
|
63
|
+
expect(await driver.tk.timeHasError()).toBe(false);
|
|
64
|
+
await driver.submit();
|
|
65
|
+
expect(driver.onSubmit.mock.calls[0][0][driver.field.id]).toBe(
|
|
66
|
+
'2026-09-18T12:00:00.000Z',
|
|
67
|
+
);
|
|
68
|
+
},
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
it('keeps the error when another field is replaced or removed', async () => {
|
|
72
|
+
const driver = setup({ initialValue: '2026-09-16T12:00:00.000Z' });
|
|
73
|
+
await driver.tk.enterDateText('not-a-date');
|
|
74
|
+
await driver.tk.blurDate();
|
|
75
|
+
await driver.setValue('2026-09-18T12:00:00.000Z', 'anotherField');
|
|
76
|
+
await driver.unregister('anotherField');
|
|
77
|
+
await driver.submit();
|
|
78
|
+
expect(driver.onSubmit).not.toHaveBeenCalled();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it.each([false, true])(
|
|
82
|
+
'resets invalid input to an empty value (required=%s)',
|
|
83
|
+
async (required) => {
|
|
84
|
+
const driver = setup({
|
|
85
|
+
field: makeField({ type: 'DATETIME', validation: { required } }),
|
|
86
|
+
});
|
|
87
|
+
await driver.tk.enterDateText('not-a-date');
|
|
88
|
+
await driver.tk.blurDate();
|
|
89
|
+
await driver.reset(null);
|
|
90
|
+
expect(await driver.tk.getDateText()).toBe('');
|
|
91
|
+
await driver.submit();
|
|
92
|
+
expect(driver.onSubmit).toHaveBeenCalledTimes(required ? 0 : 1);
|
|
93
|
+
if (!required) {
|
|
94
|
+
expect(driver.onSubmit.mock.calls[0][0][driver.field.id]).toBeNull();
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
it.each([false, true])(
|
|
100
|
+
'blocks submit for an invalid date (required=%s)',
|
|
101
|
+
async (required) => {
|
|
102
|
+
const driver = setup({
|
|
103
|
+
field: makeField({ type: 'DATETIME', validation: { required } }),
|
|
104
|
+
initialValue: '2026-09-16T12:00:00.000Z',
|
|
105
|
+
});
|
|
106
|
+
await driver.tk.enterDateText('not-a-date');
|
|
107
|
+
await driver.tk.blurDate();
|
|
108
|
+
expect(await driver.tk.dateHasError()).toBe(true);
|
|
109
|
+
expect(await driver.tk.timeHasError()).toBe(false);
|
|
110
|
+
|
|
111
|
+
await driver.submit();
|
|
112
|
+
|
|
113
|
+
expect(driver.onSubmit).not.toHaveBeenCalled();
|
|
114
|
+
expect(await driver.tk.timeHasError()).toBe(false);
|
|
115
|
+
},
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
it('allows submit after correcting an invalid date', async () => {
|
|
119
|
+
const driver = setup({ initialValue: '2026-09-16T12:00:00.000Z' });
|
|
120
|
+
await driver.tk.enterDateText('not-a-date');
|
|
121
|
+
await driver.tk.blurDate();
|
|
122
|
+
await driver.submit();
|
|
123
|
+
expect(driver.onSubmit).not.toHaveBeenCalled();
|
|
124
|
+
|
|
125
|
+
await driver.tk.enterDateText('09/17/2026');
|
|
126
|
+
await driver.tk.blurDate();
|
|
127
|
+
await driver.submit();
|
|
128
|
+
|
|
129
|
+
expect(await driver.tk.dateHasError()).toBe(false);
|
|
130
|
+
expect(driver.onSubmit).toHaveBeenCalledTimes(1);
|
|
131
|
+
expect(
|
|
132
|
+
new Date(driver.onSubmit.mock.calls[0][0][driver.field.id]).getDate(),
|
|
133
|
+
).toBe(17);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('blocks an invalid time and allows submit after correcting it', async () => {
|
|
137
|
+
const driver = setup({ initialValue: '2026-09-16T12:00:00.000Z' });
|
|
138
|
+
await driver.tk.enterTimeText('not-a-time');
|
|
139
|
+
await driver.tk.blurTime();
|
|
140
|
+
expect(await driver.tk.timeHasError()).toBe(true);
|
|
141
|
+
expect(await driver.tk.dateHasError()).toBe(false);
|
|
142
|
+
await driver.submit();
|
|
143
|
+
expect(driver.onSubmit).not.toHaveBeenCalled();
|
|
144
|
+
expect(await driver.tk.dateHasError()).toBe(false);
|
|
145
|
+
|
|
146
|
+
await driver.tk.enterTimeText('14:30');
|
|
147
|
+
await driver.tk.blurTime();
|
|
148
|
+
await driver.submit();
|
|
149
|
+
|
|
150
|
+
expect(await driver.tk.timeHasError()).toBe(false);
|
|
151
|
+
expect(driver.onSubmit).toHaveBeenCalledTimes(1);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('does not clear an invalid date when the time changes', async () => {
|
|
155
|
+
const driver = setup({ initialValue: '2026-09-16T12:00:00.000Z' });
|
|
156
|
+
await driver.tk.enterDateText('not-a-date');
|
|
157
|
+
await driver.tk.blurDate();
|
|
158
|
+
await driver.tk.enterTimeText('14:30');
|
|
159
|
+
await driver.tk.blurTime();
|
|
160
|
+
|
|
161
|
+
expect(await driver.tk.dateHasError()).toBe(true);
|
|
162
|
+
await driver.submit();
|
|
163
|
+
expect(driver.onSubmit).not.toHaveBeenCalled();
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('shows each input’s own message when both inputs are invalid', async () => {
|
|
167
|
+
const driver = setup({ initialValue: '2026-09-16T12:00:00.000Z' });
|
|
168
|
+
await driver.tk.enterDateText('not-a-date');
|
|
169
|
+
await driver.tk.blurDate();
|
|
170
|
+
await driver.tk.enterTimeText('not-a-time');
|
|
171
|
+
await driver.tk.blurTime();
|
|
172
|
+
await driver.submit();
|
|
173
|
+
|
|
174
|
+
expect(driver.onSubmit).not.toHaveBeenCalled();
|
|
175
|
+
expect(await driver.tk.getDateErrorMessage()).toContain(
|
|
176
|
+
'cairo.customFields.fieldType.date.invalid.value',
|
|
177
|
+
);
|
|
178
|
+
expect(await driver.tk.getTimeErrorMessage()).toBe(
|
|
179
|
+
'CMS.formTime.invalidMessage',
|
|
180
|
+
);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('does not clear an invalid time when the date changes', async () => {
|
|
184
|
+
const driver = setup({ initialValue: '2026-09-16T12:00:00.000Z' });
|
|
185
|
+
await driver.tk.enterTimeText('not-a-time');
|
|
186
|
+
await driver.tk.blurTime();
|
|
187
|
+
await driver.tk.enterDateText('09/17/2026');
|
|
188
|
+
await driver.tk.blurDate();
|
|
189
|
+
|
|
190
|
+
expect(await driver.tk.timeHasError()).toBe(true);
|
|
191
|
+
await driver.submit();
|
|
192
|
+
expect(driver.onSubmit).not.toHaveBeenCalled();
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it.each([false, true])(
|
|
196
|
+
'handles clearing an invalid date and time (required=%s)',
|
|
197
|
+
async (required) => {
|
|
198
|
+
const driver = setup({
|
|
199
|
+
field: makeField({ type: 'DATETIME', validation: { required } }),
|
|
200
|
+
initialValue: '2026-09-16T12:00:00.000Z',
|
|
201
|
+
});
|
|
202
|
+
await driver.tk.enterDateText('not-a-date');
|
|
203
|
+
await driver.tk.blurDate();
|
|
204
|
+
await driver.tk.enterTimeText('');
|
|
205
|
+
await driver.tk.blurTime();
|
|
206
|
+
await driver.tk.enterDateText('');
|
|
207
|
+
await driver.tk.blurDate();
|
|
208
|
+
await driver.submit();
|
|
209
|
+
|
|
210
|
+
expect(driver.onSubmit).toHaveBeenCalledTimes(required ? 0 : 1);
|
|
211
|
+
if (!required) {
|
|
212
|
+
expect(driver.onSubmit.mock.calls[0][0][driver.field.id]).toBeNull();
|
|
213
|
+
expect(await driver.tk.dateHasError()).toBe(false);
|
|
214
|
+
expect(await driver.tk.timeHasError()).toBe(false);
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
);
|
|
218
|
+
|
|
25
219
|
it('renders the field displayName as the label', async () => {
|
|
26
220
|
const driver = setup();
|
|
27
221
|
|
|
@@ -61,6 +61,33 @@ describe('FormShortText field', () => {
|
|
|
61
61
|
expect(await driver.tk.getCharCountLeft()).toBe(7);
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
+
it.each([undefined, null])(
|
|
65
|
+
'shows the full character allowance when the initial value is %p',
|
|
66
|
+
async (initialValue) => {
|
|
67
|
+
const driver = new FormFieldDriver({
|
|
68
|
+
Component: FormShortText,
|
|
69
|
+
UniDriverFactory: FormShortTextDriver,
|
|
70
|
+
dataHook: (f) => `short-text-field-${f.id}`,
|
|
71
|
+
field: makeField({
|
|
72
|
+
validation: { required: true, stringLengthRange: { maxLength: 10 } },
|
|
73
|
+
}),
|
|
74
|
+
initialValue: initialValue as unknown as string,
|
|
75
|
+
});
|
|
76
|
+
driver.render();
|
|
77
|
+
|
|
78
|
+
expect(await driver.tk.getValue()).toBe('');
|
|
79
|
+
expect(await driver.tk.getCharCountLeft()).toBe(10);
|
|
80
|
+
|
|
81
|
+
await driver.tk.enterText('abc');
|
|
82
|
+
|
|
83
|
+
expect(await driver.tk.getCharCountLeft()).toBe(7);
|
|
84
|
+
|
|
85
|
+
await driver.tk.enterText('');
|
|
86
|
+
|
|
87
|
+
expect(await driver.tk.getCharCountLeft()).toBe(10);
|
|
88
|
+
},
|
|
89
|
+
);
|
|
90
|
+
|
|
64
91
|
it('marks the field as required when validation.required is true', async () => {
|
|
65
92
|
const driver = setup({
|
|
66
93
|
field: makeField({ validation: { required: true } }),
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { act, fireEvent, render, RenderResult } from '@testing-library/react';
|
|
3
3
|
import Chance from 'chance';
|
|
4
4
|
import { useForm } from '@wix/bex-core/form';
|
|
5
|
-
import type { Control, FieldValues } from '@wix/bex-core/form';
|
|
5
|
+
import type { Control, FieldValues, UseFormReturn } from '@wix/bex-core/form';
|
|
6
6
|
import type { Field } from '@wix/bex-core';
|
|
7
7
|
import { UniDriver } from '@wix/wix-ui-test-utils/unidriver';
|
|
8
8
|
import type { BaseUniDriver } from '@wix/wix-ui-test-utils/base-driver';
|
|
@@ -12,7 +12,6 @@ import { PatternsFieldsTestProvider } from '../testkit/patterns-fields-test-prov
|
|
|
12
12
|
import type { BaseInputProps } from '../types/base-input';
|
|
13
13
|
|
|
14
14
|
const chance = new Chance();
|
|
15
|
-
const noop = () => {};
|
|
16
15
|
const SUBMIT_HOOK = 'form-field-driver-submit';
|
|
17
16
|
|
|
18
17
|
type UniDriverFactory<U> = (
|
|
@@ -31,9 +30,11 @@ export interface FormFieldDriverOptions<U extends BaseUniDriver, T> {
|
|
|
31
30
|
|
|
32
31
|
export class FormFieldDriver<U extends BaseUniDriver, T> {
|
|
33
32
|
private _renderResult?: RenderResult;
|
|
33
|
+
private form?: UseFormReturn<FieldValues>;
|
|
34
34
|
readonly field: Field;
|
|
35
35
|
readonly initialValue: T;
|
|
36
36
|
readonly onChange = jest.fn<void, [T]>();
|
|
37
|
+
readonly onSubmit = jest.fn<void, [FieldValues]>();
|
|
37
38
|
private readonly opts: FormFieldDriverOptions<U, T>;
|
|
38
39
|
private readonly _dataHook: string;
|
|
39
40
|
|
|
@@ -67,6 +68,24 @@ export class FormFieldDriver<U extends BaseUniDriver, T> {
|
|
|
67
68
|
});
|
|
68
69
|
}
|
|
69
70
|
|
|
71
|
+
async reset(value: T): Promise<void> {
|
|
72
|
+
await act(async () => {
|
|
73
|
+
this.form!.reset({ [this.field.id]: value });
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async setValue(value: T, name = this.field.id): Promise<void> {
|
|
78
|
+
await act(async () => {
|
|
79
|
+
this.form!.setValue(name, value, { shouldValidate: true });
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async unregister(name: string): Promise<void> {
|
|
84
|
+
await act(async () => {
|
|
85
|
+
this.form!.unregister(name);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
70
89
|
render() {
|
|
71
90
|
const { Component } = this.opts;
|
|
72
91
|
const { field, initialValue, _dataHook: dataHook, onChange } = this;
|
|
@@ -74,6 +93,10 @@ export class FormFieldDriver<U extends BaseUniDriver, T> {
|
|
|
74
93
|
<TestForm
|
|
75
94
|
field={field}
|
|
76
95
|
initialValue={initialValue}
|
|
96
|
+
onSubmit={this.onSubmit}
|
|
97
|
+
onFormReady={(form) => {
|
|
98
|
+
this.form = form;
|
|
99
|
+
}}
|
|
77
100
|
renderField={(control) => (
|
|
78
101
|
<Component
|
|
79
102
|
field={field}
|
|
@@ -93,20 +116,25 @@ export class FormFieldDriver<U extends BaseUniDriver, T> {
|
|
|
93
116
|
interface TestFormProps<T> {
|
|
94
117
|
field: Field;
|
|
95
118
|
initialValue: T;
|
|
119
|
+
onSubmit: (values: FieldValues) => void;
|
|
120
|
+
onFormReady: (form: UseFormReturn<FieldValues>) => void;
|
|
96
121
|
renderField: (control: Control<FieldValues>) => React.ReactElement;
|
|
97
122
|
}
|
|
98
123
|
|
|
99
124
|
const TestForm = <T,>({
|
|
100
125
|
field,
|
|
101
126
|
initialValue,
|
|
127
|
+
onSubmit,
|
|
128
|
+
onFormReady,
|
|
102
129
|
renderField,
|
|
103
130
|
}: TestFormProps<T>) => {
|
|
104
131
|
const methods = useForm<FieldValues>({
|
|
105
132
|
mode: 'onChange',
|
|
106
133
|
defaultValues: { [field.id]: initialValue },
|
|
107
134
|
});
|
|
135
|
+
onFormReady(methods);
|
|
108
136
|
return (
|
|
109
|
-
<form onSubmit={methods.handleSubmit(
|
|
137
|
+
<form onSubmit={methods.handleSubmit(onSubmit)}>
|
|
110
138
|
{renderField(methods.control)}
|
|
111
139
|
<button type="submit" data-hook={SUBMIT_HOOK} />
|
|
112
140
|
</form>
|