├── .babelrc ├── .eslintrc.js ├── .github └── FUNDING.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── commitlint.config.js ├── package.json ├── renovate.json ├── src └── index.js └── test ├── ScrollNextLevel.spec.js └── fixtures └── Target.vue /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "vue-app", 5 | { 6 | "modules": false 7 | } 8 | ] 9 | ], 10 | "env": { 11 | "test": { 12 | "presets": [ 13 | [ 14 | "vue-app", 15 | { 16 | "targets": { 17 | "node": 8 18 | } 19 | } 20 | ] 21 | ] 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parserOptions: { 4 | parser: 'babel-eslint', 5 | sourceType: 'module' 6 | }, 7 | extends: [ 8 | '@nuxtjs' 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [manniL] 2 | custom: ['https://www.lichter.io/support-me/'] 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/** 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pids 8 | *.pid 9 | *.seed 10 | *.pid.lock 11 | lib-cov 12 | coverage 13 | .nyc_output 14 | .grunt 15 | bower_components 16 | .lock-wscript 17 | build/Release 18 | node_modules/ 19 | package-lock.json 20 | jspm_packages/ 21 | typings/ 22 | .npm 23 | .eslintcache 24 | .node_repl_history 25 | *.tgz 26 | .yarn-integrity 27 | .env 28 | .next 29 | dist 30 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "8" 4 | - "9" 5 | - "10" 6 | cache: 7 | npm: true 8 | directories: 9 | - node_modules 10 | install: 11 | - npm install 12 | script: 13 | - npm t 14 | after_success: 15 | - npm run coverage 16 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | 6 | # [1.2.0](https://github.com/Developmint/vue-next-level-scroll/compare/v1.1.2...v1.2.0) (2018-10-14) 7 | 8 | 9 | ### Features 10 | 11 | * add custom tag option ([4f99727](https://github.com/Developmint/vue-next-level-scroll/commit/4f99727)) 12 | * add navigation support ([d1d1aa8](https://github.com/Developmint/vue-next-level-scroll/commit/d1d1aa8)) 13 | 14 | 15 | 16 | 17 | ## [1.1.2](https://github.com/Developmint/vue-next-level-scroll/compare/v1.1.1...v1.1.2) (2018-06-03) 18 | 19 | 20 | ### Bug Fixes 21 | 22 | * set entry points correctly ([fdcd432](https://github.com/Developmint/vue-next-level-scroll/commit/fdcd432)) 23 | 24 | 25 | 26 | 27 | ## [1.1.1](https://github.com/Developmint/vue-next-level-scroll/compare/v1.1.0...v1.1.1) (2018-06-03) 28 | 29 | 30 | 31 | 32 | # [1.1.0](https://github.com/Developmint/vue-next-level-scroll/compare/v1.0.1...v1.1.0) (2018-05-11) 33 | 34 | 35 | ### Features 36 | 37 | * convert SFC to normal js file ([274d39d](https://github.com/Developmint/vue-next-level-scroll/commit/274d39d)) 38 | 39 | 40 | 41 | 42 | ## [1.0.1](https://github.com/Developmint/vue-next-level-scroll/compare/v1.0.0...v1.0.1) (2018-05-07) 43 | 44 | 45 | 46 | 47 | # 1.0.0 (2018-05-07) 48 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to VueNextLevelScroll 2 | 3 | 1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device. 4 | 2. Install the dependencies: `npm install`. 5 | 3. Develop your feature/bugfix. 6 | 4. Add tests into `test` directory and try them with `npm test`. 7 | 5. Send the PR! 8 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Alexander Lichter ([@manniL](https://github.com/manniL)) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VueNextLevelScroll - Bring your scroll game to the next level! 2 | 3 |

4 | Build Status 5 | Code coverage 6 | Downloads 7 | Version 8 | License 9 | We use Conventional Commits 10 | Thanks badge 11 |

12 | 13 | > "Click to scroll" **component** using the modern Browser API. 14 | 15 | ## :fire: Features 16 | 17 | - Just **one tiny file** 18 | - Component based (great for **async loading** and code splitting) 19 | - Supports navigation through *VueRouter* 20 | - Universal code/SSR-safe 21 | - Well tested and **documented** 22 | - Compatible with Node 8.0+ 23 | - Vue as the only dependency 24 | - Highly customizable 25 | 26 | ## :mag_right: Getting started 27 | 28 | ### :star: Demo 29 | 30 | A live demo is available at [https://oqxy5xr5ny.sse.codesandbox.io/](https://oqxy5xr5ny.sse.codesandbox.io/). 31 | 32 | ### :package: Through NPM 33 | 34 | ``` 35 | $ npm install vue-next-level-scroll 36 | ``` 37 | 38 | #### Synchronous import 39 | 40 | ```js 41 | import VueNextLevelScroll from 'vue-next-level-scroll' 42 | 43 | 44 | export default { 45 | components: { 46 | VueNextLevelScroll 47 | } 48 | } 49 | 50 | ``` 51 | 52 | #### Async import 53 | 54 | ```js 55 | export default { 56 | components: { 57 | VueNextLevelScroll: () => import('vue-next-level-scroll') 58 | } 59 | } 60 | 61 | ``` 62 | 63 | ### :link: Using a CDN 64 | 65 | [UNPKG](https://unpkg.com/vue-next-level-scroll/dist/) | [jsDelivr](https://cdn.jsdelivr.net/npm/vue-next-level-scroll/dist/) (available as window.nextLevelScroll) 66 | 67 | ```js 68 | Vue.component('scroll', window.nextLevelScroll) 69 | 70 | // Continue as you wish. If you want to load a scroll behavior polyfill, do it **before** adding the CDN link. 71 | 72 | ``` 73 | 74 | 75 | ## :hammer_and_wrench: Usage 76 | 77 | ### You might like to go for a Polyfill 78 | 79 | VueNextLevelScroll uses the new [`ScrollBehavior specification`](https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior) by default. 80 | Unfortunately, Firefox is the only browser that has it built-in (by now). 81 | For this reason, you might like to go for [this polyfill](https://github.com/iamdustan/smoothscroll) (don't worry, less than 2kB after GZIP). 82 | 83 | 84 | ### The component based approach 85 | 86 | As you likely have seen, there are various *Vue directives* out their that handle scrolling as well. 87 | You might have used one or two of them already or built one yourself. 88 | 89 | **But!** A component can sometimes be the better approach, as it can be tree shaken, is 90 | better suited for universal/SSR code and can be loaded asynchronously as well! 91 | 92 | ### Prop overview 93 | 94 | 95 | | Prop | Optional? | Comment | 96 | |---| --- | --- | 97 | | target | :white_check_mark: | Can be any query selector you want (or a function that returns such). Will be passed to the scroll function | 98 | | tag | :white_check_mark: | Defaults to `div`. The HTML tag used for the VueNextLevelScroll component | 99 | | scrollFunction | :white_check_mark: | You can define an own scroll function that will take the `target` prop as parameter and can do whatever you like. | 100 | | shouldNavigate | :white_check_mark: | If set, VueRouter will reflect navigation changes in the url(top: no hash, target: hash) | 101 | | navigationType | :white_check_mark: | Defaults to `push`. The navigation type of that VueRouter should use. Usually either `push` or `replace` | 102 | 103 | 104 | ### Default scroll function explained 105 | 106 | #### Scroll to top 107 | 108 | When no `target` prop is set, the default scroll function will trigger a scroll to top: 109 | 110 | ```html 111 | 112 | 113 | 114 | ``` 115 | 116 | #### Scroll to query selector 117 | 118 | When the `target` prop is provided, the default scroll function look the DOM node up and smooth scroll to it. 119 | If the `target` is a class query, the first found element will be chosen to scroll to. 120 | 121 | ```html 122 | 123 | 124 | 125 |
126 | ``` 127 | 128 | #### Scroll to non-existing query selector 129 | 130 | When the `target` prop is given but no node matches, a console error will appear. 131 | 132 | ```html 133 | 134 | 135 | 136 |
137 | ``` 138 | 139 | ```js 140 | Error: Could not scroll to #my-target 141 | ``` 142 | 143 | ### Custom scroll function 144 | 145 | Most users are satisfied with the default scroll function provided by *VueNextLevelScroll* 146 | However if you need other behavior you can simply write your own function: 147 | 148 | ```html 149 | 157 | 158 | 165 | ``` 166 | 167 | You might not need the polyfill then as well :wink: 168 | 169 | ## :gear: Contributing 170 | 171 | Please see our [CONTRIBUTING.md](./CONTRIBUTING.md) 172 | 173 | 174 | ## :bookmark_tabs: License 175 | 176 | [MIT License](./LICENSE.md) - Copyright (c) Developmint - Alexander Lichter 177 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { extends: ['@commitlint/config-conventional'] } 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-next-level-scroll", 3 | "version": "1.2.0", 4 | "description": "Bring your scroll game to the next level", 5 | "author": "Alexander Lichter ", 6 | "license": "MIT", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/Developmint/vue-next-level-scroll" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/Developmint/vue-next-level-scroll/issues" 13 | }, 14 | "main": "dist/vue-next-level-scroll.cjs.js", 15 | "module": "dist/vue-next-level-scroll.es.js", 16 | "cdn": "dist/vue-next-level-scroll.min.js", 17 | "unpkg": "dist/vue-next-level-scroll.min.js", 18 | "jsdelivr": "dist/vue-next-level-scroll.min.js", 19 | "scripts": { 20 | "dev": "nuxt test/fixture", 21 | "lint": "eslint src test", 22 | "test": "npm run lint && jest", 23 | "build": "bili --format cjs,es,umd,umd-min --moduleName nextLevelScroll --no-babel.babelrc", 24 | "release": "npm run build && standard-version && git push --follow-tags && npm publish", 25 | "commitlint": "commitlint -e $GIT_PARAMS", 26 | "coverage": "codecov" 27 | }, 28 | "sideEffects": false, 29 | "files": [ 30 | "src", 31 | "dist" 32 | ], 33 | "keywords": [ 34 | "vue", 35 | "vuejs", 36 | "scroll", 37 | "component", 38 | "plugin" 39 | ], 40 | "engines": { 41 | "node": ">=8.0.0", 42 | "npm": ">=5.0.0" 43 | }, 44 | "jest": { 45 | "moduleFileExtensions": [ 46 | "js", 47 | "json", 48 | "vue" 49 | ], 50 | "transform": { 51 | "^.+\\.js$": "/node_modules/babel-jest", 52 | ".*\\.(vue)$": "/node_modules/vue-jest" 53 | }, 54 | "moduleNameMapper": { 55 | "^@/(.*)$": "/lib/$1" 56 | }, 57 | "snapshotSerializers": [ 58 | "/node_modules/jest-serializer-vue" 59 | ], 60 | "collectCoverage": true, 61 | "coveragePathIgnorePatterns": [ 62 | "/node_modules/", 63 | "/test/fixtures" 64 | ] 65 | }, 66 | "devDependencies": { 67 | "@commitlint/cli": "^7.2.1", 68 | "@commitlint/config-conventional": "^7.1.2", 69 | "@nuxtjs/eslint-config": "0.0.1", 70 | "@vue/server-test-utils": "^1.0.0-beta", 71 | "@vue/test-utils": "^1.0.0-beta", 72 | "babel-core": "^6.26.3", 73 | "babel-eslint": "^10.0.1", 74 | "babel-jest": "^23.6.0", 75 | "babel-loader": "^8.0.4", 76 | "babel-preset-vue-app": "^2.0.0", 77 | "bili": "^4.0.0", 78 | "cheerio": "^1.0.0-rc.2", 79 | "codecov": "latest", 80 | "eslint": "^5.8.0", 81 | "eslint-config-standard": "^12.0.0", 82 | "eslint-plugin-import": "^2.14.0", 83 | "eslint-plugin-jest": "latest", 84 | "eslint-plugin-node": "^8.0.0", 85 | "eslint-plugin-promise": "^4.0.1", 86 | "eslint-plugin-standard": "^4.0.0", 87 | "eslint-plugin-vue": "^4.7.1", 88 | "flush-promises": "^1.0.2", 89 | "husky": "^1.1.3", 90 | "jest": "latest", 91 | "jest-serializer-vue": "^2.0.2", 92 | "jsdom": "latest", 93 | "standard-version": "latest", 94 | "vue-jest": "^3.0.0", 95 | "vue-loader": "^15.4.2", 96 | "vue-router": "^3.0.1", 97 | "vue-server-renderer": "^2.5.17", 98 | "vue-template-compiler": "^2.5.17" 99 | }, 100 | "dependencies": { 101 | "vue": "^2.5.17" 102 | }, 103 | "husky": { 104 | "hooks": { 105 | "pre-commit": "npm run lint", 106 | "commit-msg": "npm run commitlint" 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "@nuxtjs" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export default { 2 | functional: true, 3 | render(h, { children, data, props: { target, scrollFunction, shouldNavigate = false, navigationType = 'push', tag = 'div' }, parent: { $router }, _ssrNode }) { 4 | const clickFunction = () => { 5 | const fn = scrollFunction || defaultScrollFunction 6 | fn(target, { shouldNavigate, navigationType, $router }) 7 | } 8 | 9 | return h(tag, { 10 | ...data, 11 | on: { 12 | // Ignore scroll function on server side 13 | click: _ssrNode || process.server ? undefined : clickFunction 14 | } 15 | }, children) 16 | } 17 | } 18 | 19 | const defaultScrollFunction = async (rawTarget, { shouldNavigate, navigationType, $router }) => { 20 | const target = (typeof rawTarget === 'function') ? await rawTarget() : rawTarget 21 | // If no target given, auto scroll to top 22 | if (!target) { 23 | window.scroll({ 24 | top: 0, 25 | behavior: 'smooth' 26 | }) 27 | if (shouldNavigate && $router) { 28 | const currentRoute = $router.currentRoute 29 | const hash = currentRoute.hash 30 | const fullPath = currentRoute.fullPath 31 | const newPath = fullPath.replace(hash, '') 32 | navigate($router, newPath, navigationType) 33 | } 34 | return 35 | } 36 | 37 | const node = document.querySelector(target) 38 | 39 | // If target prop is present but the node does not exist, send an error 40 | if (!node) { 41 | // eslint-disable-next-line no-console 42 | return console.error(`Could not scroll to ${target}`) 43 | } 44 | 45 | node.scrollIntoView({ 46 | behavior: 'smooth' 47 | }) 48 | 49 | if (shouldNavigate && $router) { 50 | navigate($router, target, navigationType) 51 | } 52 | } 53 | 54 | const navigate = ($router, path, type) => { $router[type](path) } 55 | -------------------------------------------------------------------------------- /test/ScrollNextLevel.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | import { createLocalVue, mount } from '@vue/test-utils' 3 | import { render } from '@vue/server-test-utils' 4 | import flushPromises from 'flush-promises' 5 | import VueRouter from 'vue-router' 6 | import ScrollNextLevel from '../src' 7 | import Target from './fixtures/Target' 8 | 9 | const targetString = '#target' 10 | 11 | describe('ScrollNextLevel', () => { 12 | let spy 13 | 14 | beforeAll(() => { 15 | global.scroll = () => {} 16 | }) 17 | 18 | beforeEach(() => { 19 | Element.prototype.scrollIntoView = () => {} 20 | }) 21 | 22 | afterEach(() => { 23 | if (spy) { 24 | try { 25 | spy.mockClear() 26 | } catch (e) {} 27 | spy = undefined 28 | } 29 | }) 30 | 31 | describe('default scroll', () => { 32 | describe('clicked', () => { 33 | it('does scroll to top without target', () => { 34 | spy = jest.spyOn(global, 'scroll') 35 | const wrapper = mount(ScrollNextLevel, { 36 | attachToDocument: true 37 | }) 38 | 39 | expect(spy).toHaveBeenCalledTimes(0) 40 | 41 | wrapper.trigger('click') 42 | 43 | expect(spy).toBeCalledWith({ 44 | top: 0, 45 | behavior: 'smooth' 46 | }) 47 | }) 48 | 49 | it('does navigate to path without hash when enabled and scroll to top', () => { 50 | spy = jest.spyOn(global, 'scroll') 51 | const localVue = createLocalVue() 52 | localVue.use(VueRouter) 53 | const router = new VueRouter() 54 | 55 | const wrapper = mount(ScrollNextLevel, { 56 | attachToDocument: true, 57 | context: { 58 | props: { 59 | shouldNavigate: true 60 | } 61 | }, 62 | localVue, 63 | router 64 | }) 65 | 66 | router.replace('#test') 67 | 68 | expect(spy).toHaveBeenCalledTimes(0) 69 | 70 | wrapper.trigger('click') 71 | 72 | expect(spy).toBeCalledWith({ 73 | top: 0, 74 | behavior: 'smooth' 75 | }) 76 | expect(router.currentRoute.fullPath).toBe('/') 77 | }) 78 | 79 | it('does smooth scroll to target when present', () => { 80 | spy = jest.spyOn(Element.prototype, 'scrollIntoView') 81 | 82 | const wrapper = mount(ScrollNextLevel, { 83 | attachToDocument: true, 84 | context: { 85 | props: { 86 | target: targetString 87 | } 88 | }, 89 | slots: { 90 | default: Target 91 | } 92 | }) 93 | 94 | expect(wrapper.html()).toBe('
Hi
') 95 | 96 | expect(wrapper.contains(targetString)).toBe(true) 97 | 98 | const element = wrapper.find(targetString).element 99 | 100 | expect(element.scrollIntoView).toHaveBeenCalledTimes(0) 101 | 102 | wrapper.trigger('click') 103 | 104 | expect(element.scrollIntoView).toBeCalledWith({ 105 | behavior: 'smooth' 106 | }) 107 | }) 108 | 109 | it('does navigate to target after smooth-scrolling', () => { 110 | spy = jest.spyOn(Element.prototype, 'scrollIntoView') 111 | const localVue = createLocalVue() 112 | localVue.use(VueRouter) 113 | const router = new VueRouter() 114 | 115 | const wrapper = mount(ScrollNextLevel, { 116 | attachToDocument: true, 117 | context: { 118 | props: { 119 | target: targetString, 120 | shouldNavigate: true 121 | } 122 | }, 123 | slots: { 124 | default: Target 125 | }, 126 | localVue, 127 | router 128 | }) 129 | 130 | expect(wrapper.html()).toBe('
Hi
') 131 | 132 | expect(wrapper.contains(targetString)).toBe(true) 133 | 134 | const element = wrapper.find(targetString).element 135 | 136 | expect(element.scrollIntoView).toHaveBeenCalledTimes(0) 137 | 138 | wrapper.trigger('click') 139 | 140 | expect(element.scrollIntoView).toBeCalledWith({ 141 | behavior: 'smooth' 142 | }) 143 | 144 | expect(router.currentRoute.fullPath).toBe(`/${targetString}`) 145 | }) 146 | 147 | it('does send error if target is set but not present', () => { 148 | const weirdTarget = 'weird things here' 149 | spy = jest.spyOn(console, 'error') 150 | 151 | const wrapper = mount(ScrollNextLevel, { 152 | attachToDocument: true, 153 | context: { 154 | props: { 155 | target: weirdTarget 156 | } 157 | } 158 | }) 159 | 160 | expect(spy).toHaveBeenCalledTimes(0) 161 | 162 | wrapper.trigger('click') 163 | 164 | expect(spy).toBeCalledWith(`Could not scroll to ${weirdTarget}`) 165 | }) 166 | 167 | it('does smooth scroll to target (as function) when present', async () => { 168 | spy = jest.spyOn(Element.prototype, 'scrollIntoView') 169 | 170 | const wrapper = mount(ScrollNextLevel, { 171 | attachToDocument: true, 172 | context: { 173 | props: { 174 | target: async () => { 175 | await Promise.resolve(r => setTimeout(r, Math.random() * 500)) 176 | return targetString 177 | } 178 | } 179 | }, 180 | slots: { 181 | default: Target 182 | } 183 | }) 184 | 185 | expect(wrapper.html()).toBe('
Hi
') 186 | 187 | expect(wrapper.contains(targetString)).toBe(true) 188 | 189 | const element = wrapper.find(targetString).element 190 | 191 | expect(element.scrollIntoView).toHaveBeenCalledTimes(0) 192 | 193 | wrapper.trigger('click') 194 | 195 | await flushPromises() 196 | 197 | expect(element.scrollIntoView).toHaveBeenCalledTimes(1) 198 | 199 | expect(element.scrollIntoView).toBeCalledWith({ 200 | behavior: 'smooth' 201 | }) 202 | }) 203 | }) 204 | }) 205 | 206 | describe('custom scroll function', () => { 207 | it('does not call custom function if not clicked', () => { 208 | const spy = jest.fn() 209 | mount(ScrollNextLevel, { 210 | context: { 211 | props: { 212 | scrollFunction: spy 213 | } 214 | }, 215 | attachToDocument: true 216 | }) 217 | 218 | expect(spy).toHaveBeenCalledTimes(0) 219 | }) 220 | 221 | it('calls custom function on click', () => { 222 | const spy = jest.fn(() => {}) 223 | const wrapper = mount(ScrollNextLevel, { 224 | context: { 225 | props: { 226 | scrollFunction: spy 227 | } 228 | }, 229 | attachToDocument: true 230 | }) 231 | wrapper.trigger('click') 232 | 233 | expect(spy).toBeCalledWith(undefined, { $parent: undefined, navigationType: 'push', shouldNavigate: false }) 234 | }) 235 | 236 | it('calls custom function with target on click', () => { 237 | const spy = jest.fn(() => {}) 238 | const wrapper = mount(ScrollNextLevel, { 239 | context: { 240 | props: { 241 | scrollFunction: spy, 242 | target: targetString 243 | } 244 | }, 245 | attachToDocument: true 246 | }) 247 | wrapper.trigger('click') 248 | 249 | expect(spy).toBeCalledWith(targetString, { 250 | $parent: undefined, 251 | navigationType: 'push', 252 | shouldNavigate: false 253 | }) 254 | }) 255 | }) 256 | 257 | describe('SSR', () => { 258 | it('does nothing on server-side', (done) => { 259 | try { 260 | render(ScrollNextLevel, { 261 | context: { 262 | props: { 263 | targetString 264 | } 265 | }, 266 | slots: { 267 | default: Target 268 | } 269 | }) 270 | done() 271 | } catch (e) { } 272 | }) 273 | }) 274 | }) 275 | -------------------------------------------------------------------------------- /test/fixtures/Target.vue: -------------------------------------------------------------------------------- 1 | 4 | --------------------------------------------------------------------------------