I have an HTML form (really simple one, no tricky parts like Ajax, ...) on a simple page. I try to read default value of any input (type="text", again no tricks) and store it in constant for later use (assert).
HTML looks like:
<form method="post" ...>
<input type="text" id="xyz" name="xyz" value="123">
</form>
Cypress test, that DOESN'T work, looks like:
describe('General tests', function(){
context('General', function() {
it('can read the input and store in const', function () {
cy.visit('http://localhost/settings')
const xyz = Cypress.$('#xyz').val()
cy.log(xyz)
})
})
})
This doesn't work. BUT after several hours of playing (by accident this worked for me in more complex test suite = file). What I realized is, that this construct works as expected in case previous test ( = it() ) visits the same URL as the last visited URL. Than it works like a miracle.
Cypress test, that WORKS, looks like:
describe('General tests', function(){
context('General', function() {
it('makes magic and allows the next test to work', function () {
cy.visit('http://localhost/settings')
})
it('can read the input and store in const', function () {
cy.visit('http://localhost/settings')
const xyz = Cypress.$('#xyz').val()
cy.log(xyz)
})
})
})
I thought that tests should be independent, but it looks like they are not.
I tried other ways how to get the value of input info variable and the closest what I needed was using closure ".then()", but it can be used for just a single input, not for more complex forms.
Simple asserting like "cy.get('#id_of_input').should('eq', ...)" works fine, but it doesn't allow me to work with default (and by test overridden) value of inputs.
So my questions:
1) Is it OK to use included jQuery in this way to get and store value of input into constant? If now what is the other way for cases when I need to do this for like 5 various input fields in the form (for a signel input closure will be just fine) 2) Is it OK that tests influence each other?
Thanks everyone for any help.
To answer your questions:
1) According to the docs, Cypress.$ is "a great way to synchronously query for elements". (emphasis theirs)
The way you're using it circumvents the intended Cypress workflow with asynchronous command queuing. If you don't know what I'm talking about here, I suggest reading the fantastic introduction to Cypress in their documentation.
I would suggest the following as an alternative to the code you posted:
cy.visit('http://localhost/settings');
cy.get('#xyz').then(elem => {
// elem is the underlying Javascript object targeted by the .get() command.
const xyz = Cypress.$(elem).val();
cy.log(xyz);
});
.then(). lets you queue up code to be run in sequence with your test by the test runner. See this answer for more info about command queuing and .then().
2) Yes, it is okay for describe functions to influence each other. Cypress runs each file separately, but separate describes are simply run in the sequence they are queued in.
For example, the following code will work just fine:
let message = "";
describe("Set a value", () => {
it("Sets a value", () => {
message = "hi";
});
});
describe("Retrieve a value", () => {
it("Retrieves and prints the set value", () => {
cy.log(message); // Logs "hi" to the Cypress log window
});
});
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