@object-ui/data-objectstack 0.3.0 → 0.5.0
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/README.md +317 -1
- package/dist/index.cjs +649 -34
- package/dist/index.d.cts +267 -7
- package/dist/index.d.ts +267 -7
- package/dist/index.js +639 -33
- package/package.json +4 -4
- package/src/cache/MetadataCache.test.ts +426 -0
- package/src/cache/MetadataCache.ts +229 -0
- package/src/connection.test.ts +100 -0
- package/src/errors.test.ts +426 -0
- package/src/errors.ts +275 -0
- package/src/index.ts +463 -42
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI
|
|
3
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
10
|
+
import { ObjectStackAdapter, ConnectionState, ConnectionStateEvent, BatchProgressEvent } from './index';
|
|
11
|
+
|
|
12
|
+
describe('Connection State Monitoring', () => {
|
|
13
|
+
let adapter: ObjectStackAdapter;
|
|
14
|
+
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
adapter = new ObjectStackAdapter({
|
|
17
|
+
baseUrl: 'http://localhost:3000',
|
|
18
|
+
autoReconnect: false, // Disable auto-reconnect for testing
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('should initialize with disconnected state', () => {
|
|
23
|
+
expect(adapter.getConnectionState()).toBe('disconnected');
|
|
24
|
+
expect(adapter.isConnected()).toBe(false);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should allow subscribing to connection state changes', () => {
|
|
28
|
+
const listener = vi.fn();
|
|
29
|
+
const unsubscribe = adapter.onConnectionStateChange(listener);
|
|
30
|
+
|
|
31
|
+
expect(typeof unsubscribe).toBe('function');
|
|
32
|
+
expect(listener).not.toHaveBeenCalled();
|
|
33
|
+
|
|
34
|
+
// Cleanup
|
|
35
|
+
unsubscribe();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should allow subscribing to batch progress events', () => {
|
|
39
|
+
const listener = vi.fn();
|
|
40
|
+
const unsubscribe = adapter.onBatchProgress(listener);
|
|
41
|
+
|
|
42
|
+
expect(typeof unsubscribe).toBe('function');
|
|
43
|
+
expect(listener).not.toHaveBeenCalled();
|
|
44
|
+
|
|
45
|
+
// Cleanup
|
|
46
|
+
unsubscribe();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should unsubscribe connection state listener', () => {
|
|
50
|
+
const listener = vi.fn();
|
|
51
|
+
const unsubscribe = adapter.onConnectionStateChange(listener);
|
|
52
|
+
|
|
53
|
+
// Unsubscribe
|
|
54
|
+
unsubscribe();
|
|
55
|
+
|
|
56
|
+
// Listener should not be called after unsubscribe
|
|
57
|
+
// (We can't easily test this without triggering a connection state change)
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should unsubscribe batch progress listener', () => {
|
|
61
|
+
const listener = vi.fn();
|
|
62
|
+
const unsubscribe = adapter.onBatchProgress(listener);
|
|
63
|
+
|
|
64
|
+
// Unsubscribe
|
|
65
|
+
unsubscribe();
|
|
66
|
+
|
|
67
|
+
// Listener should not be called after unsubscribe
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should support auto-reconnect configuration', () => {
|
|
71
|
+
const adapterWithReconnect = new ObjectStackAdapter({
|
|
72
|
+
baseUrl: 'http://localhost:3000',
|
|
73
|
+
autoReconnect: true,
|
|
74
|
+
maxReconnectAttempts: 5,
|
|
75
|
+
reconnectDelay: 2000,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
expect(adapterWithReconnect.getConnectionState()).toBe('disconnected');
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe('Batch Progress Events', () => {
|
|
83
|
+
let adapter: ObjectStackAdapter;
|
|
84
|
+
|
|
85
|
+
beforeEach(() => {
|
|
86
|
+
adapter = new ObjectStackAdapter({
|
|
87
|
+
baseUrl: 'http://localhost:3000',
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('should allow subscribing to batch progress', () => {
|
|
92
|
+
const listener = vi.fn();
|
|
93
|
+
const unsubscribe = adapter.onBatchProgress(listener);
|
|
94
|
+
|
|
95
|
+
expect(typeof unsubscribe).toBe('function');
|
|
96
|
+
|
|
97
|
+
// Cleanup
|
|
98
|
+
unsubscribe();
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI
|
|
3
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, it, expect } from 'vitest';
|
|
10
|
+
import {
|
|
11
|
+
ObjectStackError,
|
|
12
|
+
MetadataNotFoundError,
|
|
13
|
+
BulkOperationError,
|
|
14
|
+
ConnectionError,
|
|
15
|
+
AuthenticationError,
|
|
16
|
+
ValidationError,
|
|
17
|
+
createErrorFromResponse,
|
|
18
|
+
isObjectStackError,
|
|
19
|
+
isErrorType,
|
|
20
|
+
} from './errors';
|
|
21
|
+
|
|
22
|
+
describe('Error Classes', () => {
|
|
23
|
+
describe('ObjectStackError', () => {
|
|
24
|
+
it('should create base error with all properties', () => {
|
|
25
|
+
const error = new ObjectStackError(
|
|
26
|
+
'Test error',
|
|
27
|
+
'TEST_ERROR',
|
|
28
|
+
500,
|
|
29
|
+
{ extra: 'info' }
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
expect(error.message).toBe('Test error');
|
|
33
|
+
expect(error.code).toBe('TEST_ERROR');
|
|
34
|
+
expect(error.statusCode).toBe(500);
|
|
35
|
+
expect(error.details).toEqual({ extra: 'info' });
|
|
36
|
+
expect(error.name).toBe('ObjectStackError');
|
|
37
|
+
expect(error).toBeInstanceOf(Error);
|
|
38
|
+
expect(error).toBeInstanceOf(ObjectStackError);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should work without optional parameters', () => {
|
|
42
|
+
const error = new ObjectStackError('Test error', 'TEST_ERROR');
|
|
43
|
+
|
|
44
|
+
expect(error.message).toBe('Test error');
|
|
45
|
+
expect(error.code).toBe('TEST_ERROR');
|
|
46
|
+
expect(error.statusCode).toBeUndefined();
|
|
47
|
+
expect(error.details).toBeUndefined();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should convert to JSON correctly', () => {
|
|
51
|
+
const error = new ObjectStackError(
|
|
52
|
+
'Test error',
|
|
53
|
+
'TEST_ERROR',
|
|
54
|
+
500,
|
|
55
|
+
{ extra: 'info' }
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const json = error.toJSON();
|
|
59
|
+
expect(json).toHaveProperty('name', 'ObjectStackError');
|
|
60
|
+
expect(json).toHaveProperty('message', 'Test error');
|
|
61
|
+
expect(json).toHaveProperty('code', 'TEST_ERROR');
|
|
62
|
+
expect(json).toHaveProperty('statusCode', 500);
|
|
63
|
+
expect(json).toHaveProperty('details', { extra: 'info' });
|
|
64
|
+
expect(json).toHaveProperty('stack');
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('should maintain proper stack trace', () => {
|
|
68
|
+
const error = new ObjectStackError('Test error', 'TEST_ERROR');
|
|
69
|
+
expect(error.stack).toBeDefined();
|
|
70
|
+
expect(error.stack).toContain('ObjectStackError');
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
describe('MetadataNotFoundError', () => {
|
|
75
|
+
it('should create metadata not found error', () => {
|
|
76
|
+
const error = new MetadataNotFoundError('users');
|
|
77
|
+
|
|
78
|
+
expect(error.message).toBe('Metadata not found for object: users');
|
|
79
|
+
expect(error.code).toBe('METADATA_NOT_FOUND');
|
|
80
|
+
expect(error.statusCode).toBe(404);
|
|
81
|
+
expect(error.name).toBe('MetadataNotFoundError');
|
|
82
|
+
expect(error.details).toHaveProperty('objectName', 'users');
|
|
83
|
+
expect(error).toBeInstanceOf(ObjectStackError);
|
|
84
|
+
expect(error).toBeInstanceOf(MetadataNotFoundError);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should include additional details', () => {
|
|
88
|
+
const error = new MetadataNotFoundError('users', { reason: 'Schema not loaded' });
|
|
89
|
+
|
|
90
|
+
expect(error.details).toEqual({
|
|
91
|
+
objectName: 'users',
|
|
92
|
+
reason: 'Schema not loaded',
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
describe('BulkOperationError', () => {
|
|
98
|
+
it('should create bulk operation error', () => {
|
|
99
|
+
const errors = [
|
|
100
|
+
{ index: 0, error: 'Invalid data' },
|
|
101
|
+
{ index: 2, error: 'Duplicate key' },
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
const error = new BulkOperationError('create', 8, 2, errors);
|
|
105
|
+
|
|
106
|
+
expect(error.message).toBe('Bulk create operation failed: 8 succeeded, 2 failed');
|
|
107
|
+
expect(error.code).toBe('BULK_OPERATION_ERROR');
|
|
108
|
+
expect(error.statusCode).toBe(500);
|
|
109
|
+
expect(error.name).toBe('BulkOperationError');
|
|
110
|
+
expect(error.successCount).toBe(8);
|
|
111
|
+
expect(error.failureCount).toBe(2);
|
|
112
|
+
expect(error.errors).toEqual(errors);
|
|
113
|
+
expect(error).toBeInstanceOf(ObjectStackError);
|
|
114
|
+
expect(error).toBeInstanceOf(BulkOperationError);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('should provide operation summary', () => {
|
|
118
|
+
const errors = [{ index: 0, error: 'Error' }];
|
|
119
|
+
const error = new BulkOperationError('update', 9, 1, errors);
|
|
120
|
+
|
|
121
|
+
const summary = error.getSummary();
|
|
122
|
+
expect(summary).toEqual({
|
|
123
|
+
operation: 'update',
|
|
124
|
+
total: 10,
|
|
125
|
+
successful: 9,
|
|
126
|
+
failed: 1,
|
|
127
|
+
failureRate: 0.1,
|
|
128
|
+
errors: errors,
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('should handle different operation types', () => {
|
|
133
|
+
const createError = new BulkOperationError('create', 5, 0, []);
|
|
134
|
+
const updateError = new BulkOperationError('update', 3, 2, []);
|
|
135
|
+
const deleteError = new BulkOperationError('delete', 10, 1, []);
|
|
136
|
+
|
|
137
|
+
expect(createError.message).toContain('create');
|
|
138
|
+
expect(updateError.message).toContain('update');
|
|
139
|
+
expect(deleteError.message).toContain('delete');
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
describe('ConnectionError', () => {
|
|
144
|
+
it('should create connection error', () => {
|
|
145
|
+
const error = new ConnectionError(
|
|
146
|
+
'Network timeout',
|
|
147
|
+
'https://api.example.com'
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
expect(error.message).toBe('Connection error: Network timeout');
|
|
151
|
+
expect(error.code).toBe('CONNECTION_ERROR');
|
|
152
|
+
expect(error.statusCode).toBe(503);
|
|
153
|
+
expect(error.name).toBe('ConnectionError');
|
|
154
|
+
expect(error.url).toBe('https://api.example.com');
|
|
155
|
+
expect(error).toBeInstanceOf(ObjectStackError);
|
|
156
|
+
expect(error).toBeInstanceOf(ConnectionError);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('should work without URL', () => {
|
|
160
|
+
const error = new ConnectionError('Network timeout');
|
|
161
|
+
|
|
162
|
+
expect(error.url).toBeUndefined();
|
|
163
|
+
expect(error.message).toBe('Connection error: Network timeout');
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
describe('AuthenticationError', () => {
|
|
168
|
+
it('should create authentication error', () => {
|
|
169
|
+
const error = new AuthenticationError();
|
|
170
|
+
|
|
171
|
+
expect(error.message).toBe('Authentication failed');
|
|
172
|
+
expect(error.code).toBe('AUTHENTICATION_ERROR');
|
|
173
|
+
expect(error.statusCode).toBe(401);
|
|
174
|
+
expect(error.name).toBe('AuthenticationError');
|
|
175
|
+
expect(error).toBeInstanceOf(ObjectStackError);
|
|
176
|
+
expect(error).toBeInstanceOf(AuthenticationError);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('should accept custom message', () => {
|
|
180
|
+
const error = new AuthenticationError('Invalid API token');
|
|
181
|
+
|
|
182
|
+
expect(error.message).toBe('Invalid API token');
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('should include additional details', () => {
|
|
186
|
+
const error = new AuthenticationError('Invalid token', { token: 'abc123' });
|
|
187
|
+
|
|
188
|
+
expect(error.details).toEqual({ token: 'abc123' });
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
describe('ValidationError', () => {
|
|
193
|
+
it('should create validation error', () => {
|
|
194
|
+
const error = new ValidationError('Invalid input');
|
|
195
|
+
|
|
196
|
+
expect(error.message).toBe('Invalid input');
|
|
197
|
+
expect(error.code).toBe('VALIDATION_ERROR');
|
|
198
|
+
expect(error.statusCode).toBe(400);
|
|
199
|
+
expect(error.name).toBe('ValidationError');
|
|
200
|
+
expect(error).toBeInstanceOf(ObjectStackError);
|
|
201
|
+
expect(error).toBeInstanceOf(ValidationError);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('should include field information', () => {
|
|
205
|
+
const error = new ValidationError('Email is invalid', 'email');
|
|
206
|
+
|
|
207
|
+
expect(error.field).toBe('email');
|
|
208
|
+
expect(error.details).toHaveProperty('field', 'email');
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('should include validation errors array', () => {
|
|
212
|
+
const validationErrors = [
|
|
213
|
+
{ field: 'email', message: 'Invalid email format' },
|
|
214
|
+
{ field: 'age', message: 'Must be a positive number' },
|
|
215
|
+
];
|
|
216
|
+
|
|
217
|
+
const error = new ValidationError(
|
|
218
|
+
'Validation failed',
|
|
219
|
+
undefined,
|
|
220
|
+
validationErrors
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
expect(error.validationErrors).toEqual(validationErrors);
|
|
224
|
+
expect(error.getValidationErrors()).toEqual(validationErrors);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('should return empty array when no validation errors', () => {
|
|
228
|
+
const error = new ValidationError('Validation failed');
|
|
229
|
+
|
|
230
|
+
expect(error.getValidationErrors()).toEqual([]);
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
describe('Error Helpers', () => {
|
|
236
|
+
describe('createErrorFromResponse', () => {
|
|
237
|
+
it('should create AuthenticationError for 401 status', () => {
|
|
238
|
+
const response = {
|
|
239
|
+
status: 401,
|
|
240
|
+
message: 'Unauthorized',
|
|
241
|
+
data: null,
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
const error = createErrorFromResponse(response, 'API request');
|
|
245
|
+
|
|
246
|
+
expect(error).toBeInstanceOf(AuthenticationError);
|
|
247
|
+
expect(error.message).toBe('Unauthorized');
|
|
248
|
+
expect(error.statusCode).toBe(401);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it('should create AuthenticationError for 403 status', () => {
|
|
252
|
+
const response = {
|
|
253
|
+
status: 403,
|
|
254
|
+
message: 'Forbidden',
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
const error = createErrorFromResponse(response);
|
|
258
|
+
|
|
259
|
+
expect(error).toBeInstanceOf(AuthenticationError);
|
|
260
|
+
expect(error.statusCode).toBe(403);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it('should create MetadataNotFoundError for 404 with metadata context', () => {
|
|
264
|
+
const response = {
|
|
265
|
+
status: 404,
|
|
266
|
+
message: 'Not found',
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
const error = createErrorFromResponse(response, 'getObjectSchema(users)');
|
|
270
|
+
|
|
271
|
+
expect(error).toBeInstanceOf(MetadataNotFoundError);
|
|
272
|
+
expect(error.statusCode).toBe(404);
|
|
273
|
+
expect((error as MetadataNotFoundError).details.objectName).toBe('users');
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
it('should create generic error for 404 without metadata context', () => {
|
|
277
|
+
const response = {
|
|
278
|
+
status: 404,
|
|
279
|
+
message: 'Not found',
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
const error = createErrorFromResponse(response, 'data request');
|
|
283
|
+
|
|
284
|
+
expect(error).toBeInstanceOf(ObjectStackError);
|
|
285
|
+
expect(error).not.toBeInstanceOf(MetadataNotFoundError);
|
|
286
|
+
expect(error.code).toBe('NOT_FOUND');
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it('should create ValidationError for 400 status', () => {
|
|
290
|
+
const response = {
|
|
291
|
+
status: 400,
|
|
292
|
+
message: 'Bad request',
|
|
293
|
+
data: {
|
|
294
|
+
errors: [
|
|
295
|
+
{ field: 'email', message: 'Invalid email' },
|
|
296
|
+
],
|
|
297
|
+
},
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
const error = createErrorFromResponse(response);
|
|
301
|
+
|
|
302
|
+
expect(error).toBeInstanceOf(ValidationError);
|
|
303
|
+
expect(error.statusCode).toBe(400);
|
|
304
|
+
expect((error as ValidationError).validationErrors).toEqual([
|
|
305
|
+
{ field: 'email', message: 'Invalid email' },
|
|
306
|
+
]);
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
it('should create ConnectionError for 503 status', () => {
|
|
310
|
+
const response = {
|
|
311
|
+
status: 503,
|
|
312
|
+
message: 'Service unavailable',
|
|
313
|
+
config: { url: 'https://api.example.com' },
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
const error = createErrorFromResponse(response);
|
|
317
|
+
|
|
318
|
+
expect(error).toBeInstanceOf(ConnectionError);
|
|
319
|
+
expect(error.statusCode).toBe(503);
|
|
320
|
+
expect((error as ConnectionError).url).toBe('https://api.example.com');
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
it('should create ConnectionError for 504 status', () => {
|
|
324
|
+
const response = {
|
|
325
|
+
status: 504,
|
|
326
|
+
message: 'Gateway timeout',
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
const error = createErrorFromResponse(response);
|
|
330
|
+
|
|
331
|
+
expect(error).toBeInstanceOf(ConnectionError);
|
|
332
|
+
expect(error.statusCode).toBe(504);
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
it('should create generic error for unknown status', () => {
|
|
336
|
+
const response = {
|
|
337
|
+
status: 418,
|
|
338
|
+
message: "I'm a teapot",
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
const error = createErrorFromResponse(response);
|
|
342
|
+
|
|
343
|
+
expect(error).toBeInstanceOf(ObjectStackError);
|
|
344
|
+
expect(error.code).toBe('UNKNOWN_ERROR');
|
|
345
|
+
expect(error.statusCode).toBe(418);
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
it('should handle response without status code', () => {
|
|
349
|
+
const response = {
|
|
350
|
+
message: 'Unknown error',
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
const error = createErrorFromResponse(response);
|
|
354
|
+
|
|
355
|
+
expect(error).toBeInstanceOf(ObjectStackError);
|
|
356
|
+
expect(error.statusCode).toBe(500);
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
it('should include context in error details', () => {
|
|
360
|
+
const response = {
|
|
361
|
+
status: 500,
|
|
362
|
+
message: 'Server error',
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
const error = createErrorFromResponse(response, 'user creation');
|
|
366
|
+
|
|
367
|
+
expect(error.details).toHaveProperty('context', 'user creation');
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
describe('isObjectStackError', () => {
|
|
372
|
+
it('should return true for ObjectStackError instances', () => {
|
|
373
|
+
const error = new ObjectStackError('Test', 'TEST');
|
|
374
|
+
expect(isObjectStackError(error)).toBe(true);
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
it('should return true for derived error classes', () => {
|
|
378
|
+
const metadataError = new MetadataNotFoundError('users');
|
|
379
|
+
const bulkError = new BulkOperationError('create', 0, 1, []);
|
|
380
|
+
const connError = new ConnectionError('timeout');
|
|
381
|
+
const authError = new AuthenticationError();
|
|
382
|
+
const validError = new ValidationError('invalid');
|
|
383
|
+
|
|
384
|
+
expect(isObjectStackError(metadataError)).toBe(true);
|
|
385
|
+
expect(isObjectStackError(bulkError)).toBe(true);
|
|
386
|
+
expect(isObjectStackError(connError)).toBe(true);
|
|
387
|
+
expect(isObjectStackError(authError)).toBe(true);
|
|
388
|
+
expect(isObjectStackError(validError)).toBe(true);
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
it('should return false for regular Error', () => {
|
|
392
|
+
const error = new Error('Regular error');
|
|
393
|
+
expect(isObjectStackError(error)).toBe(false);
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
it('should return false for non-error values', () => {
|
|
397
|
+
expect(isObjectStackError(null)).toBe(false);
|
|
398
|
+
expect(isObjectStackError(undefined)).toBe(false);
|
|
399
|
+
expect(isObjectStackError('error')).toBe(false);
|
|
400
|
+
expect(isObjectStackError({})).toBe(false);
|
|
401
|
+
});
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
describe('isErrorType', () => {
|
|
405
|
+
it('should return true for matching error type', () => {
|
|
406
|
+
const error = new MetadataNotFoundError('users');
|
|
407
|
+
expect(isErrorType(error, MetadataNotFoundError)).toBe(true);
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
it('should return false for non-matching error type', () => {
|
|
411
|
+
const error = new MetadataNotFoundError('users');
|
|
412
|
+
expect(isErrorType(error, ValidationError)).toBe(false);
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
it('should return true for base class check', () => {
|
|
416
|
+
const error = new MetadataNotFoundError('users');
|
|
417
|
+
expect(isErrorType(error, ObjectStackError)).toBe(true);
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
it('should return false for non-error values', () => {
|
|
421
|
+
expect(isErrorType(null, ObjectStackError)).toBe(false);
|
|
422
|
+
expect(isErrorType(undefined, ObjectStackError)).toBe(false);
|
|
423
|
+
expect(isErrorType({}, ObjectStackError)).toBe(false);
|
|
424
|
+
});
|
|
425
|
+
});
|
|
426
|
+
});
|