@applicaster/zapp-react-native-utils 15.0.0-rc.94 → 15.0.0-rc.96
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/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/cloudEventsUtils/__tests__/index.test.ts +529 -0
- package/cloudEventsUtils/index.ts +65 -1
- 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/package.json +2 -2
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import { HttpStatusCode, HttpStatusCodeHelper } from "../HttpStatusCode";
|
|
2
|
+
|
|
3
|
+
describe("HttpStatusCode", () => {
|
|
4
|
+
describe("enum values", () => {
|
|
5
|
+
it("should have correct informational status codes", () => {
|
|
6
|
+
expect(HttpStatusCode.Continue).toBe(100);
|
|
7
|
+
expect(HttpStatusCode.SwitchingProtocols).toBe(101);
|
|
8
|
+
expect(HttpStatusCode.Processing).toBe(102);
|
|
9
|
+
expect(HttpStatusCode.EarlyHints).toBe(103);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("should have correct success status codes", () => {
|
|
13
|
+
expect(HttpStatusCode.Ok).toBe(200);
|
|
14
|
+
expect(HttpStatusCode.Created).toBe(201);
|
|
15
|
+
expect(HttpStatusCode.Accepted).toBe(202);
|
|
16
|
+
expect(HttpStatusCode.NoContent).toBe(204);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("should have correct redirection status codes", () => {
|
|
20
|
+
expect(HttpStatusCode.MovedPermanently).toBe(301);
|
|
21
|
+
expect(HttpStatusCode.Found).toBe(302);
|
|
22
|
+
expect(HttpStatusCode.SeeOther).toBe(303);
|
|
23
|
+
expect(HttpStatusCode.NotModified).toBe(304);
|
|
24
|
+
expect(HttpStatusCode.TemporaryRedirect).toBe(307);
|
|
25
|
+
expect(HttpStatusCode.PermanentRedirect).toBe(308);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("should have correct client error status codes", () => {
|
|
29
|
+
expect(HttpStatusCode.BadRequest).toBe(400);
|
|
30
|
+
expect(HttpStatusCode.Unauthorized).toBe(401);
|
|
31
|
+
expect(HttpStatusCode.PaymentRequired).toBe(402);
|
|
32
|
+
expect(HttpStatusCode.Forbidden).toBe(403);
|
|
33
|
+
expect(HttpStatusCode.NotFound).toBe(404);
|
|
34
|
+
expect(HttpStatusCode.MethodNotAllowed).toBe(405);
|
|
35
|
+
expect(HttpStatusCode.RequestTimeout).toBe(408);
|
|
36
|
+
expect(HttpStatusCode.Conflict).toBe(409);
|
|
37
|
+
expect(HttpStatusCode.Gone).toBe(410);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("should have correct server error status codes", () => {
|
|
41
|
+
expect(HttpStatusCode.InternalServerError).toBe(500);
|
|
42
|
+
expect(HttpStatusCode.NotImplemented).toBe(501);
|
|
43
|
+
expect(HttpStatusCode.BadGateway).toBe(502);
|
|
44
|
+
expect(HttpStatusCode.ServiceUnavailable).toBe(503);
|
|
45
|
+
expect(HttpStatusCode.GatewayTimeout).toBe(504);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("should have special status codes", () => {
|
|
49
|
+
expect(HttpStatusCode.ImATeapot).toBe(418);
|
|
50
|
+
expect(HttpStatusCode.TooManyRequests).toBe(429);
|
|
51
|
+
expect(HttpStatusCode.UnavailableForLegalReasons).toBe(451);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe("HttpStatusCodeHelper", () => {
|
|
57
|
+
describe("fromStatusCode", () => {
|
|
58
|
+
it("should return -1 for null status code", () => {
|
|
59
|
+
expect(HttpStatusCodeHelper.fromStatusCode(null as any)).toBe(-1);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("should return -1 for undefined status code", () => {
|
|
63
|
+
expect(HttpStatusCodeHelper.fromStatusCode(undefined as any)).toBe(-1);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("should return -1 for 0 status code", () => {
|
|
67
|
+
expect(HttpStatusCodeHelper.fromStatusCode(0)).toBe(-1);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("should return correct HttpStatusCode for valid status codes", () => {
|
|
71
|
+
expect(HttpStatusCodeHelper.fromStatusCode(200)).toBe(HttpStatusCode.Ok);
|
|
72
|
+
|
|
73
|
+
expect(HttpStatusCodeHelper.fromStatusCode(201)).toBe(
|
|
74
|
+
HttpStatusCode.Created
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
expect(HttpStatusCodeHelper.fromStatusCode(400)).toBe(
|
|
78
|
+
HttpStatusCode.BadRequest
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
expect(HttpStatusCodeHelper.fromStatusCode(401)).toBe(
|
|
82
|
+
HttpStatusCode.Unauthorized
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
expect(HttpStatusCodeHelper.fromStatusCode(404)).toBe(
|
|
86
|
+
HttpStatusCode.NotFound
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
expect(HttpStatusCodeHelper.fromStatusCode(500)).toBe(
|
|
90
|
+
HttpStatusCode.InternalServerError
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("should return the status code itself for unknown codes", () => {
|
|
95
|
+
expect(HttpStatusCodeHelper.fromStatusCode(999)).toBe(999);
|
|
96
|
+
expect(HttpStatusCodeHelper.fromStatusCode(123)).toBe(123);
|
|
97
|
+
expect(HttpStatusCodeHelper.fromStatusCode(600)).toBe(600);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("should handle all standard HTTP status codes", () => {
|
|
101
|
+
const standardCodes = [
|
|
102
|
+
100, 101, 102, 103, 200, 201, 202, 203, 204, 205, 206, 207, 208, 226,
|
|
103
|
+
300, 301, 302, 303, 304, 305, 306, 307, 308, 400, 401, 402, 403, 404,
|
|
104
|
+
405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418,
|
|
105
|
+
421, 422, 423, 424, 425, 426, 428, 429, 431, 451, 500, 501, 502, 503,
|
|
106
|
+
504, 505, 506, 507, 508, 510, 511,
|
|
107
|
+
];
|
|
108
|
+
|
|
109
|
+
standardCodes.forEach((code) => {
|
|
110
|
+
const result = HttpStatusCodeHelper.fromStatusCode(code);
|
|
111
|
+
expect(result).toBe(code);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe("informational", () => {
|
|
117
|
+
it("should return true for 1xx status codes", () => {
|
|
118
|
+
expect(HttpStatusCodeHelper.informational(HttpStatusCode.Continue)).toBe(
|
|
119
|
+
true
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
expect(
|
|
123
|
+
HttpStatusCodeHelper.informational(HttpStatusCode.SwitchingProtocols)
|
|
124
|
+
).toBe(true);
|
|
125
|
+
|
|
126
|
+
expect(
|
|
127
|
+
HttpStatusCodeHelper.informational(HttpStatusCode.Processing)
|
|
128
|
+
).toBe(true);
|
|
129
|
+
|
|
130
|
+
expect(
|
|
131
|
+
HttpStatusCodeHelper.informational(HttpStatusCode.EarlyHints)
|
|
132
|
+
).toBe(true);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("should return false for non-1xx status codes", () => {
|
|
136
|
+
expect(HttpStatusCodeHelper.informational(HttpStatusCode.Ok)).toBe(false);
|
|
137
|
+
|
|
138
|
+
expect(
|
|
139
|
+
HttpStatusCodeHelper.informational(HttpStatusCode.MovedPermanently)
|
|
140
|
+
).toBe(false);
|
|
141
|
+
|
|
142
|
+
expect(
|
|
143
|
+
HttpStatusCodeHelper.informational(HttpStatusCode.BadRequest)
|
|
144
|
+
).toBe(false);
|
|
145
|
+
|
|
146
|
+
expect(
|
|
147
|
+
HttpStatusCodeHelper.informational(HttpStatusCode.InternalServerError)
|
|
148
|
+
).toBe(false);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
describe("successful", () => {
|
|
153
|
+
it("should return true for 2xx status codes", () => {
|
|
154
|
+
expect(HttpStatusCodeHelper.successful(HttpStatusCode.Ok)).toBe(true);
|
|
155
|
+
|
|
156
|
+
expect(HttpStatusCodeHelper.successful(HttpStatusCode.Created)).toBe(
|
|
157
|
+
true
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
expect(HttpStatusCodeHelper.successful(HttpStatusCode.Accepted)).toBe(
|
|
161
|
+
true
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
expect(HttpStatusCodeHelper.successful(HttpStatusCode.NoContent)).toBe(
|
|
165
|
+
true
|
|
166
|
+
);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("should return false for non-2xx status codes", () => {
|
|
170
|
+
expect(HttpStatusCodeHelper.successful(HttpStatusCode.Continue)).toBe(
|
|
171
|
+
false
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
expect(
|
|
175
|
+
HttpStatusCodeHelper.successful(HttpStatusCode.MovedPermanently)
|
|
176
|
+
).toBe(false);
|
|
177
|
+
|
|
178
|
+
expect(HttpStatusCodeHelper.successful(HttpStatusCode.BadRequest)).toBe(
|
|
179
|
+
false
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
expect(
|
|
183
|
+
HttpStatusCodeHelper.successful(HttpStatusCode.InternalServerError)
|
|
184
|
+
).toBe(false);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
describe("redirection", () => {
|
|
189
|
+
it("should return true for 3xx status codes", () => {
|
|
190
|
+
expect(
|
|
191
|
+
HttpStatusCodeHelper.redirection(HttpStatusCode.MovedPermanently)
|
|
192
|
+
).toBe(true);
|
|
193
|
+
|
|
194
|
+
expect(HttpStatusCodeHelper.redirection(HttpStatusCode.Found)).toBe(true);
|
|
195
|
+
|
|
196
|
+
expect(HttpStatusCodeHelper.redirection(HttpStatusCode.SeeOther)).toBe(
|
|
197
|
+
true
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
expect(HttpStatusCodeHelper.redirection(HttpStatusCode.NotModified)).toBe(
|
|
201
|
+
true
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
expect(
|
|
205
|
+
HttpStatusCodeHelper.redirection(HttpStatusCode.TemporaryRedirect)
|
|
206
|
+
).toBe(true);
|
|
207
|
+
|
|
208
|
+
expect(
|
|
209
|
+
HttpStatusCodeHelper.redirection(HttpStatusCode.PermanentRedirect)
|
|
210
|
+
).toBe(true);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it("should return false for non-3xx status codes", () => {
|
|
214
|
+
expect(HttpStatusCodeHelper.redirection(HttpStatusCode.Ok)).toBe(false);
|
|
215
|
+
|
|
216
|
+
expect(HttpStatusCodeHelper.redirection(HttpStatusCode.BadRequest)).toBe(
|
|
217
|
+
false
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
expect(
|
|
221
|
+
HttpStatusCodeHelper.redirection(HttpStatusCode.InternalServerError)
|
|
222
|
+
).toBe(false);
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
describe("clientError", () => {
|
|
227
|
+
it("should return true for 4xx status codes", () => {
|
|
228
|
+
expect(HttpStatusCodeHelper.clientError(HttpStatusCode.BadRequest)).toBe(
|
|
229
|
+
true
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
expect(
|
|
233
|
+
HttpStatusCodeHelper.clientError(HttpStatusCode.Unauthorized)
|
|
234
|
+
).toBe(true);
|
|
235
|
+
|
|
236
|
+
expect(HttpStatusCodeHelper.clientError(HttpStatusCode.Forbidden)).toBe(
|
|
237
|
+
true
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
expect(HttpStatusCodeHelper.clientError(HttpStatusCode.NotFound)).toBe(
|
|
241
|
+
true
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
expect(
|
|
245
|
+
HttpStatusCodeHelper.clientError(HttpStatusCode.TooManyRequests)
|
|
246
|
+
).toBe(true);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it("should return false for non-4xx status codes", () => {
|
|
250
|
+
expect(HttpStatusCodeHelper.clientError(HttpStatusCode.Ok)).toBe(false);
|
|
251
|
+
|
|
252
|
+
expect(
|
|
253
|
+
HttpStatusCodeHelper.clientError(HttpStatusCode.MovedPermanently)
|
|
254
|
+
).toBe(false);
|
|
255
|
+
|
|
256
|
+
expect(
|
|
257
|
+
HttpStatusCodeHelper.clientError(HttpStatusCode.InternalServerError)
|
|
258
|
+
).toBe(false);
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
describe("serverError", () => {
|
|
263
|
+
it("should return true for 5xx status codes", () => {
|
|
264
|
+
expect(
|
|
265
|
+
HttpStatusCodeHelper.serverError(HttpStatusCode.InternalServerError)
|
|
266
|
+
).toBe(true);
|
|
267
|
+
|
|
268
|
+
expect(
|
|
269
|
+
HttpStatusCodeHelper.serverError(HttpStatusCode.NotImplemented)
|
|
270
|
+
).toBe(true);
|
|
271
|
+
|
|
272
|
+
expect(HttpStatusCodeHelper.serverError(HttpStatusCode.BadGateway)).toBe(
|
|
273
|
+
true
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
expect(
|
|
277
|
+
HttpStatusCodeHelper.serverError(HttpStatusCode.ServiceUnavailable)
|
|
278
|
+
).toBe(true);
|
|
279
|
+
|
|
280
|
+
expect(
|
|
281
|
+
HttpStatusCodeHelper.serverError(HttpStatusCode.GatewayTimeout)
|
|
282
|
+
).toBe(true);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it("should return false for non-5xx status codes", () => {
|
|
286
|
+
expect(HttpStatusCodeHelper.serverError(HttpStatusCode.Ok)).toBe(false);
|
|
287
|
+
|
|
288
|
+
expect(
|
|
289
|
+
HttpStatusCodeHelper.serverError(HttpStatusCode.MovedPermanently)
|
|
290
|
+
).toBe(false);
|
|
291
|
+
|
|
292
|
+
expect(HttpStatusCodeHelper.serverError(HttpStatusCode.BadRequest)).toBe(
|
|
293
|
+
false
|
|
294
|
+
);
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
describe("category helpers edge cases", () => {
|
|
299
|
+
it("should handle boundaries correctly", () => {
|
|
300
|
+
// 100 is the first informational code
|
|
301
|
+
expect(HttpStatusCodeHelper.informational(100 as HttpStatusCode)).toBe(
|
|
302
|
+
true
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
expect(HttpStatusCodeHelper.informational(99 as HttpStatusCode)).toBe(
|
|
306
|
+
false
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
// 200 is the first successful code
|
|
310
|
+
expect(HttpStatusCodeHelper.successful(200 as HttpStatusCode)).toBe(true);
|
|
311
|
+
|
|
312
|
+
expect(HttpStatusCodeHelper.successful(199 as HttpStatusCode)).toBe(
|
|
313
|
+
false
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
// 300 is the first redirection code
|
|
317
|
+
expect(HttpStatusCodeHelper.redirection(300 as HttpStatusCode)).toBe(
|
|
318
|
+
true
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
expect(HttpStatusCodeHelper.redirection(299 as HttpStatusCode)).toBe(
|
|
322
|
+
false
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
// 400 is the first client error code
|
|
326
|
+
expect(HttpStatusCodeHelper.clientError(400 as HttpStatusCode)).toBe(
|
|
327
|
+
true
|
|
328
|
+
);
|
|
329
|
+
|
|
330
|
+
expect(HttpStatusCodeHelper.clientError(399 as HttpStatusCode)).toBe(
|
|
331
|
+
false
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
// 500 is the first server error code
|
|
335
|
+
expect(HttpStatusCodeHelper.serverError(500 as HttpStatusCode)).toBe(
|
|
336
|
+
true
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
expect(HttpStatusCodeHelper.serverError(499 as HttpStatusCode)).toBe(
|
|
340
|
+
false
|
|
341
|
+
);
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
});
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { MissingPluginError } from "../MissingPluginError";
|
|
2
|
+
import * as ERROR_CODES from "../errorCodes";
|
|
3
|
+
|
|
4
|
+
describe("MissingPluginError", () => {
|
|
5
|
+
it("should create error with plugin identifier", () => {
|
|
6
|
+
const identifier = "com.example.myplugin";
|
|
7
|
+
const error = new MissingPluginError(identifier);
|
|
8
|
+
|
|
9
|
+
expect(error).toBeInstanceOf(Error);
|
|
10
|
+
expect(error).toBeInstanceOf(MissingPluginError);
|
|
11
|
+
expect(error.message).toContain(identifier);
|
|
12
|
+
expect(error.code).toBe(ERROR_CODES.MISSING_PLUGIN);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("should include error code in message", () => {
|
|
16
|
+
const identifier = "video-player";
|
|
17
|
+
const error = new MissingPluginError(identifier);
|
|
18
|
+
|
|
19
|
+
expect(error.message).toContain(ERROR_CODES.MISSING_PLUGIN);
|
|
20
|
+
expect(error.message).toContain("Error code:");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("should include descriptive message", () => {
|
|
24
|
+
const identifier = "analytics-plugin";
|
|
25
|
+
const error = new MissingPluginError(identifier);
|
|
26
|
+
|
|
27
|
+
expect(error.message).toContain("Cannot find");
|
|
28
|
+
expect(error.message).toContain("plugin");
|
|
29
|
+
|
|
30
|
+
expect(error.message).toContain(
|
|
31
|
+
"Please make sure the plugin is properly added"
|
|
32
|
+
);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("should have correct error code property", () => {
|
|
36
|
+
const error = new MissingPluginError("test-plugin");
|
|
37
|
+
|
|
38
|
+
expect(error.code).toBe("MISSING_PLUGIN");
|
|
39
|
+
expect(error.code).toBe(ERROR_CODES.MISSING_PLUGIN);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("should be throwable and catchable", () => {
|
|
43
|
+
const identifier = "missing-plugin";
|
|
44
|
+
|
|
45
|
+
expect(() => {
|
|
46
|
+
throw new MissingPluginError(identifier);
|
|
47
|
+
}).toThrow(MissingPluginError);
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
throw new MissingPluginError(identifier);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
expect(error).toBeInstanceOf(MissingPluginError);
|
|
53
|
+
|
|
54
|
+
expect((error as MissingPluginError).code).toBe(
|
|
55
|
+
ERROR_CODES.MISSING_PLUGIN
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("should handle various identifier formats", () => {
|
|
61
|
+
const identifiers = [
|
|
62
|
+
"com.applicaster.plugin",
|
|
63
|
+
"my-plugin-123",
|
|
64
|
+
"plugin_name",
|
|
65
|
+
"Plugin Name With Spaces",
|
|
66
|
+
"123",
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
identifiers.forEach((identifier) => {
|
|
70
|
+
const error = new MissingPluginError(identifier);
|
|
71
|
+
expect(error.message).toContain(identifier);
|
|
72
|
+
expect(error.code).toBe(ERROR_CODES.MISSING_PLUGIN);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("should maintain stack trace", () => {
|
|
77
|
+
const error = new MissingPluginError("stack-test-plugin");
|
|
78
|
+
|
|
79
|
+
expect(error.stack).toBeDefined();
|
|
80
|
+
expect(error.stack).toContain("stack-test-plugin");
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("should handle null identifier", () => {
|
|
84
|
+
const error = new MissingPluginError(null as any);
|
|
85
|
+
|
|
86
|
+
expect(error.message).toContain("null");
|
|
87
|
+
expect(error.code).toBe(ERROR_CODES.MISSING_PLUGIN);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("should handle undefined identifier", () => {
|
|
91
|
+
const error = new MissingPluginError(undefined as any);
|
|
92
|
+
|
|
93
|
+
expect(error.message).toContain("undefined");
|
|
94
|
+
expect(error.code).toBe(ERROR_CODES.MISSING_PLUGIN);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("should handle empty string identifier", () => {
|
|
98
|
+
const error = new MissingPluginError("");
|
|
99
|
+
|
|
100
|
+
expect(error.message).toBeDefined();
|
|
101
|
+
expect(error.code).toBe(ERROR_CODES.MISSING_PLUGIN);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("should be distinguishable from other errors", () => {
|
|
105
|
+
const missingPluginError = new MissingPluginError("test");
|
|
106
|
+
const regularError = new Error("test");
|
|
107
|
+
const customError = { code: "MISSING_PLUGIN", message: "test" };
|
|
108
|
+
|
|
109
|
+
expect(missingPluginError).toBeInstanceOf(MissingPluginError);
|
|
110
|
+
expect(regularError).not.toBeInstanceOf(MissingPluginError);
|
|
111
|
+
expect(customError).not.toBeInstanceOf(MissingPluginError);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
@@ -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
|
+
});
|