cypress component test not catching update event emitted from my Vue3 component

184 views Asked by At

I am new to component testing and using spys in cypress so this might be a silly question.

I have a pretty simple component that I am testing where when you make a selection in the component and the selection is emitted back to the parent through the modelValue property.

My component works in my application (the v-model updates with the proper value from the selection just fine) but I cant seem to catch and validate it in the test.

Inside my component here is how I'm doing the emit:

handleSelectionChange() {
  console.log("emitting update:modelValue= ", this.selectedOption);
  this.$emit('update:modelValue', this.selectedOption);
}, 

The console shows the values changing when the test runs so I think this part is OK. Again, when I use the component in my application the v-model is updating so I expect this isn't the problem.

My Cypress Component test looks like this:

it.only('should emit an event when the value is changed', () => {
const mockData = ["one", "two", "three"];

cy.intercept('GET', '/v1/product', {
  statusCode: 200,
  body: mockData,
}).as('getProductData');

cy.mount(ProductPicker, {
  props: { modelValue: null },
  on: {
    'update:modelValue': cy.spy().as('updateModelValueSpy'),
  },
}).then(() => {
  cy.get('select').select('two');

  // Wait added as part of trouble shooting, hopefully not needed
  cy.wait(500); 

  // Ensure the spy has captured the emitted event
  cy.get('@updateModelValueSpy').should('have.been.called');
});

});

When the test runs I see the value "two" printed to the console so the test has called my function which seems to be emitting the "update:modelValue" event...

But the test fails with the message: assertexpected updateModelValueSpy to have been called at least once, but it was never called

I've spent hours twiddling this over the course of a couple of days. Does anyone have anything that I can try?

My intent is just to validate that the v-model of my mounted control is updated when a selection is made.

1

There are 1 answers

0
TesterDick On BEST ANSWER

I'm not sure how to attach a spy to the event, but this question How to test if a component emits an event in Vue? shows a pattern you can use.

If I take the basic HelloWorld Vue app and add a button with a similar handler

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <button @click="handleSelectionChange">Greet</button>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }, 
  methods: {
    handleSelectionChange() {
      console.log("emitting update:modelValue= ", 'abc');
      this.$emit('update:modelValue', 'abc');
    },
  }
}
</script>

The this.$emit call can be accessed via the wrapper.emitted() property (where this === wrapper)

cy.mount(HelloWorld)
  .then(({ wrapper, component }) => {

    cy.get('button').click()

    cy.then(() => {
      expect(wrapper.emitted()['update:modelValue'][0]).to.deep.eq(['abc'])
    })
  })

enter image description here