1
votes

Description

I have a BaseCheckbox component that renders a checkbox, using a "value" prop. When I click on the tag, the component emits event.target.checked. When testing with jest, the event.target.checked does not change and the same value as the prop is emitted. Running in the browser, event.target.checked changes correctly on every click and every time the opposite of the value prop is emitted (which I checked by adding the console.log in BaseCheckbox.vue).

The Vue Component

<template>
  <div class="custom-checkbox">
    <div v-if="value" class="checkmark"></div>
    <input :checked="value" type="checkbox" @change="onChange" />
  </div>
</template>

<script>
export default {
  props: {
    value: {
      type: Boolean,
      required: true
    }
  },
  methods: {
    onChange(event) {
      console.log(event.target.checked);
      this.$emit("input", event.target.checked);
    }
  }
};
</script>

The Test that fails on the 2nd expect

it("should emit 'input' event with value payload", () => {
        wrapper.setProps({ value: true });
        expect(wrapper.vm.$props.value).toEqual(true);
        wrapper.find("input").trigger("change");
        expect(wrapper.emitted().input[0]).toEqual([false]);
})

Expected: emit the opposite of the value prop

Actual: in jest: emits the same value as the value prop, browser: emits the opposite of the value prop

Error Message

 FAIL  tests/components/baseComponents/BaseCheckbox.spec.js
  BaseCheckbox
    ✓ should show checkmark when value is true (6ms)
    ✓ should not show checkmark when value is false (3ms)
    ✕ should emit 'input' event with value payload (84ms)

  ● BaseCheckbox › should emit 'input' event with value payload

    expect(received).toEqual(expected)

    Expected value to equal:
      [false]
    Received:
      [true]

    Difference:

    - Expected
    + Received

      Array [
    -   false,
    +   true,
      ]

      23 |         expect(wrapper.vm.$props.value).toEqual(true);
      24 |         wrapper.find("input").trigger("change");
    > 25 |         expect(wrapper.emitted().input[0]).toEqual([false]);
         |                                            ^
      26 |     })
      27 | })
      28 | 

      at Object.toEqual (tests/components/baseComponents/BaseCheckbox.spec.js:25:44)

  console.log src/components/baseComponents/BaseCheckbox.vue:18
    true

Test Suites: 1 failed, 1 total
Tests:       1 failed, 2 passed, 3 total
Snapshots:   0 total
Time:        5.435s
1

1 Answers

0
votes

I figured it out myself. Vue-Test-Utils provides a function for this exact usecase.

https://vue-test-utils.vuejs.org/api/wrapper/#setchecked

The final working test

it("should emit 'input' event with value payload", () => {
        wrapper.setProps({ value: true });
        wrapper.find("input").setChecked(false);
        expect(wrapper.emitted().input[0]).toEqual([false]);
})