Hone logo
Hone
Problems

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:

  1. 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 itemSelected event should emit a payload containing the id and name of an item (you can hardcode these for simplicity, e.g., id: 1, name: 'Sample Item').
  2. 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 itemSelected event was emitted.
    • Assert that the emitted event's payload matches the expected id and name.
    • 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 defineEmits in Vue 3.
  • Understand how to use mount from 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 await when simulating user interactions.
Loading editor...
typescript