refactor: remove isNullOrDefined() helper
[e-mobility-charging-stations-simulator.git] / tests / utils / Utils.test.ts
CommitLineData
66a7748d 1import { describe, it } from 'node:test'
6c43b441 2
66a7748d
JB
3import { hoursToMilliseconds, hoursToSeconds } from 'date-fns'
4import { expect } from 'expect'
a2111e8d 5
66a7748d 6import { Constants } from '../../src/utils/Constants.js'
9bf0ef23
JB
7import {
8 cloneObject,
9 convertToBoolean,
10 convertToDate,
11 convertToFloat,
12 convertToInt,
1553f6df 13 extractTimeSeriesValues,
be4c6702 14 formatDurationMilliSeconds,
8053c842 15 formatDurationSeconds,
9bf0ef23
JB
16 generateUUID,
17 getRandomFloat,
18 getRandomInteger,
19 hasOwnProp,
80c58041 20 isArraySorted,
9bf0ef23
JB
21 isEmptyArray,
22 isEmptyObject,
23 isEmptyString,
24 isIterable,
25 isNotEmptyArray,
26 isNotEmptyString,
9bf0ef23
JB
27 isObject,
28 isUndefined,
0bd926c1 29 isValidTime,
5adf6ca4
JB
30 max,
31 min,
5f742aac 32 once,
9bf0ef23
JB
33 roundTo,
34 secureRandom,
35 sleep,
66a7748d
JB
36 validateUUID
37} from '../../src/utils/Utils.js'
a2111e8d 38
6c43b441
JB
39await describe('Utils test suite', async () => {
40 await it('Verify generateUUID()/validateUUID()', () => {
66a7748d
JB
41 const uuid = generateUUID()
42 expect(uuid).toBeDefined()
43 expect(uuid.length).toEqual(36)
44 expect(validateUUID(uuid)).toBe(true)
45 expect(validateUUID('abcdef00-0000-4000-0000-000000000000')).toBe(true)
46 expect(validateUUID('')).toBe(false)
878e026c 47 // Shall invalidate Nil UUID
66a7748d
JB
48 expect(validateUUID('00000000-0000-0000-0000-000000000000')).toBe(false)
49 expect(validateUUID('987FBC9-4BED-3078-CF07A-9141BA07C9F3')).toBe(false)
50 })
8bd02502 51
6c43b441 52 await it('Verify sleep()', async () => {
66a7748d
JB
53 const start = performance.now()
54 await sleep(1000)
55 const stop = performance.now()
56 expect(stop - start).toBeGreaterThanOrEqual(1000)
57 })
45999aab 58
6c43b441 59 await it('Verify formatDurationMilliSeconds()', () => {
66a7748d
JB
60 expect(formatDurationMilliSeconds(0)).toBe('0 seconds')
61 expect(formatDurationMilliSeconds(900)).toBe('0 seconds')
62 expect(formatDurationMilliSeconds(1000)).toBe('1 second')
63 expect(formatDurationMilliSeconds(hoursToMilliseconds(4380))).toBe('182 days 12 hours')
64 })
be4c6702 65
6c43b441 66 await it('Verify formatDurationSeconds()', () => {
66a7748d
JB
67 expect(formatDurationSeconds(0)).toBe('0 seconds')
68 expect(formatDurationSeconds(0.9)).toBe('0 seconds')
69 expect(formatDurationSeconds(1)).toBe('1 second')
70 expect(formatDurationSeconds(hoursToSeconds(4380))).toBe('182 days 12 hours')
71 })
8053c842 72
6c43b441 73 await it('Verify isValidTime()', () => {
66a7748d
JB
74 expect(isValidTime(undefined)).toBe(false)
75 expect(isValidTime(null)).toBe(false)
76 expect(isValidTime('')).toBe(false)
77 expect(isValidTime({})).toBe(false)
78 expect(isValidTime([])).toBe(false)
79 expect(isValidTime(new Map())).toBe(false)
80 expect(isValidTime(new Set())).toBe(false)
81 expect(isValidTime(new WeakMap())).toBe(false)
82 expect(isValidTime(new WeakSet())).toBe(false)
83 expect(isValidTime(-1)).toBe(true)
84 expect(isValidTime(0)).toBe(true)
85 expect(isValidTime(1)).toBe(true)
86 expect(isValidTime(-0.5)).toBe(true)
87 expect(isValidTime(0.5)).toBe(true)
88 expect(isValidTime(new Date())).toBe(true)
89 })
ac8178a4 90
6c43b441 91 await it('Verify convertToDate()', () => {
66a7748d
JB
92 expect(convertToDate(undefined)).toBe(undefined)
93 expect(convertToDate(null)).toBe(null)
94 expect(() => convertToDate('')).toThrow(new Error("Cannot convert to date: ''"))
95 expect(() => convertToDate('00:70:61')).toThrow(new Error("Cannot convert to date: '00:70:61'"))
96 expect(convertToDate(0)).toStrictEqual(new Date('1970-01-01T00:00:00.000Z'))
97 expect(convertToDate(-1)).toStrictEqual(new Date('1969-12-31T23:59:59.999Z'))
98 const dateStr = '2020-01-01T00:00:00.000Z'
99 let date = convertToDate(dateStr)
100 expect(date).toBeInstanceOf(Date)
101 expect(date).toStrictEqual(new Date(dateStr))
102 date = convertToDate(new Date(dateStr))
103 expect(date).toBeInstanceOf(Date)
104 expect(date).toStrictEqual(new Date(dateStr))
105 })
df645d8f 106
6c43b441 107 await it('Verify convertToInt()', () => {
66a7748d
JB
108 expect(convertToInt(undefined)).toBe(0)
109 expect(convertToInt(null)).toBe(0)
110 expect(convertToInt(0)).toBe(0)
111 const randomInteger = getRandomInteger()
112 expect(convertToInt(randomInteger)).toEqual(randomInteger)
113 expect(convertToInt('-1')).toBe(-1)
114 expect(convertToInt('1')).toBe(1)
115 expect(convertToInt('1.1')).toBe(1)
116 expect(convertToInt('1.9')).toBe(1)
117 expect(convertToInt('1.999')).toBe(1)
118 expect(convertToInt(-1)).toBe(-1)
119 expect(convertToInt(1)).toBe(1)
120 expect(convertToInt(1.1)).toBe(1)
121 expect(convertToInt(1.9)).toBe(1)
122 expect(convertToInt(1.999)).toBe(1)
878e026c 123 expect(() => {
66a7748d
JB
124 convertToInt('NaN')
125 }).toThrow("Cannot convert to integer: 'NaN'")
126 })
df645d8f 127
6c43b441 128 await it('Verify convertToFloat()', () => {
66a7748d
JB
129 expect(convertToFloat(undefined)).toBe(0)
130 expect(convertToFloat(null)).toBe(0)
131 expect(convertToFloat(0)).toBe(0)
132 const randomFloat = getRandomFloat()
133 expect(convertToFloat(randomFloat)).toEqual(randomFloat)
134 expect(convertToFloat('-1')).toBe(-1)
135 expect(convertToFloat('1')).toBe(1)
136 expect(convertToFloat('1.1')).toBe(1.1)
137 expect(convertToFloat('1.9')).toBe(1.9)
138 expect(convertToFloat('1.999')).toBe(1.999)
139 expect(convertToFloat(-1)).toBe(-1)
140 expect(convertToFloat(1)).toBe(1)
141 expect(convertToFloat(1.1)).toBe(1.1)
142 expect(convertToFloat(1.9)).toBe(1.9)
143 expect(convertToFloat(1.999)).toBe(1.999)
878e026c 144 expect(() => {
66a7748d
JB
145 convertToFloat('NaN')
146 }).toThrow("Cannot convert to float: 'NaN'")
147 })
df645d8f 148
6c43b441 149 await it('Verify convertToBoolean()', () => {
66a7748d
JB
150 expect(convertToBoolean(undefined)).toBe(false)
151 expect(convertToBoolean(null)).toBe(false)
152 expect(convertToBoolean('true')).toBe(true)
153 expect(convertToBoolean('false')).toBe(false)
154 expect(convertToBoolean('TRUE')).toBe(true)
155 expect(convertToBoolean('FALSE')).toBe(false)
156 expect(convertToBoolean('1')).toBe(true)
157 expect(convertToBoolean('0')).toBe(false)
158 expect(convertToBoolean(1)).toBe(true)
159 expect(convertToBoolean(0)).toBe(false)
160 expect(convertToBoolean(true)).toBe(true)
161 expect(convertToBoolean(false)).toBe(false)
162 expect(convertToBoolean('')).toBe(false)
163 expect(convertToBoolean('NoNBoolean')).toBe(false)
164 })
df645d8f 165
6c43b441 166 await it('Verify secureRandom()', () => {
66a7748d
JB
167 const random = secureRandom()
168 expect(typeof random === 'number').toBe(true)
169 expect(random).toBeGreaterThanOrEqual(0)
170 expect(random).toBeLessThan(1)
171 })
a2111e8d 172
6c43b441 173 await it('Verify getRandomInteger()', () => {
66a7748d
JB
174 let randomInteger = getRandomInteger()
175 expect(Number.isSafeInteger(randomInteger)).toBe(true)
176 expect(randomInteger).toBeGreaterThanOrEqual(0)
177 expect(randomInteger).toBeLessThanOrEqual(Constants.MAX_RANDOM_INTEGER)
178 expect(randomInteger).not.toEqual(getRandomInteger())
179 randomInteger = getRandomInteger(0, -Constants.MAX_RANDOM_INTEGER)
180 expect(randomInteger).toBeGreaterThanOrEqual(-Constants.MAX_RANDOM_INTEGER)
181 expect(randomInteger).toBeLessThanOrEqual(0)
68f56fdf 182 expect(() => getRandomInteger(0, 1)).toThrow(
66a7748d
JB
183 'The value of "max" is out of range. It must be greater than the value of "min" (1). Received 1'
184 )
68f56fdf 185 expect(() => getRandomInteger(-1)).toThrow(
66a7748d
JB
186 'The value of "max" is out of range. It must be greater than the value of "min" (0). Received 0'
187 )
68f56fdf 188 expect(() => getRandomInteger(Constants.MAX_RANDOM_INTEGER + 1)).toThrow(
878e026c
JB
189 `The value of "max" is out of range. It must be <= ${
190 Constants.MAX_RANDOM_INTEGER + 1
66a7748d
JB
191 }. Received 281_474_976_710_656`
192 )
193 randomInteger = getRandomInteger(2, 1)
194 expect(randomInteger).toBeGreaterThanOrEqual(1)
195 expect(randomInteger).toBeLessThanOrEqual(2)
196 const maximum = 2.2
197 const minimum = 1.1
198 randomInteger = getRandomInteger(maximum, minimum)
199 expect(randomInteger).toBeLessThanOrEqual(Math.floor(maximum))
200 expect(randomInteger).toBeGreaterThanOrEqual(Math.ceil(minimum))
201 })
a2111e8d 202
6c43b441 203 await it('Verify roundTo()', () => {
66a7748d
JB
204 expect(roundTo(0, 2)).toBe(0)
205 expect(roundTo(0.5, 0)).toBe(1)
206 expect(roundTo(0.5, 2)).toBe(0.5)
207 expect(roundTo(-0.5, 0)).toBe(-1)
208 expect(roundTo(-0.5, 2)).toBe(-0.5)
209 expect(roundTo(1.005, 0)).toBe(1)
210 expect(roundTo(1.005, 2)).toBe(1.01)
211 expect(roundTo(2.175, 2)).toBe(2.18)
212 expect(roundTo(5.015, 2)).toBe(5.02)
213 expect(roundTo(-1.005, 2)).toBe(-1.01)
214 expect(roundTo(-2.175, 2)).toBe(-2.18)
215 expect(roundTo(-5.015, 2)).toBe(-5.02)
216 })
316d1564 217
6c43b441 218 await it('Verify getRandomFloat()', () => {
66a7748d
JB
219 let randomFloat = getRandomFloat()
220 expect(typeof randomFloat === 'number').toBe(true)
221 expect(randomFloat).toBeGreaterThanOrEqual(0)
222 expect(randomFloat).toBeLessThanOrEqual(Number.MAX_VALUE)
223 expect(randomFloat).not.toEqual(getRandomFloat())
224 expect(() => getRandomFloat(0, 1)).toThrow(new RangeError('Invalid interval'))
68f56fdf 225 expect(() => getRandomFloat(Number.MAX_VALUE, -Number.MAX_VALUE)).toThrow(
66a7748d
JB
226 new RangeError('Invalid interval')
227 )
228 randomFloat = getRandomFloat(0, -Number.MAX_VALUE)
229 expect(randomFloat).toBeGreaterThanOrEqual(-Number.MAX_VALUE)
230 expect(randomFloat).toBeLessThanOrEqual(0)
231 })
a2111e8d 232
6c43b441 233 await it('Verify extractTimeSeriesValues()', () => {
66a7748d
JB
234 expect(extractTimeSeriesValues([])).toEqual([])
235 expect(extractTimeSeriesValues([{ timestamp: Date.now(), value: 1.1 }])).toEqual([1.1])
1553f6df
JB
236 expect(
237 extractTimeSeriesValues([
238 { timestamp: Date.now(), value: 1.1 },
66a7748d
JB
239 { timestamp: Date.now(), value: 2.2 }
240 ])
241 ).toEqual([1.1, 2.2])
242 })
1553f6df 243
6c43b441 244 await it('Verify isObject()', () => {
66a7748d
JB
245 expect(isObject('test')).toBe(false)
246 expect(isObject(undefined)).toBe(false)
247 expect(isObject(null)).toBe(false)
248 expect(isObject(0)).toBe(false)
249 expect(isObject([])).toBe(false)
250 expect(isObject([0, 1])).toBe(false)
251 expect(isObject(['0', '1'])).toBe(false)
252 expect(isObject({})).toBe(true)
253 expect(isObject({ 1: 1 })).toBe(true)
254 expect(isObject({ 1: '1' })).toBe(true)
255 expect(isObject(new Map())).toBe(true)
256 expect(isObject(new Set())).toBe(true)
257 expect(isObject(new WeakMap())).toBe(true)
258 expect(isObject(new WeakSet())).toBe(true)
259 })
a2111e8d 260
6c43b441 261 await it('Verify cloneObject()', () => {
66a7748d
JB
262 const obj = { 1: 1 }
263 expect(cloneObject(obj)).toStrictEqual(obj)
264 expect(cloneObject(obj) === obj).toBe(false)
265 const nestedObj = { 1: obj, 2: obj }
266 expect(cloneObject(nestedObj)).toStrictEqual(nestedObj)
267 expect(cloneObject(nestedObj) === nestedObj).toBe(false)
268 const array = [1, 2]
269 expect(cloneObject(array)).toStrictEqual(array)
270 expect(cloneObject(array) === array).toBe(false)
271 const objArray = [obj, obj]
272 expect(cloneObject(objArray)).toStrictEqual(objArray)
273 expect(cloneObject(objArray) === objArray).toBe(false)
274 const date = new Date()
275 expect(cloneObject(date)).toStrictEqual(date)
276 expect(cloneObject(date) === date).toBe(false)
277 const map = new Map([['1', '2']])
278 expect(cloneObject(map)).toStrictEqual({})
279 const set = new Set(['1'])
280 expect(cloneObject(set)).toStrictEqual({})
dd5a1d6c 281 // The URL object seems to have not enumerable properties
66a7748d
JB
282 const url = new URL('https://domain.tld')
283 expect(cloneObject(url)).toStrictEqual({})
284 const weakMap = new WeakMap([[{ 1: 1 }, { 2: 2 }]])
285 expect(cloneObject(weakMap)).toStrictEqual({})
286 const weakSet = new WeakSet([{ 1: 1 }, { 2: 2 }])
287 expect(cloneObject(weakSet)).toStrictEqual({})
288 })
dd5a1d6c 289
6c43b441 290 await it('Verify hasOwnProp()', () => {
66a7748d
JB
291 expect(hasOwnProp('test', '')).toBe(false)
292 expect(hasOwnProp(undefined, '')).toBe(false)
293 expect(hasOwnProp(null, '')).toBe(false)
294 expect(hasOwnProp([], '')).toBe(false)
295 expect(hasOwnProp({}, '')).toBe(false)
296 expect(hasOwnProp({ 1: 1 }, 1)).toBe(true)
297 expect(hasOwnProp({ 1: 1 }, '1')).toBe(true)
298 expect(hasOwnProp({ 1: 1 }, 2)).toBe(false)
299 expect(hasOwnProp({ 1: 1 }, '2')).toBe(false)
300 expect(hasOwnProp({ 1: '1' }, '1')).toBe(true)
301 expect(hasOwnProp({ 1: '1' }, 1)).toBe(true)
302 expect(hasOwnProp({ 1: '1' }, '2')).toBe(false)
303 expect(hasOwnProp({ 1: '1' }, 2)).toBe(false)
304 })
af29b598 305
6c43b441 306 await it('Verify isIterable()', () => {
66a7748d
JB
307 expect(isIterable('')).toBe(true)
308 expect(isIterable(' ')).toBe(true)
309 expect(isIterable('test')).toBe(true)
310 expect(isIterable(undefined)).toBe(false)
311 expect(isIterable(null)).toBe(false)
312 expect(isIterable(0)).toBe(false)
313 expect(isIterable([0, 1])).toBe(true)
314 expect(isIterable({ 1: 1 })).toBe(false)
315 expect(isIterable(new Map())).toBe(true)
316 expect(isIterable(new Set())).toBe(true)
317 expect(isIterable(new WeakMap())).toBe(false)
318 expect(isIterable(new WeakSet())).toBe(false)
319 })
a2111e8d 320
6c43b441 321 await it('Verify isEmptyString()', () => {
66a7748d
JB
322 expect(isEmptyString('')).toBe(true)
323 expect(isEmptyString(' ')).toBe(true)
324 expect(isEmptyString(' ')).toBe(true)
325 expect(isEmptyString('test')).toBe(false)
326 expect(isEmptyString(' test')).toBe(false)
327 expect(isEmptyString('test ')).toBe(false)
328 expect(isEmptyString(undefined)).toBe(true)
329 expect(isEmptyString(null)).toBe(true)
330 expect(isEmptyString(0)).toBe(false)
331 expect(isEmptyString({})).toBe(false)
332 expect(isEmptyString([])).toBe(false)
333 expect(isEmptyString(new Map())).toBe(false)
334 expect(isEmptyString(new Set())).toBe(false)
335 expect(isEmptyString(new WeakMap())).toBe(false)
336 expect(isEmptyString(new WeakSet())).toBe(false)
337 })
5a2a53cf 338
6c43b441 339 await it('Verify isNotEmptyString()', () => {
66a7748d
JB
340 expect(isNotEmptyString('')).toBe(false)
341 expect(isNotEmptyString(' ')).toBe(false)
342 expect(isNotEmptyString(' ')).toBe(false)
343 expect(isNotEmptyString('test')).toBe(true)
344 expect(isNotEmptyString(' test')).toBe(true)
345 expect(isNotEmptyString('test ')).toBe(true)
346 expect(isNotEmptyString(undefined)).toBe(false)
347 expect(isNotEmptyString(null)).toBe(false)
348 expect(isNotEmptyString(0)).toBe(false)
349 expect(isNotEmptyString({})).toBe(false)
350 expect(isNotEmptyString([])).toBe(false)
351 expect(isNotEmptyString(new Map())).toBe(false)
352 expect(isNotEmptyString(new Set())).toBe(false)
353 expect(isNotEmptyString(new WeakMap())).toBe(false)
354 expect(isNotEmptyString(new WeakSet())).toBe(false)
355 })
429f8c9d 356
6c43b441 357 await it('Verify isUndefined()', () => {
66a7748d
JB
358 expect(isUndefined(undefined)).toBe(true)
359 expect(isUndefined(null)).toBe(false)
360 expect(isUndefined('')).toBe(false)
361 expect(isUndefined(0)).toBe(false)
362 expect(isUndefined({})).toBe(false)
363 expect(isUndefined([])).toBe(false)
364 expect(isUndefined(new Map())).toBe(false)
365 expect(isUndefined(new Set())).toBe(false)
366 expect(isUndefined(new WeakMap())).toBe(false)
367 expect(isUndefined(new WeakSet())).toBe(false)
368 })
a2111e8d 369
6c43b441 370 await it('Verify isEmptyArray()', () => {
66a7748d
JB
371 expect(isEmptyArray([])).toBe(true)
372 expect(isEmptyArray([1, 2])).toBe(false)
373 expect(isEmptyArray(['1', '2'])).toBe(false)
374 expect(isEmptyArray(undefined)).toBe(false)
375 expect(isEmptyArray(null)).toBe(false)
376 expect(isEmptyArray('')).toBe(false)
377 expect(isEmptyArray('test')).toBe(false)
378 expect(isEmptyArray(0)).toBe(false)
379 expect(isEmptyArray({})).toBe(false)
380 expect(isEmptyArray(new Map())).toBe(false)
381 expect(isEmptyArray(new Set())).toBe(false)
382 expect(isEmptyArray(new WeakMap())).toBe(false)
383 expect(isEmptyArray(new WeakSet())).toBe(false)
384 })
a2111e8d 385
6c43b441 386 await it('Verify isNotEmptyArray()', () => {
66a7748d
JB
387 expect(isNotEmptyArray([])).toBe(false)
388 expect(isNotEmptyArray([1, 2])).toBe(true)
389 expect(isNotEmptyArray(['1', '2'])).toBe(true)
390 expect(isNotEmptyArray(undefined)).toBe(false)
391 expect(isNotEmptyArray(null)).toBe(false)
392 expect(isNotEmptyArray('')).toBe(false)
393 expect(isNotEmptyArray('test')).toBe(false)
394 expect(isNotEmptyArray(0)).toBe(false)
395 expect(isNotEmptyArray({})).toBe(false)
396 expect(isNotEmptyArray(new Map())).toBe(false)
397 expect(isNotEmptyArray(new Set())).toBe(false)
398 expect(isNotEmptyArray(new WeakMap())).toBe(false)
399 expect(isNotEmptyArray(new WeakSet())).toBe(false)
400 })
878e026c 401
6c43b441 402 await it('Verify isEmptyObject()', () => {
66a7748d
JB
403 expect(isEmptyObject({})).toBe(true)
404 expect(isEmptyObject({ 1: 1, 2: 2 })).toBe(false)
405 expect(isEmptyObject(new Map())).toBe(false)
406 expect(isEmptyObject(new Set())).toBe(false)
407 expect(isEmptyObject(new WeakMap())).toBe(false)
408 expect(isEmptyObject(new WeakSet())).toBe(false)
409 })
80c58041 410
6c43b441 411 await it('Verify isArraySorted()', () => {
80c58041
JB
412 expect(
413 isArraySorted([], (a, b) => {
66a7748d
JB
414 return a - b
415 })
416 ).toBe(true)
80c58041
JB
417 expect(
418 isArraySorted([1], (a, b) => {
66a7748d
JB
419 return a - b
420 })
421 ).toBe(true)
422 expect(isArraySorted<number>([1, 2, 3, 4, 5], (a, b) => a - b)).toBe(true)
423 expect(isArraySorted<number>([1, 2, 3, 5, 4], (a, b) => a - b)).toBe(false)
424 expect(isArraySorted<number>([2, 1, 3, 4, 5], (a, b) => a - b)).toBe(false)
425 })
5f742aac 426
6c43b441 427 await it('Verify once()', () => {
66a7748d
JB
428 let called = 0
429 const fn = (): number => ++called
430 const onceFn = once(fn, this)
431 const result1 = onceFn()
432 expect(called).toBe(1)
433 expect(result1).toBe(1)
434 const result2 = onceFn()
435 expect(called).toBe(1)
436 expect(result2).toBe(1)
437 const result3 = onceFn()
438 expect(called).toBe(1)
439 expect(result3).toBe(1)
440 })
5adf6ca4 441
6c43b441 442 await it('Verify min()', () => {
66a7748d
JB
443 expect(min()).toBe(Infinity)
444 expect(min(0, 1)).toBe(0)
445 expect(min(1, 0)).toBe(0)
446 expect(min(0, -1)).toBe(-1)
447 expect(min(-1, 0)).toBe(-1)
448 })
5adf6ca4 449
6c43b441 450 await it('Verify max()', () => {
66a7748d
JB
451 expect(max()).toBe(-Infinity)
452 expect(max(0, 1)).toBe(1)
453 expect(max(1, 0)).toBe(1)
454 expect(max(0, -1)).toBe(0)
455 expect(max(-1, 0)).toBe(0)
456 })
457})