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.
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'])
})
})