Невозможно отобразить Vue компонент в моем модульном тесте с Jest - PullRequest
0 голосов
/ 28 февраля 2020

Я пытаюсь визуализировать компонент в моем Vue модульном тесте с помощью Jest, но я не могу заставить его работать.

В журналах написано: TypeError: Cannot read property 'length' of null

Я пробовал другие компоненты, и он отлично работает.

ErrandsListTable. vue

<template>
  <div
    v-if="!error"
    class="flex-table flex-table--white-background flex-table--green-header flex-table--with-dropdown"
    :class="{ loading: loading }"
  >
    <div class="flex-table__row flex-table--header text--level-6">
      <div class="flex-table__cell flex-table__cell--width-3">
        {{ statusHeader }}
      </div>
      <div class="flex-table__cell flex-table__cell--width-3">
        {{ idHeader }}
      </div>
      <div class="flex-table__cell flex-table__cell--width-7">
        {{ descriptionHeader }}
      </div>
      <div class="flex-table__cell flex-table__cell--width-5">
        {{ typeHeader }}
      </div>
      <div class="flex-table__cell flex-table__cell--width-3">
        {{ dateOpenedHeader }}
      </div>
      <div class="flex-table__cell flex-table__cell--width-3">
        {{ dateClosedHeader }}
      </div>
      <div class="flex-table__cell flex-table__cell--width-1" />
    </div>

    <div
      v-for="(errand, index) in sliceArray(errands)"
      :key="!errand.id ? index : errand.id"
    >
      <div
        class="flex-table__row"
        :class="{ 'flex-table__row--closed': index !== selectedErrand }"
        @click="toggleExpanded(index)"
      >
        <div class="flex-table__cell flex-table__cell--width-3">
          {{ errand.status }}
        </div>
        <div class="flex-table__cell flex-table__cell--width-3">
          {{ errand.id }}
        </div>
        <div
          class="flex-table__cell flex-table__cell--width-7 flex-table__cell--show-on-mobile"
          :data-header="descriptionHeader"
        >
          {{ errand.description }}
        </div>
        <div class="flex-table__cell flex-table__cell--width-5">
          {{ errand.type }}
        </div>
        <div
          class="flex-table__cell flex-table__cell--width-3 flex-table__cell--show-on-mobile"
          :data-header="dateOpenedHeader"
        >
          {{ errand.orderDate }}
        </div>
        <div class="flex-table__cell flex-table__cell--width-3">
          {{ errand.deliveryDate }}
        </div>
        <div
          class="flex-table__cell flex-table__cell--width-1 flex-table__cell--dropdown-show-on-mobile"
        >
          <i
            class="icon-angle__small"
            :class="{ 'icon-angle__small--down': selectedErrand === index }"
          />
        </div>
      </div>

      <ErrandsListDetails
        v-if="selectedErrand >= 0 && selectedErrand === index"
        :errand="errand"
        v-bind="$props"
      />
    </div>

    <div
      v-if="errands.length >= numberOfErrandsLoaded"
      class="flex-table--load-more text--level-5"
    >
      <a href="#" @click="loadMore">
        {{ showMoreText }}
        <i class="icon-down" />
      </a>
    </div>
    <div
      v-if="errands.length < 1 && !loading"
      class="flex-table--error text--level-5"
    >
      {{ noCasesText }}
    </div>
    <div v-if="error && !loading" class="flex-table--error text--level-5">
      {{ errorText }}
    </div>
  </div>
</template>

<script>
import _ from "lodash";
import ErrandsListDetails from "./ErrandsListDetails.vue";

export default {
  components: {
    ErrandsListDetails: ErrandsListDetails
  },
  props: {
    componentTitle: {
      type: String,
      default: () => {
        return "";
      }
    },
    showMoreText: {
      type: String,
      default: "Visa fler ärenden"
    },
    statusHeader: {
      type: String,
      default: () => {
        return "Status";
      }
    },
    dateOpenedHeader: {
      type: String,
      default: () => {
        return "Beställt/Anmält";
      }
    },
    dateClosedHeader: {
      type: String,
      default: () => {
        return "Beräknad klar";
      }
    },
    idHeader: {
      type: String,
      default: () => {
        return "Ärendenummer";
      }
    },
    descriptionHeader: {
      type: String,
      default: () => {
        return "Beskrivning";
      }
    },
    typeHeader: {
      type: String,
      default: () => {
        return "Typ";
      }
    },
    fileDetails: {
      type: String,
      default: () => {
        return "Ladda ned beställningen som PDF:";
      }
    },
    commentsDetails: {
      type: String,
      default: () => {
        return "Noteringar";
      }
    },
    wordList: {
      type: String,
      default: () => {
        return "";
      }
    },
    attachment: {
      type: String,
      default: () => {
        return "";
      }
    },
    noCasesText: {
      type: String,
      default: () => {
        return "Det finns inget att visa";
      }
    },
    errorText: {
      type: String,
      default: () => {
        return "Något gick fel";
      }
    },
    createdOnFallback: {
      type: String,
      default: () => {
        return "-";
      }
    },
    closedOnFallback: {
      type: String,
      default: () => {
        return "-";
      }
    },
    errandsCounter: {
      type: Object,
      default: () => {
        return null;
      }
    },
    errands: {
      type: Array,
      default: () => {
        return null;
      }
    },
    loading: {
      type: Boolean,
      default: () => {
        return false;
      }
    }
  },
  data() {
    return {
      selectedErrand: -1,
      error: undefined,
      numberOfErrandsLoaded: 10
    };
  },
  methods: {
    toggleExpanded: function(index) {
      this.selectedErrand = this.selectedErrand === index ? -1 : index;
    },

    loadMore: function(event) {
      event.preventDefault();
      this.numberOfErrandsLoaded += 10;
    },

    sliceArray: function(array) {
      let val = _.orderBy(array, "orderDate", "desc");
      return val.slice(0, this.numberOfErrandsLoaded);
    }
  }
};
</script>

Также игнорируйте тот факт, что этот компонент не выполнен и может не обязательно включать наиболее подходящие варианты использования для модульных тестов. Мне просто любопытно узнать, почему этот определенный компонент не может быть загружен в качестве экземпляра Vue в моем тесте?

import { shallowMount } from "@vue/test-utils";
import ErrandsListTable from "../ErrandsListTable.vue";

let wrapper;

describe("Errandslist table", () => {
  beforeEach(() => {
    wrapper = shallowMount(ErrandsListTable);
  });

  afterEach(() => {
    wrapper.destroy();
  });
  it("is a Vue instance", () => {
    expect(wrapper.isVueInstance).toBeTruthy();
  });
});

У кого-нибудь была такая же проблема? Если так, может кто-нибудь объяснить мне, как вы решили это?

Ответы [ 2 ]

1 голос
/ 28 февраля 2020

В вашем шаблоне ваш массив errands равен нулю, поэтому вы не можете получить доступ к свойству длины. Вы должны либо обработать этот случай в своем компоненте, либо передать это свойство компоненту.

установить значение по умолчанию

errands: {
  type: Array,
  default: () => {
    return [];
  }
}

передать значение по умолчанию значение во время теста

const wrapper = shallowMount(ErrandsListTable, {
  propsData: {
    errands: []
  }
})
expect(wrapper.props().errands.length).toBe(0)
1 голос
/ 28 февраля 2020

Значение по умолчанию errands prop равно null. Поскольку вы монтируете свой компонент без каких-либо подпорок, действует значение по умолчанию null. Ваш шаблон имеет errands.length, что приводит к появившейся ошибке.

Чтобы устранить ошибку, вы можете либо смонтировать компонент с массивом для errands prop :

wrapper = shallowMount(ErrandsListTable, {
  propsData: {
    errands: []
  }
});

... или измените значение по умолчанию с null на пустой массив:

export default {
  props: {
    errands: {
      type: Array,
      default: () => []
    }
  }
}

... или добавьте условное (т.е. v-if="errands") к ваш шаблон, так что он может быть разыменован, только когда истина:

<div v-if="errands && errands.length >= numberOfErrandsLoaded">
           ^^^^^^^^^^

Последнее решение - защитное программирование , которое защитит от пользователей, передающих в null / undefined проп, вызывая та же ошибка, с которой вы столкнулись.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...