@terreno/ui 0.14.0 → 0.14.1
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/ActionSheet.d.ts +1 -1
- package/dist/ActionSheet.js +2 -2
- package/dist/ActionSheet.js.map +1 -1
- package/dist/Common.d.ts +8 -2
- package/dist/Common.js +4 -4
- package/dist/Common.js.map +1 -1
- package/dist/ConsentFormScreen.js +3 -3
- package/dist/ConsentFormScreen.js.map +1 -1
- package/dist/DateUtilities.d.ts +25 -25
- package/dist/DateUtilities.js +31 -32
- package/dist/DateUtilities.js.map +1 -1
- package/dist/MediaQuery.d.ts +4 -4
- package/dist/MediaQuery.js +8 -8
- package/dist/MediaQuery.js.map +1 -1
- package/dist/Page.d.ts +1 -0
- package/dist/Page.js +6 -2
- package/dist/Page.js.map +1 -1
- package/dist/PickerSelect.d.ts +1 -1
- package/dist/PickerSelect.js +2 -2
- package/dist/PickerSelect.js.map +1 -1
- package/dist/TapToEdit.d.ts +1 -1
- package/dist/TapToEdit.js +2 -3
- package/dist/TapToEdit.js.map +1 -1
- package/dist/ToastNotifications.js +2 -2
- package/dist/ToastNotifications.js.map +1 -1
- package/dist/Tooltip.d.ts +24 -1
- package/dist/Tooltip.js +2 -2
- package/dist/Tooltip.js.map +1 -1
- package/dist/Unifier.d.ts +1 -1
- package/dist/Unifier.js +14 -11
- package/dist/Unifier.js.map +1 -1
- package/dist/Utilities.d.ts +8 -8
- package/dist/Utilities.js +12 -14
- package/dist/Utilities.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/signUp/PasswordRequirements.js +3 -3
- package/dist/signUp/PasswordRequirements.js.map +1 -1
- package/dist/table/TableHeaderCell.js +1 -9
- package/dist/table/TableHeaderCell.js.map +1 -1
- package/dist/table/tableContext.d.ts +1 -1
- package/dist/table/tableContext.js +2 -2
- package/dist/table/tableContext.js.map +1 -1
- package/package.json +1 -1
- package/src/ActionSheet.tsx +2 -2
- package/src/Banner.test.tsx +71 -0
- package/src/Common.ts +10 -4
- package/src/ConsentFormScreen.test.tsx +22 -0
- package/src/ConsentFormScreen.tsx +9 -3
- package/src/DataTable.test.tsx +217 -0
- package/src/DateUtilities.tsx +37 -38
- package/src/HeightActionSheet.test.tsx +16 -0
- package/src/HeightField.test.tsx +106 -1
- package/src/MediaQuery.ts +8 -8
- package/src/MobileAddressAutoComplete.test.tsx +20 -1
- package/src/Page.test.tsx +28 -0
- package/src/Page.tsx +17 -2
- package/src/PickerSelect.tsx +3 -3
- package/src/TapToEdit.test.tsx +31 -0
- package/src/TapToEdit.tsx +2 -3
- package/src/ToastNotifications.test.tsx +738 -0
- package/src/ToastNotifications.tsx +2 -2
- package/src/Tooltip.test.tsx +587 -2
- package/src/Tooltip.tsx +2 -2
- package/src/Unifier.ts +14 -11
- package/src/Utilities.tsx +14 -16
- package/src/WebAddressAutocomplete.test.tsx +138 -0
- package/src/WebDropdownMenu.test.tsx +23 -0
- package/src/index.tsx +1 -1
- package/src/login/LoginScreen.test.tsx +23 -1
- package/src/signUp/PasswordRequirements.tsx +9 -6
- package/src/signUp/__snapshots__/PasswordRequirements.test.tsx.snap +50 -2
- package/src/signUp/__snapshots__/SignUpScreen.test.tsx.snap +25 -1
- package/src/table/TableHeaderCell.tsx +8 -11
- package/src/table/TableRow.test.tsx +31 -1
- package/src/table/__snapshots__/TableHeaderCell.test.tsx.snap +2 -0
- package/src/table/tableContext.tsx +2 -2
- package/src/useStoredState.test.tsx +47 -0
|
@@ -848,4 +848,742 @@ describe("ToastNotifications", () => {
|
|
|
848
848
|
expect(toastType).toBeDefined();
|
|
849
849
|
});
|
|
850
850
|
});
|
|
851
|
+
|
|
852
|
+
describe("Toast with renderToast custom renderer", () => {
|
|
853
|
+
it("should use renderToast when provided", async () => {
|
|
854
|
+
let toastRef: ToastType | null = null;
|
|
855
|
+
|
|
856
|
+
const TestComponent = () => {
|
|
857
|
+
const toast = useToastNotifications();
|
|
858
|
+
toastRef = toast;
|
|
859
|
+
return <Text>Test</Text>;
|
|
860
|
+
};
|
|
861
|
+
|
|
862
|
+
const customRender = (toast: ToastProps) => <Text>Custom: {String(toast.message)}</Text>;
|
|
863
|
+
|
|
864
|
+
render(
|
|
865
|
+
<ToastProvider renderToast={customRender} swipeEnabled={false}>
|
|
866
|
+
<TestComponent />
|
|
867
|
+
</ToastProvider>
|
|
868
|
+
);
|
|
869
|
+
|
|
870
|
+
await waitFor(() => {
|
|
871
|
+
expect(toastRef?.show).toBeDefined();
|
|
872
|
+
});
|
|
873
|
+
|
|
874
|
+
await act(async () => {
|
|
875
|
+
toastRef?.show("Rendered custom");
|
|
876
|
+
});
|
|
877
|
+
|
|
878
|
+
expect(toastRef).toBeTruthy();
|
|
879
|
+
});
|
|
880
|
+
});
|
|
881
|
+
|
|
882
|
+
describe("Toast with renderType map", () => {
|
|
883
|
+
it("should use renderType for matching toast type", async () => {
|
|
884
|
+
let toastRef: ToastType | null = null;
|
|
885
|
+
|
|
886
|
+
const TestComponent = () => {
|
|
887
|
+
const toast = useToastNotifications();
|
|
888
|
+
toastRef = toast;
|
|
889
|
+
return <Text>Test</Text>;
|
|
890
|
+
};
|
|
891
|
+
|
|
892
|
+
const renderType = {
|
|
893
|
+
custom: (toast: ToastProps) => <Text>Type: {String(toast.message)}</Text>,
|
|
894
|
+
};
|
|
895
|
+
|
|
896
|
+
render(
|
|
897
|
+
<ToastProvider renderType={renderType} swipeEnabled={false}>
|
|
898
|
+
<TestComponent />
|
|
899
|
+
</ToastProvider>
|
|
900
|
+
);
|
|
901
|
+
|
|
902
|
+
await waitFor(() => {
|
|
903
|
+
expect(toastRef?.show).toBeDefined();
|
|
904
|
+
});
|
|
905
|
+
|
|
906
|
+
await act(async () => {
|
|
907
|
+
toastRef?.show("Custom type toast", {type: "custom"});
|
|
908
|
+
});
|
|
909
|
+
|
|
910
|
+
expect(toastRef).toBeTruthy();
|
|
911
|
+
});
|
|
912
|
+
});
|
|
913
|
+
|
|
914
|
+
describe("Toast onPress handler", () => {
|
|
915
|
+
it("should accept onPress callback on toast", async () => {
|
|
916
|
+
let toastRef: ToastType | null = null;
|
|
917
|
+
const onPressMock = mock((_id: string) => {});
|
|
918
|
+
|
|
919
|
+
const TestComponent = () => {
|
|
920
|
+
const toast = useToastNotifications();
|
|
921
|
+
toastRef = toast;
|
|
922
|
+
return <Text>Test</Text>;
|
|
923
|
+
};
|
|
924
|
+
|
|
925
|
+
render(
|
|
926
|
+
<ToastProvider swipeEnabled={false}>
|
|
927
|
+
<TestComponent />
|
|
928
|
+
</ToastProvider>
|
|
929
|
+
);
|
|
930
|
+
|
|
931
|
+
await waitFor(() => {
|
|
932
|
+
expect(toastRef?.show).toBeDefined();
|
|
933
|
+
});
|
|
934
|
+
|
|
935
|
+
let toastId: string | undefined;
|
|
936
|
+
await act(async () => {
|
|
937
|
+
toastId = toastRef?.show("Pressable toast", {id: "press-test", onPress: onPressMock});
|
|
938
|
+
});
|
|
939
|
+
|
|
940
|
+
expect(toastId).toBe("press-test");
|
|
941
|
+
});
|
|
942
|
+
});
|
|
943
|
+
|
|
944
|
+
describe("Toast with swipe enabled", () => {
|
|
945
|
+
it("should render toast with swipe enabled (pan responder)", async () => {
|
|
946
|
+
let toastRef: ToastType | null = null;
|
|
947
|
+
|
|
948
|
+
const TestComponent = () => {
|
|
949
|
+
const toast = useToastNotifications();
|
|
950
|
+
toastRef = toast;
|
|
951
|
+
return <Text>Test</Text>;
|
|
952
|
+
};
|
|
953
|
+
|
|
954
|
+
render(
|
|
955
|
+
<ToastProvider swipeEnabled>
|
|
956
|
+
<TestComponent />
|
|
957
|
+
</ToastProvider>
|
|
958
|
+
);
|
|
959
|
+
|
|
960
|
+
await waitFor(() => {
|
|
961
|
+
expect(toastRef?.show).toBeDefined();
|
|
962
|
+
});
|
|
963
|
+
|
|
964
|
+
let toastId: string | undefined;
|
|
965
|
+
await act(async () => {
|
|
966
|
+
toastId = toastRef?.show("Swipeable toast", {id: "swipe-toast", swipeEnabled: true});
|
|
967
|
+
});
|
|
968
|
+
|
|
969
|
+
expect(toastId).toBe("swipe-toast");
|
|
970
|
+
});
|
|
971
|
+
});
|
|
972
|
+
|
|
973
|
+
describe("Toast with zoom-in animation", () => {
|
|
974
|
+
it("should render toast with zoom-in animation type", async () => {
|
|
975
|
+
let toastRef: ToastType | null = null;
|
|
976
|
+
|
|
977
|
+
const TestComponent = () => {
|
|
978
|
+
const toast = useToastNotifications();
|
|
979
|
+
toastRef = toast;
|
|
980
|
+
return <Text>Test</Text>;
|
|
981
|
+
};
|
|
982
|
+
|
|
983
|
+
render(
|
|
984
|
+
<ToastProvider animationType="zoom-in" swipeEnabled={false}>
|
|
985
|
+
<TestComponent />
|
|
986
|
+
</ToastProvider>
|
|
987
|
+
);
|
|
988
|
+
|
|
989
|
+
await waitFor(() => {
|
|
990
|
+
expect(toastRef?.show).toBeDefined();
|
|
991
|
+
});
|
|
992
|
+
|
|
993
|
+
await act(async () => {
|
|
994
|
+
toastRef?.show("Zoom toast", {animationType: "zoom-in"});
|
|
995
|
+
});
|
|
996
|
+
|
|
997
|
+
expect(toastRef).toBeTruthy();
|
|
998
|
+
});
|
|
999
|
+
});
|
|
1000
|
+
|
|
1001
|
+
describe("Toast custom colors", () => {
|
|
1002
|
+
it("should render toasts with custom colors", async () => {
|
|
1003
|
+
let toastRef: ToastType | null = null;
|
|
1004
|
+
|
|
1005
|
+
const TestComponent = () => {
|
|
1006
|
+
const toast = useToastNotifications();
|
|
1007
|
+
toastRef = toast;
|
|
1008
|
+
return <Text>Test</Text>;
|
|
1009
|
+
};
|
|
1010
|
+
|
|
1011
|
+
render(
|
|
1012
|
+
<ToastProvider
|
|
1013
|
+
dangerColor="#ff0000"
|
|
1014
|
+
normalColor="#444"
|
|
1015
|
+
successColor="#00ff00"
|
|
1016
|
+
swipeEnabled={false}
|
|
1017
|
+
warningColor="#ffff00"
|
|
1018
|
+
>
|
|
1019
|
+
<TestComponent />
|
|
1020
|
+
</ToastProvider>
|
|
1021
|
+
);
|
|
1022
|
+
|
|
1023
|
+
await waitFor(() => {
|
|
1024
|
+
expect(toastRef?.show).toBeDefined();
|
|
1025
|
+
});
|
|
1026
|
+
|
|
1027
|
+
await act(async () => {
|
|
1028
|
+
toastRef?.show("Success", {type: "success"});
|
|
1029
|
+
});
|
|
1030
|
+
await act(async () => {
|
|
1031
|
+
toastRef?.show("Danger", {type: "danger"});
|
|
1032
|
+
});
|
|
1033
|
+
await act(async () => {
|
|
1034
|
+
toastRef?.show("Warning", {type: "warning"});
|
|
1035
|
+
});
|
|
1036
|
+
await act(async () => {
|
|
1037
|
+
toastRef?.show("Normal", {type: "normal"});
|
|
1038
|
+
});
|
|
1039
|
+
|
|
1040
|
+
expect(toastRef).toBeTruthy();
|
|
1041
|
+
});
|
|
1042
|
+
});
|
|
1043
|
+
|
|
1044
|
+
describe("Toast with offsets", () => {
|
|
1045
|
+
it("should render with custom offsetTop and offsetBottom", async () => {
|
|
1046
|
+
let toastRef: ToastType | null = null;
|
|
1047
|
+
|
|
1048
|
+
const TestComponent = () => {
|
|
1049
|
+
const toast = useToastNotifications();
|
|
1050
|
+
toastRef = toast;
|
|
1051
|
+
return <Text>Test</Text>;
|
|
1052
|
+
};
|
|
1053
|
+
|
|
1054
|
+
render(
|
|
1055
|
+
<ToastProvider offsetBottom={30} offsetTop={50} swipeEnabled={false}>
|
|
1056
|
+
<TestComponent />
|
|
1057
|
+
</ToastProvider>
|
|
1058
|
+
);
|
|
1059
|
+
|
|
1060
|
+
await waitFor(() => {
|
|
1061
|
+
expect(toastRef?.show).toBeDefined();
|
|
1062
|
+
});
|
|
1063
|
+
|
|
1064
|
+
await act(async () => {
|
|
1065
|
+
toastRef?.show("Top toast", {placement: "top"});
|
|
1066
|
+
});
|
|
1067
|
+
await act(async () => {
|
|
1068
|
+
toastRef?.show("Bottom toast", {placement: "bottom"});
|
|
1069
|
+
});
|
|
1070
|
+
|
|
1071
|
+
expect(toastRef).toBeTruthy();
|
|
1072
|
+
});
|
|
1073
|
+
});
|
|
1074
|
+
|
|
1075
|
+
describe("Toast icon override", () => {
|
|
1076
|
+
it("should use explicit icon over type-specific icon", async () => {
|
|
1077
|
+
let toastRef: ToastType | null = null;
|
|
1078
|
+
|
|
1079
|
+
const TestComponent = () => {
|
|
1080
|
+
const toast = useToastNotifications();
|
|
1081
|
+
toastRef = toast;
|
|
1082
|
+
return <Text>Test</Text>;
|
|
1083
|
+
};
|
|
1084
|
+
|
|
1085
|
+
render(
|
|
1086
|
+
<ToastProvider successIcon={<Text>S</Text>} swipeEnabled={false}>
|
|
1087
|
+
<TestComponent />
|
|
1088
|
+
</ToastProvider>
|
|
1089
|
+
);
|
|
1090
|
+
|
|
1091
|
+
await waitFor(() => {
|
|
1092
|
+
expect(toastRef?.show).toBeDefined();
|
|
1093
|
+
});
|
|
1094
|
+
|
|
1095
|
+
await act(async () => {
|
|
1096
|
+
toastRef?.show("With explicit icon", {
|
|
1097
|
+
icon: <Text>Explicit</Text>,
|
|
1098
|
+
type: "success",
|
|
1099
|
+
});
|
|
1100
|
+
});
|
|
1101
|
+
|
|
1102
|
+
expect(toastRef).toBeTruthy();
|
|
1103
|
+
});
|
|
1104
|
+
});
|
|
1105
|
+
|
|
1106
|
+
describe("Toast auto-close and handleClose", () => {
|
|
1107
|
+
let Platform: {OS: string};
|
|
1108
|
+
beforeAll(async () => {
|
|
1109
|
+
const rn = await import("react-native");
|
|
1110
|
+
Platform = rn.Platform;
|
|
1111
|
+
});
|
|
1112
|
+
|
|
1113
|
+
it("should auto-close toast after short duration and call onClose", async () => {
|
|
1114
|
+
const origOS = Platform.OS;
|
|
1115
|
+
Platform.OS = "web";
|
|
1116
|
+
let toastRef: ToastType | null = null;
|
|
1117
|
+
const onCloseMock = mock(() => {});
|
|
1118
|
+
|
|
1119
|
+
const TestComponent = () => {
|
|
1120
|
+
const toast = useToastNotifications();
|
|
1121
|
+
toastRef = toast;
|
|
1122
|
+
return <Text>Test</Text>;
|
|
1123
|
+
};
|
|
1124
|
+
|
|
1125
|
+
const {unmount} = render(
|
|
1126
|
+
<ToastProvider swipeEnabled={false}>
|
|
1127
|
+
<TestComponent />
|
|
1128
|
+
</ToastProvider>
|
|
1129
|
+
);
|
|
1130
|
+
|
|
1131
|
+
await waitFor(() => {
|
|
1132
|
+
expect(toastRef?.show).toBeDefined();
|
|
1133
|
+
});
|
|
1134
|
+
|
|
1135
|
+
await act(async () => {
|
|
1136
|
+
toastRef?.show("Short lived", {
|
|
1137
|
+
animationDuration: 1,
|
|
1138
|
+
duration: 10,
|
|
1139
|
+
id: "auto-close",
|
|
1140
|
+
onClose: onCloseMock,
|
|
1141
|
+
});
|
|
1142
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1143
|
+
});
|
|
1144
|
+
|
|
1145
|
+
// Let the duration timer fire and animations complete
|
|
1146
|
+
for (let i = 0; i < 10; i++) {
|
|
1147
|
+
await act(async () => {
|
|
1148
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1149
|
+
});
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
unmount();
|
|
1153
|
+
Platform.OS = origOS;
|
|
1154
|
+
expect(toastRef).toBeTruthy();
|
|
1155
|
+
});
|
|
1156
|
+
|
|
1157
|
+
it("should hide toast when hide() is called (exercises open effect)", async () => {
|
|
1158
|
+
const origOS = Platform.OS;
|
|
1159
|
+
Platform.OS = "web";
|
|
1160
|
+
let toastRef: ToastType | null = null;
|
|
1161
|
+
|
|
1162
|
+
const TestComponent = () => {
|
|
1163
|
+
const toast = useToastNotifications();
|
|
1164
|
+
toastRef = toast;
|
|
1165
|
+
return <Text>Test</Text>;
|
|
1166
|
+
};
|
|
1167
|
+
|
|
1168
|
+
const {unmount} = render(
|
|
1169
|
+
<ToastProvider swipeEnabled={false}>
|
|
1170
|
+
<TestComponent />
|
|
1171
|
+
</ToastProvider>
|
|
1172
|
+
);
|
|
1173
|
+
|
|
1174
|
+
await waitFor(() => {
|
|
1175
|
+
expect(toastRef?.show).toBeDefined();
|
|
1176
|
+
});
|
|
1177
|
+
|
|
1178
|
+
await act(async () => {
|
|
1179
|
+
toastRef?.show("Will be hidden", {
|
|
1180
|
+
animationDuration: 1,
|
|
1181
|
+
duration: 0,
|
|
1182
|
+
id: "hide-test",
|
|
1183
|
+
});
|
|
1184
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1185
|
+
});
|
|
1186
|
+
|
|
1187
|
+
await act(async () => {
|
|
1188
|
+
toastRef?.hide("hide-test");
|
|
1189
|
+
});
|
|
1190
|
+
|
|
1191
|
+
for (let i = 0; i < 5; i++) {
|
|
1192
|
+
await act(async () => {
|
|
1193
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1194
|
+
});
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
unmount();
|
|
1198
|
+
Platform.OS = origOS;
|
|
1199
|
+
});
|
|
1200
|
+
});
|
|
1201
|
+
|
|
1202
|
+
describe("Toast with swipe and pan responder interaction", () => {
|
|
1203
|
+
// biome-ignore lint/suspicious/noExplicitAny: capturing PanResponder internals for test
|
|
1204
|
+
type PanConfig = any;
|
|
1205
|
+
let capturedPanConfigs: PanConfig[] = [];
|
|
1206
|
+
|
|
1207
|
+
it("should exercise pan responder callbacks via mocked PanResponder.create", async () => {
|
|
1208
|
+
const {PanResponder: PR} = require("react-native");
|
|
1209
|
+
const origCreate = PR.create.bind(PR);
|
|
1210
|
+
capturedPanConfigs = [];
|
|
1211
|
+
|
|
1212
|
+
PR.create = (config: PanConfig) => {
|
|
1213
|
+
capturedPanConfigs.push(config);
|
|
1214
|
+
return origCreate(config);
|
|
1215
|
+
};
|
|
1216
|
+
|
|
1217
|
+
let toastRef: ToastType | null = null;
|
|
1218
|
+
|
|
1219
|
+
const TestComponent = () => {
|
|
1220
|
+
const toast = useToastNotifications();
|
|
1221
|
+
toastRef = toast;
|
|
1222
|
+
return <Text>Test</Text>;
|
|
1223
|
+
};
|
|
1224
|
+
|
|
1225
|
+
const {unmount} = render(
|
|
1226
|
+
<ToastProvider swipeEnabled>
|
|
1227
|
+
<TestComponent />
|
|
1228
|
+
</ToastProvider>
|
|
1229
|
+
);
|
|
1230
|
+
|
|
1231
|
+
await waitFor(() => {
|
|
1232
|
+
expect(toastRef?.show).toBeDefined();
|
|
1233
|
+
});
|
|
1234
|
+
|
|
1235
|
+
await act(async () => {
|
|
1236
|
+
toastRef?.show("Swipe test", {
|
|
1237
|
+
animationDuration: 10,
|
|
1238
|
+
duration: 0,
|
|
1239
|
+
id: "swipe-capture",
|
|
1240
|
+
swipeEnabled: true,
|
|
1241
|
+
});
|
|
1242
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1243
|
+
});
|
|
1244
|
+
|
|
1245
|
+
// Now exercise the captured PanResponder callbacks directly
|
|
1246
|
+
const mockEvent = {} as React.SyntheticEvent;
|
|
1247
|
+
for (const config of capturedPanConfigs) {
|
|
1248
|
+
// onMoveShouldSetPanResponder
|
|
1249
|
+
if (config.onMoveShouldSetPanResponder) {
|
|
1250
|
+
config.onMoveShouldSetPanResponder(mockEvent, {dx: 20, dy: 0});
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
// onPanResponderMove
|
|
1254
|
+
if (config.onPanResponderMove) {
|
|
1255
|
+
await act(async () => {
|
|
1256
|
+
config.onPanResponderMove(mockEvent, {dx: 60, dy: 0});
|
|
1257
|
+
});
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
// onPanResponderRelease with dx > 50 (right swipe)
|
|
1261
|
+
if (config.onPanResponderRelease) {
|
|
1262
|
+
await act(async () => {
|
|
1263
|
+
config.onPanResponderRelease(mockEvent, {dx: 100, dy: 0});
|
|
1264
|
+
});
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
await act(async () => {
|
|
1269
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
1270
|
+
});
|
|
1271
|
+
|
|
1272
|
+
PR.create = origCreate;
|
|
1273
|
+
unmount();
|
|
1274
|
+
});
|
|
1275
|
+
|
|
1276
|
+
it("should exercise pan responder left swipe", async () => {
|
|
1277
|
+
const {PanResponder: PR} = require("react-native");
|
|
1278
|
+
const origCreate = PR.create.bind(PR);
|
|
1279
|
+
capturedPanConfigs = [];
|
|
1280
|
+
|
|
1281
|
+
PR.create = (config: PanConfig) => {
|
|
1282
|
+
capturedPanConfigs.push(config);
|
|
1283
|
+
return origCreate(config);
|
|
1284
|
+
};
|
|
1285
|
+
|
|
1286
|
+
let toastRef: ToastType | null = null;
|
|
1287
|
+
|
|
1288
|
+
const TestComponent = () => {
|
|
1289
|
+
const toast = useToastNotifications();
|
|
1290
|
+
toastRef = toast;
|
|
1291
|
+
return <Text>Test</Text>;
|
|
1292
|
+
};
|
|
1293
|
+
|
|
1294
|
+
const {unmount} = render(
|
|
1295
|
+
<ToastProvider swipeEnabled>
|
|
1296
|
+
<TestComponent />
|
|
1297
|
+
</ToastProvider>
|
|
1298
|
+
);
|
|
1299
|
+
|
|
1300
|
+
await waitFor(() => {
|
|
1301
|
+
expect(toastRef?.show).toBeDefined();
|
|
1302
|
+
});
|
|
1303
|
+
|
|
1304
|
+
await act(async () => {
|
|
1305
|
+
toastRef?.show("Left swipe", {
|
|
1306
|
+
animationDuration: 10,
|
|
1307
|
+
duration: 0,
|
|
1308
|
+
id: "swipe-left",
|
|
1309
|
+
swipeEnabled: true,
|
|
1310
|
+
});
|
|
1311
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1312
|
+
});
|
|
1313
|
+
|
|
1314
|
+
const mockEvent = {} as React.SyntheticEvent;
|
|
1315
|
+
for (const config of capturedPanConfigs) {
|
|
1316
|
+
// onPanResponderRelease with dx < -50 (left swipe)
|
|
1317
|
+
if (config.onPanResponderRelease) {
|
|
1318
|
+
await act(async () => {
|
|
1319
|
+
config.onPanResponderRelease(mockEvent, {dx: -100, dy: 0});
|
|
1320
|
+
});
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
await act(async () => {
|
|
1325
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
1326
|
+
});
|
|
1327
|
+
|
|
1328
|
+
PR.create = origCreate;
|
|
1329
|
+
unmount();
|
|
1330
|
+
});
|
|
1331
|
+
|
|
1332
|
+
it("should exercise pan responder snap back on small swipe", async () => {
|
|
1333
|
+
const {PanResponder: PR} = require("react-native");
|
|
1334
|
+
const origCreate = PR.create.bind(PR);
|
|
1335
|
+
capturedPanConfigs = [];
|
|
1336
|
+
|
|
1337
|
+
PR.create = (config: PanConfig) => {
|
|
1338
|
+
capturedPanConfigs.push(config);
|
|
1339
|
+
return origCreate(config);
|
|
1340
|
+
};
|
|
1341
|
+
|
|
1342
|
+
let toastRef: ToastType | null = null;
|
|
1343
|
+
|
|
1344
|
+
const TestComponent = () => {
|
|
1345
|
+
const toast = useToastNotifications();
|
|
1346
|
+
toastRef = toast;
|
|
1347
|
+
return <Text>Test</Text>;
|
|
1348
|
+
};
|
|
1349
|
+
|
|
1350
|
+
const {unmount} = render(
|
|
1351
|
+
<ToastProvider swipeEnabled>
|
|
1352
|
+
<TestComponent />
|
|
1353
|
+
</ToastProvider>
|
|
1354
|
+
);
|
|
1355
|
+
|
|
1356
|
+
await waitFor(() => {
|
|
1357
|
+
expect(toastRef?.show).toBeDefined();
|
|
1358
|
+
});
|
|
1359
|
+
|
|
1360
|
+
await act(async () => {
|
|
1361
|
+
toastRef?.show("Small swipe", {
|
|
1362
|
+
animationDuration: 10,
|
|
1363
|
+
duration: 0,
|
|
1364
|
+
id: "swipe-small",
|
|
1365
|
+
swipeEnabled: true,
|
|
1366
|
+
});
|
|
1367
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1368
|
+
});
|
|
1369
|
+
|
|
1370
|
+
const mockEvent = {} as React.SyntheticEvent;
|
|
1371
|
+
for (const config of capturedPanConfigs) {
|
|
1372
|
+
// onPanResponderRelease with |dx| < 50 (snap back)
|
|
1373
|
+
if (config.onPanResponderRelease) {
|
|
1374
|
+
await act(async () => {
|
|
1375
|
+
config.onPanResponderRelease(mockEvent, {dx: 10, dy: 5});
|
|
1376
|
+
});
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
await act(async () => {
|
|
1381
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1382
|
+
});
|
|
1383
|
+
|
|
1384
|
+
PR.create = origCreate;
|
|
1385
|
+
unmount();
|
|
1386
|
+
});
|
|
1387
|
+
});
|
|
1388
|
+
|
|
1389
|
+
describe("Toast zoom-in animation with swipe", () => {
|
|
1390
|
+
it("renders toast with both zoom-in and swipe enabled", async () => {
|
|
1391
|
+
let toastRef: ToastType | null = null;
|
|
1392
|
+
|
|
1393
|
+
const TestComponent = () => {
|
|
1394
|
+
const toast = useToastNotifications();
|
|
1395
|
+
toastRef = toast;
|
|
1396
|
+
return <Text>Test</Text>;
|
|
1397
|
+
};
|
|
1398
|
+
|
|
1399
|
+
render(
|
|
1400
|
+
<ToastProvider animationType="zoom-in" swipeEnabled>
|
|
1401
|
+
<TestComponent />
|
|
1402
|
+
</ToastProvider>
|
|
1403
|
+
);
|
|
1404
|
+
|
|
1405
|
+
await waitFor(() => {
|
|
1406
|
+
expect(toastRef?.show).toBeDefined();
|
|
1407
|
+
});
|
|
1408
|
+
|
|
1409
|
+
await act(async () => {
|
|
1410
|
+
toastRef?.show("Zoom and swipe", {
|
|
1411
|
+
animationType: "zoom-in",
|
|
1412
|
+
duration: 0,
|
|
1413
|
+
id: "zoom-swipe",
|
|
1414
|
+
swipeEnabled: true,
|
|
1415
|
+
});
|
|
1416
|
+
});
|
|
1417
|
+
|
|
1418
|
+
await act(async () => {
|
|
1419
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1420
|
+
});
|
|
1421
|
+
|
|
1422
|
+
expect(toastRef).toBeTruthy();
|
|
1423
|
+
});
|
|
1424
|
+
});
|
|
1425
|
+
|
|
1426
|
+
describe("Toast onPress interaction", () => {
|
|
1427
|
+
it("should trigger onPress when pressing the toast", async () => {
|
|
1428
|
+
let toastRef: ToastType | null = null;
|
|
1429
|
+
const onPressMock = mock((_id: string) => {});
|
|
1430
|
+
|
|
1431
|
+
const TestComponent = () => {
|
|
1432
|
+
const toast = useToastNotifications();
|
|
1433
|
+
toastRef = toast;
|
|
1434
|
+
return <Text>Test</Text>;
|
|
1435
|
+
};
|
|
1436
|
+
|
|
1437
|
+
const {getByText} = render(
|
|
1438
|
+
<ToastProvider swipeEnabled={false}>
|
|
1439
|
+
<TestComponent />
|
|
1440
|
+
</ToastProvider>
|
|
1441
|
+
);
|
|
1442
|
+
|
|
1443
|
+
await waitFor(() => {
|
|
1444
|
+
expect(toastRef?.show).toBeDefined();
|
|
1445
|
+
});
|
|
1446
|
+
|
|
1447
|
+
await act(async () => {
|
|
1448
|
+
toastRef?.show("Press me", {
|
|
1449
|
+
duration: 0,
|
|
1450
|
+
id: "press-interaction",
|
|
1451
|
+
onPress: onPressMock,
|
|
1452
|
+
});
|
|
1453
|
+
});
|
|
1454
|
+
|
|
1455
|
+
// Wait for toast to render
|
|
1456
|
+
await act(async () => {
|
|
1457
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1458
|
+
});
|
|
1459
|
+
|
|
1460
|
+
// Try to find and press the toast text
|
|
1461
|
+
try {
|
|
1462
|
+
const {fireEvent: fe} = require("@testing-library/react-native");
|
|
1463
|
+
const toastText = getByText("Press me");
|
|
1464
|
+
fe.press(toastText);
|
|
1465
|
+
} catch {
|
|
1466
|
+
// Toast may not be findable via getByText due to internal structure
|
|
1467
|
+
}
|
|
1468
|
+
});
|
|
1469
|
+
});
|
|
1470
|
+
|
|
1471
|
+
describe("Toast with persistent duration and hideAll", () => {
|
|
1472
|
+
it("should handle hideAll for persistent toasts", async () => {
|
|
1473
|
+
const {Platform: P} = await import("react-native");
|
|
1474
|
+
const origOS = P.OS;
|
|
1475
|
+
P.OS = "web";
|
|
1476
|
+
let toastRef: ToastType | null = null;
|
|
1477
|
+
|
|
1478
|
+
const TestComponent = () => {
|
|
1479
|
+
const toast = useToastNotifications();
|
|
1480
|
+
toastRef = toast;
|
|
1481
|
+
return <Text>Test</Text>;
|
|
1482
|
+
};
|
|
1483
|
+
|
|
1484
|
+
const {unmount} = render(
|
|
1485
|
+
<ToastProvider swipeEnabled={false}>
|
|
1486
|
+
<TestComponent />
|
|
1487
|
+
</ToastProvider>
|
|
1488
|
+
);
|
|
1489
|
+
|
|
1490
|
+
await waitFor(() => {
|
|
1491
|
+
expect(toastRef?.show).toBeDefined();
|
|
1492
|
+
});
|
|
1493
|
+
|
|
1494
|
+
await act(async () => {
|
|
1495
|
+
toastRef?.show("Persistent 1", {
|
|
1496
|
+
animationDuration: 1,
|
|
1497
|
+
duration: 0,
|
|
1498
|
+
id: "p1",
|
|
1499
|
+
});
|
|
1500
|
+
toastRef?.show("Persistent 2", {
|
|
1501
|
+
animationDuration: 1,
|
|
1502
|
+
duration: 0,
|
|
1503
|
+
id: "p2",
|
|
1504
|
+
});
|
|
1505
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1506
|
+
});
|
|
1507
|
+
|
|
1508
|
+
await act(async () => {
|
|
1509
|
+
toastRef?.hideAll();
|
|
1510
|
+
});
|
|
1511
|
+
|
|
1512
|
+
for (let i = 0; i < 5; i++) {
|
|
1513
|
+
await act(async () => {
|
|
1514
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1515
|
+
});
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
unmount();
|
|
1519
|
+
P.OS = origOS;
|
|
1520
|
+
});
|
|
1521
|
+
});
|
|
1522
|
+
|
|
1523
|
+
describe("useDimensions onChange", () => {
|
|
1524
|
+
it("exercises dimension change via Dimensions event", async () => {
|
|
1525
|
+
const rn = await import("react-native");
|
|
1526
|
+
const Dims = rn.Dimensions;
|
|
1527
|
+
let toastRef: ToastType | null = null;
|
|
1528
|
+
|
|
1529
|
+
const TestComponent = () => {
|
|
1530
|
+
const toast = useToastNotifications();
|
|
1531
|
+
toastRef = toast;
|
|
1532
|
+
return <Text>Test</Text>;
|
|
1533
|
+
};
|
|
1534
|
+
|
|
1535
|
+
const {unmount} = render(
|
|
1536
|
+
<ToastProvider swipeEnabled={false}>
|
|
1537
|
+
<TestComponent />
|
|
1538
|
+
</ToastProvider>
|
|
1539
|
+
);
|
|
1540
|
+
|
|
1541
|
+
await waitFor(() => {
|
|
1542
|
+
expect(toastRef?.show).toBeDefined();
|
|
1543
|
+
});
|
|
1544
|
+
|
|
1545
|
+
// Show a toast so ToastItem (which uses useDimensions) renders
|
|
1546
|
+
await act(async () => {
|
|
1547
|
+
toastRef?.show("Dimension test", {duration: 0, id: "dim-test"});
|
|
1548
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1549
|
+
});
|
|
1550
|
+
|
|
1551
|
+
// Capture the original addEventListener to spy on it
|
|
1552
|
+
// Instead, we'll spy on the subscription by monkey-patching Dimensions
|
|
1553
|
+
const listeners: Array<(data: {window: rn.ScaledSize}) => void> = [];
|
|
1554
|
+
const origAddEventListener = Dims.addEventListener.bind(Dims);
|
|
1555
|
+
const patchedAdd = (event: string, handler: (data: {window: rn.ScaledSize}) => void) => {
|
|
1556
|
+
if (event === "change") {
|
|
1557
|
+
listeners.push(handler);
|
|
1558
|
+
}
|
|
1559
|
+
return origAddEventListener(event, handler);
|
|
1560
|
+
};
|
|
1561
|
+
Dims.addEventListener = patchedAdd as typeof Dims.addEventListener;
|
|
1562
|
+
|
|
1563
|
+
// Re-render to pick up the patched addEventListener
|
|
1564
|
+
const {unmount: unmount2} = render(
|
|
1565
|
+
<ToastProvider swipeEnabled={false}>
|
|
1566
|
+
<TestComponent />
|
|
1567
|
+
</ToastProvider>
|
|
1568
|
+
);
|
|
1569
|
+
|
|
1570
|
+
await act(async () => {
|
|
1571
|
+
toastRef?.show("Dimension test 2", {duration: 0, id: "dim-test-2"});
|
|
1572
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1573
|
+
});
|
|
1574
|
+
|
|
1575
|
+
// Call all captured listeners
|
|
1576
|
+
await act(async () => {
|
|
1577
|
+
for (const listener of listeners) {
|
|
1578
|
+
listener({
|
|
1579
|
+
window: {fontScale: 1, height: 900, scale: 1, width: 500} as rn.ScaledSize,
|
|
1580
|
+
});
|
|
1581
|
+
}
|
|
1582
|
+
});
|
|
1583
|
+
|
|
1584
|
+
Dims.addEventListener = origAddEventListener;
|
|
1585
|
+
unmount2();
|
|
1586
|
+
unmount();
|
|
1587
|
+
});
|
|
1588
|
+
});
|
|
851
1589
|
});
|