Context: I have an element with innerText in Page1 and another element with innerText on Page 2. And I need to compare these two values in Page 3. So I need to find a way to save these values in a variable globally so that they can be used later.
Things I tried:
Trial 1: Didn't work as page1value scope is limited to the cy.get()
cy.get('#selector').invoke('text').then(text => {
const page1value = text
})
Trial 2: Didn't work as whenever I try to print the value outside, it comes as undefined or the value with which it was initialized it with.
it('TC Name', () => {
let page1value,
cy.get('#selector').invoke('text').then(text => {
page1value = text
})
cy.log(page1value) //comes as undefined
})
Trial 3: Using .as() as well its coming as undefined.
let page1value;
cy.get('#selector').invoke('text').as('page1value');
cy.log(page1value) //comes as undefined
It would be great if someone could tell me where I am doing wrong.
Cypress commands are pushed (enqueued) into a queue (called the Command queue --- which is basically an array), and then executed serially (one after another), and asynchronously.
While your cy.log()
will be executed asynchronously, too, after the previous command, the value you pass to it (page1value
) is passed/evaluated synchronously, at the time you push the command to the queue (which is evaluated at the time the callback passed to it()
is called --- at the beginning of the test).
This is just regular JavaScript behavior, and has nothing to do with Cypress. All the commands cy.*
are just methods (functions) on the cy
object, and they're called immediately. What is not called (executed) immediately, is the logic that each command does (e.g. query the DOM for the selector you supply to cy.get()
, log to Command log when you call cy.log('string')
, etc.).
Thus, in your 2nd example:
page1value
.cy.get()
, cy.invoke
, cy.then()
.cy.log
, to which you pass page1value
(which at this time is still undefined
).cy.then
command takes turn to execute, the page1value
variable is assigned, but it's no longer used (read) anywhere for the rest of the test (recall that you've already read it when you passed it to the cy.log
command in the previous step).Thus, what you want to do instead, is:
cy.get('#selector').invoke('text').then(text => {
cy.log(text);
});
In your 3rd example, if you alias something, you need to access that value using another command (remember, everything is asynchronous, so you can't access values that are set asynchronously, in a synchronous manner as you're doing), in this case cy.get('@aliasName')
:
cy.get('#selector').invoke('text').as('page1value');
cy.get('@page1value').then( value => {
cy.log(value);
});
Note that the above explanations are slightly inaccurate and inexhaustive (there are more things going on behind the scenes), for the sake of simplicity. But as an intro to how things work, they should do.
Anyway, you should definitely read Introduction to Cypress.
You may also take a look at my older answers that touch on related concepts:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With