Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/emitted events cache #1449

Merged
merged 1 commit into from Apr 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/emit.ts
Expand Up @@ -11,7 +11,7 @@ const enum DevtoolsHooks {
COMPONENT_EMIT = 'component:emit'
}

let events: Events
let events: Events = {}

export function emitted<T = unknown>(
vm: ComponentPublicInstance,
Expand All @@ -28,7 +28,6 @@ export function emitted<T = unknown>(
}

export const attachEmitListener = () => {
events = {}
// use devtools to capture this "emit"
setDevtoolsHook(createDevTools(events), {})
}
Expand Down Expand Up @@ -65,3 +64,8 @@ export const recordEvent = (
// Record the event message sent by the emit
events[cid][event].push(args)
}

export const removeEventHistory = (vm: ComponentPublicInstance): void => {
const cid = vm.$.uid
delete events[cid]
}
4 changes: 3 additions & 1 deletion src/vueWrapper.ts
Expand Up @@ -13,7 +13,7 @@ import domEvents from './constants/dom-events'
import { VueElement, VueNode } from './types'
import { mergeDeep } from './utils'
import { getRootNodes } from './utils/getRootNodes'
import { emitted, recordEvent } from './emit'
import { emitted, recordEvent, removeEventHistory } from './emit'
import BaseWrapper from './baseWrapper'
import type { DOMWrapper } from './domWrapper'
import {
Expand Down Expand Up @@ -182,6 +182,8 @@ export class VueWrapper<
`wrapper.unmount() can only be called by the root wrapper`
)
}
// Clear emitted events cache for this component instance
removeEventHistory(this.vm)

this.__app.unmount()
}
Expand Down
31 changes: 31 additions & 0 deletions tests/emit.spec.ts
Expand Up @@ -364,4 +364,35 @@ describe('emitted', () => {
expect(wrapper.emitted().bar[0]).toEqual(['mounted'])
expect(wrapper.emitted().bar[1]).toEqual(['click'])
})

it('does not clear all emitted event history on mount/unmount', async () => {
const Foo = defineComponent({
name: 'Foo',
emits: ['foo'],
setup(_, ctx) {
return () =>
h(
'div',
{
onClick: () => {
ctx.emit('foo', 'bar')
}
},
'hello world'
)
}
})

const wrapper1 = mount(Foo)
await wrapper1.trigger('click')
expect(wrapper1.emitted('foo')).toHaveLength(1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also assert

expect(wrapper2.emitted('foo')).toHaveLength(0)

Here as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would have to wait until after wrapper2 is mounted. We can do that, but the ultimate point of the test is to ensure that subsequent mounts no longer clear the emit history for previously mounted components.


const wrapper2 = mount(Foo)
await wrapper2.trigger('click')
expect(wrapper2.emitted('foo')).toHaveLength(1)
expect(wrapper1.emitted('foo')).toHaveLength(1) // ensuring that subsequent mount does not clear event history for other wrappers

wrapper1.unmount()
wrapper2.unmount()
})
})