Vue-test-utils: Enable support to call setValue() an a Bootstrap Vue b-form-input

Created on 6 Sep 2018  路  13Comments  路  Source: vuejs/vue-test-utils

What problem does this feature solve?

The current project on which I am working makes extensive use of Bootstrap Vue's b-form-input and other custom html elements. When trying to write a test that exercises, amongst other things, on of the b-form-inputs I have in my template, when I find() my b-form-input element and try to call setValue() on it, I receive an error that setValue() cannot be called on the b-form-input element.

The end user experience that I am trying to build is an input that validates on content and length, and I would like to wrap unit tests around this functionality. Currently I cannot do that because vue-test-utils does not support calling setValue() on a b-form-input html element.

_I fully recognize that this feature request may not be the responsibility of vue-test-utils. Perhaps I need to put in a feature request to the Boostrap Vue project instead, but I figured it was a 50/50 shot on who to contact about this first._

What does the proposed API look like?

I believe that there would be no changes to the public facing API, but rather an internal support for b-form-inputs. The call should be the same as it currently is: bFormInputElement.setValue().

feature request

Most helpful comment

Does anyone know the current status of this issue, I have gotten the same error when using Vuetify's v-text-field component.

All 13 comments

After continuing my search, I reread the documentation for setValue() (I swear what I was reading on that page was different 3 hrs ago, but that doesn't make sense).

Using

textInput.element.value = value
textInput.trigger('input')

effectively accomplishes the same thing, _even_ with a b-form-input custom html element. While using just setValue() would be really nice, I don't expect that it is the responsibility of vue-test-utils to support boostrap vue functionality.

As a result I'm going to go ahead and close this feature request.

Actually I think we could support this, since the b-form-input pattern is common

So we are discovering today that the above solution worked for some of our tests, but not others. Our initial tests were just to check if a method defined in our component was getting called when we input data into the b-form-input field. Those tests failed as expected, and then passed when we provided the correct implementation logic.

We are now working on a test that checks to see if the b-form-input's state attribute gets updated after input happens:

<template>
  ...
  <b-form-input
    placeholder="7-digit code"
    :value="productData.contractId"
    @input="updateProduct($event, 'contractId')"
    aria-describedby="contractIdFeedback"
    autocomplete="off"
    maxlength="7"
    :state="this.productValidationStates.contractId"
    @keydown.native="allowNumeric($event)"
    >
    </b-form-input>
  ...
</template>

<script>
  updateProduct(value,type) {
    ...
    this.setValidationStates()
    ...
  }

  setValidationStates() {
    if (this.productData.contractId.length !== 7) {
      this.productValidationStates.contractId = 'invalid'
    } else {
      this.productValidationStates.contractId = 'valid'
    }
  }
</script>

In my test, I used the

textInput.element.value = '1234567'
textInput.trigger('input')

syntax to trigger an input event. I added console.log within updateProduct() and setValidationStates() to confirm that both methods were being called when the input event is triggered, and indeed both methods are called. However, it doesn't appear that the textInput.element.value = '1234567' line is actually setting the input value correctly because the line that checks the length of the input was trying to compare an event with 7. For some reason (that I'm trying to figure out), the number that I'm trying to input isn't binding to the component data on the line :value="productData.contractId" _in my test_. This all works as expected in the browser when I manually test it.

Any thoughts? Apologies, as I would provide the source code if I had access to it right now, but I don't, so I'm writing this from memory.

If you are using mount() try selecting the input element. If shallow mounting this is not possible

https://codesandbox.io/s/43zx9klxp9

I vote for this as well. On shallow mount, using custom input component should have setValue() shorthand for @input :value.
Im using element-ui for example

I have the same problem mentioned by @mjvezzani. After updating to the latest versions it's unable to set the value directly to the b-form-input

Just curious to know what the status of supporting custom input components are. Right now we are running into a different issue in which we are trying to trigger a click event on a b-btn custom input component, and we can't get the test to pass. When we change b-btn to a normal button element, the test passes without issue. Seems like the issue here is that vue-test-utils doesn't support interacting with custom input components.

@eddyerburgh Is my conclusion correct? Or is there something that I am missing?

trigger works by dispatching a DOM event on the root element of the wrapper that you call it on (accessible by wrapper.element). So if the root element has a listener for the event, it will be triggered.

setValue works by setting the element value property of the root element.

Not all components pass event handlers/ props to their root element, which causes this unexpected behavior.

I intend to investigate this issue further in the future.

re: b-btn, are you using shallowMount? If not, can you please create a new issue with a reproduction.

Does anyone know the current status of this issue, I have gotten the same error when using Vuetify's v-text-field component.

I want to know the latest progress on this issue, I have gotten the same error when testing my custom input component

I'm running into this too. Would love to know if there are any updates 馃檹

The exmaple of @beyersito helped me. I use shallowMount and searchInput.element.value and the trigger method. FYI.

I think we can close this one - there are a number of solutions here.

If you are using shallowMount, it will stub out third party components. Use mount, and then call setValue on the <input> element. This should work for <v-text-field> in Vuetify too. If not, post and I will reopen this.

For the Vue 3 integration we will use Vuetify and Bootstrap Vue as part of the unit tests, since those are popular libraries, and hopefully provide a better API then. For now

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alexanderstudte picture alexanderstudte  路  3Comments

38elements picture 38elements  路  3Comments

benm-eras picture benm-eras  路  3Comments

matt-sanders picture matt-sanders  路  3Comments

lusarz picture lusarz  路  3Comments