@terreno/ui 0.0.15 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Button.js +7 -9
- package/dist/Button.js.map +1 -1
- package/dist/Common.d.ts +39 -0
- package/dist/DateUtilities.js +2 -2
- package/dist/UserInactivity.d.ts +28 -0
- package/dist/UserInactivity.js +100 -0
- package/dist/UserInactivity.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/ActionSheet.test.tsx +77 -0
- package/src/Banner.test.tsx +106 -0
- package/src/Body.test.tsx +79 -0
- package/src/BooleanField.test.tsx +84 -0
- package/src/Button.test.tsx +160 -0
- package/src/Button.tsx +20 -37
- package/src/Card.test.tsx +61 -0
- package/src/CheckBox.test.tsx +53 -0
- package/src/Common.ts +45 -0
- package/src/CustomSelectField.test.tsx +85 -0
- package/src/DataTable.test.tsx +133 -0
- package/src/DateTimeActionSheet.test.tsx +65 -0
- package/src/DateUtilities.tsx +2 -2
- package/src/DecimalRangeActionSheet.test.tsx +46 -0
- package/src/DismissButton.test.tsx +49 -0
- package/src/EmailField.test.tsx +106 -0
- package/src/ErrorBoundary.test.tsx +44 -0
- package/src/ErrorPage.test.tsx +44 -0
- package/src/Field.test.tsx +128 -0
- package/src/Heading.test.tsx +66 -0
- package/src/HeightActionSheet.test.tsx +34 -0
- package/src/Hyperlink.test.tsx +52 -0
- package/src/Icon.test.tsx +61 -0
- package/src/IconButton.test.tsx +145 -0
- package/src/Image.test.tsx +65 -0
- package/src/ImageBackground.test.tsx +46 -0
- package/src/InfoModalIcon.test.tsx +54 -0
- package/src/InfoTooltipButton.test.tsx +22 -0
- package/src/Link.test.tsx +64 -0
- package/src/MarkdownView.test.tsx +50 -0
- package/src/MobileAddressAutoComplete.test.tsx +58 -0
- package/src/Modal.test.tsx +169 -0
- package/src/ModalSheet.test.tsx +52 -0
- package/src/MultiselectField.test.tsx +134 -0
- package/src/NumberField.test.tsx +133 -0
- package/src/NumberPickerActionSheet.test.tsx +46 -0
- package/src/OpenAPIContext.test.tsx +36 -0
- package/src/Page.test.tsx +128 -0
- package/src/Pagination.test.tsx +86 -0
- package/src/PasswordField.test.tsx +17 -0
- package/src/PhoneNumberField.test.tsx +79 -0
- package/src/PickerSelect.test.tsx +52 -0
- package/src/Radio.test.tsx +30 -0
- package/src/RadioField.test.tsx +89 -0
- package/src/SectionDivider.test.tsx +17 -0
- package/src/SegmentedControl.test.tsx +84 -0
- package/src/SelectBadge.test.tsx +103 -0
- package/src/SelectField.test.tsx +84 -0
- package/src/SideDrawer.test.tsx +99 -0
- package/src/Signature.test.tsx +32 -0
- package/src/SignatureField.test.tsx +60 -0
- package/src/Spinner.test.tsx +74 -0
- package/src/SplitPage.test.tsx +82 -0
- package/src/TapToEdit.test.tsx +147 -0
- package/src/TerrenoProvider.test.tsx +36 -0
- package/src/Text.test.tsx +147 -0
- package/src/Theme.test.tsx +153 -0
- package/src/TimezonePicker.test.tsx +57 -0
- package/src/Toast.test.tsx +82 -0
- package/src/Tooltip.test.tsx +89 -0
- package/src/UnifiedAddressAutoComplete.test.tsx +53 -0
- package/src/UserInactivity.test.tsx +96 -0
- package/src/UserInactivity.tsx +129 -0
- package/src/Utilities.test.tsx +237 -0
- package/src/WebAddressAutocomplete.test.tsx +33 -0
- package/src/__snapshots__/ActionSheet.test.tsx.snap +889 -0
- package/src/__snapshots__/Banner.test.tsx.snap +546 -0
- package/src/__snapshots__/Body.test.tsx.snap +685 -0
- package/src/__snapshots__/BooleanField.test.tsx.snap +553 -0
- package/src/__snapshots__/Button.test.tsx.snap +934 -0
- package/src/__snapshots__/Card.test.tsx.snap +195 -0
- package/src/__snapshots__/CheckBox.test.tsx.snap +190 -0
- package/src/__snapshots__/CustomSelectField.test.tsx.snap +2299 -0
- package/src/__snapshots__/DataTable.test.tsx.snap +9614 -0
- package/src/__snapshots__/DateTimeActionSheet.test.tsx.snap +11 -0
- package/src/__snapshots__/DecimalRangeActionSheet.test.tsx.snap +1719 -0
- package/src/__snapshots__/DismissButton.test.tsx.snap +91 -0
- package/src/__snapshots__/EmailField.test.tsx.snap +168 -0
- package/src/__snapshots__/ErrorBoundary.test.tsx.snap +57 -0
- package/src/__snapshots__/ErrorPage.test.tsx.snap +195 -0
- package/src/__snapshots__/Field.test.tsx.snap +4510 -0
- package/src/__snapshots__/Heading.test.tsx.snap +193 -0
- package/src/__snapshots__/HeightActionSheet.test.tsx.snap +1269 -0
- package/src/__snapshots__/Hyperlink.test.tsx.snap +81 -0
- package/src/__snapshots__/Icon.test.tsx.snap +47 -0
- package/src/__snapshots__/IconButton.test.tsx.snap +29 -0
- package/src/__snapshots__/Image.test.tsx.snap +282 -0
- package/src/__snapshots__/ImageBackground.test.tsx.snap +120 -0
- package/src/__snapshots__/InfoModalIcon.test.tsx.snap +1229 -0
- package/src/__snapshots__/InfoTooltipButton.test.tsx.snap +7 -0
- package/src/__snapshots__/Link.test.tsx.snap +41 -0
- package/src/__snapshots__/MarkdownView.test.tsx.snap +965 -0
- package/src/__snapshots__/MobileAddressAutoComplete.test.tsx.snap +230 -0
- package/src/__snapshots__/Modal.test.tsx.snap +1477 -0
- package/src/__snapshots__/ModalSheet.test.tsx.snap +37 -0
- package/src/__snapshots__/MultiselectField.test.tsx.snap +1454 -0
- package/src/__snapshots__/NumberField.test.tsx.snap +80 -0
- package/src/__snapshots__/NumberPickerActionSheet.test.tsx.snap +5359 -0
- package/src/__snapshots__/OpenAPIContext.test.tsx.snap +14 -0
- package/src/__snapshots__/Page.test.tsx.snap +1647 -0
- package/src/__snapshots__/Pagination.test.tsx.snap +1913 -0
- package/src/__snapshots__/PasswordField.test.tsx.snap +15 -0
- package/src/__snapshots__/PhoneNumberField.test.tsx.snap +405 -0
- package/src/__snapshots__/PickerSelect.test.tsx.snap +1053 -0
- package/src/__snapshots__/Radio.test.tsx.snap +111 -0
- package/src/__snapshots__/RadioField.test.tsx.snap +944 -0
- package/src/__snapshots__/SectionDivider.test.tsx.snap +37 -0
- package/src/__snapshots__/SegmentedControl.test.tsx.snap +1422 -0
- package/src/__snapshots__/SelectBadge.test.tsx.snap +2377 -0
- package/src/__snapshots__/SelectField.test.tsx.snap +1658 -0
- package/src/__snapshots__/SideDrawer.test.tsx.snap +1857 -0
- package/src/__snapshots__/Signature.test.tsx.snap +67 -0
- package/src/__snapshots__/SignatureField.test.tsx.snap +241 -0
- package/src/__snapshots__/Spinner.test.tsx.snap +73 -0
- package/src/__snapshots__/SplitPage.test.tsx.snap +686 -0
- package/src/__snapshots__/TapToEdit.test.tsx.snap +839 -0
- package/src/__snapshots__/TerrenoProvider.test.tsx.snap +203 -0
- package/src/__snapshots__/Text.test.tsx.snap +558 -0
- package/src/__snapshots__/TimezonePicker.test.tsx.snap +6676 -0
- package/src/__snapshots__/Toast.test.tsx.snap +1982 -0
- package/src/__snapshots__/Tooltip.test.tsx.snap +456 -0
- package/src/__snapshots__/UnifiedAddressAutoComplete.test.tsx.snap +377 -0
- package/src/__snapshots__/UserInactivity.test.tsx.snap +108 -0
- package/src/__snapshots__/WebAddressAutocomplete.test.tsx.snap +238 -0
- package/src/bunSetup.ts +101 -8
- package/src/fieldElements/FieldError.test.tsx +40 -0
- package/src/fieldElements/FieldHelperText.test.tsx +34 -0
- package/src/fieldElements/FieldTitle.test.tsx +30 -0
- package/src/fieldElements/__snapshots__/FieldError.test.tsx.snap +85 -0
- package/src/fieldElements/__snapshots__/FieldHelperText.test.tsx.snap +30 -0
- package/src/fieldElements/__snapshots__/FieldTitle.test.tsx.snap +19 -0
- package/src/icons/MobileIcon.test.tsx +21 -0
- package/src/icons/OfflineIcon.test.tsx +21 -0
- package/src/icons/OnlineIcon.test.tsx +21 -0
- package/src/icons/OutOfficeIcon.test.tsx +21 -0
- package/src/icons/__snapshots__/MobileIcon.test.tsx.snap +160 -0
- package/src/icons/__snapshots__/OfflineIcon.test.tsx.snap +133 -0
- package/src/icons/__snapshots__/OnlineIcon.test.tsx.snap +124 -0
- package/src/icons/__snapshots__/OutOfficeIcon.test.tsx.snap +160 -0
- package/src/index.tsx +1 -0
- package/src/table/Table.test.tsx +107 -0
- package/src/table/TableBadge.test.tsx +53 -0
- package/src/table/TableBoolean.test.tsx +38 -0
- package/src/table/TableDate.test.tsx +27 -0
- package/src/table/TableHeader.test.tsx +67 -0
- package/src/table/TableHeaderCell.test.tsx +113 -0
- package/src/table/TableIconButton.test.tsx +51 -0
- package/src/table/TableNumber.test.tsx +45 -0
- package/src/table/TableRow.test.tsx +83 -0
- package/src/table/TableText.test.tsx +30 -0
- package/src/table/TableTitle.test.tsx +30 -0
- package/src/table/__snapshots__/Table.test.tsx.snap +2090 -0
- package/src/table/__snapshots__/TableBadge.test.tsx.snap +710 -0
- package/src/table/__snapshots__/TableBoolean.test.tsx.snap +231 -0
- package/src/table/__snapshots__/TableDate.test.tsx.snap +61 -0
- package/src/table/__snapshots__/TableHeader.test.tsx.snap +1089 -0
- package/src/table/__snapshots__/TableHeaderCell.test.tsx.snap +1773 -0
- package/src/table/__snapshots__/TableIconButton.test.tsx.snap +81 -0
- package/src/table/__snapshots__/TableNumber.test.tsx.snap +91 -0
- package/src/table/__snapshots__/TableRow.test.tsx.snap +1391 -0
- package/src/table/__snapshots__/TableText.test.tsx.snap +73 -0
- package/src/table/__snapshots__/TableTitle.test.tsx.snap +109 -0
|
@@ -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,53 @@
|
|
|
1
|
+
import {describe, expect, it, mock} from "bun:test";
|
|
2
|
+
import {forwardRef} from "react";
|
|
3
|
+
import {Text, View} from "react-native";
|
|
4
|
+
import {renderWithTheme} from "./test-utils";
|
|
5
|
+
import {UnifiedAddressAutoCompleteField} from "./UnifiedAddressAutoComplete";
|
|
6
|
+
|
|
7
|
+
// Mock react-native-google-places-autocomplete (used by MobileAddressAutocomplete)
|
|
8
|
+
mock.module("react-native-google-places-autocomplete", () => ({
|
|
9
|
+
GooglePlacesAutocomplete: forwardRef(({placeholder}: any, ref) => (
|
|
10
|
+
<View ref={ref as any} testID="google-places-autocomplete">
|
|
11
|
+
<Text>{placeholder}</Text>
|
|
12
|
+
</View>
|
|
13
|
+
)),
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
describe("UnifiedAddressAutoCompleteField", () => {
|
|
17
|
+
const defaultProps = {
|
|
18
|
+
handleAddressChange: () => {},
|
|
19
|
+
handleAutoCompleteChange: () => {},
|
|
20
|
+
inputValue: "",
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
it("renders correctly without Google API key (fallback to TextField)", () => {
|
|
24
|
+
const {toJSON} = renderWithTheme(<UnifiedAddressAutoCompleteField {...defaultProps} />);
|
|
25
|
+
expect(toJSON()).toMatchSnapshot();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("component is defined", () => {
|
|
29
|
+
expect(UnifiedAddressAutoCompleteField).toBeDefined();
|
|
30
|
+
expect(typeof UnifiedAddressAutoCompleteField).toBe("function");
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("renders with input value", () => {
|
|
34
|
+
const {toJSON} = renderWithTheme(
|
|
35
|
+
<UnifiedAddressAutoCompleteField {...defaultProps} inputValue="123 Main St" />
|
|
36
|
+
);
|
|
37
|
+
expect(toJSON()).toMatchSnapshot();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("renders disabled state", () => {
|
|
41
|
+
const {toJSON} = renderWithTheme(
|
|
42
|
+
<UnifiedAddressAutoCompleteField {...defaultProps} disabled />
|
|
43
|
+
);
|
|
44
|
+
expect(toJSON()).toMatchSnapshot();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("renders with invalid Google API key (falls back to TextField)", () => {
|
|
48
|
+
const {toJSON} = renderWithTheme(
|
|
49
|
+
<UnifiedAddressAutoCompleteField {...defaultProps} googleMapsApiKey="invalid" />
|
|
50
|
+
);
|
|
51
|
+
expect(toJSON()).toMatchSnapshot();
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import {describe, expect, it, mock} from "bun:test";
|
|
2
|
+
import {act} from "@testing-library/react-native";
|
|
3
|
+
|
|
4
|
+
import {Text} from "./Text";
|
|
5
|
+
import {renderWithTheme} from "./test-utils";
|
|
6
|
+
import {UserInactivity} from "./UserInactivity";
|
|
7
|
+
|
|
8
|
+
describe("UserInactivity", () => {
|
|
9
|
+
it("renders children correctly", () => {
|
|
10
|
+
const onAction = mock((_active: boolean) => {});
|
|
11
|
+
const {getByText} = renderWithTheme(
|
|
12
|
+
<UserInactivity onAction={onAction}>
|
|
13
|
+
<Text>Test Content</Text>
|
|
14
|
+
</UserInactivity>
|
|
15
|
+
);
|
|
16
|
+
expect(getByText("Test Content")).toBeTruthy();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("renders with custom style", () => {
|
|
20
|
+
const onAction = mock((_active: boolean) => {});
|
|
21
|
+
const {toJSON} = renderWithTheme(
|
|
22
|
+
<UserInactivity onAction={onAction} style={{backgroundColor: "red", flex: 2}}>
|
|
23
|
+
<Text>Test Content</Text>
|
|
24
|
+
</UserInactivity>
|
|
25
|
+
);
|
|
26
|
+
expect(toJSON()).toMatchSnapshot();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("renders with default style when no style provided", () => {
|
|
30
|
+
const onAction = mock((_active: boolean) => {});
|
|
31
|
+
const {toJSON} = renderWithTheme(
|
|
32
|
+
<UserInactivity onAction={onAction}>
|
|
33
|
+
<Text>Test Content</Text>
|
|
34
|
+
</UserInactivity>
|
|
35
|
+
);
|
|
36
|
+
expect(toJSON()).toMatchSnapshot();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("calls onAction with false after timeout", async () => {
|
|
40
|
+
const onAction = mock((_active: boolean) => {});
|
|
41
|
+
|
|
42
|
+
renderWithTheme(
|
|
43
|
+
<UserInactivity onAction={onAction} timeForInactivity={50}>
|
|
44
|
+
<Text>Test Content</Text>
|
|
45
|
+
</UserInactivity>
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
await act(async () => {
|
|
49
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
expect(onAction).toHaveBeenCalledWith(false);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("accepts timeForInactivity prop", () => {
|
|
56
|
+
const onAction = mock((_active: boolean) => {});
|
|
57
|
+
const {toJSON} = renderWithTheme(
|
|
58
|
+
<UserInactivity onAction={onAction} timeForInactivity={5000}>
|
|
59
|
+
<Text>Test Content</Text>
|
|
60
|
+
</UserInactivity>
|
|
61
|
+
);
|
|
62
|
+
expect(toJSON()).toBeTruthy();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("accepts isActive prop", () => {
|
|
66
|
+
const onAction = mock((_active: boolean) => {});
|
|
67
|
+
const {toJSON} = renderWithTheme(
|
|
68
|
+
<UserInactivity isActive={true} onAction={onAction}>
|
|
69
|
+
<Text>Test Content</Text>
|
|
70
|
+
</UserInactivity>
|
|
71
|
+
);
|
|
72
|
+
expect(toJSON()).toBeTruthy();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("renders multiple children", () => {
|
|
76
|
+
const onAction = mock((_active: boolean) => {});
|
|
77
|
+
const {getByText} = renderWithTheme(
|
|
78
|
+
<UserInactivity onAction={onAction}>
|
|
79
|
+
<Text>First Child</Text>
|
|
80
|
+
<Text>Second Child</Text>
|
|
81
|
+
</UserInactivity>
|
|
82
|
+
);
|
|
83
|
+
expect(getByText("First Child")).toBeTruthy();
|
|
84
|
+
expect(getByText("Second Child")).toBeTruthy();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("accepts skipKeyboard prop", () => {
|
|
88
|
+
const onAction = mock((_active: boolean) => {});
|
|
89
|
+
const {toJSON} = renderWithTheme(
|
|
90
|
+
<UserInactivity onAction={onAction} skipKeyboard={true}>
|
|
91
|
+
<Text>Test Content</Text>
|
|
92
|
+
</UserInactivity>
|
|
93
|
+
);
|
|
94
|
+
expect(toJSON()).toBeTruthy();
|
|
95
|
+
});
|
|
96
|
+
});
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MIT License
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2017-2021 Alberto Schiabel
|
|
5
|
+
*
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
* in the Software without restriction, including without limitation the rights
|
|
9
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
* furnished to do so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
*
|
|
24
|
+
* Vendored from https://github.com/jkomyno/react-native-user-inactivity
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import {type FC, useCallback, useEffect, useRef, useState} from "react";
|
|
28
|
+
import {Keyboard, PanResponder, View, type ViewStyle} from "react-native";
|
|
29
|
+
|
|
30
|
+
import type {UserInactivityProps} from "./Common";
|
|
31
|
+
|
|
32
|
+
const DEFAULT_TIME_FOR_INACTIVITY = 10000;
|
|
33
|
+
const DEFAULT_STYLE: ViewStyle = {
|
|
34
|
+
flex: 1,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const UserInactivity: FC<UserInactivityProps> = ({
|
|
38
|
+
children,
|
|
39
|
+
isActive: isActiveProp,
|
|
40
|
+
onAction,
|
|
41
|
+
skipKeyboard = false,
|
|
42
|
+
style,
|
|
43
|
+
timeForInactivity = DEFAULT_TIME_FOR_INACTIVITY,
|
|
44
|
+
}) => {
|
|
45
|
+
const actualStyle = style ?? DEFAULT_STYLE;
|
|
46
|
+
|
|
47
|
+
const initialActive = isActiveProp === undefined ? true : isActiveProp;
|
|
48
|
+
const [active, setActive] = useState(initialActive);
|
|
49
|
+
const [resetKey, setResetKey] = useState(0);
|
|
50
|
+
|
|
51
|
+
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
52
|
+
const isFirstRender = useRef(true);
|
|
53
|
+
|
|
54
|
+
const clearTimer = useCallback(() => {
|
|
55
|
+
if (timeoutRef.current !== null) {
|
|
56
|
+
clearTimeout(timeoutRef.current);
|
|
57
|
+
timeoutRef.current = null;
|
|
58
|
+
}
|
|
59
|
+
}, []);
|
|
60
|
+
|
|
61
|
+
const resetTimerDueToActivity = useCallback(() => {
|
|
62
|
+
clearTimer();
|
|
63
|
+
setActive(true);
|
|
64
|
+
setResetKey((prev) => prev + 1);
|
|
65
|
+
}, [clearTimer]);
|
|
66
|
+
|
|
67
|
+
// Handle isActive prop changes
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
if (isActiveProp) {
|
|
70
|
+
resetTimerDueToActivity();
|
|
71
|
+
}
|
|
72
|
+
}, [isActiveProp, resetTimerDueToActivity]);
|
|
73
|
+
|
|
74
|
+
// Setup the inactivity timeout
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
timeoutRef.current = setTimeout(() => {
|
|
77
|
+
setActive(false);
|
|
78
|
+
onAction(false);
|
|
79
|
+
}, timeForInactivity);
|
|
80
|
+
|
|
81
|
+
return clearTimer;
|
|
82
|
+
}, [resetKey, timeForInactivity, onAction, clearTimer]);
|
|
83
|
+
|
|
84
|
+
// Trigger onAction when active state changes (except on first render)
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
if (isFirstRender.current) {
|
|
87
|
+
isFirstRender.current = false;
|
|
88
|
+
} else {
|
|
89
|
+
if (active) {
|
|
90
|
+
onAction(true);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}, [active, onAction]);
|
|
94
|
+
|
|
95
|
+
// Setup keyboard listeners
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
if (skipKeyboard) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const hideEvent = Keyboard.addListener("keyboardDidHide", resetTimerDueToActivity);
|
|
102
|
+
const showEvent = Keyboard.addListener("keyboardDidShow", resetTimerDueToActivity);
|
|
103
|
+
|
|
104
|
+
return () => {
|
|
105
|
+
hideEvent.remove();
|
|
106
|
+
showEvent.remove();
|
|
107
|
+
};
|
|
108
|
+
}, [skipKeyboard, resetTimerDueToActivity]);
|
|
109
|
+
|
|
110
|
+
const resetTimerForPanResponder = useCallback(() => {
|
|
111
|
+
resetTimerDueToActivity();
|
|
112
|
+
return false;
|
|
113
|
+
}, [resetTimerDueToActivity]);
|
|
114
|
+
|
|
115
|
+
// Initialize PanResponder once
|
|
116
|
+
const [panResponder] = useState(() =>
|
|
117
|
+
PanResponder.create({
|
|
118
|
+
onMoveShouldSetPanResponderCapture: resetTimerForPanResponder,
|
|
119
|
+
onPanResponderTerminationRequest: resetTimerForPanResponder,
|
|
120
|
+
onStartShouldSetPanResponderCapture: resetTimerForPanResponder,
|
|
121
|
+
})
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<View collapsable={false} style={actualStyle} {...panResponder.panHandlers}>
|
|
126
|
+
{children}
|
|
127
|
+
</View>
|
|
128
|
+
);
|
|
129
|
+
};
|