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

Attributes of provided objects are not reactive #2035

Open
MelvinFrohike opened this issue Nov 23, 2022 · 1 comment
Open

Attributes of provided objects are not reactive #2035

MelvinFrohike opened this issue Nov 23, 2022 · 1 comment

Comments

@MelvinFrohike
Copy link

When providing an object, its properties are correctly injected into the (shallow)mounted component.
However, when changing the properties, computed properties of my component do not notice the change and do not recompute. I am using the Vue-Property-Decorator InjectReactive annotation, which automatically wraps annotated attributes into a "reactiveInject" object.
Relevant versions are VueJs 2.7.10, vue-test-utils 1.3.0, vue-property-decorator 9.1.2

Example code

@Component
export default class MyComponent extends Vue {
  @InjectReactive someValue!: string | null
  
  get computedProperty(): string {
    return this.someValue
  }
})


const localVue = createLocalVue()
describe('test', () =>  {
  let wrapper
  let reativeInject

  beforeEach(() => { 
    reactiveInject = { someValue: 'hello' }
    wrapper = shallowMount(MyComponent, {
      provide: () => {
        return { __reactiveInject__: reactiveInject }
     },
    localVue
    }
  })

  it('initial injection', () => {
    expect(wrapper.vm.computedProperty).toEqual('hello') // TEST PASSES
  })

  it('changed value', async () => {
    reactiveInject.someValue = 'goodbye'
    await wrapper.vm.nextTick()
    expect(wrapper.vm.computedProperty).toEqual('goodbye') // TEST FAILS, value is still 'hello'
  })
})

Expected behaviour

Both tests should be green

Actual behaviour

The second test fails, as the value is still 'hello'. The computed property is not recomputed. When actually using the code in production it works as expected.

Possible Solution

I can only get the second test to pass with injection if I mount the component again with a different value. However, this is a lot of overhead and doesn't allow me to test that my component reacts to changes correctly.
Alternatively, I can choose not to use provide when mounting and instead pass the value as data. However, this means that the test doesn't show the correct usage of the InjectReactive annotation. The test would even pass if I forget to use the annotation.

I've tried multiple ways to provide the information in my test, including a more elaborate setup for the provided data:

let someValue
let reactiveData
beforeEach(() => {
  someValue = 'hello'
})
...
provide() {
    reactiveData = {}
    Object.defineProperty(reactiveData, 'someValue', {
      enumerable: true,
      get: () => someValue,
      set:  (newValue) => (someValue = newValue)
    })
    return {
      __reactiveInject__: reactiveData
    }
}

...

 it('changed value', async () => {
    reactiveData.someValue = 'goodbye'
    await wrapper.vm.nextTick()
    expect(wrapper.vm.computedProperty).toEqual('goodbye') // TEST FAILS, value is still 'hello'
  })

Am I doing something wrong or is there a problem with the vue-test-utils?

@lmiller1990
Copy link
Member

I haven't seen this use case before; I'm not sure if this should work, or not. Does the bug manifest without class component, too?

Sorry about the slow reply. I hope we can start to fix some of the Vue 2.7 bugs.

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

3 participants