使用 Jest 对 V-If 标签进行单元测试始终为真

Unit test a V-If label with Jest is alway true

我正在尝试使用 Jest 测试以下标签:

<label class="no-content-label" v-if="products.length===0 && !isTableBusy">No Content To Show</label>

通过以下测试:

it('Test No Content To Show When table is not empty', async () => {
        const wrapper = mount(productTable, {
            propsData: {
                products: items1,
                fields: fields1
            }
        })
        expect(wrapper.find(".no-content-label").exists()).toBeFalsy()
        wrapper.destroy();
    }) 

其中项目只是:[{ a: 1, b: 2, c: 3 }, { a: 4, b: 5, c: 6 }] 坚果我总是得到 True,即使组件没有显示并且应该得到 false。

完整组件代码:

<template>
  <div id="ProductTable" class="container mt-3 mb-5">
    <h1 class="mainTitle">Product Table Home</h1>
    <b-alert variant="danger" :show="showError" v-for="(error,index) in errorArray" :key="index" dismissible>
      {{ error }}
    </b-alert>
    <b-row class="mb-3">
      <b-col md="3">
        <b-form-input v-model="filterInput" type="search" id="filterInput" placeholder="Type to Search"></b-form-input>
      </b-col>
    </b-row>
    <b-table id="product-table" striped hover head-variant="light"
             :busy="isTableBusy"
             :items="products"
             :filter="filterInput"
             :fields="fields"
             :bordered="bordered"
             :borderless="bordered"
             :total-rows="rows">
      <template #table-busy>
        <div class="text-center text-danger my-2">
          <b-spinner class="align-middle"></b-spinner>
          <strong>Loading...</strong>
        </div>
      </template>
      <template #cell(cogs.unitManufacturingCost)="row">
        {{
          row.item.cogs.unitManufacturingCost ? Number(row.item.cogs.unitManufacturingCost).toLocaleString() + '$' : '0$'
        }}
      </template>
      <template #cell(cogs.shipmentUnitCost)="row">
        {{ row.item.cogs.shipmentUnitCost ? Number(row.item.cogs.shipmentUnitCost).toLocaleString() + '$' : '0$' }}
      </template>
      <template #cell(cogs.monthlyAdvertismentCost)="row">
        {{
          row.item.cogs.monthlyAdvertismentCost ? Number(row.item.cogs.monthlyAdvertismentCost).toLocaleString() + '$' : '0$'
        }}
      </template>
      <template #cell(cogs.manufacturingCountry)="row">
        {{ row.item.cogs.manufacturingCountry ? row.item.cogs.manufacturingCountry : '-' }}
      </template>
      <template #cell(actions)="row">
        <b-button size="md" variant="primary" @click="openEditProductModal(row.item)">
          Edit
        </b-button>
        <edit-product-modal ref="EditProductModal" :item="row.item" @fetchProducts="fetchProducts"></edit-product-modal>
      </template>

    </b-table>
    <label class="no-content-label" v-if="products.length===0 && !isTableBusy">No Content To Show</label>
  </div>
</template>

<script>
import EditProductModal from "@/components/EditProductModal";
import {BAlert} from "bootstrap-vue";
import {BRow} from "bootstrap-vue";
import {BCol} from "bootstrap-vue";
import {BFormInput} from "bootstrap-vue";
import {BTable} from "bootstrap-vue";



export default {
  name: "BootstrapProductTable",
  components: {
    EditProductModal: EditProductModal,
    'b-alert': BAlert,
    'b-row': BRow,
    'b-col': BCol,
    'b-form-input': BFormInput,
    'b-table': BTable,
  },
  data() {
    return {
      filterInput: "",
      bordered: true,
      isTableBusy: false,
      products: [],
      fields: [
        {key: 'productName', label: 'Product Name', sortable: true, sortDirection: 'desc'},
        {key: 'cogs.unitManufacturingCost', label: 'Unit manufacturing cost', sortable: true,},
        {key: 'cogs.shipmentUnitCost', label: 'Shipment unit cost', sortable: true},
        {key: 'cogs.monthlyAdvertismentCost', label: 'Monthly advertising cost', sortable: true,},
        {key: 'cogs.manufacturingCountry', label: 'Manufacturing country', sortable: true,},
        {key: 'actions', label: 'Actions'}
      ],
      errorArray: [],
      showError: false
    }
  },
  computed: {
    rows() {
      return this.products.length;
    }
  },
  created() {
    this.fetchProducts();
  },
  methods: {
    openEditProductModal(row) {
      this.$refs.EditProductModal.show(row)
    },
    async fetchProducts() {
      try {
        this.isTableBusy = true;
        //delay example
        // const delay = ms => new Promise(resolve => setTimeout(resolve, ms))
        // await delay(1000)
        let response;
        response = await this.axios.get(
            "http://localhost:3000/products"
        );
        this.products = response.data;
      } catch (error) {
        this.showError = true;
        this.errorArray = error.response ? error.response.data.errors : [error]
      }
      this.isTableBusy = false;
    }
  }
}
</script>

您正在尝试通过 products,但您的组件不需要任何道具。

我看到 products 是在 fetchProducts 方法中获取的。所有 api 调用都必须被模拟。 fields 已在组件中设置。所以你所要做的就是模拟 api 调用。这就是为什么我建议你模拟 fetchProducts 方法,这样它总是会返回相同的数组 products:

const mockProducts = [{ a: 1, b: 2, c: 3 }, { a: 4, b: 5, c: 6 }];

it('Test No Content To Show When table is not empty', async () => {
  const wrapper = mount(productTable, {
    mocks: {
      fetchProducts: () => mockProducts
    }
  })
  expect(wrapper.find(".no-content-label").exists()).toBeFalsy()
    wrapper.destroy();
  }) 

我终于能够通过向标签添加 id 属性并通过 id 找到它来修复测试:

标签:

 <label id="no-content-label" v-if="products.length===0 && !isTableBusy">No Content To Show</label> 

工作测试:

 let wrapper = null
    beforeEach(() => {
        wrapper = mount(ProductTable)
    })
    afterEach(() => {
        wrapper.destroy()
    })
it('Test "No Content To" Show appear When Products are empty', async () => {
        await wrapper.setData({products: []})
        expect(wrapper.find('[id="no-content-label"]').exists()).toBe(true)
        expect(wrapper.find('[id="no-content-label"]').text()).toBe("No Content To Show");
    })
    it('Test "No Content To" not Show do not appear When Products are not empty', async () => {
        await wrapper.setData({products: mockProduct})
        expect(wrapper.find('[id="no-content-label"]').exists()).toBe(false);
    })