Skip to content
This repository has been archived by the owner on Feb 7, 2024. It is now read-only.

Attributes of injected objects are not reactive during test #442

Open
MelvinFrohike opened this issue Nov 23, 2022 · 0 comments
Open

Attributes of injected objects are not reactive during test #442

MelvinFrohike opened this issue Nov 23, 2022 · 0 comments

Comments

@MelvinFrohike
Copy link

When providing an object in a test using vue-test-utils, 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 InjectReactive annotation.
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 compatibility problem with the vue-test-utils?

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

No branches or pull requests

1 participant