1
1
// @flow
2
2
3
3
import Vue from 'vue'
4
- import { isValidSelector } from '../lib/validators '
4
+ import getSelectorTypeOrThrow , { selectorTypes } from '../lib/get-selector-type '
5
5
import findVueComponents , { vmCtorMatchesName } from '../lib/find-vue-components'
6
- import findMatchingVNodes from '../lib/find-matching-vnodes'
6
+ import findVNodesBySelector from '../lib/find-vnodes-by-selector'
7
+ import findVNodesByRef from '../lib/find-vnodes-by-ref'
7
8
import VueWrapper from './vue-wrapper'
8
9
import WrapperArray from './wrapper-array'
9
10
import ErrorWrapper from './error-wrapper'
@@ -36,16 +37,22 @@ export default class Wrapper implements BaseWrapper {
36
37
* Checks if wrapper contains provided selector.
37
38
*/
38
39
contains ( selector : Selector ) {
39
- if ( ! isValidSelector ( selector ) ) {
40
- throwError ( 'wrapper.contains() must be passed a valid CSS selector or a Vue constructor' )
41
- }
40
+ const selectorType = getSelectorTypeOrThrow ( selector , 'contains' )
42
41
43
- if ( typeof selector === 'object' ) {
42
+ if ( selectorType === selectorTypes . VUE_COMPONENT ) {
44
43
const vm = this . vm || this . vnode . context . $root
45
44
return findVueComponents ( vm , selector . name ) . length > 0
46
45
}
47
46
48
- if ( typeof selector === 'string' && this . element instanceof HTMLElement ) {
47
+ if ( selectorType === selectorTypes . OPTIONS_OBJECT ) {
48
+ if ( ! this . isVueComponent ) {
49
+ throwError ( '$ref selectors can only be used on Vue component wrappers' )
50
+ }
51
+ const nodes = findVNodesByRef ( this . vnode , selector . ref )
52
+ return nodes . length > 0
53
+ }
54
+
55
+ if ( selectorType === selectorTypes . DOM_SELECTOR && this . element instanceof HTMLElement ) {
49
56
return this . element . querySelectorAll ( selector ) . length > 0
50
57
}
51
58
@@ -174,12 +181,10 @@ export default class Wrapper implements BaseWrapper {
174
181
/**
175
182
* Finds first node in tree of the current wrapper that matches the provided selector.
176
183
*/
177
- find ( selector : string ) : Wrapper | ErrorWrapper | VueWrapper {
178
- if ( ! isValidSelector ( selector ) ) {
179
- throwError ( 'wrapper.find() must be passed a valid CSS selector or a Vue constructor' )
180
- }
184
+ find ( selector : Selector ) : Wrapper | ErrorWrapper | VueWrapper {
185
+ const selectorType = getSelectorTypeOrThrow ( selector , 'find' )
181
186
182
- if ( typeof selector === 'object' ) {
187
+ if ( selectorType === selectorTypes . VUE_COMPONENT ) {
183
188
if ( ! selector . name ) {
184
189
throwError ( '.find() requires component to have a name property' )
185
190
}
@@ -191,7 +196,18 @@ export default class Wrapper implements BaseWrapper {
191
196
return new VueWrapper ( components [ 0 ] , this . options )
192
197
}
193
198
194
- const nodes = findMatchingVNodes ( this . vnode , selector )
199
+ if ( selectorType === selectorTypes . OPTIONS_OBJECT ) {
200
+ if ( ! this . isVueComponent ) {
201
+ throwError ( '$ref selectors can only be used on Vue component wrappers' )
202
+ }
203
+ const nodes = findVNodesByRef ( this . vnode , selector . ref )
204
+ if ( nodes . length === 0 ) {
205
+ return new ErrorWrapper ( `ref="${ selector . ref } "` )
206
+ }
207
+ return new Wrapper ( nodes [ 0 ] , this . update , this . options )
208
+ }
209
+
210
+ const nodes = findVNodesBySelector ( this . vnode , selector )
195
211
196
212
if ( nodes . length === 0 ) {
197
213
return new ErrorWrapper ( selector )
@@ -203,11 +219,9 @@ export default class Wrapper implements BaseWrapper {
203
219
* Finds node in tree of the current wrapper that matches the provided selector.
204
220
*/
205
221
findAll ( selector : Selector ) : WrapperArray {
206
- if ( ! isValidSelector ( selector ) ) {
207
- throwError ( 'wrapper.findAll() must be passed a valid CSS selector or a Vue constructor' )
208
- }
222
+ const selectorType = getSelectorTypeOrThrow ( selector , 'findAll' )
209
223
210
- if ( typeof selector === 'object' ) {
224
+ if ( selectorType === selectorTypes . VUE_COMPONENT ) {
211
225
if ( ! selector . name ) {
212
226
throwError ( '.findAll() requires component to have a name property' )
213
227
}
@@ -216,11 +230,19 @@ export default class Wrapper implements BaseWrapper {
216
230
return new WrapperArray ( components . map ( component => new VueWrapper ( component , this . options ) ) )
217
231
}
218
232
233
+ if ( selectorType === selectorTypes . OPTIONS_OBJECT ) {
234
+ if ( ! this . isVueComponent ) {
235
+ throwError ( '$ref selectors can only be used on Vue component wrappers' )
236
+ }
237
+ const nodes = findVNodesByRef ( this . vnode , selector . ref )
238
+ return new WrapperArray ( nodes . map ( node => new Wrapper ( node , this . update , this . options ) ) )
239
+ }
240
+
219
241
function nodeMatchesSelector ( node , selector ) {
220
242
return node . elm && node . elm . getAttribute && node . elm . matches ( selector )
221
243
}
222
244
223
- const nodes = findMatchingVNodes ( this . vnode , selector )
245
+ const nodes = findVNodesBySelector ( this . vnode , selector )
224
246
const matchingNodes = nodes . filter ( node => nodeMatchesSelector ( node , selector ) )
225
247
226
248
return new WrapperArray ( matchingNodes . map ( node => new Wrapper ( node , this . update , this . options ) ) )
@@ -237,20 +259,23 @@ export default class Wrapper implements BaseWrapper {
237
259
* Checks if node matches selector
238
260
*/
239
261
is ( selector : Selector ) : boolean {
240
- if ( ! isValidSelector ( selector ) ) {
241
- throwError ( 'wrapper.is() must be passed a valid CSS selector or a Vue constructor' )
242
- }
262
+ const selectorType = getSelectorTypeOrThrow ( selector , 'is' )
243
263
244
- if ( typeof selector === 'object' ) {
245
- if ( ! this . isVueComponent ) {
246
- return false
247
- }
264
+ if ( selectorType === selectorTypes . VUE_COMPONENT && this . isVueComponent ) {
248
265
if ( typeof selector . name !== 'string' ) {
249
266
throwError ( 'a Component used as a selector must have a name property' )
250
267
}
251
268
return vmCtorMatchesName ( this . vm , selector . name )
252
269
}
253
270
271
+ if ( selectorType === selectorTypes . OPTIONS_OBJECT ) {
272
+ throwError ( '$ref selectors can not be used with wrapper.is()' )
273
+ }
274
+
275
+ if ( typeof selector === 'object' ) {
276
+ return false
277
+ }
278
+
254
279
return ! ! ( this . element &&
255
280
this . element . getAttribute &&
256
281
this . element . matches ( selector ) )
0 commit comments