@radio-garden/ditojs-utils 2.85.0-0.5067ad799
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/package.json +43 -0
- package/src/__snapshots__/index.test.js.snap +88 -0
- package/src/array/flatten.js +14 -0
- package/src/array/flattten.test.js +29 -0
- package/src/array/index.js +2 -0
- package/src/array/shuffle.js +11 -0
- package/src/array/shuffle.test.js +25 -0
- package/src/base/base.js +118 -0
- package/src/base/base.test.js +590 -0
- package/src/base/index.js +1 -0
- package/src/class/index.js +1 -0
- package/src/class/mixin.js +29 -0
- package/src/class/mixin.test.js +70 -0
- package/src/dataPath/getEntriesAtDataPath.js +67 -0
- package/src/dataPath/getEntriesAtDataPath.test.js +204 -0
- package/src/dataPath/getValueAtDataPath.js +45 -0
- package/src/dataPath/getValueAtDataPath.test.js +140 -0
- package/src/dataPath/index.js +6 -0
- package/src/dataPath/normalizeDataPath.js +27 -0
- package/src/dataPath/normalizeDataPath.test.js +36 -0
- package/src/dataPath/parseDataPath.js +16 -0
- package/src/dataPath/parseDataPath.test.js +67 -0
- package/src/dataPath/setDataPathEntries.js +8 -0
- package/src/dataPath/setDataPathEntries.test.js +36 -0
- package/src/dataPath/setValueAtDataPath.js +13 -0
- package/src/dataPath/setValueAtDataPath.test.js +34 -0
- package/src/function/deprecate.js +9 -0
- package/src/function/index.js +4 -0
- package/src/function/toAsync.js +9 -0
- package/src/function/toAsync.test.js +31 -0
- package/src/function/toCallback.js +11 -0
- package/src/function/toCallback.test.js +29 -0
- package/src/function/toPromiseCallback.js +9 -0
- package/src/function/toPromiseCallback.test.js +24 -0
- package/src/html/escapeHtml.js +11 -0
- package/src/html/escapeHtml.test.js +19 -0
- package/src/html/index.js +2 -0
- package/src/html/stripHtml.js +23 -0
- package/src/html/stripHtml.test.js +37 -0
- package/src/index.js +10 -0
- package/src/index.test.js +7 -0
- package/src/object/asCallback.js +9 -0
- package/src/object/clone.js +75 -0
- package/src/object/clone.test.js +131 -0
- package/src/object/equals.js +36 -0
- package/src/object/equals.test.js +269 -0
- package/src/object/groupBy.js +15 -0
- package/src/object/groupBy.test.js +70 -0
- package/src/object/index.js +8 -0
- package/src/object/mapKeys.js +7 -0
- package/src/object/mapKeys.test.js +16 -0
- package/src/object/mapValues.js +9 -0
- package/src/object/mapValues.test.js +38 -0
- package/src/object/mergeDeeply.js +47 -0
- package/src/object/mergeDeeply.test.js +152 -0
- package/src/object/pick.js +11 -0
- package/src/object/pick.test.js +23 -0
- package/src/object/pickBy.js +11 -0
- package/src/object/pickBy.test.js +48 -0
- package/src/promise/index.js +2 -0
- package/src/promise/mapConcurrently.js +33 -0
- package/src/promise/mapSequentially.js +9 -0
- package/src/string/camelize.js +14 -0
- package/src/string/camelize.test.js +37 -0
- package/src/string/capitalize.js +7 -0
- package/src/string/capitalize.test.js +33 -0
- package/src/string/decamelize.js +27 -0
- package/src/string/decamelize.test.js +83 -0
- package/src/string/deindent.js +69 -0
- package/src/string/deindent.test.js +181 -0
- package/src/string/escapeRegexp.js +3 -0
- package/src/string/format.js +109 -0
- package/src/string/format.test.js +196 -0
- package/src/string/formatDate.js +13 -0
- package/src/string/formatDate.test.js +28 -0
- package/src/string/getCommonPrefix.js +35 -0
- package/src/string/getCommonPrefix.test.js +23 -0
- package/src/string/index.js +15 -0
- package/src/string/isAbsoluteUrl.js +7 -0
- package/src/string/isAbsoluteUrl.test.js +15 -0
- package/src/string/isCreditCard.js +21 -0
- package/src/string/isCreditCard.test.js +50 -0
- package/src/string/isDomain.js +9 -0
- package/src/string/isDomain.test.js +15 -0
- package/src/string/isEmail.js +6 -0
- package/src/string/isEmail.test.js +37 -0
- package/src/string/isHostname.js +8 -0
- package/src/string/isHostname.test.js +12 -0
- package/src/string/isUrl.js +23 -0
- package/src/string/isUrl.test.js +1595 -0
- package/src/string/labelize.js +17 -0
- package/src/string/labelize.test.js +39 -0
- package/src/timer/debounce.js +34 -0
- package/src/timer/debounce.test.js +101 -0
- package/src/timer/debounceAsync.js +60 -0
- package/src/timer/debounceAsync.test.js +143 -0
- package/src/timer/index.js +2 -0
- package/types/index.d.ts +939 -0
- package/types/tests/base.test-d.ts +172 -0
- package/types/tests/datapath.test-d.ts +75 -0
- package/types/tests/function.test-d.ts +137 -0
- package/types/tests/object.test-d.ts +190 -0
- package/types/tests/promise.test-d.ts +66 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export function labelize(str) {
|
|
2
|
+
// Handle hyphenated, underscored and camel-cased property names and
|
|
3
|
+
// expand them to title cased labels.
|
|
4
|
+
return str
|
|
5
|
+
? str.replace(
|
|
6
|
+
/[-_](?=\W)|([-_ ]|^)(\w)|([a-z])(?=[A-Z0-9])|(\d)([a-zA-Z])/g,
|
|
7
|
+
(all, hyphen, hyphenated, camel, decimal, decimalNext) =>
|
|
8
|
+
all === '-' || all === '_'
|
|
9
|
+
? ' '
|
|
10
|
+
: hyphenated
|
|
11
|
+
? `${hyphen ? ' ' : ''}${hyphenated.toUpperCase()}`
|
|
12
|
+
: camel
|
|
13
|
+
? `${camel} `
|
|
14
|
+
: `${decimal} ${decimalNext.toUpperCase()}`
|
|
15
|
+
)
|
|
16
|
+
: ''
|
|
17
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { labelize } from './labelize.js'
|
|
2
|
+
|
|
3
|
+
describe('labelize()', () => {
|
|
4
|
+
it('should labelize hyphenated text', () => {
|
|
5
|
+
expect(labelize('some-hyphenated-text')).toBe('Some Hyphenated Text')
|
|
6
|
+
expect(labelize('one-&-two', true)).toBe('One & Two')
|
|
7
|
+
expect(labelize('one-2-three', true)).toBe('One 2 Three')
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
it('should labelize underscored text', () => {
|
|
11
|
+
expect(labelize('some_underscored_text')).toBe('Some Underscored Text')
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
it('should labelize camel-cased text', () => {
|
|
15
|
+
expect(labelize('SomeCamelCasedText')).toBe('Some Camel Cased Text')
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
it('should labelize normal text', () => {
|
|
19
|
+
expect(labelize('some normal text')).toBe('Some Normal Text')
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('should split numbers and words', () => {
|
|
23
|
+
expect(labelize('one2')).toBe('One 2')
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('should split words and numbers both sides', () => {
|
|
27
|
+
expect(labelize('one2three')).toBe('One 2 Three')
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('should keep multiple numbers together', () => {
|
|
31
|
+
expect(labelize('one234five')).toBe('One 234 Five')
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('should return an empty string if nothing can be processed', () => {
|
|
35
|
+
expect(labelize()).toBe('')
|
|
36
|
+
expect(labelize(null)).toBe('')
|
|
37
|
+
expect(labelize('')).toBe('')
|
|
38
|
+
})
|
|
39
|
+
})
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { isNumber } from '../base/index.js'
|
|
2
|
+
|
|
3
|
+
export function debounce(func, options) {
|
|
4
|
+
const { delay, immediate } = isNumber(options) ? { delay: options } : options
|
|
5
|
+
|
|
6
|
+
let timer = null
|
|
7
|
+
let result
|
|
8
|
+
|
|
9
|
+
const debounced = function (...args) {
|
|
10
|
+
const callNow = immediate && !timer
|
|
11
|
+
clearTimeout(timer)
|
|
12
|
+
timer = setTimeout(async () => {
|
|
13
|
+
timer = null
|
|
14
|
+
if (!immediate) {
|
|
15
|
+
result = func.apply(this, args)
|
|
16
|
+
}
|
|
17
|
+
}, delay)
|
|
18
|
+
if (callNow) {
|
|
19
|
+
result = func.apply(this, args)
|
|
20
|
+
}
|
|
21
|
+
return result
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
debounced.cancel = function () {
|
|
25
|
+
const pending = timer !== null
|
|
26
|
+
if (pending) {
|
|
27
|
+
clearTimeout(timer)
|
|
28
|
+
timer = null
|
|
29
|
+
}
|
|
30
|
+
return pending
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return debounced
|
|
34
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { debounce } from './debounce.js'
|
|
2
|
+
import { vi } from 'vitest'
|
|
3
|
+
|
|
4
|
+
// Tell vitest to mock all timeout functions:
|
|
5
|
+
vi.useFakeTimers()
|
|
6
|
+
|
|
7
|
+
describe('debounce()', () => {
|
|
8
|
+
const fixture = Symbol('fixture')
|
|
9
|
+
|
|
10
|
+
it('should never execute if intervals are less than wait', () => {
|
|
11
|
+
const func = vi.fn()
|
|
12
|
+
const debounced = debounce(func, 1000)
|
|
13
|
+
for (let i = 0; i < 10; i++) {
|
|
14
|
+
vi.advanceTimersByTime(500)
|
|
15
|
+
debounced()
|
|
16
|
+
}
|
|
17
|
+
expect(func).toBeCalledTimes(0)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('should execute just once if an interval is big enough', () => {
|
|
21
|
+
const func = vi.fn()
|
|
22
|
+
const debounced = debounce(func, 1000)
|
|
23
|
+
for (let i = 0; i < 10; i++) {
|
|
24
|
+
vi.advanceTimersByTime(500)
|
|
25
|
+
debounced()
|
|
26
|
+
}
|
|
27
|
+
vi.advanceTimersByTime(1000)
|
|
28
|
+
debounced()
|
|
29
|
+
expect(func).toBeCalledTimes(1)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('should pass through argument', async () => {
|
|
33
|
+
const func = vi.fn(value => value)
|
|
34
|
+
const debounced = debounce(func, 1000)
|
|
35
|
+
expect(debounced(fixture)).toBeUndefined()
|
|
36
|
+
vi.advanceTimersByTime(1000)
|
|
37
|
+
expect(debounced()).toBe(fixture)
|
|
38
|
+
expect(func).toBeCalledTimes(1)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('should pass through return value', () => {
|
|
42
|
+
const func = vi.fn().mockReturnValue(fixture)
|
|
43
|
+
const debounced = debounce(func, 1000)
|
|
44
|
+
expect(debounced()).toBeUndefined()
|
|
45
|
+
vi.advanceTimersByTime(1000)
|
|
46
|
+
expect(debounced()).toBe(fixture)
|
|
47
|
+
expect(func).toBeCalledTimes(1)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('should pass through `this`', () => {
|
|
51
|
+
const func = vi.fn().mockReturnThis()
|
|
52
|
+
const debounced = debounce(func, 0)
|
|
53
|
+
const obj = {}
|
|
54
|
+
expect(debounced.call(obj)).toBeUndefined()
|
|
55
|
+
vi.advanceTimersByTime(1000)
|
|
56
|
+
expect(debounced.call(obj)).toBe(obj)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('should allow to cancel', () => {
|
|
60
|
+
const func = vi.fn()
|
|
61
|
+
const debounced = debounce(func, 1000)
|
|
62
|
+
debounced()
|
|
63
|
+
vi.advanceTimersByTime(500)
|
|
64
|
+
expect(debounced.cancel()).toBe(true)
|
|
65
|
+
expect(debounced.cancel()).toBe(false)
|
|
66
|
+
vi.advanceTimersByTime(500)
|
|
67
|
+
expect(func).toBeCalledTimes(0)
|
|
68
|
+
vi.advanceTimersByTime(1000)
|
|
69
|
+
expect(func).toBeCalledTimes(0)
|
|
70
|
+
debounced()
|
|
71
|
+
vi.advanceTimersByTime(1000)
|
|
72
|
+
expect(func).toBeCalledTimes(1)
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('should execute once immediately if intervals are less than wait', () => {
|
|
76
|
+
const func = vi.fn()
|
|
77
|
+
const debounced = debounce(func, { delay: 1000, immediate: true })
|
|
78
|
+
debounced()
|
|
79
|
+
expect(func).toBeCalledTimes(1)
|
|
80
|
+
for (let i = 0; i < 10; i++) {
|
|
81
|
+
vi.advanceTimersByTime(500)
|
|
82
|
+
debounced()
|
|
83
|
+
}
|
|
84
|
+
expect(func).toBeCalledTimes(1)
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
it(`should execute once immediately and once at the end with long enough intervals`, () => {
|
|
88
|
+
const func = vi.fn()
|
|
89
|
+
const debounced = debounce(func, { delay: 1000, immediate: true })
|
|
90
|
+
debounced()
|
|
91
|
+
expect(func).toBeCalledTimes(1)
|
|
92
|
+
for (let i = 0; i < 10; i++) {
|
|
93
|
+
vi.advanceTimersByTime(500)
|
|
94
|
+
debounced()
|
|
95
|
+
}
|
|
96
|
+
expect(func).toBeCalledTimes(1)
|
|
97
|
+
vi.advanceTimersByTime(1000)
|
|
98
|
+
debounced()
|
|
99
|
+
expect(func).toBeCalledTimes(2)
|
|
100
|
+
})
|
|
101
|
+
})
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { isNumber } from '../base/index.js'
|
|
2
|
+
|
|
3
|
+
export function debounceAsync(func, options) {
|
|
4
|
+
const { delay, immediate } = isNumber(options) ? { delay: options } : options
|
|
5
|
+
|
|
6
|
+
let timer = null
|
|
7
|
+
let callbacks = []
|
|
8
|
+
let cancelled = false
|
|
9
|
+
|
|
10
|
+
const resolve = result => {
|
|
11
|
+
for (const { resolve } of callbacks) {
|
|
12
|
+
resolve(result)
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const execute = async (that, args) => {
|
|
17
|
+
try {
|
|
18
|
+
resolve(await func.apply(that, args))
|
|
19
|
+
} catch (err) {
|
|
20
|
+
// Convention: reject the last waiting promise, while all the others are
|
|
21
|
+
// resolved with undefined.
|
|
22
|
+
const { reject } = callbacks.pop()
|
|
23
|
+
resolve(undefined)
|
|
24
|
+
reject(err)
|
|
25
|
+
}
|
|
26
|
+
callbacks = []
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const debounced = function (...args) {
|
|
30
|
+
return new Promise((resolve, reject) => {
|
|
31
|
+
const callNow = immediate && !timer
|
|
32
|
+
clearTimeout(timer)
|
|
33
|
+
timer = setTimeout(() => {
|
|
34
|
+
timer = null
|
|
35
|
+
if (!immediate) {
|
|
36
|
+
execute(this, args)
|
|
37
|
+
}
|
|
38
|
+
}, delay)
|
|
39
|
+
callbacks.push({ resolve, reject })
|
|
40
|
+
if (cancelled) {
|
|
41
|
+
resolve(undefined)
|
|
42
|
+
} else if (callNow) {
|
|
43
|
+
execute(this, args)
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
debounced.cancel = function () {
|
|
49
|
+
const pending = timer !== null
|
|
50
|
+
if (pending) {
|
|
51
|
+
resolve(undefined)
|
|
52
|
+
clearTimeout(timer)
|
|
53
|
+
timer = null
|
|
54
|
+
}
|
|
55
|
+
cancelled = true
|
|
56
|
+
return pending
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return debounced
|
|
60
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { debounceAsync } from './debounceAsync.js'
|
|
2
|
+
import { vi } from 'vitest'
|
|
3
|
+
|
|
4
|
+
// Tell vitest to mock all timeout functions:
|
|
5
|
+
vi.useFakeTimers()
|
|
6
|
+
|
|
7
|
+
describe('debounceAsync()', () => {
|
|
8
|
+
const fixture = Symbol('fixture')
|
|
9
|
+
|
|
10
|
+
it('should never execute if intervals are less than wait', () => {
|
|
11
|
+
const func = vi.fn()
|
|
12
|
+
const debounced = debounceAsync(func, 1000)
|
|
13
|
+
for (let i = 0; i < 10; i++) {
|
|
14
|
+
vi.advanceTimersByTime(500)
|
|
15
|
+
debounced()
|
|
16
|
+
}
|
|
17
|
+
expect(func).toBeCalledTimes(0)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('should execute just once if an interval is big enough', () => {
|
|
21
|
+
const func = vi.fn()
|
|
22
|
+
const debounced = debounceAsync(func, 1000)
|
|
23
|
+
for (let i = 0; i < 10; i++) {
|
|
24
|
+
vi.advanceTimersByTime(500)
|
|
25
|
+
debounced()
|
|
26
|
+
}
|
|
27
|
+
vi.advanceTimersByTime(1000)
|
|
28
|
+
debounced()
|
|
29
|
+
expect(func).toBeCalledTimes(1)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('should pass through argument', async () => {
|
|
33
|
+
expect.assertions(2)
|
|
34
|
+
const func = vi.fn(async value => value)
|
|
35
|
+
const debounced = debounceAsync(func, 1000)
|
|
36
|
+
const promise = debounced(fixture)
|
|
37
|
+
vi.advanceTimersByTime(1000)
|
|
38
|
+
expect(await promise).toBe(fixture)
|
|
39
|
+
expect(func).toBeCalledTimes(1)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it('should pass through return value', async () => {
|
|
43
|
+
expect.assertions(2)
|
|
44
|
+
const func = vi.fn().mockResolvedValueOnce(fixture)
|
|
45
|
+
const debounced = debounceAsync(func, 1000)
|
|
46
|
+
const promises = []
|
|
47
|
+
promises.push(debounced())
|
|
48
|
+
vi.advanceTimersByTime(1000)
|
|
49
|
+
promises.push(debounced())
|
|
50
|
+
expect(await Promise.all(promises)).toStrictEqual([fixture, fixture])
|
|
51
|
+
expect(func).toBeCalledTimes(1)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('should pass through `this`', async () => {
|
|
55
|
+
expect.assertions(2)
|
|
56
|
+
const func = vi.fn(async function () {
|
|
57
|
+
return this
|
|
58
|
+
})
|
|
59
|
+
const debounced = debounceAsync(func, 1000)
|
|
60
|
+
const obj = {}
|
|
61
|
+
const promises = []
|
|
62
|
+
promises.push(debounced.call(obj))
|
|
63
|
+
vi.advanceTimersByTime(1000)
|
|
64
|
+
promises.push(debounced.call(obj))
|
|
65
|
+
expect(await Promise.all(promises)).toStrictEqual([obj, obj])
|
|
66
|
+
expect(func).toBeCalledTimes(1)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('should allow to cancel', async () => {
|
|
70
|
+
expect.assertions(6)
|
|
71
|
+
const func = vi.fn()
|
|
72
|
+
const debounced = debounceAsync(func, 1000)
|
|
73
|
+
const promise = debounced()
|
|
74
|
+
vi.advanceTimersByTime(500)
|
|
75
|
+
expect(debounced.cancel()).toBe(true)
|
|
76
|
+
expect(debounced.cancel()).toBe(false)
|
|
77
|
+
vi.advanceTimersByTime(500)
|
|
78
|
+
expect(func).toBeCalledTimes(0)
|
|
79
|
+
expect(await promise).toBeUndefined()
|
|
80
|
+
vi.advanceTimersByTime(1000)
|
|
81
|
+
expect(func).toBeCalledTimes(0)
|
|
82
|
+
await debounced()
|
|
83
|
+
vi.advanceTimersByTime(1000)
|
|
84
|
+
expect(func).toBeCalledTimes(1)
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
it('should execute once immediately if intervals are less than wait', async () => {
|
|
88
|
+
expect.assertions(2)
|
|
89
|
+
const func = vi.fn()
|
|
90
|
+
const debounced = debounceAsync(func, { delay: 1000, immediate: true })
|
|
91
|
+
const promises = []
|
|
92
|
+
promises.push(debounced())
|
|
93
|
+
expect(func).toBeCalledTimes(1)
|
|
94
|
+
for (let i = 0; i < 10; i++) {
|
|
95
|
+
vi.advanceTimersByTime(500)
|
|
96
|
+
promises.push(debounced())
|
|
97
|
+
}
|
|
98
|
+
await Promise.all(promises)
|
|
99
|
+
expect(func).toBeCalledTimes(1)
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
it('should execute twice immediately with long enough intervals', async () => {
|
|
103
|
+
expect.assertions(3)
|
|
104
|
+
const func = vi.fn()
|
|
105
|
+
const debounced = debounceAsync(func, { delay: 1000, immediate: true })
|
|
106
|
+
const promises = []
|
|
107
|
+
promises.push(debounced())
|
|
108
|
+
expect(func).toBeCalledTimes(1)
|
|
109
|
+
for (let i = 0; i < 10; i++) {
|
|
110
|
+
vi.advanceTimersByTime(500)
|
|
111
|
+
promises.push(debounced())
|
|
112
|
+
}
|
|
113
|
+
expect(func).toBeCalledTimes(1)
|
|
114
|
+
vi.advanceTimersByTime(1000)
|
|
115
|
+
promises.push(debounced())
|
|
116
|
+
await Promise.all(promises)
|
|
117
|
+
expect(func).toBeCalledTimes(2)
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
it('should only reject the last waiting promise', async () => {
|
|
121
|
+
expect.assertions(5)
|
|
122
|
+
let count = 0
|
|
123
|
+
const func = vi.fn(() => {
|
|
124
|
+
if (++count > 1) {
|
|
125
|
+
throw new Error('boom')
|
|
126
|
+
}
|
|
127
|
+
})
|
|
128
|
+
const debounced = debounceAsync(func, { delay: 1000, immediate: true })
|
|
129
|
+
const promises = []
|
|
130
|
+
promises.push(debounced())
|
|
131
|
+
expect(func).toBeCalledTimes(1)
|
|
132
|
+
for (let i = 0; i < 10; i++) {
|
|
133
|
+
vi.advanceTimersByTime(500)
|
|
134
|
+
promises.push(debounced())
|
|
135
|
+
}
|
|
136
|
+
expect(func).toBeCalledTimes(1)
|
|
137
|
+
vi.advanceTimersByTime(1000)
|
|
138
|
+
await expect(debounced()).rejects.toThrow('boom')
|
|
139
|
+
const results = await Promise.all(promises)
|
|
140
|
+
expect(results).toStrictEqual(new Array(11).fill(undefined))
|
|
141
|
+
expect(func).toBeCalledTimes(2)
|
|
142
|
+
})
|
|
143
|
+
})
|