@xiboplayer/utils 0.6.1 → 0.6.3
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/package.json +2 -2
- package/src/cms-api.js +48 -54
- package/src/logger.js +10 -4
- package/src/logger.test.js +22 -18
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xiboplayer/utils",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.3",
|
|
4
4
|
"description": "Shared utilities for Xibo Player packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"./config": "./src/config.js"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@xiboplayer/crypto": "0.6.
|
|
15
|
+
"@xiboplayer/crypto": "0.6.3"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"vitest": "^2.0.0"
|
package/src/cms-api.js
CHANGED
|
@@ -111,15 +111,7 @@ export class CmsApiClient {
|
|
|
111
111
|
const response = await fetch(url, options);
|
|
112
112
|
|
|
113
113
|
if (!response.ok) {
|
|
114
|
-
|
|
115
|
-
let errorMsg;
|
|
116
|
-
try {
|
|
117
|
-
const errorData = JSON.parse(text);
|
|
118
|
-
errorMsg = errorData.error?.message || errorData.message || text;
|
|
119
|
-
} catch (_) {
|
|
120
|
-
errorMsg = text;
|
|
121
|
-
}
|
|
122
|
-
throw new CmsApiError(method, path, response.status, errorMsg);
|
|
114
|
+
await this._handleErrorResponse(response, method, path);
|
|
123
115
|
}
|
|
124
116
|
|
|
125
117
|
// Some endpoints return empty body (204)
|
|
@@ -141,6 +133,35 @@ export class CmsApiClient {
|
|
|
141
133
|
/** DELETE request (path relative to /api/) */
|
|
142
134
|
del(path) { return this.request('DELETE', path); }
|
|
143
135
|
|
|
136
|
+
/**
|
|
137
|
+
* GET a list endpoint and ensure the result is always an array.
|
|
138
|
+
* @param {string} path - API path
|
|
139
|
+
* @param {Object} [filters={}] - Query parameters
|
|
140
|
+
* @returns {Promise<Array>}
|
|
141
|
+
*/
|
|
142
|
+
async _listRequest(path, filters = {}) {
|
|
143
|
+
const data = await this.request('GET', path, filters);
|
|
144
|
+
return Array.isArray(data) ? data : [];
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Parse an error response body and throw a structured error.
|
|
149
|
+
* @param {Response} response - Fetch response
|
|
150
|
+
* @param {string} method - HTTP method
|
|
151
|
+
* @param {string} path - API path
|
|
152
|
+
*/
|
|
153
|
+
async _handleErrorResponse(response, method, path) {
|
|
154
|
+
const text = await response.text();
|
|
155
|
+
let errorMsg;
|
|
156
|
+
try {
|
|
157
|
+
const errorData = JSON.parse(text);
|
|
158
|
+
errorMsg = errorData.error?.message || errorData.message || text;
|
|
159
|
+
} catch (_) {
|
|
160
|
+
errorMsg = text;
|
|
161
|
+
}
|
|
162
|
+
throw new CmsApiError(method, path, response.status, errorMsg);
|
|
163
|
+
}
|
|
164
|
+
|
|
144
165
|
// ── Display Management ──────────────────────────────────────────
|
|
145
166
|
|
|
146
167
|
/**
|
|
@@ -150,10 +171,7 @@ export class CmsApiClient {
|
|
|
150
171
|
*/
|
|
151
172
|
async findDisplay(hardwareKey) {
|
|
152
173
|
log.info('Looking up display by hardwareKey:', hardwareKey);
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
// API returns array of matching displays
|
|
156
|
-
const displays = Array.isArray(data) ? data : [];
|
|
174
|
+
const displays = await this._listRequest('/display', { hardwareKey });
|
|
157
175
|
if (displays.length === 0) {
|
|
158
176
|
log.info('No display found for hardwareKey:', hardwareKey);
|
|
159
177
|
return null;
|
|
@@ -192,8 +210,7 @@ export class CmsApiClient {
|
|
|
192
210
|
* @returns {Promise<Array>} Array of display objects
|
|
193
211
|
*/
|
|
194
212
|
async listDisplays(filters = {}) {
|
|
195
|
-
|
|
196
|
-
return Array.isArray(data) ? data : [];
|
|
213
|
+
return this._listRequest('/display', filters);
|
|
197
214
|
}
|
|
198
215
|
|
|
199
216
|
/**
|
|
@@ -238,15 +255,7 @@ export class CmsApiClient {
|
|
|
238
255
|
});
|
|
239
256
|
|
|
240
257
|
if (!response.ok) {
|
|
241
|
-
|
|
242
|
-
let errorMsg;
|
|
243
|
-
try {
|
|
244
|
-
const errorData = JSON.parse(text);
|
|
245
|
-
errorMsg = errorData.error?.message || errorData.message || text;
|
|
246
|
-
} catch (_) {
|
|
247
|
-
errorMsg = text;
|
|
248
|
-
}
|
|
249
|
-
throw new Error(`CMS API ${method} ${path} failed (${response.status}): ${errorMsg}`);
|
|
258
|
+
await this._handleErrorResponse(response, method, path);
|
|
250
259
|
}
|
|
251
260
|
|
|
252
261
|
const contentType = response.headers.get('Content-Type') || '';
|
|
@@ -278,8 +287,7 @@ export class CmsApiClient {
|
|
|
278
287
|
* @returns {Promise<Array>}
|
|
279
288
|
*/
|
|
280
289
|
async listLayouts(filters = {}) {
|
|
281
|
-
|
|
282
|
-
return Array.isArray(data) ? data : [];
|
|
290
|
+
return this._listRequest('/layout', filters);
|
|
283
291
|
}
|
|
284
292
|
|
|
285
293
|
/**
|
|
@@ -446,8 +454,7 @@ export class CmsApiClient {
|
|
|
446
454
|
* @returns {Promise<Array>}
|
|
447
455
|
*/
|
|
448
456
|
async listMedia(filters = {}) {
|
|
449
|
-
|
|
450
|
-
return Array.isArray(data) ? data : [];
|
|
457
|
+
return this._listRequest('/library', filters);
|
|
451
458
|
}
|
|
452
459
|
|
|
453
460
|
/**
|
|
@@ -485,8 +492,7 @@ export class CmsApiClient {
|
|
|
485
492
|
* @returns {Promise<Array>}
|
|
486
493
|
*/
|
|
487
494
|
async listCampaigns(filters = {}) {
|
|
488
|
-
|
|
489
|
-
return Array.isArray(data) ? data : [];
|
|
495
|
+
return this._listRequest('/campaign', filters);
|
|
490
496
|
}
|
|
491
497
|
|
|
492
498
|
/**
|
|
@@ -600,8 +606,7 @@ export class CmsApiClient {
|
|
|
600
606
|
* @returns {Promise<Array>}
|
|
601
607
|
*/
|
|
602
608
|
async listDisplayGroups(filters = {}) {
|
|
603
|
-
|
|
604
|
-
return Array.isArray(data) ? data : [];
|
|
609
|
+
return this._listRequest('/displaygroup', filters);
|
|
605
610
|
}
|
|
606
611
|
|
|
607
612
|
/**
|
|
@@ -688,8 +693,7 @@ export class CmsApiClient {
|
|
|
688
693
|
* @returns {Promise<Array>}
|
|
689
694
|
*/
|
|
690
695
|
async listResolutions() {
|
|
691
|
-
|
|
692
|
-
return Array.isArray(data) ? data : [];
|
|
696
|
+
return this._listRequest('/resolution');
|
|
693
697
|
}
|
|
694
698
|
|
|
695
699
|
// ── Template Management ──────────────────────────────────────────
|
|
@@ -700,8 +704,7 @@ export class CmsApiClient {
|
|
|
700
704
|
* @returns {Promise<Array>}
|
|
701
705
|
*/
|
|
702
706
|
async listTemplates(filters = {}) {
|
|
703
|
-
|
|
704
|
-
return Array.isArray(data) ? data : [];
|
|
707
|
+
return this._listRequest('/template', filters);
|
|
705
708
|
}
|
|
706
709
|
|
|
707
710
|
// ── Playlist Management ──────────────────────────────────────────
|
|
@@ -870,8 +873,7 @@ export class CmsApiClient {
|
|
|
870
873
|
* @returns {Promise<Array>}
|
|
871
874
|
*/
|
|
872
875
|
async listCommands(filters = {}) {
|
|
873
|
-
|
|
874
|
-
return Array.isArray(data) ? data : [];
|
|
876
|
+
return this._listRequest('/command', filters);
|
|
875
877
|
}
|
|
876
878
|
|
|
877
879
|
/**
|
|
@@ -949,8 +951,7 @@ export class CmsApiClient {
|
|
|
949
951
|
* @returns {Promise<Array>}
|
|
950
952
|
*/
|
|
951
953
|
async listDayParts(filters = {}) {
|
|
952
|
-
|
|
953
|
-
return Array.isArray(data) ? data : [];
|
|
954
|
+
return this._listRequest('/daypart', filters);
|
|
954
955
|
}
|
|
955
956
|
|
|
956
957
|
/**
|
|
@@ -1055,8 +1056,7 @@ export class CmsApiClient {
|
|
|
1055
1056
|
* @returns {Promise<Array>}
|
|
1056
1057
|
*/
|
|
1057
1058
|
async listPlaylists(filters = {}) {
|
|
1058
|
-
|
|
1059
|
-
return Array.isArray(data) ? data : [];
|
|
1059
|
+
return this._listRequest('/playlist', filters);
|
|
1060
1060
|
}
|
|
1061
1061
|
|
|
1062
1062
|
/**
|
|
@@ -1212,8 +1212,7 @@ export class CmsApiClient {
|
|
|
1212
1212
|
* @returns {Promise<Array>}
|
|
1213
1213
|
*/
|
|
1214
1214
|
async listDatasets(filters = {}) {
|
|
1215
|
-
|
|
1216
|
-
return Array.isArray(data) ? data : [];
|
|
1215
|
+
return this._listRequest('/dataset', filters);
|
|
1217
1216
|
}
|
|
1218
1217
|
|
|
1219
1218
|
/**
|
|
@@ -1250,8 +1249,7 @@ export class CmsApiClient {
|
|
|
1250
1249
|
* @returns {Promise<Array>}
|
|
1251
1250
|
*/
|
|
1252
1251
|
async listDatasetColumns(dataSetId) {
|
|
1253
|
-
|
|
1254
|
-
return Array.isArray(data) ? data : [];
|
|
1252
|
+
return this._listRequest(`/dataset/${dataSetId}/column`);
|
|
1255
1253
|
}
|
|
1256
1254
|
|
|
1257
1255
|
/**
|
|
@@ -1292,8 +1290,7 @@ export class CmsApiClient {
|
|
|
1292
1290
|
* @returns {Promise<Array>}
|
|
1293
1291
|
*/
|
|
1294
1292
|
async listDatasetData(dataSetId, filters = {}) {
|
|
1295
|
-
|
|
1296
|
-
return Array.isArray(data) ? data : [];
|
|
1293
|
+
return this._listRequest(`/dataset/data/${dataSetId}`, filters);
|
|
1297
1294
|
}
|
|
1298
1295
|
|
|
1299
1296
|
/**
|
|
@@ -1354,8 +1351,7 @@ export class CmsApiClient {
|
|
|
1354
1351
|
* @returns {Promise<Array>}
|
|
1355
1352
|
*/
|
|
1356
1353
|
async listNotifications(filters = {}) {
|
|
1357
|
-
|
|
1358
|
-
return Array.isArray(data) ? data : [];
|
|
1354
|
+
return this._listRequest('/notification', filters);
|
|
1359
1355
|
}
|
|
1360
1356
|
|
|
1361
1357
|
/**
|
|
@@ -1394,8 +1390,7 @@ export class CmsApiClient {
|
|
|
1394
1390
|
* @returns {Promise<Array>}
|
|
1395
1391
|
*/
|
|
1396
1392
|
async listFolders(filters = {}) {
|
|
1397
|
-
|
|
1398
|
-
return Array.isArray(data) ? data : [];
|
|
1393
|
+
return this._listRequest('/folder', filters);
|
|
1399
1394
|
}
|
|
1400
1395
|
|
|
1401
1396
|
/**
|
|
@@ -1434,8 +1429,7 @@ export class CmsApiClient {
|
|
|
1434
1429
|
* @returns {Promise<Array>}
|
|
1435
1430
|
*/
|
|
1436
1431
|
async listTags(filters = {}) {
|
|
1437
|
-
|
|
1438
|
-
return Array.isArray(data) ? data : [];
|
|
1432
|
+
return this._listRequest('/tag', filters);
|
|
1439
1433
|
}
|
|
1440
1434
|
|
|
1441
1435
|
/**
|
package/src/logger.js
CHANGED
|
@@ -40,6 +40,12 @@ class Logger {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
/** HH:MM:SS.mmm timestamp for log lines */
|
|
44
|
+
_ts() {
|
|
45
|
+
const d = new Date();
|
|
46
|
+
return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}.${String(d.getMilliseconds()).padStart(3, '0')}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
43
49
|
setLevel(level) {
|
|
44
50
|
this.useGlobal = false;
|
|
45
51
|
if (typeof level === 'string') {
|
|
@@ -56,28 +62,28 @@ class Logger {
|
|
|
56
62
|
|
|
57
63
|
debug(...args) {
|
|
58
64
|
if (this.getEffectiveLevel() <= LOG_LEVELS.DEBUG) {
|
|
59
|
-
console.log(
|
|
65
|
+
console.log(`${this._ts()} [${this.name}] DEBUG:`, ...args);
|
|
60
66
|
}
|
|
61
67
|
_dispatchToSinks('debug', this.name, args);
|
|
62
68
|
}
|
|
63
69
|
|
|
64
70
|
info(...args) {
|
|
65
71
|
if (this.getEffectiveLevel() <= LOG_LEVELS.INFO) {
|
|
66
|
-
console.log(
|
|
72
|
+
console.log(`${this._ts()} [${this.name}]`, ...args);
|
|
67
73
|
}
|
|
68
74
|
_dispatchToSinks('info', this.name, args);
|
|
69
75
|
}
|
|
70
76
|
|
|
71
77
|
warn(...args) {
|
|
72
78
|
if (this.getEffectiveLevel() <= LOG_LEVELS.WARNING) {
|
|
73
|
-
console.warn(
|
|
79
|
+
console.warn(`${this._ts()} [${this.name}]`, ...args);
|
|
74
80
|
}
|
|
75
81
|
_dispatchToSinks('warning', this.name, args);
|
|
76
82
|
}
|
|
77
83
|
|
|
78
84
|
error(...args) {
|
|
79
85
|
if (this.getEffectiveLevel() <= LOG_LEVELS.ERROR) {
|
|
80
|
-
console.error(
|
|
86
|
+
console.error(`${this._ts()} [${this.name}]`, ...args);
|
|
81
87
|
}
|
|
82
88
|
_dispatchToSinks('error', this.name, args);
|
|
83
89
|
}
|
package/src/logger.test.js
CHANGED
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
8
8
|
import { createLogger, setLogLevel, getLogLevel, LOG_LEVELS } from './logger.js';
|
|
9
9
|
|
|
10
|
+
// Matches "HH:MM:SS.mmm [Name]" or "HH:MM:SS.mmm [Name] DEBUG:"
|
|
11
|
+
const ts = (name, suffix = '') =>
|
|
12
|
+
expect.stringMatching(new RegExp(`^\\d{2}:\\d{2}:\\d{2}\\.\\d{3} \\[${name}\\]${suffix}$`));
|
|
13
|
+
|
|
10
14
|
describe('Logger', () => {
|
|
11
15
|
let consoleLogSpy;
|
|
12
16
|
let consoleWarnSpy;
|
|
@@ -62,7 +66,7 @@ describe('Logger', () => {
|
|
|
62
66
|
logger.debug('Debug message', { data: 'value' });
|
|
63
67
|
|
|
64
68
|
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
65
|
-
'
|
|
69
|
+
ts('Test', ' DEBUG:'),
|
|
66
70
|
'Debug message',
|
|
67
71
|
{ data: 'value' }
|
|
68
72
|
);
|
|
@@ -100,7 +104,7 @@ describe('Logger', () => {
|
|
|
100
104
|
logger.info('Info message', 'arg1', 'arg2');
|
|
101
105
|
|
|
102
106
|
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
103
|
-
'
|
|
107
|
+
ts('Test'),
|
|
104
108
|
'Info message',
|
|
105
109
|
'arg1',
|
|
106
110
|
'arg2'
|
|
@@ -139,7 +143,7 @@ describe('Logger', () => {
|
|
|
139
143
|
logger.warn('Warning message', { warn: true });
|
|
140
144
|
|
|
141
145
|
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
142
|
-
'
|
|
146
|
+
ts('Test'),
|
|
143
147
|
'Warning message',
|
|
144
148
|
{ warn: true }
|
|
145
149
|
);
|
|
@@ -177,7 +181,7 @@ describe('Logger', () => {
|
|
|
177
181
|
logger.error('Error message', new Error('Test error'));
|
|
178
182
|
|
|
179
183
|
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
180
|
-
'
|
|
184
|
+
ts('Test'),
|
|
181
185
|
'Error message',
|
|
182
186
|
expect.any(Error)
|
|
183
187
|
);
|
|
@@ -226,37 +230,37 @@ describe('Logger', () => {
|
|
|
226
230
|
it('should delegate to debug()', () => {
|
|
227
231
|
logger.log('DEBUG', 'message');
|
|
228
232
|
|
|
229
|
-
expect(consoleLogSpy).toHaveBeenCalledWith('
|
|
233
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(ts('Test', ' DEBUG:'), 'message');
|
|
230
234
|
});
|
|
231
235
|
|
|
232
236
|
it('should delegate to info()', () => {
|
|
233
237
|
logger.log('INFO', 'message');
|
|
234
238
|
|
|
235
|
-
expect(consoleLogSpy).toHaveBeenCalledWith('
|
|
239
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(ts('Test'), 'message');
|
|
236
240
|
});
|
|
237
241
|
|
|
238
242
|
it('should delegate to warn() for WARNING', () => {
|
|
239
243
|
logger.log('WARNING', 'message');
|
|
240
244
|
|
|
241
|
-
expect(consoleWarnSpy).toHaveBeenCalledWith('
|
|
245
|
+
expect(consoleWarnSpy).toHaveBeenCalledWith(ts('Test'), 'message');
|
|
242
246
|
});
|
|
243
247
|
|
|
244
248
|
it('should delegate to warn() for WARN', () => {
|
|
245
249
|
logger.log('WARN', 'message');
|
|
246
250
|
|
|
247
|
-
expect(consoleWarnSpy).toHaveBeenCalledWith('
|
|
251
|
+
expect(consoleWarnSpy).toHaveBeenCalledWith(ts('Test'), 'message');
|
|
248
252
|
});
|
|
249
253
|
|
|
250
254
|
it('should delegate to error()', () => {
|
|
251
255
|
logger.log('ERROR', 'message');
|
|
252
256
|
|
|
253
|
-
expect(consoleErrorSpy).toHaveBeenCalledWith('
|
|
257
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith(ts('Test'), 'message');
|
|
254
258
|
});
|
|
255
259
|
|
|
256
260
|
it('should handle lowercase level names', () => {
|
|
257
261
|
logger.log('debug', 'message');
|
|
258
262
|
|
|
259
|
-
expect(consoleLogSpy).toHaveBeenCalledWith('
|
|
263
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(ts('Test', ' DEBUG:'), 'message');
|
|
260
264
|
});
|
|
261
265
|
});
|
|
262
266
|
|
|
@@ -345,7 +349,7 @@ describe('Logger', () => {
|
|
|
345
349
|
logger.info('Message', 1, 'two', { three: 3 }, [4, 5]);
|
|
346
350
|
|
|
347
351
|
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
348
|
-
'
|
|
352
|
+
ts('Test'),
|
|
349
353
|
'Message',
|
|
350
354
|
1,
|
|
351
355
|
'two',
|
|
@@ -357,7 +361,7 @@ describe('Logger', () => {
|
|
|
357
361
|
it('should handle zero arguments', () => {
|
|
358
362
|
logger.info();
|
|
359
363
|
|
|
360
|
-
expect(consoleLogSpy).toHaveBeenCalledWith('
|
|
364
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(ts('Test'));
|
|
361
365
|
});
|
|
362
366
|
|
|
363
367
|
it('should handle objects and errors', () => {
|
|
@@ -367,7 +371,7 @@ describe('Logger', () => {
|
|
|
367
371
|
logger.error('Error:', error, obj);
|
|
368
372
|
|
|
369
373
|
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
370
|
-
'
|
|
374
|
+
ts('Test'),
|
|
371
375
|
'Error:',
|
|
372
376
|
error,
|
|
373
377
|
obj
|
|
@@ -381,7 +385,7 @@ describe('Logger', () => {
|
|
|
381
385
|
|
|
382
386
|
logger.info('Test');
|
|
383
387
|
|
|
384
|
-
expect(consoleLogSpy).toHaveBeenCalledWith('
|
|
388
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(ts('MyModule'), 'Test');
|
|
385
389
|
});
|
|
386
390
|
|
|
387
391
|
it('should support different module names', () => {
|
|
@@ -391,8 +395,8 @@ describe('Logger', () => {
|
|
|
391
395
|
logger1.info('From 1');
|
|
392
396
|
logger2.info('From 2');
|
|
393
397
|
|
|
394
|
-
expect(consoleLogSpy).toHaveBeenCalledWith('
|
|
395
|
-
expect(consoleLogSpy).toHaveBeenCalledWith('
|
|
398
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(ts('Module1'), 'From 1');
|
|
399
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(ts('Module2'), 'From 2');
|
|
396
400
|
});
|
|
397
401
|
});
|
|
398
402
|
|
|
@@ -402,7 +406,7 @@ describe('Logger', () => {
|
|
|
402
406
|
|
|
403
407
|
logger.info('Test');
|
|
404
408
|
|
|
405
|
-
expect(consoleLogSpy).toHaveBeenCalledWith('
|
|
409
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(ts('null'), 'Test');
|
|
406
410
|
});
|
|
407
411
|
|
|
408
412
|
it('should handle undefined level (use default)', () => {
|
|
@@ -419,7 +423,7 @@ describe('Logger', () => {
|
|
|
419
423
|
|
|
420
424
|
logger.info(longMessage);
|
|
421
425
|
|
|
422
|
-
expect(consoleLogSpy).toHaveBeenCalledWith('
|
|
426
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(ts('Test'), longMessage);
|
|
423
427
|
});
|
|
424
428
|
|
|
425
429
|
it('should handle circular references in objects', () => {
|