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: support object class binding in stubbed functional components #1476

Merged
Merged
Show file tree
Hide file tree
Changes from 2 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
21 changes: 18 additions & 3 deletions packages/create-instance/create-component-stubs.js
Expand Up @@ -60,10 +60,25 @@ function getCoreProperties(componentOptions: Component): Object {
}

function createClassString(staticClass, dynamicClass) {
if (staticClass && dynamicClass) {
return staticClass + ' ' + dynamicClass
// :class="someComputedObject" can return a string, object or undefined
// if it is a string, we don't need to do anything special.
let evaluatedDynamicClass = dynamicClass

// if it is an object, eg { 'foo': true }, we need to evaluate it.
// see https://github.com/vuejs/vue-test-utils/issues/1474 for more context.
if (typeof dynamicClass === 'object') {
evaluatedDynamicClass = Object.keys(dynamicClass).reduce((acc, key) => {
if (dynamicClass[key] === true) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we check if this is a truthy value or like this, straight up true?

Copy link
Member Author

Choose a reason for hiding this comment

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

Not sure, I just went with this to be explicit. I haven't seen people use something like :class={ 'my-class': 'some-truthy-val' }. I guess we should just copy whatever Vue does - will try it out.

return acc + ' ' + key
}
return acc
}, '')
}

if (staticClass && evaluatedDynamicClass) {
return staticClass + ' ' + evaluatedDynamicClass
}
return staticClass || dynamicClass
return staticClass || evaluatedDynamicClass
Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldnt have pushing all to an array and using join(' ') at the end been a more cleaner way of doing this?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think both are fine - was having problems iterating over Object.keys, using of throws some warning. A few other places in the codebase do Object.keys().reduce so I just tried to follow that same style.

I like reduce but I don't mind either way.

}

function resolveOptions(component, _Vue) {
Expand Down
22 changes: 22 additions & 0 deletions test/resources/components/component-with-functional-child.vue
@@ -0,0 +1,22 @@
<template>
<functional-component
:class="{ bar: a + b === 2, foo: a === 1, qux: a === 2 }"
/>
</template>

<script>
import FunctionalComponent from './functional-component.vue'

export default {
components: {
FunctionalComponent
},

data() {
return {
a: 1,
b: 1
}
}
}
</script>
12 changes: 12 additions & 0 deletions test/specs/shallow-mount.spec.js
Expand Up @@ -3,6 +3,7 @@ import Vue from 'vue'
import { mount, shallowMount, createLocalVue } from '@vue/test-utils'
import Component from '~resources/components/component.vue'
import ComponentWithChild from '~resources/components/component-with-child.vue'
import ComponentWithFunctionalChild from '~resources/components/component-with-functional-child.vue'
import ComponentWithNestedChildren from '~resources/components/component-with-nested-children.vue'
import ComponentWithLifecycleHooks from '~resources/components/component-with-lifecycle-hooks.vue'
import ComponentWithoutName from '~resources/components/component-without-name.vue'
Expand All @@ -25,6 +26,17 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'shallowMount', () => {
sandbox.restore()
})

it('renders dynamic class of functional child', () => {
const wrapper = shallowMount(ComponentWithFunctionalChild)
expect(wrapper.find('functional-component-stub').classes()).to.contain(
'foo',
'bar'
)
expect(wrapper.find('functional-component-stub').classes()).not.to.contain(
'qux'
)
})

it('returns new VueWrapper of Vue localVue if no options are passed', () => {
const compiled = compileToFunctions('<div><input /></div>')
const wrapper = shallowMount(compiled)
Expand Down