Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Triggering custom events #145

Closed
pimhooghiemstra opened this issue Nov 3, 2017 · 13 comments
Closed

Triggering custom events #145

pimhooghiemstra opened this issue Nov 3, 2017 · 13 comments

Comments

@pimhooghiemstra
Copy link

I was trying to test a custom event (in the parent) that is emitted by a child component. However, using wrapper.trigger we can only use DOM events.

Would it be possible to add custom events?

If not, is there a way to test custom events from within the shallow rendered parent component?

My testcase is that the child emits an event and the parent should execute a function on occurrence of this event.

@eddyerburgh
Copy link
Member

You can call $emit on the wrapper vm

wrapper.vm.$emit('foo')

We're hesitant to add this as a feature because there are many possible aliases like this, and we want to keep the API small.

If lots of people would find this feature useful, we can consider adding it.

It's also worth us adding a note on this to the trigger docs. Is anyone able to make a PR adding details on this?

@lmiller1990
Copy link
Member

lmiller1990 commented Nov 4, 2017

@eddyerburgh I can do the PR next week if noone gets there first.

There was a point where I wanted this feature, but after playing around a bit, I don't think it is necessary. I'll think a bit more about it and if I come up with some good use cases, post them.

@pimhooghiemstra
Copy link
Author

@eddyerburgh I think it is clear from the docs, I just wasn't sure why only DOM events could be triggered.

Anyway, I made my test now using

const stub = jest.fn();
wrapper.vm.$on('hit', stub);
wrapper.vm.$emit('hit');
expect(stub).toBeCalled();

And the test passes. However, this feels a bit clumsy. I am not even sure what exactly I am testing here?

@eddyerburgh
Copy link
Member

It looks like you're testing Vue functionality, rather than logic in your code.

@lmiller1990
Copy link
Member

I got started on a small demo, and thought about how I I would expect the docs (wrapper/emitted) to look, but couldn't really come up with a big improvement on them.

Unless @eddyerburgh has something you'd like added, I think we can just close this for now. The main problem seems to not be the docs, but a lack of how/what to test - maybe we should add more targetted/details guides.

@pimhooghiemstra
Copy link
Author

@eddyerburgh I agree I was testing Vue functionality itself. With the help of issue #145, I am now on my way testing my own Vue code. Thanks for the clarification!

@baixiaoji
Copy link

You can call $emit on the wrapper vm

wrapper.vm.$emit('foo')

We're hesitant to add this as a feature because there are many possible aliases like this, and we want to keep the API small.

If lots of people would find this feature useful, we can consider adding it.

It's also worth us adding a note on this to the trigger docs. Is anyone able to make a PR adding details on this?

how to testing custom event params with $event, I read doc, the doc don't mention.

changeValue(type, event) {
        const value = event.target.value;
        const eventName = type ? 'behindValue' : 'frontValue';
        this.$emit('on-change');
        this.$emit(`update:${eventName}`, value);
},
// in unit  test file
/*
const mock = jest.fn();
const beforeInput = wrapper.find('input.group_input_before');
beforeInput.vm.$emit('on-change', 0,  {target: {value: 100}});
wrapper.vm.$on('update:frontValue', mock);
 expect(mock).toBeCalledWith(100);
*/

error:

[Vue warn]: Error in v-on handler: "TypeError: Cannot read property 'value' of undefined"

@lmiller1990
Copy link
Member

lmiller1990 commented Apr 10, 2019

It looks like event.target is undefined here. Try vm.$emit('change').

You could try to mock the method you are expecting to be called, and assert against that. Eg:

const mock = jest.fn()
const wrapper = shallowMount(Component, {
  methods: {
    frontValue: mock
  }
}

wrapper.find('.....').vm.$emit('.....')
expect(mock).toHaveBeenCalledWith(100)

If you can post the rest of your source code, I can help you get the test working.

@baixiaoji
Copy link

It looks like event.target is undefined here. Try vm.$emit('change').

You could try to mock the method you are expecting to be called, and assert against that. Eg:

const mock = jest.fn()
const wrapper = shallowMount(Component, {
  methods: {
    frontValue: mock
  }
}

wrapper.find('.....').vm.$emit('.....')
expect(mock).toHaveBeenCalledWith(100)

If you can post the rest of your source code, I can help you get the test working.

I having a test the same as your advice, then I see the coverage, it said the changeValue method didn't cover, so I want to test it.
I put my source code in codesandbox, it only source code

@baixiaoji
Copy link

baixiaoji commented Apr 11, 2019

I invoke the $emit('on-change') and log the beforeInput.emitted(), then I see it's an empty array, so the $emit function that utils provide can't pass the vue $event params in custom event ?
image

BTW, I must have a try..catch wrapper the value = event.target.value, then it can pass the the component function, but do you think it's ugly

@baixiaoji
Copy link

First, Thx for you reply 😃 .
Then it's my fault, I misunderstand about the vm.$emit function when I manual invoke it's only need a params that is the $event params pass into the listener.
and I change the unit test to this, it light the green pass.

test('testing changeValue fn can invoke the custom event', () => {
    const mock = jest.fn();
    const Event = {target: {value: 16}};
    const InputComponent = shallowMount(inputGroup, {
      propsData: {
        frontValue: 12,
        behindValue: 14,
      },
      listeners: {
        'update:behindValue': mock,
        'update:frontValue': mock,
      },
    });
    const frontInput = InputComponent.find('input.group_input_before');
    const afterInput = InputComponent.find('input.group_input_after');
    frontInput.vm.$emit('on-change', Event);
    afterInput.vm.$emit('on-change', Event);
    // console.log(InputComponent.emitted());
    expect(mock).toHaveBeenCalledTimes(2);
  });

the source code was in here , if you having less time, forget it.

@lmiller1990
Copy link
Member

Looks like you solved your problem, then?

@baixiaoji
Copy link

Looks like you solved your problem, then?

yes

itsalaidbacklife added a commit to itsalaidbacklife/vue-test-utils that referenced this issue Jul 6, 2020
Add a note about custom DOM events per [issue 145](vuejs#145)
lmiller1990 pushed a commit that referenced this issue Jul 6, 2020
Add a note about custom DOM events per [issue 145](#145)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants