From dd62ff8e1d0b1216c1508e2267f6968bd9904600 Mon Sep 17 00:00:00 2001 From: Salvatore Tedde Date: Mon, 17 Feb 2020 22:30:41 +0000 Subject: [PATCH 1/2] feat(useIdle): Adding useIdle and improving handling of clearMock for all function tests --- README.md | 2 + package-lock.json | 55 +++++++++++++-- package.json | 5 +- .../useClickAway/useClickAway.spec.ts | 13 +++- .../useFullscreen/useFullscreen.spec.ts | 4 ++ src/components/useHover/useHover.spec.ts | 12 ++++ src/components/useIdle/index.ts | 1 + .../useIdle/stories/UseIdleDemo.vue | 67 +++++++++++++++++++ src/components/useIdle/stories/useIdle.md | 65 ++++++++++++++++++ .../useIdle/stories/useIdle.story.ts | 28 ++++++++ src/components/useIdle/useIdle.spec.ts | 26 +++++++ src/components/useIdle/useIdle.ts | 62 +++++++++++++++++ .../useIntersection/useIntersection.spec.ts | 4 ++ .../useInterval/useInterval.spec.ts | 1 + .../useIntervalFn/useIntervalFn.spec.ts | 1 + src/components/useMedia/useMedia.spec.ts | 6 +- src/components/useMouse/useMouse.spec.ts | 13 +++- .../useMouseElement/useMouseElement.spec.ts | 13 +++- src/components/useRaf/useRaf.spec.ts | 2 +- src/components/useRafFn/useRafFn.spec.ts | 2 +- .../useSampleComponent.spec.ts | 4 ++ src/components/useTimeout/useTimeout.spec.ts | 1 + .../useTimeoutFn/useTimeoutFn.spec.ts | 1 + src/vue-use-kit.ts | 1 + 24 files changed, 376 insertions(+), 13 deletions(-) create mode 100755 src/components/useIdle/index.ts create mode 100755 src/components/useIdle/stories/UseIdleDemo.vue create mode 100755 src/components/useIdle/stories/useIdle.md create mode 100755 src/components/useIdle/stories/useIdle.story.ts create mode 100755 src/components/useIdle/useIdle.spec.ts create mode 100755 src/components/useIdle/useIdle.ts diff --git a/README.md b/README.md index 5242b6b..d1d915d 100755 --- a/README.md +++ b/README.md @@ -63,6 +63,8 @@ Vue.use(VueCompositionAPI); [![Demo](https://img.shields.io/badge/demo-🚀-yellow.svg)](https://microcipcip.github.io/vue-use-kit/?path=/story/sensors-usegeolocation--demo) - [`useHover`](./src/components/useHover/stories/useHover.md) — tracks mouse hover state of a given element. [![Demo](https://img.shields.io/badge/demo-🚀-yellow.svg)](https://microcipcip.github.io/vue-use-kit/?path=/story/sensors-usehover--demo) + - [`useIdle`](./src/components/useIdle/stories/useIdle.md) — tracks whether user is being inactive. + [![Demo](https://img.shields.io/badge/demo-🚀-yellow.svg)](https://microcipcip.github.io/vue-use-kit/?path=/story/sensors-useidle--demo) - [`useIntersection`](./src/components/useIntersection/stories/useIntersection.md) — tracks intersection of target element with an ancestor element. [![Demo](https://img.shields.io/badge/demo-🚀-yellow.svg)](https://microcipcip.github.io/vue-use-kit/?path=/story/sensors-useintersection--demo) [![Demo](https://img.shields.io/badge/advanced_demo-🚀-yellow.svg)](https://microcipcip.github.io/vue-use-kit/?path=/story/sensors-useintersection--advanced-demo) diff --git a/package-lock.json b/package-lock.json index 431f63e..6735421 100755 --- a/package-lock.json +++ b/package-lock.json @@ -1192,6 +1192,14 @@ "meow": "5.0.0", "resolve-from": "5.0.0", "resolve-global": "1.0.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + } } }, "@commitlint/config-conventional": { @@ -1207,6 +1215,14 @@ "dev": true, "requires": { "lodash": "4.17.11" + }, + "dependencies": { + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + } } }, "@commitlint/execute-rule": { @@ -1248,6 +1264,14 @@ "@commitlint/rules": "^7.6.0", "babel-runtime": "^6.23.0", "lodash": "4.17.11" + }, + "dependencies": { + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + } } }, "@commitlint/load": { @@ -1262,6 +1286,14 @@ "cosmiconfig": "^5.2.0", "lodash": "4.17.11", "resolve-from": "^5.0.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + } } }, "@commitlint/message": { @@ -1304,6 +1336,14 @@ "lodash": "4.17.11", "resolve-from": "^5.0.0", "resolve-global": "^1.0.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + } } }, "@commitlint/rules": { @@ -3760,6 +3800,12 @@ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, + "@types/throttle-debounce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/throttle-debounce/-/throttle-debounce-2.1.0.tgz", + "integrity": "sha512-5eQEtSCoESnh2FsiLTxE121IiE60hnMqcb435fShf4bpLRjEu1Eoekht23y6zXS9Ts3l+Szu3TARnTsA0GkOkQ==", + "dev": true + }, "@types/webpack-env": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.15.1.tgz", @@ -13015,9 +13061,9 @@ } }, "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, "lodash._reinterpolate": { @@ -22652,8 +22698,7 @@ "throttle-debounce": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-2.1.0.tgz", - "integrity": "sha512-AOvyNahXQuU7NN+VVvOOX+uW6FPaWdAOdRP5HfwYxAfCzXTFKRMoIMk+n+po318+ktcChx+F1Dd91G3YHeMKyg==", - "dev": true + "integrity": "sha512-AOvyNahXQuU7NN+VVvOOX+uW6FPaWdAOdRP5HfwYxAfCzXTFKRMoIMk+n+po318+ktcChx+F1Dd91G3YHeMKyg==" }, "through": { "version": "2.3.8", diff --git a/package.json b/package.json index ac62a02..3d69244 100755 --- a/package.json +++ b/package.json @@ -94,6 +94,7 @@ "@storybook/vue": "^5.3.13", "@types/jest": "^23.3.2", "@types/node": "^10.11.0", + "@types/throttle-debounce": "^2.1.0", "@typescript-eslint/eslint-plugin": "^2.18.0", "@typescript-eslint/parser": "^2.18.0", "@vue/composition-api": "^0.3.4", @@ -136,5 +137,7 @@ "vue-loader": "^15.8.3", "vue-template-compiler": "^2.6.11" }, - "dependencies": {} + "dependencies": { + "throttle-debounce": "^2.1.0" + } } diff --git a/src/components/useClickAway/useClickAway.spec.ts b/src/components/useClickAway/useClickAway.spec.ts index d4345d8..3abe883 100755 --- a/src/components/useClickAway/useClickAway.spec.ts +++ b/src/components/useClickAway/useClickAway.spec.ts @@ -2,6 +2,10 @@ import { mount } from '@src/helpers/test' import { ref } from '@src/api' import { useClickAway } from '@src/vue-use-kit' +afterEach(() => { + jest.clearAllMocks() +}) + const testComponent = () => ({ template: `
@@ -29,10 +33,17 @@ describe('useClickAway', () => { const wrapper = mount(testComponent()) await wrapper.vm.$nextTick() expect(addEventListenerSpy).toHaveBeenCalled() + expect(addEventListenerSpy).toBeCalledWith( + 'mousedown', + expect.any(Function) + ) // Destroy instance to check if the remove event listener is being called wrapper.destroy() expect(removeEventListenerSpy).toHaveBeenCalled() - addEventListenerSpy.mockClear() + expect(removeEventListenerSpy).toBeCalledWith( + 'mousedown', + expect.any(Function) + ) }) }) diff --git a/src/components/useFullscreen/useFullscreen.spec.ts b/src/components/useFullscreen/useFullscreen.spec.ts index 52850ec..b9017f1 100755 --- a/src/components/useFullscreen/useFullscreen.spec.ts +++ b/src/components/useFullscreen/useFullscreen.spec.ts @@ -5,6 +5,10 @@ import { useFullscreen } from '@src/vue-use-kit' // This feature is difficult to test therefore // I've only written a simple test +afterEach(() => { + jest.clearAllMocks() +}) + const testComponent = () => ({ template: `
diff --git a/src/components/useHover/useHover.spec.ts b/src/components/useHover/useHover.spec.ts index 0ef5738..9b085c4 100755 --- a/src/components/useHover/useHover.spec.ts +++ b/src/components/useHover/useHover.spec.ts @@ -2,6 +2,10 @@ import { mount } from '@src/helpers/test' import { ref } from '@src/api' import { useHover } from '@src/vue-use-kit' +afterEach(() => { + jest.clearAllMocks() +}) + const testComponent = () => ({ template: `
@@ -22,9 +26,17 @@ describe('useHover', () => { ) const wrapper = mount(testComponent()) expect(addEventListenerSpy).toHaveBeenCalled() + expect(addEventListenerSpy).toBeCalledWith( + 'mouseenter', + expect.any(Function) + ) expect(removeEventListenerSpy).not.toHaveBeenCalled() wrapper.destroy() expect(removeEventListenerSpy).toHaveBeenCalled() + expect(removeEventListenerSpy).toBeCalledWith( + 'mouseenter', + expect.any(Function) + ) }) it('should return isHovered false by default', () => { diff --git a/src/components/useIdle/index.ts b/src/components/useIdle/index.ts new file mode 100755 index 0000000..f09837c --- /dev/null +++ b/src/components/useIdle/index.ts @@ -0,0 +1 @@ +export * from './useIdle' diff --git a/src/components/useIdle/stories/UseIdleDemo.vue b/src/components/useIdle/stories/UseIdleDemo.vue new file mode 100755 index 0000000..29e4f3e --- /dev/null +++ b/src/components/useIdle/stories/UseIdleDemo.vue @@ -0,0 +1,67 @@ + + + + + diff --git a/src/components/useIdle/stories/useIdle.md b/src/components/useIdle/stories/useIdle.md new file mode 100755 index 0000000..a03d8bc --- /dev/null +++ b/src/components/useIdle/stories/useIdle.md @@ -0,0 +1,65 @@ +# useIdle + +Vue function that tracks whether user is being inactive. + +## Reference + +```typescript +useIdle( + ms?: number, + events?: string[], + runOnMount?: boolean +): { + isIdle: Ref; + start: () => void; + stop: () => void; +} +``` + +### Parameters + +- `ms: number` milliseconds to wait before deciding whether the user is being idle +- `events: string[]` list of events to track the user for +- `runOnMount: boolean` whether to start tracking idle state on mount, `true` by default + +### Returns + +- `isIdle: Ref` it is `true` when the user is idle, `false` otherwise +- `start: Function` the function used for start tracking the user's idle state +- `stop: Function` the function used for stop tracking the user's idle state + +## Usage + +```html + + + +``` diff --git a/src/components/useIdle/stories/useIdle.story.ts b/src/components/useIdle/stories/useIdle.story.ts new file mode 100755 index 0000000..6e63974 --- /dev/null +++ b/src/components/useIdle/stories/useIdle.story.ts @@ -0,0 +1,28 @@ +import { storiesOf } from '@storybook/vue' +import path from 'path' +import StoryTitle from '@src/helpers/StoryTitle.vue' +import UseIdleDemo from './UseIdleDemo.vue' + +const functionName = 'useIdle' +const functionPath = path.resolve(__dirname, '..') +const notes = require(`./${functionName}.md`).default + +const basicDemo = () => ({ + components: { StoryTitle, demo: UseIdleDemo }, + template: ` +
+ + + + + +
` +}) + +storiesOf('sensors|useIdle', module) + .addParameters({ notes }) + .add('Demo', basicDemo) diff --git a/src/components/useIdle/useIdle.spec.ts b/src/components/useIdle/useIdle.spec.ts new file mode 100755 index 0000000..afe6646 --- /dev/null +++ b/src/components/useIdle/useIdle.spec.ts @@ -0,0 +1,26 @@ +import { mount } from '@src/helpers/test' +import { useIdle } from '@src/vue-use-kit' + +afterEach(() => { + jest.clearAllMocks() +}) + +const testComponent = () => ({ + template: ` +
+
+ + +
+ `, + setup() { + const { isIdle, stop, start } = useIdle(3000) + return { isIdle, stop, start } + } +}) + +describe('useIdle', () => { + it('should do something', () => { + // Add test here + }) +}) diff --git a/src/components/useIdle/useIdle.ts b/src/components/useIdle/useIdle.ts new file mode 100755 index 0000000..f78e904 --- /dev/null +++ b/src/components/useIdle/useIdle.ts @@ -0,0 +1,62 @@ +import { throttle } from 'throttle-debounce' +import { ref, onMounted, onUnmounted } from '@src/api' + +export const idleEventsList = [ + 'mousemove', + 'mousedown', + 'resize', + 'keydown', + 'touchstart', + 'wheel' +] +const oneMinute = 60e3 + +export function useIdle( + ms = oneMinute, + events = idleEventsList, + runOnMount = true +) { + let timeout: any = null + const isIdle = ref(false) + + const handleChange = throttle(50, () => { + isIdle.value = false + + if (timeout) clearTimeout(timeout) + timeout = setTimeout(() => { + isIdle.value = true + }, ms) + }) + + const handleVisibility = () => { + if (!document.hidden) return + handleChange() + } + + const start = () => { + events.forEach(evtName => document.addEventListener(evtName, handleChange)) + document.addEventListener('visibilitychange', handleVisibility) + + // Initialize it since the events above may not run immediately + handleChange() + } + + const stop = () => { + events.forEach(evtName => + document.removeEventListener(evtName, handleChange) + ) + document.removeEventListener('visibilitychange', handleVisibility) + + // Stop timer if it is still running + if (timeout) clearTimeout(timeout) + + // Restore initial status + timeout = null + isIdle.value = false + } + + onMounted(() => runOnMount && start()) + onUnmounted(stop) + + return { isIdle, start, stop } +} diff --git a/src/components/useIntersection/useIntersection.spec.ts b/src/components/useIntersection/useIntersection.spec.ts index 2d1ea33..bc7bd4e 100755 --- a/src/components/useIntersection/useIntersection.spec.ts +++ b/src/components/useIntersection/useIntersection.spec.ts @@ -16,6 +16,10 @@ beforeEach(() => { })) }) +afterEach(() => { + jest.clearAllMocks() +}) + const testComponent = (onMount = true) => ({ template: `
diff --git a/src/components/useInterval/useInterval.spec.ts b/src/components/useInterval/useInterval.spec.ts index b4b1cab..2ff73de 100755 --- a/src/components/useInterval/useInterval.spec.ts +++ b/src/components/useInterval/useInterval.spec.ts @@ -7,6 +7,7 @@ beforeEach(() => { afterEach(() => { jest.clearAllTimers() + jest.clearAllMocks() }) const testComponent = () => ({ diff --git a/src/components/useIntervalFn/useIntervalFn.spec.ts b/src/components/useIntervalFn/useIntervalFn.spec.ts index 9fc4b1a..7e0c783 100755 --- a/src/components/useIntervalFn/useIntervalFn.spec.ts +++ b/src/components/useIntervalFn/useIntervalFn.spec.ts @@ -8,6 +8,7 @@ beforeEach(() => { afterEach(() => { jest.clearAllTimers() + jest.clearAllMocks() }) const testComponent = (onMount = true) => ({ diff --git a/src/components/useMedia/useMedia.spec.ts b/src/components/useMedia/useMedia.spec.ts index 7fea1b8..6865a04 100755 --- a/src/components/useMedia/useMedia.spec.ts +++ b/src/components/useMedia/useMedia.spec.ts @@ -14,6 +14,10 @@ const createMediaQueryListMock = (matchingQuery: string) => ( } }) +afterEach(() => { + jest.clearAllMocks() +}) + const testComponent = ( mobileQuery: string, desktopQuery: string, @@ -43,8 +47,6 @@ describe('useMedia', () => { expect(matchMediaSpy).not.toHaveBeenCalled() mount(testComponent(mobileQuery, desktopQuery)) expect(matchMediaSpy).toHaveBeenCalled() - - matchMediaSpy.mockClear() }) it('display the #desktop element when it matches', async () => { diff --git a/src/components/useMouse/useMouse.spec.ts b/src/components/useMouse/useMouse.spec.ts index d86a2b7..91c220b 100755 --- a/src/components/useMouse/useMouse.spec.ts +++ b/src/components/useMouse/useMouse.spec.ts @@ -1,6 +1,10 @@ import { mount } from '@src/helpers/test' import { useMouse } from '@src/vue-use-kit' +afterEach(() => { + jest.clearAllMocks() +}) + const testComponent = () => ({ template: `
@@ -22,12 +26,19 @@ describe('useMouse', () => { const wrapper = mount(testComponent()) await wrapper.vm.$nextTick() expect(addEventListenerSpy).toHaveBeenCalledTimes(1) + expect(addEventListenerSpy).toBeCalledWith( + 'mousemove', + expect.any(Function) + ) expect(removeEventListenerSpy).not.toHaveBeenCalled() // Destroy instance to check if the remove event listener is being called wrapper.destroy() expect(removeEventListenerSpy).toHaveBeenCalledTimes(1) - addEventListenerSpy.mockClear() + expect(removeEventListenerSpy).toBeCalledWith( + 'mousemove', + expect.any(Function) + ) }) it('should not render any document before onMount since all values are 0 by default', () => { diff --git a/src/components/useMouseElement/useMouseElement.spec.ts b/src/components/useMouseElement/useMouseElement.spec.ts index 41ab622..3d13f97 100755 --- a/src/components/useMouseElement/useMouseElement.spec.ts +++ b/src/components/useMouseElement/useMouseElement.spec.ts @@ -2,6 +2,10 @@ import { mount } from '@src/helpers/test' import { ref } from '@src/api' import { useMouseElement } from '@src/vue-use-kit' +afterEach(() => { + jest.clearAllMocks() +}) + const testComponent = () => ({ template: `
@@ -39,12 +43,19 @@ describe('useMouseElement', () => { const wrapper = mount(testComponent()) await wrapper.vm.$nextTick() expect(addEventListenerSpy).toHaveBeenCalledTimes(1) + expect(addEventListenerSpy).toBeCalledWith( + 'mousemove', + expect.any(Function) + ) expect(removeEventListenerSpy).not.toHaveBeenCalled() // Destroy instance to check if the remove event listener is being called wrapper.destroy() expect(removeEventListenerSpy).toHaveBeenCalledTimes(1) - addEventListenerSpy.mockClear() + expect(removeEventListenerSpy).toBeCalledWith( + 'mousemove', + expect.any(Function) + ) }) it('should not render any document before onMount since all values are 0 by default', () => { diff --git a/src/components/useRaf/useRaf.spec.ts b/src/components/useRaf/useRaf.spec.ts index 2311a24..cd57f88 100755 --- a/src/components/useRaf/useRaf.spec.ts +++ b/src/components/useRaf/useRaf.spec.ts @@ -16,7 +16,7 @@ beforeEach(() => { afterEach(() => { count = 0 - rafSpy.mockClear() + jest.clearAllMocks() }) const testComponent = (onMount = false) => ({ diff --git a/src/components/useRafFn/useRafFn.spec.ts b/src/components/useRafFn/useRafFn.spec.ts index 2ffde0a..eca0fd2 100755 --- a/src/components/useRafFn/useRafFn.spec.ts +++ b/src/components/useRafFn/useRafFn.spec.ts @@ -17,7 +17,7 @@ beforeEach(() => { afterEach(() => { count = 0 - rafSpy.mockClear() + jest.clearAllMocks() }) const testComponent = (onMount = false) => ({ diff --git a/src/components/useSampleComponent/useSampleComponent.spec.ts b/src/components/useSampleComponent/useSampleComponent.spec.ts index 349144b..a849de5 100755 --- a/src/components/useSampleComponent/useSampleComponent.spec.ts +++ b/src/components/useSampleComponent/useSampleComponent.spec.ts @@ -1,6 +1,10 @@ // import { mount } from '@src/helpers/test' // import { useSampleComponent } from '@src/vue-use-kit' +afterEach(() => { + jest.clearAllMocks() +}) + describe('useSampleComponent', () => { it('should do something', () => { // Add test here diff --git a/src/components/useTimeout/useTimeout.spec.ts b/src/components/useTimeout/useTimeout.spec.ts index 3a38bad..14331e3 100755 --- a/src/components/useTimeout/useTimeout.spec.ts +++ b/src/components/useTimeout/useTimeout.spec.ts @@ -8,6 +8,7 @@ beforeEach(() => { afterEach(() => { jest.clearAllTimers() + jest.clearAllMocks() }) const testComponent = () => ({ diff --git a/src/components/useTimeoutFn/useTimeoutFn.spec.ts b/src/components/useTimeoutFn/useTimeoutFn.spec.ts index 0b28ed8..7be3ff1 100755 --- a/src/components/useTimeoutFn/useTimeoutFn.spec.ts +++ b/src/components/useTimeoutFn/useTimeoutFn.spec.ts @@ -8,6 +8,7 @@ beforeEach(() => { afterEach(() => { jest.clearAllTimers() + jest.clearAllMocks() }) const testComponent = (onMount = true) => ({ diff --git a/src/vue-use-kit.ts b/src/vue-use-kit.ts index 89b4bbd..d227110 100755 --- a/src/vue-use-kit.ts +++ b/src/vue-use-kit.ts @@ -5,6 +5,7 @@ export * from './components/useFullscreen' export * from './components/useGeolocation' export * from './components/useHover' +export * from './components/useIdle' export * from './components/useIntersection' export * from './components/useMedia' export * from './components/useMouse' From 59235298c416c142ecee46ea5e72fbe84a08ac56 Mon Sep 17 00:00:00 2001 From: Salvatore Tedde Date: Mon, 17 Feb 2020 22:53:43 +0000 Subject: [PATCH 2/2] improvement(useIdle): Adding useIdle tests --- src/components/useIdle/useIdle.spec.ts | 48 ++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/src/components/useIdle/useIdle.spec.ts b/src/components/useIdle/useIdle.spec.ts index afe6646..883c62d 100755 --- a/src/components/useIdle/useIdle.spec.ts +++ b/src/components/useIdle/useIdle.spec.ts @@ -1,5 +1,5 @@ import { mount } from '@src/helpers/test' -import { useIdle } from '@src/vue-use-kit' +import { useIdle, idleEventsList } from '@src/vue-use-kit' afterEach(() => { jest.clearAllMocks() @@ -20,7 +20,49 @@ const testComponent = () => ({ }) describe('useIdle', () => { - it('should do something', () => { - // Add test here + // the total of the events is idleEventsList + visibilitychange + const totEvents = idleEventsList.length + 1 + + it('should call document.addEventListener', async () => { + const addEventListenerSpy = jest.spyOn(document, 'addEventListener') + const removeEventListenerSpy = jest.spyOn(document, 'removeEventListener') + expect(addEventListenerSpy).not.toHaveBeenCalled() + const wrapper = mount(testComponent()) + await wrapper.vm.$nextTick() + expect(addEventListenerSpy).toHaveBeenCalledTimes(totEvents) + expect(addEventListenerSpy).toBeCalledWith( + 'mousemove', + expect.any(Function) + ) + + // Destroy instance to check if the remove event listener is being called + wrapper.destroy() + expect(removeEventListenerSpy).toHaveBeenCalledTimes(totEvents) + expect(removeEventListenerSpy).toBeCalledWith( + 'mousemove', + expect.any(Function) + ) + }) + + it('should call document.addEventListener again when start is called', async () => { + const addEventListenerSpy = jest.spyOn(document, 'addEventListener') + const wrapper = mount(testComponent()) + expect(addEventListenerSpy).toHaveBeenCalledTimes(totEvents) + wrapper.find('#stop').trigger('click') + + // Wait for Vue to append #start in the DOM + await wrapper.vm.$nextTick() + wrapper.find('#start').trigger('click') + expect(addEventListenerSpy).toHaveBeenCalledTimes(totEvents * 2) + }) + + it('should call document.removeEventListener when stop is called', async () => { + const removeEventListenerSpy = jest.spyOn(document, 'removeEventListener') + const wrapper = mount(testComponent()) + wrapper.find('#stop').trigger('click') + + // Wait for Vue to append #start in the DOM + await wrapper.vm.$nextTick() + expect(removeEventListenerSpy).toHaveBeenCalledTimes(totEvents) }) })