Hone logo
Hone
Problems

Vue Component Unit Testing with Vitest

This challenge focuses on building robust Vue.js applications by implementing comprehensive unit tests for a given Vue component. Writing unit tests is crucial for ensuring component functionality, preventing regressions, and facilitating confident refactoring. You will use Vitest, a modern and fast testing framework, to test a simple Vue component.

Problem Description

You are tasked with writing unit tests for a UserProfileCard Vue component. This component displays a user's name and an optional status message. The tests should cover various scenarios to ensure the component behaves as expected under different conditions.

Requirements:

  1. Component Rendering: Test that the UserProfileCard component renders correctly with provided props.
  2. Prop Handling:
    • Test that the userName prop is displayed correctly.
    • Test that the statusMessage prop is displayed when provided.
    • Test that the statusMessage is not displayed when it's an empty string or null/undefined.
  3. Interactivity (Optional but Recommended):
    • If the component had a hypothetical button to "Toggle Status", you would test that clicking it updates some internal state or emits an event. (For this specific challenge, we'll focus on rendering and prop handling, but consider this for future expansion).
  4. Test Framework: Use Vitest for writing and running your unit tests.
  5. Vue Test Utils: Utilize @vue/test-utils for mounting and interacting with your Vue components in tests.

Expected Behavior:

  • When userName is provided, it should be visible in the rendered output.
  • When statusMessage is provided and not empty, it should be visible.
  • When statusMessage is an empty string, null, or undefined, the corresponding area for the status message should not be rendered.

Edge Cases to Consider:

  • What happens if userName is an empty string?
  • What happens if statusMessage is an empty string?

Examples

Let's assume the UserProfileCard component has the following structure:

<script setup lang="ts">
import { computed } from 'vue';

interface Props {
  userName: string;
  statusMessage?: string | null;
}

const props = defineProps<Props>();

const hasStatus = computed(() => !!props.statusMessage);
</script>

<template>
  <div class="user-profile-card">
    <h2>{{ props.userName }}</h2>
    <p v-if="hasStatus" class="status-message">{{ props.statusMessage }}</p>
  </div>
</template>

<style scoped>
.user-profile-card {
  border: 1px solid #ccc;
  padding: 16px;
  border-radius: 8px;
}
.status-message {
  color: gray;
  font-size: 0.9em;
}
</style>

Example 1:

  • Input:
    <UserProfileCard userName="Alice" statusMessage="Online" />
    
  • Output: The rendered component should contain:
    • An <h2> tag with the text "Alice".
    • A <p> tag with the class status-message and the text "Online".
  • Explanation: Both userName and statusMessage are provided and valid, so both should be displayed.

Example 2:

  • Input:
    <UserProfileCard userName="Bob" />
    
  • Output: The rendered component should contain:
    • An <h2> tag with the text "Bob".
    • No <p> tag with the class status-message.
  • Explanation: userName is provided, but statusMessage is undefined (not provided), so only the user name is displayed.

Example 3 (Edge Case):

  • Input:
    <UserProfileCard userName="Charlie" statusMessage="" />
    
  • Output: The rendered component should contain:
    • An <h2> tag with the text "Charlie".
    • No <p> tag with the class status-message.
  • Explanation: Although statusMessage is provided, it's an empty string. The component's logic (v-if="hasStatus") correctly prevents the status message from being rendered in this case.

Constraints

  • All tests must pass for the solution to be considered complete.
  • Tests should be written in TypeScript.
  • You are expected to set up Vitest and @vue/test-utils in your project. Assume a standard Vue 3 setup with Vite.
  • The focus is on correctness and readability of the tests. Performance is secondary but generally good with Vitest.

Notes

  • You will need to install Vitest and @vue/test-utils as development dependencies.
  • Consider how to import and mount your UserProfileCard component within your test files.
  • @vue/test-utils provides methods like mount, findAll, find, text(), exists(), etc., which will be very useful.
  • Think about the different ways to assert that elements are present or absent, and that their content is correct.
  • For testing components with setup syntax (as in the example above), mount from @vue/test-utils is generally the preferred way to render.
  • Remember to mock any external dependencies if your component were to have them (though this example is self-contained).
Loading editor...
typescript