Skip to content

Commit 7a0b7e0

Browse files
feat: Optionally hide deprecation errors (#1518)
* feat: add config to show deprecation warnings * test: fix failing deprecated test * test: skip tests in old version of vue Co-authored-by: Lachlan Miller <[email protected]>
1 parent c2de268 commit 7a0b7e0

File tree

16 files changed

+168
-64
lines changed

16 files changed

+168
-64
lines changed

Diff for: flow/config.flow.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ declare type Config = {
33
mocks?: Object,
44
methods?: { [name: string]: Function },
55
provide?: Object,
6-
silent?: boolean
6+
silent?: boolean,
7+
showDeprecationWarnings?: boolean
78
}

Diff for: package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,9 @@
9898
"cz-conventional-changelog": "^3.0.2",
9999
"husky": "^3.1.0",
100100
"lint-staged": "^9.5.0",
101-
"prettier": "^1.16.0"
101+
"prettier": "^1.16.0",
102+
"rollup-plugin-delete": "^1.2.0",
103+
"rollup-plugin-replace": "^2.2.0"
102104
},
103105
"config": {
104106
"commitizen": {

Diff for: packages/create-instance/create-component-stubs.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
capitalize,
88
hyphenate,
99
keys,
10-
warn
10+
warnDeprecated
1111
} from '../shared/util'
1212
import {
1313
componentNeedsCompiling,
@@ -159,7 +159,7 @@ export function createStubFromComponent(
159159

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

164164
if (templateContainsComponent(templateString, name)) {
165165
throwError('options.stub cannot contain a circular reference')

Diff for: packages/shared/merge-options.js

+3-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// @flow
22
import { normalizeStubs, normalizeProvide } from './normalize'
3-
import { warn } from 'shared/util'
3+
import { warnDeprecated } from 'shared/util'
44

55
function getOption(option, config?: Object): any {
66
if (option === false) {
@@ -34,11 +34,8 @@ export function mergeOptions(
3434
const methods = (getOption(options.methods, config.methods): {
3535
[key: string]: Function
3636
})
37-
38-
if (config.methods && Object.keys(config.methods).length) {
39-
warn(
40-
`config.methods has been deprecated. It will be removed in a future release`
41-
)
37+
if (methods && Object.keys(methods).length) {
38+
warnDeprecated('overwriting methods via the `methods` property')
4239
}
4340

4441
const provide = (getOption(options.provide, config.provide): Object)

Diff for: packages/shared/util.js

+8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// @flow
22
import Vue from 'vue'
33
import semver from 'semver'
4+
import { config } from '@vue/test-utils'
45

56
export function throwError(msg: string): void {
67
throw new Error(`[vue-test-utils]: ${msg}`)
@@ -85,3 +86,10 @@ export function getCheckedEvent() {
8586
// change is handler for version 2.0 - 2.1.8, and 2.5+
8687
return 'change'
8788
}
89+
90+
export function warnDeprecated(method: string, fallback: string = '') {
91+
if (!config.showDeprecationWarnings) return
92+
let msg = `${method} is deprecated and will removed in the next major version`
93+
if (fallback) msg += ` ${fallback}`
94+
warn(msg)
95+
}

Diff for: packages/test-utils/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
],
1111
"scripts": {
1212
"build": "node scripts/build.js",
13-
"build:test": "cross-env NODE_ENV=test node scripts/build.js"
13+
"build:test": "cross-env NODE_ENV=test SHOW_DEPRECATIONS=false node scripts/build.js"
1414
},
1515
"repository": {
1616
"type": "git",

Diff for: packages/test-utils/scripts/build.js

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ const nodeResolve = require('rollup-plugin-node-resolve')
66
const commonjs = require('rollup-plugin-commonjs')
77
const chalk = require('chalk')
88
const json = require('rollup-plugin-json')
9+
const replace = require('rollup-plugin-replace')
10+
const del = require('rollup-plugin-delete')
911

1012
function success(text) {
1113
console.log(chalk.green(`${text} ✔`))
@@ -57,6 +59,10 @@ rollupOptions.forEach(options => {
5759
input: resolve('src/index.js'),
5860
external: ['vue', 'vue-template-compiler'],
5961
plugins: [
62+
del({ targets: 'dist/*' }),
63+
replace({
64+
'process.env.SHOW_DEPRECATIONS': process.env.SHOW_DEPRECATIONS
65+
}),
6066
flow(),
6167
json(),
6268
buble({

Diff for: packages/test-utils/src/config.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,9 @@ export default {
66
mocks: {},
77
methods: {},
88
provide: {},
9-
silent: true
9+
silent: true,
10+
showDeprecationWarnings:
11+
typeof process.env.SHOW_DEPRECATIONS !== 'undefined'
12+
? process.env.SHOW_DEPRECATIONS
13+
: true
1014
}

Diff for: packages/test-utils/src/wrapper.js

+41-23
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@ import {
1212
import config from './config'
1313
import WrapperArray from './wrapper-array'
1414
import ErrorWrapper from './error-wrapper'
15-
import { throwError, getCheckedEvent, isPhantomJS, warn } from 'shared/util'
15+
import {
16+
throwError,
17+
getCheckedEvent,
18+
isPhantomJS,
19+
warnDeprecated
20+
} from 'shared/util'
1621
import find from './find'
1722
import createWrapper from './create-wrapper'
1823
import { recursivelySetData } from './recursively-set-data'
@@ -122,8 +127,9 @@ export default class Wrapper implements BaseWrapper {
122127
* Checks if wrapper contains provided selector.
123128
*/
124129
contains(rawSelector: Selector): boolean {
125-
warn(
126-
'contains is deprecated and will be removed in a future release. Use `wrapper.find`, `wrapper.findComponent` or `wrapper.get` instead'
130+
warnDeprecated(
131+
'contains',
132+
'Use `wrapper.find`, `wrapper.findComponent` or `wrapper.get` instead'
127133
)
128134
const selector = getSelector(rawSelector, 'contains')
129135
const nodes = find(this.rootNode, this.vm, selector)
@@ -171,9 +177,7 @@ export default class Wrapper implements BaseWrapper {
171177
* Returns an Array containing custom events emitted by the Wrapper vm
172178
*/
173179
emittedByOrder(): Array<{ name: string, args: Array<any> }> {
174-
warn(
175-
'emittedByOrder is deprecated and will be removed in a future release. Use `wrapper.emitted` instead'
176-
)
180+
warnDeprecated('emittedByOrder', 'Use `wrapper.emitted` instead')
177181
if (!this._emittedByOrder && !this.vm) {
178182
throwError(
179183
`wrapper.emittedByOrder() can only be called on a Vue instance`
@@ -201,9 +205,6 @@ export default class Wrapper implements BaseWrapper {
201205
* matches the provided selector.
202206
*/
203207
get(rawSelector: Selector): Wrapper {
204-
warn(
205-
'get is deprecated and will be removed in a future release. Use `find` or `findComponent` instead'
206-
)
207208
const found = this.find(rawSelector)
208209
if (found instanceof ErrorWrapper) {
209210
throw new Error(`Unable to find ${rawSelector} within: ${this.html()}`)
@@ -218,8 +219,9 @@ export default class Wrapper implements BaseWrapper {
218219
find(rawSelector: Selector): Wrapper | ErrorWrapper {
219220
const selector = getSelector(rawSelector, 'find')
220221
if (selector.type !== DOM_SELECTOR) {
221-
warn(
222-
'finding components with `find` is deprecated and will be removed in a future release. Use `findComponent` instead'
222+
warnDeprecated(
223+
'finding components with `find`',
224+
'Use `findComponent` instead'
223225
)
224226
}
225227
const node = find(this.rootNode, this.vm, selector)[0]
@@ -240,8 +242,9 @@ export default class Wrapper implements BaseWrapper {
240242
findAll(rawSelector: Selector): WrapperArray {
241243
const selector = getSelector(rawSelector, 'findAll')
242244
if (selector.type !== DOM_SELECTOR) {
243-
warn(
244-
'finding components with `findAll` is deprecated and will be removed in a future release. Use `findAllComponents` instead'
245+
warnDeprecated(
246+
'finding components with `findAll`',
247+
'Use `findAllComponents` instead'
245248
)
246249
}
247250
const nodes = find(this.rootNode, this.vm, selector)
@@ -316,9 +319,7 @@ export default class Wrapper implements BaseWrapper {
316319
* Checks if node matches selector
317320
*/
318321
is(rawSelector: Selector): boolean {
319-
warn(
320-
`is is deprecated and will be removed in a future release. Use element.tagName instead`
321-
)
322+
warnDeprecated('is', 'Use element.tagName instead')
322323
const selector = getSelector(rawSelector, 'is')
323324

324325
if (selector.type === REF_SELECTOR) {
@@ -332,9 +333,9 @@ export default class Wrapper implements BaseWrapper {
332333
* Checks if node is empty
333334
*/
334335
isEmpty(): boolean {
335-
warn(
336-
`isEmpty is deprecated and will be removed in a future release. ` +
337-
`Consider a custom matcher such as those provided in jest-dom: https://github.com/testing-library/jest-dom#tobeempty`
336+
warnDeprecated(
337+
'isEmpty',
338+
'Consider a custom matcher such as those provided in jest-dom: https://github.com/testing-library/jest-dom#tobeempty'
338339
)
339340
if (!this.vnode) {
340341
return this.element.innerHTML === ''
@@ -360,8 +361,10 @@ export default class Wrapper implements BaseWrapper {
360361
* Checks if node is visible
361362
*/
362363
isVisible(): boolean {
363-
warn(`isEmpty is deprecated and will be removed in a future release.
364-
Consider a custom matcher such as those provided in jest-dom: https://github.com/testing-library/jest-dom#tobevisible`)
364+
warnDeprecated(
365+
'isEmpty',
366+
`Consider a custom matcher such as those provided in jest-dom: https://github.com/testing-library/jest-dom#tobevisible`
367+
)
365368
let element = this.element
366369
while (element) {
367370
if (
@@ -382,14 +385,16 @@ export default class Wrapper implements BaseWrapper {
382385
* Checks if wrapper is a vue instance
383386
*/
384387
isVueInstance(): boolean {
385-
warn(`isVueInstance is deprecated and will be removed in a future release`)
388+
warnDeprecated(`isVueInstance`)
386389
return !!this.vm
387390
}
388391

389392
/**
390393
* Returns name of component, or tag name if node is not a Vue component
391394
*/
392395
name(): string {
396+
warnDeprecated(`name`)
397+
393398
if (this.vm) {
394399
return (
395400
this.vm.$options.name ||
@@ -410,6 +415,8 @@ export default class Wrapper implements BaseWrapper {
410415
* with useful information for debugging
411416
*/
412417
overview(): void {
418+
warnDeprecated(`overview`)
419+
413420
if (!this.isVueInstance()) {
414421
throwError(`wrapper.overview() can only be called on a Vue instance`)
415422
}
@@ -511,6 +518,11 @@ export default class Wrapper implements BaseWrapper {
511518
* Checks radio button or checkbox element
512519
*/
513520
setChecked(checked: boolean = true): void {
521+
warnDeprecated(
522+
`setChecked`,
523+
'When you migrate to VTU 2, use setValue instead.'
524+
)
525+
514526
if (typeof checked !== 'boolean') {
515527
throwError('wrapper.setChecked() must be passed a boolean')
516528
}
@@ -558,6 +570,11 @@ export default class Wrapper implements BaseWrapper {
558570
* Selects <option></option> element
559571
*/
560572
setSelected(): void {
573+
warnDeprecated(
574+
`setSelected`,
575+
'When you migrate to VTU 2, use setValue instead.'
576+
)
577+
561578
const tagName = this.element.tagName
562579

563580
if (tagName === 'SELECT') {
@@ -610,7 +627,8 @@ export default class Wrapper implements BaseWrapper {
610627
* Sets vm methods
611628
*/
612629
setMethods(methods: Object): void {
613-
warn(`setMethods is deprecated and will be removed in a future release`)
630+
warnDeprecated(`setMethods`)
631+
614632
if (!this.isVueInstance()) {
615633
throwError(`wrapper.setMethods() can only be called on a Vue instance`)
616634
}

Diff for: packages/test-utils/types/index.d.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ interface VueTestUtilsConfigOptions {
150150
mocks?: Record<string, any>
151151
methods?: Record<string, Function>
152152
provide?: Record<string, any>,
153-
silent?: Boolean
153+
silent?: Boolean,
154+
showDeprecationWarnings?: boolean
154155
}
155156

156157
export declare function createLocalVue (): typeof Vue

Diff for: test/specs/config.spec.js

+15
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ describeWithShallowAndMount('config', mountingMethod => {
1717
afterEach(() => {
1818
config.stubs = configStubsSave
1919
config.silent = configSilentSave
20+
config.methods = {}
2021
sandbox.reset()
2122
sandbox.restore()
2223
})
@@ -99,4 +100,18 @@ describeWithShallowAndMount('config', mountingMethod => {
99100
await wrapper.vm.$nextTick()
100101
expect(wrapper.find('[data-testid="expanded"]').exists()).to.equal(false)
101102
})
103+
104+
it('allows control deprecation warnings visibility', () => {
105+
config.showDeprecationWarnings = true
106+
const Component = {
107+
name: 'Foo',
108+
template: '<div>Foo</div>'
109+
}
110+
const wrapper = mountingMethod(Component)
111+
wrapper.name()
112+
expect(console.error).to.be.calledWith(sandbox.match('name is deprecated'))
113+
config.showDeprecationWarnings = false
114+
wrapper.name()
115+
expect(console.error).to.have.callCount(1)
116+
})
102117
})

Diff for: test/specs/mounting-options/slots.spec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ describeWithShallowAndMount('options.slots', mountingMethod => {
343343
.with.property('message', message)
344344
})
345345

346-
it('throws error if passed a number for named slots', () => {
346+
it('throws error if passed an array of numbers for named slots', () => {
347347
const TestComponent = {
348348
name: 'component-with-slots',
349349
functional: true,

Diff for: test/specs/mounting-options/stubs.spec.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,7 @@ describeWithShallowAndMount('options.stub', mountingMethod => {
630630
)
631631

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

640641
expect(console.error).calledWith(
641-
sandbox.match(
642-
'[vue-test-utils]: String stubs are deprecated and will be removed in future versions'
643-
)
642+
sandbox.match('[vue-test-utils]: Using a string for stubs is deprecated')
644643
)
644+
config.showDeprecationWarnings = false
645645
})
646646
})

Diff for: test/specs/wrapper/setMethods.spec.js

+17-12
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { compileToFunctions } from 'vue-template-compiler'
22
import ComponentWithMethods from '~resources/components/component-with-methods.vue'
33
import ComponentWithEvents from '~resources/components/component-with-events.vue'
4-
import { describeWithShallowAndMount } from '~resources/utils'
4+
import { describeWithShallowAndMount, vueVersion } from '~resources/utils'
5+
import { itDoNotRunIf } from 'conditional-specs'
56

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

22-
it('should replace methods when tied to an event', () => {
23-
const wrapper = mountingMethod(ComponentWithEvents)
24-
expect(wrapper.vm.isActive).to.be.false
25-
wrapper.find('.toggle').trigger('click')
26-
expect(wrapper.vm.isActive).to.be.true
27-
// Replace the toggle function so that the data supposedly won't change
28-
const toggleActive = () => {}
29-
wrapper.setMethods({ toggleActive })
30-
wrapper.find('.toggle').trigger('click')
31-
expect(wrapper.vm.isActive).to.be.true
32-
})
23+
itDoNotRunIf(
24+
vueVersion < 2.2,
25+
'should replace methods when tied to an event',
26+
() => {
27+
const wrapper = mountingMethod(ComponentWithEvents)
28+
expect(wrapper.vm.isActive).to.be.false
29+
wrapper.find('.toggle').trigger('click')
30+
expect(wrapper.vm.isActive).to.be.true
31+
// Replace the toggle function so that the data supposedly won't change
32+
const toggleActive = () => {}
33+
wrapper.setMethods({ toggleActive })
34+
wrapper.find('.toggle').trigger('click')
35+
expect(wrapper.vm.isActive).to.be.true
36+
}
37+
)
3338
})

0 commit comments

Comments
 (0)