Nils-o-mat
Nils-o-mat

Reputation: 1256

Testing the value of a Vue enhanced input does not work as expected

I want to test a Vue input-component, which changes its input on the mounted hook (and later on blur). The component itself seems to work, but the test-utils do not get the correct values. I use the jasmine test-framework for this demonstration:

const appendValue = '_lily';

const testInput = {
  props: ['value'],
  template: `<input ref="testInput" v-on:blur="appendTest" v-model="inputValue"/>`,
  mounted() {
    this.appendTest();
  },
  computed: {
    inputValue: {
      get() {
        return this.value;
      },
      set(newValue) {
        this.$emit('input', newValue);
      }
    }
  },
  methods: {
    appendTest() {
      this.$emit('input', this.value + appendValue);
    }
  }
}

describe("Vue-input-test", function() {
  it("appends _lily", function(done) {
    const testValue = "tiger";
    const tWrapper = VueTestUtils.mount(testInput, {
      propsData: {
        value: testValue
      }
    });

    Vue.nextTick(function() {
      const expectedValue = testValue + appendValue;
      expect(tWrapper.emitted().input.length).toEqual(1);
      expect(tWrapper.emitted().input[0][0]).toEqual(expectedValue);

      /* These assertions fail: */
      expect(tWrapper.vm.$refs.testInput.value).toEqual(expectedValue);
      expect(tWrapper.vm.value).toEqual(expectedValue);

      tWrapper.destroy();
      done();
    });
  });
});

Here is my fiddle. I'm grateful for every helpful suggestion. Thanks!

Upvotes: 3

Views: 459

Answers (1)

logaretm
logaretm

Reputation: 1435

Your test is missing a parent component, this is a caveat with events and especially with v-model on custom components.

Remember that v-model is loosely equivalent to doing:

:value="value" @input="value = $event"

Because you are testing the component directly without a parent, there is nobody listening for the input event, which means the value = $event part never runs, so the value prop will never change.

You can solve this by wrapping your utils.mount call with another component like this:

const tWrapper = VueTestUtils.mount({
  template: '<div><test-input v-model="value"></test-input></div>',
  components: {
    testInput
  },
  data: () => ({
    value: testValue
  })
});

The failing assertions will now pass, but some assertions will have to change, of course. I have updated the fiddle for you.

This never happens in a real app because there is always a root component, so all other components are most likely to have a parent.

Upvotes: 1

Related Questions