@linzjs/step-ag-grid 23.0.0 → 24.0.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/src/components/ComponentLoadingWrapper.d.ts +1 -1
- package/dist/src/components/Grid.d.ts +17 -17
- package/dist/src/components/GridCell.d.ts +9 -9
- package/dist/src/components/GridCellFiller.d.ts +2 -2
- package/dist/src/components/GridCellMultiEditor.d.ts +6 -6
- package/dist/src/components/GridCellMultiSelectClassRules.d.ts +1 -1
- package/dist/src/components/GridIcon.d.ts +2 -2
- package/dist/src/components/GridNoRowsOverlay.d.ts +1 -1
- package/dist/src/components/GridPopoverHook.d.ts +2 -2
- package/dist/src/components/GridWrapper.d.ts +1 -1
- package/dist/src/components/PostSortRowsHook.d.ts +1 -1
- package/dist/src/components/clickInputWhenContainingCellClicked.d.ts +1 -1
- package/dist/src/components/gridFilter/GridFilterButtons.d.ts +5 -5
- package/dist/src/components/gridFilter/GridFilterColumnsToggle.d.ts +1 -1
- package/dist/src/components/gridFilter/GridFilterDownloadCsvButton.d.ts +1 -1
- package/dist/src/components/gridFilter/GridFilterHeaderIconButton.d.ts +2 -2
- package/dist/src/components/gridFilter/GridFilters.d.ts +1 -1
- package/dist/src/components/gridFilter/index.d.ts +7 -7
- package/dist/src/components/gridFilter/useGridFilter.d.ts +2 -2
- package/dist/src/components/gridForm/GridFormDropDown.d.ts +8 -8
- package/dist/src/components/gridForm/GridFormEditBearing.d.ts +2 -2
- package/dist/src/components/gridForm/GridFormMessage.d.ts +3 -3
- package/dist/src/components/gridForm/GridFormMultiSelect.d.ts +4 -4
- package/dist/src/components/gridForm/GridFormMultiSelectGrid.d.ts +4 -4
- package/dist/src/components/gridForm/GridFormPopoverMenu.d.ts +5 -5
- package/dist/src/components/gridForm/GridFormSubComponentTextArea.d.ts +4 -4
- package/dist/src/components/gridForm/GridFormSubComponentTextInput.d.ts +4 -4
- package/dist/src/components/gridForm/GridFormTextArea.d.ts +4 -4
- package/dist/src/components/gridForm/GridFormTextInput.d.ts +3 -3
- package/dist/src/components/gridForm/index.d.ts +10 -10
- package/dist/src/components/gridHeader/GridHeaderSelect.d.ts +1 -1
- package/dist/src/components/gridHeader/index.d.ts +1 -1
- package/dist/src/components/gridHook/index.d.ts +1 -1
- package/dist/src/components/gridHook/useGridContextMenu.d.ts +4 -4
- package/dist/src/components/gridPopoverEdit/GridButton.d.ts +5 -5
- package/dist/src/components/gridPopoverEdit/GridEditBoolean.d.ts +4 -4
- package/dist/src/components/gridPopoverEdit/GridPopoutEditMultiSelect.d.ts +4 -4
- package/dist/src/components/gridPopoverEdit/GridPopoutEditMultiSelectGrid.d.ts +4 -4
- package/dist/src/components/gridPopoverEdit/GridPopoverEditBearing.d.ts +4 -4
- package/dist/src/components/gridPopoverEdit/GridPopoverEditDropDown.d.ts +4 -4
- package/dist/src/components/gridPopoverEdit/GridPopoverMenu.d.ts +4 -4
- package/dist/src/components/gridPopoverEdit/GridPopoverMessage.d.ts +4 -4
- package/dist/src/components/gridPopoverEdit/GridPopoverTextArea.d.ts +4 -4
- package/dist/src/components/gridPopoverEdit/GridPopoverTextInput.d.ts +4 -4
- package/dist/src/components/gridPopoverEdit/index.d.ts +11 -11
- package/dist/src/components/gridRender/GridRenderGenericCell.d.ts +5 -5
- package/dist/src/components/gridRender/GridRenderPopoutMenuCell.d.ts +1 -1
- package/dist/src/components/gridRender/index.d.ts +2 -2
- package/dist/src/components/gridUtil.d.ts +1 -1
- package/dist/src/components/index.d.ts +19 -19
- package/dist/src/contexts/GridContext.d.ts +4 -4
- package/dist/src/contexts/GridContextProvider.d.ts +3 -3
- package/dist/src/contexts/GridPopoverContext.d.ts +3 -3
- package/dist/src/contexts/GridPopoverContextProvider.d.ts +4 -4
- package/dist/src/contexts/GridUpdatingContextProvider.d.ts +1 -1
- package/dist/src/index.d.ts +17 -17
- package/dist/src/lui/ActionButton.d.ts +9 -9
- package/dist/src/lui/FormError.d.ts +2 -2
- package/dist/src/lui/TextAreaInput.d.ts +1 -1
- package/dist/src/lui/TextInputFormatted.d.ts +2 -2
- package/dist/src/lui/reactUtils.d.ts +1 -1
- package/dist/src/lui/stateDeferredHook.d.ts +1 -1
- package/dist/src/react-menu3/components/ControlledMenu.d.ts +2 -2
- package/dist/src/react-menu3/components/FocusableItem.d.ts +3 -3
- package/dist/src/react-menu3/components/Menu.d.ts +3 -3
- package/dist/src/react-menu3/components/MenuButton.d.ts +2 -2
- package/dist/src/react-menu3/components/MenuDivider.d.ts +1 -1
- package/dist/src/react-menu3/components/MenuGroup.d.ts +2 -2
- package/dist/src/react-menu3/components/MenuHeader.d.ts +2 -2
- package/dist/src/react-menu3/components/MenuItem.d.ts +3 -3
- package/dist/src/react-menu3/components/MenuList.d.ts +1 -1
- package/dist/src/react-menu3/components/MenuRadioGroup.d.ts +2 -2
- package/dist/src/react-menu3/components/SubMenu.d.ts +5 -5
- package/dist/src/react-menu3/contexts/EventHandlersContext.d.ts +1 -1
- package/dist/src/react-menu3/contexts/MenuListContext.d.ts +2 -2
- package/dist/src/react-menu3/contexts/MenuListItemContext.d.ts +1 -1
- package/dist/src/react-menu3/contexts/RadioGroupContext.d.ts +1 -1
- package/dist/src/react-menu3/contexts/SettingsContext.d.ts +2 -2
- package/dist/src/react-menu3/hooks/index.d.ts +9 -9
- package/dist/src/react-menu3/hooks/useBEM.d.ts +1 -1
- package/dist/src/react-menu3/hooks/useCombinedRef.d.ts +1 -1
- package/dist/src/react-menu3/hooks/useIsomorphicLayoutEffect.d.ts +1 -1
- package/dist/src/react-menu3/hooks/useItemEffect.d.ts +1 -1
- package/dist/src/react-menu3/hooks/useItemState.d.ts +1 -1
- package/dist/src/react-menu3/hooks/useItems.d.ts +2 -2
- package/dist/src/react-menu3/hooks/useMenuChange.d.ts +1 -1
- package/dist/src/react-menu3/hooks/useMenuState.d.ts +1 -1
- package/dist/src/react-menu3/hooks/useMenuStateAndFocus.d.ts +1 -1
- package/dist/src/react-menu3/index.d.ts +11 -11
- package/dist/src/react-menu3/positionUtils/getPositionHelpers.d.ts +1 -1
- package/dist/src/react-menu3/positionUtils/index.d.ts +3 -3
- package/dist/src/react-menu3/positionUtils/placeArrowHorizontal.d.ts +1 -1
- package/dist/src/react-menu3/positionUtils/placeArrowVertical.d.ts +1 -1
- package/dist/src/react-menu3/positionUtils/placeLeftorRight.d.ts +4 -4
- package/dist/src/react-menu3/positionUtils/placeToporBottom.d.ts +5 -5
- package/dist/src/react-menu3/positionUtils/positionContextMenu.d.ts +2 -2
- package/dist/src/react-menu3/positionUtils/positionMenu.d.ts +5 -5
- package/dist/src/react-menu3/style-utils/index.d.ts +1 -1
- package/dist/src/react-menu3/types.d.ts +15 -15
- package/dist/src/react-menu3/utils/constants.d.ts +1 -1
- package/dist/src/react-menu3/utils/index.d.ts +3 -3
- package/dist/src/react-menu3/utils/utils.d.ts +5 -5
- package/dist/src/react-menu3/utils/withHovering.d.ts +1 -1
- package/dist/src/utils/testQuick.d.ts +2 -2
- package/dist/src/utils/testUtil.d.ts +2 -2
- package/dist/src/utils/textValidator.d.ts +2 -2
- package/dist/step-ag-grid.cjs.js +966 -952
- package/dist/step-ag-grid.cjs.js.map +1 -1
- package/dist/step-ag-grid.esm.js +968 -954
- package/dist/step-ag-grid.esm.js.map +1 -1
- package/package.json +26 -41
- package/src/components/ComponentLoadingWrapper.tsx +5 -6
- package/src/components/Grid.tsx +85 -83
- package/src/components/GridCell.test.tsx +15 -15
- package/src/components/GridCell.tsx +46 -44
- package/src/components/GridCellFiller.tsx +5 -4
- package/src/components/GridCellMultiEditor.tsx +7 -7
- package/src/components/GridCellMultiSelectClassRules.tsx +3 -3
- package/src/components/GridIcon.tsx +6 -7
- package/src/components/GridLoadableCell.tsx +2 -2
- package/src/components/GridNoRowsOverlay.tsx +8 -8
- package/src/components/GridPopoverHook.tsx +16 -16
- package/src/components/GridWrapper.tsx +2 -2
- package/src/components/PostSortRowsHook.ts +11 -11
- package/src/components/clickInputWhenContainingCellClicked.tsx +5 -5
- package/src/components/gridFilter/GridFilterButtons.tsx +8 -9
- package/src/components/gridFilter/GridFilterColumnsToggle.tsx +25 -26
- package/src/components/gridFilter/GridFilterDownloadCsvButton.tsx +12 -13
- package/src/components/gridFilter/GridFilterHeaderIconButton.tsx +9 -10
- package/src/components/gridFilter/GridFilterQuick.tsx +6 -6
- package/src/components/gridFilter/GridFilters.tsx +1 -1
- package/src/components/gridFilter/index.ts +7 -7
- package/src/components/gridFilter/useGridFilter.ts +3 -3
- package/src/components/gridForm/GridFormDropDown.tsx +56 -52
- package/src/components/gridForm/GridFormEditBearing.tsx +12 -12
- package/src/components/gridForm/GridFormMessage.tsx +10 -10
- package/src/components/gridForm/GridFormMultiSelect.tsx +53 -51
- package/src/components/gridForm/GridFormMultiSelectGrid.tsx +25 -26
- package/src/components/gridForm/GridFormPopoverMenu.tsx +32 -29
- package/src/components/gridForm/GridFormSubComponentTextArea.tsx +10 -10
- package/src/components/gridForm/GridFormSubComponentTextInput.tsx +8 -8
- package/src/components/gridForm/GridFormTextArea.tsx +11 -11
- package/src/components/gridForm/GridFormTextInput.tsx +11 -11
- package/src/components/gridForm/index.ts +10 -10
- package/src/components/gridHeader/GridHeaderSelect.tsx +9 -9
- package/src/components/gridHeader/index.ts +1 -1
- package/src/components/gridHook/index.ts +1 -1
- package/src/components/gridHook/useGridContextMenu.tsx +7 -7
- package/src/components/gridPopoverEdit/GridButton.tsx +13 -12
- package/src/components/gridPopoverEdit/GridEditBoolean.tsx +19 -18
- package/src/components/gridPopoverEdit/GridPopoutEditMultiSelect.ts +7 -6
- package/src/components/gridPopoverEdit/GridPopoutEditMultiSelectGrid.ts +7 -6
- package/src/components/gridPopoverEdit/GridPopoverEditBearing.ts +9 -9
- package/src/components/gridPopoverEdit/GridPopoverEditDropDown.ts +8 -7
- package/src/components/gridPopoverEdit/GridPopoverMenu.tsx +6 -6
- package/src/components/gridPopoverEdit/GridPopoverMessage.ts +4 -4
- package/src/components/gridPopoverEdit/GridPopoverTextArea.ts +4 -4
- package/src/components/gridPopoverEdit/GridPopoverTextInput.ts +4 -4
- package/src/components/gridPopoverEdit/index.ts +11 -11
- package/src/components/gridRender/GridRenderGenericCell.tsx +5 -5
- package/src/components/gridRender/GridRenderPopoutMenuCell.tsx +8 -9
- package/src/components/gridRender/index.ts +2 -2
- package/src/components/gridUtil.ts +3 -3
- package/src/components/index.ts +19 -19
- package/src/contexts/GridContext.tsx +52 -46
- package/src/contexts/GridContextProvider.test.tsx +14 -14
- package/src/contexts/GridContextProvider.tsx +42 -41
- package/src/contexts/GridPopoverContext.tsx +10 -7
- package/src/contexts/GridPopoverContextProvider.tsx +12 -10
- package/src/contexts/GridSubComponentContext.ts +6 -5
- package/src/contexts/GridUpdatingContext.tsx +5 -4
- package/src/contexts/GridUpdatingContextProvider.tsx +3 -3
- package/src/index.ts +17 -21
- package/src/lui/ActionButton.tsx +42 -41
- package/src/lui/FormError.tsx +4 -4
- package/src/lui/TextAreaInput.tsx +9 -9
- package/src/lui/TextInputFormatted.tsx +11 -11
- package/src/lui/reactUtils.test.tsx +8 -8
- package/src/lui/reactUtils.tsx +2 -2
- package/src/lui/stateDeferredHook.tsx +3 -5
- package/src/lui/timeoutHook.test.tsx +5 -5
- package/src/lui/timeoutHook.tsx +1 -1
- package/src/react-app-env.d.ts +1 -1
- package/src/react-menu3/components/ControlledMenu.tsx +48 -48
- package/src/react-menu3/components/FocusableItem.tsx +7 -7
- package/src/react-menu3/components/Menu.tsx +11 -11
- package/src/react-menu3/components/MenuButton.tsx +4 -4
- package/src/react-menu3/components/MenuDivider.tsx +4 -4
- package/src/react-menu3/components/MenuGroup.tsx +5 -5
- package/src/react-menu3/components/MenuHeader.tsx +4 -4
- package/src/react-menu3/components/MenuItem.tsx +14 -14
- package/src/react-menu3/components/MenuList.tsx +55 -55
- package/src/react-menu3/components/MenuRadioGroup.tsx +7 -7
- package/src/react-menu3/components/SubMenu.tsx +24 -24
- package/src/react-menu3/contexts/EventHandlersContext.ts +2 -2
- package/src/react-menu3/contexts/HoverItemContext.ts +1 -1
- package/src/react-menu3/contexts/ItemSettingsContext.ts +1 -1
- package/src/react-menu3/contexts/MenuListContext.ts +2 -2
- package/src/react-menu3/contexts/MenuListItemContext.ts +2 -2
- package/src/react-menu3/contexts/RadioGroupContext.ts +2 -2
- package/src/react-menu3/contexts/SettingsContext.ts +2 -2
- package/src/react-menu3/hooks/index.ts +9 -9
- package/src/react-menu3/hooks/useBEM.ts +4 -4
- package/src/react-menu3/hooks/useCombinedRef.ts +2 -2
- package/src/react-menu3/hooks/useIsomorphicLayoutEffect.ts +4 -4
- package/src/react-menu3/hooks/useItemEffect.ts +3 -3
- package/src/react-menu3/hooks/useItemState.ts +5 -5
- package/src/react-menu3/hooks/useItems.ts +8 -8
- package/src/react-menu3/hooks/useMenuChange.ts +3 -3
- package/src/react-menu3/hooks/useMenuState.ts +5 -5
- package/src/react-menu3/hooks/useMenuStateAndFocus.ts +4 -4
- package/src/react-menu3/index.ts +11 -11
- package/src/react-menu3/positionUtils/getPositionHelpers.ts +2 -2
- package/src/react-menu3/positionUtils/index.ts +3 -3
- package/src/react-menu3/positionUtils/placeArrowHorizontal.ts +1 -1
- package/src/react-menu3/positionUtils/placeArrowVertical.ts +1 -1
- package/src/react-menu3/positionUtils/placeLeftorRight.ts +13 -13
- package/src/react-menu3/positionUtils/placeToporBottom.ts +15 -15
- package/src/react-menu3/positionUtils/positionContextMenu.ts +4 -4
- package/src/react-menu3/positionUtils/positionMenu.ts +14 -14
- package/src/react-menu3/style-utils/index.ts +24 -24
- package/src/react-menu3/types.ts +15 -15
- package/src/react-menu3/utils/constants.ts +33 -33
- package/src/react-menu3/utils/index.ts +3 -4
- package/src/react-menu3/utils/propTypes2.ts +10 -10
- package/src/react-menu3/utils/utils.ts +14 -14
- package/src/react-menu3/utils/withHovering.tsx +3 -3
- package/src/stories/components/ActionButton.stories.tsx +23 -24
- package/src/stories/grid/FormTest.tsx +15 -16
- package/src/stories/grid/GridDragRow.stories.tsx +33 -34
- package/src/stories/grid/GridFilterButtons.stories.tsx +32 -33
- package/src/stories/grid/GridNoRowsOverlay.stories.tsx +9 -10
- package/src/stories/grid/GridNonEditableRow.stories.tsx +40 -41
- package/src/stories/grid/GridPinnedRow.stories.tsx +25 -26
- package/src/stories/grid/GridPopoutContextMenu.stories.tsx +33 -32
- package/src/stories/grid/GridPopoutEditBoolean.stories.tsx +21 -22
- package/src/stories/grid/GridPopoutEditGeneric.stories.tsx +18 -19
- package/src/stories/grid/GridPopoutEditGenericTextArea.stories.tsx +50 -49
- package/src/stories/grid/GridPopoverEditBearing.stories.tsx +25 -26
- package/src/stories/grid/GridPopoverEditDropDown.stories.tsx +93 -94
- package/src/stories/grid/GridPopoverEditMultiSelect.stories.tsx +62 -63
- package/src/stories/grid/GridPopoverEditMultiSelectGrid.stories.tsx +28 -28
- package/src/stories/grid/GridReadOnly.stories.tsx +66 -67
- package/src/stories/grid/GridViewList.stories.tsx +37 -38
- package/src/stories/grid/gridFormInteraction/GridFormDropDownInteraction.stories.tsx +37 -38
- package/src/stories/grid/gridFormInteraction/GridFormEditBearingCorrectionInteraction.stories.tsx +25 -26
- package/src/stories/grid/gridFormInteraction/GridFormEditBearingInteraction.stories.tsx +25 -26
- package/src/stories/grid/gridFormInteraction/GridFormMultiSelectGridInteraction.stories.tsx +31 -31
- package/src/stories/grid/gridFormInteraction/GridFormMultiSelectInteraction.stories.tsx +47 -48
- package/src/stories/grid/gridFormInteraction/GridFormPopoverMenuInteraction.stories.tsx +44 -45
- package/src/stories/grid/gridFormInteraction/GridFormTextAreaInteraction.stories.tsx +19 -20
- package/src/stories/grid/gridFormInteraction/GridFormTextInputInteraction.stories.tsx +21 -22
- package/src/stories/grid/gridFormStatic/GridFormDropDown.stories.tsx +40 -41
- package/src/stories/grid/gridFormStatic/GridFormEditBearing.stories.tsx +14 -15
- package/src/stories/grid/gridFormStatic/GridFormEditBearingCorrection.stories.tsx +14 -15
- package/src/stories/grid/gridFormStatic/GridFormMessage.stories.tsx +10 -11
- package/src/stories/grid/gridFormStatic/GridFormMultiSelect.stories.tsx +20 -21
- package/src/stories/grid/gridFormStatic/GridFormPopoverMenu.stories.tsx +16 -17
- package/src/stories/grid/gridFormStatic/GridFormTextArea.stories.tsx +13 -14
- package/src/stories/grid/gridFormStatic/GridFormTextInput.stories.tsx +13 -14
- package/src/stories/grid/interactions/GridKeyboardInteractions.stories.tsx +68 -71
- package/src/stories/react-menu/ReactMenu.stories.tsx +26 -26
- package/src/utils/bearing.test.ts +44 -44
- package/src/utils/bearing.ts +20 -20
- package/src/utils/deferredPromise.ts +1 -1
- package/src/utils/storybookTestUtil.ts +2 -2
- package/src/utils/testQuick.ts +15 -14
- package/src/utils/testUtil.ts +31 -36
- package/src/utils/textMatcher.test.ts +9 -9
- package/src/utils/textMatcher.ts +8 -8
- package/src/utils/textValidator.test.ts +56 -56
- package/src/utils/textValidator.ts +11 -11
- package/src/utils/util.test.ts +20 -20
- package/src/utils/util.ts +7 -7
package/src/utils/testQuick.ts
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* @param container Optional container
|
|
6
6
|
* @return HTMLElement array
|
|
7
7
|
*/
|
|
8
|
-
import { IconName } from
|
|
8
|
+
import { IconName } from '@linzjs/lui/dist/components/LuiIcon/LuiIcon';
|
|
9
9
|
|
|
10
|
-
import { wait } from
|
|
10
|
+
import { wait } from './util';
|
|
11
11
|
|
|
12
12
|
const queryAllBySelector = <T extends HTMLElement>(selector: string, container: HTMLElement = document.body): T[] =>
|
|
13
13
|
Array.from(container.querySelectorAll<T>(selector));
|
|
@@ -17,7 +17,8 @@ const queryAllBySelector = <T extends HTMLElement>(selector: string, container:
|
|
|
17
17
|
*/
|
|
18
18
|
export interface IQueryQuick {
|
|
19
19
|
testId?: string;
|
|
20
|
-
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
|
|
21
|
+
tagName?: 'button' | 'span' | 'div' | 'input' | 'textarea' | any;
|
|
21
22
|
text?: string | RegExp;
|
|
22
23
|
icon?: IconName;
|
|
23
24
|
ariaLabel?: string;
|
|
@@ -26,11 +27,11 @@ export interface IQueryQuick {
|
|
|
26
27
|
child?: IQueryQuick;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
const escapeSelectorParam = (param: string): string => param.replace(/["\\]/g,
|
|
30
|
+
const escapeSelectorParam = (param: string): string => param.replace(/["\\]/g, '\\$&');
|
|
30
31
|
|
|
31
32
|
export const getMatcher = (matcherText: string | RegExp) => {
|
|
32
33
|
const textMatcher =
|
|
33
|
-
typeof matcherText ===
|
|
34
|
+
typeof matcherText === 'string'
|
|
34
35
|
? (text?: string) => text != null && text.toLowerCase() === matcherText.toLowerCase()
|
|
35
36
|
: (text?: string) => text != null && matcherText.test(text);
|
|
36
37
|
return (e: HTMLElement) => textMatcher(e.innerHTML?.trim()) || textMatcher(e.innerText?.trim());
|
|
@@ -46,7 +47,7 @@ const quickSelector = <T extends HTMLElement>(
|
|
|
46
47
|
props: IQueryQuick,
|
|
47
48
|
container?: HTMLElement,
|
|
48
49
|
): { selector: string; els: T[] } => {
|
|
49
|
-
let selector =
|
|
50
|
+
let selector = '';
|
|
50
51
|
let lastIQueryQuick = props;
|
|
51
52
|
for (let loop: IQueryQuick | undefined = props; loop; loop = loop.child) {
|
|
52
53
|
lastIQueryQuick = loop;
|
|
@@ -56,11 +57,11 @@ const quickSelector = <T extends HTMLElement>(
|
|
|
56
57
|
loop.testId && (selector += `[data-testid="${escapeSelectorParam(loop.testId)}"]`);
|
|
57
58
|
loop.icon && (selector += `[data-icon='${loop.icon}']`);
|
|
58
59
|
loop.classes && (selector += loop.classes);
|
|
59
|
-
selector +=
|
|
60
|
+
selector += ' ';
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
if (selector.trim() ==
|
|
63
|
-
throw
|
|
63
|
+
if (selector.trim() == '') {
|
|
64
|
+
throw 'get/query/findQuick needs at least one defined parameter';
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
let els = queryAllBySelector<T>(selector, container);
|
|
@@ -73,10 +74,10 @@ const quickSelector = <T extends HTMLElement>(
|
|
|
73
74
|
return {
|
|
74
75
|
selector: [
|
|
75
76
|
selector,
|
|
76
|
-
typeof lastIQueryQuick.text
|
|
77
|
+
typeof lastIQueryQuick.text === 'string' ? JSON.stringify(lastIQueryQuick.text) : lastIQueryQuick.text,
|
|
77
78
|
]
|
|
78
79
|
.filter((r) => r)
|
|
79
|
-
.join(
|
|
80
|
+
.join(' '),
|
|
80
81
|
els,
|
|
81
82
|
};
|
|
82
83
|
};
|
|
@@ -91,9 +92,9 @@ const quickSelector = <T extends HTMLElement>(
|
|
|
91
92
|
export const queryQuick = <T extends HTMLElement>(filter: IQueryQuick, container?: HTMLElement): T | null => {
|
|
92
93
|
const { els, selector } = quickSelector<T>(filter, container);
|
|
93
94
|
if (els.length > 1) {
|
|
94
|
-
throw `Found multiple(${els.length}) elements by selector ${selector}\n${els
|
|
95
|
-
(el, index) => `${index}: ${el.parentElement?.innerHTML}\n\n
|
|
96
|
-
|
|
95
|
+
throw `Found multiple(${els.length}) elements by selector ${selector}\n${els
|
|
96
|
+
.map((el, index) => `${index}: ${el.parentElement?.innerHTML}\n\n`)
|
|
97
|
+
.join()}`;
|
|
97
98
|
}
|
|
98
99
|
return els[0] ?? null;
|
|
99
100
|
};
|
package/src/utils/testUtil.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { act, waitFor, within } from
|
|
2
|
-
import userEvent from
|
|
3
|
-
import { isEqual } from
|
|
1
|
+
import { act, waitFor, within } from '@testing-library/react';
|
|
2
|
+
import userEvent from '@testing-library/user-event';
|
|
3
|
+
import { isEqual } from 'lodash-es';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { findQuick, getAllQuick, getMatcher, getQuick, IQueryQuick, queryQuick } from './testQuick';
|
|
6
6
|
|
|
7
7
|
let user = userEvent;
|
|
8
8
|
/**
|
|
@@ -10,16 +10,17 @@ let user = userEvent;
|
|
|
10
10
|
* @param customisedUserEvent
|
|
11
11
|
*/
|
|
12
12
|
export const setUpUserEvent = (customisedUserEvent: any) => {
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
13
14
|
user = customisedUserEvent;
|
|
14
15
|
};
|
|
15
16
|
|
|
16
|
-
export const countRows =
|
|
17
|
+
export const countRows = (within?: HTMLElement): number => {
|
|
17
18
|
return getAllQuick({ tagName: `div[row-id]:not(:empty)` }, within).length;
|
|
18
19
|
};
|
|
19
20
|
|
|
20
21
|
export const findRowByIndex = async (rowIndex: number | string, within?: HTMLElement): Promise<HTMLDivElement> => {
|
|
21
|
-
await waitFor(
|
|
22
|
-
expect(getAllQuick({ classes:
|
|
22
|
+
await waitFor(() => {
|
|
23
|
+
expect(getAllQuick({ classes: '.ag-row' }).length > 0).toBe(true);
|
|
23
24
|
});
|
|
24
25
|
//if this is not wrapped in an act console errors are logged during testing
|
|
25
26
|
let row!: HTMLDivElement;
|
|
@@ -28,7 +29,6 @@ export const findRowByIndex = async (rowIndex: number | string, within?: HTMLEle
|
|
|
28
29
|
{ tagName: `.ag-center-cols-container div[row-index='${rowIndex}']:not(:empty)` },
|
|
29
30
|
within,
|
|
30
31
|
);
|
|
31
|
-
// @ts-ignore
|
|
32
32
|
let combineChildren = [...Array.from(row.children)];
|
|
33
33
|
|
|
34
34
|
const leftCols = queryQuick<HTMLDivElement>(
|
|
@@ -36,7 +36,6 @@ export const findRowByIndex = async (rowIndex: number | string, within?: HTMLEle
|
|
|
36
36
|
within,
|
|
37
37
|
);
|
|
38
38
|
if (leftCols) {
|
|
39
|
-
// @ts-ignore
|
|
40
39
|
combineChildren = [...Array.from(leftCols.children), ...combineChildren];
|
|
41
40
|
}
|
|
42
41
|
|
|
@@ -45,7 +44,6 @@ export const findRowByIndex = async (rowIndex: number | string, within?: HTMLEle
|
|
|
45
44
|
within,
|
|
46
45
|
);
|
|
47
46
|
if (rightCols) {
|
|
48
|
-
// @ts-ignore
|
|
49
47
|
combineChildren = [...Array.from(rightCols.children), ...combineChildren];
|
|
50
48
|
}
|
|
51
49
|
|
|
@@ -55,8 +53,8 @@ export const findRowByIndex = async (rowIndex: number | string, within?: HTMLEle
|
|
|
55
53
|
};
|
|
56
54
|
|
|
57
55
|
export const findRow = async (rowId: number | string, within?: HTMLElement): Promise<HTMLDivElement> => {
|
|
58
|
-
await waitFor(
|
|
59
|
-
expect(getAllQuick({ classes:
|
|
56
|
+
await waitFor(() => {
|
|
57
|
+
expect(getAllQuick({ classes: '.ag-row' }).length > 0).toBe(true);
|
|
60
58
|
});
|
|
61
59
|
//if this is not wrapped in an act console errors are logged during testing
|
|
62
60
|
let row!: HTMLDivElement;
|
|
@@ -65,7 +63,6 @@ export const findRow = async (rowId: number | string, within?: HTMLElement): Pro
|
|
|
65
63
|
{ tagName: `.ag-center-cols-container div[row-id='${rowId}']:not(:empty)` },
|
|
66
64
|
within,
|
|
67
65
|
);
|
|
68
|
-
// @ts-ignore
|
|
69
66
|
let combineChildren = [...Array.from(row.children)];
|
|
70
67
|
|
|
71
68
|
const leftCols = queryQuick<HTMLDivElement>(
|
|
@@ -73,7 +70,6 @@ export const findRow = async (rowId: number | string, within?: HTMLElement): Pro
|
|
|
73
70
|
within,
|
|
74
71
|
);
|
|
75
72
|
if (leftCols) {
|
|
76
|
-
// @ts-ignore
|
|
77
73
|
combineChildren = [...Array.from(leftCols.children), ...combineChildren];
|
|
78
74
|
}
|
|
79
75
|
|
|
@@ -82,7 +78,6 @@ export const findRow = async (rowId: number | string, within?: HTMLElement): Pro
|
|
|
82
78
|
within,
|
|
83
79
|
);
|
|
84
80
|
if (rightCols) {
|
|
85
|
-
// @ts-ignore
|
|
86
81
|
combineChildren = [...Array.from(rightCols.children), ...combineChildren];
|
|
87
82
|
}
|
|
88
83
|
|
|
@@ -91,33 +86,33 @@ export const findRow = async (rowId: number | string, within?: HTMLElement): Pro
|
|
|
91
86
|
return row;
|
|
92
87
|
};
|
|
93
88
|
|
|
94
|
-
export const queryRow =
|
|
89
|
+
export const queryRow = (rowId: number | string, within?: HTMLElement): HTMLDivElement | null => {
|
|
95
90
|
return queryQuick<HTMLDivElement>({ tagName: `div[row-id='${rowId}']:not(:empty)` }, within);
|
|
96
91
|
};
|
|
97
92
|
|
|
98
93
|
const _selectRow = async (
|
|
99
|
-
select:
|
|
94
|
+
select: 'select' | 'deselect' | 'toggle',
|
|
100
95
|
rowId: string | number,
|
|
101
96
|
within?: HTMLElement,
|
|
102
97
|
): Promise<void> => {
|
|
103
98
|
const row = await findRow(rowId, within);
|
|
104
|
-
const isSelected = row.className.includes(
|
|
105
|
-
if (select ===
|
|
106
|
-
const cell = await findCell(rowId,
|
|
99
|
+
const isSelected = row.className.includes('ag-row-selected');
|
|
100
|
+
if (select === 'toggle' || (select === 'select' && !isSelected) || (select === 'deselect' && isSelected)) {
|
|
101
|
+
const cell = await findCell(rowId, 'selection', within);
|
|
107
102
|
await user.click(cell);
|
|
108
103
|
await waitFor(async () => {
|
|
109
104
|
const row = await findRow(rowId, within);
|
|
110
|
-
const nowSelected = row.className.includes(
|
|
105
|
+
const nowSelected = row.className.includes('ag-row-selected');
|
|
111
106
|
if (nowSelected === isSelected) throw `Row ${rowId} won't select`;
|
|
112
107
|
});
|
|
113
108
|
}
|
|
114
109
|
};
|
|
115
110
|
|
|
116
111
|
export const selectRow = async (rowId: string | number, within?: HTMLElement): Promise<void> =>
|
|
117
|
-
_selectRow(
|
|
112
|
+
_selectRow('select', rowId, within);
|
|
118
113
|
|
|
119
114
|
export const deselectRow = async (rowId: string | number, within?: HTMLElement): Promise<void> =>
|
|
120
|
-
_selectRow(
|
|
115
|
+
_selectRow('deselect', rowId, within);
|
|
121
116
|
|
|
122
117
|
export const findCell = async (rowId: number | string, colId: string, within?: HTMLElement): Promise<HTMLElement> => {
|
|
123
118
|
const row = await findRow(rowId, within);
|
|
@@ -157,14 +152,14 @@ export const editCell = async (rowId: number | string, colId: string, within?: H
|
|
|
157
152
|
|
|
158
153
|
export const isCellReadOnly = async (rowId: number | string, colId: string, within?: HTMLElement): Promise<boolean> => {
|
|
159
154
|
const cell = await findCell(rowId, colId, within);
|
|
160
|
-
return cell.className.includes(
|
|
155
|
+
return cell.className.includes('GridCell-readonly');
|
|
161
156
|
};
|
|
162
157
|
|
|
163
|
-
export const findOpenPopover = () => findQuick({ classes:
|
|
158
|
+
export const findOpenPopover = () => findQuick({ classes: '.szh-menu--state-open' });
|
|
164
159
|
|
|
165
160
|
export const queryMenuOption = async (menuOptionText: string | RegExp): Promise<HTMLElement | null> => {
|
|
166
161
|
const openMenu = await findOpenPopover();
|
|
167
|
-
const els = await within(openMenu).findAllByRole(
|
|
162
|
+
const els = await within(openMenu).findAllByRole('menuitem');
|
|
168
163
|
const matcher = getMatcher(menuOptionText);
|
|
169
164
|
const result = els.find(matcher);
|
|
170
165
|
return result ?? null;
|
|
@@ -190,7 +185,7 @@ export const validateMenuOptions = async (
|
|
|
190
185
|
): Promise<boolean> => {
|
|
191
186
|
await editCell(rowId, colId);
|
|
192
187
|
const openMenu = await findOpenPopover();
|
|
193
|
-
const actualOptions = (await within(openMenu).findAllByRole(
|
|
188
|
+
const actualOptions = (await within(openMenu).findAllByRole('menuitem')).map((menuItem) => menuItem.textContent);
|
|
194
189
|
return isEqual(actualOptions, expectedMenuOptions);
|
|
195
190
|
};
|
|
196
191
|
|
|
@@ -221,7 +216,7 @@ export const openAndFindMenuOption = async (
|
|
|
221
216
|
|
|
222
217
|
export const getMultiSelectOptions = async () => {
|
|
223
218
|
const openMenu = await findOpenPopover();
|
|
224
|
-
return getAllQuick<HTMLInputElement>({ role:
|
|
219
|
+
return getAllQuick<HTMLInputElement>({ role: 'menuitem', child: { tagName: 'input,textarea' } }, openMenu).map(
|
|
225
220
|
(input) => {
|
|
226
221
|
return {
|
|
227
222
|
v: input.value,
|
|
@@ -233,7 +228,7 @@ export const getMultiSelectOptions = async () => {
|
|
|
233
228
|
|
|
234
229
|
export const findMultiSelectOption = async (value: string): Promise<HTMLElement> => {
|
|
235
230
|
const openMenu = await findOpenPopover();
|
|
236
|
-
return getQuick({ role:
|
|
231
|
+
return getQuick({ role: 'menuitem', child: { tagName: `input[value='${value}']` } }, openMenu);
|
|
237
232
|
};
|
|
238
233
|
|
|
239
234
|
export const clickMultiSelectOption = async (value: string): Promise<void> => {
|
|
@@ -255,14 +250,14 @@ export const typeOnlyInput = async (value: string): Promise<void> =>
|
|
|
255
250
|
typeInput(value, { child: { tagName: "input[type='text'], textarea" } });
|
|
256
251
|
|
|
257
252
|
export const typeInputByLabel = async (value: string, labelText: string): Promise<void> => {
|
|
258
|
-
const labels = getAllQuick({ child: { tagName:
|
|
253
|
+
const labels = getAllQuick({ child: { tagName: 'label' } }).filter((l) => l.textContent === labelText);
|
|
259
254
|
if (labels.length === 0) {
|
|
260
255
|
throw Error(`Label not found for text: ${labelText}`);
|
|
261
256
|
}
|
|
262
257
|
if (labels.length > 1) {
|
|
263
258
|
throw Error(`Multiple labels found for text: ${labelText}`);
|
|
264
259
|
}
|
|
265
|
-
const inputId = labels[0].getAttribute(
|
|
260
|
+
const inputId = labels[0].getAttribute('for');
|
|
266
261
|
await typeInput(value, { child: { tagName: `input[id='${inputId}'], textarea[id='${inputId}']` } });
|
|
267
262
|
};
|
|
268
263
|
|
|
@@ -272,16 +267,16 @@ export const typeInputByPlaceholder = async (value: string, placeholder: string)
|
|
|
272
267
|
});
|
|
273
268
|
|
|
274
269
|
export const typeOtherInput = async (value: string): Promise<void> =>
|
|
275
|
-
typeInput(value, { classes:
|
|
270
|
+
typeInput(value, { classes: '.subComponent', child: { tagName: "input[type='text']" } });
|
|
276
271
|
|
|
277
272
|
export const typeOtherTextArea = async (value: string): Promise<void> =>
|
|
278
|
-
typeInput(value, { classes:
|
|
273
|
+
typeInput(value, { classes: '.subComponent', child: { tagName: 'textarea' } });
|
|
279
274
|
|
|
280
275
|
export const closeMenu = () => user.click(document.body);
|
|
281
276
|
export const closePopover = () => user.click(document.body);
|
|
282
277
|
|
|
283
278
|
export const findActionButton = (text: string, container?: HTMLElement): Promise<HTMLElement> =>
|
|
284
|
-
findQuick({ tagName:
|
|
279
|
+
findQuick({ tagName: 'button', child: { classes: '.ActionButton-minimalAreaDisplay', text: text } }, container);
|
|
285
280
|
|
|
286
281
|
export const clickActionButton = async (text: string, container?: HTMLElement): Promise<void> => {
|
|
287
282
|
const button = await findActionButton(text, container);
|
|
@@ -289,11 +284,11 @@ export const clickActionButton = async (text: string, container?: HTMLElement):
|
|
|
289
284
|
};
|
|
290
285
|
|
|
291
286
|
export const waitForGridReady = async (props?: { grid?: HTMLElement; timeout?: number }) =>
|
|
292
|
-
waitFor(() => expect(getAllQuick({ classes:
|
|
287
|
+
waitFor(() => expect(getAllQuick({ classes: '.Grid-ready' }, props?.grid)).toBeInTheDocument(), {
|
|
293
288
|
timeout: props?.timeout ?? 5000,
|
|
294
289
|
});
|
|
295
290
|
|
|
296
291
|
export const waitForGridRows = async (props?: { grid?: HTMLElement; timeout?: number }) =>
|
|
297
|
-
waitFor(
|
|
292
|
+
waitFor(() => expect(getAllQuick({ classes: '.ag-row' }, props?.grid).length > 0).toBe(true), {
|
|
298
293
|
timeout: props?.timeout ?? 5000,
|
|
299
294
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { textMatch } from
|
|
1
|
+
import { textMatch } from './textMatcher';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* "L" => L*
|
|
@@ -11,18 +11,18 @@ import { textMatch } from "./textMatcher";
|
|
|
11
11
|
* "=!A" => all values must not match exactly A
|
|
12
12
|
* Returns true if there's a text match.
|
|
13
13
|
*/
|
|
14
|
-
describe(
|
|
15
|
-
test(
|
|
14
|
+
describe('textMatch', () => {
|
|
15
|
+
test('textMatch', () => {
|
|
16
16
|
const validate = [
|
|
17
17
|
{
|
|
18
|
-
value:
|
|
19
|
-
matched: [
|
|
20
|
-
unmatched: [
|
|
18
|
+
value: '',
|
|
19
|
+
matched: [''],
|
|
20
|
+
unmatched: ['a', 'a*', '*a*'],
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
|
-
value:
|
|
24
|
-
matched: [
|
|
25
|
-
unmatched: [
|
|
23
|
+
value: 'two words',
|
|
24
|
+
matched: ['', '*wo', '*or*', 'tw', 'two', 'tw wo', 'tw, rr', '=!tw'],
|
|
25
|
+
unmatched: ['ds', 'o', '=tw', 'tw rr', '!two', '!tw*'],
|
|
26
26
|
},
|
|
27
27
|
];
|
|
28
28
|
|
package/src/utils/textMatcher.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { isEmpty, partition } from
|
|
2
|
-
import { isMatch } from
|
|
1
|
+
import { isEmpty, partition } from 'lodash-es';
|
|
2
|
+
import { isMatch } from 'matcher';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Text matching with wildcards and multiple matchers.
|
|
@@ -17,22 +17,22 @@ export const textMatch = (text: string | undefined | null, filter: string): bool
|
|
|
17
17
|
if (text == null) return true;
|
|
18
18
|
|
|
19
19
|
const superFilters = filter
|
|
20
|
-
.split(
|
|
20
|
+
.split(',')
|
|
21
21
|
.map((sf) => sf.trim())
|
|
22
22
|
.filter((sf) => sf)
|
|
23
23
|
.map((r) =>
|
|
24
24
|
r
|
|
25
25
|
.split(/\s+/)
|
|
26
|
-
.map((f) => (f.startsWith(
|
|
27
|
-
.join(
|
|
26
|
+
.map((f) => (f.startsWith('=') ? f.slice(1) : f + '*'))
|
|
27
|
+
.join(' '),
|
|
28
28
|
);
|
|
29
|
-
const [negativeFilters, positiveFilters] = partition(superFilters, (superFilters) => superFilters.startsWith(
|
|
29
|
+
const [negativeFilters, positiveFilters] = partition(superFilters, (superFilters) => superFilters.startsWith('!'));
|
|
30
30
|
|
|
31
|
-
const values = text.replaceAll(
|
|
31
|
+
const values = text.replaceAll(',', ' ').trim().split(/\s+/);
|
|
32
32
|
return (
|
|
33
33
|
(isEmpty(positiveFilters) || // Not filtered
|
|
34
34
|
positiveFilters.some((superFilter) => {
|
|
35
|
-
const subFilters = superFilter.split(/\s+/).map((s) => s.replaceAll(/([!?])/g,
|
|
35
|
+
const subFilters = superFilter.split(/\s+/).map((s) => s.replaceAll(/([!?])/g, '\\$1'));
|
|
36
36
|
return subFilters.every((subFilter) => values.some((value) => isMatch(value, subFilter)));
|
|
37
37
|
})) &&
|
|
38
38
|
(isEmpty(negativeFilters) ||
|
|
@@ -1,89 +1,89 @@
|
|
|
1
|
-
import { GridBaseRow } from
|
|
2
|
-
import { TextInputValidator, TextInputValidatorProps } from
|
|
1
|
+
import { GridBaseRow } from '../components/Grid';
|
|
2
|
+
import { TextInputValidator, TextInputValidatorProps } from './textValidator';
|
|
3
3
|
|
|
4
|
-
describe(
|
|
5
|
-
test(
|
|
4
|
+
describe('TextInputValidator', () => {
|
|
5
|
+
test('number format', () => {
|
|
6
6
|
const validate = [
|
|
7
7
|
{
|
|
8
8
|
numberFormat: {},
|
|
9
9
|
tests: [
|
|
10
|
-
[
|
|
11
|
-
[
|
|
12
|
-
[
|
|
13
|
-
[
|
|
14
|
-
[
|
|
15
|
-
[
|
|
16
|
-
[
|
|
17
|
-
[
|
|
18
|
-
[
|
|
10
|
+
['x', 'Must be a valid number'],
|
|
11
|
+
['1.2e6', 'Must be a valid number'],
|
|
12
|
+
['', null],
|
|
13
|
+
['1', null],
|
|
14
|
+
['1.2', null],
|
|
15
|
+
['.2', null],
|
|
16
|
+
['-1.2', null],
|
|
17
|
+
['-.2', null],
|
|
18
|
+
['-.2', null],
|
|
19
19
|
],
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
numberFormat: { geMin: 0, leMax: 10 },
|
|
23
23
|
tests: [
|
|
24
|
-
[
|
|
25
|
-
[
|
|
26
|
-
[
|
|
27
|
-
[
|
|
28
|
-
[
|
|
29
|
-
[
|
|
30
|
-
[
|
|
24
|
+
['x', 'Must be a valid number'],
|
|
25
|
+
['', null],
|
|
26
|
+
['1', null],
|
|
27
|
+
['0', null],
|
|
28
|
+
['-1', 'Must not be less than 0'],
|
|
29
|
+
['10', null],
|
|
30
|
+
['10.1', 'Must not be greater than 10'],
|
|
31
31
|
],
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
34
|
numberFormat: { gtMin: 0, ltMax: 10 },
|
|
35
35
|
tests: [
|
|
36
|
-
[
|
|
37
|
-
[
|
|
38
|
-
[
|
|
39
|
-
[
|
|
40
|
-
[
|
|
36
|
+
['x', 'Must be a valid number'],
|
|
37
|
+
['', null],
|
|
38
|
+
['1', null],
|
|
39
|
+
['0', 'Must be greater than 0'],
|
|
40
|
+
['10', 'Must be less than 10'],
|
|
41
41
|
],
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
44
|
numberFormat: { precision: 3 },
|
|
45
45
|
tests: [
|
|
46
|
-
[
|
|
47
|
-
[
|
|
48
|
-
[
|
|
49
|
-
[
|
|
50
|
-
[
|
|
51
|
-
[
|
|
46
|
+
['x', 'Must be a valid number'],
|
|
47
|
+
['', null],
|
|
48
|
+
['1.22', null],
|
|
49
|
+
['0.122', null],
|
|
50
|
+
['1.123', 'Must have no more than 3 digits precision'],
|
|
51
|
+
['0.1234', 'Must have no more than 3 digits precision'],
|
|
52
52
|
],
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
numberFormat: { scale: 2 },
|
|
56
56
|
tests: [
|
|
57
|
-
[
|
|
58
|
-
[
|
|
59
|
-
[
|
|
60
|
-
[
|
|
61
|
-
[
|
|
57
|
+
['x', 'Must be a valid number'],
|
|
58
|
+
['', null],
|
|
59
|
+
['1.22', null],
|
|
60
|
+
['0.122', 'Must have no more than 2 decimal places'],
|
|
61
|
+
['1.123', 'Must have no more than 2 decimal places'],
|
|
62
62
|
],
|
|
63
63
|
},
|
|
64
64
|
{
|
|
65
65
|
numberFormat: { scale: 0 },
|
|
66
66
|
tests: [
|
|
67
|
-
[
|
|
68
|
-
[
|
|
67
|
+
['1', null],
|
|
68
|
+
['1.1', 'Must be a whole number'],
|
|
69
69
|
],
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
72
|
numberFormat: { notZero: true },
|
|
73
73
|
tests: [
|
|
74
|
-
[
|
|
75
|
-
[
|
|
74
|
+
['1', null],
|
|
75
|
+
['0', 'Must not be 0'],
|
|
76
76
|
],
|
|
77
77
|
},
|
|
78
78
|
{
|
|
79
79
|
required: true,
|
|
80
80
|
tests: [
|
|
81
|
-
[
|
|
82
|
-
[
|
|
83
|
-
[
|
|
84
|
-
[
|
|
85
|
-
[
|
|
86
|
-
[
|
|
81
|
+
['xx', null],
|
|
82
|
+
['', 'Must not be empty'],
|
|
83
|
+
['\t', 'Must not be empty'],
|
|
84
|
+
['\n', 'Must not be empty'],
|
|
85
|
+
['\r', 'Must not be empty'],
|
|
86
|
+
[' ', 'Must not be empty'],
|
|
87
87
|
],
|
|
88
88
|
},
|
|
89
89
|
] as (TextInputValidatorProps<GridBaseRow> & { tests: [string, string | undefined][] })[];
|
|
@@ -98,21 +98,21 @@ describe("TextInputValidator", () => {
|
|
|
98
98
|
});
|
|
99
99
|
});
|
|
100
100
|
|
|
101
|
-
test(
|
|
101
|
+
test('validator is called', () => {
|
|
102
102
|
const fn = jest.fn();
|
|
103
|
-
TextInputValidator({ invalid: fn },
|
|
103
|
+
TextInputValidator({ invalid: fn }, '', { id: 0 }, {});
|
|
104
104
|
expect(fn).toHaveBeenCalled();
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
-
test(
|
|
108
|
-
expect(TextInputValidator({ maxLength: 2 },
|
|
109
|
-
expect(TextInputValidator({ maxLength: 2 },
|
|
110
|
-
expect(TextInputValidator({ maxLength: 2 },
|
|
107
|
+
test('maxLength', () => {
|
|
108
|
+
expect(TextInputValidator({ maxLength: 2 }, '', { id: 0 }, {})).toBeNull();
|
|
109
|
+
expect(TextInputValidator({ maxLength: 2 }, 'aa', { id: 0 }, {})).toBeNull();
|
|
110
|
+
expect(TextInputValidator({ maxLength: 2 }, 'aaa', { id: 0 }, {})).toBe('Must be no longer than 2 characters');
|
|
111
111
|
});
|
|
112
112
|
|
|
113
|
-
test(
|
|
114
|
-
expect(TextInputValidator({ maxBytes: 2 },
|
|
115
|
-
expect(TextInputValidator({ maxBytes: 2 },
|
|
116
|
-
expect(TextInputValidator({ maxBytes: 2 },
|
|
113
|
+
test('maxBytes', () => {
|
|
114
|
+
expect(TextInputValidator({ maxBytes: 2 }, '', { id: 0 }, {})).toBeNull();
|
|
115
|
+
expect(TextInputValidator({ maxBytes: 2 }, 'aa', { id: 0 }, {})).toBeNull();
|
|
116
|
+
expect(TextInputValidator({ maxBytes: 2 }, 'a–', { id: 0 }, {})).toBe('Must be no longer than 2 bytes');
|
|
117
117
|
});
|
|
118
118
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { ReactElement } from
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
2
|
|
|
3
|
-
import { GridBaseRow } from
|
|
4
|
-
import { isFloat, stringByteLengthIsInvalid } from
|
|
3
|
+
import { GridBaseRow } from '../components/Grid';
|
|
4
|
+
import { isFloat, stringByteLengthIsInvalid } from './util';
|
|
5
5
|
|
|
6
6
|
export interface TextInputValidatorProps<TData extends GridBaseRow> {
|
|
7
7
|
required?: boolean;
|
|
@@ -28,11 +28,11 @@ export const TextInputValidator = <TData extends GridBaseRow>(
|
|
|
28
28
|
if (value == null) return null;
|
|
29
29
|
|
|
30
30
|
// This can happen because subcomponent is invoked without type safety
|
|
31
|
-
if (typeof value !==
|
|
32
|
-
return
|
|
31
|
+
if (typeof value !== 'string') {
|
|
32
|
+
return 'Value is not a string';
|
|
33
33
|
}
|
|
34
|
-
if (props.required && value.trim() ==
|
|
35
|
-
return
|
|
34
|
+
if (props.required && value.trim() == '') {
|
|
35
|
+
return 'Must not be empty';
|
|
36
36
|
}
|
|
37
37
|
if (props.maxLength && value.length > props.maxLength) {
|
|
38
38
|
return `Must be no longer than ${props.maxLength} characters`;
|
|
@@ -42,10 +42,10 @@ export const TextInputValidator = <TData extends GridBaseRow>(
|
|
|
42
42
|
}
|
|
43
43
|
const nf = props.numberFormat;
|
|
44
44
|
if (nf) {
|
|
45
|
-
if (value !=
|
|
45
|
+
if (value != '' && !isFloat(value)) {
|
|
46
46
|
return `Must be a valid number`;
|
|
47
47
|
}
|
|
48
|
-
if (value !=
|
|
48
|
+
if (value != '') {
|
|
49
49
|
const number = parseFloat(value);
|
|
50
50
|
if (nf.notZero && number === 0) {
|
|
51
51
|
return `Must not be 0`;
|
|
@@ -63,13 +63,13 @@ export const TextInputValidator = <TData extends GridBaseRow>(
|
|
|
63
63
|
return `Must not be greater than ${nf.leMax.toLocaleString()}`;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
if (nf.precision != null && value !=
|
|
66
|
+
if (nf.precision != null && value != '') {
|
|
67
67
|
if (parseFloat(number.toPrecision(nf.precision)) != number) {
|
|
68
68
|
return `Must have no more than ${nf.precision} digits precision`;
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
if (nf.scale != null && value !=
|
|
72
|
+
if (nf.scale != null && value != '') {
|
|
73
73
|
if (parseFloat(number.toFixed(nf.scale)) != number) {
|
|
74
74
|
return nf.scale == 0 ? `Must be a whole number` : `Must have no more than ${nf.scale} decimal places`;
|
|
75
75
|
}
|