Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: improve test coverage #2327

Merged
merged 8 commits into from
Oct 25, 2022
84 changes: 84 additions & 0 deletions packages/core/useEventListener/index.test.ts
@@ -0,0 +1,84 @@
import { noop } from '@vueuse/shared'
import { isVue2 } from 'vue-demi'
import type { Ref } from 'vue'
import { effectScope, nextTick, ref } from 'vue'
import { useEventListener } from '.'

describe('useEventListener', () => {
let target: Ref<HTMLDivElement | null>
let listener: () => any

beforeEach(() => {
target = ref(document.createElement('div'))
listener = vi.fn()
})

it('should not listen when target is invalid', async () => {
useEventListener(target, 'click', listener)
const el = target.value
target.value = null
await nextTick()
el?.dispatchEvent(new MouseEvent('click'))
await nextTick()

expect(listener).toHaveBeenCalledTimes(isVue2 ? 1 : 0)
expect(useEventListener(null, 'click', listener)).toBe(noop)
})

function getTargetName(useTarget: boolean) {
return useTarget ? 'element' : 'window'
}

function getArgs(useTarget: boolean) {
return (useTarget ? [target, 'click', listener] : ['click', listener])
}

function trigger(useTarget: boolean) {
(useTarget ? target.value : window)!.dispatchEvent(new MouseEvent('click'))
}

function testTarget(useTarget: boolean) {
it(`should ${getTargetName(useTarget)} listen event`, async () => {
// @ts-expect-error mock different args
const stop = useEventListener(...getArgs(useTarget))

trigger(useTarget)

await nextTick()

expect(listener).toHaveBeenCalledTimes(1)
})

it(`should ${getTargetName(useTarget)} manually stop listening event`, async () => {
// @ts-expect-error mock different args
const stop = useEventListener(...getArgs(useTarget))

stop()

trigger(useTarget)

await nextTick()

expect(listener).toHaveBeenCalledTimes(0)
})

it(`should ${getTargetName(useTarget)} auto stop listening event`, async () => {
const scope = effectScope()
await scope.run(async () => {
// @ts-expect-error mock different args
useEventListener(...getArgs(useTarget))
})

await scope.stop()

trigger(useTarget)

await nextTick()

expect(listener).toHaveBeenCalledTimes(isVue2 ? 1 : 0)
})
}

testTarget(false)
testTarget(true)
})
38 changes: 38 additions & 0 deletions packages/core/useNow/index.test.ts
@@ -0,0 +1,38 @@
import { promiseTimeout } from '@vueuse/shared'
import { useNow } from '.'

describe('useNow', () => {
it('should get now timestamp by default', async () => {
const now = useNow()

expect(+now.value).toBeLessThanOrEqual(+new Date())
})

function testControl(interval: any) {
it(`should control now timestamp by ${interval}`, async () => {
let initial = +new Date()
const { now, pause, resume } = useNow({ controls: true, interval })

expect(+now.value).toBeGreaterThanOrEqual(initial)

await promiseTimeout(50)

expect(+now.value).toBeGreaterThan(initial)

initial = +now.value

pause()
await promiseTimeout(50)

expect(+now.value).toBe(initial)

resume()
await promiseTimeout(50)

expect(+now.value).toBeGreaterThan(initial)
})
}

testControl('requestAnimationFrame')
testControl(50)
})
14 changes: 14 additions & 0 deletions packages/core/useTimestamp/index.test.ts
Expand Up @@ -13,41 +13,55 @@ describe('useTimestamp', () => {
})

it('allows for a delayed start using requestAnimationFrame', async () => {
let now
const callback = vi.fn((time) => {
now = time
})
const { resume, timestamp } = useTimestamp({
controls: true,
immediate: false,
callback,
})

const initial = timestamp.value

await promiseTimeout(50)

expect(timestamp.value).toBe(initial)
expect(now).toBeUndefined()

resume()

await promiseTimeout(50)

expect(timestamp.value).greaterThan(initial)
expect(now).greaterThan(initial)
})

it('allows for a delayed start using common interval', async () => {
let now
const callback = vi.fn((time) => {
now = time
})
const { resume, timestamp } = useTimestamp({
controls: true,
immediate: false,
interval: 50,
callback,
})

const initial = timestamp.value

await promiseTimeout(50)

expect(timestamp.value).toBe(initial)
expect(now).toBeUndefined()

resume()

await promiseTimeout(50)

expect(timestamp.value).greaterThan(initial)
expect(now).greaterThan(initial)
})
})
29 changes: 29 additions & 0 deletions packages/shared/createEventHook/index.test.ts
Expand Up @@ -25,4 +25,33 @@ describe('createEventHook', () => {

expect(message).toBe('Hello World')
})

it('should add and remove event listener', () => {
const listener = vi.fn()
const { on, off, trigger } = createEventHook<string>()

on(listener)

trigger('xxx')

expect(listener).toHaveBeenCalledTimes(1)

off(listener)

trigger('xxx')

expect(listener).toHaveBeenCalledTimes(1)

const { off: remove } = on(listener)

trigger('xxx')

expect(listener).toHaveBeenCalledTimes(2)

remove()

trigger('xxx')

expect(listener).toHaveBeenCalledTimes(2)
})
})
46 changes: 46 additions & 0 deletions packages/shared/watchDebounced/index.test.ts
@@ -0,0 +1,46 @@
import { nextTick, ref } from 'vue-demi'
import { promiseTimeout } from '../utils'
import { debouncedWatch, watchDebounced } from '.'

describe('watchDebounced', () => {
it('should export module', () => {
expect(watchDebounced).toBeDefined()
expect(debouncedWatch).toBeDefined()
})

it('should work by default', async () => {
const num = ref(0)
const cb = vi.fn()
watchDebounced(num, cb)

num.value = 1
await nextTick()
expect(cb).toHaveBeenCalledWith(1, 0, expect.anything())
})

it('should work when set debounce and maxWait', async () => {
const num = ref(0)
const cb = vi.fn()
watchDebounced(num, cb, { debounce: 100, maxWait: 150 })

num.value = 1
await nextTick()
expect(cb).toHaveBeenCalledTimes(0)

num.value = 2
await promiseTimeout(50)
expect(cb).toHaveBeenCalledTimes(0)

await promiseTimeout(50)
expect(cb).toHaveBeenCalledWith(2, 1, expect.anything())

num.value = 4
await promiseTimeout(80)
expect(cb).toHaveBeenCalledTimes(1)

num.value = 5
await promiseTimeout(70)
expect(cb).toHaveBeenCalledTimes(2)
expect(cb).toHaveBeenCalledWith(4, 2, expect.anything())
})
})
34 changes: 34 additions & 0 deletions packages/shared/watchThrottled/index.test.ts
@@ -0,0 +1,34 @@
import { nextTick, ref } from 'vue-demi'
import { promiseTimeout } from '../utils'
import { throttledWatch, watchThrottled } from '.'

describe('watchThrottled', () => {
it('should export module', () => {
expect(watchThrottled).toBeDefined()
expect(throttledWatch).toBeDefined()
})

it('should work', async () => {
const num = ref(0)
const cb = vi.fn()
watchThrottled(num, cb, { throttle: 100 })

num.value = 1
await nextTick()
expect(cb).toHaveBeenCalledWith(1, 0, expect.anything())

num.value = 2
await promiseTimeout(50)
expect(cb).toHaveBeenCalledTimes(1)

num.value = 3
await promiseTimeout(50)
expect(cb).toHaveBeenCalledTimes(1)
expect(cb).toHaveBeenCalledWith(1, 0, expect.anything())

num.value = 4
await promiseTimeout(100)
expect(cb).toHaveBeenCalledTimes(2)
expect(cb).toHaveBeenCalledWith(4, 3, expect.anything())
})
})