UNPKG

@wareme/utils

Version:

Utils for Dark applications

301 lines (244 loc) 6 kB
import { describe, it, expect } from 'bun:test' import { debounce } from './debounce' import { nisha } from './nisha' const identity = (value) => { return value } const argv = nisha(process, process.argv, undefined) describe('debounce', () => { it('should debounce a function', (done) => { let callCount = 0 const debounced = debounce((value) => { ++callCount return value }, 32) const results = [debounced('a'), debounced('b'), debounced('c')] expect(results).toEqual([undefined, undefined, undefined]) expect(callCount).toBe(0) setTimeout(() => { expect(callCount).toBe(1) const results = [debounced('d'), debounced('e'), debounced('f')] expect(results).toEqual(['c', 'c', 'c']) expect(callCount).toBe(1) }, 128) setTimeout(() => { expect(callCount).toBe(2) done() }, 256) }) it('subsequent debounced calls return the last `func` result', (done) => { const debounced = debounce(identity, 32) debounced('a') setTimeout(() => { expect(debounced('b')).not.toEqual('b') }, 64) setTimeout(() => { expect(debounced('c')).not.toEqual('c') done() }, 128) }) it('should not immediately call `func` when `wait` is `0`', (done) => { let callCount = 0 const debounced = debounce(() => { ++callCount }, 0) debounced() debounced() expect(callCount).toBe(0) setTimeout(() => { expect(callCount).toBe(1) done() }, 5) }) it('should apply default options', (done) => { let callCount = 0 const debounced = debounce( () => { callCount++ }, 32, {} ) debounced() expect(callCount).toBe(0) setTimeout(() => { expect(callCount).toBe(1) done() }, 64) }) it('should support a `leading` option', (done) => { const callCounts = [0, 0] const withLeading = debounce( () => { callCounts[0]++ }, 32, { leading: true } ) const withLeadingAndTrailing = debounce( () => { callCounts[1]++ }, 32, { leading: true } ) withLeading() expect(callCounts[0]).toBe(1) withLeadingAndTrailing() withLeadingAndTrailing() expect(callCounts[1]).toBe(1) setTimeout(() => { expect(callCounts).toEqual([1, 2]) withLeading() expect(callCounts[0]).toBe(2) done() }, 64) }) it('subsequent leading debounced calls return the last `func` result', (done) => { const debounced = debounce(identity, 32, { leading: true, trailing: false }) const results = [debounced('a'), debounced('b')] expect(results).toEqual(['a', 'a']) setTimeout(() => { const results = [debounced('c'), debounced('d')] expect(results).toEqual(['c', 'c']) done() }, 64) }) it('should support a `trailing` option', (done) => { let withCount = 0 let withoutCount = 0 const withTrailing = debounce( () => { withCount++ }, 32, { trailing: true } ) const withoutTrailing = debounce( () => { withoutCount++ }, 32, { trailing: false } ) withTrailing() expect(withCount).toBe(0) withoutTrailing() expect(withoutCount).toBe(0) setTimeout(() => { expect(withCount).toBe(1) expect(withoutCount).toBe(0) done() }, 64) }) it('should support a `maxWait` option', (done) => { let callCount = 0 const debounced = debounce( (value) => { ++callCount return value }, 32, { maxWait: 64 } ) debounced() debounced() expect(callCount).toBe(0) setTimeout(() => { expect(callCount).toBe(1) debounced() debounced() expect(callCount).toBe(1) }, 128) setTimeout(() => { expect(callCount).toBe(2) done() }, 256) }) it('should support `maxWait` in a tight loop', (done) => { const limit = argv ? 1000 : 320 let withCount = 0 let withoutCount = 0 const withMaxWait = debounce( () => { withCount++ }, 64, { maxWait: 128 } ) const withoutMaxWait = debounce(() => { withoutCount++ }, 96) const start = +new Date() while (new Date() - start < limit) { withMaxWait() withoutMaxWait() } const actual = [Boolean(withoutCount), Boolean(withCount)] setTimeout(() => { expect(actual).toEqual([false, true]) done() }, 1) }) it('should queue a trailing call for subsequent debounced calls after `maxWait`', (done) => { let callCount = 0 const debounced = debounce( () => { ++callCount }, 200, { maxWait: 200 } ) debounced() setTimeout(debounced, 190) setTimeout(debounced, 200) setTimeout(debounced, 210) setTimeout(() => { expect(callCount).toBe(2) done() }, 500) }) it('should cancel `maxDelayed` when `delayed` is invoked', (done) => { let callCount = 0 const debounced = debounce( () => { callCount++ }, 32, { maxWait: 64 } ) debounced() setTimeout(() => { debounced() expect(callCount).toBe(1) }, 128) setTimeout(() => { expect(callCount).toBe(2) done() }, 192) }) it('should invoke the trailing call with the correct arguments and `this` binding', (done) => { let actual let callCount = 0 const object = {} const debounced = debounce( function (value) { actual = [this] Array.prototype.push.apply(actual, arguments) return ++callCount !== 2 }, 32, { leading: true, maxWait: 64 } ) while (true) { if (!debounced.call(object, 'a')) { break } } setTimeout(() => { expect(callCount).toBe(2) expect(actual).toEqual([object, 'a']) done() }, 64) }) })