1

I have a selector that changes when running in mobile. For example:

Desktop: div[data-test-id="popup"] div:nth-child(2) Mobile: div[data-test-id="popup"] div:nth-child(3)

My idea is to check the size of the window and if it's below 375 use the Mobile selector else Desktop.

I have the following working solution but I dont want to have repeated code and rather would like to pass 2 or 3 as a parameter:

cy.get('body').then( (body) => {
       if ( body.width() <= 375 ) {
           cy.get('div[data-test-id="popup"] div:nth-child(3)')
               .children().eq(0)
               .should('exist')
               .should('have.text', time);
       }
       else {
           cy.get('div[data-test-id="popup"] div:nth-child(2)')
               .children().eq(0)
               .should('exist')
               .should('have.text', time);
       }
    });

Is there a better way to rewrite it?

Also, the above code, even though it runs and the tests pass, the build fails with a Typescript error due to body.width() --> TS2532: Object is possibly 'undefined'.

therock_21
  • 71
  • 4

2 Answers2

1

I would be testing both desktop and mobile using viewport to explicitly set the width

const widths = [500, 350]
widths.forEach(width => {

  // You are looking for a way to parameterize the selector,
  // do it using a template literal
  const param = width === 350 ? 3 : 2
  const selector = `div[data-test-id="popup"] div:nth-child(${param})`

  beforeEach(() => {
    cy.viewport(width, 800)
  })

  it(`tests the width of ${width}px`, () => {
    cy.get(selector)
      .children().eq(0)
      .should('exist')
      .should('have.text', time)
  })
})

It looks like you need to use viewport in a somewhat restricted way, either

  • in beforeEach() hook
  • before a page cy.visit()
  • before a page cy.reload()

The typescript error

body.width() --> TS2532: Object is possibly 'undefined'

can be fixed by using the non-null assertion operator

body!.width()   // telling typescript that we know body exists
Fody
  • 23,754
  • 3
  • 20
  • 37
0

You can simplify your code by using the .contains() command instead of the all the .get()s.

Assuming you don't have any other elements with data-test-id="popup" with the time text or any nested data-testid="popup" within the div[data-test-id="popup" one, then this will work for both desktop and mobile and here is what it will look like.

cy.contains('[data-test-id=popup]', time) 
  .should('exist')
  .should('have.text', time);
jjhelguero
  • 2,281
  • 5
  • 13