In my e2e, I need to check if the datatable is populated first before before checkboxes in the table are clicked.
I am able to check the count like so
cy.get('.p-datatable-table').find('tr').its('length').should('be.gte', 0);
unfortunately, the below does not work.
if (cy.get('.p-datatable-table').find('tr').its('length').should('be.gte', 0)) {
cy.get('.select-all-boxes').click();
}
Any suggestions?
You can't use the expression cy.get('.p-datatable-table').find('tr').its('length').should('be.gte', 0) to perform an if check.
The result of that expression is a chainable, so you have to chain it
cy.get('.p-datatable-table').find('tr').its('length')
.then(length => {
if ( length ) {
cy.get('.select-all-boxes').click()
}
})
Not sure what you expect with .should('be.gte', 0) but it does nothing so I dropped it.
Related
I am testing a virtual dropdown list, my code is like this:
while (!cy.contains('.ant-select-item',/^Cypress$/)) {
cy.get('.ant-select-dropdown').trigger('wheel', {deltaX:0,deltaY:100});
}
It keeps wheeling down until finds a specific element. However, this code does not work, when contains does not find the specific element, it fails the test instead of return false.
How to make the while loop work?
You can use jQuery, Cypress.$ instead.
while (!Cypress.$('.ant-select-item:contains('Cypress').length) {
cy.get('.ant-select-dropdown').trigger('wheel', {deltaX:0,deltaY:100});
}
One thing - :contains() will match partially, so this is no good if more than one item has the string.
Long version - Cypress.$('.ant-select-item:contains('Cypress') gets a list of matching elements. If none found, it does not fail but the length of the list is 0. Since 0 is falsy, the loop continues.
The loop idea is only good if the dropdown does actually contain the value somewhere, otherwise it spins forever.
While loops generally don't work with Cypress, it would be safer to use a repeating (recursive) function
function findItem(item, loop = 0) {
if (loop === 10) throw 'Too many attempts'
cy.get('.ant-select-item')
.invoke('text')
.then(textsOfCurrentList => {
if (!textsOfCurrentList.contains(item)) {
// wheel down and try next
cy.get('.ant-select-dropdown').trigger('wheel', {deltaX:0,deltaY:100})
findItem(item, ++loop)
} else {
return
}
})
})
findItem('Cypress')
Or with package cypress-recurse
recurse(
() => cy.get('.ant-select-item').invoke('text'),
(textsOfCurrentList) => {
const found = textsOfCurrentList.contains(item)
if (!found) {
cy.get('.ant-select-dropdown').trigger('wheel', {deltaX:0,deltaY:100})
}
return found // true means finish, false means repeat
},
{
log: true,
limit: 10, // max number of iterations
timeout: 30000, // time limit in ms
},
)
A good background info avoid-while-loops-in-cypress
Somehow I couldn't get my comparison operators working. I have the following piece of code:
function handleNotifClickRemind(key) {
localStorage.setItem('no_remind_change_pwd', true);
notification.close(key);
}
// ...
<Button outline size="small" onClick={() => handleNotifClickRemind(key)}>
Dont remind me
</Button>
// ...
console.log(localStorage.getItem('no_remind_change_pwd'));
function another_func(data) {
if (localStorage.getItem('no_remind_change_pwd') != true) {
openNotification('topRight');
}
}
When I clicked the "Don't remind me" button, handleNotifClickRemind was triggered because the log output on the third section prints true. However, openNotification was still being triggered. Can anyone please help?
P.S. I didn't initialize the value, I just let no_remind_change_pwd be null.
Thanks in advance.
All you've saved in localstorage are strings.
So you are comparing "true"!=true which is always true.
If you want to compare the value, you can use like the following.
JSON.parse(localStorage.getItem('no_remind_change_pwd')) != true
That means, the following is true
console.log(JSON.parse("true") === true)
It's always good practice to use triple comparison operator like === or !==.
localStorage.getItem() return data in String format so if you want to compare with some boolean then first convert it to boolean. By Boolean(localStorage.getItem('no_remind_change_pwd')).
function another_func(data) {
if (Boolean(localStorage.getItem('no_remind_change_pwd')) !== true) {
openNotification('topRight');
}
}
Hope this should clear your understanding.
I have an autocomplete input.
Every time a letter is entered or deleted I do an HTTP request.
The response is mapped to a list of suggestions, which I show in a dropdown beneath the input.
However: If the last letter is deleted, making the input empty, I want to skip the HTTP request etc. and return an empty array instead.
So I need an operator called first in the pipe, which every time a condition is met skips all operators below and "returns early" just like a "break" or "return" statement in a for loop.
I cannot use filter(), because this operator would prevent the resulting observable to emit. But I need it to emit to clear the dropdown.
<input [formControl]="formGroup.searchTerm">
<ul>
<li *ngFor="let suggestion of suggestions$ | async">{{suggestion}}</li>
</ul>
suggetions$ = this.formGroup.valueChanges.pipe(
pluck('searchString')
// filter(searchString => searchString.length > 0) // does not help
unknownOperator(searchString => {
if(searchString.length === 0) {
skipOperatorsBelowAndReturnThisInstead([])
} else {
continueWithOperatorsBelow(searchTerm)
}
})
switchMap(values => this.http.get(this.url + values.term)),
map(this.buildSuggestions),
),
Thanks!
You can't skip all operators below with an operator. You have to switch to a different stream depending on a condition.
suggetions$ = this.formGroup.valueChanges.pipe(
pluck('searchString'),
switchMap(searchString => searchString.length === 0
? of([])
: this.http.get(this.url + searchString).pipe(
map(this.buildSuggestions)
)
)
);
I am creating an app in Vue that will filter items in a JSON object. I am having issues with adding a checkbox type filter to this app, because I only want the checkbox filter to run if at least one checkbox is checked, and not to run if none are checked. So currently I have:
computed: {
filteredJobs: function(){
var filteredList = this.jobs.filter(el=> {
return el.title.toUpperCase().match(this.search.toUpperCase())
&& el.employmentType.toUpperCase().match(this.selectedJobType.toUpperCase())
&& el.customText12.toUpperCase().match(this.selectedLocation.toUpperCase())
&& el.dateAdded >= this.checkedDate
});
if (!this.checkedServiceAreas.length) {
return filteredList;
}else{
return filteredList.filter(job => this.checkedServiceAreas.includes(job.categories.data.map(({name}) => name).join(' ')));
}
}
}
So I am doing most of my filtering using select dropdowns, which makes it easy to use the match method to filter the JSON object, but for checkboxes it is a little more difficult because they can be multiple checked. How I currently have it set up is in an IF statement to only filter the checkedServiceAreas if there is at least one checkbox checked. If there isn't just run my normal filtered method.
What I am trying to do is figure out a way to incorporate my IF statement into my filter method without having to do it in two steps like I have above.
return el.title.toUpperCase().match(this.search.toUpperCase())
&& el.employmentType.toUpperCase().match(this.selectedJobType.toUpperCase())
&& el.customText12.toUpperCase().match(this.selectedLocation.toUpperCase())
&& el.dateAdded >= this.checkedDate
&& (this.checkedServiceAreas.length === 0 ||
this.checkedServiceAreas.includes(el.categories.data.map(({name}) => name).join(' '))));
I have a fullcalendar where I display non-editable events which are collected from a google calendar, or from a database. Then I want to register customer requests for events from the calendar. This works, but I am not able to list only the events that are added by the user.
Any hint on how to do this?
I tried this:
function retrieve_events() {
var rdv=$('#calendar').fullCalendar( 'clientEvents', undefined);
for (i=0; i<=rdv.length-1; i++) {
/*alert(rdv.toSource());*/
alert(rdv[i].title+" id: "+rdv[i].id+" start: "+rdv[i].start+" end:"+rdv[i].end+" heldag:"+rdv[i].allDay);
}
}
The the "undefined" as id, means that I have given all the non-editable events an id, while the new ones haven't got one. But this way I get all events listed, even those without an id. The same happens with null and ''. But using hardcoded id-numbers returns that specific event.
I see from the documentation that there seems to be other ways to get hold of the events I need, by using other criteria like classes. However I cannot figure out how to specify this filter.
I haven't worked with FullCalendar yet nor do I intend to extensively test this, so I cannot guarantee that this will work.
However, why don't you simple test whether rdv[i].id evaluates to false?
Try:
function retrieve_events( ) {
var rdv = $('#calendar').fullCalendar('clientEvents'),
results = [];
for( var i = 0; i < rdv.length; ++i ) {
if( !rdv[i].id ) {
results.push(rdv[i]);
}
}
return results;
}
P.S.: Passing undefined to .fullCalendar() probably is redundant. It would be equivalent to passing only a single variable. I'd guess the second parameter is a type of events that you can filter for, but passing only a single parameter would cause the plugin to return all events. Also, note that !!'' === false.
The internal check whether the second parameter is set is probably similar to this:
$.fn.fullCalendar = function( command ) {
switch( command ) {
// ... some case's
case 'clientEvents':
var filter = arguments[1];
if( !filter ) {
// Retrieve ALL client events
}
else {
// Filter client events
}
break;
// ... some more case's
}
};
This does not compare types. Testing filter === false would only return true, if filter would evaluate to false and is a boolean.
Following are examples of values that evaluate to false. There may be more, but I believe those are all.
undefined
null
0
false
''