cypresscypress-component-test-runnercypress-intercept

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


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.


Solution

  • 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