Vue Component Event Emission Testing
This challenge focuses on writing robust unit tests for Vue components, specifically testing the events they emit. Testing emitted events is crucial for ensuring your components communicate correctly with their parent components, allowing for effective integration and predictable application behavior.
Problem Description
Your task is to create a Vue component that emits a custom event when a specific user interaction occurs and then write comprehensive unit tests for this component to verify that the correct event is emitted with the expected payload.
Requirements:
-
Create a Vue Component:
- Design a simple Vue 3 component using the Composition API with
<script setup>. - This component should have a button.
- When the button is clicked, the component must emit a custom event named
itemSelected. - The
itemSelectedevent should emit a payload containing theidandnameof an item (you can hardcode these for simplicity, e.g.,id: 1,name: 'Sample Item').
- Design a simple Vue 3 component using the Composition API with
-
Write Unit Tests:
- Use a testing framework like Vitest or Jest with Vue Test Utils.
- Mount the created Vue component in your tests.
- Simulate a click event on the button.
- Assert that the
itemSelectedevent was emitted. - Assert that the emitted event's payload matches the expected
idandname. - Test that no other events are emitted.
Expected Behavior:
When the button within the component is clicked, the itemSelected event should be triggered, carrying the specified item data. The tests should confirm this emission and payload.
Edge Cases:
- Consider what happens if the button is clicked multiple times (though for this basic scenario, simply confirming the last emission is sufficient).
- Ensure your tests are isolated and don't interfere with each other.
Examples
Example 1: Successful Event Emission
// Component: ItemSelector.vue
<template>
<button @click="selectItem">Select Item</button>
</template>
<script setup lang="ts">
import { defineEmits } from 'vue';
const emit = defineEmits(['itemSelected']);
const selectItem = () => {
emit('itemSelected', { id: 1, name: 'Sample Item' });
};
</script>
// Test File: ItemSelector.spec.ts
import { mount } from '@vue/test-utils';
import ItemSelector from './ItemSelector.vue';
describe('ItemSelector', () => {
it('emits itemSelected event with correct payload on button click', async () => {
const wrapper = mount(ItemSelector);
const button = wrapper.find('button');
await button.trigger('click');
// Assert that the event was emitted
expect(wrapper.emitted('itemSelected')).toBeTruthy();
// Assert the number of times the event was emitted
expect(wrapper.emitted('itemSelected')!.length).toBe(1);
// Assert the payload of the emitted event
const emittedPayload = wrapper.emitted('itemSelected')![0][0]; // [0] for the event, [0] for the first argument (payload)
expect(emittedPayload).toEqual({ id: 1, name: 'Sample Item' });
});
it('does not emit any other events', async () => {
const wrapper = mount(ItemSelector);
const button = wrapper.find('button');
await button.trigger('click');
// Check that only 'itemSelected' was emitted
expect(Object.keys(wrapper.emitted())).toEqual(['itemSelected']);
});
});
Explanation:
The ItemSelector.vue component emits itemSelected with { id: 1, name: 'Sample Item' } when its button is clicked. The tests mount this component, simulate a click, and then assert that the itemSelected event was emitted exactly once with the correct payload. It also verifies that no other events were emitted.
Constraints
- The Vue component should be written in Vue 3 with the Composition API and
<script setup>. - Tests should be written in TypeScript.
- Use a standard Vue testing utility library like Vue Test Utils.
- Ensure tests are asynchronous where event triggering and subsequent assertions are concerned (use
await).
Notes
- Familiarize yourself with
defineEmitsin Vue 3. - Understand how to use
mountfrom Vue Test Utils to render components. - Pay close attention to how to access emitted events and their payloads using
wrapper.emitted(). - Remember to handle asynchronous operations correctly using
awaitwhen simulating user interactions.