1

Since aliases are cleared after each test (it) when using Cypress, it seems subsequent tests needs to execute the same request again and again, while I would prefer to get it only once. This can be verified by replacing beforeEach with before, resulting in the second and third test to fail. Of course all assertions could be placed in a single it, I want each assertion to be reported separately however. Why does Cypress need to reload the resource for each test and how can this be avoided?

/// <reference types="cypress" />

describe('When requesting the resource', () => {
    beforeEach(() => {
        cy.request('http://startpage.com/').as('response');
    });

    it('The status code should be 200', () => {
        cy.get('@response').its('status').should('be.ok');
    });

    it('The content type should be text/html', () => {
        cy.get('@response').its('headers.content-type').should('include', 'text/html');
    });

    it('The content should be encoded using UTF-8', () => {
        cy.get('@response').its('headers.content-type').should('include', 'charset=utf-8');
    });
});

1 Answer 1

1

Aliases in Cypress are removed between tests, that's why your response alias is not preserved. A discussion around this topic could be found e.g. here.

What works is this code:

const { expect } = require("chai")

describe('When requesting the resource', () => {

    let response;

    before(() => {
        cy.request('http://startpage.com/').then(res => response = res);
    });

    it('The status code should be 200', () => {        
        expect(response.status).to.equal(200);
    });

    it('The content type should be text/html', () => {
        expect(response.headers['content-type']).to.include('text/html');
    });

    it('The content should be encoded using UTF-8', () => {
        expect(response.headers['content-type']).to.include('charset=utf-8');
    });
});

you can see that cy.request() was run only once:

enter image description here

On the other hand, I don't consider this a nice solution, because it works only because you know that before() runs before all the tests, that's why you can rely on response having a value. But if you ever want to do something like this:

before(() => {
    cy.request('http://startpage.com/').then(res => response = res);
    console.log(response); // or any other usage of response variable
});

it will not work because you're mixing asynchronous and synchronous code, so by the time console.log(response) executes, response is still undefined.


So if there's a better solution, please post it and I'll delete my answer.

3
  • 1
    Thank you for your clearly formulated answer and provided solution. Storing the response in a variable seems a nice solution to me, but for some reason the Cypress documentation doesn't recommend this: "We could make our code do some ugly backflips using let to get access to it", followed by demo code with an identical structure as in your answer, accompanied with a warning not to use code like this. And then followed by the recommendation to use aliases instead. But why? And why clear aliases?
    – Bouke
    Commented Jan 10, 2021 at 23:40
  • 1
    Ah, issue concerning aliases being cleared has been reopened again: github.com/cypress-io/cypress/issues/665#
    – Bouke
    Commented Jan 10, 2021 at 23:48
  • 1
    Yes, this code is not ideal, that's what I tried to formulate in my answer as well. I know Cypress doesn't recommend that, I've read that doc page a few times. I think the reason is mostly what I said, plus it doesn't look nice :D If your test suite is simple like this example, and you are aware of it not being the right solution but can't find a better one, I'd go for it.
    – pavelsaman
    Commented Jan 11, 2021 at 6:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.