vuejs / test-utils

Vue Test Utils for Vue 3
https://test-utils.vuejs.org
MIT License
1.02k stars 242 forks source link

Config for transition stub ignored #471

Closed tweichart closed 3 years ago

tweichart commented 3 years ago

Subject of the issue

I'm currently in the process of upgrading a library from Vue2 -> Vue3. One of the tests is checking components with transitions. In Vue2, transitions could be removed via config.stubs.transition = false which does not seem to work anymore in Vue3 via config.global.stubs.transition = false.

Steps to reproduce

Clean projects created via cue-cli & default configs for vue2 & 3 (with minor package additions, see package.json files)

Vue2 example (success):

import { mount, config } from '@vue/test-utils'

config.stubs.transition = false

test('empty transition', () => {
  const t = {
    render(h) {
      return h('transition',)
    }
  }
  const wrapper = mount(t)
  expect(wrapper.html()).toBe(''); // html is ''
})
Vue2 package.json ```json { "name": "vue2", "version": "0.1.0", "private": true, "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "test:unit": "vue-cli-service test:unit", "lint": "vue-cli-service lint" }, "dependencies": { "core-js": "^3.6.5", "vue": "^2.6.11" }, "devDependencies": { "@vue/cli-plugin-babel": "~4.5.0", "@vue/cli-plugin-eslint": "~4.5.0", "@vue/cli-plugin-unit-jest": "~4.5.0", "@vue/cli-service": "~4.5.0", "@vue/test-utils": "^1.1.3", "babel-eslint": "^10.1.0", "eslint": "^6.7.2", "eslint-plugin-vue": "^6.2.2", "vue-template-compiler": "^2.6.11" }, "eslintConfig": { "root": true, "env": { "node": true }, "extends": [ "plugin:vue/essential", "eslint:recommended" ], "parserOptions": { "parser": "babel-eslint" }, "rules": {}, "overrides": [ { "files": [ "**/__tests__/*.{j,t}s?(x)", "**/tests/unit/**/*.spec.{j,t}s?(x)" ], "env": { "jest": true } } ] }, "browserslist": [ "> 1%", "last 2 versions", "not dead" ] } ```

Vue3 example (failure):

import { h } from 'vue'
import { mount, config } from '@vue/test-utils'

config.global.stubs.transition = false

test('displays message', () => {
  const t = {
    render() {
      return h('transition',)
    }
  }
  const wrapper = mount(t)
  expect(wrapper.html()).toBe(''); // html is '<transition></transition>'
})
Vue3 package.json ```json { "name": "vue3", "version": "0.1.0", "private": true, "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "test:unit": "vue-cli-service test:unit", "lint": "vue-cli-service lint" }, "dependencies": { "core-js": "^3.6.5", "vue": "^3.0.0" }, "devDependencies": { "@vue/cli-plugin-babel": "~4.5.0", "@vue/cli-plugin-eslint": "~4.5.0", "@vue/cli-plugin-unit-jest": "~4.5.0", "@vue/cli-service": "~4.5.0", "@vue/compiler-sfc": "^3.0.0", "@vue/test-utils": "^2.0.0-rc.4", "babel-eslint": "^10.1.0", "eslint": "^6.7.2", "eslint-plugin-vue": "^7.0.0", "typescript": "~3.9.3", "vue-jest": "^5.0.0-0", "vue-loader-v16": "^16.0.0-beta.5.4" }, "eslintConfig": { "root": true, "env": { "node": true }, "extends": [ "plugin:vue/vue3-essential", "eslint:recommended" ], "parserOptions": { "parser": "babel-eslint" }, "rules": {}, "overrides": [ { "files": [ "**/__tests__/*.{j,t}s?(x)", "**/tests/unit/**/*.spec.{j,t}s?(x)" ], "env": { "jest": true } } ] }, "browserslist": [ "> 1%", "last 2 versions", "not dead" ] } ```

Expected behaviour

Both cases should return success, Vue3 should also "replace" the transition.

Actual behaviour

Vue3 example fails as it returns <transition></transition>

lmiller1990 commented 3 years ago

Hi! This might be a bug. Can you try:

import { Transition } from 'vue'

const t = {
  render() {
    return h(Transition)
  }
}

I am not sure if h('transition') is valid - I am assuming it is, I have never tried writing a render function like that, though. Does h('transition') that work when rendered in the browser?

If it does, it sounds like we might need some extra logic to support built in components (<Transition>, <KeepAlive>) in this same fashion.

tweichart commented 3 years ago

thanks @lmiller1990 , using Transition works as expected 👍 Normally I'd just use Transition here, but as it's been working with transition in Vue2 I assumed it should work the same way now in Vue3.

cexbrayat commented 3 years ago

Closing this issue as it looks like it's resolved.

tweichart commented 3 years ago

@cexbrayat no, it's not resolved. The old vue-test-utils version returned the same result for transition as a string as well as for the imported Transition component provided by vue itself. Now the new vue-test-utils version can only use the imported component, transition doesn't work. So it's either a bug or an undocumented breaking change imo.

Edit: just as an example, bootstrap-vue uses this transition element in the BVTransition component (https://github.com/bootstrap-vue/bootstrap-vue/blob/dev/src/components/transition/bv-transition.js#L74) which then in turn is e.g. used in the alert box (https://github.com/bootstrap-vue/bootstrap-vue/blob/dev/src/components/alert/alert.js#L183)

cexbrayat commented 3 years ago

@tweichart Thaks for the feedback. My question is similar to what @lmiller1990 was asking: does it work in the browser if doing so in Vue 3? I haven't tried myself, but maybe this is a behavior change in Vue itself (I don't see what VTU would have to do here?).

tweichart commented 3 years ago

@cexbrayat sure, I just tried this as an example (Vue v3.07):

./App.vue ```javascript ```

where the component files look like this:

./components/Transitioncomp.js ```javascript import { defineComponent, h, Transition } from 'vue' export const Transitioncomp = defineComponent({ name: 'Transitioncomp', render() { return h( 'transition', {}, this.$slots.default() ) } }) ```
./components/Transitioncompvue.js ```javascript import { defineComponent, h, Transition } from 'vue' export const Transitioncompvue = defineComponent({ name: 'Transitioncompvue', render() { return h( Transition, {}, this.$slots.default() ) } }) ```

The result in the browser then is this:

<div id="app" data-v-app="">
    <transition><div>test</div></transition>
    <div>testvue</div>
    <p>hello</p>
</div>

So, using Transition imported from Vue is fine (renders the same as if I'd use <transition>), transition as default DOM element isn't though. Therefore, is this a problem then in Vue3 rather than a problem with the vue-test-utils? Basically due to the fact that Vue3 doesn't use the transition element the way it did before, the initially described config.global.stubs.transition doesn't work anymore?

Edit: https://codesandbox.io/s/vue3-transition-render-inkuj & issue created in vue-next

cexbrayat commented 3 years ago

Based on https://github.com/vuejs/vue-next/issues/826#issuecomment-598207464 this is a behavior change in Vue 3, hence not an issue in VTU. Thanks for the investigation @tweichart !