Search code examples
testingautomated-teststhiscypressarrow-functions

Cypress access alias with this.* doesn't works


I'm having a little problem understanding Cypress documentation. In the alias section they've added a use case of accessing alias with fixtures using the this.* reference:

beforeEach(() => {
    // alias the users fixtures
    cy.fixture("users.json").as("users");
});

it("utilize users in some way", function () {
    // access the users property
    const user = this.users[0];

    // make sure the header contains the first
    // user's name
    cy.get("header").should("contain", user.name);
});

But when I try to reproduce it, I keep getting the error: Cannot read property 'SOAP_body' of undefined.

I don't understand where is my error. Here is my spec:

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

describe("SOAP API Test", () => {
    beforeEach(() => {
        cy.fixture("SOAP_body.xml").as("SOAP_body");
    });

    it("Test with task", function () {
        const body = this.SOAP_body;

        cy.request({

            method: "POST",
            headers: {
                "content-type": "text/xml; charset=utf-8",
                Authorization: "Token myVerySecretToken",
                SOAPAction: "http://tempuri.org/TrackingFull",
            },
            url: `https://path.of/the/application.asmx`,
            body: body,
            failOnStatusCode: false,

        }).then((result) => {

            expect(result.status).to.equal(200);
            cy.task("XMLtoJSON", result.body).then((response) => {
                expect(
                    response.elements[0].elements[1].elements[0].elements[0]
                        .elements[1].elements[0].elements[0].elements[0]
                        .elements[0].elements[0].text
                ).to.equal("something");
                
            });
        });
    });
});

and my task

/**
 * @type {Cypress.PluginConfig}
 */

module.exports = (on, config) => {

    on("task", {
        XMLtoJSON(XML_body) {
            var convert = require("xml-js");
            let result = convert.xml2js(XML_body, {
                compact: false,
                spaces: 2,
            });
            return result;
        },
    });
};

Using debugger just before the const definition I can see that the variables are undefineddebbuger output

I do know about cy.get(), but I just wanted to learn how to use the this.* pattern.


Solution

  • After fiddling with the code I've realized that I was using an arrow function in the step definition:

    it("Test with task", () => { ... }

    I've done it simply because I use a lot of code snippets in VSC, and never paid attention to the syntax is used.

    So, after seeing it, I've remembered that it would never work, as the MDN documentation says:

    An arrow function expression is a compact alternative to a traditional function expression, but is limited and can't be used in all situations.

    Differences & Limitations:

    • Does not have its own bindings to this Facepalm or super, and should not be used as methods.
    • Does not have arguments, or new.target keywords.
    • Not suitable for call, apply and bind methods, which generally rely on establishing a scope.
    • Can not be used as constructors.
    • Can not use yield, within its body.

    The solution was simple as replacing it with a function definition:

    it("Test with task", function () { ... }

    and the this context was as expected

    debbuger output

    Moral of the history, don't trust blindly in your code editor (even if its VSC)