From 193a0f402b4c7e51c1c7e79216f6269968915e9b Mon Sep 17 00:00:00 2001 From: Brett Largent Date: Fri, 22 Apr 2022 10:50:02 -0500 Subject: [PATCH] fix: removing events cache clearing inside attachEmitListener method Refactoring attachEmitListener function to not clear entire emitted events history on every call. A new removeEventHistory has been exposed and added to the unmount method logic so that specific emit history will be cleared on wrapper unmount. Unit testing has been added as well to show that the bug has been fixed. fixes issue #1445 --- src/emit.ts | 8 ++++++-- src/vueWrapper.ts | 4 +++- tests/emit.spec.ts | 31 +++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/emit.ts b/src/emit.ts index 25a08ee4f..bfe29e912 100644 --- a/src/emit.ts +++ b/src/emit.ts @@ -11,7 +11,7 @@ const enum DevtoolsHooks { COMPONENT_EMIT = 'component:emit' } -let events: Events +let events: Events = {} export function emitted( vm: ComponentPublicInstance, @@ -28,7 +28,6 @@ export function emitted( } export const attachEmitListener = () => { - events = {} // use devtools to capture this "emit" setDevtoolsHook(createDevTools(events), {}) } @@ -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] +} diff --git a/src/vueWrapper.ts b/src/vueWrapper.ts index f789cdd16..f45c7f604 100644 --- a/src/vueWrapper.ts +++ b/src/vueWrapper.ts @@ -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 { @@ -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() } diff --git a/tests/emit.spec.ts b/tests/emit.spec.ts index cb057f76c..404d01832 100644 --- a/tests/emit.spec.ts +++ b/tests/emit.spec.ts @@ -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) + + 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() + }) })