From d331fc3d82d3b861831b5598094ce55f5bbc9f1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Kr=C3=B3l?= Date: Sat, 27 Jun 2020 17:22:03 +0200 Subject: [PATCH 1/5] enabledOnProduction flag and basic logic added --- src/deprecate.ts | 10 +++++++++- types/deprecate.d.ts | 4 +++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/deprecate.ts b/src/deprecate.ts index c6c83c2..5c83e49 100644 --- a/src/deprecate.ts +++ b/src/deprecate.ts @@ -53,13 +53,21 @@ function printDeprecated (message: string) { } interface VueDeprecateOptions { + enabledOnProduction: boolean; +} +const defaultOptions: VueDeprecateOptions = { + enabledOnProduction: false, } const VueDeprecate: PluginObject = { - install: function (vue: typeof Vue, options?: VueDeprecateOptions) { + install: function (vue: typeof Vue, options: VueDeprecateOptions = defaultOptions) { vue.mixin({ created: function () { + if (process.env.NODE_ENV === 'production' && options && !options.enabledOnProduction) { + return; + } + // TODO: fix typings checkComponent(this as Vue); checkProps(this as Vue); diff --git a/types/deprecate.d.ts b/types/deprecate.d.ts index 772247b..f7ca613 100644 --- a/types/deprecate.d.ts +++ b/types/deprecate.d.ts @@ -2,7 +2,9 @@ import Vue, { PluginObject } from 'vue'; export declare interface VueDeprecateOptions {} -interface VueDeprecate extends PluginObject {} +interface VueDeprecate extends PluginObject { + enabledOnProduction: boolean; +} declare const VueDeprecate: VueDeprecate From abba9c489bb44afa43e03d694994527cc29d0198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Kr=C3=B3l?= Date: Sat, 27 Jun 2020 17:25:49 +0200 Subject: [PATCH 2/5] code splitted into smaller files --- src/components.ts | 16 ++++++++++++++ src/deprecate.ts | 54 ++--------------------------------------------- src/helpers.ts | 9 ++++++++ src/logger.ts | 3 +++ src/properties.ts | 29 +++++++++++++++++++++++++ 5 files changed, 59 insertions(+), 52 deletions(-) create mode 100644 src/components.ts create mode 100644 src/helpers.ts create mode 100644 src/logger.ts create mode 100644 src/properties.ts diff --git a/src/components.ts b/src/components.ts new file mode 100644 index 0000000..a8d927d --- /dev/null +++ b/src/components.ts @@ -0,0 +1,16 @@ +import Vue from 'vue'; +import { printDeprecated } from '@/logger'; +import { getComponentOptions } from '@/helpers'; + +export const checkComponent = (component: Vue) => { + const options = getComponentOptions(component); + if (!options || !options.deprecated) { + return; + } + + if (typeof options.deprecated === "string") { + printDeprecated(options.deprecated); + } else { + printDeprecated('Component ' + options.name + ' is deprecated'); + } +} diff --git a/src/deprecate.ts b/src/deprecate.ts index 5c83e49..efac2c3 100644 --- a/src/deprecate.ts +++ b/src/deprecate.ts @@ -1,56 +1,6 @@ import Vue, { PluginObject } from 'vue'; - -function getOptions(component: Vue) { - if (!component.$vnode) { - return; - } - - return (component.$vnode.componentOptions?.Ctor as any).options; -} - -function checkComponent (component: Vue) { - const options = getOptions(component); - if (!options || !options.deprecated) { - return; - } - - if (typeof options.deprecated === "string") { - printDeprecated(options.deprecated); - } else { - printDeprecated('Component ' + options.name + ' is deprecated'); - } -} - -function checkProps (component: Vue) { - const options = getOptions(component); - if (!options || !options.props || typeof options.props !== 'object') { - return; - } - - const propsData = component.$options.propsData as any; - if (!propsData) { - return - } - - Object.keys(options.props).forEach(key => { - const value = options.props[key]; - if (!propsData[key] || !value.deprecated) { - return; - } - - if (typeof value.deprecated === "string") { - printDeprecated(value.deprecated); - } else { - printDeprecated(`Property ${key} in component ${options.name} is deprecated`); - } - } - ) -} - - -function printDeprecated (message: string) { - console.warn(`[DEPRECATED] ${message}`); -} +import { checkComponent } from '@/components'; +import { checkProps } from '@/properties'; interface VueDeprecateOptions { enabledOnProduction: boolean; diff --git a/src/helpers.ts b/src/helpers.ts new file mode 100644 index 0000000..0539864 --- /dev/null +++ b/src/helpers.ts @@ -0,0 +1,9 @@ +import Vue from 'vue'; + +export const getComponentOptions = (component: Vue) => { + if (!component.$vnode) { + return; + } + + return (component.$vnode.componentOptions?.Ctor as any).options; +} diff --git a/src/logger.ts b/src/logger.ts new file mode 100644 index 0000000..2943445 --- /dev/null +++ b/src/logger.ts @@ -0,0 +1,3 @@ +export const printDeprecated = (message: string) => { + console.warn(`[DEPRECATED] ${message}`); +} diff --git a/src/properties.ts b/src/properties.ts new file mode 100644 index 0000000..bb365c7 --- /dev/null +++ b/src/properties.ts @@ -0,0 +1,29 @@ +import Vue from 'vue'; +import { printDeprecated } from '@/logger'; +import { getComponentOptions } from '@/helpers'; + +export const checkProps = (component: Vue) => { + const options = getComponentOptions(component); + if (!options || !options.props || typeof options.props !== 'object') { + return; + } + + const propsData = component.$options.propsData as any; + if (!propsData) { + return + } + + Object.keys(options.props).forEach(key => { + const value = options.props[key]; + if (!propsData[key] || !value.deprecated) { + return; + } + + if (typeof value.deprecated === "string") { + printDeprecated(value.deprecated); + } else { + printDeprecated(`Property ${key} in component ${options.name} is deprecated`); + } + } + ) +} From b7bb745792c28c2cc38e8881d04c81dd0d3ca63b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Kr=C3=B3l?= Date: Sat, 27 Jun 2020 17:36:57 +0200 Subject: [PATCH 3/5] tests added --- src/deprecate.ts | 2 +- tests/unit/components.spec.ts | 2 +- tests/unit/options.spec.ts | 127 ++++++++++++++++++++++++++++++++++ tests/unit/props.spec.ts | 4 +- types/deprecate.d.ts | 2 +- 5 files changed, 132 insertions(+), 5 deletions(-) create mode 100644 tests/unit/options.spec.ts diff --git a/src/deprecate.ts b/src/deprecate.ts index efac2c3..93b656c 100644 --- a/src/deprecate.ts +++ b/src/deprecate.ts @@ -3,7 +3,7 @@ import { checkComponent } from '@/components'; import { checkProps } from '@/properties'; interface VueDeprecateOptions { - enabledOnProduction: boolean; + enabledOnProduction?: boolean; } const defaultOptions: VueDeprecateOptions = { diff --git a/tests/unit/components.spec.ts b/tests/unit/components.spec.ts index f9c0e58..0038ce0 100644 --- a/tests/unit/components.spec.ts +++ b/tests/unit/components.spec.ts @@ -1,4 +1,4 @@ -import { shallowMount, createLocalVue, VueClass } from '@vue/test-utils'; +import { shallowMount, createLocalVue } from '@vue/test-utils'; import VueDeprecate from '@/deprecate'; describe('Components', () => { diff --git a/tests/unit/options.spec.ts b/tests/unit/options.spec.ts new file mode 100644 index 0000000..061b16a --- /dev/null +++ b/tests/unit/options.spec.ts @@ -0,0 +1,127 @@ +import { shallowMount, createLocalVue } from '@vue/test-utils'; +import VueDeprecate from '@/deprecate'; + +describe('Options', () => { + + const deprecatedComponent = { + name: 'DeprecatedComponent', + deprecated: true, + props: { + deprecatedProp: { deprecated: true }, + }, + template: '
this is component
' + }; + + // TODO: fix types + function mountWithPluginSpy(component: any, options?: any) { + const installSpy = jest.spyOn(VueDeprecate, 'install'); + + const localVue = createLocalVue() + localVue.use(VueDeprecate, options); + + shallowMount(component, { + localVue, + propsData: { + deprecatedProp: 'some value', + } + }); + + expect(installSpy).toHaveBeenCalled(); + } + + const OLD_ENV = process.env; + + beforeEach(() => { + jest.resetModules(); + process.env = { ...OLD_ENV }; + delete process.env.NODE_ENV; + }); + + afterEach(() => { + process.env = OLD_ENV; + }); + + it('log warnings if no options and not production', () => { + const warnMock = jest.fn(); + console.warn = warnMock; + + mountWithPluginSpy(deprecatedComponent); + + expect(warnMock).toHaveBeenCalledTimes(2); + }); + + it('log warnings if empty options and not production', () => { + const warnMock = jest.fn(); + console.warn = warnMock; + + mountWithPluginSpy(deprecatedComponent, {}); + + expect(warnMock).toHaveBeenCalledTimes(2); + }); + + it('log warnings if enabledOnProduction=true and not production', () => { + const warnMock = jest.fn(); + console.warn = warnMock; + + mountWithPluginSpy(deprecatedComponent, { + enabledOnProduction: true, + }); + + expect(warnMock).toHaveBeenCalledTimes(2); + }); + + it('log warnings if enabledOnProduction=false and not production', () => { + const warnMock = jest.fn(); + console.warn = warnMock; + + mountWithPluginSpy(deprecatedComponent, { + enabledOnProduction: false, + }); + + expect(warnMock).toHaveBeenCalledTimes(2); + }); + + it('no warnings if no options and production', () => { + const warnMock = jest.fn(); + console.warn = warnMock; + + process.env.NODE_ENV = 'production'; + mountWithPluginSpy(deprecatedComponent); + + expect(warnMock).not.toHaveBeenCalled(); + }); + + it('no warnings if empty options and production', () => { + const warnMock = jest.fn(); + console.warn = warnMock; + + process.env.NODE_ENV = 'production'; + mountWithPluginSpy(deprecatedComponent, {}); + + expect(warnMock).not.toHaveBeenCalled(); + }); + + it('log warnings if enabledOnProduction=true and production', () => { + const warnMock = jest.fn(); + console.warn = warnMock; + + process.env.NODE_ENV = 'production'; + mountWithPluginSpy(deprecatedComponent, { + enabledOnProduction: true, + }); + + expect(warnMock).toHaveBeenCalledTimes(2); + }); + + it('no warnings if enabledOnProduction=false and production', () => { + const warnMock = jest.fn(); + console.warn = warnMock; + + process.env.NODE_ENV = 'production'; + mountWithPluginSpy(deprecatedComponent, { + enabledOnProduction: false, + }); + + expect(warnMock).not.toHaveBeenCalled(); + }); +}); diff --git a/tests/unit/props.spec.ts b/tests/unit/props.spec.ts index 27b8464..b6c14f4 100644 --- a/tests/unit/props.spec.ts +++ b/tests/unit/props.spec.ts @@ -128,7 +128,7 @@ describe('Props', () => { deprecatedProp: 'value' }); - expect(warnMock).toHaveBeenCalledTimes(1) + expect(warnMock).toHaveBeenCalledTimes(1); expect(warnMock.mock.calls[0][0]).toContain('[DEPRECATED]'); expect(warnMock.mock.calls[0][0]).toContain(componentWithObjectProps.name); expect(warnMock.mock.calls[0][0]).toContain('deprecatedProp'); @@ -142,7 +142,7 @@ describe('Props', () => { deprecatedPropWithDefaultVal: true, }); - expect(warnMock).toHaveBeenCalledTimes(1) + expect(warnMock).toHaveBeenCalledTimes(1); expect(warnMock.mock.calls[0][0]).toContain('[DEPRECATED]'); expect(warnMock.mock.calls[0][0]).toContain(componentWithObjectProps.name); expect(warnMock.mock.calls[0][0]).toContain('deprecatedPropWithDefaultVal'); diff --git a/types/deprecate.d.ts b/types/deprecate.d.ts index f7ca613..385a96f 100644 --- a/types/deprecate.d.ts +++ b/types/deprecate.d.ts @@ -3,7 +3,7 @@ import Vue, { PluginObject } from 'vue'; export declare interface VueDeprecateOptions {} interface VueDeprecate extends PluginObject { - enabledOnProduction: boolean; + enabledOnProduction?: boolean; } declare const VueDeprecate: VueDeprecate From 5cab8f85f7afd3360aabc2c31499c5d6580542c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Kr=C3=B3l?= Date: Sat, 27 Jun 2020 17:38:39 +0200 Subject: [PATCH 4/5] version update --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 783071e..2ea1383 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-deprecate", - "version": "0.2.4", + "version": "0.3.0", "author": "fringers", "scripts": { "build": "vue-cli-service build --target lib src/deprecate.ts --mode production", From 7e7abe16bcd1a3e6347f2fb323e7b79be9de96da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Kr=C3=B3l?= Date: Sat, 27 Jun 2020 17:45:23 +0200 Subject: [PATCH 5/5] tests update --- tests/unit/options.spec.ts | 136 +++++++++++++++++++------------------ 1 file changed, 71 insertions(+), 65 deletions(-) diff --git a/tests/unit/options.spec.ts b/tests/unit/options.spec.ts index 061b16a..5c95caa 100644 --- a/tests/unit/options.spec.ts +++ b/tests/unit/options.spec.ts @@ -29,99 +29,105 @@ describe('Options', () => { expect(installSpy).toHaveBeenCalled(); } - const OLD_ENV = process.env; + describe('enabledOnProduction', () => { + const OLD_ENV = process.env; - beforeEach(() => { - jest.resetModules(); - process.env = { ...OLD_ENV }; - delete process.env.NODE_ENV; - }); + beforeEach(() => { + jest.resetModules(); + process.env = { ...OLD_ENV }; + delete process.env.NODE_ENV; + }); - afterEach(() => { - process.env = OLD_ENV; - }); + afterEach(() => { + process.env = OLD_ENV; + }); - it('log warnings if no options and not production', () => { - const warnMock = jest.fn(); - console.warn = warnMock; + it('log warnings if no options and not production', () => { + const warnMock = jest.fn(); + console.warn = warnMock; - mountWithPluginSpy(deprecatedComponent); + mountWithPluginSpy(deprecatedComponent); - expect(warnMock).toHaveBeenCalledTimes(2); - }); + expect(warnMock).toHaveBeenCalledTimes(2); + }); - it('log warnings if empty options and not production', () => { - const warnMock = jest.fn(); - console.warn = warnMock; + it('log warnings if other options and not production', () => { + const warnMock = jest.fn(); + console.warn = warnMock; - mountWithPluginSpy(deprecatedComponent, {}); + mountWithPluginSpy(deprecatedComponent, { + someProp: 'value', + }); - expect(warnMock).toHaveBeenCalledTimes(2); - }); + expect(warnMock).toHaveBeenCalledTimes(2); + }); + + it('log warnings if enabledOnProduction=true and not production', () => { + const warnMock = jest.fn(); + console.warn = warnMock; - it('log warnings if enabledOnProduction=true and not production', () => { - const warnMock = jest.fn(); - console.warn = warnMock; + mountWithPluginSpy(deprecatedComponent, { + enabledOnProduction: true, + }); - mountWithPluginSpy(deprecatedComponent, { - enabledOnProduction: true, + expect(warnMock).toHaveBeenCalledTimes(2); }); - expect(warnMock).toHaveBeenCalledTimes(2); - }); + it('log warnings if enabledOnProduction=false and not production', () => { + const warnMock = jest.fn(); + console.warn = warnMock; - it('log warnings if enabledOnProduction=false and not production', () => { - const warnMock = jest.fn(); - console.warn = warnMock; + mountWithPluginSpy(deprecatedComponent, { + enabledOnProduction: false, + }); - mountWithPluginSpy(deprecatedComponent, { - enabledOnProduction: false, + expect(warnMock).toHaveBeenCalledTimes(2); }); - expect(warnMock).toHaveBeenCalledTimes(2); - }); + it('no warnings if no options and production', () => { + const warnMock = jest.fn(); + console.warn = warnMock; - it('no warnings if no options and production', () => { - const warnMock = jest.fn(); - console.warn = warnMock; + process.env.NODE_ENV = 'production'; + mountWithPluginSpy(deprecatedComponent); - process.env.NODE_ENV = 'production'; - mountWithPluginSpy(deprecatedComponent); + expect(warnMock).not.toHaveBeenCalled(); + }); - expect(warnMock).not.toHaveBeenCalled(); - }); + it('no warnings if other options and production', () => { + const warnMock = jest.fn(); + console.warn = warnMock; - it('no warnings if empty options and production', () => { - const warnMock = jest.fn(); - console.warn = warnMock; + process.env.NODE_ENV = 'production'; + mountWithPluginSpy(deprecatedComponent, { + someProp: 'value', + }); - process.env.NODE_ENV = 'production'; - mountWithPluginSpy(deprecatedComponent, {}); + expect(warnMock).not.toHaveBeenCalled(); + }); - expect(warnMock).not.toHaveBeenCalled(); - }); + it('log warnings if enabledOnProduction=true and production', () => { + const warnMock = jest.fn(); + console.warn = warnMock; - it('log warnings if enabledOnProduction=true and production', () => { - const warnMock = jest.fn(); - console.warn = warnMock; + process.env.NODE_ENV = 'production'; + mountWithPluginSpy(deprecatedComponent, { + enabledOnProduction: true, + }); - process.env.NODE_ENV = 'production'; - mountWithPluginSpy(deprecatedComponent, { - enabledOnProduction: true, + expect(warnMock).toHaveBeenCalledTimes(2); }); - expect(warnMock).toHaveBeenCalledTimes(2); - }); + it('no warnings if enabledOnProduction=false and production', () => { + const warnMock = jest.fn(); + console.warn = warnMock; - it('no warnings if enabledOnProduction=false and production', () => { - const warnMock = jest.fn(); - console.warn = warnMock; + process.env.NODE_ENV = 'production'; + mountWithPluginSpy(deprecatedComponent, { + enabledOnProduction: false, + }); - process.env.NODE_ENV = 'production'; - mountWithPluginSpy(deprecatedComponent, { - enabledOnProduction: false, + expect(warnMock).not.toHaveBeenCalled(); }); - - expect(warnMock).not.toHaveBeenCalled(); }); });