Skip to content

Commit 4d030bb

Browse files
authored
Merge pull request #296 from cuixiaorui/master
refactor: use devtools realize emit
2 parents 4c959da + 4e43570 commit 4d030bb

File tree

7 files changed

+67
-55
lines changed

7 files changed

+67
-55
lines changed

src/emit.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { setDevtoolsHook, devtools } from 'vue'
2+
3+
const enum DevtoolsHooks {
4+
COMPONENT_EMIT = 'component:emit'
5+
}
6+
7+
let events: Record<string, unknown[]>
8+
9+
export function emitted<T = unknown>(
10+
eventName?: string
11+
): T[] | Record<string, T[]> {
12+
if (eventName) {
13+
const emitted = (events as Record<string, T[]>)[eventName]
14+
return emitted
15+
}
16+
17+
return events as Record<string, T[]>
18+
}
19+
20+
export const attachEmitListener = () => {
21+
events = {}
22+
// use devtools to capture this "emit"
23+
setDevtoolsHook(createDevTools(events))
24+
}
25+
26+
function createDevTools(events): any {
27+
const devTools: Partial<typeof devtools> = {
28+
emit(eventType, ...payload) {
29+
if (eventType !== DevtoolsHooks.COMPONENT_EMIT) return
30+
31+
// The first argument is root component
32+
// The second argument is vm
33+
// The third argument is event
34+
// The fourth argument is args of event
35+
recordEvent(events, payload[2], payload[3])
36+
}
37+
}
38+
39+
return devTools
40+
}
41+
42+
function recordEvent(events, event, args) {
43+
// Record the event message sent by the emit
44+
events[event]
45+
? (events[event] = [...events[event], [...args]])
46+
: (events[event] = [[...args]])
47+
}

src/emitMixin.ts

Lines changed: 0 additions & 34 deletions
This file was deleted.

src/mount.ts

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import {
3232
} from './utils'
3333
import { processSlot } from './utils/compileSlots'
3434
import { createWrapper, VueWrapper } from './vueWrapper'
35-
import { attachEmitListener } from './emitMixin'
35+
import { attachEmitListener } from './emit'
3636
import { createDataMixin } from './dataMixin'
3737
import { MOUNT_COMPONENT_REF, MOUNT_PARENT_NAME } from './constants'
3838
import { createStub, stubComponents } from './stubs'
@@ -233,16 +233,8 @@ export function mount(
233233
let component
234234

235235
if (isFunctionalComponent(originalComponent)) {
236-
// we need to wrap it like this so we can capture emitted events.
237-
// we capture events using a mixin that mutates `emit` in `beforeCreate`,
238-
// but functional components do not support mixins, so we need to wrap it
239-
// and make it a non-functional component for testing purposes.
240236
component = defineComponent({
241-
setup: (_, { attrs, slots, emit }) => () => {
242-
return h((props: any, ctx: any) =>
243-
originalComponent(props, { ...ctx, ...attrs, emit, slots })
244-
)
245-
}
237+
setup: (_, { attrs, slots }) => () => h(originalComponent, attrs, slots)
246238
})
247239
} else if (isObjectComponent(originalComponent)) {
248240
component = { ...originalComponent }
@@ -346,6 +338,9 @@ export function mount(
346338
return vm.$nextTick()
347339
}
348340

341+
// add tracking for emitted events
342+
attachEmitListener()
343+
349344
// create the app
350345
const app = createApp(Parent)
351346

@@ -408,9 +403,6 @@ export function mount(
408403
}
409404
}
410405

411-
// add tracking for emitted events
412-
app.mixin(attachEmitListener())
413-
414406
// stubs
415407
// even if we are using `mount`, we will still
416408
// stub out Transition and Transition Group by default.

src/vueWrapper.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { createWrapperError } from './errorWrapper'
88
import { TriggerOptions } from './createDomEvent'
99
import { find, matches } from './utils/find'
1010
import { mergeDeep } from './utils'
11+
import { emitted } from './emit'
1112

1213
export class VueWrapper<T extends ComponentPublicInstance> {
1314
private componentVM: T
@@ -72,12 +73,7 @@ export class VueWrapper<T extends ComponentPublicInstance> {
7273
emitted<T = unknown>(): Record<string, T[]>
7374
emitted<T = unknown>(eventName?: string): T[]
7475
emitted<T = unknown>(eventName?: string): T[] | Record<string, T[]> {
75-
if (eventName) {
76-
const emitted = (this.vm['__emitted'] as Record<string, T[]>)[eventName]
77-
return emitted
78-
}
79-
80-
return this.vm['__emitted'] as Record<string, T[]>
76+
return emitted(eventName)
8177
}
8278

8379
html() {

tests/emit.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,14 @@ describe('emitted', () => {
154154
expect(wrapper.emitted('hello')).toHaveLength(1)
155155
expect(wrapper.emitted('hello')[0]).toEqual(['foo', 'bar'])
156156
})
157+
158+
it('captures an event emitted in setup', () => {
159+
const Comp = {
160+
setup(_, { emit }) {
161+
emit('foo')
162+
}
163+
}
164+
const wrapper = mount(Comp)
165+
expect(wrapper.emitted().foo).toBeTruthy()
166+
})
157167
})

tests/mountingOptions/props.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ describe('mountingOptions.props', () => {
7272

7373
test('assigns event listeners', async () => {
7474
const Component = {
75+
emits: ['customEvent'],
7576
template: '<button @click="$emit(\'customEvent\', true)">Click</button>'
7677
}
7778
const onCustomEvent = jest.fn()

tests/setValue.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,12 +180,12 @@ describe('setValue', () => {
180180

181181
describe('on component instance', () => {
182182
const PlainInputComponent = defineComponent({
183-
props: ['modelValue'],
183+
props: ['modelValue', 'onUpdate:modelValue'],
184184
template: '<div>{{ modelValue }}</div>'
185185
})
186186

187187
const MultiInputComponent = defineComponent({
188-
props: ['foo', 'bar'],
188+
props: ['foo', 'bar', 'onUpdate:bar', 'onUpdate:foo'],
189189
template: '<div>{{ foo }} {{ bar }}</div>'
190190
})
191191

0 commit comments

Comments
 (0)