@applicaster/zapp-react-native-utils 15.0.0-alpha.4429053208 → 15.0.0-alpha.4920020685
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/adsUtils/__tests__/createVMAP.test.ts +419 -0
- package/analyticsUtils/analyticsMapper.ts +10 -2
- package/appDataUtils/__tests__/urlScheme.test.ts +678 -0
- package/appUtils/HooksManager/__tests__/__snapshots__/hooksManager.test.js.snap +0 -188
- package/appUtils/HooksManager/__tests__/hooksManager.test.js +16 -2
- package/appUtils/contextKeysManager/__tests__/getKeys/failure.test.ts +7 -2
- package/appUtils/contextKeysManager/__tests__/getKeys/success.test.ts +48 -0
- package/appUtils/contextKeysManager/contextResolver.ts +51 -22
- package/appUtils/contextKeysManager/index.ts +65 -10
- package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +1 -1
- package/appUtils/focusManager/index.ios.ts +7 -8
- package/appUtils/focusManagerAux/utils/index.ios.ts +5 -5
- package/appUtils/focusManagerAux/utils/utils.ios.ts +10 -21
- package/cloudEventsUtils/__tests__/index.test.ts +529 -0
- package/cloudEventsUtils/index.ts +65 -1
- package/configurationUtils/__tests__/imageSrcFromMediaItem.test.ts +38 -0
- package/configurationUtils/index.ts +17 -11
- package/dateUtils/__tests__/dayjs.test.ts +330 -0
- package/enumUtils/__tests__/getEnumKeyByEnumValue.test.ts +207 -0
- package/errorUtils/__tests__/GeneralError.test.ts +97 -0
- package/errorUtils/__tests__/HttpStatusCode.test.ts +344 -0
- package/errorUtils/__tests__/MissingPluginError.test.ts +113 -0
- package/errorUtils/__tests__/NetworkError.test.ts +202 -0
- package/errorUtils/__tests__/getParsedResponse.test.ts +188 -0
- package/errorUtils/__tests__/invariant.test.ts +112 -0
- package/headersUtils/__tests__/headersUtils.test.js +11 -1
- package/headersUtils/index.ts +2 -1
- package/manifestUtils/defaultManifestConfigurations/player.js +29 -0
- package/manifestUtils/platformIsTV.js +13 -0
- package/navigationUtils/index.ts +15 -5
- package/numberUtils/__tests__/toNumber.test.ts +12 -0
- package/numberUtils/__tests__/toPositiveNumber.test.ts +165 -0
- package/numberUtils/index.ts +19 -1
- package/package.json +4 -4
- package/reactHooks/analytics/__tests__/useSendAnalyticsOnPress.test.ts +537 -0
- package/reactHooks/app/__tests__/useAppState.test.ts +1 -1
- package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +1 -1
- package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +1 -2
- package/reactHooks/cell-click/__tests__/index.test.js +1 -3
- package/reactHooks/configuration/__tests__/index.test.tsx +1 -1
- package/reactHooks/connection/__tests__/index.test.js +1 -1
- package/reactHooks/dev/__tests__/useReRenderLog.test.ts +188 -0
- package/reactHooks/device/useIsTablet.tsx +14 -19
- package/reactHooks/events/index.ts +20 -0
- package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +32 -23
- package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +19 -19
- package/reactHooks/feed/__tests__/useEntryScreenId.test.tsx +1 -1
- package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +42 -30
- package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +1 -1
- package/reactHooks/feed/__tests__/useInflatedUrl.test.tsx +1 -1
- package/reactHooks/hookModal/hooks/useHookModalScreenData.ts +12 -8
- package/reactHooks/index.ts +2 -0
- package/reactHooks/layout/__tests__/index.test.tsx +1 -1
- package/reactHooks/layout/__tests__/useLayoutVersion.test.tsx +1 -1
- package/reactHooks/navigation/__tests__/index.test.tsx +40 -9
- package/reactHooks/navigation/index.ts +15 -4
- package/reactHooks/navigation/useRoute.ts +3 -1
- package/reactHooks/player/__tests__/useAutoSeek._test.tsx +1 -1
- package/reactHooks/player/__tests__/useTapSeek._test.ts +1 -1
- package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +1 -1
- package/reactHooks/resolvers/__tests__/useComponentResolver.test.tsx +1 -1
- package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +1 -1
- package/reactHooks/screen/__tests__/useScreenBackgroundColor.test.tsx +1 -1
- package/reactHooks/screen/__tests__/useScreenData.test.tsx +1 -1
- package/reactHooks/screen/__tests__/useTargetScreenData.test.tsx +1 -1
- package/reactHooks/state/useRefWithInitialValue.ts +10 -0
- package/reactHooks/ui/__tests__/useFadeOutWhenBlurred.test.ts +580 -0
- package/reactHooks/utils/__tests__/index.test.js +1 -1
- package/rectUtils/__tests__/index.test.ts +549 -0
- package/rectUtils/index.ts +2 -2
- package/screenPickerUtils/__tests__/index.test.ts +333 -0
- package/screenState/__tests__/index.test.ts +1 -1
- package/services/storageServiceSync.web.ts +1 -1
- package/stringUtils/index.ts +1 -1
- package/time/__tests__/BackgroundTimer.test.ts +156 -0
- package/time/__tests__/Timer.test.ts +236 -0
- package/typeGuards/__tests__/isString.test.ts +21 -0
- package/typeGuards/index.ts +4 -0
- package/reactHooks/componentsMap/index.ts +0 -55
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { NetworkError } from "../NetworkError";
|
|
2
|
+
import { HttpStatusCode } from "../HttpStatusCode";
|
|
3
|
+
|
|
4
|
+
describe("NetworkError", () => {
|
|
5
|
+
describe("constructor", () => {
|
|
6
|
+
it("should create network error with message and status code", () => {
|
|
7
|
+
const message = "Request failed";
|
|
8
|
+
const statusCode = 404;
|
|
9
|
+
const error = new NetworkError(message, statusCode);
|
|
10
|
+
|
|
11
|
+
expect(error).toBeInstanceOf(Error);
|
|
12
|
+
expect(error).toBeInstanceOf(NetworkError);
|
|
13
|
+
expect(error.originalMessage).toBe(message);
|
|
14
|
+
expect(error.statusCode).toBe(statusCode);
|
|
15
|
+
expect(error.message).toContain("404");
|
|
16
|
+
expect(error.message).toContain(message);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("should format readable log message", () => {
|
|
20
|
+
const message = "Not found";
|
|
21
|
+
const statusCode = 404;
|
|
22
|
+
const error = new NetworkError(message, statusCode);
|
|
23
|
+
|
|
24
|
+
expect(error.message).toContain("statusCode:");
|
|
25
|
+
expect(error.message).toContain("message:");
|
|
26
|
+
expect(error.message).toContain("readableStatus:");
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("should handle null message", () => {
|
|
30
|
+
const error = new NetworkError(null as any, 500);
|
|
31
|
+
|
|
32
|
+
expect(error.originalMessage).toBeNull();
|
|
33
|
+
expect(error.message).toContain("No error message available");
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should handle undefined message", () => {
|
|
37
|
+
const error = new NetworkError(undefined as any, 500);
|
|
38
|
+
|
|
39
|
+
expect(error.originalMessage).toBeUndefined();
|
|
40
|
+
expect(error.message).toContain("No error message available");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should handle custom status codes", () => {
|
|
44
|
+
const message = "Custom error";
|
|
45
|
+
const statusCode = 999;
|
|
46
|
+
const error = new NetworkError(message, statusCode);
|
|
47
|
+
|
|
48
|
+
expect(error.statusCode).toBe(statusCode);
|
|
49
|
+
expect(error.message).toContain("999");
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe("isNetworkError static method", () => {
|
|
54
|
+
it("should return true for NetworkError instance", () => {
|
|
55
|
+
const error = new NetworkError("Test", 500);
|
|
56
|
+
|
|
57
|
+
expect(NetworkError.isNetworkError(error)).toBe(true);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("should return false for regular Error", () => {
|
|
61
|
+
const error = new Error("Regular error");
|
|
62
|
+
|
|
63
|
+
expect(NetworkError.isNetworkError(error)).toBe(false);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("should return false for other error types", () => {
|
|
67
|
+
class CustomError extends Error {}
|
|
68
|
+
const error = new CustomError("Custom");
|
|
69
|
+
|
|
70
|
+
expect(NetworkError.isNetworkError(error)).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
describe("httpStatusCode getter", () => {
|
|
75
|
+
it("should return correct HttpStatusCode for 401", () => {
|
|
76
|
+
const error = new NetworkError("Unauthorized", 401);
|
|
77
|
+
|
|
78
|
+
expect(error.httpStatusCode).toBe(HttpStatusCode.Unauthorized);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("should return correct HttpStatusCode for 403", () => {
|
|
82
|
+
const error = new NetworkError("Forbidden", 403);
|
|
83
|
+
|
|
84
|
+
expect(error.httpStatusCode).toBe(HttpStatusCode.Forbidden);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("should return correct HttpStatusCode for 402", () => {
|
|
88
|
+
const error = new NetworkError("Payment Required", 402);
|
|
89
|
+
|
|
90
|
+
expect(error.httpStatusCode).toBe(HttpStatusCode.PaymentRequired);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("should return correct HttpStatusCode for 500", () => {
|
|
94
|
+
const error = new NetworkError("Server Error", 500);
|
|
95
|
+
|
|
96
|
+
expect(error.httpStatusCode).toBe(HttpStatusCode.InternalServerError);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("should handle unknown status codes", () => {
|
|
100
|
+
const error = new NetworkError("Unknown", 999);
|
|
101
|
+
|
|
102
|
+
expect(error.httpStatusCode).toBe(999);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
describe("isTokenExpired", () => {
|
|
107
|
+
it("should return true for 401 status code", () => {
|
|
108
|
+
const error = new NetworkError("Unauthorized", 401);
|
|
109
|
+
|
|
110
|
+
expect(error.isTokenExpired()).toBe(true);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("should return false for non-401 status codes", () => {
|
|
114
|
+
expect(new NetworkError("Forbidden", 403).isTokenExpired()).toBe(false);
|
|
115
|
+
expect(new NetworkError("Not Found", 404).isTokenExpired()).toBe(false);
|
|
116
|
+
|
|
117
|
+
expect(new NetworkError("Server Error", 500).isTokenExpired()).toBe(
|
|
118
|
+
false
|
|
119
|
+
);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe("isNoAccess", () => {
|
|
124
|
+
it("should return true for 403 status code", () => {
|
|
125
|
+
const error = new NetworkError("Forbidden", 403);
|
|
126
|
+
|
|
127
|
+
expect(error.isNoAccess()).toBe(true);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it("should return false for non-403 status codes", () => {
|
|
131
|
+
expect(new NetworkError("Unauthorized", 401).isNoAccess()).toBe(false);
|
|
132
|
+
expect(new NetworkError("Not Found", 404).isNoAccess()).toBe(false);
|
|
133
|
+
expect(new NetworkError("Server Error", 500).isNoAccess()).toBe(false);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
describe("isPaymentRequired", () => {
|
|
138
|
+
it("should return true for 402 status code", () => {
|
|
139
|
+
const error = new NetworkError("Payment Required", 402);
|
|
140
|
+
|
|
141
|
+
expect(error.isPaymentRequired()).toBe(true);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it("should return false for non-402 status codes", () => {
|
|
145
|
+
expect(new NetworkError("Unauthorized", 401).isPaymentRequired()).toBe(
|
|
146
|
+
false
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
expect(new NetworkError("Forbidden", 403).isPaymentRequired()).toBe(
|
|
150
|
+
false
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
expect(new NetworkError("Not Found", 404).isPaymentRequired()).toBe(
|
|
154
|
+
false
|
|
155
|
+
);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
describe("error handling scenarios", () => {
|
|
160
|
+
it("should be throwable and catchable", () => {
|
|
161
|
+
const message = "Test throw";
|
|
162
|
+
const statusCode = 500;
|
|
163
|
+
|
|
164
|
+
expect(() => {
|
|
165
|
+
throw new NetworkError(message, statusCode);
|
|
166
|
+
}).toThrow(NetworkError);
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
throw new NetworkError(message, statusCode);
|
|
170
|
+
} catch (error) {
|
|
171
|
+
expect(error).toBeInstanceOf(NetworkError);
|
|
172
|
+
expect((error as NetworkError).originalMessage).toBe(message);
|
|
173
|
+
expect((error as NetworkError).statusCode).toBe(statusCode);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("should maintain stack trace", () => {
|
|
178
|
+
const error = new NetworkError("Stack test", 500);
|
|
179
|
+
|
|
180
|
+
expect(error.stack).toBeDefined();
|
|
181
|
+
expect(error.stack).toContain("Error data:");
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it("should handle multiple error scenarios", () => {
|
|
185
|
+
const unauthorizedError = new NetworkError("Token expired", 401);
|
|
186
|
+
const forbiddenError = new NetworkError("Access denied", 403);
|
|
187
|
+
const paymentError = new NetworkError("Subscription required", 402);
|
|
188
|
+
|
|
189
|
+
expect(unauthorizedError.isTokenExpired()).toBe(true);
|
|
190
|
+
expect(unauthorizedError.isNoAccess()).toBe(false);
|
|
191
|
+
expect(unauthorizedError.isPaymentRequired()).toBe(false);
|
|
192
|
+
|
|
193
|
+
expect(forbiddenError.isTokenExpired()).toBe(false);
|
|
194
|
+
expect(forbiddenError.isNoAccess()).toBe(true);
|
|
195
|
+
expect(forbiddenError.isPaymentRequired()).toBe(false);
|
|
196
|
+
|
|
197
|
+
expect(paymentError.isTokenExpired()).toBe(false);
|
|
198
|
+
expect(paymentError.isNoAccess()).toBe(false);
|
|
199
|
+
expect(paymentError.isPaymentRequired()).toBe(true);
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
});
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { getParsedResponse } from "../index";
|
|
2
|
+
import { RESPONSES } from "../errorCodes";
|
|
3
|
+
|
|
4
|
+
describe("getParsedResponse", () => {
|
|
5
|
+
it("should parse error with response status code from response.data", () => {
|
|
6
|
+
const err = {
|
|
7
|
+
response: {
|
|
8
|
+
data: {
|
|
9
|
+
statusCode: 404,
|
|
10
|
+
message: "Resource not found",
|
|
11
|
+
},
|
|
12
|
+
config: {
|
|
13
|
+
url: "https://api.example.com/data",
|
|
14
|
+
params: { id: 123 },
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
name: "AxiosError",
|
|
18
|
+
context: { userId: "user123" },
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const result = getParsedResponse(err);
|
|
22
|
+
|
|
23
|
+
expect(result.message).toBe("Error: Resource not found");
|
|
24
|
+
expect(result.data.statusCode).toBe("404");
|
|
25
|
+
expect(result.data.url).toBe("https://api.example.com/data");
|
|
26
|
+
expect(result.data.params).toEqual({ id: 123 });
|
|
27
|
+
expect(result.data.context).toEqual({ userId: "user123" });
|
|
28
|
+
expect(result.data.name).toBe("AxiosError");
|
|
29
|
+
expect(result.jsOnly).toBe(false);
|
|
30
|
+
expect(result.exception).toBe(result.message);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("should parse error with response status code from response.status", () => {
|
|
34
|
+
const err = {
|
|
35
|
+
response: {
|
|
36
|
+
status: 500,
|
|
37
|
+
config: {
|
|
38
|
+
url: "https://api.example.com/data",
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const result = getParsedResponse(err);
|
|
44
|
+
|
|
45
|
+
expect(result.message).toBe(`Error: ${RESPONSES[500]}`);
|
|
46
|
+
expect(result.data.statusCode).toBe("500");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("should handle error with request but no response", () => {
|
|
50
|
+
const err = {
|
|
51
|
+
request: {},
|
|
52
|
+
message: "Network timeout",
|
|
53
|
+
config: {
|
|
54
|
+
url: "https://api.example.com/data",
|
|
55
|
+
params: { test: "value" },
|
|
56
|
+
},
|
|
57
|
+
name: "NetworkError",
|
|
58
|
+
context: { app: "test" },
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const result = getParsedResponse(err);
|
|
62
|
+
|
|
63
|
+
expect(result.message).toBe("Error: Network timeout");
|
|
64
|
+
expect(result.data.url).toBe("https://api.example.com/data");
|
|
65
|
+
expect(result.data.params).toEqual({ test: "value" });
|
|
66
|
+
expect(result.data.name).toBe("NetworkError");
|
|
67
|
+
expect(result.data.context).toEqual({ app: "test" });
|
|
68
|
+
expect(result.jsOnly).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("should handle error with request but no response and no message", () => {
|
|
72
|
+
const err = {
|
|
73
|
+
request: {},
|
|
74
|
+
config: {
|
|
75
|
+
url: "https://api.example.com/data",
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const result = getParsedResponse(err);
|
|
80
|
+
|
|
81
|
+
expect(result.message).toBe(`Error: ${RESPONSES.noResponse}`);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("should handle error with neither response nor request", () => {
|
|
85
|
+
const err = {
|
|
86
|
+
message: "Failed to set up request",
|
|
87
|
+
config: {
|
|
88
|
+
url: "https://api.example.com/data",
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const result = getParsedResponse(err);
|
|
93
|
+
|
|
94
|
+
expect(result.message).toBe("Error: Failed to set up request");
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("should handle error with neither response nor request and no message", () => {
|
|
98
|
+
const err = {
|
|
99
|
+
config: {
|
|
100
|
+
url: "https://api.example.com/data",
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const result = getParsedResponse(err);
|
|
105
|
+
|
|
106
|
+
expect(result.message).toBe(`Error: ${RESPONSES.unknown}`);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("should handle null error", () => {
|
|
110
|
+
const err = null;
|
|
111
|
+
|
|
112
|
+
const result = getParsedResponse(err);
|
|
113
|
+
|
|
114
|
+
expect(result.message).toBe(`Error: ${RESPONSES.unknown}`);
|
|
115
|
+
|
|
116
|
+
expect(result.data).toEqual({
|
|
117
|
+
context: undefined,
|
|
118
|
+
name: undefined,
|
|
119
|
+
params: undefined,
|
|
120
|
+
url: undefined,
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("should handle undefined error", () => {
|
|
125
|
+
const err = undefined;
|
|
126
|
+
|
|
127
|
+
const result = getParsedResponse(err);
|
|
128
|
+
|
|
129
|
+
expect(result.message).toBe(`Error: ${RESPONSES.unknown}`);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("should extract params from err.config when response is not present", () => {
|
|
133
|
+
const err = {
|
|
134
|
+
request: {},
|
|
135
|
+
message: "Request failed",
|
|
136
|
+
config: {
|
|
137
|
+
url: "https://api.example.com/data",
|
|
138
|
+
params: { key: "value" },
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const result = getParsedResponse(err);
|
|
143
|
+
|
|
144
|
+
expect(result.data.params).toEqual({ key: "value" });
|
|
145
|
+
expect(result.data.url).toBe("https://api.example.com/data");
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("should prioritize response config over error config", () => {
|
|
149
|
+
const err = {
|
|
150
|
+
response: {
|
|
151
|
+
status: 404,
|
|
152
|
+
config: {
|
|
153
|
+
url: "https://api.example.com/response-url",
|
|
154
|
+
params: { from: "response" },
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
config: {
|
|
158
|
+
url: "https://api.example.com/error-url",
|
|
159
|
+
params: { from: "error" },
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const result = getParsedResponse(err);
|
|
164
|
+
|
|
165
|
+
expect(result.data.url).toBe("https://api.example.com/response-url");
|
|
166
|
+
expect(result.data.params).toEqual({ from: "response" });
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("should handle response with custom status codes", () => {
|
|
170
|
+
const err = {
|
|
171
|
+
response: {
|
|
172
|
+
data: {
|
|
173
|
+
statusCode: 418,
|
|
174
|
+
message: "I'm a teapot",
|
|
175
|
+
},
|
|
176
|
+
status: 418,
|
|
177
|
+
config: {
|
|
178
|
+
url: "https://api.example.com/coffee",
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const result = getParsedResponse(err);
|
|
184
|
+
|
|
185
|
+
expect(result.message).toBe("Error: I'm a teapot");
|
|
186
|
+
expect(result.data.statusCode).toBe("418");
|
|
187
|
+
});
|
|
188
|
+
});
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { invariant } from "../index";
|
|
2
|
+
|
|
3
|
+
// Mock __DEV__ global
|
|
4
|
+
declare global {
|
|
5
|
+
var __DEV__: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
describe("invariant", () => {
|
|
9
|
+
const originalDev = global.__DEV__;
|
|
10
|
+
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
global.__DEV__ = originalDev;
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
describe("in development mode", () => {
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
global.__DEV__ = true;
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("should not throw when condition is true", () => {
|
|
21
|
+
expect(() => {
|
|
22
|
+
invariant(true, "This should not throw");
|
|
23
|
+
}).not.toThrow();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("should throw when condition is false", () => {
|
|
27
|
+
expect(() => {
|
|
28
|
+
invariant(false, "This should throw");
|
|
29
|
+
}).toThrow("This should throw");
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("should throw with correct error message", () => {
|
|
33
|
+
const errorMessage = "Custom error message";
|
|
34
|
+
|
|
35
|
+
expect(() => {
|
|
36
|
+
invariant(false, errorMessage);
|
|
37
|
+
}).toThrow(errorMessage);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("should not throw when condition is truthy value", () => {
|
|
41
|
+
expect(() => {
|
|
42
|
+
invariant(1 as any, "Should not throw");
|
|
43
|
+
}).not.toThrow();
|
|
44
|
+
|
|
45
|
+
expect(() => {
|
|
46
|
+
invariant("string" as any, "Should not throw");
|
|
47
|
+
}).not.toThrow();
|
|
48
|
+
|
|
49
|
+
expect(() => {
|
|
50
|
+
invariant({} as any, "Should not throw");
|
|
51
|
+
}).not.toThrow();
|
|
52
|
+
|
|
53
|
+
expect(() => {
|
|
54
|
+
invariant([] as any, "Should not throw");
|
|
55
|
+
}).not.toThrow();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("should throw when condition is falsy value", () => {
|
|
59
|
+
expect(() => {
|
|
60
|
+
invariant(0 as any, "Should throw for 0");
|
|
61
|
+
}).toThrow("Should throw for 0");
|
|
62
|
+
|
|
63
|
+
expect(() => {
|
|
64
|
+
invariant("" as any, "Should throw for empty string");
|
|
65
|
+
}).toThrow("Should throw for empty string");
|
|
66
|
+
|
|
67
|
+
expect(() => {
|
|
68
|
+
invariant(null as any, "Should throw for null");
|
|
69
|
+
}).toThrow("Should throw for null");
|
|
70
|
+
|
|
71
|
+
expect(() => {
|
|
72
|
+
invariant(undefined as any, "Should throw for undefined");
|
|
73
|
+
}).toThrow("Should throw for undefined");
|
|
74
|
+
|
|
75
|
+
expect(() => {
|
|
76
|
+
invariant(NaN as any, "Should throw for NaN");
|
|
77
|
+
}).toThrow("Should throw for NaN");
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe("in production mode", () => {
|
|
82
|
+
beforeEach(() => {
|
|
83
|
+
global.__DEV__ = false;
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("should not throw when condition is true", () => {
|
|
87
|
+
expect(() => {
|
|
88
|
+
invariant(true, "This should not throw");
|
|
89
|
+
}).not.toThrow();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("should not throw when condition is false", () => {
|
|
93
|
+
expect(() => {
|
|
94
|
+
invariant(false, "This should not throw in production");
|
|
95
|
+
}).not.toThrow();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("should not throw for any condition", () => {
|
|
99
|
+
expect(() => {
|
|
100
|
+
invariant(0 as any, "Should not throw in production");
|
|
101
|
+
}).not.toThrow();
|
|
102
|
+
|
|
103
|
+
expect(() => {
|
|
104
|
+
invariant(null as any, "Should not throw in production");
|
|
105
|
+
}).not.toThrow();
|
|
106
|
+
|
|
107
|
+
expect(() => {
|
|
108
|
+
invariant(undefined as any, "Should not throw in production");
|
|
109
|
+
}).not.toThrow();
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
});
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
|
|
2
2
|
import { getAppDataHeaders } from "../index";
|
|
3
3
|
|
|
4
|
+
const mockUILanguage = "en-US";
|
|
5
|
+
|
|
6
|
+
jest.mock(
|
|
7
|
+
"@applicaster/zapp-react-native-utils/appUtils/localizationsHelper",
|
|
8
|
+
() => ({
|
|
9
|
+
getUILanguage: jest.fn(() => mockUILanguage),
|
|
10
|
+
})
|
|
11
|
+
);
|
|
12
|
+
|
|
4
13
|
describe("getAppDataHeaders", () => {
|
|
5
14
|
const mockAppData = {
|
|
6
15
|
riversConfigurationId: "test-layout",
|
|
@@ -25,7 +34,7 @@ describe("getAppDataHeaders", () => {
|
|
|
25
34
|
const expectedHeaders = {
|
|
26
35
|
"x-applicaster-layout-id": mockAppData.riversConfigurationId,
|
|
27
36
|
"x-applicaster-screen-id": screenId,
|
|
28
|
-
"x-applicaster-language-code":
|
|
37
|
+
"x-applicaster-language-code": mockUILanguage,
|
|
29
38
|
"x-applicaster-version-number": mockAppData.version_name,
|
|
30
39
|
"x-applicaster-platform": mockAppData.platform,
|
|
31
40
|
"x-applicaster-country-code": mockAppData.countryCode,
|
|
@@ -33,6 +42,7 @@ describe("getAppDataHeaders", () => {
|
|
|
33
42
|
mockAppData.signedDeviceInfoToken,
|
|
34
43
|
"x-applicaster-device-make": mockAppData.deviceMake,
|
|
35
44
|
"x-applicaster-device-model": mockAppData.deviceModel,
|
|
45
|
+
"x-applicaster-uuid": undefined,
|
|
36
46
|
};
|
|
37
47
|
|
|
38
48
|
const headers = getAppDataHeaders(screenId);
|
package/headersUtils/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
|
|
2
2
|
import { getPlatform } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
3
3
|
import { utilsLogger } from "../logger";
|
|
4
|
+
import { getUILanguage } from "../localizationUtils";
|
|
4
5
|
|
|
5
6
|
const logger = utilsLogger.addSubsystem("headersUtils");
|
|
6
7
|
|
|
@@ -21,7 +22,7 @@ export const getAppDataHeaders = (screenId: string) => {
|
|
|
21
22
|
"x-applicaster-layout-id":
|
|
22
23
|
appData.riversConfigurationId || appData.rivers_configuration_id,
|
|
23
24
|
"x-applicaster-screen-id": screenId,
|
|
24
|
-
"x-applicaster-language-code":
|
|
25
|
+
"x-applicaster-language-code": getUILanguage(),
|
|
25
26
|
"x-applicaster-version-number": appData.version_name || appData.versionName,
|
|
26
27
|
"x-applicaster-platform": (platform || appData.platform).toLowerCase(),
|
|
27
28
|
"x-applicaster-country-code": appData.countryCode,
|
|
@@ -331,6 +331,35 @@ function getPlayerConfiguration({ platform, version }) {
|
|
|
331
331
|
label_tooltip: "Hint for skip intro button accessibility",
|
|
332
332
|
type: "text_input",
|
|
333
333
|
},
|
|
334
|
+
{
|
|
335
|
+
type: "text_input",
|
|
336
|
+
label: "Text Tracks Label",
|
|
337
|
+
key: "text_tracks_label",
|
|
338
|
+
initial_value: "Subtitles",
|
|
339
|
+
label_tooltip: "Label for the text tracks list",
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
type: "text_input",
|
|
343
|
+
label: "Audio Tracks Label",
|
|
344
|
+
key: "audio_tracks_label",
|
|
345
|
+
initial_value: "Audio",
|
|
346
|
+
label_tooltip: "Label for the audio tracks list",
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
type: "text_input",
|
|
350
|
+
label: "Off Track Label",
|
|
351
|
+
key: "off_track_label",
|
|
352
|
+
initial_value: "Off",
|
|
353
|
+
label_tooltip: "Label for the 'Off' option in text tracks list",
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
type: "text_input",
|
|
357
|
+
label: "Default Track Label",
|
|
358
|
+
key: "default_track_label",
|
|
359
|
+
initial_value: "Default",
|
|
360
|
+
label_tooltip:
|
|
361
|
+
"Label for the 'Default' audio track in audio tracks list",
|
|
362
|
+
},
|
|
334
363
|
],
|
|
335
364
|
};
|
|
336
365
|
|
package/navigationUtils/index.ts
CHANGED
|
@@ -5,7 +5,8 @@ import { layoutV2TypeMatcher } from "./layoutV2TypeMatcher";
|
|
|
5
5
|
import { HOOKS_EVENTS } from "../appUtils/HooksManager/constants";
|
|
6
6
|
import { HooksManager } from "../appUtils/HooksManager";
|
|
7
7
|
import { appStore } from "@applicaster/zapp-react-native-redux/AppStore";
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
import { zappHookModalStore } from "@applicaster/zapp-react-native-ui-components/Contexts/ZappHookModalContext";
|
|
9
10
|
import { logger } from "@applicaster/zapp-react-native-utils/logger";
|
|
10
11
|
import {
|
|
11
12
|
isGeneralPlugin,
|
|
@@ -15,6 +16,8 @@ import {
|
|
|
15
16
|
} from "./itemTypeMatchers";
|
|
16
17
|
import { RootState } from "@applicaster/zapp-react-native-redux/store";
|
|
17
18
|
|
|
19
|
+
import { pick } from "@applicaster/zapp-react-native-utils/utils";
|
|
20
|
+
|
|
18
21
|
type PathAttribute = {
|
|
19
22
|
screenType: string;
|
|
20
23
|
screenId: string;
|
|
@@ -403,15 +406,22 @@ export const mapContentTypesToRivers = (
|
|
|
403
406
|
};
|
|
404
407
|
|
|
405
408
|
export const runZappHooksForEntry = async (
|
|
406
|
-
entry: HookPluginProps["payload"]
|
|
407
|
-
|
|
409
|
+
entry: HookPluginProps["payload"]
|
|
410
|
+
): Promise<{ success: boolean; payload: ZappEntry }> => {
|
|
411
|
+
const {
|
|
408
412
|
setState,
|
|
409
413
|
resetState,
|
|
410
414
|
setIsHooksExecutionInProgress,
|
|
411
415
|
setIsPresentingFullScreen,
|
|
412
416
|
setIsRunningInBackground,
|
|
413
|
-
}
|
|
414
|
-
|
|
417
|
+
} = pick(zappHookModalStore.getState(), [
|
|
418
|
+
"setState",
|
|
419
|
+
"resetState",
|
|
420
|
+
"setIsHooksExecutionInProgress",
|
|
421
|
+
"setIsPresentingFullScreen",
|
|
422
|
+
"setIsRunningInBackground",
|
|
423
|
+
]);
|
|
424
|
+
|
|
415
425
|
resetState?.();
|
|
416
426
|
|
|
417
427
|
let success;
|
|
@@ -11,6 +11,16 @@ describe("toNumber", () => {
|
|
|
11
11
|
});
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
+
it("return number if input is BigInt", () => {
|
|
15
|
+
const inputs = [5n, -5n];
|
|
16
|
+
expect.assertions(inputs.length);
|
|
17
|
+
|
|
18
|
+
inputs.forEach((input) => {
|
|
19
|
+
const output = toNumber(input);
|
|
20
|
+
expect(output).toBe(Number(input));
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
14
24
|
it("return number if input is string as number", () => {
|
|
15
25
|
const inputs = ["-1", "0", "1", "100", "0.2"];
|
|
16
26
|
expect.assertions(inputs.length);
|
|
@@ -32,6 +42,8 @@ describe("toNumber", () => {
|
|
|
32
42
|
{ test: 1 },
|
|
33
43
|
[],
|
|
34
44
|
[1],
|
|
45
|
+
"5n",
|
|
46
|
+
"-5n",
|
|
35
47
|
];
|
|
36
48
|
|
|
37
49
|
expect.assertions(inputs.length);
|