@@ -17,6 +17,7 @@ import {
1717 getCheckedEvent ,
1818 isPhantomJS ,
1919 nextTick ,
20+ warn ,
2021 warnDeprecated
2122} from 'shared/util'
2223import { isElementVisible } from 'shared/is-visible'
@@ -82,14 +83,27 @@ export default class Wrapper implements BaseWrapper {
8283 }
8384 }
8485
86+ /**
87+ * Prints warning if component is destroyed
88+ */
89+ __warnIfDestroyed ( ) {
90+ if ( ! this . exists ( ) ) {
91+ warn ( 'Operations on destroyed component are discouraged' )
92+ }
93+ }
94+
8595 at ( ) : void {
96+ this. __warnIfDestroyed ( )
97+
8698 throwError ( 'at() must be called on a WrapperArray' )
8799 }
88100
89101 /**
90102 * Returns an Object containing all the attribute/value pairs on the element.
91103 */
92104 attributes ( key ? : string ) : { [ name : string ] : string } | string {
105+ this . __warnIfDestroyed ( )
106+
93107 const attributes = this . element . attributes
94108 const attributeMap = { }
95109 for ( let i = 0 ; i < attributes . length ; i ++ ) {
@@ -104,6 +118,8 @@ export default class Wrapper implements BaseWrapper {
104118 * Returns an Array containing all the classes on the element
105119 */
106120 classes ( className ? : string ) : Array < string > | boolean {
121+ this . __warnIfDestroyed ( )
122+
107123 const classAttribute = this . element . getAttribute ( 'class' )
108124 let classes = classAttribute ? classAttribute . split ( ' ' ) : [ ]
109125 // Handle converting cssmodules identifiers back to the original class name
@@ -134,6 +150,9 @@ export default class Wrapper implements BaseWrapper {
134150 'contains' ,
135151 'Use `wrapper.find`, `wrapper.findComponent` or `wrapper.get` instead'
136152 )
153+
154+ this . __warnIfDestroyed ( )
155+
137156 const selector = getSelector ( rawSelector , 'contains' )
138157 const nodes = find ( this . rootNode , this . vm , selector )
139158 return nodes . length > 0
@@ -209,6 +228,8 @@ export default class Wrapper implements BaseWrapper {
209228 * matches the provided selector.
210229 */
211230 get ( rawSelector : Selector ) : Wrapper {
231+ this . __warnIfDestroyed ( )
232+
212233 const found = this . find ( rawSelector )
213234 if ( found instanceof ErrorWrapper ) {
214235 throw new Error ( `Unable to find ${ rawSelector } within: ${ this . html ( ) } ` )
@@ -221,6 +242,8 @@ export default class Wrapper implements BaseWrapper {
221242 * matches the provided selector.
222243 */
223244 find ( rawSelector : Selector ) : Wrapper | ErrorWrapper {
245+ this . __warnIfDestroyed ( )
246+
224247 const selector = getSelector ( rawSelector , 'find' )
225248 if ( selector . type !== DOM_SELECTOR ) {
226249 warnDeprecated (
@@ -237,6 +260,8 @@ export default class Wrapper implements BaseWrapper {
237260 * matches the provided selector.
238261 */
239262 findComponent ( rawSelector : Selector ) : Wrapper | ErrorWrapper {
263+ this . __warnIfDestroyed ( )
264+
240265 const selector = getSelector ( rawSelector , 'findComponent' )
241266 if ( ! this . vm && ! this . isFunctionalComponent ) {
242267 throwError (
@@ -270,6 +295,8 @@ export default class Wrapper implements BaseWrapper {
270295 * the provided selector.
271296 */
272297 findAll ( rawSelector : Selector ) : WrapperArray {
298+ this . __warnIfDestroyed ( )
299+
273300 const selector = getSelector ( rawSelector , 'findAll' )
274301 if ( selector . type !== DOM_SELECTOR ) {
275302 warnDeprecated (
@@ -285,6 +312,8 @@ export default class Wrapper implements BaseWrapper {
285312 * the provided selector.
286313 */
287314 findAllComponents ( rawSelector : Selector ) : WrapperArray {
315+ this . __warnIfDestroyed ( )
316+
288317 const selector = getSelector ( rawSelector , 'findAll' )
289318 if ( ! this . vm ) {
290319 throwError (
@@ -318,13 +347,17 @@ export default class Wrapper implements BaseWrapper {
318347 * Returns HTML of element as a string
319348 */
320349 html ( ) : string {
350+ this . __warnIfDestroyed ( )
351+
321352 return pretty ( this . element . outerHTML )
322353 }
323354
324355 /**
325356 * Checks if node matches selector or component definition
326357 */
327358 is ( rawSelector : Selector ) : boolean {
359+ this . __warnIfDestroyed ( )
360+
328361 const selector = getSelector ( rawSelector , 'is' )
329362
330363 if ( selector . type === DOM_SELECTOR ) {
@@ -351,6 +384,8 @@ export default class Wrapper implements BaseWrapper {
351384 'Consider a custom matcher such as those provided in jest-dom: https://github.com/testing-library/jest-dom#tobeempty. ' +
352385 'When using with findComponent, access the DOM element with findComponent(Comp).element'
353386 )
387+ this . __warnIfDestroyed ( )
388+
354389 if ( ! this . vnode ) {
355390 return this . element . innerHTML === ''
356391 }
@@ -375,6 +410,8 @@ export default class Wrapper implements BaseWrapper {
375410 * Checks if node is visible
376411 */
377412 isVisible ( ) : boolean {
413+ this . __warnIfDestroyed ( )
414+
378415 return isElementVisible ( this . element )
379416 }
380417
@@ -384,6 +421,8 @@ export default class Wrapper implements BaseWrapper {
384421 */
385422 isVueInstance ( ) : boolean {
386423 warnDeprecated ( `isVueInstance` )
424+ this . __warnIfDestroyed ( )
425+
387426 return ! ! this . vm
388427 }
389428
@@ -393,6 +432,7 @@ export default class Wrapper implements BaseWrapper {
393432 */
394433 name ( ) : string {
395434 warnDeprecated ( `name` )
435+ this . __warnIfDestroyed ( )
396436
397437 if ( this . vm ) {
398438 return (
@@ -416,6 +456,7 @@ export default class Wrapper implements BaseWrapper {
416456 */
417457 overview ( ) : void {
418458 warnDeprecated ( `overview` )
459+ this . __warnIfDestroyed ( )
419460
420461 if ( ! this . vm ) {
421462 throwError ( `wrapper.overview() can only be called on a Vue instance` )
@@ -495,6 +536,7 @@ export default class Wrapper implements BaseWrapper {
495536 if ( ! this . vm ) {
496537 throwError ( 'wrapper.props() must be called on a Vue instance' )
497538 }
539+ this . __warnIfDestroyed ( )
498540
499541 const props = { }
500542 const keys = this . vm && this . vm . $options . _propKeys
@@ -519,6 +561,8 @@ export default class Wrapper implements BaseWrapper {
519561 * @deprecated
520562 */
521563 setChecked ( checked : boolean = true ) : Promise < * > {
564+ this . __warnIfDestroyed ( )
565+
522566 if ( typeof checked !== 'boolean' ) {
523567 throwError ( 'wrapper.setChecked() must be passed a boolean' )
524568 }
@@ -568,6 +612,8 @@ export default class Wrapper implements BaseWrapper {
568612 * @deprecated
569613 */
570614 setSelected ( ) : Promise < void > {
615+ this . __warnIfDestroyed ( )
616+
571617 const tagName = this . element . tagName
572618
573619 if ( tagName === 'SELECT' ) {
@@ -613,6 +659,8 @@ export default class Wrapper implements BaseWrapper {
613659 throwError ( `wrapper.setData() can only be called on a Vue instance` )
614660 }
615661
662+ this . __warnIfDestroyed ( )
663+
616664 recursivelySetData ( this . vm , this . vm , data )
617665 return nextTick ( )
618666 }
@@ -630,6 +678,8 @@ export default class Wrapper implements BaseWrapper {
630678 if ( ! this . vm ) {
631679 throwError ( `wrapper.setMethods() can only be called on a Vue instance` )
632680 }
681+ this . __warnIfDestroyed ( )
682+
633683 Object . keys ( methods ) . forEach ( key => {
634684 // $FlowIgnore : Problem with possibly null this.vm
635685 this . vm [ key ] = methods [ key ]
@@ -657,6 +707,7 @@ export default class Wrapper implements BaseWrapper {
657707 if ( ! this . vm ) {
658708 throwError ( `wrapper.setProps() can only be called on a Vue instance` )
659709 }
710+ this . __warnIfDestroyed ( )
660711
661712 // Save the original "silent" config so that we can directly mutate props
662713 const originalConfig = Vue . config . silent
@@ -730,6 +781,7 @@ export default class Wrapper implements BaseWrapper {
730781 const tagName = this . element . tagName
731782 // $FlowIgnore
732783 const type = this . attributes ( ) . type
784+ this . __warnIfDestroyed ( )
733785
734786 if ( tagName === 'OPTION' ) {
735787 throwError (
@@ -782,13 +834,17 @@ export default class Wrapper implements BaseWrapper {
782834 * Return text of wrapper element
783835 */
784836 text ( ) : string {
837+ this . __warnIfDestroyed ( )
838+
785839 return this . element . textContent . trim ( )
786840 }
787841
788842 /**
789843 * Dispatches a DOM event on wrapper
790844 */
791845 trigger ( type : string , options : Object = { } ) : Promise < void > {
846+ this . __warnIfDestroyed ( )
847+
792848 if ( typeof type !== 'string' ) {
793849 throwError ( 'wrapper.trigger() must be passed a string' )
794850 }
0 commit comments