Cypress: Check if Select Option Exists - javascript

I'm trying to check if there is an option in my select using the code below, but it keeps failing, can somenone give some help?
My Select have about 70 names and I'm trying to loop all them looking for the specific name.
cy.get('[id="names"] option').each(($ele) => {
expect($ele).to.have.text('Have This Name')
})
Thanks in advance,

I would not use .each(), only one will pass but any other will fail.
Use .contains() if your text is specific enough (not in multiple options)
cy.contains('[id="names"] option', 'Have This Name') // fails only if
// no option has the text
If you have to match exactly, filter the options
cy.get('[id="names"] option')
.filter((idx, el) => el.innerText === 'Have This Name') // fails if filter
// returns 0 items
If you want .each() for another reason, this will do
let found;
cy.get('[id="names"] option')
.each(($option) => {
if ($option.text() === 'Have This Name') {
found = $option
return false // return now, have found it
}
})
.then(() => { // after loop exit
expect(found).to.have.text('Have This Name')
})

You can handle the scenario like this-
cy.get('[id="names"] option').then(($ele) =>
{
if ($ele.text().includes('Have This Name'))
{
// do your statements
}
else
{
// do your statements
}
})

Related

Cypress - Working with div tables - Validating text on each row

I want to check if the first column of each row's text starts with "AA", "BB" or "CC". But I couldn't manage it on div table. I can only select and check the first row (code below). But I also tried with selecting the whole column and tried with using cy.each & cy.wrap and got errors too.
How can I check the first column for each row's text? (Table has 40-45 rows.)
The table looks like this:
Right now I can only check the first row with the code below. How can I check all the rows like this? Is the code below clear to you by the way?
cy.get('div[row-index="0"]')
.eq(1)
.invoke('text')
.then(text => {
const productID = text.trim();
let correctProductIDPrefix = false;
['AA', 'BB', 'CC'].forEach(possibleProductIDPrefix => {
if (!correctProductIDPrefix) {
correctProductIDPrefix = productID.startsWith(possibleProductIDPrefix);
}
});
expect(correctProductIDPrefix).to.be.true;
});
Thanks in advance!
To perform the same test on all rows
select all the rows (change [row-index="0"] to [row-index])
use .each() to run test on all rows
sub-select just the column you want, in case some other column also has the prefix and gives you a false-positive result
use Array.some() method to check at least one prefix matches
const possibleProductPrefixes = ['AA', 'BB', 'CC'] // define once outside test
cy.get('div[row-index]') // selects every row
.each($row => {
const $col = $row.find('[col-id="orderNumber"]') // pick out the column
const productId = $col.text().trim()
const correctProductIDPrefix = possibleProductPrefixes.some(prefix => {
return productId.startsWith(prefix)
})
expect(correctProductIDPrefix).to.be.true;
});
Ref Array.prototype.some()
The some() method tests whether at least one element in the array passes the test implemented by the provided function. It returns true if, in the array, it finds an element for which the provided function returns true; otherwise it returns false. It doesn't modify the array.
You can do something like this:
let prefix = ['AA', 'BB', 'CC']
cy.get('.ag-cell-value').each(($ele, index) => {
expect($ele.text().trim().startsWith(prefix[index])).to.be.true
})

Conditionally assert element values in DOM depending on it's value in backend with Cypress?

Trying to do Cypress Testing with my React app.
I'm retrieving an object with an attribute expirationDate from the backend. It's an integer with format YYYYMMDD. In my corresponding frontend in the <input> component, it's rendered as an YYYY-MM-DD string.
However the object may optionally not have an expiration date at all, which is instead represented as the attribute being -1 or -2. This is presented as an empty string '' in the <input>.
I thus need to conditionally check the value. How do I go about doing this with Cypress?
Closest I have right now is
cy.get('#input-expiration-date').should('have.value', expirationDate || '')
But this is not really an accurate test of the above conditions.
Conditional testing can be done as follows, but this is bad practice.
cy.get('#input-expiration-date')
.invoke('val')
.then(val => {
if (val === expirationDate) { // fails because page is still fetching
...
}
})
The test runs faster than the value can be fetched from the server.
You can avoid the issue by waiting for the object fetch with cy.intercept() and do the conditional check then.
let expirationDate = 'YYYYMMDD'
cy.intercept(url).as('object')
cy.visit(...)
cy.wait('#object').then(object => {
if (object.expirationDate) {
cy.get('#input-expiration-date')
.should('have.value', expirationDate)
}
})
you can do:
cy.get('#input-expiration-date').then(element => {
//and here you can have conditions and access the DOM element
})
There a Chai method oneOf() you can use.
Cypress uses Chai internally, so the expression works inside .should().
cy.get('#input-expiration-date')
.invoke('val')
.should('have.oneOf', [expirationDate, ''])
Using Chai directly
cy.get('#input-expiration-date').then($input => {
expect($input.val()).to.have.oneOf([expirationDate, ''])
})
Or if you want to check and further do some actions based on the value, you can do something like this:
cy.get('#input-expiration-date')
.invoke('val')
.then((val) => {
if (val == expirationDate) {
//Do something
} else if (val == '') {
// Do something
} else {
//Do something
}
})

Find texbox value match in an array

I am trying to look for texbox values matching an array I have provided a code snippet below:
$('#message').on('keyup', function () {
suggest_array_sample = [
{ array_val: "#{person1}" },
{ array_val: "#{person2}" },
{ array_val: "#{person3}" }
];
found_variable_array = [];
$.each(suggest_array_sample, function (key, value) {
console.log(value);
if ($.inArray(value, textbox_value)) {
console.log('found');
found_variable_array.push(value);
} else {
console.log('not found');
}
})
console.log(found_variable_array);
});
<textarea id="message"></textarea>
The problem is it always return the whole array instead of just the matches the ouput should be when I type #{person1} on the textbox the output should be
[{array_val:"#{person1}"}] //expected output
[{array_val:"#{person1}"},{array_val:"#person2"}]// expected output when two or more matches are found on the textbox
instead of
[{array_val:"#{person1}"},]{array_val:"#{person2}",{array_val:"#{person3}"}] //current output
is this possible using the inArray() or do I need to change the code.
use filter method of Array.
yourArray.filter ( yourArrayModel => yourArrayModel.fieldValue === yourSearchValue )
In your case yourSearchValue can be “{#person1}”
For more information, look for filter method documentation, i hope this is what you want.
$.inArray return a position, if not found return -1 else return >= 0
The $.inArray() method is similar to JavaScript's native .indexOf()
method in that it returns -1 when it doesn't find a match. If the
first element within the array matches value, $.inArray() returns 0
Try this code
$('#message').on('keyup', function () {
textbox_value = $(this).val();
suggest_array_sample = ["#{person1}", "#{person2}", "#{person3}"];
console.log($.inArray(textbox_value, suggest_array_sample));
});
It's not entirely clear what you're trying to achieve. I've written something using $.inArray that tells you the array index of the found value. You need to use .map() on the array to extract the val you want.
EDIT:
From what I understood of your comment, I've now had the value be added to found_value_array each time the value is found.
Or is it that you want an array to be returned because the same value might appear multiple times?
let found_variable_array = [];
$('#message').on('keyup',function(){
suggest_array_sample = [
{array_val:"#{person1}"},
{array_val:"#{person2}"},
{array_val:"#{person3}"}
]
let index = $.inArray($(this).val(), suggest_array_sample.map(o => o.array_val));
if (index >= 0) found_variable_array.push(suggest_array_sample[index]);
console.log(found_variable_array);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="message"></textarea>
After combining ideas presented here this method work for me
match_value = suggest_array.filter(function(result){
if(textbox_value){
return textbox_value.search(result)>-1
}
else{
return false
}
})
console.log(match_value);

How to reset filter in Angular 4

Currently I have multiple filters. I would like to reset the filter however, its not working.
showOnlyMyRequest(){
this.requests = this.requests.filter(request => request.requestedBy === 'John Doe');
}
showAllRequest(){
this.requests = this.requests.filter(request => request.requestedBy === '*');
}
In the above example the showAllRequest() doesn't reset the previous filter.
From MDN web doc :
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
So your requests array becomes the one .filter() returned, you should stock your filtered values somewhere else if you need to either show your requests filtered or not.
In case if you decide to send a parameter to your search function from your search text field you can try this.
let me know if there is a better solution so I can improve myself too. Thanks in advance.
showAllRequest(parameter1){
if (parameter1 === '') {
/* call getmethod or the whole array variable got during get mehtod
*/
}
this.requests = this.requests.filter(request => request.requestedBy
=== '*');
}
coded version below :
filterform(search) {
if (search === '') {
this.getFormSettings();
}
this.requests = this.requests.filter(request =>
request.requestedBy.indexOf(search.toLowerCase()) >= 0 === '*');
}

Search does not clear filter

I need to do a search on a text field (mongodb). The Search criteria / filter on the collection can be any substring of the sting in the field. I save the filter (input) in a session variable. The filter seems to work the first time after the Sessionvariable is null.
After the first search I get no result when I enter a new (extisting!) value. In case I clear the filter, hit enter and than reenter the filter I get the result.
I assume that my code is suboptimal. Can someone please review and maybe make a suggestion?
Here is what I have:
html:
<input class="medinput" maxlength="80" type="text" name="nameSearchBar" id="nameSearchBar" value="{{searchText}}">
javascript:
Session.setDefault('searchText', null);
Template.questions.helpers({
questions:function(){
if ((Session.get('searchText') === null) || (Session.get('searchText') === '')) {
Session.get('searchText',null);
return Questions.find({archived:{$ne:true}});
} else {
var searchText = Session.get('searchText');
Session.get('searchText',null);
return Questions.find( { $and: [ { archived: { $ne: true } }, {note:{$regex: (".*"+searchText+".*") } } ] } )
}
},
searchText:function(){
return Session.get('searchText');
}
})
Template.questions.events({
"change #nameSearchBar":function(event){;
searchText = event.target.value;
Session.set('searchText', searchText);
}
})
Questions:
why do I need to first "enter" an empty string to get a valid result
is this a good procedure? Doesn't hitting enter works against the reactive
approach? I think after enter the complete page is resent ??
Would it be better to check "keyup" for ASCII 27 and 13?
it seems to me that the regex works, are there any concerns? I like to find any substring of the typed in filter, also when the filter has a whitespace.
this is a full text search do I need to set something up on the mongodb side?
Open Question: are the already prebuild implementiations - I do not need to reinvent the wheel...
Here's my interpretation, or how I would possibly have built this:
Template.questions.helpers({
questions:function(){
var searchText = Session.get('search-text');
if(searchText && searchText != '') {
return Questions.find({$and: [{archived: {$ne: true}}, {note:{$regex: (".*"+searchText+".*")}}]});
} else {
return Questions.find({archived: {$ne: true}});
}
}
});
Template.questions.events({
"keyup #nameSearchBar": _.throttle(function(event){
searchText = event.target.value;
Session.set('searchText', searchText);
}), 500)
});
To me it doesn't seem necessary to set a default, or to call Session.get('search-text', null). Also you'll see how my code is a bit more concise. keyup is probably more effective as an event here too.
N.B. The _.throttle is an underscore.js function which will limit changing the Session variable to only every 500ms rather than constantly. This helps save unnecessary server load.
Two pre-built packages that are popular amongst Meteor developers are worth looking into: Easy Search or Search Source
I copied a generally working example for a search on a single text field.
#Ian: Thanks for the suggestion! I took the toggle part, I found that you can not leave the session variable as is, even it gets over written, it must evaluated before. So it has to be set back with NULL.
Session.setDefault('searchText', null);
Template.questions.helpers({
questions:function(){
if ((Session.get('searchText') === null) || (Session.get('searchText') === '')) {
return Questions.find({archived:{$ne:true}});
} else {
var searchText = Session.get('searchText');
return Questions.find( { $and: [ { archived: { $ne: true } }, {note:{$regex: (".*"+searchText+".*") } } ] } )
}
},
searchText:function(){
return Session.get('searchText');
}
})
Template.questions.events({
'keyup #nameSearchBar': _.throttle(function(event){;
Session.set('searchText',null);
searchText = event.target.value;
Session.set('searchText', searchText);
},500)
})

Categories