Cypress - How to use if statement with contains - cypress

so I have to use cy.contains to find the element I want, but all I can find online is how to use if() with cy.find or cy.get if there a way to do this with contains?
Example code:
if(cy.contains('div.name', 'Test 1').length > 0) {
//Type in name
cy.get('input.newName').click().type('Test 1');
cy.wait(2000);
//Click Add Name
cy.get('div.createNewName> a').click();
cy.wait(2000);
}
What I am trying to do there is:
if(Name doesnt exist){
Create it
}
I'm not sure if I have explained myself too well, if any more clarifications are needed feel free to ask

You can also do like this:
cy.get('body').then(($body) => {
if ($body.find('div.name:contains("Test 1")').length > 0) {
//Element Found
} else {
//Element not found
}
})

The general pattern for this would be as follows:
const element = Cypress.$('div.name:contains(Test 1)')
if (element.length > 0) {
...
Make sure the DOM is stable when you run this code, there is no retry built in as there is with cy.contains()
If the code inside if() is creating the name, then maybe the logic would be
const element = Cypress.$('div.name:contains(Test 1)')
if (element.length === 0) {
// not found so create it
...

You can also do it like this
cy.get('div.name').then($div => {
const found = $div.find(':contains("Test 1")')
if (found.length === 0) {
// create...
}
})

Related

Cypress Custom Command - Break from a .each() loop and return a value to be used in further steps

I am new to Cypress [3 days :)]. I am creating a custom command which is trying to find the column index of column in a table.
I want to return the column index and store it in a variable and use it in future steps.
Here is what I have tried:
Cypress.Commands.add('get_table_column_index', (columnName) => {
cy.getIframeBody().find('table').within(() => {
cy.get('tr th[scope=col]').each((element, index) => {
let colName = element.text();
cy.log(index, colName);
if(colName == columnName)
{
cy.wrap(index).as('index');
return false;
}
});
});
});
let columnIndex = cy.get_table_column_index('ColName').get('#index');
cy.log('index' + columnIndex);
index is [object Object]
Can someone please guide me in resolving this issue?
What am I doing wrong?
I can see that wrap is returning the correct index value but I am not sure how to extract and use it.
======= Update =========
I tried this and looks like it was able to log the correct value:
let columnIndex =
cy.get_table_column_index(column_name).get('#index');
columnIndex.then(index => cy.log(index));
Now, I am trying to expand it to use the index value in the next step like this:
Cypress.Commands.add('get_text', (row_num, column_name) => {
let txt;
cy.test_index(column_name).get('#index').then(index => {
let element = cy.get('main > table').within(() => {
cy.log('${index');
cy.get('tr:nth-child(${row_num}) td:nth-child(${index})');
//txt = element.text();
cy.log(txt);
});
});
return txt;
})
I am not able to figure out how to use the value of index and row_num in cy.get('tr:nth-child(${row_num}) td:nth-child(${index})'; expression.
Error: Syntax error, unrecognized expression: :nth-child
All you need to do is change the way that you are using variable.
cy.log(this.index + columnIndex);
I was able to get this working like this:
.get('#index').then(....
was used to extract the value of the index which is returned by my method get_table_column_index.
Then used cy.wrap again to return the cell value.
Cypress.Commands.add('get_text', (row_num, column_name) => {
cy.get_table_column_index(column_name).get('#index').then(index => {
cy.get('main > table').within(() => {
cy.get(`tr:nth-child(${row_num}) td:nth-child(${index})`)
.invoke('text')
.then((text) => {
cy.log("Text = " + text);
return cy.wrap(text).as('cell_value');
})
});
});
})
Then finally in my method call:
let cell_text = cy.get_text(2, 'Licensing').get('#cell_value');
cell_text.then(cell_value => {
cy.log(cell_value);
expect(cell_value).to.include('QTP');
})
The only thing I am not able to do is to store the value in a variable and use it without chaining any command like then to extract its value.
It would be great if someone can provide more information on that.
Thanks.

cypress: How can manage the application flow, if the element xpath is not present

I have the following scenario:
if the element is present, i have to do one activity and if not present will do another activity.
cy.xpath("//div[text()= 'button').its('length').then(res=> {
if (res > 0) {
return 1;
}
else {
cy.log ("Element is not present")
}
}
)} '''
if element is present = Code is working fine,
if the element xpath is not present = it try to search the element xpath (//div[text()= 'button') and throwing the error as 'Timed out retrying: Expected to find element: undefined, but never found it.'
if element is not present, Is there any way, i can handle the code ,
When using xpath you can (sort of) make it conditional by wrapping the xpath selector with count().
cy.xpath("count(//div[text()= 'button'])") // ok with async content
.then(count => {
if (count) {
//return 1; // not useful, returns a "chainer"
// ...but you can perform the required test here, e.g
cy.xpath("//div[text()= 'button']").click()
} else {
cy.log('not found')
}
})
The shorter syntax using built-in jQuery might be
const exists = !!Cypress.$("div:contains('button')").length
if (exists) {
cy.xpath("//div[text()= 'button']").click()
} else {
cy.log('not found')
}
Note that this is a partial match to 'button', where-as the xpath syntax is an exact match.
Also note - using Cypress.$ by-passes retry-ability, so it should not be used where the text is asynchronous.
From docs
This is a great way to synchronously query for elements when debugging from Developer Tools.
The implication is that it's more for debugging after the page has loaded.
The best practice is to try to construct the test and the app's data in such a way that you know that the button is present.
You can do something like this. With Cypress.$, you can validate the presence of the element with the help of the length attribute and then do further actions.
cy.get('body').then($body => {
const ele = $body.find('selector');
if (Cypress.$(ele).length == 0) {
//Do Something element is not present
}
else if (Cypress.$(ele).length > 0) {
//Do Something when element is present
}
})

Laravel Search Condition Problem. When condition is value empty, then go to else condition. But it's not work properly

This is my search code please see then solution, thank you.
You have to use like this
$report_ex = Expenses::where(condition)->where(condition)->get();
or
$report_ex = Expenses::where(condition)->where(condition)->first();
If you are using
$report_ex = Expenses::where(condition)->where(condition)->first();
then you need to call
if(!empty($report_ex))
{
// your code
}
else
{
//your code
}
But if you are using
$report_ex = Expenses::where(condition)->where(condition)->get();
then you should use
if(count($report_ex) > 0)
{
// your code
}
else
{
// your code
}
since get function returns an empty object

Shopify Hide unavailable option variants

Using the Debut theme in Shopify, I have a product with variants that are not compatible. At present they show as unavailable but I want to hide them totally so that only valid options show with each other. So as example if I have Red, Blue, Green shoes and have sizes 9,10,11. But can only get Red shoes in Size 10. I don't want to see options for 9 or 11 ever.
Online someone pointed to theme.js and the code below, but I'm not sure what to change.
Thanks
$(this.singleOptionSelector, this.$container).on(
'change',
this._onSelectChange.bind(this)
);
}
I've just spend most of the day on this, and have come up with the following, which seems to work nicely on the site I'm developing.
The answer I came up with involves editing the assets/theme.js file. At present, the code below disables the select options which are not relevant by checking them against the available variant combinations, but you could easily adapt the below to hide them and then show them instead with CSS.
assets/theme.js
The _hideUnavailableOptions method below needs to be added to the Variants.prototype object.
You then need to call the method from two different places, see below.
_hideUnavailableOptions: function() {
const option1 = document.getElementById("SingleOptionSelector-0");
const option2 = document.getElementById("SingleOptionSelector-1");
if (option2) {
const secondOptions = option2.options;
const variants = this.product.variants;
let possibles = [];
variants.forEach((variant) => {
if (variant.options.includes(option1.value)) {
possibles.push(variant.options)
}
})
for (let option of secondOptions) {
const value = option.value;
let flag = false;
possibles.forEach((possible) => {
if (possible.includes(value)) {
flag = true;
}
})
if (flag === false) {
option.removeAttribute('selected');
option.setAttribute('disabled', 'disabled');
} else {
option.removeAttribute('disabled');
}
} option2.querySelector(':not([disabled="disabled"])').setAttribute('selected', 'selected');
}
},
Call the method as follows:
function Variants(options) {
//stuff before this, then...
this.enableHistoryState = options.enableHistoryState;
this._hideUnavailableOptions(); //N.B. this MUST be before the next line
this.currentVariant = this._getVariantFromOptions();
}
...and again, call the method from Variants.prototype._onSelectChange() - make sure it's the first line in there...
_onSelectChange: function() {
let hideUnavailable = this._hideUnavailableOptions(); //N.B. this MUST be before the next line
var variant = this._getVariantFromOptions();
//lots more stuff follows...
}

Filter multi-key dimension with dc.selectmenu

I have attempted to extend this fiddle
https://jsfiddle.net/rn3ja9n4/
here
https://jsfiddle.net/thyfoubq/32/
but it is unclear what I should use to power the dc.selectmenu or if the it is even capable of working in the multi-key scenario.
Is this possible?
I have tried several variations of this but i can't seem to get the filter to work with the composite key or the single branch key
var storedim =ndx.dimension(function(d){ return [d.store]})
var storegroup =storedim.group()
storeselect
.dimension(storedim)
.group(storegroup)
.multiple(true)
.size(5)
.controlsUseVisibility(true)
.title(kv => kv.key);
----------------------- possible solution that appears to work---------
---change the group to remove empty bins
var suppliersSumGroup = remove_empty_bins(suppliersSumDistinct.group().reduceSum( d => d.earnings ));
function remove_empty_bins(source_group) {
return {
all:function () {
return source_group.all().filter(function(d) {
return d.value !=0; //appears to work borrowed from another SO post
//unsure which one but it seems logical and works for this example
});
}
};
}

Resources