@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,98 @@
1
+ import React from "react";
2
+ import { render } from "@testing-library/react-native";
3
+ import { Banner } from ".";
4
+ import { Text } from "../Text";
5
+ import { TextList } from "../TextList";
6
+ describe("Banner", () => {
7
+ describe("Type", () => {
8
+ it("renders an error Banner", () => {
9
+ const { getByText, getByTestId } = render(React.createElement(Banner, { type: "error", text: "An error happened" }));
10
+ const icon = getByTestId("ATL-Banner-Icon");
11
+ expect(getByText("An error happened")).toBeDefined();
12
+ expect(icon.props.children.props.name).toBe("alert");
13
+ });
14
+ it("renders a warning Banner", () => {
15
+ const { getByText, getByTestId } = render(React.createElement(Banner, { type: "warning", text: "Here is a warning" }));
16
+ const icon = getByTestId("ATL-Banner-Icon");
17
+ expect(getByText("Here is a warning")).toBeDefined();
18
+ expect(icon.props.children.props.name).toBe("help");
19
+ });
20
+ it("renders a notice Banner", () => {
21
+ const { getByText, getByTestId } = render(React.createElement(Banner, { type: "notice", text: "Notice me" }));
22
+ const icon = getByTestId("ATL-Banner-Icon");
23
+ expect(getByText("Notice me")).toBeDefined();
24
+ expect(icon.props.children.props.name).toBe("starburst");
25
+ });
26
+ it("renders a success Banner", () => {
27
+ const { getByText, getByTestId } = render(React.createElement(Banner, { type: "success" },
28
+ React.createElement(Text, null, "Your import is complete")));
29
+ const icon = getByTestId("ATL-Banner-Icon");
30
+ expect(getByText("Your import is complete")).toBeDefined();
31
+ expect(icon.props.children.props.name).toBe("checkmark");
32
+ });
33
+ });
34
+ describe("Children", () => {
35
+ describe("should flow", () => {
36
+ it("renders using RNText when there is a text prop", () => {
37
+ const { getByText, queryByTestId } = render(React.createElement(Banner, { type: "notice", text: "Notice me" }));
38
+ expect(getByText("Notice me")).toBeDefined();
39
+ expect(queryByTestId("ATL-Banner-RNText")).toBeDefined();
40
+ });
41
+ it("renders using RNText when there is a Text element", () => {
42
+ const { getByText, queryByTestId } = render(React.createElement(Banner, { type: "notice" },
43
+ React.createElement(Text, null, "Notice me")));
44
+ expect(getByText("Notice me")).toBeDefined();
45
+ expect(queryByTestId("ATL-Banner-RNText")).toBeDefined();
46
+ });
47
+ });
48
+ describe("should stack", () => {
49
+ it("renders using View when there is a details prop", () => {
50
+ const { getByText, queryByTestId } = render(React.createElement(Banner, { type: "notice", details: ["details"] }));
51
+ expect(getByText("details")).toBeDefined();
52
+ expect(queryByTestId("ATL-View-Container")).toBeDefined();
53
+ });
54
+ it("renders using View when there is more than one child", () => {
55
+ const { getByText, queryByTestId } = render(React.createElement(Banner, { type: "notice" },
56
+ React.createElement(Text, null, "Notice me"),
57
+ React.createElement(TextList, { items: ["Detail One", "Detail Two", "Detail Three"] })));
58
+ expect(getByText("Notice me")).toBeDefined();
59
+ expect(getByText("Detail Three")).toBeDefined();
60
+ expect(queryByTestId("ATL-View-Container")).toBeDefined();
61
+ });
62
+ it("renders using View when there is a details prop and a text prop", () => {
63
+ const { getByText, queryByTestId } = render(React.createElement(Banner, { type: "notice", text: "Notice me", details: ["details"] }));
64
+ expect(getByText("Notice me")).toBeDefined();
65
+ expect(getByText("details")).toBeDefined();
66
+ expect(queryByTestId("ATL-View-Container")).toBeDefined();
67
+ });
68
+ it("renders using View when there are text and details props, as well as a child", () => {
69
+ const { getByText, queryByTestId } = render(React.createElement(Banner, { type: "notice", text: "Notice me", details: ["details"] },
70
+ React.createElement(Text, null, "I am a text child!")));
71
+ expect(getByText("Notice me")).toBeDefined();
72
+ expect(getByText("I am a text child!")).toBeDefined();
73
+ expect(queryByTestId("ATL-View-Container")).toBeDefined();
74
+ });
75
+ });
76
+ it("should render multiple details when using the details prop", () => {
77
+ const tree = render(React.createElement(Banner, { type: "error", text: "You are disconnected", details: ["details", "etc"] }));
78
+ expect(tree.getByText("details")).toBeDefined();
79
+ expect(tree.getByText("etc")).toBeDefined();
80
+ });
81
+ it("should render multiple details when using the TextList component", () => {
82
+ const tree = render(React.createElement(Banner, { type: "error", text: "You are disconnected" },
83
+ React.createElement(TextList, { items: ["details", "etc"] })));
84
+ expect(tree.getByText("details")).toBeDefined();
85
+ expect(tree.getByText("etc")).toBeDefined();
86
+ });
87
+ it("should render a Typography bar when there is an action prop but no details", () => {
88
+ const { getByText } = render(React.createElement(Banner, { type: "error", text: "You are disconnected", action: { label: "Reconnect", onPress: jest.fn() } }));
89
+ expect(getByText("Reconnect")).toBeDefined();
90
+ expect(getByText("|")).toBeDefined();
91
+ });
92
+ it("should not render a Typography bar when there are action and details props", () => {
93
+ const { getByText, queryByText } = render(React.createElement(Banner, { type: "error", text: "You are disconnected", details: ["details"], action: { label: "Reconnect", onPress: jest.fn() } }));
94
+ expect(getByText("Reconnect")).toBeDefined();
95
+ expect(queryByText("|")).toBeNull();
96
+ });
97
+ });
98
+ });
@@ -0,0 +1,105 @@
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, { createRef } from "react";
11
+ import { act, render, userEvent, waitFor } from "@testing-library/react-native";
12
+ import { AccessibilityInfo, View } from "react-native";
13
+ import { BottomSheet } from ".";
14
+ import { waitForUntestableRender } from "../utils/test/wait";
15
+ import { Text } from "../Text";
16
+ jest.unmock("../hooks/useIsScreenReaderEnabled");
17
+ const ref = createRef();
18
+ const mockOnClose = jest.fn();
19
+ const mockOnOpen = jest.fn();
20
+ function setup({ heading, showCancel, loading, }) {
21
+ return render(React.createElement(BottomSheet, { ref: ref, heading: heading, showCancel: showCancel, loading: loading, onClose: mockOnClose, onOpen: mockOnOpen },
22
+ React.createElement(View, null,
23
+ React.createElement(Text, null, "BottomSheet"))));
24
+ }
25
+ it("renders a BottomSheet", () => __awaiter(void 0, void 0, void 0, function* () {
26
+ const { findByText } = setup({});
27
+ yield waitForUntestableRender("Wait for AccessibilityInfo.isScreenReaderEnabled to resolve");
28
+ yield act(() => __awaiter(void 0, void 0, void 0, function* () {
29
+ var _a;
30
+ (_a = ref.current) === null || _a === void 0 ? void 0 : _a.open();
31
+ }));
32
+ expect(yield findByText("BottomSheet")).toBeDefined();
33
+ }));
34
+ it("renders a BottomSheet with a header", () => __awaiter(void 0, void 0, void 0, function* () {
35
+ const header = "Hello this is header";
36
+ const { findByText } = setup({ heading: header });
37
+ yield waitForUntestableRender("Wait for AccessibilityInfo.isScreenReaderEnabled to resolve");
38
+ yield act(() => __awaiter(void 0, void 0, void 0, function* () {
39
+ var _a;
40
+ (_a = ref.current) === null || _a === void 0 ? void 0 : _a.open();
41
+ }));
42
+ expect(yield findByText(header)).toBeDefined();
43
+ }));
44
+ it("BottomSheet can be closed with the cancel action", () => __awaiter(void 0, void 0, void 0, function* () {
45
+ const { findByLabelText, queryByText } = setup({ showCancel: true });
46
+ yield act(() => __awaiter(void 0, void 0, void 0, function* () {
47
+ var _a;
48
+ (_a = ref.current) === null || _a === void 0 ? void 0 : _a.open();
49
+ }));
50
+ const cancelButton = yield findByLabelText("Cancel");
51
+ yield userEvent.press(cancelButton);
52
+ yield waitFor(() => {
53
+ expect(queryByText("BottomSheet")).toBeNull();
54
+ });
55
+ }));
56
+ describe("when loading is provided and true", () => {
57
+ it("hides the cancel action", () => __awaiter(void 0, void 0, void 0, function* () {
58
+ const { queryByText } = setup({ showCancel: true, loading: true });
59
+ yield waitForUntestableRender("Wait for AccessibilityInfo.isScreenReaderEnabled to resolve");
60
+ yield act(() => __awaiter(void 0, void 0, void 0, function* () {
61
+ var _a;
62
+ (_a = ref.current) === null || _a === void 0 ? void 0 : _a.open();
63
+ }));
64
+ expect(queryByText("Cancel")).toBeNull();
65
+ }));
66
+ });
67
+ it("calls onClose when BottomSheet is closed", () => __awaiter(void 0, void 0, void 0, function* () {
68
+ setup({});
69
+ yield act(() => __awaiter(void 0, void 0, void 0, function* () {
70
+ var _a, _b;
71
+ (_a = ref.current) === null || _a === void 0 ? void 0 : _a.open();
72
+ (_b = ref.current) === null || _b === void 0 ? void 0 : _b.close();
73
+ }));
74
+ yield waitFor(() => {
75
+ expect(mockOnClose).toHaveBeenCalledTimes(1);
76
+ });
77
+ }));
78
+ it("calls onOpen when BottomSheet is opened", () => __awaiter(void 0, void 0, void 0, function* () {
79
+ setup({});
80
+ yield act(() => __awaiter(void 0, void 0, void 0, function* () {
81
+ var _a;
82
+ (_a = ref.current) === null || _a === void 0 ? void 0 : _a.open();
83
+ }));
84
+ yield waitFor(() => {
85
+ expect(mockOnOpen).toHaveBeenCalledTimes(1);
86
+ });
87
+ }));
88
+ describe("when there is a screen reader enabled", () => {
89
+ it("should always show the cancel action", () => __awaiter(void 0, void 0, void 0, function* () {
90
+ jest
91
+ .spyOn(AccessibilityInfo, "isScreenReaderEnabled")
92
+ .mockImplementation(() => Promise.resolve(true));
93
+ const { findByLabelText, queryByText } = setup({});
94
+ yield act(() => __awaiter(void 0, void 0, void 0, function* () {
95
+ var _a;
96
+ (_a = ref.current) === null || _a === void 0 ? void 0 : _a.open();
97
+ }));
98
+ const cancelButton = yield findByLabelText("Cancel");
99
+ expect(cancelButton).toBeDefined();
100
+ yield userEvent.press(cancelButton);
101
+ yield waitFor(() => {
102
+ expect(queryByText("BottomSheet")).toBeNull();
103
+ });
104
+ }));
105
+ });
@@ -0,0 +1,19 @@
1
+ import React from "react";
2
+ import { fireEvent, render } from "@testing-library/react-native";
3
+ import { BottomSheetOption } from "./BottomSheetOption";
4
+ describe("BottomSheetOption component", () => {
5
+ it("renders", () => {
6
+ const mockNavigate = jest.fn();
7
+ const iconName = "camera";
8
+ const optionLabel = "Take photo";
9
+ const { getByTestId, getByText } = render(React.createElement(BottomSheetOption, { onPress: mockNavigate, icon: iconName, text: optionLabel }));
10
+ expect(getByTestId(iconName)).toBeDefined();
11
+ expect(getByText(optionLabel)).toBeDefined();
12
+ });
13
+ it("responds to presses", () => {
14
+ const mockNavigate = jest.fn();
15
+ const tree = render(React.createElement(BottomSheetOption, { onPress: mockNavigate, icon: "camera", text: "Take photo" }));
16
+ fireEvent.press(tree.getByLabelText("Take photo"));
17
+ expect(mockNavigate).toHaveBeenCalled();
18
+ });
19
+ });
@@ -0,0 +1,68 @@
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 { createRef } from "react";
11
+ import { act, renderHook } from "@testing-library/react-native";
12
+ import { BackHandler } from "react-native";
13
+ import { useBottomSheetBackHandler } from "./useBottomSheetBackHandler";
14
+ describe("useBottomSheetBackHandler", () => {
15
+ let mockRemove;
16
+ let mockAddEventListener;
17
+ beforeEach(() => {
18
+ mockRemove = jest.fn();
19
+ mockAddEventListener = jest.spyOn(BackHandler, "addEventListener");
20
+ mockAddEventListener.mockReturnValue({ remove: mockRemove });
21
+ });
22
+ afterEach(() => {
23
+ mockAddEventListener.mockRestore();
24
+ });
25
+ it("should register BackHandler listener when sheet becomes visible", () => __awaiter(void 0, void 0, void 0, function* () {
26
+ const bottomSheetRef = createRef();
27
+ const { result } = renderHook(() => useBottomSheetBackHandler(bottomSheetRef));
28
+ yield act(() => __awaiter(void 0, void 0, void 0, function* () {
29
+ result.current.handleSheetPositionChange(0);
30
+ }));
31
+ expect(mockAddEventListener).toHaveBeenCalledWith("hardwareBackPress", expect.any(Function));
32
+ }));
33
+ it("should call dismiss() when back button is pressed", () => __awaiter(void 0, void 0, void 0, function* () {
34
+ const mockDismiss = jest.fn();
35
+ const bottomSheetRef = {
36
+ current: {
37
+ dismiss: mockDismiss,
38
+ },
39
+ };
40
+ const { result } = renderHook(() => useBottomSheetBackHandler(bottomSheetRef));
41
+ yield act(() => __awaiter(void 0, void 0, void 0, function* () {
42
+ result.current.handleSheetPositionChange(0);
43
+ }));
44
+ const registeredCallback = mockAddEventListener.mock.calls[0][1];
45
+ const returnValue = registeredCallback();
46
+ expect(mockDismiss).toHaveBeenCalled();
47
+ expect(returnValue).toBe(true);
48
+ }));
49
+ it("should remove listener when sheet is dismissed", () => __awaiter(void 0, void 0, void 0, function* () {
50
+ const bottomSheetRef = createRef();
51
+ const { result } = renderHook(() => useBottomSheetBackHandler(bottomSheetRef));
52
+ yield act(() => __awaiter(void 0, void 0, void 0, function* () {
53
+ result.current.handleSheetPositionChange(0);
54
+ }));
55
+ yield act(() => __awaiter(void 0, void 0, void 0, function* () {
56
+ result.current.handleSheetPositionChange(-1);
57
+ }));
58
+ expect(mockRemove).toHaveBeenCalled();
59
+ }));
60
+ it("should not register listener when index is negative", () => __awaiter(void 0, void 0, void 0, function* () {
61
+ const bottomSheetRef = createRef();
62
+ const { result } = renderHook(() => useBottomSheetBackHandler(bottomSheetRef));
63
+ yield act(() => __awaiter(void 0, void 0, void 0, function* () {
64
+ result.current.handleSheetPositionChange(-1);
65
+ }));
66
+ expect(mockAddEventListener).not.toHaveBeenCalled();
67
+ }));
68
+ });
@@ -0,0 +1,228 @@
1
+ import React from "react";
2
+ import { fireEvent, render } from "@testing-library/react-native";
3
+ import { Path } from "react-native-svg";
4
+ import { Button } from ".";
5
+ import { baseButtonHeight, smallButtonHeight } from "./Button.style";
6
+ import { tokens } from "../utils/design";
7
+ function getIconAndTextColorFromRender({ type = "primary", variation = "work", }) {
8
+ const pressHandler = jest.fn();
9
+ const text = "🌚 I am the text 🌚";
10
+ const iconName = "cog";
11
+ const { getByTestId, getByRole } = render(React.createElement(Button, { onPress: pressHandler, label: text, icon: iconName, type: type, variation: variation }));
12
+ const iconColor = getByTestId(iconName).findByType(Path).props.fill;
13
+ const textColor = getByRole("text").props.style.find((style) => style.color).color;
14
+ return { iconColor, textColor };
15
+ }
16
+ function renderButton(element) {
17
+ const instance = render(element);
18
+ const button = instance.getByLabelText(element.props.label);
19
+ expect(button).toBeDefined();
20
+ expect(instance.getByText(element.props.label)).toBeDefined();
21
+ const buttonStyleEl = button.children[0];
22
+ const buttonStyle = buttonStyleEl.props.style.flat().reduce((mergedStyles, additionalStyles) => (Object.assign(Object.assign({}, mergedStyles), additionalStyles)), {});
23
+ return Object.assign(Object.assign({}, instance), { button, buttonStyle });
24
+ }
25
+ describe("Button", () => {
26
+ it("renders the default primary button", () => {
27
+ const { button, buttonStyle } = renderButton(React.createElement(Button, { label: "Foo", onPress: jest.fn() }));
28
+ expect(button.props.accessibilityRole).toBe("button");
29
+ expect(buttonStyle).toMatchObject({
30
+ backgroundColor: tokens["color-interactive"],
31
+ borderColor: tokens["color-interactive"],
32
+ });
33
+ });
34
+ it.each([
35
+ ["work", { bgColor: tokens["color-interactive"] }],
36
+ [
37
+ "cancel",
38
+ {
39
+ bgColor: tokens["color-white"],
40
+ borderColor: tokens["color-border"],
41
+ },
42
+ ],
43
+ ["destructive", { bgColor: tokens["color-destructive"] }],
44
+ ["learning", { bgColor: tokens["color-interactive--subtle"] }],
45
+ ])("renders a %s Button", (variation, { bgColor, borderColor }) => {
46
+ const { buttonStyle } = renderButton(React.createElement(Button, { label: variation, variation: variation, onPress: jest.fn() }));
47
+ expect(buttonStyle).toMatchObject({
48
+ backgroundColor: bgColor,
49
+ borderColor: borderColor || bgColor,
50
+ });
51
+ });
52
+ it.each([
53
+ ["primary", { bgColor: tokens["color-interactive"] }],
54
+ [
55
+ "secondary",
56
+ {
57
+ bgColor: tokens["color-white"],
58
+ borderColor: tokens["color-border"],
59
+ },
60
+ ],
61
+ [
62
+ "tertiary",
63
+ { bgColor: tokens["color-surface"], borderColor: "transparent" },
64
+ ],
65
+ ])("renders a %s Button", (type, { bgColor, borderColor }) => {
66
+ const { buttonStyle } = renderButton(React.createElement(Button, { label: type, type: type, onPress: jest.fn() }));
67
+ expect(buttonStyle).toMatchObject({
68
+ backgroundColor: bgColor,
69
+ borderColor: borderColor || bgColor,
70
+ });
71
+ });
72
+ it.each([
73
+ [
74
+ "small",
75
+ {
76
+ minHeight: smallButtonHeight,
77
+ },
78
+ ],
79
+ [
80
+ "base",
81
+ {
82
+ minHeight: baseButtonHeight,
83
+ },
84
+ ],
85
+ ])("renders a %s Button", (size, { minHeight }) => {
86
+ const { buttonStyle } = renderButton(React.createElement(Button, { label: "Button Size", size: size }));
87
+ expect(buttonStyle).toMatchObject({
88
+ minHeight,
89
+ });
90
+ });
91
+ it("renders a disabled Button", () => {
92
+ const { button, buttonStyle } = renderButton(React.createElement(Button, { label: "Can't touch this", disabled: true, onPress: jest.fn() }));
93
+ expect(button.props.accessibilityState).toHaveProperty("disabled", true);
94
+ expect(buttonStyle).toMatchObject({
95
+ backgroundColor: tokens["color-disabled--secondary"],
96
+ borderColor: tokens["color-disabled--secondary"],
97
+ });
98
+ });
99
+ it("renders a non-fullWidth Button", () => {
100
+ const expectedValue = { alignSelf: "stretch" };
101
+ const { button, rerender } = renderButton(React.createElement(Button, { label: "Thicc", onPress: jest.fn() }));
102
+ expect(button.props.style).toContainEqual(expectedValue);
103
+ rerender(React.createElement(Button, { label: "Thicc", fullWidth: false, onPress: jest.fn() }));
104
+ expect(button.props.style).not.toContainEqual(expectedValue);
105
+ });
106
+ it("should call the onPress handler", () => {
107
+ const pressHandler = jest.fn();
108
+ const text = "🌚 I am the text 🌚";
109
+ const a11yLabel = "A button";
110
+ const { getByLabelText } = render(React.createElement(Button, { onPress: pressHandler, label: text, accessibilityLabel: a11yLabel }));
111
+ fireEvent.press(getByLabelText(a11yLabel));
112
+ expect(pressHandler).toHaveBeenCalled();
113
+ });
114
+ describe("accessibilityLabel", () => {
115
+ it("uses accessibilityLabel if specified", () => {
116
+ const pressHandler = jest.fn();
117
+ const text = "🌚 I am the text 🌚";
118
+ const a11yLabel = "A button";
119
+ const { getByLabelText } = render(React.createElement(Button, { onPress: pressHandler, label: text, accessibilityLabel: a11yLabel }));
120
+ expect(getByLabelText(a11yLabel)).toBeTruthy();
121
+ });
122
+ it("uses label if unspecified", () => {
123
+ const pressHandler = jest.fn();
124
+ const text = "🌚 I am the text 🌚";
125
+ const { getByLabelText } = render(React.createElement(Button, { onPress: pressHandler, label: text }));
126
+ expect(getByLabelText(text)).toBeTruthy();
127
+ });
128
+ });
129
+ describe("if an icon is passed in", () => {
130
+ it("renders an icon Button with same color as the Button text", () => {
131
+ const { iconColor, textColor } = getIconAndTextColorFromRender({});
132
+ expect(iconColor).toBe(tokens["color-white"]);
133
+ expect(textColor).toBe(iconColor);
134
+ });
135
+ it("renders the learning variation and secondary type with icon and label with the same color", () => {
136
+ const { iconColor, textColor } = getIconAndTextColorFromRender({
137
+ variation: "learning",
138
+ type: "secondary",
139
+ });
140
+ expect(iconColor).toBe(tokens["color-interactive--subtle"]);
141
+ expect(textColor).toBe(iconColor);
142
+ });
143
+ it("renders the destructive variation and secondary type with icon and label with the same color", () => {
144
+ const { iconColor, textColor } = getIconAndTextColorFromRender({
145
+ variation: "destructive",
146
+ type: "secondary",
147
+ });
148
+ expect(iconColor).toBe(tokens["color-destructive"]);
149
+ expect(textColor).toBe(iconColor);
150
+ });
151
+ it("renders the cancel variation and tertiary type with icon and label with the same color", () => {
152
+ const { iconColor, textColor } = getIconAndTextColorFromRender({
153
+ variation: "cancel",
154
+ type: "tertiary",
155
+ });
156
+ expect(iconColor).toBe(tokens["color-interactive--subtle"]);
157
+ expect(textColor).toBe(iconColor);
158
+ });
159
+ it("renders an icon Button if only an icon is passed", () => {
160
+ const pressHandler = jest.fn();
161
+ const icon = "cog";
162
+ const accessibilityLabel = "cog";
163
+ const { getByLabelText } = render(React.createElement(Button, { onPress: pressHandler, icon: icon, accessibilityLabel: accessibilityLabel }));
164
+ expect(getByLabelText(icon)).toBeDefined();
165
+ });
166
+ });
167
+ describe("Loading", () => {
168
+ const label = "I am loading";
169
+ it("does render a loading state", () => {
170
+ const { getByTestId, getByRole } = render(React.createElement(Button, { label: label, onPress: jest.fn, loading: true }));
171
+ expect(getByTestId("loadingImage")).toBeDefined();
172
+ expect(getByRole("button", { busy: true })).toBeDefined();
173
+ });
174
+ it("doesn't render a loading state", () => {
175
+ const { queryByTestId, queryByRole, rerender } = render(React.createElement(Button, { label: label, onPress: jest.fn, loading: false }));
176
+ expect(queryByTestId("loadingImage")).toBeNull();
177
+ expect(queryByRole("button", { busy: true })).toBeNull();
178
+ rerender(React.createElement(Button, { label: "I am loading", onPress: jest.fn }));
179
+ expect(queryByTestId("loadingImage")).toBeNull();
180
+ expect(queryByRole("button", { busy: true })).toBeNull();
181
+ });
182
+ it("should not allow press events", () => {
183
+ const handlePress = jest.fn();
184
+ const setup = (loading) => (React.createElement(Button, { label: label, onPress: handlePress, loading: loading }));
185
+ const { getByLabelText, rerender } = render(setup(true));
186
+ fireEvent.press(getByLabelText(label));
187
+ expect(handlePress).not.toHaveBeenCalled();
188
+ // Sanity check that it's not a false positive
189
+ rerender(setup());
190
+ fireEvent.press(getByLabelText(label));
191
+ expect(handlePress).toHaveBeenCalledTimes(1);
192
+ });
193
+ });
194
+ describe("UNSAFE_style", () => {
195
+ it("should apply the container style override", () => {
196
+ const containerStyle = {
197
+ backgroundColor: "red",
198
+ borderColor: tokens["color-base-red--500"],
199
+ };
200
+ const { buttonStyle } = renderButton(React.createElement(Button, { label: "Override", onPress: jest.fn(), UNSAFE_style: { container: containerStyle } }));
201
+ expect(buttonStyle).toMatchObject(containerStyle);
202
+ });
203
+ it("should apply the contentContainer style override to labels", () => {
204
+ const contentContainerStyle = { padding: 10 };
205
+ const { getByTestId } = renderButton(React.createElement(Button, { label: "Override", onPress: jest.fn(), UNSAFE_style: { contentContainer: contentContainerStyle } }));
206
+ const contentContainer = getByTestId("contentContainer");
207
+ expect(contentContainer.props.style).toContainEqual(contentContainerStyle);
208
+ });
209
+ it("should apply the contentContainer style override to icons", () => {
210
+ const contentContainerStyle = { padding: 10 };
211
+ const { getByTestId } = renderButton(React.createElement(Button, { label: "Cog", icon: "cog", onPress: jest.fn(), UNSAFE_style: { contentContainer: contentContainerStyle } }));
212
+ const contentContainer = getByTestId("contentContainer");
213
+ expect(contentContainer.props.style).toContainEqual(contentContainerStyle);
214
+ });
215
+ it("should apply the iconContainer style override", () => {
216
+ const iconContainerStyle = { margin: 5 };
217
+ const { getByTestId } = renderButton(React.createElement(Button, { label: "Cog", icon: "cog", onPress: jest.fn(), UNSAFE_style: { iconContainer: iconContainerStyle } }));
218
+ const iconContainer = getByTestId("iconContainer");
219
+ expect(iconContainer.props.style).toContainEqual(iconContainerStyle);
220
+ });
221
+ it("should apply the actionLabelContainer style override", () => {
222
+ const actionLabelContainerStyle = { margin: 5 };
223
+ const { getByTestId } = renderButton(React.createElement(Button, { label: "Override", onPress: jest.fn(), UNSAFE_style: { actionLabelContainer: actionLabelContainerStyle } }));
224
+ const actionLabelContainer = getByTestId("actionLabelContainer");
225
+ expect(actionLabelContainer.props.style).toContainEqual(actionLabelContainerStyle);
226
+ });
227
+ });
228
+ });
@@ -0,0 +1,25 @@
1
+ import React from "react";
2
+ import { render } from "@testing-library/react-native";
3
+ import { InternalButtonLoading, darkPattern, lightPattern, } from "./InternalButtonLoading";
4
+ describe("Loading pattern", () => {
5
+ it.each([
6
+ [lightPattern, "primary", "work"],
7
+ [lightPattern, "primary", "destructive"],
8
+ [lightPattern, "primary", "learning"],
9
+ [darkPattern, "primary", "cancel"],
10
+ [darkPattern, "secondary", "cancel"],
11
+ [darkPattern, "secondary", "work"],
12
+ [darkPattern, "secondary", "destructive"],
13
+ [darkPattern, "secondary", "learning"],
14
+ [darkPattern, "tertiary", "cancel"],
15
+ [darkPattern, "tertiary", "work"],
16
+ [darkPattern, "tertiary", "destructive"],
17
+ [darkPattern, "tertiary", "learning"],
18
+ ])("should render a %s pattern on %s %s combination", (pattern, type, variation) => {
19
+ const { getByTestId } = render(React.createElement(InternalButtonLoading, { type: type, variation: variation }));
20
+ const component = getByTestId("loadingImage");
21
+ expect(component.props.source).toMatchObject({
22
+ uri: expect.stringContaining(pattern),
23
+ });
24
+ });
25
+ });