question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Recommended implementation for writing unit tests with villus

See original GitHub issue

I’m trying to write unit tests in Jest for my Vue application, but I’m running into problems because of Villus, and I’m not entirely sure how I should go about mocking things like useMutation and useQuery. Any tips?

This is the error I’m getting:

  ● GameCard.vue › renders platforms and developers when passed

    Cannot detect villus Client, did you forget to call `useClient`?

      57 |     });
      58 |
    > 59 |     const { execute: executeFavoriteGame } = useMutation(FavoriteGameDocument);

The Jest test looks like this:

import { createLocalVue, mount } from '@vue/test-utils'
import GameCard from '@/components/GameCard.vue'

const localVue = createLocalVue();

describe('GameCard.vue', () => {
  it('renders platforms and developers when passed', () => {
    const wrapper = mount(GameCard, {
      stubs: ['router-link', 'router-view'],
      localVue,
      propsData: {
        game: {
          id: 1,
          platforms: {
            nodes: [
              {
                id: 1,
                name: 'Nintendo Switch'
              }
            ]
          },
          developers: {
            nodes: [
              {
                id: 1,
                name: 'Valve'
              }
            ]
          },
          isFavorited: true
        }
      }
    })
    expect(wrapper.text()).toMatch('Nintendo Switch')
  })
})

and my component looks like this:

<template>
  <div class="custom-card game-card">
    <router-link :to="{ name: 'Game', params: { id: game.id } }" class="card-container">
      <figure class="game-cover">
        <img v-if="game.coverUrl !== null" :src="game.coverUrl" />
        <img v-else src="@/assets/images/no-cover.png"/>
      </figure>
      <div class="card-content">
        <p class="title is-4 mr-10">{{ game.name }}</p>
        <p class="subtitle is-6" v-if="platforms !== null">{{ platforms }}</p>
        <p class="subtitle is-6" v-if="developers !== null">{{ developers }}</p>
      </div>
    </router-link>

    <!-- Game card Dropdown -->
    <div class="dropdown dropdown-dynamic game-card-dropdown is-right" :class="{ 'is-active': isActive }" v-if="userSignedIn">
      <div class="dropdown-trigger">
        <button class="button is-borderless is-shadowless" aria-haspopup="true" aria-controls="dropdown-menu" @click="toggleActive">
          <SvgIcon :name="'chevron-down'" :classes="['icon']" :size="15" />
        </button>
      </div>
      <div class="dropdown-menu" id="dropdown-menu" role="menu">
        <div class="dropdown-content">
          <a v-if="game.isFavorited || localIsFavorited" class="dropdown-item" @click="unfavoriteGame">Unfavorite</a>
          <a v-else class="dropdown-item" @click="favoriteGame">Favorite</a>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { Company, FavoriteGameDocument, Platform, UnfavoriteGameDocument } from '@/generated/graphql';
import { computed, defineComponent, ref } from '@vue/composition-api';
import SvgIcon from '@/components/SvgIcon.vue';
import { useMutation } from 'villus';

export default defineComponent({
  name: 'GameCard',
  components: {
    SvgIcon
  },
  props: {
    game: {
      required: true,
      type: Object
    }
  },
  setup(props, context) {
    const platforms = computed(() => {
      if (props.game.platforms.nodes.size === 0) { return null; }
      return props.game.platforms.nodes.map((p: Platform) => p.name).join(', ');
    });
    const developers = computed(() => {
      if (props.game.developers.nodes.size === 0) { return null; }
      return props.game.developers.nodes.map((d: Company) => d.name).join(', ');
    });

    const { execute: executeFavoriteGame } = useMutation(FavoriteGameDocument);
    const { execute: executeUnfavoriteGame } = useMutation(UnfavoriteGameDocument);

    let isActive = ref<boolean>(false);

    // Tracks whether the game has been favorited, will be toggled when the
    // mutation is executed so we don't have to reload the game record.
    let localIsFavorited = ref<boolean>(props.game.isFavorited);

    const favoriteGame = () => {
      executeFavoriteGame({ id: props.game.id }).then(() => {
        toggleActive();
        localIsFavorited.value = true;
      });
    };

    const unfavoriteGame = () => {
      executeUnfavoriteGame({ id: props.game.id }).then(() => {
        toggleActive();
        localIsFavorited.value = false;
      });
    };

    const toggleActive = () => isActive.value = !isActive.value;

    const userSignedIn = computed(() => {
      return context.root.$store.state.userSignedIn;
    });

    return {
      isActive,
      platforms,
      developers,
      favoriteGame,
      unfavoriteGame,
      toggleActive,
      userSignedIn,
      localIsFavorited
    };
  }
});
</script>

I’m using Vue 2.x with TypeScript and @vue/composition-api.

See similar docs for Apollo: https://apollo.vuejs.org/guide/testing.html#testing

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
logaretmcommented, Apr 25, 2021

I’ve added an initial testing guide, it might be missing a lot so let me know what is missing and I will try adding it. It should have an example for you.

https://villus.logaretm.com/guide/testing

1reaction
logaretmcommented, Mar 16, 2021

Yea, I think it is important to have a testing guide, I will give you some quick tips here.

  • Check villus own tests
  • I don’t mock fetch or any network calls, I actually prefer to mock a server using mswjs
  • I use wait-for-expect to perform assertions as network requests usually have a delay and hard to wait for them with flush-promises or a timeout.
  • Inject villus client with global.provides, the VILLUS_CLIENT symbol is exported just for that.

I will work around adding a testing guide this week probably.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Writing Tests - villus
In this guide, you will find some recommendations and examples on how to write unit tests for components using villus . Testing tools...
Read more >
Unit Tests, How to Write Testable Code, and Why It Matters
In this article, I will show that unit testing itself is quite easy; the real problems that complicate unit testing, and introduce expensive...
Read more >
Get started with unit testing - Visual Studio (Windows)
Use Visual Studio to define and run unit tests to maintain code health, and to find errors and faults before your customers do....
Read more >
Unit Testing Best Practices: 9 to Ensure You Do It Right
Do you know any unit testing best practice? In this post, you'll learn nine of them so you can get started the right...
Read more >
All about unit testing: 11 best practices and overview
1. Write tests for a number of scenarios · 2. Write good test names · 3. Set up automated tests · 4. Write...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found