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

wrapper.setProps doesn't work on Functional component #402

Closed
jonnyparris opened this issue Feb 2, 2018 · 17 comments
Closed

wrapper.setProps doesn't work on Functional component #402

jonnyparris opened this issue Feb 2, 2018 · 17 comments

Comments

@jonnyparris
Copy link

Version

1.0.0-beta.11

Reproduction link

https://github.com/jonnyparris/vue-test-utils-mocha-webpack-example/blob/e2e634e4640ce40180b957b4feab51076b77a780/test/Message.spec.js#L19

Steps to reproduce

use setData() as per docs

What is expected?

data should be set

What is actually happening?

data remains unchanged


Bug seems to have been introduced somewhere between version beta3 and beta11 (only just upgraded packages across my project)

@eddyerburgh eddyerburgh changed the title wrapper.setData no longer working wrapper.setData not working on Functional component Feb 3, 2018
@eddyerburgh eddyerburgh added the bug label Feb 3, 2018
@eddyerburgh
Copy link
Member

There isn't any data in a functional component, so you calling setData will have no effect. We should add error handling to tell the user that they can't call setData on a functional component.

But there is an issue with setProps and functional components. It's going to be tricky to fix.

@jonnyparris
Copy link
Author

MessageToggle.vue has a data object - I'm not sure I understand what you mean. Please can you explain?
To clarify on my side, I have a bunch of tests that were working fine using setData that suddenly stop working withe the latest version.
I just forked that example from the docs to both verify it was that method in particular but also to use a minimal example.

@eddyerburgh
Copy link
Member

You're calling setData on the wrapper of a functional component. Functional components are stateless, so there's no data to set.

If the tests were previously working correctly with setData, it was because setData was behaving incorrectly.

@jonnyparris
Copy link
Author

Thanks & my bad, I thought I was testing MessageToggle but actually it was just the Message component that wrote the spec for.
Adding the same setData spec to MessageToggle passes with beta11 but the prop test that was already in the repo is indeed failing.

I'm going to have to double check my original failing setData tests then 😕

@eddyerburgh eddyerburgh changed the title wrapper.setData not working on Functional component wrapper.setProps not working on Functional component Feb 21, 2018
@eddyerburgh eddyerburgh changed the title wrapper.setProps not working on Functional component wrapper.setProps doesn't work on Functional component Feb 21, 2018
@dimensi
Copy link

dimensi commented Mar 23, 2018

@eddyerburgh if setProps and setData not working. How set props on functional component?
propsData, not working too

@beyer-martin
Copy link
Contributor

In what state is this?

@eddyerburgh
Copy link
Member

It's not being worked on. I think we need a change in core to be able to implement this. I believe we need to have access to the render context, but it's not exposed—https://github.com/vuejs/vue/blob/dev/src/core/vdom/create-functional-component.js#L97.

If you want to look into this, I'd be happy to help.

@artf
Copy link

artf commented May 24, 2018

@dimensi you can mount it via context https://vue-test-utils.vuejs.org/api/options.html#context

@EmilioAiolfi
Copy link

Guys, help.
I create a functional component
But the tests return an error with .props()

I tried with shallowMount and mount
Is it a bug? I don't know

  it('should to be a div default in prop tag', () => {
    const wrapper = shallowMount(container, {
      context: {
        propsData: { fluid: true },
      },
      slots: {
        default: [contentHtml],
      },
    })

    expect(wrapper.props().fluid).toBe(true)
    expect(wrapper.html()).toMatchSnapshot()
  })

Run test
screen shot 2018-09-04 at 7 06 50 pm

But i tried a another approach.
wrapper.vm.$vnode.componentInstance._renderProxy._self._vnode.data
return this

   wrapper { class:
       [ { className: false,
           container: true,
           'container-fluid': false,
           flex: false } ],
      style: [ undefined ],
      propsData: { fluid: true },
      scopedSlots: {},
      normalizedStyle: {} }

@eddyerburgh
Copy link
Member

No this is intended behavior, props is currently not supported with functional components. It will be supported in dev mode when this PR lands—vuejs/vue#8586

@marszall87
Copy link

Looks like the mentioned PR was merged, can we do something about .props() on functional components?

@eddyerburgh
Copy link
Member

Yes, although it's fairly low on my priority list. I'll try to get it done within a month, but if somebody else would like to work on it I'd be happy to review the PR and give pointers on how to do it.

@Orlayhemmy
Copy link

I will like to work on it @eddyerburgh. Can you give me pointers please

@hiendv
Copy link
Contributor

hiendv commented Aug 16, 2019

Ping!

@lmiller1990
Copy link
Member

At the time this seems like a good idea, however reflecting on it setProps (and props) makes very little sense for a functional component (and regular components in general, imo, but that's a different discussion). Functional components are literally a pure function, their rendered output (ie the DOM) is the state of the props.

For your functional component tests, make assertions on the DOM instead of using .props(). For setting specific data, instead of setProps, just use the propsData mounting option.

@mprinc
Copy link

mprinc commented Jul 6, 2021

@lmiller1990 thanks for the advice, but I am still not possible to use basic DOM for functional component that accepts binded objects, for example:

		<fieldset class="fieldset" is="ColaboMaterial" type="fieldset" :info="{test: "hello"}">
		<select is="ColaboMaterial" type="autocomplete" class="node-select" v-model="autocompleteCustomTemplateValue" :info="{ options: getAutocompleteCustomTemplateOptions, placeholder: 'Chose {{ schemaName }}' }">
		<button class="button-select-target-node" is="ColaboMaterial" type="button" :info="{ primary: false, raised: true }" @click="selectTargetNode()">Select</button>

For all 3 of them if I access the info attribute (there is no v-bind:info or :info) I will just get toString() value which is useless for testing: [object Object]

Is there any workaround to test bound (object) props for functional components

@lmiller1990
Copy link
Member

I don't understand what passing an info prop to <button> does - is this part of HTML? What does it do? What behavior are you trying to test (eg: just knowing that a prop was passed is not really testing anything; does your component/system use the info prop to do something?)

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

No branches or pull requests