Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Optionally hide deprecation errors #1518

Merged
merged 3 commits into from Apr 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion flow/config.flow.js
Expand Up @@ -3,5 +3,6 @@ declare type Config = {
mocks?: Object,
methods?: { [name: string]: Function },
provide?: Object,
silent?: boolean
silent?: boolean,
showDeprecationWarnings?: boolean
}
4 changes: 3 additions & 1 deletion package.json
Expand Up @@ -98,7 +98,9 @@
"cz-conventional-changelog": "^3.0.2",
"husky": "^3.1.0",
"lint-staged": "^9.5.0",
"prettier": "^1.16.0"
"prettier": "^1.16.0",
"rollup-plugin-delete": "^1.2.0",
"rollup-plugin-replace": "^2.2.0"
},
"config": {
"commitizen": {
Expand Down
4 changes: 2 additions & 2 deletions packages/create-instance/create-component-stubs.js
Expand Up @@ -7,7 +7,7 @@ import {
capitalize,
hyphenate,
keys,
warn
warnDeprecated
} from '../shared/util'
import {
componentNeedsCompiling,
Expand Down Expand Up @@ -159,7 +159,7 @@ export function createStubFromComponent(

// DEPRECATED: converts string stub to template stub.
function createStubFromString(templateString: string, name: string): Component {
warn('String stubs are deprecated and will be removed in future versions')
warnDeprecated('Using a string for stubs')

if (templateContainsComponent(templateString, name)) {
throwError('options.stub cannot contain a circular reference')
Expand Down
9 changes: 3 additions & 6 deletions packages/shared/merge-options.js
@@ -1,6 +1,6 @@
// @flow
import { normalizeStubs, normalizeProvide } from './normalize'
import { warn } from 'shared/util'
import { warnDeprecated } from 'shared/util'

function getOption(option, config?: Object): any {
if (option === false) {
Expand Down Expand Up @@ -34,11 +34,8 @@ export function mergeOptions(
const methods = (getOption(options.methods, config.methods): {
[key: string]: Function
})

if (config.methods && Object.keys(config.methods).length) {
warn(
`config.methods has been deprecated. It will be removed in a future release`
)
if (methods && Object.keys(methods).length) {
warnDeprecated('overwriting methods via the `methods` property')
}

const provide = (getOption(options.provide, config.provide): Object)
Expand Down
8 changes: 8 additions & 0 deletions packages/shared/util.js
@@ -1,6 +1,7 @@
// @flow
import Vue from 'vue'
import semver from 'semver'
import { config } from '@vue/test-utils'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why, but this new import here breaks the IIFE. Would love some help tracking this down and fixing it. See #1553


export function throwError(msg: string): void {
throw new Error(`[vue-test-utils]: ${msg}`)
Expand Down Expand Up @@ -85,3 +86,10 @@ export function getCheckedEvent() {
// change is handler for version 2.0 - 2.1.8, and 2.5+
return 'change'
}

export function warnDeprecated(method: string, fallback: string = '') {
if (!config.showDeprecationWarnings) return
let msg = `${method} is deprecated and will removed in the next major version`
if (fallback) msg += ` ${fallback}`
warn(msg)
}
2 changes: 1 addition & 1 deletion packages/test-utils/package.json
Expand Up @@ -10,7 +10,7 @@
],
"scripts": {
"build": "node scripts/build.js",
"build:test": "cross-env NODE_ENV=test node scripts/build.js"
"build:test": "cross-env NODE_ENV=test SHOW_DEPRECATIONS=false node scripts/build.js"
},
"repository": {
"type": "git",
Expand Down
6 changes: 6 additions & 0 deletions packages/test-utils/scripts/build.js
Expand Up @@ -6,6 +6,8 @@ const nodeResolve = require('rollup-plugin-node-resolve')
const commonjs = require('rollup-plugin-commonjs')
const chalk = require('chalk')
const json = require('rollup-plugin-json')
const replace = require('rollup-plugin-replace')
const del = require('rollup-plugin-delete')

function success(text) {
console.log(chalk.green(`${text} ✔`))
Expand Down Expand Up @@ -57,6 +59,10 @@ rollupOptions.forEach(options => {
input: resolve('src/index.js'),
external: ['vue', 'vue-template-compiler'],
plugins: [
del({ targets: 'dist/*' }),
replace({
'process.env.SHOW_DEPRECATIONS': process.env.SHOW_DEPRECATIONS
}),
flow(),
json(),
buble({
Expand Down
6 changes: 5 additions & 1 deletion packages/test-utils/src/config.js
Expand Up @@ -6,5 +6,9 @@ export default {
mocks: {},
methods: {},
provide: {},
silent: true
silent: true,
showDeprecationWarnings:
typeof process.env.SHOW_DEPRECATIONS !== 'undefined'
? process.env.SHOW_DEPRECATIONS
: true
}
64 changes: 41 additions & 23 deletions packages/test-utils/src/wrapper.js
Expand Up @@ -12,7 +12,12 @@ import {
import config from './config'
import WrapperArray from './wrapper-array'
import ErrorWrapper from './error-wrapper'
import { throwError, getCheckedEvent, isPhantomJS, warn } from 'shared/util'
import {
throwError,
getCheckedEvent,
isPhantomJS,
warnDeprecated
} from 'shared/util'
import find from './find'
import createWrapper from './create-wrapper'
import { recursivelySetData } from './recursively-set-data'
Expand Down Expand Up @@ -122,8 +127,9 @@ export default class Wrapper implements BaseWrapper {
* Checks if wrapper contains provided selector.
*/
contains(rawSelector: Selector): boolean {
warn(
'contains is deprecated and will be removed in a future release. Use `wrapper.find`, `wrapper.findComponent` or `wrapper.get` instead'
warnDeprecated(
'contains',
'Use `wrapper.find`, `wrapper.findComponent` or `wrapper.get` instead'
)
const selector = getSelector(rawSelector, 'contains')
const nodes = find(this.rootNode, this.vm, selector)
Expand Down Expand Up @@ -171,9 +177,7 @@ export default class Wrapper implements BaseWrapper {
* Returns an Array containing custom events emitted by the Wrapper vm
*/
emittedByOrder(): Array<{ name: string, args: Array<any> }> {
warn(
'emittedByOrder is deprecated and will be removed in a future release. Use `wrapper.emitted` instead'
)
warnDeprecated('emittedByOrder', 'Use `wrapper.emitted` instead')
if (!this._emittedByOrder && !this.vm) {
throwError(
`wrapper.emittedByOrder() can only be called on a Vue instance`
Expand Down Expand Up @@ -201,9 +205,6 @@ export default class Wrapper implements BaseWrapper {
* matches the provided selector.
*/
get(rawSelector: Selector): Wrapper {
warn(
'get is deprecated and will be removed in a future release. Use `find` or `findComponent` instead'
)
const found = this.find(rawSelector)
if (found instanceof ErrorWrapper) {
throw new Error(`Unable to find ${rawSelector} within: ${this.html()}`)
Expand All @@ -218,8 +219,9 @@ export default class Wrapper implements BaseWrapper {
find(rawSelector: Selector): Wrapper | ErrorWrapper {
const selector = getSelector(rawSelector, 'find')
if (selector.type !== DOM_SELECTOR) {
warn(
'finding components with `find` is deprecated and will be removed in a future release. Use `findComponent` instead'
warnDeprecated(
'finding components with `find`',
'Use `findComponent` instead'
)
}
const node = find(this.rootNode, this.vm, selector)[0]
Expand All @@ -240,8 +242,9 @@ export default class Wrapper implements BaseWrapper {
findAll(rawSelector: Selector): WrapperArray {
const selector = getSelector(rawSelector, 'findAll')
if (selector.type !== DOM_SELECTOR) {
warn(
'finding components with `findAll` is deprecated and will be removed in a future release. Use `findAllComponents` instead'
warnDeprecated(
'finding components with `findAll`',
'Use `findAllComponents` instead'
)
}
const nodes = find(this.rootNode, this.vm, selector)
Expand Down Expand Up @@ -316,9 +319,7 @@ export default class Wrapper implements BaseWrapper {
* Checks if node matches selector
*/
is(rawSelector: Selector): boolean {
warn(
`is is deprecated and will be removed in a future release. Use element.tagName instead`
)
warnDeprecated('is', 'Use element.tagName instead')
const selector = getSelector(rawSelector, 'is')

if (selector.type === REF_SELECTOR) {
Expand All @@ -332,9 +333,9 @@ export default class Wrapper implements BaseWrapper {
* Checks if node is empty
*/
isEmpty(): boolean {
warn(
`isEmpty is deprecated and will be removed in a future release. ` +
`Consider a custom matcher such as those provided in jest-dom: https://github.com/testing-library/jest-dom#tobeempty`
warnDeprecated(
'isEmpty',
'Consider a custom matcher such as those provided in jest-dom: https://github.com/testing-library/jest-dom#tobeempty'
)
if (!this.vnode) {
return this.element.innerHTML === ''
Expand All @@ -360,8 +361,10 @@ export default class Wrapper implements BaseWrapper {
* Checks if node is visible
*/
isVisible(): boolean {
warn(`isEmpty is deprecated and will be removed in a future release.
Consider a custom matcher such as those provided in jest-dom: https://github.com/testing-library/jest-dom#tobevisible`)
warnDeprecated(
'isEmpty',
`Consider a custom matcher such as those provided in jest-dom: https://github.com/testing-library/jest-dom#tobevisible`
)
let element = this.element
while (element) {
if (
Expand All @@ -382,14 +385,16 @@ export default class Wrapper implements BaseWrapper {
* Checks if wrapper is a vue instance
*/
isVueInstance(): boolean {
warn(`isVueInstance is deprecated and will be removed in a future release`)
warnDeprecated(`isVueInstance`)
return !!this.vm
}

/**
* Returns name of component, or tag name if node is not a Vue component
*/
name(): string {
warnDeprecated(`name`)

if (this.vm) {
return (
this.vm.$options.name ||
Expand All @@ -410,6 +415,8 @@ export default class Wrapper implements BaseWrapper {
* with useful information for debugging
*/
overview(): void {
warnDeprecated(`overview`)

if (!this.isVueInstance()) {
throwError(`wrapper.overview() can only be called on a Vue instance`)
}
Expand Down Expand Up @@ -511,6 +518,11 @@ export default class Wrapper implements BaseWrapper {
* Checks radio button or checkbox element
*/
setChecked(checked: boolean = true): void {
warnDeprecated(
`setChecked`,
'When you migrate to VTU 2, use setValue instead.'
)

if (typeof checked !== 'boolean') {
throwError('wrapper.setChecked() must be passed a boolean')
}
Expand Down Expand Up @@ -558,6 +570,11 @@ export default class Wrapper implements BaseWrapper {
* Selects <option></option> element
*/
setSelected(): void {
warnDeprecated(
`setSelected`,
'When you migrate to VTU 2, use setValue instead.'
)

const tagName = this.element.tagName

if (tagName === 'SELECT') {
Expand Down Expand Up @@ -610,7 +627,8 @@ export default class Wrapper implements BaseWrapper {
* Sets vm methods
*/
setMethods(methods: Object): void {
warn(`setMethods is deprecated and will be removed in a future release`)
warnDeprecated(`setMethods`)

if (!this.isVueInstance()) {
throwError(`wrapper.setMethods() can only be called on a Vue instance`)
}
Expand Down
3 changes: 2 additions & 1 deletion packages/test-utils/types/index.d.ts
Expand Up @@ -150,7 +150,8 @@ interface VueTestUtilsConfigOptions {
mocks?: Record<string, any>
methods?: Record<string, Function>
provide?: Record<string, any>,
silent?: Boolean
silent?: Boolean,
showDeprecationWarnings?: boolean
}

export declare function createLocalVue (): typeof Vue
Expand Down
15 changes: 15 additions & 0 deletions test/specs/config.spec.js
Expand Up @@ -17,6 +17,7 @@ describeWithShallowAndMount('config', mountingMethod => {
afterEach(() => {
config.stubs = configStubsSave
config.silent = configSilentSave
config.methods = {}
sandbox.reset()
sandbox.restore()
})
Expand Down Expand Up @@ -99,4 +100,18 @@ describeWithShallowAndMount('config', mountingMethod => {
await wrapper.vm.$nextTick()
expect(wrapper.find('[data-testid="expanded"]').exists()).to.equal(false)
})

it('allows control deprecation warnings visibility', () => {
config.showDeprecationWarnings = true
const Component = {
name: 'Foo',
template: '<div>Foo</div>'
}
const wrapper = mountingMethod(Component)
wrapper.name()
expect(console.error).to.be.calledWith(sandbox.match('name is deprecated'))
config.showDeprecationWarnings = false
wrapper.name()
expect(console.error).to.have.callCount(1)
})
})
2 changes: 1 addition & 1 deletion test/specs/mounting-options/slots.spec.js
Expand Up @@ -343,7 +343,7 @@ describeWithShallowAndMount('options.slots', mountingMethod => {
.with.property('message', message)
})

it('throws error if passed a number for named slots', () => {
it('throws error if passed an array of numbers for named slots', () => {
const TestComponent = {
name: 'component-with-slots',
functional: true,
Expand Down
6 changes: 3 additions & 3 deletions test/specs/mounting-options/stubs.spec.js
Expand Up @@ -630,6 +630,7 @@ describeWithShallowAndMount('options.stub', mountingMethod => {
)

it('warns when passing a string', () => {
config.showDeprecationWarnings = true
const StringComponent = '<div></div>'
mountingMethod(ComponentWithChild, {
stubs: {
Expand All @@ -638,9 +639,8 @@ describeWithShallowAndMount('options.stub', mountingMethod => {
})

expect(console.error).calledWith(
sandbox.match(
'[vue-test-utils]: String stubs are deprecated and will be removed in future versions'
)
sandbox.match('[vue-test-utils]: Using a string for stubs is deprecated')
)
config.showDeprecationWarnings = false
})
})
29 changes: 17 additions & 12 deletions test/specs/wrapper/setMethods.spec.js
@@ -1,7 +1,8 @@
import { compileToFunctions } from 'vue-template-compiler'
import ComponentWithMethods from '~resources/components/component-with-methods.vue'
import ComponentWithEvents from '~resources/components/component-with-events.vue'
import { describeWithShallowAndMount } from '~resources/utils'
import { describeWithShallowAndMount, vueVersion } from '~resources/utils'
import { itDoNotRunIf } from 'conditional-specs'

describeWithShallowAndMount('setMethods', mountingMethod => {
it('sets component data and updates nested vm nodes when called on Vue instance', () => {
Expand All @@ -19,15 +20,19 @@ describeWithShallowAndMount('setMethods', mountingMethod => {
expect(() => p.setMethods({ ready: true })).throw(Error, message)
})

it('should replace methods when tied to an event', () => {
const wrapper = mountingMethod(ComponentWithEvents)
expect(wrapper.vm.isActive).to.be.false
wrapper.find('.toggle').trigger('click')
expect(wrapper.vm.isActive).to.be.true
// Replace the toggle function so that the data supposedly won't change
const toggleActive = () => {}
wrapper.setMethods({ toggleActive })
wrapper.find('.toggle').trigger('click')
expect(wrapper.vm.isActive).to.be.true
})
itDoNotRunIf(
vueVersion < 2.2,
'should replace methods when tied to an event',
() => {
const wrapper = mountingMethod(ComponentWithEvents)
expect(wrapper.vm.isActive).to.be.false
wrapper.find('.toggle').trigger('click')
expect(wrapper.vm.isActive).to.be.true
// Replace the toggle function so that the data supposedly won't change
const toggleActive = () => {}
wrapper.setMethods({ toggleActive })
wrapper.find('.toggle').trigger('click')
expect(wrapper.vm.isActive).to.be.true
}
)
})