首页 > 解决方案 > 单击后 vue-test-utils 未更新组件

问题描述

我正在使用 vue-test-utils/mocha-webpack/expect 来测试以下组件:

<template>
    <div>
        <div id="agent-customer-container" class="top-tabs" v-if="agentName || customerName || miniBasket">
            <div v-if="agentName || customerName">
                <div class="text-primary bg-white top-tabs__item px-5" id="customer-slot" v-if="customerName" @click="customerDetailShow = !customerDetailShow">
                <span>
                    <i class="fa fa-user-circle fa-2x mr-3"></i>
                    {{ customerName }}
                </span>
                    <i :class="'fa fa-caret-'+(customerDetailShow?'up':'down')" id="customer-caret"></i>
                </div>
                <div class="text-primary top-tabs__item top-tabs__item--light px-5" id="agent-slot" v-if="agentName">
                    {{ agentName }}
                </div>
            </div>
            <div class="top-tabs__mini-basket text-primary px-5" v-if="miniBasket && !loading">
                <span v-if="firstEnquiry !== null && firstEnquiry.cruise !== null && firstEnquiry.cruise !== undefined">
                    <span id="first-enquiry-cruise-summary">{{ firstEnquiry.cruise.name }} ({{ firstEnquiry.cruise.code }})</span>
                 - <span class="text-semibold">£XX.XX</span>
                </span>
                <span id="toggle__mini-basket" :class="[{'fa-counter': (enquiryCount > 0), 'mini-basket__count' : (enquiryCount > 0)}, 'fa-stack v-top ml-3 cursor-pointer']" @click="toggleMiniBasket" :data-count="enquiryCount">
                <i class="fas fa-circle fa-stack-2x"></i>
                <i class="fas fa-shopping-cart fa-stack-1x fa-inverse"></i>
            </span>
            </div>
            <div class="customer-detail bord-rgt" v-show="customerDetailShow">
                <div class="row p-5 bord-btm" v-for="i in 2" :key="i">
                    <div class="col-sm-6">
                        <p><a href="#">Sydney to Hong Kong</a></p>
                        <p>Text<br>Text</p>
                    </div>
                    <div class="col-sm-6">
                        <p><strong>Grade data</strong>
                            <br>
                            Lorem ipsum
                        </p>
                    </div>
                </div>
                <div class="row p-5 bg-primary customer-detail__footer">
                    <div class="row">
                        <div class="col-sm-6">
                            Text
                        </div>
                        <div class="col-sm-6 text-right text-bold">
                            Total £1000
                        </div>
                    </div>
                </div>
            </div>
            <div class="mini-basket-detail bord-lft" v-if="miniBasketDetailShow">
                <div v-if="myEnquiry !== false && myEnquiry !== undefined && myEnquiry['cruise_enquiries'] !== undefined && firstEnquiry !== null && firstEnquiry.cruise !== null">
                    <div class="row p-5 bord-btm" v-for="(cruiseEnquiry, cruiseEnquiryIndex) in myEnquiry['cruise_enquiries']" :key="cruiseEnquiry.id">
                        <div class="col-sm-12 text-sm" v-if="cruiseEnquiry.cruise !== undefined">
                            <cruise-enquiry
                                :cruise-name="cruiseEnquiry.cruise.name"
                                :cruise-code="cruiseEnquiry.cruise.code"
                                :ship-name="cruiseEnquiry.cruise.ship.name"
                                :departure-port-name="cruiseEnquiry.cruise.departure_port.name"
                                :departure-date="new Date(cruiseEnquiry.cruise.departure_date)"
                                :duration="cruiseEnquiry.cruise.duration"
                                :cruise-enquiry-cabins="cruiseEnquiry.cruise_cabin_cruise_enquiry"/>
                        </div>
                    </div>
                </div>
                <div v-else>
                    <div class="row p-5 bord-btm">
                        <div class="col-sm-12 text-sm">
                            <p>Your itinerary is currently empty. Please start by selecting a cruise.</p>
                        </div>
                    </div>
                </div>
                <div id="toggle__mini-basket--close" class="row p-3 bg-primary customer-detail__footer text-center cursor-pointer d-block" @click="miniBasketDetailShow = false">
                    <caret :up="true" additional-classes="fa-2x"></caret>
                </div>
            </div>
            <span class="float-right"></span>
        </div>
    </div>
</template>

<script>
    import Caret from "./Caret";
    import CruiseEnquiry from "./enquiry-panel/CruiseEnquiry";

    export default {
        name: "EnquiryPanel",
        components: {
            CruiseEnquiry,
            Caret,
        },
        props: {
            loading: {
                type: Boolean,
                required: false,
                default: false,
            },
            customerName: {
                type: String,
                required: false,
                default: ''
            },
            agentName: {
                type: String,
                required: false,
                default: ''
            },
            myEnquiry: {
                type: Object|Boolean,
                required: false,
                default: false,
            },
            miniBasket: {
                type: Boolean,
                required: false,
                default: false,
            }
        },
        data() {
            return {
                customerDetailShow: false,
                miniBasketDetailShow: false,
                firstEnquiry: null,
                enquiryCount: 0,
                miniBasketCabinNumber: 0,
            }
        },
        watch: {
            myEnquiry: {
                deep: true,
                immediate: true,
                handler(newValue) {
                    if (this.myEnquiry !== false && this.myEnquiry['cruise_enquiries'] !== undefined && this.myEnquiry['cruise_enquiries'][0] !== undefined) {
                        this.firstEnquiry = this.myEnquiry['cruise_enquiries'][0];
                        for (let i = 0; i <= (this.myEnquiry['cruise_enquiries'].length - 1); i++) {
                            if (this.myEnquiry['cruise_enquiries'][i].cruise !== undefined && this.myEnquiry['cruise_enquiries'][i].cruise !== null) {
                                this.setEnquiryCount(this.enquiryCount + 1);
                            }
                        }
                    }
                }
            }
        },
        methods: {
            setEnquiryCount(count) {
                this.enquiryCount = count;
            },

            toggleMiniBasket() {
                this.miniBasketDetailShow != this.miniBasketDetailShow;
            }
        }
    }
</script>

当我单击时,#toggle__mini-basket我希望miniBasketDetailShow设置为 true(安装时默认为 false),并且应该显示篮子(在元素上使用 `v-if="miniBasketDetailsS​​how")。

这是我的测试:

import {createLocalVue, shallowMount, mount} from '@vue/test-utils';
import expect from 'expect';
import EnquiryPanel from '~/components/EnquiryPanel';
import VueMoment from "vue-moment";

describe('EnquiryPanel', () => {
    let localVue;

    beforeEach(() => {
        localVue = createLocalVue();
        localVue.use(VueMoment);
    });

    // If a user clicks on the mini basket icon and the basket panel is not open, the basket panel should open
    it('opens mini basket if user clicks icon and basket is not open', () => {
        let component = shallowMount(EnquiryPanel, {
            localVue,
            propsData: {
                miniBasket: true
            }
        });

        expect(component.vm.miniBasket).toBe(true);
        expect(component.vm.miniBasketDetailShow).toBe(false);

        component.find('#toggle__mini-basket').trigger('click');
        component.vm.$forceUpdate();
        expect(component.vm.miniBasketDetailShow).toBe(true);
    });

});

这是一个简单的测试,所以我不确定出了什么问题。结果如下:

 3) EnquiryPanel
       opens mini basket if user clicks icon and basket is not open:
     Error: expect(received).toBe(expected) // Object.is equality

Expected: true
Received: false
      at Context.eval (webpack-internal:///./tests/Javascript/EnquiryPanel.spec.js:62:86)

我希望这个测试能够通过。我试过让 shallowMount 与sync: false. 我也尝试过添加await component.vm.$nextTick但没有运气。任何帮助,将不胜感激。

标签: vue.jsvuejs2vue-test-utils

解决方案


错误在于toggleMiniBasket方法:

this.miniBasketDetailShow != this.miniBasketDetailShow;

应该

this.miniBasketDetailShow = !this.miniBasketDetailShow;


推荐阅读