Home > Mobile >  Text assertion in Cypress with nested query
Text assertion in Cypress with nested query

Time:10-25

I am new to Cypress, and trying to write an assertion for some text inputs for a username. A valid text for a username should fulfill two conditions, which are,

  1. Text should contain ONLY English letters.
  2. Text length should be greater than 1, and less than 20.

My code is as follows.

getUserFirstName(textInput) {
  cy.get('[testid="user-self-update-form"]')
    .get('input[name="firstName"]')
    .clear()
    .type(textInput)
    .blur()
    .invoke('val')
    .should(($el) => {
      expect($el).to
                 .match(/[a-zA-Z] $/)
                 .to
                 .have
                 .greaterThan(1)
                 .to
                 .be
                 .lessThan(20)
    }).then(() => {
      cy.log("Invalid text input");
    })
}

My requirement: When a username text is inserted, the above test should check whether it meets with imposed conditions, if not, log a message in the console. I am now trying to do the above test for 4 inputs separately, which are 'abcd123', '123', 'textwithmorethantwentyletters', and 'belowtwenty'. When running this test for the first input text of 'abcd123'. How may I correct this code? Highly appreciate your help.

I get the following error, and the test is failed:

enter image description here

CodePudding user response:

You can try chaining the conditions with Cypress .and()

getUserFirstName(textInput) {
  cy.get('[testid="user-self-update-form"]')
    .find('input[name="firstName"]')
    .clear()
    .type(textInput).blur()
    .invoke('val')
    .should('match', /[a-zA-Z] $/)
    .and('have.length.gt', 1)
    .and('have.length.lt', 20)
}

The input abc123 does not meet the first criteria, why did you think the test would pass?

If you want to just log bu not fail the test, try

getUserFirstName(textInput) {
  cy.get('[testid="user-self-update-form"]')
    .find('input[name="firstName"]')
    .clear()
    .type(textInput).blur()
    .invoke('val')
    .then(val => {
      const lettersOnly = val.match(/[a-zA-Z] $/)
      const gt1 = val.length > 1
      const lt20 = val.length < 20
      if (!lettersOnly || !gt1 || !lt20) {
        cy.log('Failed conditions')
        // to fail the test now, throw an error
        throw 'Failed conditions'
      })
     })
}

In the 2nd example I did not use .should(), .and() or expect() because if any of those fail Cypress will fail the test at that point (and not check the other conditions).

Note also, .find(('input[name="firstName"]') instead of .get('input[name="firstName"]') because your intention is to find the firstname input within the form.

.get() also may work if there is only one 'input[name="firstName"]' on the page, but be aware that it ignores the line before and queries DOM from the root element <body>.

CodePudding user response:

Your answer is mostly correct, but it just needs a few changes.

  1. You are applying two assertions - to check that the username text matches the regex value and the text length is between 1 and 20. In your case, two different assertions will work better.
expect($el).to.match(/[a-zA-Z] $/)
expect($el.length).to.have.greaterThan(1).to.be.lessThan(20)

You can also use within which basically checks for greater and less than.

expect($el.length).to.be.within(1,20)
  1. Instead of using cy.log("Invalid text input"); you can directly pass custom log messages in expect statements.
expect($el.length).to.be.within(1,20, "Some Log message")

So implementing these two changes your code should look like:

cy.get('[testid="user-self-update-form"]')
  .get('input[name="firstName"]')
  .clear()
  .type(textInput)
  .blur()
  .invoke('val')
  .should((val) => {
    expect(val.trim()).to.match(/[a-zA-Z] $/,
      `Checking username ${val} for regex match`
    )
    expect(val.trim().length).to.be.within(1,20,
      `Checking username ${val} for length match`
    )
  })
  • Related