Closed chrisbradleydev closed 1 year ago
I have the same issue after upgrading Webpack from 1 to 4.
// Before
<loader-bar-stub
is-loading="true"
/>
// After
<loader-bar-stub
isloading="true"
/>
I don't know which lib converted it. Maybe babel
or vue-test-utils
. I would really appreciate if anyone could hep identify the root cause.
I'm using babel 6 and vue-test-utils@1.0.0-beta.29
Hi @hectorguo! Just to cross off some stuff from the list, is it possible for you to update to latest version of vue-test-utils (v1.0.3) and check if the issue is still there?
Hi @afontcu, thanks for the quick response. I've found the root cause and got a working solution.
The reason is because of this line code: https://github.com/vuejs/vue-test-utils/blob/dev/packages/create-instance/create-component-stubs.js#L119
Previously, I'm using require(...)
to import child components in Vue.
After upgrading to webpack v4, vue-loader
deprecated the support for the commonJS. So it's changed to require(...).default
.
Before upgrading, the originalComponent
is something like { default: VueComponent }
. So all options (attrs
, props
, etc.) are returning undefined
.
After changing to require(...).default
, the output becomes VueComponent directly, all options can get the correct values.
However, this line code is passing Vue props to HTML attributes.
In Vue render, all HTML attributes will be converted to lowercase since they are case insensitive. So when creating stub components, if the props are camelCase, it will be converted to lowercase instead of kebab-case. It's why the snapshot is different.
export default {
name: 'LoadingBar',
props: ['isLoading']
}
// Before
<loading-bar is-loading="true" />
// After
<loading-bar isloading="true" />
Here is a sandbox link to proof that Vue render is lowercasing attrs
: https://codesandbox.io/s/vue-render-function-vnul1?file=/src/components/CustomList.vue
There are 2 solutions for it.
change line 119 to
// To make sure there is always a default wrapping the component
// It's working great when upgrading webpack from v1 to v4
const componentOptions = resolveOptions(originalComponent.default ? originalComponent : { default: originalComponent }, _Vue)
Hyphenate $props
render: function render(h, context) {
// it will make sure camelCase props will be converted to kebab-case
// e.g. `{ isLoading: true } ` to `{ 'is-loading': true }`
const hyphenatedProps = Object.keys(this.$props).reduce((acc, key) => {
const hyphenatedKey = hyphenate(key);
acc[hyphenatedKey] = this.$props[key];
return acc;
}, {})
return h(
tagName,
{
attrs: componentOptions.functional
? Object.assign({}, context.props,
context.data.attrs,
{class: createClassString(
context.data.staticClass,
context.data.class
)})
: hyphenatedProps
},
context ? context.children : this.$options._renderChildren
)
}})
I really hope that it can be fixed in current version instead of hacking by myself.
Struggling with this issue since while upgrading to the latest @vue/test-utils version (1.2.1). Stubs' attributes are created as merged lowercase strings, therefore, attributes such as "data-test" become "datatest" and then most selectors are breaking. Is there any temporary fix that can be done?
Version
1.0.0-beta.29
Reproduction link
https://github.com/ctbradley/vue-test-utils-demo
Steps to reproduce
npm i
npm run test
or run using wallaby...
the most relevant files are:
src/components/HelloWorld.vue
src/components/HelloWorld.test.ts
src/components/VForm.vue
comment out props in
VForm.vue
to demonstrate behaviorWhat is expected?
VFormImport attributes are expected as kebab-case.
What is actually happening?
VFormImport attributes are being stripped of their hyphens.
Note that this only affects components that are being imported as demonstrated in
src/components/HelloWorld.test.ts
.