Pianoc
Pianoc

Reputation: 797

Using DOM directly in Vue unit test when no alternative

How do I correct my unit test to correctly test for the below?

Method:

close(event) {
  const element = !!event?.target?.closest('#target')

  if (!element) {
    this.isVisible = false
  }
},

Jest test:

  it('should hide visibility if element is false', () => {
    const wrapper = shallowMount(AccountLogin, { mocks })
    wrapper.vm.close()

    expect(wrapper.vm.$data.isVisible).toBe(false)
  })

Upvotes: 0

Views: 325

Answers (1)

tao
tao

Reputation: 90013

If the change() event is fired on the root element of your component, this should work:

jest.spyOn(wrapper, 'closest')
    .mockImplementationOnce(() => true)

wrapper.vm.close()
expect(wrapper.vm.$data.isVisible).toBe(false)

If the event is triggered on a child of root component element, you'll need to pass that child to spyOn, so you mock that child's closest, instead of the wrappers. e.g:

jest.spyOn(wrapper.find('input'), 'closest')
    .mockImplementationOnce(() => true)
// ...

Why you need to find the exact element: this is jsdom: it's not actual DOM. Events don't bubble.


What the above does: it hijacks .closest() method of event.target's element so it returns true.
Which, in your case, will cause

!!event?.target?.closest('#target')

to return true, so this.isVisible = true will be executed.

If you want to test that it's not executed when #target is not found, write a second test, with a .closest() mock returning false and test that isVisible has not been set from false to true upon invoking .close(). Doing more than that would be testing that HTML works as expected.
I recommended you trust that it does.

Upvotes: 1

Related Questions