I am currently writing tests for a Vue Component which implements a Vuetify Switch. As part of the testing I want to check the functionality of the vuetify switch. I am having troubling triggering a click on the switch to then verify that the switches value has changed (and once I have done that I will verify that the value bound to the switch has changed as well)
I have looked at the API docs for Vuetify and there are no methods to directly set the state of a Vuetify switch which is bewildering in my opinion. Because of this I am trying to perform a click on the VSwitch component using wrapper.find().trigger('click')
but this isn't changing the switch value, leading me to believe the click isn't doing anything at all.
Below are two tests
Any help in resolving this problem would be greatly appreciated.
switch.vue
<template>
<v-row>
<v-col>
<label class="label-text" :for="`${fieldLabel}`">{{labelText}}</label>
<v-row>
<label class="left-label">{{toggleLeftText}}</label>
<v-switch
:id="`${fieldLabel}`"
v-model="toggleState"
class="ma-0 pa-0"
:data-qa="`${fieldLabel}Checkbox`"
>
</v-switch>
<label class="right-label">{{toggleRightText}}</label>
</v-row>
<!--Hidden input field includes switch value in form when submitted-->
<input type="hidden" :value="toggleState" :name="`${fieldLabel}`">
</v-col>
</v-row>
</template>
<script>
export default {
name: "Switch",
props: {
fieldLabel: {
type: String,
required: true
},
labelText: {
type: String,
required: true
},
toggleLeftText: {
type: String,
required: true
},
toggleRightText: {
type: String,
required: true
},
toggleValue: {
type: Boolean,
required: true
},
},
data: function () {
return {
toggleState: this.toggleValue
}
}
}
</script>
switch.spec.js
describe('Switch', () => {
const toggleState = true;
const localVue = createLocalVue();
localVue.use(Vuetify, {
components: {
VRow,
VCol,
VSwitch,
InputError
}
});
const wrapperFactory = () => {
return shallowMount(Switch, {
localVue,
vuetify: new Vuetify(),
propsData: testProps,
});
};
const testProps = {
labelText: "Test Label",
fieldLabel: "testLabel",
toggleLeftText: "No",
toggleRightText: "Yes",
toggleValue: toggleState
};
let wrapper;
beforeEach(() => {
wrapper = wrapperFactory(testProps);
});
afterEach(() => {
wrapper.destroy();
});
it("should have correct toggle value", () => {
const vSwitch = wrapper.find(VSwitch);
expect(vSwitch.vm.value).toBe(toggleState);
});
it("should have correct toggle value after click", async () => {
const vSwitch = wrapper.find(VSwitch);
await vSwitch.trigger('click');
expect(vSwitch.vm.value).toBe(!toggleState);
});
});
Once compiled you can open the app by clicking Open app. I will install the Vuetify plugin, since this project will use Vuetify, a material design component framework. Go to Plugins in the Vue UI, click Add plugin and search for vuetify. Select the first option and click install. It will then ask to choose a preset.
It also includes vue-test-utils which is a great library that makes testing a lot easier in vue. It also provides the hot reloading which speeds up the development process. Once we hit this, it will ask for some information. Choose Manually select features and enable “ Unit testing ” along with other required features and continue.
Eg: example.spec.js The example.spec.js file is the default test that comes with vue cli 3. It expects the text on the HelloWorld component to match the data received as props from its parent App.vue.
(Surprised that didn't find a single code snippet that could work, after searching in both vuetify official document & via Google.) Handler method from methods part of the containing component.
I might be a bit late for answering your question, but this way you should be able to get your v-switch
.
const vSwitch = wrapper.find({ name: 'v-switch' });
and then trigger the event with
vSwitch.$emit('change', <true or false>);
, depending on what you're testing.
The limit with this approach is that if you have multiple v-switch
es in your code, you would need to target them with a data-test-id
, for example like this:
<v-switch data-test-id="my-switch-1"> ... </v-switch>;
<v-switch data-test-id="my-switch-2"> ... </v-switch>;
and then I defined a helper function on top of my test file, like so:
const getSwitchComponent = (wrapper: Wrapper<Vue>, testId: string): Wrapper<Vue> => {
const switches = wrapper.findAll({ name: 'v-switch' });
const component = switches.wrappers.find(wrapper =>
wrapper.contains(`[data-test-id="${testId}"]`),
);
if (!component) {
throw Error(`Element not found: ${testId}`);
}
return component;
};
which will let you do something like this:
const mySwitch1 = getSwitchComponent(wrapper, 'my-switch-1');
const mySwitch2 = getSwitchComponent(wrapper, 'my-switch-2');
and trigger the change
event so:
mySwitch1.vm.$emit('change', false);
mySwitch2.vm.$emit('change', true);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With