Vue: emitted custom event not triggering spy #25198
-
I have a problem wherein a spy passed to a component Setup: // support/component.ts
type MountParams = Parameters<typeof mount>
type OptionsParam = MountParams[ 1 ] & { router? : Router }
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace Cypress {
interface Chainable {
/**
* Helper mount function for Vue Components
*
* @param component Vue Component or JSX Element to mount
* @param options Options passed to Vue Test Utils
*
*/
mount( component : any , options? : OptionsParam ) : Chainable<any>
}
}
}
Cypress.Commands.add( 'mount' , ( component , options = {} ) => {
options.global = options.global || {}
options.global.plugins = options.global.plugins || []
if ( !options.router ) {
options.router = createRouter( {
routes : routes
, history : createMemoryHistory()
} )
}
options.global.plugins.push( {
install( app ) {
app.use( options.router as never )
app.use( i18n )
}
} )
return mount( component , options )
} ) This works (some code omitted: // B.cy.ts
it( 'emits a event `click` when clicked' , () => {
const clickSpy = cy.spy().as( 'clickSpy' )
cy.mount( PrimaryBtnComponent
, {
props : {
onClick : clickSpy
}
} )
cy.get( 'button' )
.click()
cy.get( '@clickSpy' )
.should( 'have.been.calledOnce' )
} ) // B.vue
<script setup lang="ts">
defineEmits<{
( e : 'click', value: void ) : void
}>()
</script>
<template>
<button
@click="$emit( 'click' )"
>
</template> This does not work: // A.cy.ts
it( 'emits a single `deleteField` event when field delete button pressed' , function() {
const onFieldDeletedSpy = cy.spy().as( 'onFieldDeletedSpy' )
cy.mount( CustConfigFormComponent
, {
props : {
...
, deleteField: onFieldDeletedSpy
}
} )
cy.get( '[data-cy=company-8-fields]' )
.first()
.scrollIntoView()
.click()
cy.contains( 'Remove Field' )
.first()
.click()
cy.get( '@onFieldDeletedSpy' )
.should( 'have.been.calledOnce' )
} ) // A.vue
<script lang="ts">
export default {
inheritAttrs : false
}
</script>
<script setup lang="ts">
const emit = defineEmits<{
( e : 'deleteField' value : FieldDeleted : void
}>()
const onFieldDeleted = ( e : FieldDeleted ) : void => {
console.log( e )
emit( 'deleteField' , e )
}
</script>
<template>
<FieldConfigAccordionComponent
@delete-field="onFieldDeleted"
/>
</template> Result: The goal of this test is to ensure that the component in question emits a single event on a certain button press. The event destination is this component's parent level, so on this level, I have no result to verify. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 6 replies
-
For anyone else in the same situation, I've managed to solve this by rewriting the assertion as such: cy.contains( 'Remove Field' )
.first()
.click()
.then( () => {
cy.wrap( Cypress.vueWrapper.emitted( 'deleteField') ).should( 'have.length' , 1 )
} ) Source: https://stackoverflow.com/a/70213943/7041984 However, I'm still curious as to why this approach works where my original one did not, and where it's documented. |
Beta Was this translation helpful? Give feedback.
For anyone else in the same situation, I've managed to solve this by rewriting the assertion as such:
Source: https://stackoverflow.com/a/70213943/7041984
However, I'm still curious as to why this approach works where my original one did not, and where it's documented.