3

I need to choose several elements in filter and check that the data would be shown according the filter. I'm trying to save text of elements in the variables, and check it at the end.

it.only('the UI with a lot of entries in a filter, should be responsive', () => {
  let listItem1
  let listItem2

  cy.get('someTab').click().then(()=> {
    cy.getText(cy.get('someSelector').first(), listItem1)
    cy.getText(cy.get('someSelector').last(), listItem2)
  }).then(()=> {
    cy.get('someSelector').first().click()
    cy.get('someSelector').last().click()
    cy.get('someButton').click()
  }).then(()=>{
    cy.log(listItem1, listItem2)  // nothing is visible
    cy.get('span[data-app]').should('contain', listItem1)  // fail
    cy.get('span[data-app]').should('contain', listItem2)  // fail
  })
})

I use this function:

getText(selector, variable) {
  return selector.invoke('text')
    .then(($text) => {
      variable = $text.trim()
    })
}  

It doesn't work, but I can't to understand how to fix it

Richard Matsen
  • 20,671
  • 3
  • 43
  • 77
Tanya
  • 31
  • 2

1 Answers1

0

The basic problem is in getText(selector, variable) the 2nd param you want to give a value is passed in "by value", but to set and use later it would need to be passed "by reference".

If you "pass by value", setting the variable has no effect outside of the function.

See Pass variables by reference in JavaScript for some background.

It's not possible to pass "by reference" in javascript, but you can wrap in a container object and modify properties

function getText(selector, container, variableName) {
  selector.invoke('text')
    .then(($text) => {
      container[variableName] = $text.trim()
    })
}

it('the UI...', () => {

  const container = {       // Note const because container never changes
    listItem1: null,        // only properties will change
    listItem2: null
  }

  cy.get('someTab').click().then(() => {
    cy.getText(cy.get('someSelector').first(), container, 'listItem1')
    cy.getText(cy.get('someSelector').last(), container, 'listItem2')
  }).then(() => {
    cy.get('someSelector').first().click()
    cy.get('someSelector').last().click()
    cy.get('someButton').click()
  }).then(() => {
    cy.log(container.listItem1); // listItem1 is visible
    cy.log(container.listItem2); // listItem2 is visible
    cy.get('span[data-app]').should('contain', container.listItem1)  
    cy.get('span[data-app]').should('contain', container.listItem2) 
  })
})

You can change getText() to a custom command

const container = {}

Cypress.Commands.add('storeAs', { prevSubject: true }, function(subject, prop) {
  cy.wrap(subject)
    .invoke('text')
    .then(text => container[prop] = text)
})

it('the UI...', () => {

  cy.get('someTab').click().then(() => {
    cy.get("someSelector").first().storeAs('listItem1')
    cy.get("someSelector").last().storeAs('listItem2')
  }).then(() => {
    ...
  }).then(() => {
    cy.log(container.listItem1); // listItem1 is visible
    cy.log(container.listItem2); // listItem2 is visible
    cy.get('span[data-app]').should('contain', container.listItem1)  
    cy.get('span[data-app]').should('contain', container.listItem2) 
  })
})