From 1663a6eef932015cb9b13af38eb0446d9c22d6ec Mon Sep 17 00:00:00 2001 From: mcibique Date: Mon, 19 Mar 2018 23:54:21 +0000 Subject: [PATCH 1/2] WIP --- src/di.js | 58 +++++++++++++++++++++++++++++++++++++ src/main.js | 3 +- src/views/Login.vue | 7 ++--- src/views/Login.vue.spec.js | 25 +++++++++++++--- 4 files changed, 83 insertions(+), 10 deletions(-) diff --git a/src/di.js b/src/di.js index bc1b11d..5a43ba5 100644 --- a/src/di.js +++ b/src/di.js @@ -45,3 +45,61 @@ export default container; // global registrations export const GLOBAL_ID = Symbol('global'); container.bind(GLOBAL_ID).toConstantValue(global); + +export const TIMEOUT_ID = Symbol('timeout'); +container.bind(TIMEOUT_ID).toDynamicValue(function ({ container }) { + let global = container.get(GLOBAL_ID); + let timeout = global.setTimeout.bind(global); + timeout.cancel = global.clearTimeout.bind(global); + return timeout; +}).inSingletonScope(); + +export const DOCUMENT_ID = Symbol('document'); +container.bind(DOCUMENT_ID).toDynamicValue(function ({ container }) { + let global = container.get(GLOBAL_ID); + return global.document; +}).inSingletonScope(); + +export class VueDI { + static install (Vue) { + Object.defineProperty(Vue.prototype, '$global', { + get () { + return container.get(GLOBAL_ID); + } + }); + + Object.defineProperty(Vue.prototype, '$timeout', { + get () { + return container.get(TIMEOUT_ID); + } + }); + + Object.defineProperty(Vue.prototype, '$document', { + get () { + return container.get(DOCUMENT_ID); + } + }); + } +} + +if (process.env.NODE_ENV === 'test') { + function init() { + container.rebind(TIMEOUT_ID).toDynamicValue(function ({ container }) { + let globalMock = {}; + let clock = require('lolex').install({ target: globalMock, toFake: ['setTimeout', 'clearTimeout'] }); + + let timeout = clock.setTimeout.bind(clock); + let cancel = clock.clearTimeout.bind(clock); + + Object.setPrototypeOf(timeout, clock); + timeout.cancel = cancel; + timeout.restore = function () { + init(); + } + return timeout; + + }).inSingletonScope(); + } + + init(); +} \ No newline at end of file diff --git a/src/main.js b/src/main.js index e6cb91d..f587348 100644 --- a/src/main.js +++ b/src/main.js @@ -1,5 +1,5 @@ import './bootstrap'; -import { registerConstantValue } from './di'; +import { registerConstantValue, VueDI } from './di'; import Vue from 'vue'; import App from './App.vue'; import { createRouter, ROUTER_ID } from './router'; @@ -7,6 +7,7 @@ import { createStore, STORE_ID } from './store'; import './services/api'; Vue.config.productionTip = false; +Vue.use(VueDI); let store = createStore(Vue); registerConstantValue(STORE_ID, store); diff --git a/src/views/Login.vue b/src/views/Login.vue index dcfa92e..a469ff3 100644 --- a/src/views/Login.vue +++ b/src/views/Login.vue @@ -26,7 +26,6 @@ import Vue from 'vue'; import { Component } from 'vue-property-decorator'; -import { LazyInject, GLOBAL_ID } from '@di'; import MyButton from '@/components/MyButton'; import Focus from '@/directives/focus'; @@ -40,8 +39,6 @@ export default class LoginView extends Vue { validationError = null; displayHelp = false; - @LazyInject(GLOBAL_ID) global; - login (username, password) { return this.$store.dispatch('auth/login', { username, password }); } @@ -76,13 +73,13 @@ export default class LoginView extends Vue { } created () { - this.displayHelpTimeout = this.global.setTimeout(() => { + this.displayHelpTimeout = this.$timeout(() => { this.displayHelp = true; }, 5000); } destroyed () { - this.global.clearTimeout(this.displayHelpTimeout); + this.$timeout.cancel(this.displayHelpTimeout); } } diff --git a/src/views/Login.vue.spec.js b/src/views/Login.vue.spec.js index 65c3b6c..f2fa086 100644 --- a/src/views/Login.vue.spec.js +++ b/src/views/Login.vue.spec.js @@ -7,7 +7,7 @@ import axios from 'axios'; import AxiosMockAdapter from 'axios-mock-adapter'; import flushPromises from 'flush-promises'; -import container, { GLOBAL_ID } from '@di'; +import container, { GLOBAL_ID, VueDI, TIMEOUT_ID } from '@di'; import LoginView from '@/views/Login.vue'; import LoginViewPageObj from '@/views/Login.vue.po'; import { createStore, STORE_ID } from '@/store'; @@ -18,16 +18,22 @@ describe('Login view', function () { this.axios = new AxiosMockAdapter(axios); this.localVue = createLocalVue(); + this.localVue.use(VueDI); + this.store = createStore(this.localVue); container.bind(STORE_ID).toConstantValue(this.store); this.router = createRouter(this.localVue); container.bind(ROUTER_ID).toConstantValue(this.router); +<<<<<<< f013b6472b4d8abb895ff9593e931b06c8d77af5 // mocking setTimeout, clearTimeout global function and enable time traveling let globalMock = {}; this.clock = lolex.install({ target: globalMock, toFake: ['setTimeout', 'clearTimeout'] }); container.rebind(GLOBAL_ID).toConstantValue(globalMock); +======= + this.$timeout = container.get(TIMEOUT_ID); +>>>>>>> WIP this.mountLoginView = function (options) { let wrapper = mount(LoginView, { localVue: this.localVue, router: this.router, store: this.store, ...options }); @@ -43,7 +49,7 @@ describe('Login view', function () { this.axios.verifyNoOutstandingExpectation(); this.axios.restore(); - this.clock.uninstall(); + this.$timeout.restore(); }); it('should enter route', function () { @@ -174,12 +180,23 @@ describe('Login view', function () { let expectedTimeWhenHelpSectionIsVisible = 5000; let tickStep = 1000; +<<<<<<< f013b6472b4d8abb895ff9593e931b06c8d77af5 while ((this.clock.now + tickStep) < expectedTimeWhenHelpSectionIsVisible) { this.clock.tick(tickStep); expect(this.loginView.helpSection.exists()).to.be.false; } this.clock.tick(tickStep); +======= + while ((this.$timeout.now + tickStep) < expectedTimeWhenHelpSectionIsVisible) { + this.$timeout.tick(tickStep); + this.loginView.update(); + expect(this.loginView.helpSection.exists()).to.be.false; + } + + this.$timeout.tick(tickStep); + this.loginView.update(); +>>>>>>> WIP expect(this.loginView.helpSection.exists()).to.be.true; }); }); @@ -187,13 +204,13 @@ describe('Login view', function () { describe('when the view is destroyed', function () { beforeEach(function () { this.loginView = this.mountLoginView(); - expect(Object.keys(this.clock.timers).length).to.equal(1); + expect(Object.keys(this.$timeout.timers).length).to.equal(1); this.loginView.destroy(); }); it('should perform a clean up', function () { - expect(Object.keys(this.clock.timers).length).to.equal(0); + expect(Object.keys(this.$timeout.timers).length).to.equal(0); }); }); }); From 6dc244a1f4e0515962311afddbf497c624f6dd1a Mon Sep 17 00:00:00 2001 From: mcibique Date: Thu, 12 Apr 2018 18:54:17 +0100 Subject: [PATCH 2/2] WIP --- src/di.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/di.js b/src/di.js index 5a43ba5..5b2d5b9 100644 --- a/src/di.js +++ b/src/di.js @@ -83,7 +83,7 @@ export class VueDI { } if (process.env.NODE_ENV === 'test') { - function init() { + (function init () { container.rebind(TIMEOUT_ID).toDynamicValue(function ({ container }) { let globalMock = {}; let clock = require('lolex').install({ target: globalMock, toFake: ['setTimeout', 'clearTimeout'] }); @@ -95,11 +95,8 @@ if (process.env.NODE_ENV === 'test') { timeout.cancel = cancel; timeout.restore = function () { init(); - } + }; return timeout; - }).inSingletonScope(); - } - - init(); -} \ No newline at end of file + })(); +}