How to return a list of objects from Cypress Custom Commands in type script

Viewed 1414

I am using Cypress for my end to end Integration tests. I have a use case which involves returning a list of objects from Cypress Custom Commands and I have a difficulty in doing so. Here is my code pointer:

index.ts

declare global {
    namespace Cypress {
        interface Chainable<Subject> {
            getTestDataFromElmoDynamoDB({locale, testType}): Cypress.Chainable<JQuery<expectedData[]>> // ??? not sure what return type should be given here.
        }
    }
}


Cypress.Commands.add('getTestDataFromDynamoDB', ({locale, testType}) => {
    // expectedData is an interface declared. My use case is to return the list of this type.
    let presetList: expectedData[] 
    cy.task('getTestDataFromDynamoDB', {
        locale: locale,
        testType: testType
    }).then((presetData: any) => {
        presetList = presetData;
        // the whole idea here is to return presetList from cypress task
        return cy.wrap(presetList) //??? not sure what should be written here
    })
})

sampleSpec.ts

describe('The Sample Test', () => {

    it.only('DemoTest', () => {
        cy.getTestDataElmoDynamoDB({
            locale: env_parameters.env.locale,
            testType: "ChangePlan"
        }).then((presetlist) => {
           // not sure on how to access the list here. Tried wrap and alias but no luck.
          presetList.forEach((preset: expectedData) => {
             //blah blah blah
           })
        })
    })
})

Did anyone work on similar use case before?

Thanks, Saahith

2 Answers

Here My own command for doing exactly that.

Cypress.Commands.add("convertArrayOfAlliasedElementsToArrayOfInteractableElements", (arrayOfAlliases) => {

    let arrayOfRecievedAlliasValues = []

    for (let arrayElement of arrayOfAlliases) {
        cy.get(arrayElement)
            .then(aelement =>{
                arrayOfRecievedAlliasValues.push(aelement)
            })
    }

    return cy.wrap(arrayOfRecievedAlliasValues)

})

The way I do it is to pass it in an array and cy.wrap the array, Because it lets you chain the command with an interactable array.

The key point is - it has to be passed as array or object, because they are Reference types, and in cypress it is hard to work with let/var/const that are value types.

You can also allias the cy.wrapped object if you like.

The way to use it in code is: cy.convertArrayOfAlliasedElementsToArrayOfInteractableElements(ArayOfElements)

What you asked for can be implemented as follows, but I do not know what type expectedData is, so let's assume that expectedData:string [], but you can replace string[] with your type.

plugins/index.ts

module.exports = (on: any, config: any) => {
  on('task', {
    getDataFromDB(arg: {locale: string, testType: string}){
      // generate some data for an example
      const list: string[] = [];
      list.push('a', 'b');
      return list;
    },
  });
};

commands.ts

declare global {
  namespace Cypress {
    interface Chainable<Subject> {
      getTestDataElmoDynamoDB(arg: {locale: string, testType: string}): Cypress.Chainable<string[]>
    }
  }
}


Cypress.Commands.add('getTestDataElmoDynamoDB', (arg: {locale: string, testType: string}) => {
  let presetList: string[] = [];
  cy.task('getDataFromDB', arg)
    .then((presetData?: string[]) => {
      expect(presetData).not.be.undefined.and.not.be.empty;
      // if the data is incorrect, the code will break earlier on expect, this line for typescript compiler
      if (!presetData || !presetData.length) throw new Error('Present data are undefined or empty');
      presetList = presetData;
      return cy.wrap(presetList); // or you can return cy.wrap(presetData)
    });
});

db.spec.ts

describe('Test database methods', () => {
    it('When take some test data, expect that the data was received successfully ', () => {
        cy.getTestDataElmoDynamoDB({ locale: 'someEnvVar', testType: 'ChangePlan' })
          .then((list) => {
            expect(list).not.empty.and.not.be.undefined;
            cy.log(list); // [a,b]
            // You can interact with list here as with a regular array, via forEach();
        });
    });
});

You can also access and receive data from cy.task directly in the spec file.

describe('Test database methods', () => {
    it('When take some test data, expect that the data was received successfully ', () => {
        cy.task('getDataFromDB', arg)
            .then((list?: string[]) => {
                expect(list).not.be.empty.and.not.be.undefined;
                cy.log(list); // [a,b] — the same list as in the version above
        });
    });
});
Related