5

I have a form setup using vue.js and v-select for a currency dropdown. I'm attempting to create a unit test to make sure the current value of the v-select is set to the computed value price_currency

Here is the vue code for the selector

<v-select
 name="price_currency"
 :value="price_currency"
 @input="value => this.updateValue('price_currency', value)"
 :options="currencies"
 v-validate="validate.select"
 :selectOnTab="true">
</v-select>

the :value is set to price_currency which is a computed value. In the unit tests, I can use the find method on the v-select which will return the element, but because it's a vue component and not an actual <select> the value element is not set, which means I can't test for it.

How can I write a unit test for the above v-select which will confirm that the field is set to the computed value of price_currency? Additionally, I want to test that when price_currency is updated so is the value on the v-select, but likely once I see an example of testing the value the rest will fall into place.

This seems like a fairly simple test, but I can't find anywhere in the documentation or online a good example of how this can be done.

For my unit tests, I am using VueTestUtils and Jest.

skyboyer
  • 22,209
  • 7
  • 57
  • 64
6557457iD9e
  • 108
  • 1
  • 9
  • Do you really need a unit test for it though? Can't you just test it in your browser locally and trust that it works later? I mean this isn't an all that fragile part of your app that really needs a test. Also all Vue components are turned into regular HTML elements, so yes it actually is a regular html input field, assuming your tester processes the Vue project fully. I recommend running your project and opening the inspector in your browser to see what kind of html is outputted by Vue. – Simon Hyll Nov 14 '18 at 02:25
  • most likely, using `:value` will not update `price_currency` when select is updated. You should be using `v-model` – A. L Nov 14 '18 at 02:26
  • As A. Lau says, you should be using `vue-model` in order to keep it in sync with a value. – Simon Hyll Nov 14 '18 at 02:42
  • I didn't mention this, but the select is actually a child view of another view. That is why v-model was not used. The updateValue() method called on the input will emit the value of the select. Now I'm thinking the select doesn't need testing in the child. Instead, the tests in the parent will cover it because that's where the value is actually set. But I still need to test when the value changes in the select that the $emit event happens, and I'm not sure how to do that without knowing the value. – 6557457iD9e Nov 14 '18 at 03:42
  • You might want to see how this can be done with browser testing: https://stackoverflow.com/questions/51163562/testing-vuetify-v-select-with-laravel-dusk/56728707#56728707 – Cato Minor Jun 24 '19 at 03:56

1 Answers1

1

I did this:

expect(wrapper.find('#selectCustomerCountry .selected-tag').text()).toEqual('lorem')

This is how my Vue template code looks like:

<v-select v-bind:class="{'input--has-error': errors.has('country')}" class="select-field input--full v-select" id="selectCustomerCountry"
          name="country"
          v-if="useCountrySearch"
          v-model="foundCountry"
          :filterable="false"
          :options="countries"
          label="name"
          :onSearch="onSearch"
          v-validate:country="'required'">
    <template slot="option" slot-scope="option">
        <span class="v-select__label">{{ option.name }}</span>
        <br />
        <span class="v-select__label--small">{{ option.continent.name }}</span>
    </template>
    <span slot="no-options">Type at least 3 characters...</span>
</v-select>

And this is how the rendered HTML looks like when I mount the page and I call wrapper.html(), after it has already selected an option called lorem:

<div dir="auto" class="dropdown v-select select-field input--full v-select single searchable" id="selectCustomerCountry" name="country">
  <div class="dropdown-toggle">
    <div class="vs__selected-options"><span class="selected-tag">
            lorem
           <!----></span> <input type="search" autocomplete="off" role="combobox" aria-label="Search for option" class="form-control"></div>
    <div class="vs__actions"><button type="button" title="Clear selection" class="clear" style=""><span aria-hidden="true">×</span></button> <i role="presentation" class="open-indicator"></i>
      <div class="spinner" style="display: none;">Loading...</div>
    </div>
  </div>
  <transition-stub name="fade">
    <!---->
  </transition-stub>
</div>

Note that I prefer a more integration-oriented style of Jest testing, so I am making assertions for the contents of the page rather than the values in the models, this is because I feel like it provides better coverage. If you prefer to test only the values in the models then you might be able to find an example in the unit tests of V-Select itself.

Velizar Hristov
  • 662
  • 2
  • 10
  • 23