在VueJS中模拟子组件的$emit事件

8

我有一个Snackbar组件,正在为其编写测试。它包含一个子组件(一个按钮,当点击时关闭Snackbar)。

此按钮会发出@click事件,父组件侦听并运行一个方法以关闭Snackbar或打开另一个Snackbar。

是否有一种方法来模拟$emit?我似乎找不到任何相关的东西。

import { render, fireEvent, waitFor } from '@testing-library/vue';
import Snackbar from '../Snackbar.vue';
import EventBus from '@/services/EventBus';

describe('Snackbar', () => {
    const role = 'alert';
    
    it('should close snackbar on button click', async () => {
        const type = 'success';

        const { getByRole } = render(Snackbar, {
            // with this the button is inaccessible
            stubs: ['OBButton'],
        });

        await EventBus.$emit('addSnack', {
            type,
        });

        const snackbar = getByRole('alert');

        // this is wrong...
        await fireEvent.click(button);
  
        // this expect should be appropriate.
        expect(snackbar).not.toBeInTheDocument;
    });
});

这是组件的模板:

<template>
    <div class="snackbar-wrapper elevated">
        <transition name="snack-slide" v-on:after-leave="checkForMoreSnacks">
            <div
                role="alert"
                class="snack-data"
                v-if="currentSnack != null"
            >
                <span class="snack-text">{{ currentSnack.text }}</span>
                <OBButton
                    :text="currentSnack.buttonText"
                    @click="closeCurrentSnack"
                    :type="buttonType"
                ></OBButton>
            </div>
        </transition>
    </div>
</template>

附加信息:

  1. 此组件永远不会被卸载。关闭它意味着将 currentSnack 值设置为 null,从而隐藏它。
3个回答

7

使用触发器从子组件中发出事件。你可以这样做:

import ButtonComponent from '@/components/ButtonComponent.vue';
import Snackbar from '@/components/Snackbar.vue';

it('should foo', () => {
  const wrapper = shallowMount(Snackbar);
  wrapper.find(ButtonComponent).trigger('click');
  // Your assertions here

})

编辑:对于自定义事件,情况会更加棘手。目前我是这样模拟该事件的:

const wrapper = shallowMount(Snackbar);
const childWrapper = wrapper.find(ButtomComponent);
childWrapper.vm.$emit('custom', { foo: 'bar' })


自定义Vue事件发射器不幸使用了@vue/test-utils而不是@testing-library/vue。 - Romainpetit
1
在您的第二个示例中,childWrapper.vmundefined。您可能想将 wrapper.find(ButtomComponent) 更改为 wrapper.getComponent(ButtomComponent) - Qback

1
原来这很简单:

结果证明这非常简单:

import ButtonComponent from '@/components/ButtonComponent.vue';

const { getByRole, getByText } = render(Snackbar, {
  components: { ButtonComponent } ,
  mocks: { $t: msg => msg }
})

此后,您可以像这样使用此组件:
const button = getByRole('button');

0

很遗憾,我已经阅读了那份文档。它并没有真正帮助到我。是否可能提供一些具体的代码,让我尝试实现?我知道这是一个困难的要求,如果不行也没关系。 - Riza Khan
你能详细说明一下你想要做什么吗? - P.B.UDAY
我想触发子组件(按钮)的emit,从而调用关闭(或更恰当地隐藏)snackbar的方法。 - Riza Khan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接