javascriptcypresscode-duplicationchain

Can chaining be abstracted in cypress?


I am writing a UI assertions test with cypress and I am seeing a lot of repeated chaining. Is there a way to abstract this out into a helper method for easier maintainability (and less code duplication)?

example code:

it('displays the table column headers', () => {
      DivisionPage.divisionNameColumnHeader()
        .should('be.visible')
        .and('have.css', 'text-transform', 'capitalize')
        .and('have.css', 'color', 'rgb(35, 40, 43)')
        .and('have.css', 'background-color', 'rgb(195, 202, 206)')
        .and('have.css', 'cursor', 'pointer')
        .and('have.css', 'font-family', '"Open Sans"')
        .and('have.css', 'position', 'sticky')
      DivisionPage.teamsColumnHeader()
        .should('be.visible')
        .and('have.css', 'text-transform', 'capitalize')
        .and('have.css', 'color', 'rgb(35, 40, 43)')
        .and('have.css', 'background-color', 'rgb(212, 217, 220)')
        .and('have.css', 'cursor', 'pointer')
        .and('have.css', 'font-family', '"Open Sans"')
        .and('have.css', 'position', 'sticky')
      DivisionPage.playersColumnHeader()
        .should('be.visible')
        .and('have.css', 'text-transform', 'capitalize')
        .and('have.css', 'color', 'rgb(35, 40, 43)')
        .and('have.css', 'background-color', 'rgb(212, 217, 220)')
        .and('have.css', 'cursor', 'pointer')
        .and('have.css', 'font-family', '"Open Sans"')
        .and('have.css', 'position', 'sticky')
})

Note that I am using page models so the DivisionPage.divisionNameColumnHeader() is equal to something like this: cy.get('[data-cy="division-name-column-header"]')


Solution

  • A function or method is feasible, but a Custom Command is better since your repeated code is Cypress assertions.

    A plus is these commands are global to all tests, if you define them in /support/commands.js.

    Cypress.Commands.add('isStickyVisibleAndCapitalizedInCorporateColors',
      {prevSubject:true},
      (subject) => {
        cy.wrap(subject)
          .should('be.visible')
          .and('have.css', 'text-transform', 'capitalize')
          .and('have.css', 'color', 'rgb(35, 40, 43)')
          .and('have.css', 'background-color', 'rgb(212, 217, 220)')
          .and('have.css', 'cursor', 'pointer')
          .and('have.css', 'font-family', 'Open Sans')
          .and('have.css', 'position', 'sticky')
    })
    
    // Used like a composite assertion
    DivisionPage.divisionNameColumnHeader().isStickyVisibleAndCapitalizedInCorporateColors()
    
    
    

    Or select all elements at once and iterate the collection

    it('displays the table column headers', () => {
    
      cy.get('[data-cy="division-name-column-header"], [data-cy="division-teams-column-header"], [data-cy="division-players-column-header"]')
        .each($el => {
          cy.wrap($el)
            .should('be.visible')
            .and('have.css', 'text-transform', 'capitalize')
            .and('have.css', 'color', 'rgb(35, 40, 43)')
            .and('have.css', 'background-color', 'rgb(195, 202, 206)')
            .and('have.css', 'cursor', 'pointer')
            .and('have.css', 'font-family', '"Open Sans"')
            .and('have.css', 'position', 'sticky')
        })
    })