Cypress: store value in a variable - cypress

I want to store a td value in a variable. Why this code doesn't work?
let storedValue;
cy.get('tbody>tr:nth-child(1)>td:nth-child(3)').invoke('text').then(text =>
{
storedValue = text;
})
cy.contains(storedValue).should('exist');
It returns "cy.contains() can only accept a string, number or regular expression"

A better approach would be to use aliases.
cy.get('tbody>tr:nth-child(1)>td:nth-child(3)').invoke('text').as('storedValue')
cy.get('#storedValue').then((storedValue) => {
//Access storedValue here
cy.log(storedValue) //prints value
})
Or if you just want to check whether the element exists or not, you can directly do:
cy.get('tbody>tr:nth-child(1)>td:nth-child(3)').should('exist')
And for the question of why is your code not working, its because javascript works asynchronously, so instead of the code that gets the text first, the contains statement is executed first and the reason it fails is that storedValue doesn't have anything in it, in short, it is undefined. To fix then you have to add then() so that the code runs in a sequence we intend it to run in.
let storedValue
cy.get('tbody>tr:nth-child(1)>td:nth-child(3)')
.invoke('text')
.then((text) => {
storedValue = text
})
.then(() => {
cy.contains(storedValue).should('exist')
})

Related

How to Assert from multiple possibilities in Cypress? One option could be true out of multiple

I have a scenario, where i need to put Assertion on an element's text which could be true OR pass the test case, if the any 1 value is present out of many.
Let say, an element can contain multiple status' : 'Open', 'Create', 'In Progress' any of these could be true.
How can i implement this scenario and Assert with OR logical operator or any other way?
cy.get('element').should('have.text', 'Open' | 'Create')
It sounds like a one-of assertion, something like the following:
cy.get('element')
.invoke('text')
.should('be.oneOf', ['Open', 'Create'])
To do it you need to extract the text before the assertion.
For reference see chaijs oneOf
Asserts that the target is a member of the given array list. However, it’s often best to assert that the target is equal to its expected value.
These both Worked:
cy.get('element')
.invoke('text')
.should('satisfy', (text) => text === 'option1' || text === 'option2')
OR
cy.get('element')
.invoke('text')
.should('be.oneOf', ['option1', 'option2']);
Wodens answer is most valuable if you wish to make an assertion and have the test fail if one of them doesn't exist
However, if you want to check the text of the element that is visible and do separate things based on which one is available:
cy
.get('element')
.filter(':visible')
.invoke('text')
.then((text) => {
if(text.includes('Open')){
// Things that only occur when Open is present
} else if (text.includes('Create')){
// Things that only occur when Create is present
} else if (text.includes('In Progress')){
// Things that only occur when In Progress is present
} else {
// Things that happen when the options are exhausted
}
});

How to assert a specific text in cypress

Please see the below code.
I am trying to assert value 2 but my code is not working.
You do something like this:
cy.get('#_evidon_message').should('contain.text', '2')
Based on the information you provided, it isn't clear if you want to check the entire text within the div or just for the number before partners.
If you only want to validate there is a 2 within the entire string, then:
cy.get('#_evidon_message')
.invoke('text')
.should('include.text', '2')
You can use also use regex on the string as well.
cy.get('#_evidon_message')
.invoke('text')
.then(text => {
const regexMatcher = /(\d+) months with (?<numPartners>(\d+)) partners/i
const numPartners = text.match(regexMatcher)?.group?.numPartners
expect(numPartners).to.eq(2)
})
The bold tags <b> are interfering with your text evaluation. It's actually HTML inside
cy.get('#_evidon_message').then($el => {
const html = $el.html()
console.log(html) // yields same as screenshot
})
To access the inner <b> use additional commands, for example
cy.get('#_evidon_message')
.find('b')
.eq(2)
.should('contain', '2')

What is the best way to assert that a component contains a string "case insensitive" using Cypress?

I want to assert that a component contains a string without caring about the string case.
For example, I want
cy.get('#label').should('contain.text', 'integrator');
to pass even if the label contains "Integrator."
What is the best way I can make this assertion?
You can also use cy.contains() with a regular expression
cy.contains('#label', /integrator/i) // should is implied in this command
or as an option
cy.contains('#label', 'integrator', {matchCase:false})
With should() you get retry of the expect()
cy.get('#label')
.should($el => {
expect($el.text().toLowerCase()).to.eq('integrator') // exact
// or
expect($el.text().toLowerCase()).to.contain('integrator') // partial
})
What you need is Regular expressions.
You can use the match assertion:
cy.get('#label')
.invoke('text')
.should('match', /integrator/i) //i = case sensitive
You can do like this as well:
cy.get('#label').then(($ele) => {
expect($ele.text().toLowerCase()).to.contain('integrator')
})

get a string and convert it to a variable and assign to a variable in cypress

Hi I want to get this value, convert it to a number and assign as a variable. Then I can do calculations. Can someone help on this?
Tried this not working.
const marks = cy.get('.ant-typography \> span').invoke('text').then(parseInt).should('be.gt', 10)
cy.log('The value is '+ marks)
.ant-typography > span // this is the locator
You need to use .then() to access the variable
cy.get('.ant-typography > span')
.invoke('text')
.then(parseInt)
.should('be.gt', 10)
.then(marks => {
cy.log('The value is '+ marks)
})
Can I return this "marks" value so I can use it outside the .then() method?
See the docs Gleb references, once you have an asynchronous command (even just a .get()) you are pretty much stuck with using a .then() to access values derived from them.
Even an alias does not help - you need a .then() to get it's value.
Please read about Cypress commands https://docs.cypress.io/guides/core-concepts/introduction-to-Cypress#Commands-Are-Asynchronous
For your situation specifically, watch https://www.youtube.com/watch?v=-aptS3yvqcc
You can use an alias to save the value in the variable like this:
cy.get('.ant-typography > span').invoke('text').as('marks')
cy.get('#marks').then((marks) => {
cy.log('The value is ' + marks) //logs marks
cy.wrap(+marks).should('be.gt', 10)
})

CaspserJS assertEval with variables

I'd like to use CasperJS to evaluate a variable equals a certain value.
I simplified my exemple as much as I could that way:
var testDate = "24/03/14";
casper.test.begin('TEST', 1, function suite(test) {
casper.start('http://www.google.com/', function() {
this.test.assertEval(function() {
return testDate == "24/03/14";
}, "testDate is 24/03/14" );
});
casper.run(function() {
this.test.done();
});
});
I don't know why it fails, here is what I get in my console:
Test file: tests.js
#TEST
FAIL testDate is 24/03/14
# type: assertEval
# file: tests.js:7
# code: }, "testDate is 24/03/14" );
# subject: null
# fn: undefined
# params: undefined
FAIL 1 test executed in 2.896s, 0 passed, 1 failed, 0 dubious, 0 skipped.
Details for the 1 failed test:
In tests.js:7
TEST
assertEval: testDate is 24/03/14
Any idea ?
UPDATE
I realised my simplified example was faulty, it didn't represent what I really needed.
Actually, what I want to achieve is to test if a variable from the current page DOM context equals a local variable.
As per manual Asserteval:
Asserts that a code evaluation in remote DOM strictly resolves to a boolean true:
your testdate variable is local to the casperjs script and is not accessible in the remote dom. You would have to inject it to the window like described here.
Ok found the answer myself.
To test if a variable from the current page DOM context equals a local variable, I realised I could use a simple assertEvalEquals():
test.assertEvalEquals(function() {
return variableFromPageDomContext;
}, localVariable);
Likewise, when testing if a variable from the current page DOM context matches a RegExp pattern, we have to use evaluate() to get the variable from the DOM as the first parameter of an assertMatch():
test.assertMatch(this.evaluate(function() {
return variableFromPageDomContext;
}), RegExpPattern);
Hope that can help.
As #Surreal answers its possible to use the assertEvalEquals() passing the function and the expected value.
However the original question wants to pass a variable from casperjs context to assertEval() function, you can simply do it as follows, passing to assertEval() three arguments: the function which receive the value, a message for the assert and the value:
var varPassToEval = 'someValue';
test.assertEval(
function(varFromCasperContext){
return varFromPageDomContext === varFromCasperContext;
},
'Assert Eval to test',
varPassToEval
);
With the above example probably is clear to use assertEvalEquals() however could be useful for more complex cases, for example imagine that you want to check if a text appears in a some <li> inside <ul> in DOM which it's dynamic and can change but you don't know at first where your text is... for this case you can use:
var somePartOfText = 'blue';
test.assertEval(
function(varFromCasperContext){
return document.getElementsByTagName("ul")[0].textContent.indexOf(varFromCasperContext) != -1;
},
'Assert Eval to test',
somePartOfText
);
Hope it helps,

Resources