@codeleap/styles 5.8.2 → 5.8.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.
Files changed (69) hide show
  1. package/package.json +9 -15
  2. package/package.json.bak +8 -14
  3. package/src/classes/Cacher.ts +169 -0
  4. package/src/classes/StaleControl.ts +125 -0
  5. package/src/classes/StyleCache.ts +116 -0
  6. package/src/classes/StylePersistor.ts +62 -0
  7. package/src/{lib → classes}/StyleRegistry.ts +7 -12
  8. package/src/classes/index.ts +2 -0
  9. package/src/classes/tests/Cache.spec.ts +371 -0
  10. package/src/classes/tests/StaleControl.spec.ts +175 -0
  11. package/src/classes/tests/StyleCache.spec.ts +452 -0
  12. package/src/classes/tests/StylePersistor.spec.ts +231 -0
  13. package/src/{lib/constants.ts → constants.ts} +1 -0
  14. package/src/hooks/index.ts +4 -0
  15. package/src/hooks/tests/useCompositionStyles.spec.ts +107 -0
  16. package/src/hooks/tests/useStyleObserver.spec.ts +89 -0
  17. package/src/hooks/useCompositionStyles.ts +33 -0
  18. package/src/hooks/useNestedStylesByKey.ts +13 -0
  19. package/src/hooks/useStyleObserver.ts +19 -0
  20. package/src/hooks/useTheme.ts +16 -0
  21. package/src/index.ts +9 -5
  22. package/src/lib/createStyles.ts +10 -1
  23. package/src/lib/createTheme.ts +22 -13
  24. package/src/lib/index.ts +1 -10
  25. package/src/lib/tests/createStyles.spec.ts +151 -0
  26. package/src/tests/colors/baseColors.ts +166 -0
  27. package/src/tests/colors/darkMode.ts +232 -0
  28. package/src/tests/colors/lightMode.ts +285 -0
  29. package/src/tests/measures.ts +31 -0
  30. package/src/tests/theme.ts +58 -0
  31. package/src/theme/generateColorScheme.ts +53 -0
  32. package/src/theme/index.ts +3 -0
  33. package/src/theme/tests/generateColorScheme.spec.ts +118 -0
  34. package/src/theme/tests/themeStore.spec.ts +698 -0
  35. package/src/theme/tests/validateTheme.spec.ts +173 -0
  36. package/src/{lib → theme}/themeStore.ts +68 -3
  37. package/src/{lib → theme}/validateTheme.ts +13 -0
  38. package/src/tools/colors.ts +83 -39
  39. package/src/tools/deepClone.ts +10 -0
  40. package/src/tools/deepmerge.ts +10 -0
  41. package/src/{lib → tools}/hashKey.ts +7 -0
  42. package/src/tools/index.ts +6 -1
  43. package/src/tools/minifier.ts +38 -0
  44. package/src/tools/tests/colors.spec.ts +233 -0
  45. package/src/tools/tests/deepClone.spec.ts +102 -0
  46. package/src/tools/tests/deepmerge.spec.ts +155 -0
  47. package/src/tools/tests/hashKey.spec.ts +69 -0
  48. package/src/tools/tests/minifier.spec.ts +173 -0
  49. package/src/types/store.ts +2 -2
  50. package/src/types/style.ts +3 -3
  51. package/src/types/theme.ts +4 -4
  52. package/src/{lib/utils.ts → utils.ts} +3 -3
  53. package/src/{lib → variants}/borderCreator.ts +2 -2
  54. package/src/{lib → variants}/createAppVariants.ts +1 -1
  55. package/src/{lib → variants}/dynamicVariants.ts +1 -1
  56. package/src/variants/index.ts +6 -0
  57. package/src/{lib → variants}/spacing.ts +37 -24
  58. package/src/variants/tests/borderCreator.spec.ts +180 -0
  59. package/src/variants/tests/dynamicVariants.spec.ts +194 -0
  60. package/src/variants/tests/spacing.spec.ts +177 -0
  61. package/src/lib/Cacher.ts +0 -112
  62. package/src/lib/StaleControl.ts +0 -73
  63. package/src/lib/StyleCache.ts +0 -81
  64. package/src/lib/StylePersistor.ts +0 -28
  65. package/src/lib/hooks.ts +0 -64
  66. package/src/lib/minifier.ts +0 -20
  67. /package/src/{lib → tools}/multiplierProperty.ts +0 -0
  68. /package/src/{lib → variants}/defaultVariants.ts +0 -0
  69. /package/src/{lib → variants}/mediaQuery.ts +0 -0
@@ -0,0 +1,371 @@
1
+ import { describe, test, expect, beforeEach, mock } from 'bun:test'
2
+ import { Cache } from '../Cacher'
3
+ import { hashKey } from '../../tools'
4
+
5
+ interface MockStateStorage {
6
+ getItem: (key: string) => any
7
+ setItem: (key: string, value: any) => void
8
+ removeItem: (key: string) => void
9
+ }
10
+
11
+ describe('Cache', () => {
12
+ let cache: Cache<string>
13
+ let mockStorageInstance: MockStateStorage
14
+
15
+ beforeEach(() => {
16
+ mockStorageInstance = {
17
+ getItem: mock(() => null),
18
+ setItem: mock(() => {}),
19
+ removeItem: mock(() => {}),
20
+ }
21
+ })
22
+
23
+ describe('Constructor', () => {
24
+ test('should create cache without persistence when storage is null', () => {
25
+ cache = new Cache<string>('styles', null, false)
26
+
27
+ expect(cache.registryName).toBe('styles')
28
+ expect(cache.persistCache).toBe(false)
29
+ expect(cache.cache).toEqual({})
30
+ })
31
+
32
+ test('should create cache with persistence enabled by default when storage is provided', () => {
33
+ cache = new Cache<string>('components', mockStorageInstance)
34
+
35
+ expect(cache.registryName).toBe('components')
36
+ expect(cache.persistCache).toBe(true)
37
+ })
38
+
39
+ test('should load persisted cache when not staled', () => {
40
+ const futureDate = new Date()
41
+ futureDate.setDate(futureDate.getDate() + 5)
42
+ const persistedCache = { 'key1': 'value1' }
43
+
44
+ mockStorageInstance.getItem = mock((key: string) => {
45
+ if (key.includes('staleTime')) return futureDate.toISOString()
46
+ if (key.includes('cache')) return persistedCache
47
+ return null
48
+ })
49
+
50
+ cache = new Cache<string>('styles', mockStorageInstance)
51
+
52
+ expect(cache.cache).toEqual(persistedCache)
53
+ })
54
+
55
+ test('should clear storage and not load cache when staled', () => {
56
+ const pastDate = new Date()
57
+ pastDate.setDate(pastDate.getDate() - 1)
58
+ const persistedCache = { 'key1': 'value1' }
59
+
60
+ mockStorageInstance.getItem = mock((key: string) => {
61
+ if (key.includes('staleTime')) return pastDate.toISOString()
62
+ if (key.includes('cache')) return persistedCache
63
+ return null
64
+ })
65
+
66
+ cache = new Cache<string>('styles', mockStorageInstance)
67
+
68
+ expect(mockStorageInstance.removeItem).toHaveBeenCalledTimes(2)
69
+ expect(cache.cache).toEqual({})
70
+ })
71
+ })
72
+
73
+ describe('Persistence Keys', () => {
74
+ beforeEach(() => {
75
+ cache = new Cache<string>('components', mockStorageInstance)
76
+ })
77
+
78
+ test('should generate correct persistence key for cache', () => {
79
+ expect(cache.persistKeyCache).toBe('@styles.caches.components.cache')
80
+ })
81
+
82
+ test('should generate correct persistence key for stale time', () => {
83
+ expect(cache.persistKeyStaleTime).toBe('@styles.caches.components.staleTime')
84
+ })
85
+ })
86
+
87
+ describe('keyFor', () => {
88
+ beforeEach(() => {
89
+ cache = new Cache<string>('styles', null, false)
90
+ })
91
+
92
+ test('should generate cache key and return null for non-existent value', () => {
93
+ const result = cache.keyFor('base-key', ['data1', 'data2'])
94
+ const expectedKey = hashKey(['base-key', ['data1', 'data2']])
95
+
96
+ expect(result.key).toBe(expectedKey)
97
+ expect(result.value).toBeNull()
98
+ })
99
+
100
+ test('should return existing cached value', () => {
101
+ const cacheKey = hashKey(['base-key', 'data'])
102
+ const testValue = 'cached-value'
103
+
104
+ // Set up the cache with a known value
105
+ cache.cache[cacheKey] = testValue
106
+
107
+ const result = cache.keyFor('base-key', 'data')
108
+
109
+ expect(result.key).toBe(cacheKey)
110
+ expect(result.value).toBe(testValue)
111
+ })
112
+ })
113
+
114
+ describe('cacheFor', () => {
115
+ test('should store value in memory cache without persistence', () => {
116
+ cache = new Cache<string>('styles', null, false)
117
+
118
+ const result = cache.cacheFor('test-key', 'test-value')
119
+
120
+ expect(cache.cache['test-key']).toBe('test-value')
121
+ expect(result).toBe('test-value')
122
+ })
123
+
124
+ test('should store value and persist to storage when persistence enabled', () => {
125
+ cache = new Cache<string>('styles', mockStorageInstance)
126
+
127
+ const result = cache.cacheFor('test-key', 'test-value')
128
+
129
+ expect(cache.cache['test-key']).toBe('test-value')
130
+ expect(mockStorageInstance.setItem).toHaveBeenCalledWith(
131
+ '@styles.caches.styles.cache',
132
+ { 'test-key': 'test-value' }
133
+ )
134
+ expect(result).toBe('test-value')
135
+ })
136
+ })
137
+
138
+ describe('setCache', () => {
139
+ beforeEach(() => {
140
+ cache = new Cache<string>('styles', null, false)
141
+ })
142
+
143
+ test('should replace entire cache with new data', () => {
144
+ cache.cache = { 'old-key': 'old-value' }
145
+ const newCache = { 'new-key': 'new-value', 'another-key': 'another-value' }
146
+
147
+ cache.setCache(newCache)
148
+
149
+ expect(cache.cache).toEqual(newCache)
150
+ })
151
+
152
+ test('should set empty object when null is passed', () => {
153
+ cache.cache = { 'some-key': 'some-value' }
154
+
155
+ cache.setCache(null as any)
156
+
157
+ expect(cache.cache).toEqual({})
158
+ })
159
+ })
160
+
161
+ describe('clear', () => {
162
+ test('should clear memory cache and storage', () => {
163
+ cache = new Cache<string>('styles', mockStorageInstance)
164
+ cache.cache = { 'key1': 'value1', 'key2': 'value2' }
165
+
166
+ cache.clear()
167
+
168
+ expect(cache.cache).toEqual({})
169
+ expect(mockStorageInstance.removeItem).toHaveBeenCalledWith('@styles.caches.styles.staleTime')
170
+ expect(mockStorageInstance.removeItem).toHaveBeenCalledWith('@styles.caches.styles.cache')
171
+ })
172
+
173
+ test('should only clear memory cache when persistence disabled', () => {
174
+ cache = new Cache<string>('styles', null, false)
175
+ cache.cache = { 'key1': 'value1' }
176
+
177
+ cache.clear()
178
+
179
+ expect(cache.cache).toEqual({})
180
+ })
181
+ })
182
+
183
+ describe('loadStorage', () => {
184
+ test('should return default values when persistence disabled', () => {
185
+ cache = new Cache<string>('styles', null, false)
186
+
187
+ const result = cache.loadStorage()
188
+
189
+ expect(result.persistedCache).toEqual({})
190
+ expect(result.persistedStaleTime).toBeInstanceOf(Date)
191
+ expect(result.persistedStaleTime.getTime()).toBeGreaterThan(new Date().getTime())
192
+ })
193
+
194
+ test('should load values from storage when available', () => {
195
+ const testDate = new Date('2024-12-01T00:00:00Z')
196
+ const testCache = { 'stored-key': 'stored-value' }
197
+
198
+ mockStorageInstance.getItem = mock((key: string) => {
199
+ if (key.includes('staleTime')) return testDate.toISOString()
200
+ if (key.includes('cache')) return testCache
201
+ return null
202
+ })
203
+
204
+ cache = new Cache<string>('styles', mockStorageInstance)
205
+ const result = cache.loadStorage()
206
+
207
+ expect(result.persistedStaleTime).toEqual(testDate)
208
+ expect(result.persistedCache).toEqual(testCache)
209
+ })
210
+
211
+ test('should generate new stale time when not found in storage', () => {
212
+ mockStorageInstance.getItem = mock((key: string) => {
213
+ if (key.includes('staleTime')) return null
214
+ if (key.includes('cache')) return { 'key': 'value' }
215
+ return null
216
+ })
217
+
218
+ cache = new Cache<string>('styles', mockStorageInstance)
219
+ const result = cache.loadStorage()
220
+
221
+ expect(result.persistedStaleTime).toBeInstanceOf(Date)
222
+ expect(result.persistedStaleTime.getTime()).toBeGreaterThan(new Date().getTime())
223
+ })
224
+ })
225
+
226
+ describe('clearStorage', () => {
227
+ test('should remove items from storage when persistence enabled', () => {
228
+ cache = new Cache<string>('styles', mockStorageInstance)
229
+
230
+ cache.clearStorage()
231
+
232
+ expect(mockStorageInstance.removeItem).toHaveBeenCalledWith('@styles.caches.styles.staleTime')
233
+ expect(mockStorageInstance.removeItem).toHaveBeenCalledWith('@styles.caches.styles.cache')
234
+ })
235
+
236
+ test('should do nothing when persistence disabled', () => {
237
+ cache = new Cache<string>('styles', null, false)
238
+
239
+ cache.clearStorage()
240
+
241
+ // Should not throw or call any storage methods
242
+ expect(true).toBe(true)
243
+ })
244
+ })
245
+
246
+ describe('storeCache', () => {
247
+ beforeEach(() => {
248
+ cache = new Cache<string>('styles', mockStorageInstance)
249
+ })
250
+
251
+ test('should store current cache when no parameter provided', () => {
252
+ cache.cache = { 'current-key': 'current-value' }
253
+
254
+ cache.storeCache()
255
+
256
+ expect(mockStorageInstance.setItem).toHaveBeenCalledWith(
257
+ '@styles.caches.styles.cache',
258
+ { 'current-key': 'current-value' }
259
+ )
260
+ })
261
+
262
+ test('should store provided cache parameter', () => {
263
+ const customCache = { 'custom-key': 'custom-value' }
264
+
265
+ cache.storeCache(customCache)
266
+
267
+ expect(mockStorageInstance.setItem).toHaveBeenCalledWith(
268
+ '@styles.caches.styles.cache',
269
+ customCache
270
+ )
271
+ })
272
+
273
+ test('should do nothing when persistence disabled', () => {
274
+ cache = new Cache<string>('styles', null, false)
275
+ cache.cache = { 'key': 'value' }
276
+
277
+ cache.storeCache()
278
+
279
+ // Should not throw or call any storage methods
280
+ expect(true).toBe(true)
281
+ })
282
+ })
283
+
284
+ describe('storeStaleTime', () => {
285
+ test('should store stale time as ISO string when persistence enabled', () => {
286
+ cache = new Cache<string>('styles', mockStorageInstance)
287
+ const testDate = new Date('2024-12-01T00:00:00Z')
288
+
289
+ cache.storeStaleTime(testDate)
290
+
291
+ expect(mockStorageInstance.setItem).toHaveBeenCalledWith(
292
+ '@styles.caches.styles.staleTime',
293
+ '2024-12-01T00:00:00.000Z'
294
+ )
295
+ })
296
+
297
+ test('should do nothing when persistence disabled', () => {
298
+ cache = new Cache<string>('styles', null, false)
299
+ const testDate = new Date()
300
+
301
+ cache.storeStaleTime(testDate)
302
+
303
+ // Should not throw or call any storage methods
304
+ expect(true).toBe(true)
305
+ })
306
+ })
307
+
308
+ describe('generateStaleTime function', () => {
309
+ test('should generate stale time 7 days in the future', () => {
310
+ const startTime = new Date()
311
+ cache = new Cache<string>('styles', null, false)
312
+
313
+ const result = cache.loadStorage()
314
+ const endTime = new Date()
315
+
316
+ // Verify the stale time is approximately 7 days from now
317
+ const expectedMinTime = new Date(startTime)
318
+ expectedMinTime.setDate(expectedMinTime.getDate() + 7)
319
+
320
+ const expectedMaxTime = new Date(endTime)
321
+ expectedMaxTime.setDate(expectedMaxTime.getDate() + 7)
322
+
323
+ expect(result.persistedStaleTime.getTime()).toBeGreaterThanOrEqual(expectedMinTime.getTime())
324
+ expect(result.persistedStaleTime.getTime()).toBeLessThanOrEqual(expectedMaxTime.getTime())
325
+ })
326
+ })
327
+
328
+ describe('Integration tests', () => {
329
+ test('should handle full cache lifecycle with persistence', () => {
330
+ // Initial setup with fresh cache
331
+ mockStorageInstance.getItem = mock(() => null)
332
+ cache = new Cache<string>('compositions', mockStorageInstance)
333
+
334
+ // Add some data
335
+ const { key } = cache.keyFor('test-base', 'test-data')
336
+ cache.cacheFor(key, 'test-value')
337
+
338
+ // Verify the value is cached
339
+ const { value } = cache.keyFor('test-base', 'test-data')
340
+ expect(value).toBe('test-value')
341
+
342
+ // Verify storage was called
343
+ expect(mockStorageInstance.setItem).toHaveBeenCalled()
344
+
345
+ // Clear cache
346
+ cache.clear()
347
+ expect(cache.cache).toEqual({})
348
+ expect(mockStorageInstance.removeItem).toHaveBeenCalledTimes(2)
349
+ })
350
+
351
+ test('should handle cache restoration from storage', () => {
352
+ const futureDate = new Date()
353
+ futureDate.setDate(futureDate.getDate() + 5)
354
+ const storedCache = { 'stored-key': 'stored-value' }
355
+
356
+ mockStorageInstance.getItem = mock((key: string) => {
357
+ if (key.includes('staleTime')) return futureDate.toISOString()
358
+ if (key.includes('cache')) return storedCache
359
+ return null
360
+ })
361
+
362
+ cache = new Cache<string>('responsive', mockStorageInstance)
363
+
364
+ expect(cache.cache).toEqual(storedCache)
365
+
366
+ // Should be able to retrieve the stored value
367
+ const cachedValue = cache.cache['stored-key']
368
+ expect(cachedValue).toBe('stored-value')
369
+ })
370
+ })
371
+ })
@@ -0,0 +1,175 @@
1
+ import { describe, test, expect, beforeEach, afterEach, mock } from 'bun:test'
2
+ import { StaleControl } from '../StaleControl'
3
+
4
+ describe('StaleControl', () => {
5
+ let staleControl: StaleControl
6
+
7
+ beforeEach(() => {
8
+ staleControl = new StaleControl()
9
+ })
10
+
11
+ afterEach(() => {
12
+ staleControl.destroy()
13
+ })
14
+
15
+ describe('constructor', () => {
16
+ test('should create instance with default values', () => {
17
+ expect(staleControl).toBeInstanceOf(StaleControl)
18
+ })
19
+
20
+ test('should create instance with custom values', () => {
21
+ const customStaleControl = new StaleControl(120, '::', 60000)
22
+ expect(customStaleControl).toBeInstanceOf(StaleControl)
23
+ customStaleControl.destroy()
24
+ })
25
+ })
26
+
27
+ describe('insertStaleTime', () => {
28
+ test('should insert stale time into value', () => {
29
+ const value = 'test-value'
30
+ const result = staleControl.insertStaleTime(value)
31
+
32
+ expect(result).toInclude(value)
33
+ expect(result).toInclude('//:')
34
+ expect(result.split('//:')).toHaveLength(2)
35
+ })
36
+
37
+ test('should handle empty string', () => {
38
+ const result = staleControl.insertStaleTime('')
39
+ expect(result).toInclude('//:')
40
+ })
41
+ })
42
+
43
+ describe('extractStaleTime', () => {
44
+ test('should extract stale time and original value', () => {
45
+ const originalValue = 'test-value'
46
+ const valueWithStaleTime = staleControl.insertStaleTime(originalValue)
47
+
48
+ const result = staleControl.extractStaleTime(valueWithStaleTime)
49
+
50
+ expect(result.value).toBe(originalValue)
51
+ expect(result.staleTime).toBeInstanceOf(Date)
52
+ expect(result.staleTime.getTime()).toBeGreaterThan(Date.now())
53
+ })
54
+
55
+ test('should handle value without stale time', () => {
56
+ const value = 'plain-value'
57
+ const result = staleControl.extractStaleTime(value)
58
+
59
+ expect(result.value).toBe(value)
60
+ expect(result.staleTime.getTime()).toBe(0)
61
+ })
62
+
63
+ test('should handle malformed stale time', () => {
64
+ const value = 'test//:invalid-date'
65
+ const result = staleControl.extractStaleTime(value)
66
+
67
+ expect(result.value).toBe('test')
68
+ expect(result.staleTime.toString()).toBe('Invalid Date')
69
+ })
70
+ })
71
+
72
+ describe('isStaled', () => {
73
+ test('should return false for fresh value', () => {
74
+ const value = staleControl.insertStaleTime('fresh-value')
75
+ const isStaled = staleControl.isStaled(value)
76
+
77
+ expect(isStaled).toBeFalse()
78
+ })
79
+
80
+ test('should return true for expired value', () => {
81
+ const expiredControl = new StaleControl(-60)
82
+ const value = expiredControl.insertStaleTime('expired-value')
83
+ const isStaled = expiredControl.isStaled(value)
84
+
85
+ expect(isStaled).toBeTrue()
86
+ expiredControl.destroy()
87
+ })
88
+
89
+ test('should handle value without stale time', () => {
90
+ const isStaled = staleControl.isStaled('plain-value')
91
+ expect(isStaled).toBeTrue()
92
+ })
93
+ })
94
+
95
+ describe('refreshStaleTime', () => {
96
+ test('should refresh stale time', () => {
97
+ const originalValue = 'test-value'
98
+ const originalStale = staleControl.insertStaleTime(originalValue)
99
+
100
+ Bun.sleepSync(10)
101
+
102
+ const refreshed = staleControl.refreshStaleTime(originalStale)
103
+
104
+ const originalExtracted = staleControl.extractStaleTime(originalStale)
105
+ const refreshedExtracted = staleControl.extractStaleTime(refreshed)
106
+
107
+ expect(refreshedExtracted.value).toBe(originalValue)
108
+ expect(refreshedExtracted.staleTime.getTime()).toBeGreaterThan(
109
+ originalExtracted.staleTime.getTime()
110
+ )
111
+ })
112
+ })
113
+
114
+ describe('cacheWiper', () => {
115
+ test('should throw error when called', () => {
116
+ expect(() => staleControl.cacheWiper()).toThrow(
117
+ 'Cache Wiper not implemented - Requires storage integration for future use'
118
+ )
119
+ })
120
+ })
121
+
122
+ describe('interval management', () => {
123
+ test('should register and unregister cache wiper', () => {
124
+ const mockCacheWiper = mock(() => {})
125
+ staleControl.cacheWiper = mockCacheWiper
126
+
127
+ staleControl.registerCacheWiper()
128
+ staleControl.unregisterCacheWiper()
129
+
130
+ expect(mockCacheWiper).not.toHaveBeenCalled()
131
+ })
132
+
133
+ test('should handle multiple register calls', () => {
134
+ const mockCacheWiper = mock(() => {})
135
+ staleControl.cacheWiper = mockCacheWiper
136
+
137
+ staleControl.registerCacheWiper()
138
+ staleControl.registerCacheWiper()
139
+ staleControl.unregisterCacheWiper()
140
+
141
+ expect(mockCacheWiper).not.toHaveBeenCalled()
142
+ })
143
+
144
+ test('should unregister non-existent wiper without error', () => {
145
+ expect(() => staleControl.unregisterCacheWiper()).not.toThrow()
146
+ })
147
+ })
148
+
149
+ describe('destroy', () => {
150
+ test('should clean up resources', () => {
151
+ const mockCacheWiper = mock(() => {})
152
+ staleControl.cacheWiper = mockCacheWiper
153
+
154
+ staleControl.registerCacheWiper()
155
+ staleControl.destroy()
156
+
157
+ expect(mockCacheWiper).not.toHaveBeenCalled()
158
+ })
159
+ })
160
+
161
+ describe('custom staleTimeIdentifier', () => {
162
+ test('should work with custom identifier', () => {
163
+ const customControl = new StaleControl(60, '::')
164
+ const value = customControl.insertStaleTime('test')
165
+
166
+ expect(value).toInclude('::')
167
+ expect(value.split('::')).toHaveLength(2)
168
+
169
+ const extracted = customControl.extractStaleTime(value)
170
+ expect(extracted.value).toBe('test')
171
+
172
+ customControl.destroy()
173
+ })
174
+ })
175
+ })