Impossible to click on a specific button part of a class with vue-test-utils - vue.js

I want to test an editable table with vue-test-utils. There are edit buttons for each row, and when an edit button is clicked, the table row expands and allow the user to input information.
Each edit button has the class "editAddress", this is what I've tried so far :
describe('Customers Addresses Table', () => {
let wrapper;
beforeEach(() => {
wrapper = mount(AddressesTable);
});
it('can edit an address',() => {
const firstEditAddressButton = wrapper.findAll('button.editAddress').at(0);
firstEditAddressButton.trigger('click');
console.log(firstEditAddressButton.html());
expect(wrapper.html()).toContain('Close');
});
});
The test fails because it doesn't seem the button has been clicked..
The html code of my table looks like this (I use bootstrap-vue table here):
<div class="panel panel-default">
<b-table>
Address Edition-->
<template v-slot:cell(name)="data">
<div>
<button class="editAddress" #click="data.toggleDetails(); buttonEditClicked(data.item)">{{ data.item.name }}</button>
</div>
</template>
</b-table>
</div>
After the edit button being clicked, the table should transform like this :
Maybe I am not fetching the first button of the class "editAddress" correctly, I don't have any idea..
Thanks for your help !

Try that
it('can edit an address', async () => {
const firstEditAddressButton = wrapper.findAll('button.editAddress').at(0);
firstEditAddressButton.trigger('click');
await wrapper.vm.$nextTick();
expect(wrapper.html()).toContain('Close');
});

Related

Add button with custom event in Filepond drop area

I want to add a button in drop area with custom event on it to trigger a modal.
<template>
<div id="app">
<file-pond
name="test"
ref="pond"
max-files="4"
label-idle="Drop files here... <button class=“Filepond—custom”>Search<\button>"
:allow-multiple="true"
accepted-file-types="image/jpeg, image/png"
:files="myFiles"
v-on:init="handleFilePondInit"
allowImagePreview ="false"
/>
</div>
</template>
Is there a way to do this?
I tried creating a plug-in on CREATE_VIEW filter but I wasn’t successful.
Edit: The problem with CREATE_VIEW or any other available filter is that they all are applied when the item(s) is added/updated.
There might be another workaround but I came up with this solution.
On Filepond initalization I was able to append the button and attached an event to it.
handleFilePondInit: function () {
// Filepond is initialized
const element = document.querySelector('.filepond--label-action');
const button = document.createElement('button');
button.type = 'button';
button.className = 'filepond--media-search-action';
button.innerHTML = 'Button Name'
button.addEventListener('click', () => {console.log('button clicked')});
element.appendChild(button);
},

Click on v-tab-item in vue-test-utils

So I have a Vue component that is built roughly like this:
<DialogLayout>
<template #activator="slotData">
<slot name="activator" v-bind="slotData"></slot>
</template>
<template #default="{ disabled }">
<v-tabs-items v-model="openTab" transition="fade">
<v-tab-item key="notPreview">
<div></div>
</v-tab-item>
<v-tab-item key="preview" data-testid="preview-button">
<h4>{{ title }}</h4>
<Card :post="preview"
></Card>
</v-tab-item>
</v-tabs-items>
</template>
</DialogLayout>
And then the test is this:
it('Image should be visible in preview', async () => {
const component = createComponent()
await component.findComponent(DialogLayout).setData({show: true})
const previewBtn = component.find('[data-testid="preview-button"]')
expect(previewBtn.exists())
await previewBtn.trigger('click')
})
It's basically two pages inside a v-dialog, and what I want to do is switch the page and render the second page to see the image that has been uploaded, but I can't figure out how to click the v-tab-item for it to change. It doesn't seem to even be able to find the button component with the data-testid.
Does anyone have any idea on how to test clicking on a v-tabs-items in vue-test-utils? I'm not interested in testing the internal function in v-tab, but I need to be able to actually click the data-testid preview-button to see the change.
I have to find and setData for the dialog to even show, and I'm mocking the transition with:
const transitionStub = () => ({
render: function(h) {
return this.$options._renderChildren
},
})
Any help is greatly appreciated!
So one of the problems with this was that it didn't render the v-tab-item, while it should have, so instead of trying to fix the test according to the code, i instead added eager to the v-tab-item. More information can be found here.

Then I reload page v-if(with computed data) not work

im search on everywhere information about my questions - not help me.
I would like to solve this issue using v-if (not v-show)
I get orders data from Vuex store
all code work ,then page loaded and mounted and then I click other tabs and going back to current tab
code not work then I reload page on current tab
code work then I reload page on current tab , but without all v-if
I would like to solve without using third-party plugins if possible
<template>
<div class="w-full">
<!--show message div-->
<div v-if="orders.length===0" class="flex flex-wrap">
...
</div>
<!--show table div-->
<div v-if="orders.length!==0" class="flex flex-wrap">
...
</div>
</div>
</template>
computed data
computed: {
orders() {
return this.$store.state.dataList.orders
}
}
// in console.log i get 4 my orders objects (4) [{…}, {…}, {…}, {…}, ob: Observer]
actions:
fetchORDERS ({ commit }) {
return new Promise((resolve, reject) => {
axios.get('/api/data-list/orders')
.then((response) => {
commit('SET_ORDERS', response.data)
resolve(response)
})
.catch((error) => { reject(error) })
})
}
mutation:
SET_ORDERS (state, order) {
state. orders = order
}
one of the forums they wrote that the matter is in mutation, but I cannot understand what exactly and where is the error, pls help
Your basic setup is correct. That v-if should work if the data-flow is correct.
From what you're giving us, I see the following:
In your computed property you're looking at: this.$store.state.dataList.orders
In your mutation you're changing state. orders. This should be state.dataList.orders.
In other words: you should check whether the state has the shape you expect it to have. You can do this with a console.log in the computed property, or one in the mutation.

How to focus and activate a vue multiselect?

When the user double-clicks this:
<div
class="open-select"
v-if="!editable"
#dblclick="editable=true">{{ name }}
</div>
I'd like this multiselect to be open and focused:
<multiselect
v-else
v-model="name"
:options="names"
track-by="id"
tabindex="0"
autofocus
#select="editable=false"
></multiselect>
The double-click event shows the multiselect element fine, but the multiselect still requires the user to click it to open. I'd like it to open automatically after appearing.
Things I've tried:
focusing the multiselect:
tabindex="0"
autofocus
When I try to select the focused item in jQuery, $(':focus')[0], I get 'undefined'
Heyo!
You can put a ref on the component and then trigger focus which will open the dropdown.
<multiselect ref="vms" v-bind="yourAttributes" />
And then in your created hook you add
this.$refs.vms.$el.focus()
A simplest solution - Toggle Vue Multiselect dropdown
You can use 2 events (#open, #close) on VueMultiselect
anda ref in multiselect
like
ref="multiselect"
keep in
data(){
isOpen: false
}
then add to the 2 events
#close="isOpen = false"
#open="isOpen = true"
and use a method
toggle() {
if (this.isOpen) {
this.$refs.multiselect.$el.blur()
this.isOpen = false
} else {
this.$refs.multiselect.$el.focus()
this.isOpen = true
}
}
Finally figured out how to do this (ref didn't work for me):
STEP 1: I was focusing on the wrong element.
So a vue-multiselect element is structured like this (shorthand to only show important parts):
<div class="multiselect"> // <= This is the element to focus on
<div class="multiselect__tags">
<input> // <= Not the input
</div>
</div>
Typically you want to put your tabindex on the input, instead you should put it on the parent with a class of multiselect. This also goes for things like jQuery's focus(). So...
No: $('.multiselect input').focus()
Yes: $('.multiselect').focus()
STEP 2: Correcting tabindex.
Another issue is when vue-multiselect puts a tabindex="-1" on all .multiselect elements. This removes them from the natural order of tabindexes, so you need to reassign all the tabindexes:
In mounted and updated (if necessary) you need code to reassign all the tabindexes:
mounted: function() {
$(document).ready(()=>{
// you may need to delete all tabindexes first.
$('[tabindex]').each( (i,v) => {
$(v).removeAttr('tabindex');
return true;
});
// add new tabindexes
$('input, textarea, button').each(( i,v ) => {
var isMultiSelect = $(v).hasClass('multiselect__input');
if(isMultiSelect){
$(v).parents('.multiselect:first').attr('tabindex', i + 1);
else{
$(v).attr('tabindex', i + 1);
}
});
});
}

Slot doesn't render well on child component VueJS

I'm trying to loop over a component, I fill up slot with some data but they are not rendering well.
Weird behaviors :
Data are displayed but not visible.
In chrome if i toggle the device toolbar in the debug panel, data are now visible.
Changing font-size in the debug panel make my data visible
When i put a Child component outside the loop, the looped ones are rendered well.
Snippet from my parent Component :
<li class="cards__item" v-for="(staffMember, index) in staff">
<card-profil>
<h3 slot="title">{{staffMember.name}}</h3>
</card-profil>
</li>
Snippet from my child Component :
<template>
<section class="card-profil">
<figure class="fig-card-profil">
<figcaption class="figcaption-card-profil">
<slot name="title"></slot>
</figcaption>
</figure>
</section>
</template>
I get my data this way in my parent component:
export default {
data: function () {
return {
staff: []
}
},
mounted () {
this.getStaff()
},
methods: {
getStaff: async function () {
const staff = await axios({ url: 'https://randomuser.me/api/?results=8' })
this.staff = staff.data.results
}
}
}
Is this problem of lifehook ? Do i have to use Scoped slot instead ? V-for issue ?
Thanks for sharing your thoughts.