Skip to content

v-model not reacting to change on element.selected #345

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

Closed
folmert opened this issue Jan 11, 2018 · 9 comments
Closed

v-model not reacting to change on element.selected #345

folmert opened this issue Jan 11, 2018 · 9 comments

Comments

@folmert
Copy link

folmert commented Jan 11, 2018

Simulating selecting radio buttons doesn't seem to be reflected in the model:

wrapperDeep.find('input[type="radio"]').element.selected = true;

Full code with the reproduced example:
https://github.com/folmert/vue-test-utils-jest-example


RadioGroup.vue:

<template>
    <div>
        <label><input v-model="folder" type="radio" name="folder" value="new"> New</label>
        <label><input v-model="folder" type="radio" name="folder" value="existing"> Existing</label>

        <div class="selected">Selected: {{folder}}</div>
    </div>
</template>

<script>
export default {
    name: 'RadioGroup',
    data () {
        return {
            folder: ''
        }
    }
}
</script>

RadioGroup.spec.js:

import {mount} from 'vue-test-utils';
import RadioGroup from '@/components/RadioGroup';

describe('RadioGroup', () => {
    let wrapperDeep;

    beforeEach(() => {
        wrapperDeep = mount(RadioGroup, {});
    });

    // works
    it('changes data according to the changed folder data', () => {
        wrapperDeep.setData({folder: 'existing'});
        expect(wrapperDeep.find('.selected').text()).toBe('Selected: existing');
    });

    // doesn't work
    it('changes data according to the selected folder option', () => {
        wrapperDeep.find('input[type="radio"][value="existing"]').element.selected = true;
        expect(wrapperDeep.find('.selected').text()).toBe('Selected: existing');
    });
});

yarn test result:

RadioGroup
√ renders changed data according to the changed folder data (38ms)
× renders changed data according to the selected folder option (8ms)

Expected value to be (using ===):
"Selected: existing"
Received:
"Selected:"

@lusarz
Copy link
Contributor

lusarz commented Feb 23, 2018

@eddyerburgh Are you working on that or can I try to investigate and implement it ?

@eddyerburgh
Copy link
Member

I'm not working on it, it would be great if you could investigate it 😀

@lusarz
Copy link
Contributor

lusarz commented Feb 23, 2018

Didn't find solution (yet), but have a few thoughts - any input about them is welcome:

  1. element.selected vs element.checked - according to HTMLInputElement documentation checked should be used - although it doesn't fix issue

  2. I'm not sure if it's good practice to modify element directly. Inside vue-test-utils specs I see similar situation once:

    wrapper.find('input').element.value = 'Value'
    wrapper.find('input').trigger('input')

    But just after modification an input event is triggered.

  3. What about:
    wrapperDeep.find('input[type="radio"][value="new"]').trigger('click')
    instead of
    wrapperDeep.find('input[type="radio"][value="new"]').element.selected = true

it worked for me in mocha, but not in jest environment - not sure why ...

@eddyerburgh
Copy link
Member

You can solve this by calling trigger with change after setting the element value:

it('changes data according to the selected folder option', () => {
    wrapperDeep.find('input[type="radio"][value="existing"]').element.selected = true;
    wrapperDeep.find('input[type="radio"][value="existing"]').trigger('change')
    expect(wrapperDeep.find('.selected').text()).toBe('Selected: existing');
});

@thatandyrose
Copy link

hi @eddyerburgh sorry to re-open this, but the above workaround doesn't seem to work on checkboxes. That is:

.element.checked = true followed by .trigger('change') doesn't seem to set the v-model prop on the component... 🤔

@eddyerburgh
Copy link
Member

There's a PR open that will add a method to set an element checked—https://github.com/vuejs/vue-test-utils/pull/557/files

In the PR they set the checked value and trigger a change event, and it works in the test cases in that PR, although in some Vue versions you also need to trigger a click event.

@thatandyrose
Copy link

hey @eddyerburgh thanks for the prompt reply, much appreciated! I'll check out the PR. Thanks again and thank you for this library, it's a godsend! 👍 #offtopic does your book test these kinds of scenarios? 🤔

@eddyerburgh
Copy link
Member

Yes it does 😉

@MarcelloTheArcane
Copy link

I came across a similar issue with setting a value of an input with v-model.lazy and a computed property with getter/setter (which is for a currency input).

I fixed it with the custom options on the change event trigger:

it('sets amount to zero on invalid input', async () => {
  const valueInput = wrapper.get('input[data-testid="value"]')
  await valueInput.trigger('change', {
    value: ''
  })
  await wrapper.vm.$nextTick()

  expect(valueInput.element.value).toBe('£0.00')
})

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

5 participants