@jobber/components-native 0.101.3 → 0.101.4

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.
Files changed (182) hide show
  1. package/dist/package.json +19 -11
  2. package/dist/src/ActionItem/ActionItem.test.js +81 -0
  3. package/dist/src/ActionItem/ActionItemGroup.test.js +25 -0
  4. package/dist/src/ActionItem/components/ActionItemContainer.test.js +24 -0
  5. package/dist/src/ActionLabel/ActionLabel.test.js +81 -0
  6. package/dist/src/ActivityIndicator/ActivityIndicator.test.js +23 -0
  7. package/dist/src/AtlantisContext/AtlantisContext.test.js +35 -0
  8. package/dist/src/AtlantisThemeContext/AtlantisThemeContext.test.js +65 -0
  9. package/dist/src/AtlantisThemeContext/buildThemedStyles.test.js +43 -0
  10. package/dist/src/AutoLink/AutoLink.test.js +133 -0
  11. package/dist/src/AutoLink/components/Link/Link.test.js +18 -0
  12. package/dist/src/Banner/Banner.test.js +98 -0
  13. package/dist/src/BottomSheet/BottomSheet.test.js +105 -0
  14. package/dist/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.test.js +19 -0
  15. package/dist/src/BottomSheet/hooks/useBottomSheetBackHandler.test.js +68 -0
  16. package/dist/src/Button/Button.test.js +228 -0
  17. package/dist/src/Button/components/InternalButtonLoading/InternalButtonLoading.test.js +25 -0
  18. package/dist/src/ButtonGroup/ButtonGroup.test.js +153 -0
  19. package/dist/src/Card/Card.test.js +80 -0
  20. package/dist/src/Card/components/InternalCardHeader.test.js +18 -0
  21. package/dist/src/Checkbox/Checkbox.test.js +135 -0
  22. package/dist/src/Checkbox/CheckboxGroup.test.js +197 -0
  23. package/dist/src/Checkbox/CheckboxGroupReducer.test.js +25 -0
  24. package/dist/src/Chip/Chip.test.js +69 -0
  25. package/dist/src/Content/Content.test.js +250 -0
  26. package/dist/src/ContentOverlay/ContentOverlay.test.js +297 -0
  27. package/dist/src/ContentOverlay/computeContentOverlayBehavior.test.js +197 -0
  28. package/dist/src/ContentOverlay/hooks/useBottomSheetModalBackHandler.test.js +62 -0
  29. package/dist/src/ContentOverlay/hooks/useKeyboardVisibility.test.js +41 -0
  30. package/dist/src/ContentOverlay/hooks/useViewLayoutHeight.test.js +62 -0
  31. package/dist/src/Disclosure/Disclosure.test.js +64 -0
  32. package/dist/src/Divider/Divider.test.js +65 -0
  33. package/dist/src/EmptyState/EmptyState.test.js +82 -0
  34. package/dist/src/ErrorMessageWrapper/ErrorMessageWrapper.test.js +29 -0
  35. package/dist/src/Flex/Flex.test.js +104 -0
  36. package/dist/src/Form/Form.test.js +393 -0
  37. package/dist/src/Form/components/FormErrorBanner/FormErrorBanner.test.js +41 -0
  38. package/dist/src/Form/components/FormMessage/FormMessage.test.js +73 -0
  39. package/dist/src/Form/components/FormMessageBanner/FormMessageBanner.test.js +30 -0
  40. package/dist/src/Form/components/FormSaveButton/FormSaveButton.test.js +82 -0
  41. package/dist/src/Form/context/AtlantisFormContext.test.js +28 -0
  42. package/dist/src/Form/hooks/useScrollToError/useScrollToError.test.js +89 -0
  43. package/dist/src/FormField/FormField.test.js +81 -0
  44. package/dist/src/FormatFile/FormatFile.test.js +212 -0
  45. package/dist/src/FormatFile/FormatFileThumbnail.test.js +192 -0
  46. package/dist/src/FormatFile/components/FormatFileBottomSheet/FormatFileBottomSheet.test.js +74 -0
  47. package/dist/src/FormatFile/components/MediaView/MediaView.test.js +202 -0
  48. package/dist/src/FormatFile/utils/parseFile.test.js +188 -0
  49. package/dist/src/Glimmer/Glimmer.test.js +61 -0
  50. package/dist/src/Heading/Heading.test.js +61 -0
  51. package/dist/src/Icon/Icon.test.js +40 -0
  52. package/dist/src/IconButton/IconButton.test.js +38 -0
  53. package/dist/src/InputCurrency/InputCurrency.test.js +106 -0
  54. package/dist/src/InputDate/InputDate.test.js +184 -0
  55. package/dist/src/InputEmail/InputEmail.test.js +27 -0
  56. package/dist/src/InputFieldWrapper/InputFieldWrapper.test.js +279 -0
  57. package/dist/src/InputFieldWrapper/components/ClearAction/ClearAction.test.js +9 -0
  58. package/dist/src/InputFieldWrapper/components/Prefix/Prefix.test.js +130 -0
  59. package/dist/src/InputFieldWrapper/components/Suffix/Suffix.test.js +51 -0
  60. package/dist/src/InputNumber/InputNumber.test.js +220 -0
  61. package/dist/src/InputPassword/InputPassword.test.js +63 -0
  62. package/dist/src/InputPressable/InputPressable.test.js +138 -0
  63. package/dist/src/InputSearch/InputSearch.test.js +54 -0
  64. package/dist/src/InputText/InputText.test.js +652 -0
  65. package/dist/src/InputText/context/InputAccessoriesProvider.test.js +71 -0
  66. package/dist/src/InputTime/InputTime.test.js +199 -0
  67. package/dist/src/InputTime/utils/utils.test.js +32 -0
  68. package/dist/src/ProgressBar/ProgressBar.test.js +89 -0
  69. package/dist/src/Select/Select.test.js +183 -0
  70. package/dist/src/Select/components/SelectDefaultPicker/SelectDefaultPicker.test.js +51 -0
  71. package/dist/src/Select/components/SelectInternalPicker/SelectInternalPicker.test.js +72 -0
  72. package/dist/src/StatusLabel/StatusLabel.test.js +51 -0
  73. package/dist/src/Switch/Switch.test.js +60 -0
  74. package/dist/src/Switch/components/BaseSwitch/BaseSwitch.test.js +61 -0
  75. package/dist/src/Text/Text.test.js +161 -0
  76. package/dist/src/TextList/TextList.test.js +16 -0
  77. package/dist/src/ThumbnailList/ThumbnailList.test.js +72 -0
  78. package/dist/src/Toast/Toast.test.js +51 -0
  79. package/dist/src/Typography/Typography.test.js +225 -0
  80. package/dist/src/hooks/useAtlantisI18n/useAtlantisI18n.test.js +103 -0
  81. package/dist/src/utils/meta/meta.test.js +83 -0
  82. package/dist/tsconfig.build.json +5 -1
  83. package/dist/tsconfig.build.tsbuildinfo +1 -1
  84. package/dist/tsconfig.eslint.json +14 -0
  85. package/dist/tsconfig.json +3 -4
  86. package/dist/types/src/ActionItem/ActionItem.test.d.ts +1 -0
  87. package/dist/types/src/ActionItem/ActionItemGroup.test.d.ts +1 -0
  88. package/dist/types/src/ActionItem/components/ActionItemContainer.test.d.ts +1 -0
  89. package/dist/types/src/ActionLabel/ActionLabel.test.d.ts +1 -0
  90. package/dist/types/src/ActivityIndicator/ActivityIndicator.test.d.ts +1 -0
  91. package/dist/types/src/AtlantisContext/AtlantisContext.test.d.ts +1 -0
  92. package/dist/types/src/AtlantisThemeContext/AtlantisThemeContext.test.d.ts +1 -0
  93. package/dist/types/src/AtlantisThemeContext/buildThemedStyles.test.d.ts +1 -0
  94. package/dist/types/src/AutoLink/AutoLink.test.d.ts +1 -0
  95. package/dist/types/src/AutoLink/components/Link/Link.test.d.ts +1 -0
  96. package/dist/types/src/Banner/Banner.test.d.ts +1 -0
  97. package/dist/types/src/BottomSheet/BottomSheet.test.d.ts +1 -0
  98. package/dist/types/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.test.d.ts +1 -0
  99. package/dist/types/src/BottomSheet/hooks/useBottomSheetBackHandler.test.d.ts +1 -0
  100. package/dist/types/src/Button/Button.test.d.ts +1 -0
  101. package/dist/types/src/Button/components/InternalButtonLoading/InternalButtonLoading.test.d.ts +1 -0
  102. package/dist/types/src/ButtonGroup/ButtonGroup.test.d.ts +1 -0
  103. package/dist/types/src/Card/Card.test.d.ts +1 -0
  104. package/dist/types/src/Card/components/InternalCardHeader.test.d.ts +1 -0
  105. package/dist/types/src/Checkbox/Checkbox.test.d.ts +1 -0
  106. package/dist/types/src/Checkbox/CheckboxGroup.test.d.ts +1 -0
  107. package/dist/types/src/Checkbox/CheckboxGroupReducer.test.d.ts +1 -0
  108. package/dist/types/src/Chip/Chip.test.d.ts +1 -0
  109. package/dist/types/src/Content/Content.test.d.ts +1 -0
  110. package/dist/types/src/ContentOverlay/BottomSheetKeyboardAwareScrollView.d.ts +2 -1
  111. package/dist/types/src/ContentOverlay/ContentOverlay.test.d.ts +1 -0
  112. package/dist/types/src/ContentOverlay/computeContentOverlayBehavior.test.d.ts +1 -0
  113. package/dist/types/src/ContentOverlay/hooks/useBottomSheetModalBackHandler.test.d.ts +1 -0
  114. package/dist/types/src/ContentOverlay/hooks/useKeyboardVisibility.test.d.ts +1 -0
  115. package/dist/types/src/ContentOverlay/hooks/useViewLayoutHeight.test.d.ts +1 -0
  116. package/dist/types/src/Disclosure/Disclosure.test.d.ts +1 -0
  117. package/dist/types/src/Divider/Divider.test.d.ts +1 -0
  118. package/dist/types/src/EmptyState/EmptyState.test.d.ts +1 -0
  119. package/dist/types/src/ErrorMessageWrapper/ErrorMessageWrapper.test.d.ts +1 -0
  120. package/dist/types/src/Flex/Flex.test.d.ts +1 -0
  121. package/dist/types/src/Form/Form.test.d.ts +1 -0
  122. package/dist/types/src/Form/components/FormErrorBanner/FormErrorBanner.test.d.ts +1 -0
  123. package/dist/types/src/Form/components/FormMessage/FormMessage.test.d.ts +1 -0
  124. package/dist/types/src/Form/components/FormMessageBanner/FormMessageBanner.test.d.ts +1 -0
  125. package/dist/types/src/Form/components/FormSaveButton/FormSaveButton.test.d.ts +1 -0
  126. package/dist/types/src/Form/context/AtlantisFormContext.test.d.ts +1 -0
  127. package/dist/types/src/Form/hooks/useScrollToError/useScrollToError.test.d.ts +1 -0
  128. package/dist/types/src/FormField/FormField.test.d.ts +1 -0
  129. package/dist/types/src/FormatFile/FormatFile.test.d.ts +1 -0
  130. package/dist/types/src/FormatFile/FormatFileThumbnail.test.d.ts +1 -0
  131. package/dist/types/src/FormatFile/components/FormatFileBottomSheet/FormatFileBottomSheet.test.d.ts +1 -0
  132. package/dist/types/src/FormatFile/components/MediaView/MediaView.test.d.ts +1 -0
  133. package/dist/types/src/FormatFile/utils/parseFile.test.d.ts +1 -0
  134. package/dist/types/src/Glimmer/Glimmer.test.d.ts +1 -0
  135. package/dist/types/src/Heading/Heading.test.d.ts +1 -0
  136. package/dist/types/src/Icon/Icon.test.d.ts +1 -0
  137. package/dist/types/src/IconButton/IconButton.test.d.ts +1 -0
  138. package/dist/types/src/InputCurrency/InputCurrency.test.d.ts +1 -0
  139. package/dist/types/src/InputDate/InputDate.test.d.ts +1 -0
  140. package/dist/types/src/InputEmail/InputEmail.test.d.ts +1 -0
  141. package/dist/types/src/InputFieldWrapper/InputFieldWrapper.test.d.ts +1 -0
  142. package/dist/types/src/InputFieldWrapper/components/ClearAction/ClearAction.test.d.ts +1 -0
  143. package/dist/types/src/InputFieldWrapper/components/Prefix/Prefix.test.d.ts +1 -0
  144. package/dist/types/src/InputFieldWrapper/components/Suffix/Suffix.test.d.ts +1 -0
  145. package/dist/types/src/InputNumber/InputNumber.test.d.ts +1 -0
  146. package/dist/types/src/InputPassword/InputPassword.test.d.ts +1 -0
  147. package/dist/types/src/InputPressable/InputPressable.test.d.ts +1 -0
  148. package/dist/types/src/InputSearch/InputSearch.test.d.ts +1 -0
  149. package/dist/types/src/InputText/InputText.test.d.ts +1 -0
  150. package/dist/types/src/InputText/context/InputAccessoriesProvider.test.d.ts +1 -0
  151. package/dist/types/src/InputTime/InputTime.test.d.ts +1 -0
  152. package/dist/types/src/InputTime/utils/utils.test.d.ts +1 -0
  153. package/dist/types/src/ProgressBar/ProgressBar.test.d.ts +1 -0
  154. package/dist/types/src/Select/Select.test.d.ts +1 -0
  155. package/dist/types/src/Select/components/SelectDefaultPicker/SelectDefaultPicker.test.d.ts +1 -0
  156. package/dist/types/src/Select/components/SelectInternalPicker/SelectInternalPicker.test.d.ts +1 -0
  157. package/dist/types/src/StatusLabel/StatusLabel.test.d.ts +1 -0
  158. package/dist/types/src/Switch/Switch.test.d.ts +1 -0
  159. package/dist/types/src/Switch/components/BaseSwitch/BaseSwitch.test.d.ts +1 -0
  160. package/dist/types/src/Text/Text.test.d.ts +1 -0
  161. package/dist/types/src/TextList/TextList.test.d.ts +1 -0
  162. package/dist/types/src/ThumbnailList/ThumbnailList.test.d.ts +1 -0
  163. package/dist/types/src/Toast/Toast.test.d.ts +1 -0
  164. package/dist/types/src/Typography/Typography.test.d.ts +1 -0
  165. package/dist/types/src/hooks/useAtlantisI18n/useAtlantisI18n.test.d.ts +1 -0
  166. package/dist/types/src/utils/meta/meta.test.d.ts +1 -0
  167. package/package.json +19 -11
  168. package/src/Button/Button.test.tsx +6 -2
  169. package/src/ContentOverlay/hooks/useViewLayoutHeight.test.ts +3 -3
  170. package/src/Divider/Divider.stories.tsx +1 -1
  171. package/src/Flex/Flex.test.tsx +1 -1
  172. package/src/Form/Form.test.tsx +3 -1
  173. package/src/FormField/FormField.test.tsx +5 -1
  174. package/src/Heading/__snapshots__/Heading.test.tsx.snap +1 -1
  175. package/src/InputDate/InputDate.test.tsx +7 -1
  176. package/src/InputText/InputText.test.tsx +2 -1
  177. package/src/InputTime/InputTime.test.tsx +7 -1
  178. package/src/Select/Select.test.tsx +1 -1
  179. package/src/StatusLabel/__snapshots__/StatusLabel.test.tsx.snap +8 -8
  180. package/src/Text/__snapshots__/Text.test.tsx.snap +2 -2
  181. package/src/ThumbnailList/__snapshots__/ThumbnailList.test.tsx.snap +1 -1
  182. package/src/Typography/__snapshots__/Typography.test.tsx.snap +4 -4
@@ -0,0 +1,82 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import React from "react";
11
+ import { fireEvent, render, waitFor } from "@testing-library/react-native";
12
+ import { FormSaveButton } from "./FormSaveButton";
13
+ jest.mock("react-hook-form", () => (Object.assign(Object.assign({}, jest.requireActual("react-hook-form")), { useFormContext: () => ({
14
+ reset: () => jest.fn(),
15
+ }) })));
16
+ function ButtonGroupForTest(props) {
17
+ return (React.createElement(FormSaveButton, { primaryAction: props.primaryAction, loading: props.loading, label: props.label, setSecondaryActionLoading: props.setSecondaryActionLoading, secondaryActions: props.secondaryAction }));
18
+ }
19
+ describe("the form save button is enabled", () => {
20
+ const loading = false;
21
+ it("renders the form save button with default label", () => {
22
+ const pressHandler = jest.fn();
23
+ const { getByLabelText } = render(React.createElement(ButtonGroupForTest, { primaryAction: pressHandler, loading: loading, setSecondaryActionLoading: jest.fn() }));
24
+ const saveButton = getByLabelText("Save");
25
+ expect(saveButton).toBeTruthy();
26
+ });
27
+ it("renders a save button and calls the onPress handler when pressed", () => {
28
+ const pressHandler = jest.fn();
29
+ const saveButtonText = "Save";
30
+ const { getByLabelText } = render(React.createElement(ButtonGroupForTest, { primaryAction: pressHandler, loading: loading, setSecondaryActionLoading: jest.fn() }));
31
+ fireEvent.press(getByLabelText(saveButtonText));
32
+ expect(pressHandler).toHaveBeenCalled();
33
+ });
34
+ it("renders a save button with a custom label if provided", () => {
35
+ const pressHandler = jest.fn();
36
+ const saveButtonText = "MySave";
37
+ const { getByLabelText } = render(React.createElement(ButtonGroupForTest, { primaryAction: pressHandler, loading: loading, setSecondaryActionLoading: jest.fn(), label: saveButtonText }));
38
+ const saveButton = getByLabelText(saveButtonText);
39
+ expect(saveButton).toBeTruthy();
40
+ });
41
+ });
42
+ describe("the form save button is loading", () => {
43
+ const loading = true;
44
+ it("renders the form save button as loading", () => {
45
+ const pressHandler = jest.fn();
46
+ const { getByTestId, getByRole } = render(React.createElement(ButtonGroupForTest, { primaryAction: pressHandler, loading: loading, setSecondaryActionLoading: jest.fn() }));
47
+ expect(getByTestId("loadingImage")).toBeDefined();
48
+ expect(getByRole("button", { busy: true })).toBeDefined();
49
+ });
50
+ });
51
+ describe("when a secondaryActions is passed in", () => {
52
+ it("renders a secondaryAction element", () => {
53
+ const pressHandler = jest.fn();
54
+ const { getByLabelText } = render(React.createElement(ButtonGroupForTest, { primaryAction: pressHandler, loading: false, setSecondaryActionLoading: jest.fn(), secondaryAction: [
55
+ { label: "hi", handleAction: { onSubmit: jest.fn() } },
56
+ ] }));
57
+ expect(getByLabelText("More")).toBeDefined();
58
+ });
59
+ it("renders a secondaryAction element with and fires the onSubmit and beforeSubmit if available", () => __awaiter(void 0, void 0, void 0, function* () {
60
+ const pressHandler = jest.fn(() => Promise.resolve());
61
+ const beforeSubmitMock = jest.fn().mockImplementation(() => {
62
+ return Promise.resolve(true);
63
+ });
64
+ const { findByLabelText, getByLabelText } = render(React.createElement(ButtonGroupForTest, { primaryAction: pressHandler, loading: false, setSecondaryActionLoading: jest.fn(), secondaryAction: [
65
+ {
66
+ icon: "trash",
67
+ label: "hi",
68
+ handleAction: {
69
+ onSubmit: pressHandler,
70
+ onBeforeSubmit: beforeSubmitMock,
71
+ },
72
+ },
73
+ ] }));
74
+ fireEvent.press(getByLabelText("More"));
75
+ expect(yield findByLabelText("hi")).toBeDefined();
76
+ fireEvent.press(getByLabelText("hi"));
77
+ expect(beforeSubmitMock).toHaveBeenCalled();
78
+ yield waitFor(() => {
79
+ expect(pressHandler).toHaveBeenCalled();
80
+ });
81
+ }));
82
+ });
@@ -0,0 +1,28 @@
1
+ import React from "react";
2
+ import { renderHook } from "@testing-library/react-native";
3
+ import { AtlantisFormContext, atlantisFormContextDefaultValues, useAtlantisFormContext, } from "./AtlantisFormContext";
4
+ const useConfirmBeforeBackMock = jest.fn();
5
+ const useInternalFormLocalCacheMock = jest.fn();
6
+ const providerValues = {
7
+ useConfirmBeforeBack: useConfirmBeforeBackMock,
8
+ useInternalFormLocalCache: useInternalFormLocalCacheMock,
9
+ };
10
+ describe("AtlantisFormContext", () => {
11
+ beforeEach(() => {
12
+ jest.resetModules();
13
+ });
14
+ describe("No Provider", () => {
15
+ it("should get the default values", () => {
16
+ const { result } = renderHook(() => useAtlantisFormContext());
17
+ expect(result.current).toMatchObject(atlantisFormContextDefaultValues);
18
+ });
19
+ });
20
+ describe("With Provider", () => {
21
+ it("should get the provider values", () => {
22
+ const { result } = renderHook(() => useAtlantisFormContext(), {
23
+ wrapper: ({ children }) => (React.createElement(AtlantisFormContext.Provider, { value: providerValues }, children)),
24
+ });
25
+ expect(result.current).toMatchObject(providerValues);
26
+ });
27
+ });
28
+ });
@@ -0,0 +1,89 @@
1
+ import { renderHook } from "@testing-library/react-native";
2
+ import { useScrollToError } from "./useScrollToError";
3
+ const mockFormState = {
4
+ isDirty: true,
5
+ isLoading: false,
6
+ isReady: true,
7
+ disabled: false,
8
+ validatingFields: {},
9
+ dirtyFields: {},
10
+ isSubmitted: false,
11
+ isSubmitSuccessful: false,
12
+ submitCount: 0,
13
+ touchedFields: {},
14
+ isSubmitting: false,
15
+ isValidating: false,
16
+ isValid: true,
17
+ errors: {},
18
+ };
19
+ const mockScreenReaderEnabled = jest.fn().mockReturnValue(false);
20
+ jest.mock("../../../hooks/useIsScreenReaderEnabled", () => ({
21
+ useIsScreenReaderEnabled: () => mockScreenReaderEnabled(),
22
+ }));
23
+ jest.mock("../../../ErrorMessageWrapper", () => ({
24
+ useErrorMessageContext: () => ({
25
+ elements: {
26
+ el: {
27
+ measure: jest.fn((_, callback) => callback()),
28
+ hasErrorMessage: true,
29
+ accessibilityFocus: jest.fn(),
30
+ },
31
+ },
32
+ register: jest.fn(),
33
+ unregister: jest.fn(),
34
+ }),
35
+ }));
36
+ const handleScrollTo = jest.fn();
37
+ const handleSetFocus = jest.fn();
38
+ const initialProps = {
39
+ formState: mockFormState,
40
+ refNode: 1,
41
+ scrollTo: handleScrollTo,
42
+ setFocus: handleSetFocus,
43
+ };
44
+ afterEach(() => {
45
+ handleScrollTo.mockClear();
46
+ handleSetFocus.mockClear();
47
+ });
48
+ describe("useScrollToError", () => {
49
+ it("should do nothing if everything is valid", () => {
50
+ renderHook((props) => useScrollToError(props), {
51
+ initialProps,
52
+ });
53
+ expect(handleSetFocus).not.toHaveBeenCalled();
54
+ expect(handleScrollTo).not.toHaveBeenCalled();
55
+ });
56
+ it("should focus with RHF if it can", () => {
57
+ const { rerender } = renderHook((props) => useScrollToError(props), {
58
+ initialProps,
59
+ });
60
+ rerender(Object.assign(Object.assign({}, initialProps), { formState: Object.assign(Object.assign({}, mockFormState), { isValid: false, submitCount: 1 }) }));
61
+ expect(handleSetFocus).toHaveBeenCalled();
62
+ expect(handleScrollTo).not.toHaveBeenCalled();
63
+ });
64
+ it("should manually scroll", () => {
65
+ // @ts-expect-error - making this fail when it gets called since you can't
66
+ // call undefined as a function. This mimic's RHF not being able to focus on
67
+ // non-input fields
68
+ const failedSetFocus = jest.fn(() => failingFn());
69
+ const manualScrollProps = Object.assign(Object.assign({}, initialProps), { setFocus: failedSetFocus });
70
+ const { rerender } = renderHook((props) => useScrollToError(props), {
71
+ initialProps: manualScrollProps,
72
+ });
73
+ rerender(Object.assign(Object.assign({}, manualScrollProps), { formState: Object.assign(Object.assign({}, mockFormState), { isValid: false, submitCount: 1 }) }));
74
+ expect(failedSetFocus).toHaveBeenCalled();
75
+ expect(failedSetFocus).toThrow();
76
+ expect(handleScrollTo).toHaveBeenCalled();
77
+ });
78
+ describe("With screen readers", () => {
79
+ it("should not fire the setFocus", () => {
80
+ mockScreenReaderEnabled.mockReturnValue(true);
81
+ const { rerender } = renderHook((props) => useScrollToError(props), {
82
+ initialProps,
83
+ });
84
+ rerender(Object.assign(Object.assign({}, initialProps), { formState: Object.assign(Object.assign({}, mockFormState), { isValid: false, submitCount: 1 }) }));
85
+ expect(handleSetFocus).not.toHaveBeenCalled();
86
+ expect(handleScrollTo).toHaveBeenCalled();
87
+ });
88
+ });
89
+ });
@@ -0,0 +1,81 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import React from "react";
11
+ import { fireEvent, render, waitFor } from "@testing-library/react-native";
12
+ import { FormProvider, useForm } from "react-hook-form";
13
+ import { Button } from "react-native";
14
+ import { FormField } from ".";
15
+ import { InputText } from "../InputText";
16
+ const mockOnSubmit = jest.fn();
17
+ const inputAccessibilityLabel = "textInput";
18
+ const saveButtonText = "Save Me";
19
+ describe("when a component is wrapped in a FormField within a Form", () => {
20
+ function SimpleFormWithProvider({ children, }) {
21
+ const formMethods = useForm();
22
+ return (React.createElement(FormProvider, Object.assign({}, formMethods),
23
+ children,
24
+ React.createElement(Button, { onPress: formMethods.handleSubmit(values => mockOnSubmit(values)), title: saveButtonText, accessibilityLabel: saveButtonText })));
25
+ }
26
+ describe("when the component's value is changed", () => {
27
+ it("updates the form value for that component", () => __awaiter(void 0, void 0, void 0, function* () {
28
+ const defaultInputValue = "Sonkey";
29
+ const newInputValue = "Donic";
30
+ const { getByLabelText } = render(React.createElement(SimpleFormWithProvider, null,
31
+ React.createElement(FormField, { name: "formTextInput", defaultValue: defaultInputValue }, field => {
32
+ return (React.createElement(InputText, { name: field.name, accessibilityLabel: inputAccessibilityLabel, value: field.value, onChangeText: field.onChange }));
33
+ })));
34
+ const textInput = getByLabelText(inputAccessibilityLabel);
35
+ fireEvent.changeText(textInput, newInputValue);
36
+ const saveButton = getByLabelText(saveButtonText);
37
+ yield waitFor(() => {
38
+ fireEvent.press(saveButton);
39
+ });
40
+ expect(mockOnSubmit).toHaveBeenCalledWith({
41
+ formTextInput: newInputValue,
42
+ });
43
+ }));
44
+ });
45
+ describe("when the validations of the component are violated", () => {
46
+ it("returns an error from the FormField wrapper", () => __awaiter(void 0, void 0, void 0, function* () {
47
+ const newInputValue = "Exceeding 5 characters";
48
+ const maxLengthErrorMessage = "error: max length exceeded";
49
+ const { getByLabelText, getAllByText } = render(React.createElement(SimpleFormWithProvider, null,
50
+ React.createElement(FormField, { name: "formTextInput", validations: {
51
+ maxLength: {
52
+ value: 5,
53
+ message: maxLengthErrorMessage,
54
+ },
55
+ } }, field => {
56
+ return (React.createElement(InputText, { name: field.name, accessibilityLabel: inputAccessibilityLabel, value: field.value, onChangeText: field.onChange }));
57
+ })));
58
+ const textInput = getByLabelText(inputAccessibilityLabel);
59
+ fireEvent.changeText(textInput, newInputValue);
60
+ const saveButton = getByLabelText(saveButtonText);
61
+ yield waitFor(() => {
62
+ fireEvent.press(saveButton);
63
+ });
64
+ expect(getAllByText(maxLengthErrorMessage, { includeHiddenElements: true })).toHaveLength(1);
65
+ }));
66
+ });
67
+ });
68
+ describe("when a component is not in a Form with a Form ProviderField within a Form", () => {
69
+ describe("when the component's value is changed", () => {
70
+ it("updates the form value for that component", () => __awaiter(void 0, void 0, void 0, function* () {
71
+ const defaultInputValue = "Sonkey";
72
+ const newInputValue = "Donic";
73
+ const { getByDisplayValue, getByLabelText } = render(React.createElement(FormField, { name: "formTextInput", defaultValue: defaultInputValue }, field => {
74
+ return (React.createElement(InputText, { name: field.name, accessibilityLabel: inputAccessibilityLabel, value: field.value, onChangeText: field.onChange }));
75
+ }));
76
+ const textInput = getByLabelText(inputAccessibilityLabel);
77
+ fireEvent.changeText(textInput, newInputValue);
78
+ expect(getByDisplayValue(newInputValue)).toBeDefined();
79
+ }));
80
+ });
81
+ });
@@ -0,0 +1,212 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import React from "react";
11
+ import { fireEvent, render, waitFor } from "@testing-library/react-native";
12
+ import { Alert } from "react-native";
13
+ import { FormatFile } from ".";
14
+ import { FILE_MOCK_FILE, FILE_MOCK_IMAGE, FILE_MOCK_PDF, FILE_MOCK_VIDEO, FILE_UPLOAD_MOCK_FILE, FILE_UPLOAD_MOCK_IMAGE, FILE_UPLOAD_MOCK_PDF, } from "./components/_mocks/mockFiles";
15
+ import { StatusCode } from "./types";
16
+ import { tokens } from "../utils/design";
17
+ let Platform;
18
+ const onRemove = jest.fn();
19
+ const mockOnPreview = jest.fn();
20
+ const mockCreateThumbnail = jest.fn(() => __awaiter(void 0, void 0, void 0, function* () {
21
+ return ({
22
+ thumbnail: "thumbnail",
23
+ error: false,
24
+ });
25
+ }));
26
+ beforeEach(() => {
27
+ Platform = require("react-native").Platform;
28
+ });
29
+ afterEach(() => {
30
+ jest.clearAllMocks();
31
+ });
32
+ const renderFormatFile = (file, bottomSheetOptionsSuffix, showFileTypeIndicator) => {
33
+ return render(React.createElement(FormatFile, { file: file, accessibilityLabel: "Custom Label", accessibilityHint: "Custom Hint Text", onTap: () => Alert.alert("alert"), onRemove: onRemove, bottomSheetOptionsSuffix: bottomSheetOptionsSuffix, showFileTypeIndicator: showFileTypeIndicator, onPreviewPress: mockOnPreview, createThumbnail: mockCreateThumbnail }));
34
+ };
35
+ function basicRenderTestWithValue() {
36
+ const progressBarAnimationTime = 500;
37
+ it.each([
38
+ [
39
+ "file",
40
+ FILE_UPLOAD_MOCK_FILE({ progress: 1, status: StatusCode.Completed }),
41
+ ],
42
+ [
43
+ "image",
44
+ FILE_UPLOAD_MOCK_IMAGE({ progress: 1, status: StatusCode.Completed }),
45
+ ],
46
+ ])("renders a %s with custom label and hint", (bottomSheetOptionsSuffix, file) => {
47
+ const { getByLabelText, getByHintText } = renderFormatFile(file, bottomSheetOptionsSuffix);
48
+ expect(getByLabelText("Custom Label")).toBeDefined();
49
+ expect(getByHintText("Custom Hint Text")).toBeDefined();
50
+ });
51
+ describe.each([
52
+ ["file", FILE_UPLOAD_MOCK_FILE({ progress: 0.9 })],
53
+ ["image", FILE_UPLOAD_MOCK_IMAGE({ progress: 0.9 })],
54
+ ])("when a local %s is being uploaded", (testIdType, file) => {
55
+ const testId = `test-${testIdType}`;
56
+ it("renders ProgressBar state when upload status is not completed", () => {
57
+ const { getByTestId } = renderFormatFile(file);
58
+ expect(getByTestId("format-file-progress-bar")).toBeDefined();
59
+ });
60
+ it("renders a helpful accessibility label", () => {
61
+ const tree = renderFormatFile(file);
62
+ expect(tree.getByLabelText("Upload in progress.")).toBeDefined();
63
+ });
64
+ it("renders an overlay on the image when upload status is not completed", () => {
65
+ const { getByTestId } = renderFormatFile(file);
66
+ const progressBarContainer = getByTestId("format-file-progress-bar-container");
67
+ const overlayStyles = progressBarContainer.props.style;
68
+ // The container needs to have a height and color in order to show the overlay
69
+ expect(overlayStyles).toEqual(expect.arrayContaining([expect.objectContaining({ height: "100%" })]));
70
+ expect(overlayStyles).toEqual(expect.arrayContaining([
71
+ expect.objectContaining({
72
+ backgroundColor: tokens["color-overlay--dimmed"],
73
+ }),
74
+ ]));
75
+ });
76
+ it("renders ProgressBar state advancing with the upload percentage", () => __awaiter(this, void 0, void 0, function* () {
77
+ jest.useFakeTimers();
78
+ const { getByTestId } = renderFormatFile(file);
79
+ jest.advanceTimersByTime(progressBarAnimationTime);
80
+ const formatFileInnerProgressBar = yield waitFor(() => getByTestId("format-file-inner-progress-bar"));
81
+ const innerProgressBarWidth = parseInt(formatFileInnerProgressBar.props.style.width, 10);
82
+ expect(innerProgressBarWidth).toBeGreaterThan(20);
83
+ }));
84
+ it("shows an alert for on tap", () => {
85
+ const { getByTestId } = renderFormatFile(file);
86
+ const spy = jest.spyOn(Alert, "alert");
87
+ fireEvent.press(getByTestId(testId));
88
+ expect(spy).toHaveBeenCalled();
89
+ });
90
+ });
91
+ describe.each([
92
+ [
93
+ "file",
94
+ Object.assign(Object.assign({}, FILE_UPLOAD_MOCK_FILE({ progress: 0.9, status: StatusCode.Failed })), { status: StatusCode.Failed }),
95
+ ],
96
+ [
97
+ "image",
98
+ Object.assign(Object.assign({}, FILE_UPLOAD_MOCK_IMAGE({ progress: 0.9, status: StatusCode.Failed })), { status: StatusCode.Failed }),
99
+ ],
100
+ ])("when a local %s upload has failed", (testIdType, file) => {
101
+ it("renders an error icon", () => {
102
+ const tree = renderFormatFile(file);
103
+ expect(tree.getByTestId("format-file-error-icon")).toBeDefined();
104
+ });
105
+ it("renders a helpful accessibility label", () => {
106
+ const tree = renderFormatFile(file);
107
+ expect(tree.getByLabelText("Failed to upload.")).toBeDefined();
108
+ });
109
+ it("does not render an overlay", () => {
110
+ const tree = renderFormatFile(file);
111
+ expect(tree.queryByTestId("format-file-progress-bar-container")).toBeNull();
112
+ });
113
+ it("shows an alert for on tap", () => {
114
+ const testId = `test-${testIdType}`;
115
+ const tree = renderFormatFile(file);
116
+ const spy = jest.spyOn(Alert, "alert");
117
+ fireEvent.press(tree.getByTestId(testId));
118
+ expect(spy).toHaveBeenCalled();
119
+ });
120
+ });
121
+ describe.each([
122
+ [
123
+ "local file",
124
+ "test-file",
125
+ FILE_UPLOAD_MOCK_FILE({ progress: 1, status: StatusCode.Completed }),
126
+ ],
127
+ [
128
+ "local image",
129
+ "test-image",
130
+ FILE_UPLOAD_MOCK_IMAGE({ progress: 1, status: StatusCode.Completed }),
131
+ ],
132
+ ["external file", "test-file", FILE_MOCK_FILE],
133
+ ["external image", "test-image", FILE_MOCK_IMAGE],
134
+ ])("when a uploaded %s is being used", (bottomSheetOptionsSuffix, testId, file) => {
135
+ let tree;
136
+ const removeLabel = `Remove ${bottomSheetOptionsSuffix}`;
137
+ beforeEach(() => {
138
+ jest.clearAllMocks();
139
+ jest.useFakeTimers();
140
+ tree = renderFormatFile(file, bottomSheetOptionsSuffix);
141
+ jest.advanceTimersByTime(progressBarAnimationTime);
142
+ });
143
+ it("shows a BottomSheet with a remove option when tapped", () => __awaiter(this, void 0, void 0, function* () {
144
+ const { getByTestId, findByLabelText } = tree;
145
+ fireEvent.press(getByTestId(testId));
146
+ expect(yield findByLabelText(removeLabel)).toBeDefined();
147
+ }));
148
+ describe("when the BottomSheet remove option is tapped", () => {
149
+ it("calls the onRemove action", () => __awaiter(this, void 0, void 0, function* () {
150
+ const { getByTestId, findByLabelText } = tree;
151
+ fireEvent.press(getByTestId(testId));
152
+ fireEvent.press(yield findByLabelText(removeLabel));
153
+ expect(onRemove).toHaveBeenCalledTimes(1);
154
+ }));
155
+ });
156
+ it("creates a thumbnail when a media file is used", () => {
157
+ const expectedCalls = testId.includes("image") ? 1 : 0;
158
+ expect(mockCreateThumbnail).toHaveBeenCalledTimes(expectedCalls);
159
+ });
160
+ });
161
+ describe("when the preview option is tapped", () => {
162
+ it("calls onPreview with a valid image", () => __awaiter(this, void 0, void 0, function* () {
163
+ const previewLabel = "Preview image";
164
+ const { getByTestId, findByLabelText } = renderFormatFile(FILE_UPLOAD_MOCK_IMAGE({ progress: 1, status: StatusCode.Completed }), "image");
165
+ fireEvent.press(getByTestId("test-image"));
166
+ fireEvent.press(yield findByLabelText(previewLabel));
167
+ expect(mockOnPreview).toHaveBeenCalledTimes(1);
168
+ }));
169
+ it("calls onPreview with a valid pdf file", () => __awaiter(this, void 0, void 0, function* () {
170
+ const previewLabel = "Preview file";
171
+ const { getByTestId, findByLabelText } = renderFormatFile(FILE_UPLOAD_MOCK_PDF({ progress: 1, status: StatusCode.Completed }), "file");
172
+ fireEvent.press(getByTestId("test-file"));
173
+ fireEvent.press(yield findByLabelText(previewLabel));
174
+ expect(mockOnPreview).toHaveBeenCalledTimes(1);
175
+ }));
176
+ it("calls onPreview with a valid external PDF file", () => __awaiter(this, void 0, void 0, function* () {
177
+ const previewLabel = "Preview file";
178
+ const { getByTestId, findByLabelText } = renderFormatFile(FILE_MOCK_PDF, "file");
179
+ fireEvent.press(getByTestId("test-file"));
180
+ fireEvent.press(yield findByLabelText(previewLabel));
181
+ expect(mockOnPreview).toHaveBeenCalledTimes(1);
182
+ }));
183
+ it("does not show the preview option with an unaccepted file", () => {
184
+ const previewLabel = "Preview file";
185
+ const { getByTestId, queryByLabelText } = renderFormatFile(FILE_UPLOAD_MOCK_FILE({ progress: 1, status: StatusCode.Completed }), "file");
186
+ fireEvent.press(getByTestId("test-file"));
187
+ expect(queryByLabelText(previewLabel)).toBeNull();
188
+ });
189
+ });
190
+ describe("when an uploaded video is being viewed", () => {
191
+ it("shows the play icon if the file type indicator is not specified", () => {
192
+ const { getByTestId } = renderFormatFile(FILE_MOCK_VIDEO, "video");
193
+ expect(getByTestId("video")).toBeDefined();
194
+ });
195
+ it("does not show the play icon if the file type indicator is set to false", () => {
196
+ const { queryByTestId } = renderFormatFile(FILE_MOCK_VIDEO, "video", false);
197
+ expect(queryByTestId("video")).toBeNull();
198
+ });
199
+ });
200
+ }
201
+ describe("ios", () => {
202
+ beforeEach(() => {
203
+ Platform.OS = "ios";
204
+ });
205
+ basicRenderTestWithValue();
206
+ });
207
+ describe("android", () => {
208
+ beforeEach(() => {
209
+ Platform.OS = "android";
210
+ });
211
+ basicRenderTestWithValue();
212
+ });