0

I'd like to write a Jest test for a Vue component, which renders a subcomponent. The component looks like this:

<template>
  <div class="add-to-cart-position">
    <a :href="item.url">
      <picture-comp
        class="add-to-cart-position__image"
        :srcset-mobile="item.imageUrlMobile"
        :srcset-desktop="item.imageUrl"
      />
    </a>
  </div>
</template>

<script lang="ts">
  import {Vue, Component, Prop} from 'vue-property-decorator';
  import BasketItem from '../interfaces/BasketItem';
  import PictureComp from '../pictureComp/pictureComp.vue';

  @Component({
    name: 'add-to-cart-position',
    components: {
      PictureComp
    }
  })
  export default class AddToCartPosition extends Vue {
    @Prop()
    item: BasketItem;
  }
</script>

According to the docs I can use shallowMount to automatically stub all subcomponents, which is exactly what I want. So my test looks like this:

import {shallowMount} from '@vue/test-utils';
import AddToCartPosition from 'AddToCartPosition.vue';
import {mockBasketItem} from '/__mocks__/data/basketItem.mock';

describe('addToCartPosition', () => {
  const wrapper = shallowMount(AddToCartPosition, {
    propsData: {
      basketItem: mockBasketItem()
    }
  });

  it('matches the snapshot', () => {
    expect(wrapper.html()).toMatchSnapshot();
  });
});

But when I run this test I get an error and the error is in the PictureComp subcomponent, which should not be rendered at all. Why does the automatic stubbing not work?

I also tried mount and manual stubbing, but it does not change anything. The error message stays the same.

Error message:

Test suite failed to run

TypeError: Object prototype may only be an Object or null: undefined
    at setPrototypeOf (<anonymous>)

  34 |       >
  35 |       <source
> 36 |         :srcset="srcLg"
     |            ^
  37 |         media="(min-width: 767px)"
  38 |       >
  39 |       <img

  at extendStatics (pictureComp/pictureComp.vue:36:12)
  at Object.<anonymous>.__extends (pictureComp/pictureComp.vue:40:5)
  at pictureComp/pictureComp.vue:62:1
  at pictureComp/pictureComp.vue:105:1
  at Object.<anonymous> (pictureComp/pictureComp.vue:137:3)
  at addToCartPosition/addToCartPosition.vue:70:1
  at Object.<anonymous> (addToCartPosition/addToCartPosition.vue:106:3)
  at Object.<anonymous> (test/components/addToCartPosition.test.ts:2:1)
Reynicke
  • 1,407
  • 1
  • 11
  • 21
  • 1
    It's not evident that the error occurs because pictureComp renders. Since you're using shallowMount, I expect it not to. The error likely occurs on pictureComp import and there's nothing shallowMount can help with. Please, provide pictureComp.vue because it's relevant. – Estus Flask May 18 '20 at 10:16
  • This is correct. The error was indeed in the subcomponent - not while rendering it but at import time. The error message is just very, very misleading. – Reynicke May 18 '20 at 11:00
  • Glad you sorted this out. extendStatics and setPrototypeOf suggest that this happens when a class is defined. Makes sense since you're using class components. – Estus Flask May 18 '20 at 11:08

2 Answers2

0

This took me ages to understand but I eventually see what you mean by the comments on the question.

For me this was that I needed to set an environment variable as one of my modules was expecting to reference a value that did not exist.

This is checked when the Import command is run even if when you come to mount your component the import would not be required due to some form of test double.

Tom Benyon
  • 971
  • 10
  • 15
  • In my case it was a problem concerning Vue, Jest and Typescript like here: https://stackoverflow.com/questions/48992278/vue-typescript-typeerror-object-prototype-may-only-be-an-object-or-null-un/ Jest and TS don't like the Vue default export. All components need a little extra care. – Reynicke May 22 '20 at 10:12
0

This is probably because Jest doesn't know what the relation between picture-comp and PictureComp is. If this even works in Vue, then my guess is that Vue knows how to resolve kebab-case to PascalCase. At any rate, I would expect it to work if you register the component correctly:

components: {
  'picture-comp': PictureComp
}

or, use <PictureComp> instead of <picture-comp> in your template.

paddotk
  • 1,359
  • 17
  • 31