Skip to content

Commit 476fe80

Browse files
committed
feat(visible): Add visible() method on Wrapper (vuejs#327)
1 parent fce6e6e commit 476fe80

File tree

8 files changed

+154
-1
lines changed

8 files changed

+154
-1
lines changed

Diff for: flow/wrapper.flow.js

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ declare interface BaseWrapper { // eslint-disable-line no-undef
1313
emitted(event?: string): { [name: string]: Array<Array<any>> } | Array<Array<any>> | void,
1414
emittedByOrder(): Array<{ name: string; args: Array<any> }> | void,
1515
exists(): boolean,
16+
visible(): boolean,
1617
hasAttribute(attribute: string, value: string): boolean | void,
1718
hasClass(className: string): boolean | void,
1819
hasProp(prop: string, value: string): boolean | void,

Diff for: package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
],
1111
"scripts": {
1212
"build": "node build/build.js",
13-
"build:test": "NODE_ENV=test node build/build.js",
13+
"build:test": "cross-env NODE_ENV=test node build/build.js",
1414
"coverage": "cross-env NODE_ENV=coverage nyc --reporter=lcov --reporter=text npm run test:unit",
1515
"docs": "cd docs && gitbook install && gitbook serve",
1616
"docs:deploy": "build/update-docs.sh",

Diff for: src/wrappers/error-wrapper.js

+4
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ export default class ErrorWrapper implements BaseWrapper {
3636
return false
3737
}
3838

39+
visible (): boolean {
40+
return false
41+
}
42+
3943
hasAttribute (): void {
4044
throwError(`find did not return ${this.selector}, cannot call hasAttribute() on empty Wrapper`)
4145
}

Diff for: src/wrappers/wrapper-array.js

+4
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ export default class WrapperArray implements BaseWrapper {
4242
return this.length > 0 && this.wrappers.every(wrapper => wrapper.exists())
4343
}
4444

45+
visible (): boolean {
46+
return this.length > 0 && this.wrappers.every(wrapper => wrapper.visible())
47+
}
48+
4549
emitted (): void {
4650
this.throwErrorIfWrappersIsEmpty('emitted')
4751

Diff for: src/wrappers/wrapper.js

+24
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,30 @@ export default class Wrapper implements BaseWrapper {
120120
return true
121121
}
122122

123+
/**
124+
* Utility to check wrapper is visible. Returns false if a parent element has display: none or visibility: hidden style.
125+
*/
126+
visible (): boolean {
127+
if (!this.exists()) {
128+
console.log('NOT EXISTS')
129+
return false
130+
}
131+
132+
let element: Element = this.element
133+
while (element) {
134+
if (element.style && (element.style.visibility === 'hidden' || element.style.display === 'none')) {
135+
return false
136+
}
137+
if (!element.parentElement) {
138+
break
139+
}
140+
element = element.parentElement
141+
}
142+
console.log('no parent')
143+
console.log(element)
144+
return true
145+
}
146+
123147
/**
124148
* Checks if wrapper has an attribute with matching value
125149
*/

Diff for: test/resources/components/component-with-v-show.vue

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<template>
2+
<div v-show="rootReady">
3+
<div v-show="!ready" class="not-ready">not-ready</div>
4+
5+
<div v-show="ready" class="parent ready">
6+
<div class="child ready">ready</div>
7+
</div>
8+
</div>
9+
</template>
10+
11+
<script>
12+
export default {
13+
name: 'component-with-show',
14+
data: () => ({
15+
ready: false,
16+
rootReady: true
17+
})
18+
}
19+
</script>

Diff for: test/unit/specs/mount/Wrapper/visible.spec.js

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { compileToFunctions } from 'vue-template-compiler'
2+
import { mount } from '~vue-test-utils'
3+
import ComponentWithVShow from '~resources/components/component-with-v-show.vue'
4+
5+
describe('visible', () => {
6+
it('returns true if element has no inline style', () => {
7+
const compiled = compileToFunctions('<div><div><span class="visible"></span></div></div>')
8+
const wrapper = mount(compiled)
9+
const element = wrapper.find('.visible')
10+
expect(element.visible()).to.equal(true)
11+
})
12+
13+
it('returns false if element has inline style display: none', () => {
14+
const compiled = compileToFunctions('<div><div><span style="display: none;" class="visible"></span></div></div>')
15+
const wrapper = mount(compiled)
16+
const element = wrapper.find('.visible')
17+
expect(element.visible()).to.equal(false)
18+
})
19+
20+
it('returns false if element has inline style visibility: hidden', () => {
21+
const compiled = compileToFunctions('<div><div><span style="visibility: hidden;" class="visible"></span></div></div>')
22+
const wrapper = mount(compiled)
23+
const element = wrapper.find('.visible')
24+
expect(element.visible()).to.equal(false)
25+
})
26+
27+
it('returns true if element has v-show true', () => {
28+
const wrapper = mount(ComponentWithVShow)
29+
wrapper.vm.$set(wrapper.vm, 'ready', true)
30+
wrapper.update()
31+
32+
const notReadyElement = wrapper.find('.not-ready')
33+
expect(notReadyElement.visible()).to.equal(false)
34+
35+
const readyElement = wrapper.find('.parent.ready')
36+
expect(readyElement.visible()).to.equal(true)
37+
})
38+
39+
it('returns false if element has v-show true', () => {
40+
const wrapper = mount(ComponentWithVShow)
41+
wrapper.vm.$set(wrapper.vm, 'ready', true)
42+
wrapper.update()
43+
44+
const notReadyElement = wrapper.find('.not-ready')
45+
expect(notReadyElement.visible()).to.equal(false)
46+
47+
const readyElement = wrapper.find('.parent.ready')
48+
expect(readyElement.visible()).to.equal(true)
49+
})
50+
51+
it('returns true if parent element has v-show true', () => {
52+
const wrapper = mount(ComponentWithVShow)
53+
wrapper.vm.$set(wrapper.vm, 'ready', true)
54+
wrapper.update()
55+
56+
const notReadyElement = wrapper.find('.not-ready')
57+
expect(notReadyElement.visible()).to.equal(false)
58+
59+
const readyChildElement = wrapper.find('.child.ready')
60+
expect(readyChildElement.visible()).to.equal(true)
61+
})
62+
63+
it('returns false if parent element has v-show false', () => {
64+
const wrapper = mount(ComponentWithVShow)
65+
wrapper.vm.$set(wrapper.vm, 'ready', true)
66+
wrapper.update()
67+
68+
const notReadyElement = wrapper.find('.not-ready')
69+
expect(notReadyElement.visible()).to.equal(false)
70+
71+
const readyChildElement = wrapper.find('.child.ready')
72+
expect(readyChildElement.visible()).to.equal(true)
73+
})
74+
75+
it('returns false if root element has v-show false and parent has v-show true', () => {
76+
const wrapper = mount(ComponentWithVShow)
77+
wrapper.vm.$set(wrapper.vm, 'ready', true)
78+
wrapper.vm.$set(wrapper.vm, 'rootReady', false)
79+
wrapper.update()
80+
81+
const notReadyElement = wrapper.find('.not-ready')
82+
expect(notReadyElement.visible()).to.equal(false)
83+
84+
const readyChildElement = wrapper.find('.child.ready')
85+
expect(readyChildElement.visible()).to.equal(false)
86+
})
87+
88+
it('returns false if root element has v-show true and parent has v-show false', () => {
89+
const wrapper = mount(ComponentWithVShow)
90+
wrapper.vm.$set(wrapper.vm, 'ready', false)
91+
wrapper.vm.$set(wrapper.vm, 'rootReady', true)
92+
wrapper.update()
93+
94+
const notReadyElement = wrapper.find('.not-ready')
95+
expect(notReadyElement.visible()).to.equal(true)
96+
97+
const readyChildElement = wrapper.find('.child.ready')
98+
expect(readyChildElement.visible()).to.equal(false)
99+
})
100+
})

Diff for: types/index.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ type RefSelector = {
4545
interface BaseWrapper {
4646
contains (selector: Selector): boolean
4747
exists (): boolean
48+
visible (): boolean
4849

4950
attributes(): { [name: string]: string } | void
5051
classes(): Array<string> | void

0 commit comments

Comments
 (0)