From db1bcdd3d2a0dbf77e66bbf6a17e531bcce3b3b9 Mon Sep 17 00:00:00 2001 From: roschaefer Date: Tue, 1 Oct 2019 17:25:28 +0200 Subject: [PATCH] refactor: register vue-scrollto in nuxt.config.js This will allow us to use this.$scrollTo in components. I'm now also using this in the mixin. With so many `this`s it gets horribly difficult to properly test the mixin in isolation. So I decided to test the mixin on the component directly. --- webapp/components/Comment/Comment.spec.js | 33 ++++++++++++- .../CommentList/CommentList.spec.js | 37 ++++++++++++++- webapp/mixins/scrollToAnchor.js | 21 +++++---- webapp/mixins/scrollToAnchor.spec.js | 47 ------------------- webapp/nuxt.config.js | 1 + 5 files changed, 81 insertions(+), 58 deletions(-) delete mode 100644 webapp/mixins/scrollToAnchor.spec.js diff --git a/webapp/components/Comment/Comment.spec.js b/webapp/components/Comment/Comment.spec.js index 381d49bc2..9dc16777e 100644 --- a/webapp/components/Comment/Comment.spec.js +++ b/webapp/components/Comment/Comment.spec.js @@ -32,6 +32,7 @@ describe('Comment.vue', () => { truncate: a => a, removeHtml: a => a, }, + $scrollTo: jest.fn(), $apollo: { mutate: jest.fn().mockResolvedValue({ data: { @@ -51,6 +52,8 @@ describe('Comment.vue', () => { }) describe('shallowMount', () => { + beforeEach(jest.useFakeTimers) + Wrapper = () => { const store = new Vuex.Store({ getters, @@ -117,7 +120,35 @@ describe('Comment.vue', () => { }) }) - beforeEach(jest.useFakeTimers) + describe('scrollToAnchor mixin', () => { + describe('$route.hash !== comment.id', () => { + beforeEach(() => { + mocks.$route = { + hash: '', + } + }) + + it('skips $scrollTo', () => { + wrapper = Wrapper() + jest.runAllTimers() + expect(mocks.$scrollTo).not.toHaveBeenCalled() + }) + }) + + describe('$route.hash === comment.id', () => { + beforeEach(() => { + mocks.$route = { + hash: '#commentId-2', + } + }) + + it('calls $scrollTo', () => { + wrapper = Wrapper() + jest.runAllTimers() + expect(mocks.$scrollTo).toHaveBeenCalledWith('#commentId-2', 1000) + }) + }) + }) describe('test callbacks', () => { beforeEach(() => { diff --git a/webapp/components/CommentList/CommentList.spec.js b/webapp/components/CommentList/CommentList.spec.js index 4d382b36d..0eacf8628 100644 --- a/webapp/components/CommentList/CommentList.spec.js +++ b/webapp/components/CommentList/CommentList.spec.js @@ -42,6 +42,7 @@ describe('CommentList.vue', () => { truncate: a => a, removeHtml: a => a, }, + $scrollTo: jest.fn(), $apollo: { queries: { Post: { @@ -65,12 +66,46 @@ describe('CommentList.vue', () => { }) } - beforeEach(() => { + it('displays a comments counter', () => { wrapper = Wrapper() + expect(wrapper.find('span.ds-tag').text()).toEqual('1') }) it('displays a comments counter', () => { + wrapper = Wrapper() expect(wrapper.find('span.ds-tag').text()).toEqual('1') }) + + describe('scrollToAnchor mixin', () => { + beforeEach(jest.useFakeTimers) + + describe('$route.hash !== `#comments`', () => { + beforeEach(() => { + mocks.$route = { + hash: '', + } + }) + + it('skips $scrollTo', () => { + wrapper = Wrapper() + jest.runAllTimers() + expect(mocks.$scrollTo).not.toHaveBeenCalled() + }) + }) + + describe('$route.hash === `#comments`', () => { + beforeEach(() => { + mocks.$route = { + hash: '#comments', + } + }) + + it('calls $scrollTo', () => { + wrapper = Wrapper() + jest.runAllTimers() + expect(mocks.$scrollTo).toHaveBeenCalledWith('#comments', 1000) + }) + }) + }) }) }) diff --git a/webapp/mixins/scrollToAnchor.js b/webapp/mixins/scrollToAnchor.js index 3ce4eb5a9..70a1bf695 100644 --- a/webapp/mixins/scrollToAnchor.js +++ b/webapp/mixins/scrollToAnchor.js @@ -1,20 +1,23 @@ -import { scrollTo } from 'vue-scrollto' +function scrollToAnchor(anchor, { checkAnchor, $scrollTo }) { + if (typeof checkAnchor !== 'function') + throw new Error( + 'You must define `checkAnchor` on the component if you use scrollToAnchor mixin!', + ) + if (!checkAnchor(anchor)) return + setTimeout(() => { + $scrollTo(anchor, 1000) + }, 250) +} export default { watch: { $route(to, from) { const anchor = to && to.hash - if (!this.checkAnchor(anchor)) return - setTimeout(() => { - scrollTo(anchor, 1000) - }, 250) + scrollToAnchor(anchor, this) }, }, mounted() { const anchor = this.$route && this.$route.hash - if (!this.checkAnchor(anchor)) return - setTimeout(() => { - scrollTo(anchor, 1000) - }, 250) + scrollToAnchor(anchor, this) }, } diff --git a/webapp/mixins/scrollToAnchor.spec.js b/webapp/mixins/scrollToAnchor.spec.js deleted file mode 100644 index a9447e458..000000000 --- a/webapp/mixins/scrollToAnchor.spec.js +++ /dev/null @@ -1,47 +0,0 @@ -import { scrollTo } from 'vue-scrollto' -import scrollToAnchor from './scrollToAnchor' -jest.mock('vue-scrollto') - -let component - -describe('scrollToAnchor', () => { - beforeEach(() => { - jest.useFakeTimers() - scrollTo.mockClear() - }) - - describe('scrollToAnchor', () => { - const action = hash => { - let { - watch: { $route }, - } = scrollToAnchor - $route.bind(component)({ hash }) - jest.runAllTimers() - } - - describe('given anchor `commentId-4711`', () => { - beforeEach(() => { - component = { - anchor: 'commentId-4711', - checkAnchor(anchor) { - return this.anchor === anchor - }, - } - }) - - describe('$route.hash === anchor', () => { - it('calls window.scroll', () => { - action('commentId-4711') - expect(scrollTo).toHaveBeenCalled() - }) - }) - - describe('$route.hash !== anchor', () => { - it('skips window.scroll', () => { - action('commentId-4712') - expect(scrollTo).not.toHaveBeenCalled() - }) - }) - }) - }) -}) diff --git a/webapp/nuxt.config.js b/webapp/nuxt.config.js index f1747b479..4867ad5d6 100644 --- a/webapp/nuxt.config.js +++ b/webapp/nuxt.config.js @@ -142,6 +142,7 @@ export default { keys: envWhitelist, }, ], + 'vue-scrollto/nuxt', 'cookie-universal-nuxt', '@nuxtjs/apollo', '@nuxtjs/axios',