From 139ced06f5169e84abe9879d0e003dae08456b00 Mon Sep 17 00:00:00 2001 From: Rijk van Zanten Date: Mon, 24 Feb 2020 12:05:06 -0500 Subject: [PATCH] Implement router dynamic route replacement logic (#116) * Implement router dynamic route replacement logic Vue router has pretty bad dynamic route registration handlers, meaning we have to hack around replacing the full routes array in order to achieve properly matched routes * Add test coverage for replacerouter function * Replace anonymous event handlers with named HoCs for better test coverage * Add tests for module registration * Get test coverage to 100% --- src/directives/tooltip/tooltip.test.ts | 28 +++-- src/directives/tooltip/tooltip.ts | 40 ++++--- src/main.ts | 4 +- src/modules/collections/collections.vue | 12 +- src/modules/files/files.vue | 4 +- src/modules/index.ts | 6 - src/modules/register.test.ts | 146 ++++++++++++++++++++++++ src/modules/register.ts | 66 +++++++++++ src/modules/settings/settings.vue | 4 +- src/modules/users/users.vue | 4 +- src/router.test.ts | 34 +++--- src/router.ts | 100 +++++++++------- src/stores/modules/modules.test.ts | 104 ----------------- src/stores/modules/modules.ts | 39 +------ src/views/private/private-view.vue | 8 +- 15 files changed, 359 insertions(+), 240 deletions(-) delete mode 100644 src/modules/index.ts create mode 100644 src/modules/register.test.ts create mode 100644 src/modules/register.ts delete mode 100644 src/stores/modules/modules.test.ts diff --git a/src/directives/tooltip/tooltip.test.ts b/src/directives/tooltip/tooltip.test.ts index 46e522076c..c705f89f6e 100644 --- a/src/directives/tooltip/tooltip.test.ts +++ b/src/directives/tooltip/tooltip.test.ts @@ -15,13 +15,21 @@ jest.useFakeTimers(); const localVue = createLocalVue(); localVue.use(VueCompositionAPI); localVue.component('v-button', VButton); -localVue.directive('tooltip', Tooltip); describe('Tooltip', () => { afterEach(() => { document.getElementsByTagName('html')[0].innerHTML = ''; }); + describe('Directive', () => { + it('Registers onmouseenter and onmouseleave event handlers', () => { + const element = document.createElement('div'); + element.addEventListener = jest.fn(); + Tooltip.bind!(element, {} as any, null as any, null as any); + expect(element.addEventListener).toHaveBeenCalledTimes(2); + }); + }); + describe('onEnterTooltip', () => { it('Instant does not wait to show the tooltip', () => { const div = document.createElement('div'); @@ -35,7 +43,7 @@ describe('Tooltip', () => { top: true, instant: true } - }); + })(); expect(tooltip.className).toBe('visible enter top'); }); @@ -52,7 +60,7 @@ describe('Tooltip', () => { top: true, instant: false } - }); + })(); expect(tooltip.className).toBe(''); jest.advanceTimersByTime(650); @@ -60,6 +68,13 @@ describe('Tooltip', () => { }); }); + describe('onLeaveTooltip', () => { + it('Clears the timeout', () => { + onLeaveTooltip()(); + expect(clearTimeout).toHaveBeenCalled(); + }); + }); + describe('updateTooltip', () => { describe('Styles and classes', () => { type Modifier = { @@ -279,13 +294,6 @@ describe('Tooltip', () => { }); }); - describe('onLeaveTooltip', () => { - it('Clears the timeout', () => { - onLeaveTooltip(); - expect(clearTimeout).toHaveBeenCalled(); - }); - }); - describe('animateIn / animateOut', () => { it('Adds the appropriate classes on entering', () => { const div = document.createElement('div'); diff --git a/src/directives/tooltip/tooltip.ts b/src/directives/tooltip/tooltip.ts index e337935660..7dbd8e4b17 100644 --- a/src/directives/tooltip/tooltip.ts +++ b/src/directives/tooltip/tooltip.ts @@ -2,9 +2,9 @@ import { DirectiveOptions } from 'vue'; import { DirectiveBinding } from 'vue/types/options'; const Tooltip: DirectiveOptions = { - inserted(element, binding) { - element.onmouseenter = () => onEnterTooltip(element, binding); - element.onmouseleave = () => onLeaveTooltip(); + bind(element, binding) { + element.addEventListener('onmouseenter', onEnterTooltip(element, binding)); + element.addEventListener('onmouseleave', onLeaveTooltip()); } }; @@ -13,17 +13,28 @@ export default Tooltip; let tooltipTimer: number; export function onEnterTooltip(element: HTMLElement, binding: DirectiveBinding) { - const tooltip = getTooltip(); + return () => { + const tooltip = getTooltip(); - if (binding.modifiers.instant) { - animateIn(tooltip); - updateTooltip(element, binding, tooltip); - } else { - tooltipTimer = setTimeout(() => { + if (binding.modifiers.instant) { animateIn(tooltip); updateTooltip(element, binding, tooltip); - }, 600); - } + } else { + tooltipTimer = setTimeout(() => { + animateIn(tooltip); + updateTooltip(element, binding, tooltip); + }, 600); + } + }; +} + +export function onLeaveTooltip() { + return () => { + const tooltip = getTooltip(); + + clearTimeout(tooltipTimer); + animateOut(tooltip); + }; } export function updateTooltip( @@ -119,13 +130,6 @@ export function updateTooltip( } } -export function onLeaveTooltip() { - const tooltip = getTooltip(); - - clearTimeout(tooltipTimer); - animateOut(tooltip); -} - export function animateIn(tooltip: HTMLElement) { tooltip.classList.add('visible', 'enter'); tooltip.classList.remove('leave', 'leave-active'); diff --git a/src/main.ts b/src/main.ts index c79dc42a9d..061a8d879d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,10 +5,12 @@ import './plugins'; import './directives/register'; import './components/register'; import './views/register'; - +import { registerGlobalModules } from './modules/register'; import router from './router'; import i18n from './lang/'; +registerGlobalModules(); + Vue.config.productionTip = false; const app = new Vue({ diff --git a/src/modules/collections/collections.vue b/src/modules/collections/collections.vue index 75982f8419..16d3bd46ae 100644 --- a/src/modules/collections/collections.vue +++ b/src/modules/collections/collections.vue @@ -1,5 +1,15 @@