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

Computed property used in template does not reevaluate when setMethods is used on dependency method #1519

Closed
enriqg9 opened this issue Apr 27, 2020 · 3 comments
Labels

Comments

@enriqg9
Copy link

enriqg9 commented Apr 27, 2020

Version

1.0.0-beta.31

Reproduction link

https://github.com/enriqg9/vue-test-utils-setmethod-replace-computed

Steps to reproduce

Computed property does not reevaluate after setMethods is used on a method that is called inside a computed property if the property is rendered in the template.

Below there are two computed properties which depend on the can() method.

methods: {
    can(){
      return false
    }
  },
  computed: {
    usedInTemplate(){
      console.log('usedInTemplate', this.can())
      return this.can()
    },
    notUsedInTemplate(){
      console.log('notUsedInTemplate', this.can())
      return this.can()
    }
  }

The usedInTemplate property is rendered inside the template and the value is cached to false.

<template>
  <button>{{ usedInTemplate }}</button>
</template>

In the test, replacing the can() method with a true value with setMethods will still yield false on usedInTemplate

  it('should reevaluate usedInTemplate when the Can method is changed', () => {
    wrapper.setMethods({
      can: () => {
        return true
      }
    })
    expect(wrapper.vm.usedInTemplate).toBeTruthy() //fails
  })

In the test, replacing the can() method with a true value with setMethods will yield true on notUsedInTemplate

  it('should reevaluate notUsedInTemplate when the Can method is changed', () =>  {
    wrapper.setMethods({
      can: () => {
        return true
      }
    })
    expect(wrapper.vm.notUsedInTemplate).toBeTruthy() //passes
  })

What is expected?

Computed property should reevaluate

What is actually happening?

Computed property is not reevaluating

@lmiller1990
Copy link
Member

lmiller1990 commented Apr 27, 2020

Hi!

This is a bug. setMethods will be be deprecated soon, though, as per this rfc, so we will not be fixing this one.

What does the implementation of can look like in your actual app? If you can share it (or something similar) I can try to recommend some alternatives.

@enriqg9
Copy link
Author

enriqg9 commented Apr 27, 2020

Hi @lmiller1990!

I have a global mixin can as part of my authorization where I check if the User has the given permission and use that to conditionally render parts of my application.

import {castArray} from 'lodash'

const authorization = {
  methods: {
    can(permission) {
      return this.$store.getters.getPermissions.some(r => castArray(permission).includes(r))
    },

    cannot(permission) {
      return !this.$store.getters.getPermissions.some(r => castArray(permission).includes(r))
    }
  }
}

export default authorization;

On my tests I mock the methods when mounting the component and wanted to replace the value without creating a new wrapper.

wrapper = shallowMount(Component, {
  methods: {
    can: () => false,
    cannot: () => true
  }
})

I ended up using a wrapper factory function. Thanks for your help and your contributions, your testing handbook has been a crucial reference!

@lmiller1990
Copy link
Member

Glad you found a work around. The way I normally would test these (I have the exact same thing in my app, $store.auth.roles or something like that) is to just provide a new Vuex store for each test.

Glad my book was of use! I am always looking to include more useful content, you can open an issue there if you have an idea.

Another way you can do this is by using the computed mounting option, if you moved can and cannot to computed properties (they don't appear to have any arguments, so that should work).

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

No branches or pull requests

2 participants