ChrisSannar
ChrisSannar

Reputation: 151

Vue Typescript Component Jest Testing doesn't render values in html

I'm attempting to focus on TDD with Typescript and so I built a new Vue project with the vue-cli (I selected to use Vue3, Typescript, and Jest). However when I ran the unit test out of the box it failed. After some investigation I found that the mount command from @vue/test-utils doesn't render any of the prop values:

HelloWorld.vue

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    {{ test }}
  </div>
</template>

<script lang="ts">
import { Options, Vue } from "vue-class-component";

@Options({
  props: {
    msg: String,
  }
})
export default class HelloWorld extends Vue {
  msg!: string;
  test: string = "It's a test";
}
</script>

example.specs.ts

import { mount } from "@vue/test-utils";
import HelloWorld from "@/components/HelloWorld.vue";

describe("HelloWorld.vue", () => {
  it("renders props.msg when passed", async () => {
    const msg = "new message";
    const wrapper = mount(HelloWorld, {
      props: { msg }
    });
    
    expect(wrapper.text()).toContain(msg);
  });
});

When I print wrapper.html() I get the following:

<div class="hello" msg="new message"><h1></h1></div>

It doesn't seem to be rendering msg or test at all into the html. It has it listed as a prop, but that's about it.

I think one of the causes might be that I'm using a Typescript component instead of a traditional which might throw it off, but I'm not sure.

Any advice/tips?

Upvotes: 0

Views: 1380

Answers (3)

Stijn Smits
Stijn Smits

Reputation: 11

This problem was tracked to vue-jest. Just made a fix. https://github.com/vuejs/vue-jest/pull/299

Upvotes: 1

ChrisSannar
ChrisSannar

Reputation: 151

So this didn't exactly fix the problem, but it's an alternative method that I'm going to try: Instead of using class based components I went more for the functional based with the typescript implementation.

HelloWorld.vue

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    {{ test }}
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  name: "HelloWorld",
  props: {
    msg: String
  },
  data() {
    return {
      test: "It's a test" as string
    }
  }
});
</script>

Upvotes: 0

devdgehog
devdgehog

Reputation: 625

  1. Your HelloWorld component is not detected as a component, this is how you need to define it:

    @Component
    export default class HelloWorld extends Vue {
      @Prop() msg!: string;
    

@Component tells the compiler its a component.

@Prop() tells the compiler the msg property is a prop.

  1. Use propsData as mount options or use setProps documentation link:

    const wrapper = mount(HelloWorld, {
      propsData: {
        msg, // or msg: msg, 
      },
    });
    

Result:

  console.log tests/unit/example.spec.ts:13
    <div class="hello">
      <h1>
        new message
      </h1>
      It's a test
    </div>

Upvotes: 0

Related Questions