@terreno/ui 0.0.15 → 0.0.16

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 (151) hide show
  1. package/dist/DateUtilities.js +2 -2
  2. package/package.json +1 -1
  3. package/src/ActionSheet.test.tsx +77 -0
  4. package/src/Banner.test.tsx +106 -0
  5. package/src/Body.test.tsx +79 -0
  6. package/src/BooleanField.test.tsx +84 -0
  7. package/src/Button.test.tsx +160 -0
  8. package/src/Card.test.tsx +61 -0
  9. package/src/CheckBox.test.tsx +53 -0
  10. package/src/CustomSelectField.test.tsx +85 -0
  11. package/src/DataTable.test.tsx +133 -0
  12. package/src/DateTimeActionSheet.test.tsx +16 -0
  13. package/src/DateUtilities.tsx +2 -2
  14. package/src/DecimalRangeActionSheet.test.tsx +46 -0
  15. package/src/DismissButton.test.tsx +49 -0
  16. package/src/EmailField.test.tsx +106 -0
  17. package/src/ErrorBoundary.test.tsx +44 -0
  18. package/src/ErrorPage.test.tsx +44 -0
  19. package/src/Field.test.tsx +128 -0
  20. package/src/Heading.test.tsx +66 -0
  21. package/src/HeightActionSheet.test.tsx +34 -0
  22. package/src/Hyperlink.test.tsx +52 -0
  23. package/src/Icon.test.tsx +61 -0
  24. package/src/IconButton.test.tsx +145 -0
  25. package/src/Image.test.tsx +65 -0
  26. package/src/ImageBackground.test.tsx +46 -0
  27. package/src/InfoModalIcon.test.tsx +54 -0
  28. package/src/InfoTooltipButton.test.tsx +22 -0
  29. package/src/Link.test.tsx +64 -0
  30. package/src/MarkdownView.test.tsx +50 -0
  31. package/src/MobileAddressAutoComplete.test.tsx +15 -0
  32. package/src/Modal.test.tsx +169 -0
  33. package/src/ModalSheet.test.tsx +20 -0
  34. package/src/MultiselectField.test.tsx +134 -0
  35. package/src/NumberField.test.tsx +133 -0
  36. package/src/NumberPickerActionSheet.test.tsx +46 -0
  37. package/src/OpenAPIContext.test.tsx +36 -0
  38. package/src/Page.test.tsx +128 -0
  39. package/src/Pagination.test.tsx +86 -0
  40. package/src/PasswordField.test.tsx +17 -0
  41. package/src/PhoneNumberField.test.tsx +79 -0
  42. package/src/PickerSelect.test.tsx +16 -0
  43. package/src/Radio.test.tsx +30 -0
  44. package/src/RadioField.test.tsx +89 -0
  45. package/src/SectionDivider.test.tsx +17 -0
  46. package/src/SegmentedControl.test.tsx +84 -0
  47. package/src/SelectBadge.test.tsx +103 -0
  48. package/src/SelectField.test.tsx +84 -0
  49. package/src/SideDrawer.test.tsx +99 -0
  50. package/src/Signature.test.tsx +15 -0
  51. package/src/SignatureField.test.tsx +16 -0
  52. package/src/Spinner.test.tsx +74 -0
  53. package/src/SplitPage.test.tsx +15 -0
  54. package/src/TapToEdit.test.tsx +147 -0
  55. package/src/TerrenoProvider.test.tsx +36 -0
  56. package/src/Text.test.tsx +147 -0
  57. package/src/Theme.test.tsx +153 -0
  58. package/src/TimezonePicker.test.tsx +57 -0
  59. package/src/Toast.test.tsx +82 -0
  60. package/src/Tooltip.test.tsx +89 -0
  61. package/src/UnifiedAddressAutoComplete.test.tsx +15 -0
  62. package/src/Utilities.test.tsx +237 -0
  63. package/src/WebAddressAutocomplete.test.tsx +15 -0
  64. package/src/__snapshots__/ActionSheet.test.tsx.snap +889 -0
  65. package/src/__snapshots__/Banner.test.tsx.snap +546 -0
  66. package/src/__snapshots__/Body.test.tsx.snap +685 -0
  67. package/src/__snapshots__/BooleanField.test.tsx.snap +553 -0
  68. package/src/__snapshots__/Button.test.tsx.snap +1281 -0
  69. package/src/__snapshots__/Card.test.tsx.snap +195 -0
  70. package/src/__snapshots__/CheckBox.test.tsx.snap +190 -0
  71. package/src/__snapshots__/CustomSelectField.test.tsx.snap +2299 -0
  72. package/src/__snapshots__/DataTable.test.tsx.snap +9614 -0
  73. package/src/__snapshots__/DecimalRangeActionSheet.test.tsx.snap +1719 -0
  74. package/src/__snapshots__/DismissButton.test.tsx.snap +91 -0
  75. package/src/__snapshots__/EmailField.test.tsx.snap +168 -0
  76. package/src/__snapshots__/ErrorBoundary.test.tsx.snap +57 -0
  77. package/src/__snapshots__/ErrorPage.test.tsx.snap +195 -0
  78. package/src/__snapshots__/Field.test.tsx.snap +4510 -0
  79. package/src/__snapshots__/Heading.test.tsx.snap +193 -0
  80. package/src/__snapshots__/HeightActionSheet.test.tsx.snap +1269 -0
  81. package/src/__snapshots__/Hyperlink.test.tsx.snap +81 -0
  82. package/src/__snapshots__/Icon.test.tsx.snap +47 -0
  83. package/src/__snapshots__/IconButton.test.tsx.snap +29 -0
  84. package/src/__snapshots__/Image.test.tsx.snap +282 -0
  85. package/src/__snapshots__/ImageBackground.test.tsx.snap +120 -0
  86. package/src/__snapshots__/InfoModalIcon.test.tsx.snap +1229 -0
  87. package/src/__snapshots__/InfoTooltipButton.test.tsx.snap +7 -0
  88. package/src/__snapshots__/Link.test.tsx.snap +41 -0
  89. package/src/__snapshots__/MarkdownView.test.tsx.snap +965 -0
  90. package/src/__snapshots__/Modal.test.tsx.snap +1477 -0
  91. package/src/__snapshots__/MultiselectField.test.tsx.snap +1454 -0
  92. package/src/__snapshots__/NumberField.test.tsx.snap +80 -0
  93. package/src/__snapshots__/NumberPickerActionSheet.test.tsx.snap +5359 -0
  94. package/src/__snapshots__/OpenAPIContext.test.tsx.snap +14 -0
  95. package/src/__snapshots__/Page.test.tsx.snap +1647 -0
  96. package/src/__snapshots__/Pagination.test.tsx.snap +1913 -0
  97. package/src/__snapshots__/PasswordField.test.tsx.snap +15 -0
  98. package/src/__snapshots__/PhoneNumberField.test.tsx.snap +405 -0
  99. package/src/__snapshots__/PickerSelect.test.tsx.snap +266 -0
  100. package/src/__snapshots__/Radio.test.tsx.snap +111 -0
  101. package/src/__snapshots__/RadioField.test.tsx.snap +944 -0
  102. package/src/__snapshots__/SectionDivider.test.tsx.snap +37 -0
  103. package/src/__snapshots__/SegmentedControl.test.tsx.snap +1422 -0
  104. package/src/__snapshots__/SelectBadge.test.tsx.snap +2377 -0
  105. package/src/__snapshots__/SelectField.test.tsx.snap +1658 -0
  106. package/src/__snapshots__/SideDrawer.test.tsx.snap +1857 -0
  107. package/src/__snapshots__/SignatureField.test.tsx.snap +133 -0
  108. package/src/__snapshots__/Spinner.test.tsx.snap +73 -0
  109. package/src/__snapshots__/TapToEdit.test.tsx.snap +839 -0
  110. package/src/__snapshots__/TerrenoProvider.test.tsx.snap +203 -0
  111. package/src/__snapshots__/Text.test.tsx.snap +558 -0
  112. package/src/__snapshots__/TimezonePicker.test.tsx.snap +6676 -0
  113. package/src/__snapshots__/Toast.test.tsx.snap +1982 -0
  114. package/src/__snapshots__/Tooltip.test.tsx.snap +456 -0
  115. package/src/bunSetup.ts +101 -8
  116. package/src/fieldElements/FieldError.test.tsx +40 -0
  117. package/src/fieldElements/FieldHelperText.test.tsx +34 -0
  118. package/src/fieldElements/FieldTitle.test.tsx +30 -0
  119. package/src/fieldElements/__snapshots__/FieldError.test.tsx.snap +85 -0
  120. package/src/fieldElements/__snapshots__/FieldHelperText.test.tsx.snap +30 -0
  121. package/src/fieldElements/__snapshots__/FieldTitle.test.tsx.snap +19 -0
  122. package/src/icons/MobileIcon.test.tsx +21 -0
  123. package/src/icons/OfflineIcon.test.tsx +21 -0
  124. package/src/icons/OnlineIcon.test.tsx +21 -0
  125. package/src/icons/OutOfficeIcon.test.tsx +21 -0
  126. package/src/icons/__snapshots__/MobileIcon.test.tsx.snap +160 -0
  127. package/src/icons/__snapshots__/OfflineIcon.test.tsx.snap +133 -0
  128. package/src/icons/__snapshots__/OnlineIcon.test.tsx.snap +124 -0
  129. package/src/icons/__snapshots__/OutOfficeIcon.test.tsx.snap +160 -0
  130. package/src/table/Table.test.tsx +107 -0
  131. package/src/table/TableBadge.test.tsx +53 -0
  132. package/src/table/TableBoolean.test.tsx +38 -0
  133. package/src/table/TableDate.test.tsx +27 -0
  134. package/src/table/TableHeader.test.tsx +67 -0
  135. package/src/table/TableHeaderCell.test.tsx +113 -0
  136. package/src/table/TableIconButton.test.tsx +51 -0
  137. package/src/table/TableNumber.test.tsx +45 -0
  138. package/src/table/TableRow.test.tsx +83 -0
  139. package/src/table/TableText.test.tsx +30 -0
  140. package/src/table/TableTitle.test.tsx +30 -0
  141. package/src/table/__snapshots__/Table.test.tsx.snap +2090 -0
  142. package/src/table/__snapshots__/TableBadge.test.tsx.snap +710 -0
  143. package/src/table/__snapshots__/TableBoolean.test.tsx.snap +231 -0
  144. package/src/table/__snapshots__/TableDate.test.tsx.snap +61 -0
  145. package/src/table/__snapshots__/TableHeader.test.tsx.snap +1089 -0
  146. package/src/table/__snapshots__/TableHeaderCell.test.tsx.snap +1773 -0
  147. package/src/table/__snapshots__/TableIconButton.test.tsx.snap +81 -0
  148. package/src/table/__snapshots__/TableNumber.test.tsx.snap +91 -0
  149. package/src/table/__snapshots__/TableRow.test.tsx.snap +1391 -0
  150. package/src/table/__snapshots__/TableText.test.tsx.snap +73 -0
  151. package/src/table/__snapshots__/TableTitle.test.tsx.snap +109 -0
@@ -0,0 +1,153 @@
1
+ import {describe, expect, it} from "bun:test";
2
+ import {render} from "@testing-library/react-native";
3
+ import {Text, View} from "react-native";
4
+
5
+ import {ThemeProvider, useTheme} from "./Theme";
6
+
7
+ const ThemeConsumer = () => {
8
+ const {theme} = useTheme();
9
+ return (
10
+ <View>
11
+ <Text testID="surface-base">{theme.surface?.base}</Text>
12
+ <Text testID="text-primary">{theme.text?.primary}</Text>
13
+ </View>
14
+ );
15
+ };
16
+
17
+ describe("Theme", () => {
18
+ describe("ThemeProvider", () => {
19
+ it("renders children", () => {
20
+ const {getByText} = render(
21
+ <ThemeProvider>
22
+ <Text>Child content</Text>
23
+ </ThemeProvider>
24
+ );
25
+ expect(getByText("Child content")).toBeTruthy();
26
+ });
27
+
28
+ it("provides default theme values", () => {
29
+ const {getByTestId} = render(
30
+ <ThemeProvider>
31
+ <ThemeConsumer />
32
+ </ThemeProvider>
33
+ );
34
+ // Default surface.base is neutral000 which maps to #FFFFFF
35
+ expect(getByTestId("surface-base").children[0]).toBe("#FFFFFF");
36
+ // Default text.primary is neutral900 which maps to #1C1C1C
37
+ expect(getByTestId("text-primary").children[0]).toBe("#1C1C1C");
38
+ });
39
+ });
40
+
41
+ describe("useTheme", () => {
42
+ it("returns theme object", () => {
43
+ let capturedTheme: any;
44
+ const Capture = () => {
45
+ capturedTheme = useTheme();
46
+ return null;
47
+ };
48
+
49
+ render(
50
+ <ThemeProvider>
51
+ <Capture />
52
+ </ThemeProvider>
53
+ );
54
+
55
+ expect(capturedTheme.theme).toBeDefined();
56
+ expect(capturedTheme.setTheme).toBeDefined();
57
+ expect(capturedTheme.setPrimitives).toBeDefined();
58
+ expect(capturedTheme.resetTheme).toBeDefined();
59
+ });
60
+
61
+ it("provides surface colors", () => {
62
+ let theme: any;
63
+ const Capture = () => {
64
+ theme = useTheme().theme;
65
+ return null;
66
+ };
67
+
68
+ render(
69
+ <ThemeProvider>
70
+ <Capture />
71
+ </ThemeProvider>
72
+ );
73
+
74
+ expect(theme.surface).toBeDefined();
75
+ expect(theme.surface.base).toBeDefined();
76
+ expect(theme.surface.primary).toBeDefined();
77
+ expect(theme.surface.error).toBeDefined();
78
+ });
79
+
80
+ it("provides text colors", () => {
81
+ let theme: any;
82
+ const Capture = () => {
83
+ theme = useTheme().theme;
84
+ return null;
85
+ };
86
+
87
+ render(
88
+ <ThemeProvider>
89
+ <Capture />
90
+ </ThemeProvider>
91
+ );
92
+
93
+ expect(theme.text).toBeDefined();
94
+ expect(theme.text.primary).toBeDefined();
95
+ expect(theme.text.inverted).toBeDefined();
96
+ expect(theme.text.error).toBeDefined();
97
+ });
98
+
99
+ it("provides border colors", () => {
100
+ let theme: any;
101
+ const Capture = () => {
102
+ theme = useTheme().theme;
103
+ return null;
104
+ };
105
+
106
+ render(
107
+ <ThemeProvider>
108
+ <Capture />
109
+ </ThemeProvider>
110
+ );
111
+
112
+ expect(theme.border).toBeDefined();
113
+ expect(theme.border.default).toBeDefined();
114
+ });
115
+
116
+ it("provides spacing values", () => {
117
+ let theme: any;
118
+ const Capture = () => {
119
+ theme = useTheme().theme;
120
+ return null;
121
+ };
122
+
123
+ render(
124
+ <ThemeProvider>
125
+ <Capture />
126
+ </ThemeProvider>
127
+ );
128
+
129
+ expect(theme.spacing).toBeDefined();
130
+ expect(theme.spacing.sm).toBeDefined();
131
+ expect(theme.spacing.md).toBeDefined();
132
+ expect(theme.spacing.lg).toBeDefined();
133
+ });
134
+
135
+ it("provides radius values", () => {
136
+ let theme: any;
137
+ const Capture = () => {
138
+ theme = useTheme().theme;
139
+ return null;
140
+ };
141
+
142
+ render(
143
+ <ThemeProvider>
144
+ <Capture />
145
+ </ThemeProvider>
146
+ );
147
+
148
+ expect(theme.radius).toBeDefined();
149
+ expect(theme.radius.default).toBeDefined();
150
+ expect(theme.radius.rounded).toBeDefined();
151
+ });
152
+ });
153
+ });
@@ -0,0 +1,57 @@
1
+ import {describe, expect, it, mock} from "bun:test";
2
+
3
+ import {TimezonePicker} from "./TimezonePicker";
4
+ import {renderWithTheme} from "./test-utils";
5
+
6
+ describe("TimezonePicker", () => {
7
+ it("renders correctly with default props", () => {
8
+ const {toJSON} = renderWithTheme(<TimezonePicker onChange={() => {}} />);
9
+ expect(toJSON()).toMatchSnapshot();
10
+ });
11
+
12
+ it("renders with title by default", () => {
13
+ const {getByText} = renderWithTheme(<TimezonePicker onChange={() => {}} />);
14
+ expect(getByText("Timezone")).toBeTruthy();
15
+ });
16
+
17
+ it("hides title when hideTitle is true", () => {
18
+ const {toJSON} = renderWithTheme(<TimezonePicker hideTitle onChange={() => {}} />);
19
+ expect(toJSON()).toMatchSnapshot();
20
+ });
21
+
22
+ it("renders with selected timezone", () => {
23
+ const {toJSON} = renderWithTheme(
24
+ <TimezonePicker onChange={() => {}} timezone="America/New_York" />
25
+ );
26
+ expect(toJSON()).toMatchSnapshot();
27
+ });
28
+
29
+ it("renders USA timezones by default", () => {
30
+ const {toJSON} = renderWithTheme(
31
+ <TimezonePicker location="USA" onChange={() => {}} timezone="America/New_York" />
32
+ );
33
+ expect(toJSON()).toMatchSnapshot();
34
+ });
35
+
36
+ it("renders worldwide timezones when specified", () => {
37
+ const {toJSON} = renderWithTheme(
38
+ <TimezonePicker location="Worldwide" onChange={() => {}} timezone="Europe/London" />
39
+ );
40
+ expect(toJSON()).toMatchSnapshot();
41
+ });
42
+
43
+ it("renders with short timezone labels", () => {
44
+ const {toJSON} = renderWithTheme(
45
+ <TimezonePicker onChange={() => {}} shortTimezone timezone="America/New_York" />
46
+ );
47
+ expect(toJSON()).toMatchSnapshot();
48
+ });
49
+
50
+ it("calls onChange when timezone is selected", () => {
51
+ const handleChange = mock((_value: string) => {});
52
+ const {toJSON} = renderWithTheme(
53
+ <TimezonePicker onChange={handleChange} timezone="America/New_York" />
54
+ );
55
+ expect(toJSON()).toMatchSnapshot();
56
+ });
57
+ });
@@ -0,0 +1,82 @@
1
+ import {describe, expect, it, mock} from "bun:test";
2
+
3
+ import {Toast} from "./Toast";
4
+ import {renderWithTheme} from "./test-utils";
5
+
6
+ describe("Toast", () => {
7
+ it("renders correctly with default props", () => {
8
+ const {toJSON} = renderWithTheme(<Toast title="Test message" />);
9
+ expect(toJSON()).toMatchSnapshot();
10
+ });
11
+
12
+ it("renders title correctly", () => {
13
+ const {getByText} = renderWithTheme(<Toast title="Success!" />);
14
+ expect(getByText("Success!")).toBeTruthy();
15
+ });
16
+
17
+ it("renders info variant (default)", () => {
18
+ const {toJSON} = renderWithTheme(<Toast title="Info message" variant="info" />);
19
+ expect(toJSON()).toMatchSnapshot();
20
+ });
21
+
22
+ it("renders success variant", () => {
23
+ const {toJSON} = renderWithTheme(<Toast title="Success!" variant="success" />);
24
+ expect(toJSON()).toMatchSnapshot();
25
+ });
26
+
27
+ it("renders warning variant", () => {
28
+ const {toJSON} = renderWithTheme(<Toast title="Warning!" variant="warning" />);
29
+ expect(toJSON()).toMatchSnapshot();
30
+ });
31
+
32
+ it("renders error variant", () => {
33
+ const {toJSON} = renderWithTheme(<Toast title="Error!" variant="error" />);
34
+ expect(toJSON()).toMatchSnapshot();
35
+ });
36
+
37
+ it("renders with small size (default)", () => {
38
+ const {toJSON} = renderWithTheme(<Toast size="sm" title="Small toast" />);
39
+ expect(toJSON()).toMatchSnapshot();
40
+ });
41
+
42
+ it("renders with large size", () => {
43
+ const {toJSON} = renderWithTheme(<Toast size="lg" title="Large toast" />);
44
+ expect(toJSON()).toMatchSnapshot();
45
+ });
46
+
47
+ it("renders with subtitle when size is large", () => {
48
+ const {getByText, toJSON} = renderWithTheme(
49
+ <Toast size="lg" subtitle="Additional details here" title="Main message" />
50
+ );
51
+ expect(getByText("Main message")).toBeTruthy();
52
+ expect(getByText("Additional details here")).toBeTruthy();
53
+ expect(toJSON()).toMatchSnapshot();
54
+ });
55
+
56
+ it("renders persistent toast with dismiss button", () => {
57
+ const handleDismiss = mock(() => {});
58
+ const {toJSON} = renderWithTheme(
59
+ <Toast onDismiss={handleDismiss} persistent title="Persistent toast" />
60
+ );
61
+ expect(toJSON()).toMatchSnapshot();
62
+ });
63
+
64
+ it("renders dismiss button when persistent with onDismiss", () => {
65
+ const handleDismiss = mock(() => {});
66
+ const {toJSON} = renderWithTheme(
67
+ <Toast onDismiss={handleDismiss} persistent title="Dismissible" />
68
+ );
69
+ // Verify dismiss button is rendered
70
+ expect(toJSON()).toMatchSnapshot();
71
+ });
72
+
73
+ it("renders all variants with large size correctly", () => {
74
+ const variants = ["info", "success", "warning", "error"] as const;
75
+ variants.forEach((variant) => {
76
+ const {toJSON} = renderWithTheme(
77
+ <Toast size="lg" subtitle="Details" title={`${variant} toast`} variant={variant} />
78
+ );
79
+ expect(toJSON()).toMatchSnapshot();
80
+ });
81
+ });
82
+ });
@@ -0,0 +1,89 @@
1
+ import {describe, expect, it} from "bun:test";
2
+
3
+ import {Text} from "./Text";
4
+ import {Tooltip} from "./Tooltip";
5
+ import {renderWithTheme} from "./test-utils";
6
+
7
+ describe("Tooltip", () => {
8
+ it("renders children correctly", () => {
9
+ const {getByText} = renderWithTheme(
10
+ <Tooltip text="Tooltip text">
11
+ <Text>Hover me</Text>
12
+ </Tooltip>
13
+ );
14
+ expect(getByText("Hover me")).toBeTruthy();
15
+ });
16
+
17
+ it("renders without tooltip when text is empty", () => {
18
+ const {getByText, toJSON} = renderWithTheme(
19
+ <Tooltip text="">
20
+ <Text>No tooltip</Text>
21
+ </Tooltip>
22
+ );
23
+ expect(getByText("No tooltip")).toBeTruthy();
24
+ expect(toJSON()).toMatchSnapshot();
25
+ });
26
+
27
+ it("renders with tooltip text", () => {
28
+ const {toJSON} = renderWithTheme(
29
+ <Tooltip text="This is helpful information">
30
+ <Text>Hover for info</Text>
31
+ </Tooltip>
32
+ );
33
+ expect(toJSON()).toMatchSnapshot();
34
+ });
35
+
36
+ it("renders with top position (default)", () => {
37
+ const {toJSON} = renderWithTheme(
38
+ <Tooltip idealPosition="top" text="Top tooltip">
39
+ <Text>Content</Text>
40
+ </Tooltip>
41
+ );
42
+ expect(toJSON()).toMatchSnapshot();
43
+ });
44
+
45
+ it("renders with bottom position", () => {
46
+ const {toJSON} = renderWithTheme(
47
+ <Tooltip idealPosition="bottom" text="Bottom tooltip">
48
+ <Text>Content</Text>
49
+ </Tooltip>
50
+ );
51
+ expect(toJSON()).toMatchSnapshot();
52
+ });
53
+
54
+ it("renders with left position", () => {
55
+ const {toJSON} = renderWithTheme(
56
+ <Tooltip idealPosition="left" text="Left tooltip">
57
+ <Text>Content</Text>
58
+ </Tooltip>
59
+ );
60
+ expect(toJSON()).toMatchSnapshot();
61
+ });
62
+
63
+ it("renders with right position", () => {
64
+ const {toJSON} = renderWithTheme(
65
+ <Tooltip idealPosition="right" text="Right tooltip">
66
+ <Text>Content</Text>
67
+ </Tooltip>
68
+ );
69
+ expect(toJSON()).toMatchSnapshot();
70
+ });
71
+
72
+ it("renders with arrow", () => {
73
+ const {toJSON} = renderWithTheme(
74
+ <Tooltip includeArrow text="Tooltip with arrow">
75
+ <Text>Content</Text>
76
+ </Tooltip>
77
+ );
78
+ expect(toJSON()).toMatchSnapshot();
79
+ });
80
+
81
+ it("renders with arrow and specific position", () => {
82
+ const {toJSON} = renderWithTheme(
83
+ <Tooltip idealPosition="bottom" includeArrow text="Bottom with arrow">
84
+ <Text>Content</Text>
85
+ </Tooltip>
86
+ );
87
+ expect(toJSON()).toMatchSnapshot();
88
+ });
89
+ });
@@ -0,0 +1,15 @@
1
+ import {describe, expect, it} from "bun:test";
2
+
3
+ import {UnifiedAddressAutoCompleteField} from "./UnifiedAddressAutoComplete";
4
+
5
+ describe("UnifiedAddressAutoCompleteField", () => {
6
+ // UnifiedAddressAutoCompleteField uses Google Places API and platform-specific implementations
7
+ it.skip("renders correctly (skipped - uses Google Places API)", () => {
8
+ expect(UnifiedAddressAutoCompleteField).toBeDefined();
9
+ });
10
+
11
+ it("component is defined", () => {
12
+ expect(UnifiedAddressAutoCompleteField).toBeDefined();
13
+ expect(typeof UnifiedAddressAutoCompleteField).toBe("function");
14
+ });
15
+ });
@@ -0,0 +1,237 @@
1
+ import {describe, expect, it} from "bun:test";
2
+
3
+ import {
4
+ concat,
5
+ findAddressComponent,
6
+ fromClassName,
7
+ fromInlineStyle,
8
+ iconNumberToSize,
9
+ identity,
10
+ isAPIError,
11
+ isNative,
12
+ isTestUser,
13
+ isValidGoogleApiKey,
14
+ mergeInlineStyles,
15
+ printAPIError,
16
+ processAddressComponents,
17
+ toProps,
18
+ } from "./Utilities";
19
+
20
+ describe("Utilities", () => {
21
+ describe("mergeInlineStyles", () => {
22
+ it("merges inline styles", () => {
23
+ const existing = {__style: {color: "red"}};
24
+ const newStyle = {backgroundColor: "blue"};
25
+ const result = mergeInlineStyles(existing, newStyle);
26
+ expect(result.__style).toEqual({backgroundColor: "blue", color: "red"});
27
+ });
28
+
29
+ it("handles undefined existing style", () => {
30
+ const result = mergeInlineStyles(undefined, {color: "red"});
31
+ expect(result.__style).toEqual({color: "red"});
32
+ });
33
+ });
34
+
35
+ describe("isTestUser", () => {
36
+ it("returns true for nang.io email", () => {
37
+ expect(isTestUser({email: "test@nang.io"} as any)).toBe(true);
38
+ });
39
+
40
+ it("returns true for example.com email", () => {
41
+ expect(isTestUser({email: "test@example.com"} as any)).toBe(true);
42
+ });
43
+
44
+ it("returns false for regular email", () => {
45
+ expect(isTestUser({email: "user@company.com"} as any)).toBe(false);
46
+ });
47
+
48
+ it("returns falsy for undefined profile", () => {
49
+ expect(isTestUser(undefined)).toBeFalsy();
50
+ });
51
+ });
52
+
53
+ describe("iconNumberToSize", () => {
54
+ it("returns xs for size less than 8", () => {
55
+ expect(iconNumberToSize(5)).toBe("xs");
56
+ });
57
+
58
+ it("returns sm for size 8-11", () => {
59
+ expect(iconNumberToSize(10)).toBe("sm");
60
+ });
61
+
62
+ it("returns md for size 12-13", () => {
63
+ expect(iconNumberToSize(12)).toBe("md");
64
+ });
65
+
66
+ it("returns lg for size 14-19", () => {
67
+ expect(iconNumberToSize(16)).toBe("lg");
68
+ });
69
+
70
+ it("returns xl for size 20+", () => {
71
+ expect(iconNumberToSize(24)).toBe("xl");
72
+ });
73
+
74
+ it("returns lg for default size (16)", () => {
75
+ expect(iconNumberToSize()).toBe("lg");
76
+ });
77
+ });
78
+
79
+ describe("Style utilities", () => {
80
+ describe("identity", () => {
81
+ it("returns empty style", () => {
82
+ const result = identity();
83
+ expect(result.className.size).toBe(0);
84
+ expect(Object.keys(result.inlineStyle).length).toBe(0);
85
+ });
86
+ });
87
+
88
+ describe("fromClassName", () => {
89
+ it("creates style from classnames", () => {
90
+ const result = fromClassName("class1", "class2");
91
+ expect(result.className.has("class1")).toBe(true);
92
+ expect(result.className.has("class2")).toBe(true);
93
+ });
94
+ });
95
+
96
+ describe("fromInlineStyle", () => {
97
+ it("creates style from inline styles", () => {
98
+ const result = fromInlineStyle({color: "red", fontSize: 14});
99
+ expect(result.inlineStyle).toEqual({color: "red", fontSize: 14});
100
+ });
101
+ });
102
+
103
+ describe("concat", () => {
104
+ it("concatenates multiple styles", () => {
105
+ const style1 = fromClassName("class1");
106
+ const style2 = fromClassName("class2");
107
+ const style3 = fromInlineStyle({color: "red"});
108
+ const result = concat([style1, style2, style3]);
109
+ expect(result.className.has("class1")).toBe(true);
110
+ expect(result.className.has("class2")).toBe(true);
111
+ expect(result.inlineStyle.color).toBe("red");
112
+ });
113
+ });
114
+
115
+ describe("toProps", () => {
116
+ it("converts style to props object", () => {
117
+ const style = concat([fromClassName("a", "b"), fromInlineStyle({color: "red"})]);
118
+ const props = toProps(style);
119
+ expect(props.className).toBe("a b");
120
+ expect(props.style).toEqual({color: "red"});
121
+ });
122
+
123
+ it("omits empty className", () => {
124
+ const style = fromInlineStyle({color: "red"});
125
+ const props = toProps(style);
126
+ expect(props.className).toBeUndefined();
127
+ });
128
+
129
+ it("omits empty style", () => {
130
+ const style = fromClassName("class1");
131
+ const props = toProps(style);
132
+ expect(props.style).toBeUndefined();
133
+ });
134
+ });
135
+ });
136
+
137
+ describe("isNative", () => {
138
+ it("returns boolean", () => {
139
+ const result = isNative();
140
+ expect(typeof result).toBe("boolean");
141
+ });
142
+ });
143
+
144
+ describe("findAddressComponent", () => {
145
+ const components = [
146
+ {long_name: "123", short_name: "123", types: ["street_number"]},
147
+ {long_name: "Main Street", short_name: "Main St", types: ["route"]},
148
+ {long_name: "New York", short_name: "NY", types: ["locality"]},
149
+ ];
150
+
151
+ it("finds component by type", () => {
152
+ expect(findAddressComponent(components, "locality")).toBe("New York");
153
+ });
154
+
155
+ it("returns empty string for missing type", () => {
156
+ expect(findAddressComponent(components, "country")).toBe("");
157
+ });
158
+ });
159
+
160
+ describe("processAddressComponents", () => {
161
+ const components = [
162
+ {long_name: "123", short_name: "123", types: ["street_number"]},
163
+ {long_name: "Main Street", short_name: "Main St", types: ["route"]},
164
+ {long_name: "Boston", short_name: "Boston", types: ["locality"]},
165
+ {long_name: "Massachusetts", short_name: "MA", types: ["administrative_area_level_1"]},
166
+ {long_name: "02101", short_name: "02101", types: ["postal_code"]},
167
+ ];
168
+
169
+ it("processes address components correctly", () => {
170
+ const result = processAddressComponents(components);
171
+ expect(result.address1).toBe("123 Main Street");
172
+ expect(result.city).toBe("Boston");
173
+ expect(result.state).toBe("Massachusetts");
174
+ expect(result.zipcode).toBe("02101");
175
+ });
176
+
177
+ it("handles empty components", () => {
178
+ const result = processAddressComponents([]);
179
+ expect(result.address1).toBe("");
180
+ });
181
+
182
+ it("handles undefined components", () => {
183
+ const result = processAddressComponents(undefined);
184
+ expect(result.address1).toBe("");
185
+ });
186
+ });
187
+
188
+ describe("isValidGoogleApiKey", () => {
189
+ it("returns true for valid-looking API key", () => {
190
+ expect(isValidGoogleApiKey("AIzaSyD-9tSrke72PouQMnMX-a7eZSW0jkFMBWY")).toBe(true);
191
+ });
192
+
193
+ it("returns false for empty string", () => {
194
+ expect(isValidGoogleApiKey("")).toBe(false);
195
+ });
196
+
197
+ it("returns false for too short key", () => {
198
+ expect(isValidGoogleApiKey("short")).toBe(false);
199
+ });
200
+
201
+ it("returns false for key with invalid characters", () => {
202
+ expect(isValidGoogleApiKey("invalid key with spaces!!!")).toBe(false);
203
+ });
204
+ });
205
+
206
+ describe("isAPIError", () => {
207
+ it("returns truthy for API error object", () => {
208
+ const error = {data: {detail: "Something went wrong", title: "Error"}};
209
+ expect(isAPIError(error)).toBeTruthy();
210
+ });
211
+
212
+ it("returns falsy for non-API error", () => {
213
+ expect(isAPIError({message: "error"})).toBeFalsy();
214
+ });
215
+
216
+ it("returns falsy for null", () => {
217
+ expect(isAPIError(null)).toBeFalsy();
218
+ });
219
+ });
220
+
221
+ describe("printAPIError", () => {
222
+ it("prints error title", () => {
223
+ const error = {data: {title: "Not Found"}};
224
+ expect(printAPIError(error as any)).toBe("Not Found");
225
+ });
226
+
227
+ it("prints error title and detail", () => {
228
+ const error = {data: {detail: "Resource does not exist", title: "Not Found"}};
229
+ expect(printAPIError(error as any)).toBe("Not Found: Resource does not exist");
230
+ });
231
+
232
+ it("omits detail when details is false", () => {
233
+ const error = {data: {detail: "Resource does not exist", title: "Not Found"}};
234
+ expect(printAPIError(error as any, false)).toBe("Not Found");
235
+ });
236
+ });
237
+ });
@@ -0,0 +1,15 @@
1
+ import {describe, expect, it} from "bun:test";
2
+
3
+ import {WebAddressAutocomplete} from "./WebAddressAutocomplete";
4
+
5
+ describe("WebAddressAutocomplete", () => {
6
+ // WebAddressAutocomplete uses Google Places API
7
+ it.skip("renders correctly (skipped - uses Google Places API)", () => {
8
+ expect(WebAddressAutocomplete).toBeDefined();
9
+ });
10
+
11
+ it("component is defined", () => {
12
+ expect(WebAddressAutocomplete).toBeDefined();
13
+ expect(typeof WebAddressAutocomplete).toBe("function");
14
+ });
15
+ });