eddyerburgh / avoriaz

🔬 a Vue.js testing utility library
https://eddyerburgh.gitbooks.io/avoriaz/content/
MIT License
759 stars 62 forks source link

Testing of computed properties #15

Closed ryanjgill closed 7 years ago

ryanjgill commented 7 years ago

When trying to test a computed property using AVA and with Avoriaz, the context of this is not what is expected. I'm trying to use a computed property that is based on some data from the component.

More details on stackoverflow.

eddyerburgh commented 7 years ago

Three potential solutions here:

  1. Deprecate computed, propsData and methods methods, since they return methods that are not bound to the vue instance. Encourage use of wrapper.vm for testing methods and data instead:

    const wrapper = mount(Component, {computed: { someMethod }})
    expect(wrapper.vm.someMethod).to.equal(someMethod) // true :)
  2. Bind all methods returned from computed(), methods() and propsData() to the vm instance. This would cause strange behavior:

    function someMethod(){
    console.log(this)
    }
    const wrapper = mount(Component, {computed: { someMethod }})
    expect(Component.computed().someMethod).to.equal(someMethod) // throws assertion error
  3. Most radical - remove computed, methods and propsData methods and change the root of the wrapper to be the vue instance with added avoriaz methods. The vue instance(vm) already supports easy checking of methods and data:

const wrapper = mount(Component, {computed: { someMethod }})
expect(wrapper.someMethod).to.equal(someMethod) // true

Problems with this:

  1. avoriaz methods could clash with component data or methods (ie. a component with a find method will clash with the avoriaz find method)
  2. It's not really a wrapper anymore

So far I'm leaning towards the first solution

I'd really appreciate any suggestions from others.

I think the best thing to do right not is log an error when method(), computed() and propsData() are called.

eddyerburgh commented 7 years ago

@atilacamurca @stephane thoughts on the above?

atilacamurca commented 7 years ago

I agree with you, you should always keep it a wrapper.

eddyerburgh commented 7 years ago

@ryanjgill I can't think of a good way of fixing this. Instead I've added a warning that points to this issue and suggest using wrapper.vm.methodName to access computed functions that use this.

ryanjgill commented 7 years ago

@eddyerburgh Sounds good. Thanks for all the feedback guys!

jasperck commented 7 years ago

hi @eddyerburgh I was writing tests for my vue component, when I tried to test the part of props, I was doing something like this

given(
  ...some test data
)
  .it('should accept prop:', (propName, propValue) => {
    const wrapper = mount(InfiniteScroller, {
      propsData: { propName: propValue }
    });
    expect(wrapper.propsData().propName).to.equal(propValue);
  });

Then I got this warning messages and found out the reason in the issue from the messages.

WARN: 'warning: functions returned by propsData() will not have this bound to the vue instance. Calling a propsData function that uses this will result in an error. You can access propsData functions by using the vue instance. e.g. to call a method function named propsDataFunc, call wrapper.vm.propsDataFunc(). See https://github.com/eddyerburgh/avoriaz/issues/15'

According to the comment https://github.com/eddyerburgh/avoriaz/issues/15#issuecomment-289435469, looks like there is still no solution for somethink like

expect(wrapper.vm.propName).to.equal(propValue);

am I right, guys?

eddyerburgh commented 7 years ago

@jasperck Both of your examples should work. The warning message is only meant for users trying to call propsData that use this.

jasperck commented 7 years ago

@eddyerburgh Thanks, I see, but actually it only worked for

expect(wrapper.propsData().propName).to.equal(propValue);

but not

expect(wrapper.vm.propName).to.equal(propValue);

// test output
expected undefined to equal `propValue`

calling prop directly on vm just caused some error about getting undefined

eddyerburgh commented 7 years ago

@jasperck Hi, sorry for the miselading message. I've updated and released a correct warning message in 1.9.4.

To access props with this bound the vue instance, you must run:

expect(wrapper.vm.$props.propName).to.equal(propValue);
beliolfa commented 7 years ago

Hi.

I am trying to follow the steps in the warning in order to check a computed but I get an error TypeError: wrapper.vm.welcomeText is not a function

and this is the code

t.is(wrapper.vm.welcomeText(), 'INTRODUCTION TEXT HERE');

Of course, the computed exists in the component.

eddyerburgh commented 7 years ago

@disitec computed methods are used as getter functions for the property - https://vuejs.org/v2/guide/computed.html#Computed-Properties

t.is(wrapper.vm.welcomeText, 'INTRODUCTION TEXT HERE');

Should pass

beliolfa commented 7 years ago

Yep, It works.

So, I think you shuould update the warning without parenthesis ;)

Thanks!

eddyerburgh commented 7 years ago

Fancy making a PR? 😉

beliolfa commented 7 years ago

Here you have.

https://github.com/eddyerburgh/avoriaz/pull/63