src/FontColorContrast.test.ts   A
last analyzed

Complexity

Total Complexity 2
Complexity/F 0

Size

Lines of Code 955
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 2
eloc 833
mnd 2
bc 2
fnc 0
dl 0
loc 955
rs 9.767
bpm 0
cpm 0
noi 0
c 0
b 0
f 0
1
/* eslint-disable no-new-wrappers */
2
import { cssNamedColors } from './cssNamedColors'
3
import { FontColorContrast, NumberType } from './FontColorContrast'
4
5
describe('constructor()', () => {
6
  test('instance is created', () => {
7
    const fcc = new FontColorContrast(1, 2, 3, 4)
8
    expect(fcc).toBeInstanceOf(FontColorContrast)
9
    expect(fcc).toEqual({
10
      red:       0,
11
      green:     0,
12
      blue:      0,
13
      threshold: 0.5,
14
    })
15
  })
16
})
17
18
describe('getColor()', () => {
19
  let setColorsFromRgbNumbers: jest.SpyInstance<any, unknown[]>
20
  let setColorsFromHexString: jest.SpyInstance<any, unknown[]>
21
  let setColorsFromNumber: jest.SpyInstance<any, unknown[]>
22
  let setColorsFromArray: jest.SpyInstance<any, unknown[]>
23
  let isRgb: jest.SpyInstance<any, unknown[]>
24
  let isHexString: jest.SpyInstance<any, unknown[]>
25
  let isNumber: jest.SpyInstance<any, unknown[]>
26
  let isArray: jest.SpyInstance<any, unknown[]>
27
  let contrastFromHSP: jest.SpyInstance<'#000000' | '#ffffff', []>
28
29
  beforeEach(() => {
30
    setColorsFromRgbNumbers = jest
31
      .spyOn(FontColorContrast.prototype, 'setColorsFromRgbNumbers')
32
      .mockImplementation(() => null)
33
    setColorsFromHexString = jest
34
      .spyOn(FontColorContrast.prototype, 'setColorsFromHexString')
35
      .mockImplementation(() => null)
36
    setColorsFromNumber = jest
37
      .spyOn(FontColorContrast.prototype, 'setColorsFromNumber')
38
      .mockImplementation(() => null)
39
    setColorsFromArray = jest
40
      .spyOn(FontColorContrast.prototype, 'setColorsFromArray')
41
      .mockImplementation(() => null)
42
    isRgb = jest
43
      .spyOn(FontColorContrast.prototype, 'isRgb')
44
      .mockImplementation(() => false)
45
    isHexString = jest
46
      .spyOn(FontColorContrast.prototype, 'isHexString')
47
      .mockImplementation(() => false)
48
    isNumber = jest
49
      .spyOn(FontColorContrast.prototype, 'isNumber')
50
      .mockImplementation(() => false)
51
    isArray = jest
52
      .spyOn(FontColorContrast.prototype, 'isArray')
53
      .mockImplementation(() => false)
54
    contrastFromHSP = jest
55
      .spyOn(FontColorContrast.prototype, 'contrastFromHSP')
56
      .mockImplementation(() => '#000000')
57
  })
58
59
  afterEach(() => {
60
    jest.resetAllMocks()
61
  })
62
63
  afterAll(() => {
64
    jest.restoreAllMocks()
65
  })
66
67
  test('RGB number colors', () => {
68
    isRgb.mockImplementation(() => true)
69
    const fcc = new FontColorContrast(10, 20, 255, 0.3)
70
    fcc.getColor()
71
    expect(setColorsFromRgbNumbers).toHaveBeenCalledTimes(1)
72
    expect(setColorsFromHexString).toHaveBeenCalledTimes(0)
73
    expect(setColorsFromNumber).toHaveBeenCalledTimes(0)
74
    expect(setColorsFromArray).toHaveBeenCalledTimes(0)
75
    expect(contrastFromHSP).toHaveBeenCalledTimes(1)
76
  })
77
78
  test('HEX string', () => {
79
    isHexString.mockImplementation(() => true)
80
    const fcc = new FontColorContrast(10, 20, 255, 0.3)
81
    fcc.getColor()
82
    expect(setColorsFromRgbNumbers).toHaveBeenCalledTimes(0)
83
    expect(setColorsFromHexString).toHaveBeenCalledTimes(1)
84
    expect(setColorsFromNumber).toHaveBeenCalledTimes(0)
85
    expect(setColorsFromArray).toHaveBeenCalledTimes(0)
86
    expect(contrastFromHSP).toHaveBeenCalledTimes(1)
87
  })
88
89
  test('HEX number', () => {
90
    isNumber.mockImplementation(() => true)
91
    const fcc = new FontColorContrast(10, 20, 255, 0.3)
92
    fcc.getColor()
93
    expect(setColorsFromRgbNumbers).toHaveBeenCalledTimes(0)
94
    expect(setColorsFromHexString).toHaveBeenCalledTimes(0)
95
    expect(setColorsFromNumber).toHaveBeenCalledTimes(1)
96
    expect(setColorsFromArray).toHaveBeenCalledTimes(0)
97
    expect(contrastFromHSP).toHaveBeenCalledTimes(1)
98
  })
99
100
  test('HEX array', () => {
101
    isArray.mockImplementation(() => true)
102
    const fcc = new FontColorContrast(10, 20, 255, 0.3)
103
    fcc.getColor()
104
    expect(setColorsFromRgbNumbers).toHaveBeenCalledTimes(0)
105
    expect(setColorsFromHexString).toHaveBeenCalledTimes(0)
106
    expect(setColorsFromNumber).toHaveBeenCalledTimes(0)
107
    expect(setColorsFromArray).toHaveBeenCalledTimes(1)
108
    expect(contrastFromHSP).toHaveBeenCalledTimes(1)
109
  })
110
111
  test('failed params', () => {
112
    const fcc = new FontColorContrast(10, 20, 255, 0.3)
113
    fcc.getColor()
114
    expect(setColorsFromRgbNumbers).toHaveBeenCalledTimes(0)
115
    expect(setColorsFromHexString).toHaveBeenCalledTimes(0)
116
    expect(setColorsFromNumber).toHaveBeenCalledTimes(0)
117
    expect(setColorsFromArray).toHaveBeenCalledTimes(0)
118
    expect(contrastFromHSP).toHaveBeenCalledTimes(0)
119
  })
120
})
121
122
describe('getColor() end to end', () => {
123
  let setColorsFromRgbNumbers: jest.SpyInstance<any, unknown[]>
124
  let setColorsFromHexString: jest.SpyInstance<any, unknown[]>
125
  let setColorsFromNumber: jest.SpyInstance<any, unknown[]>
126
  let setColorsFromArray: jest.SpyInstance<any, unknown[]>
127
  let isRgb: jest.SpyInstance<any, unknown[]>
128
  let isHexString: jest.SpyInstance<any, unknown[]>
129
  let isNumber: jest.SpyInstance<any, unknown[]>
130
  let isArray: jest.SpyInstance<any, unknown[]>
131
  let contrastFromHSP: jest.SpyInstance<'#000000' | '#ffffff', []>
132
133
  beforeEach(() => {
134
    setColorsFromRgbNumbers = jest
135
      .spyOn(FontColorContrast.prototype, 'setColorsFromRgbNumbers')
136
    setColorsFromHexString = jest
137
      .spyOn(FontColorContrast.prototype, 'setColorsFromHexString')
138
    setColorsFromNumber = jest
139
      .spyOn(FontColorContrast.prototype, 'setColorsFromNumber')
140
    setColorsFromArray = jest
141
      .spyOn(FontColorContrast.prototype, 'setColorsFromArray')
142
    isRgb = jest
143
      .spyOn(FontColorContrast.prototype, 'isRgb')
144
    isHexString = jest
145
      .spyOn(FontColorContrast.prototype, 'isHexString')
146
    isNumber = jest
147
      .spyOn(FontColorContrast.prototype, 'isNumber')
148
    isArray = jest
149
      .spyOn(FontColorContrast.prototype, 'isArray')
150
    contrastFromHSP = jest
151
      .spyOn(FontColorContrast.prototype, 'contrastFromHSP')
152
  })
153
154
  afterEach(() => {
155
    jest.restoreAllMocks()
156
  })
157
158
  test('RGB number colors', () => {
159
    const fcc = new FontColorContrast(10, 20, 255, 0.3)
160
    fcc.getColor()
161
162
    expect(fcc.red).toBe(10)
163
    expect(fcc.green).toBe(20)
164
    expect(fcc.blue).toBe(255)
165
    expect(fcc.threshold).toBe(0.3)
166
167
    expect(isRgb).toHaveBeenCalledTimes(1)
168
    expect(setColorsFromRgbNumbers).toHaveBeenCalledTimes(1)
169
    expect(isHexString).toHaveBeenCalledTimes(0)
170
    expect(setColorsFromHexString).toHaveBeenCalledTimes(0)
171
    expect(isNumber).toHaveBeenCalledTimes(0)
172
    expect(setColorsFromNumber).toHaveBeenCalledTimes(0)
173
    expect(isArray).toHaveBeenCalledTimes(0)
174
    expect(setColorsFromArray).toHaveBeenCalledTimes(0)
175
    expect(contrastFromHSP).toHaveBeenCalledTimes(1)
176
  })
177
178
  test('failed RGB number colors', () => {
179
    const fcc = new FontColorContrast(10, 256, 255, 0.3)
180
    fcc.getColor()
181
182
    expect(fcc.red).toBe(0)
183
    expect(fcc.green).toBe(0)
184
    expect(fcc.blue).toBe(0)
185
    expect(fcc.threshold).toBe(0.5)
186
187
    expect(isRgb).toHaveBeenCalledTimes(1)
188
    expect(setColorsFromRgbNumbers).toHaveBeenCalledTimes(0)
189
    expect(isHexString).toHaveBeenCalledTimes(1)
190
    expect(setColorsFromHexString).toHaveBeenCalledTimes(0)
191
    expect(isNumber).toHaveBeenCalledTimes(1)
192
    expect(setColorsFromNumber).toHaveBeenCalledTimes(0)
193
    expect(isArray).toHaveBeenCalledTimes(1)
194
    expect(setColorsFromArray).toHaveBeenCalledTimes(0)
195
    expect(contrastFromHSP).toHaveBeenCalledTimes(0)
196
  })
197
198
  test('HEX string', () => {
199
    const fcc = new FontColorContrast('#f35cea')
200
    fcc.getColor()
201
202
    expect(fcc.red).toBe(0xf3)
203
    expect(fcc.green).toBe(0x5c)
204
    expect(fcc.blue).toBe(0xea)
205
    expect(fcc.threshold).toBe(0.5)
206
207
    expect(isRgb).toHaveBeenCalledTimes(1)
208
    expect(setColorsFromRgbNumbers).toHaveBeenCalledTimes(0)
209
    expect(isHexString).toHaveBeenCalledTimes(1)
210
    expect(setColorsFromHexString).toHaveBeenCalledTimes(1)
211
    expect(isNumber).toHaveBeenCalledTimes(0)
212
    expect(setColorsFromNumber).toHaveBeenCalledTimes(0)
213
    expect(isArray).toHaveBeenCalledTimes(0)
214
    expect(setColorsFromArray).toHaveBeenCalledTimes(0)
215
    expect(contrastFromHSP).toHaveBeenCalledTimes(1)
216
  })
217
218
  test('failed HEX string', () => {
219
    const fcc = new FontColorContrast('#f35ceac')
220
    fcc.getColor()
221
222
    expect(fcc.red).toBe(0)
223
    expect(fcc.green).toBe(0)
224
    expect(fcc.blue).toBe(0)
225
    expect(fcc.threshold).toBe(0.5)
226
227
    expect(isRgb).toHaveBeenCalledTimes(1)
228
    expect(setColorsFromRgbNumbers).toHaveBeenCalledTimes(0)
229
    expect(isHexString).toHaveBeenCalledTimes(1)
230
    expect(setColorsFromHexString).toHaveBeenCalledTimes(0)
231
    expect(isNumber).toHaveBeenCalledTimes(1)
232
    expect(setColorsFromNumber).toHaveBeenCalledTimes(0)
233
    expect(isArray).toHaveBeenCalledTimes(1)
234
    expect(setColorsFromArray).toHaveBeenCalledTimes(0)
235
    expect(contrastFromHSP).toHaveBeenCalledTimes(0)
236
  })
237
238
  test('HEX number', () => {
239
    const fcc = new FontColorContrast(0xf35cea)
240
    fcc.getColor()
241
242
    expect(fcc.red).toBe(0xf3)
243
    expect(fcc.green).toBe(0x5c)
244
    expect(fcc.blue).toBe(0xea)
245
    expect(fcc.threshold).toBe(0.5)
246
247
    expect(isRgb).toHaveBeenCalledTimes(1)
248
    expect(setColorsFromRgbNumbers).toHaveBeenCalledTimes(0)
249
    expect(isHexString).toHaveBeenCalledTimes(1)
250
    expect(setColorsFromHexString).toHaveBeenCalledTimes(0)
251
    expect(isNumber).toHaveBeenCalledTimes(1)
252
    expect(setColorsFromNumber).toHaveBeenCalledTimes(1)
253
    expect(isArray).toHaveBeenCalledTimes(0)
254
    expect(setColorsFromArray).toHaveBeenCalledTimes(0)
255
    expect(contrastFromHSP).toHaveBeenCalledTimes(1)
256
  })
257
258
  test('failed HEX number', () => {
259
    const fcc = new FontColorContrast(0x1000000)
260
    fcc.getColor()
261
262
    expect(fcc.red).toBe(0)
263
    expect(fcc.green).toBe(0)
264
    expect(fcc.blue).toBe(0)
265
    expect(fcc.threshold).toBe(0.5)
266
267
    expect(isRgb).toHaveBeenCalledTimes(1)
268
    expect(setColorsFromRgbNumbers).toHaveBeenCalledTimes(0)
269
    expect(isHexString).toHaveBeenCalledTimes(1)
270
    expect(setColorsFromHexString).toHaveBeenCalledTimes(0)
271
    expect(isNumber).toHaveBeenCalledTimes(1)
272
    expect(setColorsFromNumber).toHaveBeenCalledTimes(0)
273
    expect(isArray).toHaveBeenCalledTimes(1)
274
    expect(setColorsFromArray).toHaveBeenCalledTimes(0)
275
    expect(contrastFromHSP).toHaveBeenCalledTimes(0)
276
  })
277
278
  test('HEX array', () => {
279
    const fcc = new FontColorContrast([10, 20, 255])
280
    fcc.getColor()
281
282
    expect(fcc.red).toBe(10)
283
    expect(fcc.green).toBe(20)
284
    expect(fcc.blue).toBe(255)
285
    expect(fcc.threshold).toBe(0.5)
286
287
    expect(isRgb).toHaveBeenCalledTimes(1)
288
    expect(setColorsFromRgbNumbers).toHaveBeenCalledTimes(0)
289
    expect(isHexString).toHaveBeenCalledTimes(1)
290
    expect(setColorsFromHexString).toHaveBeenCalledTimes(0)
291
    expect(isNumber).toHaveBeenCalledTimes(1)
292
    expect(setColorsFromNumber).toHaveBeenCalledTimes(0)
293
    expect(isArray).toHaveBeenCalledTimes(1)
294
    expect(setColorsFromArray).toHaveBeenCalledTimes(1)
295
    expect(contrastFromHSP).toHaveBeenCalledTimes(1)
296
  })
297
298
  test('failed HEX array', () => {
299
    const fcc = new FontColorContrast([10, 256, 255])
300
    fcc.getColor()
301
302
    expect(fcc.red).toBe(0)
303
    expect(fcc.green).toBe(0)
304
    expect(fcc.blue).toBe(0)
305
    expect(fcc.threshold).toBe(0.5)
306
307
    expect(isRgb).toHaveBeenCalledTimes(1)
308
    expect(setColorsFromRgbNumbers).toHaveBeenCalledTimes(0)
309
    expect(isHexString).toHaveBeenCalledTimes(1)
310
    expect(setColorsFromHexString).toHaveBeenCalledTimes(0)
311
    expect(isNumber).toHaveBeenCalledTimes(1)
312
    expect(setColorsFromNumber).toHaveBeenCalledTimes(0)
313
    expect(isArray).toHaveBeenCalledTimes(1)
314
    expect(setColorsFromArray).toHaveBeenCalledTimes(0)
315
    expect(contrastFromHSP).toHaveBeenCalledTimes(0)
316
  })
317
318
  test('all named css color', () => {
319
    for (const color of cssNamedColors) {
320
      const threshold = Math.random()
321
322
      const fcc = new FontColorContrast(color.name, threshold)
323
324
      fcc.getColor()
325
326
      expect(fcc.red).toBe(parseInt((color.hex).substring(1, 3), 16))
327
      expect(fcc.green).toBe(parseInt((color.hex).substring(3, 5), 16))
328
      expect(fcc.blue).toBe(parseInt((color.hex).substring(5, 7), 16))
329
      expect(fcc.threshold).toBe(threshold)
330
    }
331
    expect(isRgb).toHaveBeenCalledTimes(cssNamedColors.length)
332
    expect(setColorsFromRgbNumbers).toHaveBeenCalledTimes(0)
333
    expect(isHexString).toHaveBeenCalledTimes(cssNamedColors.length)
334
    expect(setColorsFromHexString).toHaveBeenCalledTimes(cssNamedColors.length)
335
    expect(isNumber).toHaveBeenCalledTimes(0)
336
    expect(setColorsFromNumber).toHaveBeenCalledTimes(0)
337
    expect(isArray).toHaveBeenCalledTimes(0)
338
    expect(setColorsFromArray).toHaveBeenCalledTimes(0)
339
    expect(contrastFromHSP).toHaveBeenCalledTimes(cssNamedColors.length)
340
  })
341
})
342
343
describe('isRgb()', () => {
344
  let isValidNumber: jest.SpyInstance<boolean, [num: any, numberType: number]>
345
346
  beforeEach(() => {
347
    isValidNumber = jest
348
      .spyOn(FontColorContrast, 'isValidNumber')
349
  })
350
351
  afterEach(() => {
352
    jest.restoreAllMocks()
353
  })
354
355
  test('functions are called correctly', () => {
356
    const fcc = new FontColorContrast(10, 0xff, 255, 0.3)
357
358
    expect(fcc.isRgb()).toBeTruthy()
359
    expect(isValidNumber).toHaveBeenCalledTimes(4)
360
    expect(isValidNumber).toHaveBeenNthCalledWith(1, 10, NumberType.COLOR)
361
    expect(isValidNumber).toHaveBeenNthCalledWith(2, 255, NumberType.COLOR)
362
    expect(isValidNumber).toHaveBeenNthCalledWith(3, 255, NumberType.COLOR)
363
    expect(isValidNumber).toHaveBeenNthCalledWith(4, 0.3, NumberType.THRESHOLD)
364
  })
365
366
  test('functions are called correctly without threshold', () => {
367
    const fcc = new FontColorContrast(10, 0xff, 255)
368
369
    expect(fcc.isRgb()).toBeTruthy()
370
    expect(isValidNumber).toHaveBeenCalledTimes(4)
371
    expect(isValidNumber).toHaveBeenNthCalledWith(1, 10, NumberType.COLOR)
372
    expect(isValidNumber).toHaveBeenNthCalledWith(2, 255, NumberType.COLOR)
373
    expect(isValidNumber).toHaveBeenNthCalledWith(3, 255, NumberType.COLOR)
374
    expect(isValidNumber).toHaveBeenNthCalledWith(4, undefined, NumberType.THRESHOLD)
375
  })
376
377
  test('false on the second param', () => {
378
    const fcc = new FontColorContrast(10, 0x100, 255, 0.3)
379
380
    expect(fcc.isRgb()).toBeFalsy()
381
    expect(isValidNumber).toHaveBeenCalledWith(256, NumberType.COLOR)
382
    expect(isValidNumber).toHaveBeenCalledWith(10, NumberType.COLOR)
383
    expect(isValidNumber).toHaveBeenCalledTimes(2)
384
  })
385
})
386
387
describe('isHexString()', () => {
388
  let isValidNumber: jest.SpyInstance<boolean, [num: any, numberType: NumberType]>
389
  let isNotSet: jest.SpyInstance<boolean, [value: any]>
390
391
  beforeEach(() => {
392
    isValidNumber = jest
393
      .spyOn(FontColorContrast, 'isValidNumber')
394
395
    isNotSet = jest
396
      .spyOn(FontColorContrast, 'isNotSet')
397
  })
398
399
  afterEach(() => {
400
    jest.restoreAllMocks()
401
  })
402
403
  test('result for valid 3 chars string', () => {
404
    const fcc = new FontColorContrast('fff', 0.6, null as unknown as undefined)
405
406
    expect(fcc.isHexString()).toBeTruthy()
407
    expect(isValidNumber).toHaveBeenCalledTimes(2)
408
    expect(isValidNumber).toHaveBeenNthCalledWith(1, 0xfff, NumberType.RGB)
409
    expect(isValidNumber).toHaveBeenNthCalledWith(2, 0.6, NumberType.THRESHOLD)
410
    expect(isNotSet).toHaveBeenCalledTimes(2)
411
    expect(isNotSet).toHaveBeenNthCalledWith(1, null)
412
    expect(isNotSet).toHaveBeenNthCalledWith(2, undefined)
413
  })
414
415
  test('result for valid 3 chars string with hash', () => {
416
    const fcc = new FontColorContrast('#fff', 0.6)
417
418
    expect(fcc.isHexString()).toBeTruthy()
419
    expect(isValidNumber).toHaveBeenNthCalledWith(1, 0xfff, NumberType.RGB)
420
    expect(isValidNumber).toHaveBeenNthCalledWith(2, 0.6, NumberType.THRESHOLD)
421
  })
422
423
  test('result for valid 3 chars string with hash and space', () => {
424
    const fcc = new FontColorContrast('# 000', 0.6)
425
426
    expect(fcc.isHexString()).toBeTruthy()
427
    expect(isValidNumber).toHaveBeenNthCalledWith(1, 0x000, NumberType.RGB)
428
  })
429
430
  test('result for string color with nor 3 or 6 chars', () => {
431
    const fcc = new FontColorContrast('#fcc3')
432
433
    expect(fcc.isHexString()).toBeFalsy()
434
    expect(isValidNumber).toHaveBeenNthCalledWith(1, false, NumberType.RGB)
435
  })
436
437
  test('result for invalid string color', () => {
438
    const fcc = new FontColorContrast('tex')
439
440
    expect(fcc.isHexString()).toBeFalsy()
441
    expect(isValidNumber).toHaveBeenNthCalledWith(1, NaN, NumberType.RGB)
442
  })
443
444
  test('result for invalid threshold', () => {
445
    const fcc = new FontColorContrast('fcc', 10)
446
447
    expect(fcc.isHexString()).toBeFalsy()
448
    expect(isValidNumber).toHaveBeenNthCalledWith(1, 0xfcc, NumberType.RGB)
449
    expect(isValidNumber).toHaveBeenNthCalledWith(2, 10, NumberType.THRESHOLD)
450
  })
451
452
  test('result for not a string', () => {
453
    const fcc = new FontColorContrast(45)
454
455
    expect(fcc.isHexString()).toBeFalsy()
456
    expect(isValidNumber).toHaveBeenNthCalledWith(1, false, NumberType.RGB)
457
  })
458
459
  test('result when blue is set', () => {
460
    const fcc = new FontColorContrast('#FC0523', 0.5, 0xff)
461
462
    expect(fcc.isHexString()).toBeFalsy()
463
    expect(isValidNumber).toHaveBeenNthCalledWith(1, 0xFC0523, NumberType.RGB)
464
    expect(isValidNumber).toHaveBeenNthCalledWith(2, 0.5, NumberType.THRESHOLD)
465
    expect(isNotSet).toHaveBeenCalledWith(0xff)
466
  })
467
468
  test('result when threshold is set', () => {
469
    const fcc = new FontColorContrast('#FC0523', 0.5, undefined, 0xff)
470
471
    expect(fcc.isHexString()).toBeFalsy()
472
    expect(isValidNumber).toHaveBeenNthCalledWith(1, 0xFC0523, NumberType.RGB)
473
    expect(isValidNumber).toHaveBeenNthCalledWith(2, 0.5, NumberType.THRESHOLD)
474
    expect(isNotSet).toHaveBeenCalledWith(0xff)
475
    expect(isNotSet).toHaveBeenCalledWith(undefined)
476
  })
477
})
478
479
describe('isNumber()', () => {
480
  let isValidNumber: jest.SpyInstance<boolean, [num: any, numberType: NumberType]>
481
  let isNotSet: jest.SpyInstance<boolean, [value: any]>
482
483
  beforeEach(() => {
484
    isValidNumber = jest
485
      .spyOn(FontColorContrast, 'isValidNumber')
486
487
    isNotSet = jest
488
      .spyOn(FontColorContrast, 'isNotSet')
489
  })
490
491
  afterEach(() => {
492
    jest.restoreAllMocks()
493
  })
494
495
  test('result for valid number and threshold', () => {
496
    const fcc = new FontColorContrast(0xffffff, 0.6, null as unknown as undefined)
497
498
    expect(fcc.isNumber()).toBeTruthy()
499
    expect(isValidNumber).toHaveBeenCalledTimes(2)
500
    expect(isValidNumber).toHaveBeenNthCalledWith(1, 0xffffff, NumberType.RGB)
501
    expect(isValidNumber).toHaveBeenNthCalledWith(2, 0.6, NumberType.THRESHOLD)
502
    expect(isNotSet).toHaveBeenCalledTimes(2)
503
    expect(isNotSet).toHaveBeenNthCalledWith(1, null)
504
    expect(isNotSet).toHaveBeenNthCalledWith(2, undefined)
505
  })
506
507
  test('result for invalid number', () => {
508
    const fcc = new FontColorContrast(0x1000000)
509
510
    expect(fcc.isNumber()).toBeFalsy()
511
    expect(isValidNumber).toHaveBeenNthCalledWith(1, 0x1000000, NumberType.RGB)
512
  })
513
514
  test('result for invalid threshold', () => {
515
    const fcc = new FontColorContrast(0, 10)
516
517
    expect(fcc.isNumber()).toBeFalsy()
518
    expect(isValidNumber).toHaveBeenNthCalledWith(1, 0, NumberType.RGB)
519
    expect(isValidNumber).toHaveBeenNthCalledWith(2, 10, NumberType.THRESHOLD)
520
  })
521
522
  test('result for a string', () => {
523
    const fcc = new FontColorContrast('45')
524
525
    expect(fcc.isNumber()).toBeFalsy()
526
    expect(isValidNumber).toHaveBeenNthCalledWith(1, '45', NumberType.RGB)
527
  })
528
529
  test('result for NaN', () => {
530
    const fcc = new FontColorContrast(Number('test'))
531
532
    expect(fcc.isNumber()).toBeFalsy()
533
    expect(isValidNumber).toHaveBeenNthCalledWith(1, NaN, NumberType.RGB)
534
  })
535
536
  test('result for Infinity', () => {
537
    const fcc = new FontColorContrast(Infinity)
538
539
    expect(fcc.isNumber()).toBeFalsy()
540
    expect(isValidNumber).toHaveBeenNthCalledWith(1, Infinity, NumberType.RGB)
541
  })
542
543
  test('result when blue is set', () => {
544
    const fcc = new FontColorContrast(0xFC0523, 0.5, 0xff)
545
546
    expect(fcc.isNumber()).toBeFalsy()
547
    expect(isValidNumber).toHaveBeenNthCalledWith(1, 0xFC0523, NumberType.RGB)
548
    expect(isValidNumber).toHaveBeenNthCalledWith(2, 0.5, NumberType.THRESHOLD)
549
    expect(isNotSet).toHaveBeenCalledWith(0xff)
550
  })
551
552
  test('result when threshold is set', () => {
553
    const fcc = new FontColorContrast(0, 0.5, undefined, 0xff)
554
555
    expect(fcc.isNumber()).toBeFalsy()
556
    expect(isValidNumber).toHaveBeenNthCalledWith(1, 0, NumberType.RGB)
557
    expect(isValidNumber).toHaveBeenNthCalledWith(2, 0.5, NumberType.THRESHOLD)
558
    expect(isNotSet).toHaveBeenNthCalledWith(1, undefined)
559
    expect(isNotSet).toHaveBeenNthCalledWith(2, 0xff)
560
  })
561
})
562
563
describe('isArray()', () => {
564
  let isValidNumber: jest.SpyInstance<boolean, [num: any, numberType: number]>
565
  let isNotSet: jest.SpyInstance<boolean, [num: any]>
566
  beforeEach(() => {
567
    isValidNumber = jest
568
      .spyOn(FontColorContrast, 'isValidNumber')
569
570
    isNotSet = jest
571
      .spyOn(FontColorContrast, 'isNotSet')
572
  })
573
574
  afterEach(() => {
575
    jest.restoreAllMocks()
576
  })
577
578
  test('result for valid array with threshold', () => {
579
    const fcc = new FontColorContrast([10, 0xff, 255], 0.3)
580
581
    expect(fcc.isArray()).toBeTruthy()
582
    expect(isValidNumber).toHaveBeenCalledTimes(4)
583
    expect(isValidNumber).toHaveBeenNthCalledWith(1, 10, NumberType.COLOR)
584
    expect(isValidNumber).toHaveBeenNthCalledWith(2, 255, NumberType.COLOR)
585
    expect(isValidNumber).toHaveBeenNthCalledWith(3, 255, NumberType.COLOR)
586
    expect(isValidNumber).toHaveBeenNthCalledWith(4, 0.3, NumberType.THRESHOLD)
587
  })
588
589
  test('result for valid array without threshold', () => {
590
    const fcc = new FontColorContrast([10, 0xff, 255])
591
592
    expect(fcc.isArray()).toBeTruthy()
593
    expect(isValidNumber).toHaveBeenCalledTimes(4)
594
    expect(isValidNumber).toHaveBeenNthCalledWith(1, 10, NumberType.COLOR)
595
    expect(isValidNumber).toHaveBeenNthCalledWith(2, 255, NumberType.COLOR)
596
    expect(isValidNumber).toHaveBeenNthCalledWith(3, 255, NumberType.COLOR)
597
    expect(isValidNumber).toHaveBeenNthCalledWith(4, undefined, NumberType.THRESHOLD)
598
    expect(isNotSet).toHaveBeenNthCalledWith(1, undefined)
599
    expect(isNotSet).toHaveBeenNthCalledWith(2, undefined)
600
  })
601
602
  test('result for invalid number', () => {
603
    const fcc = new FontColorContrast([0, 0xff, 0x100])
604
605
    expect(fcc.isArray()).toBeFalsy()
606
    expect(isValidNumber).toHaveBeenNthCalledWith(1, 0, NumberType.COLOR)
607
    expect(isValidNumber).toHaveBeenNthCalledWith(2, 0xff, NumberType.COLOR)
608
    expect(isValidNumber).toHaveBeenNthCalledWith(3, 0x100, NumberType.COLOR)
609
  })
610
611
  test('result for invalid threshold', () => {
612
    const fcc = new FontColorContrast([0, 0, 0], 10)
613
614
    expect(fcc.isArray()).toBeFalsy()
615
    expect(isValidNumber).toHaveBeenNthCalledWith(4, 10, NumberType.THRESHOLD)
616
  })
617
618
  test('result for an array with string', () => {
619
    const fcc = new FontColorContrast(['45' as unknown as number, 0, 0])
620
621
    expect(fcc.isArray()).toBeFalsy()
622
    expect(isValidNumber).toHaveBeenNthCalledWith(1, '45', NumberType.COLOR)
623
  })
624
625
  test('result for NaN', () => {
626
    const fcc = new FontColorContrast([Number('test'), 0, 5])
627
628
    expect(fcc.isArray()).toBeFalsy()
629
    expect(isValidNumber).toHaveBeenNthCalledWith(1, NaN, NumberType.COLOR)
630
  })
631
632
  test('result for Infinity', () => {
633
    const fcc = new FontColorContrast([Infinity, 0, 3])
634
635
    expect(fcc.isArray()).toBeFalsy()
636
    expect(isValidNumber).toHaveBeenNthCalledWith(1, Infinity, NumberType.COLOR)
637
  })
638
639
  test('result when blue is set', () => {
640
    const fcc = new FontColorContrast([0xfc, 0xff, 0x56], 0.5, 0xff)
641
642
    expect(fcc.isArray()).toBeFalsy()
643
    expect(isNotSet).toHaveBeenCalledWith(0xff)
644
  })
645
646
  test('result when threshold is set', () => {
647
    const fcc = new FontColorContrast([0, 0xff, 0xc5], 0.5, undefined, 0xff)
648
649
    expect(fcc.isArray()).toBeFalsy()
650
    expect(isNotSet).toHaveBeenNthCalledWith(2, 0xff)
651
  })
652
})
653
654
describe('setColorsFromRgbNumbers()', () => {
655
  test('colors are set and threshold is the default', () => {
656
    const fcc = new FontColorContrast(5, 10, 0xff)
657
    fcc.setColorsFromRgbNumbers()
658
    expect(fcc.red).toBe(5)
659
    expect(fcc.green).toBe(10)
660
    expect(fcc.blue).toBe(255)
661
    expect(fcc.threshold).toBe(0.5)
662
  })
663
664
  test('colors and threshold are set', () => {
665
    const fcc = new FontColorContrast(5, 10, 0xff, 0.3)
666
    fcc.setColorsFromRgbNumbers()
667
    expect(fcc.red).toBe(5)
668
    expect(fcc.green).toBe(10)
669
    expect(fcc.blue).toBe(255)
670
    expect(fcc.threshold).toBe(0.3)
671
  })
672
})
673
674
describe('setColorsFromArray()', () => {
675
  test('colors and threshold are set', () => {
676
    const fcc = new FontColorContrast([5, 10, 0xff], 0.3)
677
    fcc.setColorsFromArray()
678
    expect(fcc.red).toBe(5)
679
    expect(fcc.green).toBe(10)
680
    expect(fcc.blue).toBe(255)
681
    expect(fcc.threshold).toBe(0.3)
682
  })
683
684
  test('default threshold are set', () => {
685
    const fcc = new FontColorContrast([5, 10, 0xff])
686
    fcc.setColorsFromArray()
687
    expect(fcc.red).toBe(5)
688
    expect(fcc.green).toBe(10)
689
    expect(fcc.blue).toBe(255)
690
    expect(fcc.threshold).toBe(0.5)
691
  })
692
})
693
694
describe('setColorsFromHexString()', () => {
695
  test('colors and threshold are set with 3 chars', () => {
696
    const fcc = new FontColorContrast('fc1', 0.3)
697
    fcc.setColorsFromHexString()
698
    expect(fcc.red).toBe(0xff)
699
    expect(fcc.green).toBe(0xcc)
700
    expect(fcc.blue).toBe(0x11)
701
    expect(fcc.threshold).toBe(0.3)
702
  })
703
704
  test('colors and threshold are set with 6 chars and default theshold', () => {
705
    const fcc = new FontColorContrast('fce4d1')
706
    fcc.setColorsFromHexString()
707
    expect(fcc.red).toBe(0xfc)
708
    expect(fcc.green).toBe(0xe4)
709
    expect(fcc.blue).toBe(0xd1)
710
    expect(fcc.threshold).toBe(0.5)
711
  })
712
})
713
714
describe('setColorsFromNumber()', () => {
715
  test('extreme value', () => {
716
    const fcc = new FontColorContrast(1, 0.3) // 0x000fcc
717
    fcc.setColorsFromNumber()
718
    expect(fcc.red).toBe(0x00)
719
    expect(fcc.green).toBe(0x00)
720
    expect(fcc.blue).toBe(0x1)
721
    expect(fcc.threshold).toBe(0.3)
722
  })
723
  test('colors and threshold are set', () => {
724
    const fcc = new FontColorContrast(4044, 0.3) // 0x000fcc
725
    fcc.setColorsFromNumber()
726
    expect(fcc.red).toBe(0x00)
727
    expect(fcc.green).toBe(0x0f)
728
    expect(fcc.blue).toBe(0xcc)
729
    expect(fcc.threshold).toBe(0.3)
730
  })
731
732
  test('colors and default threshold are set', () => {
733
    const fcc = new FontColorContrast(0xfce4d1)
734
    fcc.setColorsFromNumber()
735
    expect(fcc.red).toBe(0xfc)
736
    expect(fcc.green).toBe(0xe4)
737
    expect(fcc.blue).toBe(0xd1)
738
    expect(fcc.threshold).toBe(0.5)
739
  })
740
})
741
742
describe('setThreshold(threshold)', () => {
743
  test('threshold is set', () => {
744
    const fcc = new FontColorContrast(0) // 0x000fcc
745
    fcc.setThreshold(1)
746
    expect(fcc.threshold).toBe(1)
747
  })
748
749
  test('default threshold is set', () => {
750
    const fcc = new FontColorContrast(0xfce4d1)
751
    fcc.setThreshold(undefined)
752
    expect(fcc.threshold).toBe(0.5)
753
  })
754
})
755
756
describe('isValidNumber(num, numberType)', () => {
757
  test('valid COLOR 0', () => {
758
    const valid = FontColorContrast.isValidNumber(0, NumberType.COLOR)
759
    expect(valid).toBeTruthy()
760
  })
761
762
  test('valid COLOR 0xff', () => {
763
    const valid = FontColorContrast.isValidNumber(0xff, NumberType.COLOR)
764
    expect(valid).toBeTruthy()
765
  })
766
767
  test('invalid negative COLOR', () => {
768
    const valid = FontColorContrast.isValidNumber(-3, NumberType.COLOR)
769
    expect(valid).toBeFalsy()
770
  })
771
772
  test('invalid COLOR bigger than 8 bits', () => {
773
    const valid = FontColorContrast.isValidNumber(256, NumberType.COLOR)
774
    expect(valid).toBeFalsy()
775
  })
776
777
  test('invalid COLOR NaN', () => {
778
    const valid = FontColorContrast.isValidNumber(Number('hello'), NumberType.COLOR)
779
    expect(valid).toBeFalsy()
780
  })
781
782
  test('invalid COLOR Infinity', () => {
783
    const valid = FontColorContrast.isValidNumber(Math.pow(10, 1000), NumberType.COLOR)
784
    expect(valid).toBeFalsy()
785
  })
786
787
  test('invalid COLOR decimal', () => {
788
    const valid = FontColorContrast.isValidNumber(123.5, NumberType.COLOR)
789
    expect(valid).toBeFalsy()
790
  })
791
792
  test('invalid COLOR not a number', () => {
793
    const valid = FontColorContrast.isValidNumber('foo', NumberType.COLOR)
794
    expect(valid).toBeFalsy()
795
  })
796
797
  test('invalid COLOR undefined', () => {
798
    const valid = FontColorContrast.isValidNumber(undefined, NumberType.COLOR)
799
    expect(valid).toBeFalsy()
800
  })
801
802
  test('invalid COLOR null', () => {
803
    const valid = FontColorContrast.isValidNumber(null, NumberType.COLOR)
804
    expect(valid).toBeFalsy()
805
  })
806
807
  test('invalid RGB bigger than 24 bits', () => {
808
    const valid = FontColorContrast.isValidNumber(0x100000000, NumberType.RGB)
809
    expect(valid).toBeFalsy()
810
  })
811
812
  test('valid THRESHOLD undefined', () => {
813
    const valid = FontColorContrast.isValidNumber(undefined, NumberType.THRESHOLD)
814
    expect(valid).toBeTruthy()
815
  })
816
817
  test('valid THRESHOLD null', () => {
818
    const valid = FontColorContrast.isValidNumber(null, NumberType.THRESHOLD)
819
    expect(valid).toBeTruthy()
820
  })
821
822
  test('invalid THRESHOLD bigger than 1', () => {
823
    const valid = FontColorContrast.isValidNumber(1.000000000000001, NumberType.THRESHOLD)
824
    expect(valid).toBeFalsy()
825
  })
826
})
827
828
describe('getCleanStringAndHexNum()', () => {
829
  test('not a string', () => {
830
    const fcc = new FontColorContrast(0)
831
    const [cleanString, hexNum] = fcc.getCleanStringAndHexNum()
832
    expect(cleanString).toBe('')
833
    expect(hexNum).toBeFalsy()
834
  })
835
836
  test('string with 4 chars', () => {
837
    const fcc = new FontColorContrast('#ffcc')
838
    const [cleanString, hexNum] = fcc.getCleanStringAndHexNum()
839
    expect(cleanString).toBe('')
840
    expect(hexNum).toBeFalsy()
841
  })
842
843
  test('valid string with hash and 3 chars', () => {
844
    const fcc = new FontColorContrast('#ffc')
845
    const [cleanString, hexNum] = fcc.getCleanStringAndHexNum()
846
    expect(cleanString).toBe('ffc')
847
    expect(hexNum).toBe(0xffc)
848
  })
849
850
  test('valid string with hash, space and 6 chars', () => {
851
    const fcc = new FontColorContrast('# ff4ffc')
852
    const [cleanString, hexNum] = fcc.getCleanStringAndHexNum()
853
    expect(cleanString).toBe('ff4ffc')
854
    expect(hexNum).toBe(0xff4ffc)
855
  })
856
857
  test('valid string without and 6 chars', () => {
858
    const fcc = new FontColorContrast('ff4ffc')
859
    const [cleanString, hexNum] = fcc.getCleanStringAndHexNum()
860
    expect(cleanString).toBe('ff4ffc')
861
    expect(hexNum).toBe(0xff4ffc)
862
  })
863
864
  test('valid string that generates NaN', () => {
865
    const fcc = new FontColorContrast('hellos')
866
    const [cleanString, hexNum] = fcc.getCleanStringAndHexNum()
867
    expect(cleanString).toBe('hellos')
868
    expect(hexNum).toBe(NaN)
869
  })
870
871
  test('named css color', () => {
872
    for (const color of cssNamedColors) {
873
      const expectedCleanString = color.hex.substring(1, 7)
874
      const expectedHexNum = Number('0x' + expectedCleanString)
875
876
      const fcc = new FontColorContrast(color.name)
877
878
      const [cleanString, hexNum] = fcc.getCleanStringAndHexNum()
879
      expect(cleanString).toBe(expectedCleanString)
880
      expect(hexNum).toBe(expectedHexNum)
881
    }
882
  })
883
})
884
885
describe('isNotSet(value)', () => {
886
  test('undefined', () => {
887
    const isSet = FontColorContrast.isNotSet(undefined)
888
    expect(isSet).toBeTruthy()
889
  })
890
891
  test('null', () => {
892
    const isSet = FontColorContrast.isNotSet(null)
893
    expect(isSet).toBeTruthy()
894
  })
895
896
  test('number', () => {
897
    const isSet = FontColorContrast.isNotSet(3)
898
    expect(isSet).toBeFalsy()
899
  })
900
901
  test('string', () => {
902
    const isSet = FontColorContrast.isNotSet('hi there')
903
    expect(isSet).toBeFalsy()
904
  })
905
})
906
907
describe('contrastFromHSP()', () => {
908
  const fcc = new FontColorContrast('#098')
909
  test('#098', () => {
910
    fcc.red = 0
911
    fcc.green = 0x99
912
    fcc.blue = 0x88
913
    const result = fcc.contrastFromHSP()
914
915
    expect(result).toBe('#ffffff')
916
  })
917
918
  test('#808080', () => {
919
    fcc.red = 0x80
920
    fcc.green = 0x80
921
    fcc.blue = 0x80
922
    const result = fcc.contrastFromHSP()
923
924
    expect(result).toBe('#000000')
925
  })
926
  test('#7f7f7f', () => {
927
    fcc.red = 0x7f
928
    fcc.green = 0x7f
929
    fcc.blue = 0x7f
930
    const result = fcc.contrastFromHSP()
931
932
    expect(result).toBe('#ffffff')
933
  })
934
935
  test('forced threshold 1', () => {
936
    fcc.red = 0x80
937
    fcc.green = 0x80
938
    fcc.blue = 0x80
939
    fcc.threshold = 1
940
    const result = fcc.contrastFromHSP()
941
942
    expect(result).toBe('#ffffff')
943
  })
944
945
  test('forced threshold 0', () => {
946
    fcc.red = 0x7f
947
    fcc.green = 0x7f
948
    fcc.blue = 0x7f
949
    fcc.threshold = 0
950
    const result = fcc.contrastFromHSP()
951
952
    expect(result).toBe('#000000')
953
  })
954
})
955