@terreno/ui 0.14.0 → 0.14.2
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 +17 -29
- 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/MarkdownView.js +20 -7
- package/dist/MarkdownView.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/dist/useConsentHistory.d.ts +6 -1
- package/dist/useConsentHistory.js +2 -1
- package/dist/useConsentHistory.js.map +1 -1
- package/package.json +1 -1
- package/src/ActionSheet.test.tsx +554 -0
- package/src/ActionSheet.tsx +26 -39
- package/src/Banner.test.tsx +107 -1
- package/src/Common.ts +10 -4
- package/src/ConsentFormScreen.test.tsx +22 -0
- package/src/ConsentFormScreen.tsx +9 -3
- package/src/DataTable.test.tsx +393 -1
- package/src/DateTimeField.test.tsx +716 -2
- package/src/DateUtilities.tsx +37 -38
- package/src/HeightActionSheet.test.tsx +17 -1
- package/src/HeightField.test.tsx +141 -1
- package/src/HeightFieldDesktop.test.tsx +19 -0
- package/src/MarkdownView.test.tsx +28 -0
- package/src/MarkdownView.tsx +69 -7
- package/src/MediaQuery.ts +8 -8
- package/src/MobileAddressAutoComplete.test.tsx +26 -3
- package/src/Page.test.tsx +28 -0
- package/src/Page.tsx +17 -2
- package/src/PickerSelect.test.tsx +243 -0
- package/src/PickerSelect.tsx +3 -3
- package/src/SplitPage.test.tsx +299 -43
- package/src/TapToEdit.test.tsx +44 -0
- package/src/TapToEdit.tsx +2 -3
- package/src/ToastNotifications.test.tsx +1412 -0
- package/src/ToastNotifications.tsx +2 -2
- package/src/Tooltip.test.tsx +1294 -3
- package/src/Tooltip.tsx +2 -2
- package/src/Unifier.ts +14 -11
- package/src/Utilities.tsx +14 -16
- package/src/WebAddressAutocomplete.test.tsx +237 -0
- package/src/WebDropdownMenu.test.tsx +51 -2
- package/src/__snapshots__/Banner.test.tsx.snap +125 -0
- package/src/__snapshots__/DataTable.test.tsx.snap +366 -0
- package/src/__snapshots__/MarkdownView.test.tsx.snap +284 -74
- package/src/__snapshots__/SplitPage.test.tsx.snap +698 -46
- package/src/bunSetup.ts +0 -4
- package/src/index.tsx +1 -1
- package/src/login/LoginScreen.test.tsx +35 -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/useConsentHistory.test.ts +20 -13
- package/src/useConsentHistory.ts +7 -2
- package/src/useStoredState.test.tsx +47 -0
|
@@ -848,4 +848,1416 @@ 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
|
+
});
|
|
1589
|
+
|
|
1590
|
+
describe("Toast with swipeEnabled and pan interactions", () => {
|
|
1591
|
+
// Capture PanResponder config callbacks to test them directly
|
|
1592
|
+
const capturedConfigs: Array<Record<string, Function>> = [];
|
|
1593
|
+
|
|
1594
|
+
it("should exercise pan responder callbacks directly", async () => {
|
|
1595
|
+
const {PanResponder} = require("react-native");
|
|
1596
|
+
const originalCreate = PanResponder.create;
|
|
1597
|
+
PanResponder.create = (config: Record<string, Function>) => {
|
|
1598
|
+
capturedConfigs.push(config);
|
|
1599
|
+
return originalCreate.call(PanResponder, config);
|
|
1600
|
+
};
|
|
1601
|
+
|
|
1602
|
+
let toastRef: ToastType | null = null;
|
|
1603
|
+
const TestComponent = () => {
|
|
1604
|
+
const toast = useToastNotifications();
|
|
1605
|
+
toastRef = toast;
|
|
1606
|
+
return <Text>Test</Text>;
|
|
1607
|
+
};
|
|
1608
|
+
|
|
1609
|
+
render(
|
|
1610
|
+
<ToastProvider swipeEnabled>
|
|
1611
|
+
<TestComponent />
|
|
1612
|
+
</ToastProvider>
|
|
1613
|
+
);
|
|
1614
|
+
|
|
1615
|
+
await waitFor(() => {
|
|
1616
|
+
expect(toastRef?.show).toBeDefined();
|
|
1617
|
+
});
|
|
1618
|
+
|
|
1619
|
+
await act(async () => {
|
|
1620
|
+
toastRef?.show("Swipe toast", {id: "swipe-direct", swipeEnabled: true});
|
|
1621
|
+
});
|
|
1622
|
+
|
|
1623
|
+
await act(async () => {
|
|
1624
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1625
|
+
});
|
|
1626
|
+
|
|
1627
|
+
// Find the captured PanResponder config
|
|
1628
|
+
const panConfig = capturedConfigs[capturedConfigs.length - 1];
|
|
1629
|
+
expect(panConfig).toBeDefined();
|
|
1630
|
+
|
|
1631
|
+
if (panConfig) {
|
|
1632
|
+
const mockEvent = {};
|
|
1633
|
+
|
|
1634
|
+
// Test onMoveShouldSetPanResponder with large movement
|
|
1635
|
+
if (panConfig.onMoveShouldSetPanResponder) {
|
|
1636
|
+
const result = panConfig.onMoveShouldSetPanResponder(mockEvent, {dx: 20, dy: 0});
|
|
1637
|
+
expect(result).toBe(true);
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
// Test onMoveShouldSetPanResponder with no movement
|
|
1641
|
+
if (panConfig.onMoveShouldSetPanResponder) {
|
|
1642
|
+
const result = panConfig.onMoveShouldSetPanResponder(mockEvent, {dx: 0, dy: 0});
|
|
1643
|
+
expect(result).toBe(false);
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
// Test onPanResponderMove
|
|
1647
|
+
if (panConfig.onPanResponderMove) {
|
|
1648
|
+
await act(async () => {
|
|
1649
|
+
panConfig.onPanResponderMove(mockEvent, {dx: 30, dy: 5});
|
|
1650
|
+
});
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
// Test onPanResponderRelease with swipe right (dx > 50)
|
|
1654
|
+
if (panConfig.onPanResponderRelease) {
|
|
1655
|
+
await act(async () => {
|
|
1656
|
+
panConfig.onPanResponderRelease(mockEvent, {dx: 60, dy: 0});
|
|
1657
|
+
});
|
|
1658
|
+
await act(async () => {
|
|
1659
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1660
|
+
});
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
PanResponder.create = originalCreate;
|
|
1665
|
+
});
|
|
1666
|
+
|
|
1667
|
+
it("should handle swipe left via pan responder callback", async () => {
|
|
1668
|
+
const {PanResponder} = require("react-native");
|
|
1669
|
+
const configs: Array<Record<string, Function>> = [];
|
|
1670
|
+
const originalCreate = PanResponder.create;
|
|
1671
|
+
PanResponder.create = (config: Record<string, Function>) => {
|
|
1672
|
+
configs.push(config);
|
|
1673
|
+
return originalCreate.call(PanResponder, config);
|
|
1674
|
+
};
|
|
1675
|
+
|
|
1676
|
+
let toastRef: ToastType | null = null;
|
|
1677
|
+
const TestComponent = () => {
|
|
1678
|
+
const toast = useToastNotifications();
|
|
1679
|
+
toastRef = toast;
|
|
1680
|
+
return <Text>Test</Text>;
|
|
1681
|
+
};
|
|
1682
|
+
|
|
1683
|
+
render(
|
|
1684
|
+
<ToastProvider swipeEnabled>
|
|
1685
|
+
<TestComponent />
|
|
1686
|
+
</ToastProvider>
|
|
1687
|
+
);
|
|
1688
|
+
|
|
1689
|
+
await waitFor(() => {
|
|
1690
|
+
expect(toastRef?.show).toBeDefined();
|
|
1691
|
+
});
|
|
1692
|
+
|
|
1693
|
+
await act(async () => {
|
|
1694
|
+
toastRef?.show("Swipe left", {id: "swipe-left-direct", swipeEnabled: true});
|
|
1695
|
+
});
|
|
1696
|
+
|
|
1697
|
+
await act(async () => {
|
|
1698
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1699
|
+
});
|
|
1700
|
+
|
|
1701
|
+
const panConfig = configs[configs.length - 1];
|
|
1702
|
+
if (panConfig?.onPanResponderRelease) {
|
|
1703
|
+
// Swipe left (dx < -50)
|
|
1704
|
+
await act(async () => {
|
|
1705
|
+
panConfig.onPanResponderRelease({}, {dx: -60, dy: 0});
|
|
1706
|
+
});
|
|
1707
|
+
await act(async () => {
|
|
1708
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1709
|
+
});
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
PanResponder.create = originalCreate;
|
|
1713
|
+
});
|
|
1714
|
+
|
|
1715
|
+
it("should snap back on small swipe via pan responder callback", async () => {
|
|
1716
|
+
const {PanResponder} = require("react-native");
|
|
1717
|
+
const configs: Array<Record<string, Function>> = [];
|
|
1718
|
+
const originalCreate = PanResponder.create;
|
|
1719
|
+
PanResponder.create = (config: Record<string, Function>) => {
|
|
1720
|
+
configs.push(config);
|
|
1721
|
+
return originalCreate.call(PanResponder, config);
|
|
1722
|
+
};
|
|
1723
|
+
|
|
1724
|
+
let toastRef: ToastType | null = null;
|
|
1725
|
+
const TestComponent = () => {
|
|
1726
|
+
const toast = useToastNotifications();
|
|
1727
|
+
toastRef = toast;
|
|
1728
|
+
return <Text>Test</Text>;
|
|
1729
|
+
};
|
|
1730
|
+
|
|
1731
|
+
render(
|
|
1732
|
+
<ToastProvider swipeEnabled>
|
|
1733
|
+
<TestComponent />
|
|
1734
|
+
</ToastProvider>
|
|
1735
|
+
);
|
|
1736
|
+
|
|
1737
|
+
await waitFor(() => {
|
|
1738
|
+
expect(toastRef?.show).toBeDefined();
|
|
1739
|
+
});
|
|
1740
|
+
|
|
1741
|
+
await act(async () => {
|
|
1742
|
+
toastRef?.show("Small swipe", {id: "swipe-small-direct", swipeEnabled: true});
|
|
1743
|
+
});
|
|
1744
|
+
|
|
1745
|
+
await act(async () => {
|
|
1746
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1747
|
+
});
|
|
1748
|
+
|
|
1749
|
+
const panConfig = configs[configs.length - 1];
|
|
1750
|
+
if (panConfig?.onPanResponderRelease) {
|
|
1751
|
+
// Small swipe that should spring back
|
|
1752
|
+
await act(async () => {
|
|
1753
|
+
panConfig.onPanResponderRelease({}, {dx: 10, dy: 0});
|
|
1754
|
+
});
|
|
1755
|
+
await act(async () => {
|
|
1756
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1757
|
+
});
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1760
|
+
PanResponder.create = originalCreate;
|
|
1761
|
+
});
|
|
1762
|
+
});
|
|
1763
|
+
|
|
1764
|
+
describe("Toast lifecycle and auto-close", () => {
|
|
1765
|
+
it("should auto-close toast after duration expires", async () => {
|
|
1766
|
+
let toastRef: ToastType | null = null;
|
|
1767
|
+
|
|
1768
|
+
const TestComponent = () => {
|
|
1769
|
+
const toast = useToastNotifications();
|
|
1770
|
+
toastRef = toast;
|
|
1771
|
+
return <Text>Test</Text>;
|
|
1772
|
+
};
|
|
1773
|
+
|
|
1774
|
+
render(
|
|
1775
|
+
<ToastProvider swipeEnabled={false}>
|
|
1776
|
+
<TestComponent />
|
|
1777
|
+
</ToastProvider>
|
|
1778
|
+
);
|
|
1779
|
+
|
|
1780
|
+
await waitFor(() => {
|
|
1781
|
+
expect(toastRef?.show).toBeDefined();
|
|
1782
|
+
});
|
|
1783
|
+
|
|
1784
|
+
const onCloseMock = mock(() => {});
|
|
1785
|
+
await act(async () => {
|
|
1786
|
+
toastRef?.show("Auto close toast", {
|
|
1787
|
+
duration: 100,
|
|
1788
|
+
id: "auto-close",
|
|
1789
|
+
onClose: onCloseMock,
|
|
1790
|
+
});
|
|
1791
|
+
});
|
|
1792
|
+
|
|
1793
|
+
// Wait for requestAnimationFrame + duration + animation
|
|
1794
|
+
await act(async () => {
|
|
1795
|
+
await new Promise((resolve) => setTimeout(resolve, 600));
|
|
1796
|
+
});
|
|
1797
|
+
});
|
|
1798
|
+
|
|
1799
|
+
it("should trigger handleClose when hiding a toast", async () => {
|
|
1800
|
+
let toastRef: ToastType | null = null;
|
|
1801
|
+
|
|
1802
|
+
const TestComponent = () => {
|
|
1803
|
+
const toast = useToastNotifications();
|
|
1804
|
+
toastRef = toast;
|
|
1805
|
+
return <Text>Test</Text>;
|
|
1806
|
+
};
|
|
1807
|
+
|
|
1808
|
+
render(
|
|
1809
|
+
<ToastProvider swipeEnabled={false}>
|
|
1810
|
+
<TestComponent />
|
|
1811
|
+
</ToastProvider>
|
|
1812
|
+
);
|
|
1813
|
+
|
|
1814
|
+
await waitFor(() => {
|
|
1815
|
+
expect(toastRef?.show).toBeDefined();
|
|
1816
|
+
});
|
|
1817
|
+
|
|
1818
|
+
await act(async () => {
|
|
1819
|
+
toastRef?.show("Hide me", {duration: 0, id: "hide-close"});
|
|
1820
|
+
});
|
|
1821
|
+
|
|
1822
|
+
await act(async () => {
|
|
1823
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1824
|
+
});
|
|
1825
|
+
|
|
1826
|
+
// Hide triggers the close animation
|
|
1827
|
+
await act(async () => {
|
|
1828
|
+
toastRef?.hide("hide-close");
|
|
1829
|
+
});
|
|
1830
|
+
|
|
1831
|
+
// Wait for close animation to complete
|
|
1832
|
+
await act(async () => {
|
|
1833
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
1834
|
+
});
|
|
1835
|
+
});
|
|
1836
|
+
|
|
1837
|
+
it("should auto-destroy toast after animation completes", async () => {
|
|
1838
|
+
let toastRef: ToastType | null = null;
|
|
1839
|
+
const onCloseMock = mock(() => {});
|
|
1840
|
+
|
|
1841
|
+
const TestComponent = () => {
|
|
1842
|
+
const toast = useToastNotifications();
|
|
1843
|
+
toastRef = toast;
|
|
1844
|
+
return <Text>Test</Text>;
|
|
1845
|
+
};
|
|
1846
|
+
|
|
1847
|
+
render(
|
|
1848
|
+
<ToastProvider animationDuration={50} swipeEnabled={false}>
|
|
1849
|
+
<TestComponent />
|
|
1850
|
+
</ToastProvider>
|
|
1851
|
+
);
|
|
1852
|
+
|
|
1853
|
+
await waitFor(() => {
|
|
1854
|
+
expect(toastRef?.show).toBeDefined();
|
|
1855
|
+
});
|
|
1856
|
+
|
|
1857
|
+
await act(async () => {
|
|
1858
|
+
toastRef?.show("Short life", {
|
|
1859
|
+
animationDuration: 50,
|
|
1860
|
+
duration: 50,
|
|
1861
|
+
id: "short-life",
|
|
1862
|
+
onClose: onCloseMock,
|
|
1863
|
+
});
|
|
1864
|
+
});
|
|
1865
|
+
|
|
1866
|
+
// Wait long enough for auto-close + animation
|
|
1867
|
+
await act(async () => {
|
|
1868
|
+
await new Promise((resolve) => setTimeout(resolve, 400));
|
|
1869
|
+
});
|
|
1870
|
+
|
|
1871
|
+
expect(toastRef?.isOpen("short-life")).toBe(false);
|
|
1872
|
+
});
|
|
1873
|
+
});
|
|
1874
|
+
|
|
1875
|
+
describe("Toast swipe gestures", () => {
|
|
1876
|
+
it("should render swipe-enabled toast and handle pan gestures", async () => {
|
|
1877
|
+
let toastRef: ToastType | null = null;
|
|
1878
|
+
|
|
1879
|
+
const TestComponent = () => {
|
|
1880
|
+
const toast = useToastNotifications();
|
|
1881
|
+
toastRef = toast;
|
|
1882
|
+
return <Text>Test</Text>;
|
|
1883
|
+
};
|
|
1884
|
+
|
|
1885
|
+
render(
|
|
1886
|
+
<ToastProvider swipeEnabled>
|
|
1887
|
+
<TestComponent />
|
|
1888
|
+
</ToastProvider>
|
|
1889
|
+
);
|
|
1890
|
+
|
|
1891
|
+
await waitFor(() => {
|
|
1892
|
+
expect(toastRef?.show).toBeDefined();
|
|
1893
|
+
});
|
|
1894
|
+
|
|
1895
|
+
await act(async () => {
|
|
1896
|
+
toastRef?.show("Swipe me", {swipeEnabled: true});
|
|
1897
|
+
});
|
|
1898
|
+
|
|
1899
|
+
await act(async () => {
|
|
1900
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1901
|
+
});
|
|
1902
|
+
});
|
|
1903
|
+
});
|
|
1904
|
+
|
|
1905
|
+
describe("Toast animation types", () => {
|
|
1906
|
+
it("should show toast with zoom-in animation", async () => {
|
|
1907
|
+
let toastRef: ToastType | null = null;
|
|
1908
|
+
|
|
1909
|
+
const TestComponent = () => {
|
|
1910
|
+
const toast = useToastNotifications();
|
|
1911
|
+
toastRef = toast;
|
|
1912
|
+
return <Text>Test</Text>;
|
|
1913
|
+
};
|
|
1914
|
+
|
|
1915
|
+
render(
|
|
1916
|
+
<ToastProvider animationType="zoom-in" swipeEnabled={false}>
|
|
1917
|
+
<TestComponent />
|
|
1918
|
+
</ToastProvider>
|
|
1919
|
+
);
|
|
1920
|
+
|
|
1921
|
+
await waitFor(() => {
|
|
1922
|
+
expect(toastRef?.show).toBeDefined();
|
|
1923
|
+
});
|
|
1924
|
+
|
|
1925
|
+
await act(async () => {
|
|
1926
|
+
toastRef?.show("Zoom toast", {animationType: "zoom-in"});
|
|
1927
|
+
});
|
|
1928
|
+
|
|
1929
|
+
await act(async () => {
|
|
1930
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1931
|
+
});
|
|
1932
|
+
});
|
|
1933
|
+
|
|
1934
|
+
it("should show toast with bottom placement and slide-in", async () => {
|
|
1935
|
+
let toastRef: ToastType | null = null;
|
|
1936
|
+
|
|
1937
|
+
const TestComponent = () => {
|
|
1938
|
+
const toast = useToastNotifications();
|
|
1939
|
+
toastRef = toast;
|
|
1940
|
+
return <Text>Test</Text>;
|
|
1941
|
+
};
|
|
1942
|
+
|
|
1943
|
+
render(
|
|
1944
|
+
<ToastProvider placement="bottom" swipeEnabled={false}>
|
|
1945
|
+
<TestComponent />
|
|
1946
|
+
</ToastProvider>
|
|
1947
|
+
);
|
|
1948
|
+
|
|
1949
|
+
await waitFor(() => {
|
|
1950
|
+
expect(toastRef?.show).toBeDefined();
|
|
1951
|
+
});
|
|
1952
|
+
|
|
1953
|
+
await act(async () => {
|
|
1954
|
+
toastRef?.show("Bottom slide toast", {placement: "bottom"});
|
|
1955
|
+
});
|
|
1956
|
+
|
|
1957
|
+
await act(async () => {
|
|
1958
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1959
|
+
});
|
|
1960
|
+
});
|
|
1961
|
+
});
|
|
1962
|
+
|
|
1963
|
+
describe("Toast renderType and renderToast", () => {
|
|
1964
|
+
it("should render custom toast via renderType", async () => {
|
|
1965
|
+
let toastRef: ToastType | null = null;
|
|
1966
|
+
|
|
1967
|
+
const TestComponent = () => {
|
|
1968
|
+
const toast = useToastNotifications();
|
|
1969
|
+
toastRef = toast;
|
|
1970
|
+
return <Text>Test</Text>;
|
|
1971
|
+
};
|
|
1972
|
+
|
|
1973
|
+
const customRenderType = {
|
|
1974
|
+
custom: (toast: ToastProps) => <Text>Custom: {String(toast.message)}</Text>,
|
|
1975
|
+
};
|
|
1976
|
+
|
|
1977
|
+
render(
|
|
1978
|
+
<ToastProvider renderType={customRenderType} swipeEnabled={false}>
|
|
1979
|
+
<TestComponent />
|
|
1980
|
+
</ToastProvider>
|
|
1981
|
+
);
|
|
1982
|
+
|
|
1983
|
+
await waitFor(() => {
|
|
1984
|
+
expect(toastRef?.show).toBeDefined();
|
|
1985
|
+
});
|
|
1986
|
+
|
|
1987
|
+
await act(async () => {
|
|
1988
|
+
toastRef?.show("Hello", {type: "custom"});
|
|
1989
|
+
});
|
|
1990
|
+
|
|
1991
|
+
await act(async () => {
|
|
1992
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1993
|
+
});
|
|
1994
|
+
});
|
|
1995
|
+
|
|
1996
|
+
it("should render custom toast via renderToast", async () => {
|
|
1997
|
+
let toastRef: ToastType | null = null;
|
|
1998
|
+
|
|
1999
|
+
const TestComponent = () => {
|
|
2000
|
+
const toast = useToastNotifications();
|
|
2001
|
+
toastRef = toast;
|
|
2002
|
+
return <Text>Test</Text>;
|
|
2003
|
+
};
|
|
2004
|
+
|
|
2005
|
+
render(
|
|
2006
|
+
<ToastProvider
|
|
2007
|
+
renderToast={(toast) => <Text>Rendered: {String(toast.message)}</Text>}
|
|
2008
|
+
swipeEnabled={false}
|
|
2009
|
+
>
|
|
2010
|
+
<TestComponent />
|
|
2011
|
+
</ToastProvider>
|
|
2012
|
+
);
|
|
2013
|
+
|
|
2014
|
+
await waitFor(() => {
|
|
2015
|
+
expect(toastRef?.show).toBeDefined();
|
|
2016
|
+
});
|
|
2017
|
+
|
|
2018
|
+
await act(async () => {
|
|
2019
|
+
toastRef?.show("Custom render");
|
|
2020
|
+
});
|
|
2021
|
+
|
|
2022
|
+
await act(async () => {
|
|
2023
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
2024
|
+
});
|
|
2025
|
+
});
|
|
2026
|
+
});
|
|
2027
|
+
|
|
2028
|
+
describe("Toast onPress", () => {
|
|
2029
|
+
it("should call onPress when toast is pressed", async () => {
|
|
2030
|
+
let toastRef: ToastType | null = null;
|
|
2031
|
+
const onPressMock = mock((_id: string) => {});
|
|
2032
|
+
|
|
2033
|
+
const TestComponent = () => {
|
|
2034
|
+
const toast = useToastNotifications();
|
|
2035
|
+
toastRef = toast;
|
|
2036
|
+
return <Text>Test</Text>;
|
|
2037
|
+
};
|
|
2038
|
+
|
|
2039
|
+
render(
|
|
2040
|
+
<ToastProvider swipeEnabled={false}>
|
|
2041
|
+
<TestComponent />
|
|
2042
|
+
</ToastProvider>
|
|
2043
|
+
);
|
|
2044
|
+
|
|
2045
|
+
await waitFor(() => {
|
|
2046
|
+
expect(toastRef?.show).toBeDefined();
|
|
2047
|
+
});
|
|
2048
|
+
|
|
2049
|
+
await act(async () => {
|
|
2050
|
+
toastRef?.show("Press me", {id: "press-test", onPress: onPressMock});
|
|
2051
|
+
});
|
|
2052
|
+
|
|
2053
|
+
await act(async () => {
|
|
2054
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
2055
|
+
});
|
|
2056
|
+
});
|
|
2057
|
+
});
|
|
2058
|
+
|
|
2059
|
+
describe("Toast custom colors", () => {
|
|
2060
|
+
it("should render with custom success/danger/warning/normal colors", async () => {
|
|
2061
|
+
let toastRef: ToastType | null = null;
|
|
2062
|
+
|
|
2063
|
+
const TestComponent = () => {
|
|
2064
|
+
const toast = useToastNotifications();
|
|
2065
|
+
toastRef = toast;
|
|
2066
|
+
return <Text>Test</Text>;
|
|
2067
|
+
};
|
|
2068
|
+
|
|
2069
|
+
render(
|
|
2070
|
+
<ToastProvider
|
|
2071
|
+
dangerColor="#ff0000"
|
|
2072
|
+
normalColor="#999999"
|
|
2073
|
+
successColor="#00ff00"
|
|
2074
|
+
swipeEnabled={false}
|
|
2075
|
+
warningColor="#ffff00"
|
|
2076
|
+
>
|
|
2077
|
+
<TestComponent />
|
|
2078
|
+
</ToastProvider>
|
|
2079
|
+
);
|
|
2080
|
+
|
|
2081
|
+
await waitFor(() => {
|
|
2082
|
+
expect(toastRef?.show).toBeDefined();
|
|
2083
|
+
});
|
|
2084
|
+
|
|
2085
|
+
await act(async () => {
|
|
2086
|
+
toastRef?.show("Normal toast");
|
|
2087
|
+
});
|
|
2088
|
+
|
|
2089
|
+
await act(async () => {
|
|
2090
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
2091
|
+
});
|
|
2092
|
+
});
|
|
2093
|
+
});
|
|
2094
|
+
|
|
2095
|
+
describe("center placement toast rendering", () => {
|
|
2096
|
+
it("should fully render center toast content including filter and map callbacks", async () => {
|
|
2097
|
+
let toastRef: ToastType | null = null;
|
|
2098
|
+
const TestComponent = () => {
|
|
2099
|
+
const toast = useToastNotifications();
|
|
2100
|
+
toastRef = toast;
|
|
2101
|
+
return <Text>Test</Text>;
|
|
2102
|
+
};
|
|
2103
|
+
|
|
2104
|
+
const {getByText} = render(
|
|
2105
|
+
<ToastProvider placement="center" swipeEnabled={false}>
|
|
2106
|
+
<TestComponent />
|
|
2107
|
+
</ToastProvider>
|
|
2108
|
+
);
|
|
2109
|
+
|
|
2110
|
+
await waitFor(() => {
|
|
2111
|
+
expect(toastRef?.show).toBeDefined();
|
|
2112
|
+
});
|
|
2113
|
+
|
|
2114
|
+
await act(async () => {
|
|
2115
|
+
toastRef?.show("Center rendered", {placement: "center"});
|
|
2116
|
+
});
|
|
2117
|
+
|
|
2118
|
+
// Flush the requestAnimationFrame (mocked as setTimeout(, 0)) and re-renders
|
|
2119
|
+
for (let i = 0; i < 5; i++) {
|
|
2120
|
+
await act(async () => {
|
|
2121
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
2122
|
+
});
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2125
|
+
expect(getByText("Center rendered")).toBeTruthy();
|
|
2126
|
+
});
|
|
2127
|
+
|
|
2128
|
+
it("should render multiple center toasts through filter and map", async () => {
|
|
2129
|
+
let toastRef: ToastType | null = null;
|
|
2130
|
+
const TestComponent = () => {
|
|
2131
|
+
const toast = useToastNotifications();
|
|
2132
|
+
toastRef = toast;
|
|
2133
|
+
return <Text>Test</Text>;
|
|
2134
|
+
};
|
|
2135
|
+
|
|
2136
|
+
const {getByText} = render(
|
|
2137
|
+
<ToastProvider placement="center" swipeEnabled={false}>
|
|
2138
|
+
<TestComponent />
|
|
2139
|
+
</ToastProvider>
|
|
2140
|
+
);
|
|
2141
|
+
|
|
2142
|
+
await waitFor(() => {
|
|
2143
|
+
expect(toastRef?.show).toBeDefined();
|
|
2144
|
+
});
|
|
2145
|
+
|
|
2146
|
+
await act(async () => {
|
|
2147
|
+
toastRef?.show("Center X", {id: "cx", placement: "center"});
|
|
2148
|
+
});
|
|
2149
|
+
|
|
2150
|
+
for (let i = 0; i < 5; i++) {
|
|
2151
|
+
await act(async () => {
|
|
2152
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
2153
|
+
});
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
await act(async () => {
|
|
2157
|
+
toastRef?.show("Center Y", {id: "cy", placement: "center"});
|
|
2158
|
+
});
|
|
2159
|
+
|
|
2160
|
+
for (let i = 0; i < 5; i++) {
|
|
2161
|
+
await act(async () => {
|
|
2162
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
2163
|
+
});
|
|
2164
|
+
}
|
|
2165
|
+
|
|
2166
|
+
expect(getByText("Center X")).toBeTruthy();
|
|
2167
|
+
expect(getByText("Center Y")).toBeTruthy();
|
|
2168
|
+
});
|
|
2169
|
+
});
|
|
2170
|
+
|
|
2171
|
+
describe("auto-close timer callback", () => {
|
|
2172
|
+
it("should fire the setTimeout callback that calls handleClose", async () => {
|
|
2173
|
+
let toastRef: ToastType | null = null;
|
|
2174
|
+
const onCloseMock = mock(() => {});
|
|
2175
|
+
|
|
2176
|
+
const TestComponent = () => {
|
|
2177
|
+
const toast = useToastNotifications();
|
|
2178
|
+
toastRef = toast;
|
|
2179
|
+
return <Text>Test</Text>;
|
|
2180
|
+
};
|
|
2181
|
+
|
|
2182
|
+
render(
|
|
2183
|
+
<ToastProvider swipeEnabled={false}>
|
|
2184
|
+
<TestComponent />
|
|
2185
|
+
</ToastProvider>
|
|
2186
|
+
);
|
|
2187
|
+
|
|
2188
|
+
await waitFor(() => {
|
|
2189
|
+
expect(toastRef?.show).toBeDefined();
|
|
2190
|
+
});
|
|
2191
|
+
|
|
2192
|
+
await act(async () => {
|
|
2193
|
+
toastRef?.show("Timer toast", {
|
|
2194
|
+
duration: 50,
|
|
2195
|
+
id: "timer-toast",
|
|
2196
|
+
onClose: onCloseMock,
|
|
2197
|
+
});
|
|
2198
|
+
});
|
|
2199
|
+
|
|
2200
|
+
// Flush RAF + duration timeout + close animation
|
|
2201
|
+
for (let i = 0; i < 15; i++) {
|
|
2202
|
+
await act(async () => {
|
|
2203
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
2204
|
+
});
|
|
2205
|
+
}
|
|
2206
|
+
});
|
|
2207
|
+
});
|
|
2208
|
+
|
|
2209
|
+
describe("onHide callback on toast props", () => {
|
|
2210
|
+
it("should exercise the onHide function via renderToast", async () => {
|
|
2211
|
+
let toastRef: ToastType | null = null;
|
|
2212
|
+
let capturedOnHide: (() => void) | null = null;
|
|
2213
|
+
|
|
2214
|
+
const customRenderToast = (toast: ToastProps) => {
|
|
2215
|
+
if (!capturedOnHide) {
|
|
2216
|
+
capturedOnHide = toast.onHide;
|
|
2217
|
+
}
|
|
2218
|
+
return <Text>{String(toast.message)}</Text>;
|
|
2219
|
+
};
|
|
2220
|
+
|
|
2221
|
+
const TestComponent = () => {
|
|
2222
|
+
const toast = useToastNotifications();
|
|
2223
|
+
toastRef = toast;
|
|
2224
|
+
return <Text>Test</Text>;
|
|
2225
|
+
};
|
|
2226
|
+
|
|
2227
|
+
render(
|
|
2228
|
+
<ToastProvider renderToast={customRenderToast} swipeEnabled={false}>
|
|
2229
|
+
<TestComponent />
|
|
2230
|
+
</ToastProvider>
|
|
2231
|
+
);
|
|
2232
|
+
|
|
2233
|
+
await waitFor(() => {
|
|
2234
|
+
expect(toastRef?.show).toBeDefined();
|
|
2235
|
+
});
|
|
2236
|
+
|
|
2237
|
+
await act(async () => {
|
|
2238
|
+
toastRef?.show("Custom toast", {id: "onhide-test"});
|
|
2239
|
+
});
|
|
2240
|
+
|
|
2241
|
+
// Flush RAF and let the toast render with the custom renderer
|
|
2242
|
+
for (let i = 0; i < 5; i++) {
|
|
2243
|
+
await act(async () => {
|
|
2244
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
2245
|
+
});
|
|
2246
|
+
}
|
|
2247
|
+
|
|
2248
|
+
// Call the captured onHide to exercise the () => hide(id) callback
|
|
2249
|
+
if (capturedOnHide) {
|
|
2250
|
+
await act(async () => {
|
|
2251
|
+
capturedOnHide!();
|
|
2252
|
+
});
|
|
2253
|
+
|
|
2254
|
+
// Let the hide animation complete
|
|
2255
|
+
for (let i = 0; i < 5; i++) {
|
|
2256
|
+
await act(async () => {
|
|
2257
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
2258
|
+
});
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
2261
|
+
});
|
|
2262
|
+
});
|
|
851
2263
|
});
|