jest chai vuejs trigger('click') not working - vue.js

i try to create a simple test who :
click on button
show if dropdown is open
i try to simulate a click with trigger but it is not working,
do you have any idea what i am doing wrong?
describe('test clique boutton filtre', () => {
test('should show dropdown de la colonne 1', async (done) => {
const dropdown = wrapper.find('#nom-divUpperDrop')
const button = wrapper.find('#nom-dropdown')
await button.trigger('click')
expect(dropdown.findAll('.show').length).equal(1)
done()
})
})
i'am sure i find the button because the console log show :
<button type="button" id="nom-dropdown" data-bs-toggle="dropdown" aria-bs-haspopup="true" aria-bs-expanded="false" data-bs-offset="-60,10" data-bs-auto-close="outside" class="nav-icon clear-btn">
<p> false </p>
</button>
here the dropdown where i want to find the .show
> <div aria-labelledby="nom-dropdown" class="dropdown-menu">
> <div>
> <div class="filter-deroulant">
> <!---->
> <div class="filter-input">
> <div class="input-group mb-3"><input type="text" id="filtre_0" value="" placeholder="Recherche par nom"
> aria-label="Rechercher" aria-describedby="nom" class="form-control col
> form-control-sm"> <button type="button" id="nom" class="btn
> btn-outline-secondary"><svg aria-hidden="true" focusable="false"
> data-prefix="fas" data-icon="search" role="img"
> xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
> aria-expanded="false" class="svg-inline--fa fa-search fa-w-16">
> <path fill="currentColor" d="M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0
> 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4
> 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z"
> class=""></path>
> </svg></button></div>
> </div>
> </div>
> </div>
> <div>
Any idea?
ps: i tried this : Vue Testing (JEST): button.trigger('click') not working
ps: I tried the button manually, it's work :)
but it's not working for me

Related

Vue 3 getting selected date from datepicker

I am building a date picker using Flowbite Datepicker Plugin: https://flowbite.com/docs/plugins/datepicker/ . Here is my html code:
<form #submit.prevent="checkAvailability" method="POST" class="space-y-6">
<div class="items-center">
<label for="start" class="text-sm">Pick Up Date</label>
<div class="relative mb-4">
<div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
<svg class="w-5 h-5 text-gray-500 dark:text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z" clip-rule="evenodd"></path></svg>
</div>
<input datepicker datepicker-autohide v-model="startDate" type="text" class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full pl-10 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="Select date">
</div>
</div>
<div>
<button type="submit" class="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">Check Availability</button>
</div>
</form>
and here is my Vue JS Code:
<script>
export default {
data(){
return {
startDate: '',
}
},
methods:{
checkAvailability(e) {
console.log("start date", this.startDate);
}
}
}
However, when I try to print start date in the console, it is showing as empty even if I had selected the date in the date picker.
I have tried to set #change method, but it seems like the function of onChange is not being called once I set the date.
Any help is appreacited!
Not 100% sure - but the plugin does not update in a vue way. I guess it is because the value is set by javascript, so no change event will raise.
It looks like the "data.startDate" is not updated when you click on a date but if you type something it will be changed.
What you can do is a "workaround", make a ref in the input
<input ref="datepicker1" datepicker ...>
and and use the refs value like that
console.log(this.$refs.datepicker1.value);
Just writing because you appreciate any help

VueJS file upload field cannot be reset

In my vuejs application, I have a modal to insert some user data with a file upload.
I should be able to clear all the form fields once when an user successfully upload any content.
All my fields get reset apart from the file upload field.
It will remained as it is.
Inside my form.vue, for the file upload I have
<div class="mb-1">
<dashboard-input-label
identifier="document"
:settings="{ help: true, helpDirection: 'left' }"
>
Upload document
<template slot="helpText">
Maximum filesize is 5 MB. The default allowed file extensions
are: pdf, jpeg and png.
</template>
</dashboard-input-label>
<validator-v2
:identifier="identifier"
name="document_file"
:rules="{ required: { message: 'Document is required.' } }"
>
<custom-file-upload
ref="documentDocument"
v-model="documentFile"
:max-upload-file-size="5"
name="document_file"
></custom-file-upload>
</validator-v2>
</div>
and following is my button
<loading-button ref="submitBtn" size="normal">
Save & Add new
</loading-button>
This is my submitBtn method,
storeDocumentAndAddNew() {
this.isAddNew = true
const loader = this.$refs.submitBtn
this.storeDocument(loader)
},
And for the field reset I have followings,
reset() {
this.documentName= null
this.dateOfIssue= null
this.expiryDate= null
this.documentNumber = null
this.doesNotHaveDocumentNumber = false
this.doesNotExpire = false
this.documentFile = null
this.doesOptIn = false
this.isAddNew = false
this.documentFile = ''
this.$refs.documentDocument.value = null
},
Once I hit submit, every field get reset except this file upload field.
Following is my custom-file-upload.vue component
<template>
<div>
<div class="flex items-center flex-wrap">
<div #click="selectFile" class="flex items-center cursor-pointer w-full form-input custom-file-upload ">
<p class="flex justify-between items-center w-full overflow-hidden">
<span class="font-regular text-base flex items-center justify-center">
<span v-if="filename !== null">{{ filename | limitString }} </span>
<span class="cs--file-upload-current-file overflow-hidden inline-block" v-else><slot
name="currentFile"></slot></span>
</span>
<span class="text-certstyle-text-light ">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="feather feather-upload"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline
points="17 8 12 3 7 8"></polyline><line x1="12" y1="3" x2="12" y2="15"></line></svg>
</span>
</p>
<input #change="showFileName" ref="fileInput" type="file" :name="name">
<div class="flex flex-col fixed top-0 right-0 z-50">
<toastr-alert #hidden="resetToastrMessage" v-if="message !== ''" :message="message"
:type="type"></toastr-alert>
</div>
</div>
</div>
</div>
</template>
Even though I've used, this.$refs.documentDocument.value = null it's not clearing my file upload field....
Update
I have used #wendt88's answer and then the file is removed. But the previously uploaded, document's name will be remained there as it is..As an example, if I tried to upload a document called, dummy.pdf, it'll show the dummy.pdf text even after a successful submission...
Now my reset looks likes this,
reset() {
this.documentName= null
this.dateOfIssue= null
this.expiryDate= null
this.documentNumber = null
this.doesNotHaveDocumentNumber = false
this.doesNotExpire = false
this.documentFile = null
this.doesOptIn = false
this.isAddNew = false
this.$refs.documentDocument.$refs.fileInput.value = null
},
Following is my complete custom-file-upload.vue
<template>
<div>
<div class="flex items-center flex-wrap">
<div #click="selectFile" class="flex items-center cursor-pointer w-full form-input custom-file-upload ">
<p class="flex justify-between items-center w-full overflow-hidden">
<span class="font-regular text-base flex items-center justify-center">
<span v-if="filename !== null">{{ filename | limitString }} </span>
<span class="cs--file-upload-current-file overflow-hidden inline-block" v-else><slot
name="currentFile"></slot></span>
</span>
<span class="text-certstyle-text-light ">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="feather feather-upload"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline
points="17 8 12 3 7 8"></polyline><line x1="12" y1="3" x2="12" y2="15"></line></svg>
</span>
</p>
<input #change="showFileName" ref="fileInput" type="file" :name="name">
<div class="flex flex-col fixed top-0 right-0 z-50">
<toastr-alert #hidden="resetToastrMessage" v-if="message !== ''" :message="message"
:type="type"></toastr-alert>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.custom-file-upload input {
position: absolute;
cursor: pointer;
height: 0;
width: 0;
opacity: 0;
}
.cs--file-upload-current-file {
max-width: 220px;
}
label {
font-weight: 400 !important;
}
</style>
<script>
// Mixins
import HasToastrMessage from '#/Mixins/HasToastrMessage.js';
// Helper
import Helper from '#/Support/Helper.js';
export default {
mixins: [HasToastrMessage],
props: ['name', 'value', 'maxUploadFileSize'],
data() {
return {
file: null,
filename: null,
message: "",
type: "",
fileSize: 0,
maxFileSize: 10,
validFileTypes: [
'application/pdf',
'image/jpeg',
'image/png'
]
}
},
mounted() {
if (Helper.isset(this.maxUploadFileSize)) {
this.maxFileSize = this.maxUploadFileSize;
}
},
methods: {
showFileName(e) {
this.filename = collect(e.target.value.split('\\')).last();
let file = e.target.files[0];
let fileSize = file.size / 1000000;
if (fileSize > this.maxFileSize) {
this.showToastrErrorMessage(`The uploaded file is too big. Max size: ${this.maxFileSize} MB.`);
this.$refs.fileInput.value = null
this.filename = null
} else if (!this.validFileTypes.includes(file.type)) {
this.showToastrErrorMessage(`The uploaded file is invalid. Please upload valid type.`);
this.$refs.fileInput.value = null
this.filename = null
} else if (this.filename) {
this.file = file
this.showToastrSuccessMessage(`Your file is successfully uploaded.`);
this.$emit('uploaded')
} else {
this.showToastrErrorMessage(`Your file could not be uploaded. Please try again.`);
}
},
resetToastrMessage() {
this.message = "";
this.type = "";
},
selectFile() {
this.$refs.fileInput.click();
},
}
}
</script>
this.$refs.documentDocument is a vue component, to clear it´s value property use this.$set(this.$refs.documentDocument, 'value', null) -> https://v2.vuejs.org/v2/guide/reactivity.html
otherwise documentDocument does not know that you have changed it´s value
but if you want to clear the file input value, run (https://stackoverflow.com/a/16222877/1826106):
this.$refs.documentDocument.$refs.fileInput.value = null;
this.$set(this.$refs.documentDocument, 'filename', null);

Insert twice on database with unobtrusive on ASP .NET core

I have an Ajax form on my view. It relates to Newsletter
<div class="d-flex flex-column">
<div class="d-flex align-items-center">
<div class="px-lg-8">
<div class="d-flex align-items-center">
<div class=" ml-3">
<svg xmlns="http://www.w3.org/2000/svg" width="21.238" height="15.291" viewBox="0 0 21.238 15.291">
<path d="M0 0v15.292h21.238V0zm.849.849h19.54v1.062l-8.31 7.244-.04.04a2.194 2.194 0 0 1-1.42.571 2.2 2.2 0 0 1-1.42-.571c-.158-.138-1.293-1.118-2.111-1.832C4.661 5.255.974 2.021.849 1.912zm0 2.19c.737.642 3.35 2.917 5.575 4.858L.849 12.305zm19.539 0v9.266l-5.575-4.407c2.226-1.943 4.839-4.216 5.576-4.858zM7.075 8.469l1.566 1.367.013.013a3.057 3.057 0 0 0 1.965.77 3.051 3.051 0 0 0 1.978-.783c.12-.1 1.059-.913 1.58-1.367l6.212 4.911v1.062H.849V13.38z" data-name="Path 319"></path>
</svg>
</div>
<h5 class="mb-0"> #_localizer["NewsLetterMemberShip"]</h5>
</div>
<p class="my-3 ">#_localizer["ReceiveNewsLetter"]</p>
<div class="textbox-footer ">
<form asp-controller="Home" asp-action="NewsLetter" data-ajax="true" data-ajax-mode="replace" data-ajax-success="NewLetterPostSuccess">
<input asp-for="Email" id="NewsLetterEmail" class="form-control input-textbox-footer "
placeholder="#_localizer["EnterEmail"]">
<span asp-validation-for="Email"></span>
<button type="submit" class="btn btn--orange footer__send-btn">#_localizer["SendButton"]</button>
</form>
</div>
</div>
</div>
</div>
It works well. but now I see after click on newsletter ,It inserts email twice,
It has a reference:
<script src="/lib/jquery-unobtrusive-ajax/jquery.unobtrusive-ajax.min.js"></script>
If I delete this refrence, it will be work correct and insert 1 time.
This is my script :
function NewLetterPostSuccess(result) {
swal('info', result.text, 'info');
$('#NewsLetterEmail').val('');
}
I see the way for resolve is delete this reference.
But is not for ajax form?
and If I delete reference I have another misktake too.
How can resolve this problem?
I find my mistake .
It referenced to page twice with "unobtrusive" at 2 different Route.
<script src="/lib/jquery-unobtrusive-ajax/jquery.unobtrusive-ajax.min.js"></script>
I deleted one of them and It works well now.
Check all your project for the reference always! :)

How to disable click events of mat-list-item enable click of only maticon

Hi I am working on angular 5.I want to disable click event of mat-list-item want to enable only click action of mat-icon.
<mat-nav-list>
<mat-list-item
*ngFor="
let item of (speciality_list | listFilter: { name: searchText })
"
[class.disabled]="!item.status"
[ngClass]="item.id == specialityActiveId ? 'active' : ''"
(click)="onRowClick(item, 'speciality')"
>
<div matLine>
<div fxLayout="row">
<div fxFlex="80">{{ item.name }}</div>
<div fxFlex="12" >
<button class="cursor-default"
mat-icon-button
(click)="edit($event, 'speciality', item)"
>
<mat-icon class="mat-17">edit</mat-icon>
</button>
</div>
<div fxFlex="8">
<button mat-icon-button mat-icon-button>
<mat-icon class="mat-17">arrow_forward_ios</mat-icon>
</button>
</div>
</div>
</div>
</mat-list-item>
</mat-nav-list>
Thank you,
You can stop immediate propagation by doing this:
edit(event){
event.preventDefault();
// EDIT: Looks like you also have to include Event#stopImmediatePropagation as well
event.stopImmediatePropagation();
}
I referred to the following link for my solution.
mat-nav-list with secondary buttons

Selenuim/Protractor can't find or click in textbox

I have a code from a website as follows and I want to use the 5th line from code segment below <input type="text" placeholder="Enter Workflow Name"
Code
<div class="workflow-container ng-scope" data-ng-controller="sourceCode.Designer.uiComponents.conciergeScreen.templates.NewWorkflowController">
<div class="input">
<div class="wrapper top" data-ng-class="{'fill': hosted === true}">
<label class="welcome">What should your workflow be called?</label>
<input type="text" placeholder="Enter Workflow Name" class="workflow-name-textbox ng-valid ng-not-empty ng-touched ng-dirty ng-valid-parse" data-ng-class="{'error': errors.error}" autofocus="" data-ng-focus="select($event)" data-ng-model="conciergetitle" data-ng-model-options="{ updateOn: 'default blur', debounce: { default: 300, blur: 300 } }" data-ng-change="inputchange(designeritems)" data-ng-keyup="$event.keyCode == 13 && createnewstudioitem(designerItems[0], conciergetitle, $event)" style="">
<div class="errogory">
<div class="summary">
<!-- ngIf: errors.error || errors.category -->
</div>
<div class="category" data-ng-click="categorypicker($event)">
<label>Folder</label>
<i class="icon icon-set-assetbrowser icon-size16 ic-categoryserver"></i>
Workflow
</div>
</div>
<div class="concierge-button-grid">
<div class="concierge-button-container">
<button id="createWorkflow" data-button-error="false" class="concierge-button button-command" data-ng-disabled="!newWorkflowReady" data-ng-class="{ 'error': errors.button, 'is-disabled error' : errors.button }" data-ng-click="createnewstudioitem(designerItems[0], conciergetitle, $event)" disabled="disabled">
<!-- ngIf: !errors.button --><span data-ng-bind="getString('new_workflow_create_button')" data-ng-if="!errors.button" class="ng-binding ng-scope">Create</span><!-- end ngIf: !errors.button -->
<!-- ngIf: errors.button -->
</button>
</div>
<div class="concierge-button-container">
<button id="discardWorkflow" class="concierge-button concierge-button-discard button-command tertiary" data-ng-click="discard()">
<span data-ng-bind="getString('discard_workflow_button')" class="ng-binding">Discard</span>
</button>
</div>
</div>
</div>
<!-- ngIf: showrecent -->
<!-- ngIf: showrecent -->
</div>
I want to click in the textbox so that I can clear the text. I have tried the following:
describe("New Screen", function () {
it("Should give textbox a new name", function () {
browser.sleep(10000);
console.log('Enter new name');
var editName = element.all(by.className('.workflow-name-textbox'));
editName.first().click().then(function () {
console.log('Clicked on Create');
})
browser.sleep(10000);
})
I get a error: Index out of bound. Trying to access element at index: 0 ...
if I change my code above to:
var editName = element.all(by.css('.workflow-name-textbox'));
editName.click().then(function () {
console.log('Clicked on Create');
I dont get errors but I dont see any clicking going on.
I know my protractor works because I have navigated to this page using similar code.
Do anyone have suggestions what else I could try.
I had to go two iFrames down:
//Parent
browser.switchTo().frame('Iframe1');
//Child
browser.switchTo().frame('Iframe2');
//var NewTextBox = browser.findElement(by.css('.name-textbox')).clear();
var NewTextBox = element.all(by.css('.name-textbox'));
NewTextBox.clear().then(function () {
console.log('Clear text');
Did you tried this way instead of element.all.
element.all return a list elemenet and element return only single element.
var NewTextBox = element(by.css('.workflow-name-textbox'));
or
var NewTextBox = element(by.xpath('//input[#placeholder='Enter Workflow Name']'));