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

Failed to mount when returning render function from setup() #1484

Closed
LeBenLeBen opened this issue Mar 22, 2020 · 9 comments · Fixed by vuejs/composition-api#383 or #1583
Closed

Failed to mount when returning render function from setup() #1484

LeBenLeBen opened this issue Mar 22, 2020 · 9 comments · Fixed by vuejs/composition-api#383 or #1583

Comments

@LeBenLeBen
Copy link
Contributor

Version

1.0.0-beta.32

Reproduction link

https://github.com/sduduzog/vue-composition-api-tsx-example

Steps to reproduce

  1. Clone the repo
  2. Update the package.json to have the latest @vue/test-utils version, current is 1.0.0-beta.32
  3. Install dependencies
  4. Run npm run test:unit

What is expected?

The component "HelloWorld" should be properly mounted.

What is actually happening?

The component doesn't mount with the following error:

Failed to mount component: template or render function not defined.


This is actually a cross-post from vuejs/composition-api#151. I’m looking for help to resolve this issue where render functions returned from the composition api setup functions are not properly set while mounted through vue-test-utils.

At this point I’m wondering if vue-test-utils is the problem here or if it’s totally unrelated. And if it is, I would appreciate some guidance about where to look next to debug it.

@lmiller1990
Copy link
Member

lmiller1990 commented Mar 23, 2020

I can't even get returning a render function from setup to work in a regular app. Is this even supported? It doesn't say it is here: https://github.com/vuejs/composition-api

I'll try pulling that repo. We should repro without TS; the less dependencies, the better.

Edit: I cloned that repo and ran yarn and got:

warning ../package.json: No license field
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
error An unexpected error occurred: "https://npm.codeo.co.za/@vue%2fcli-plugin-pwa/-/cli-plugin-pwa-4.2.2.tgz: Request failed \"401 Unauthorized\"".
info If you think this is a bug, please open a bug report with the information provided in "/Users/lachlan/code/dump/vue-composition-api-tsx-example/yarn-error.log".

🤔

@dobromir-hristov
Copy link
Contributor

According to https://github.com/vuejs/composition-api#template-refs it doesnt. That will work for Vue 3 i think.

@lmiller1990
Copy link
Member

lmiller1990 commented Mar 23, 2020

This is my understanding too - unless something has changed. It looks like some people have it working? Maybe the readme is outdated. From what I can tell Vue 2 does not expose h or createElement in the same way Vue 3 does. This definitely works in Vue 3, at least using regular h (which is basically what jsx is).

@LeBenLeBen
Copy link
Contributor Author

@dobromir-hristov @lmiller1990 I think that the docs you mention is specific to refs, no?

For me @vue/composition-api used with Vue 2 does support the setup function returning a render function (the code is at https://github.com/vuejs/composition-api/blob/3b7eadfbb3868fd2fc67b538ea8ded4af4905832/src/setup.ts#L176-L185), it also exports the createElement method required.

I have it working perfectly in the browser, but not when mounted through @vue/test-utils. You can see an exemple here: https://github.com/liip/chusho/blob/master/packages/chusho/src/components/CToggle/CToggle.ts#L64

@lmiller1990
Copy link
Member

lmiller1990 commented Mar 24, 2020

Looks like they do some hackery relating to the render function like we do in VTU

https://github.com/vuejs/composition-api/blob/7c8386eea241974ead77d3fd3eb6916fa8903653/src/setup.ts#L135

https://github.com/vuejs/composition-api/blob/7c8386eea241974ead77d3fd3eb6916fa8903653/src/setup.ts#L179

I guess some kind of conflict. When I run in VTU, instead of the render function getting called, I get the uncalled render function. It looks like Compsition API expects to be hijacking the original render function, but instead they received our patched one (for shallowMount).

@lmiller1990
Copy link
Member

lmiller1990 commented Mar 24, 2020

As a proof of concept I jumped into node_modules/@vue/test-utils/dist/vue-test-utils.js at on line 13500 or so, (search for function mount) I added:


function mount(component, options) {
  if ( options === void 0 ) options = {};

  component.render = component.setup() // <=========== this line

  // .......
}

And it works as expected - VTU renders the component correctly in the test env. Not sure why, I guess VTU expects a render function to be defined (would need to investigate more). Calling setup isn't ideal since it would trigger API calls etc etc. We need to find some way to grab the returned render function out and assigning it to render.

This problem doesn't exist in Vue 3, since it handles this internally. Composition APi is a bit of hack (like VTU is also).

Alternatively we need to figure out how to resolve the conflict between Composition API and VTU.

I will keep thinking about this, hopefully this info gives someone else something to go on if they want to mess around! A fix for this could be either here or over in composition API.

@LeBenLeBen
Copy link
Contributor Author

@lmiller1990 thanks for your insights!

I just tried to create my own mount wrapper that would set the result of the setup method as the component render function but that seems to be a bit more complicated than expected.

function mountWithSetup(component, options = {}) {
  component.render = component.setup(options.propsData || {}, {
    data: {},
    parent: {},
    slots: {},
  });
  return mount(component, options);
}

I need to pass the parameters to the setup function (props and context). Props is pretty easy but context contains stuff like parent which is not accessible to me I think.

In addition, composition API seems to throw warnings then:

[vue-composition-api] "provide" get called outside of "setup()"

@lmiller1990
Copy link
Member

Fixing this would be nice, but not something I'm able to focus on now unfortunately, and not something we will be doing before v1 - mainly because most people writing tests using the composition API will be moving to Vue 3 (hopefully), which won't have this problem, since composition is built in natively.

If you do manage to get something working, happy to take a look.

@lmiller1990
Copy link
Member

Fix is coming for this soon! vuejs/composition-api#383

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants