how to assign selector to an object class in Cypress

I’m trying to assign the selector to one of my object classes by using cypress. but it doesn’t work for me. here is the error I got

stocksTradePage.getStocksSearch(…).getInputField is not a function

here are my classes.

stocksShare.js

const locators = {
  inputField: 'input',
};

class StocksSearch {
  getInputField() {
    return cy.get(locators.inputField);
  }
}

module.exports = StocksSearch;

stocksTradePage.js

import StocksSearch from './stocksSearch'

const locators = {
  strocksSearch: '[data-cy=stock-search-field]',
};

let stocksSearch = new StocksSearch();

class StocksTradePage {
  getStocksSearch() {
    stocksSearch = cy.get(locators.strocksSearch);
    return stocksSearch;
  }
}

module.exports = StocksTradePage;

testStocksPage

import StocksTradePage from '../../support/trade/stroksTradePage'

const stocksTradePage = new StocksTradePage();

describe('global nav test', () => {
  it('test input field', () => {
    cy.visit('http://localhost:3000/trade');
    stocksTradePage.getStocksSearch().getInputField().type('aaaa');
  });
});

5 thoughts on “how to assign selector to an object class in Cypress”

  1. One way is to use .within() to narrow down the search (I presume you want the specific input within the search element).

    stocksTradePage.getStocksSearch().within(() => {
      const stocksSearch = new StocksSearch();
      stocksSearch.getInputField()  // restricted by the above `.within()`
                                    // to an input inside of [data-cy=stock-search-field]
        .type('aaaa');
    })
    

    One of the problems of mixing page objects with Cypress commands is that they are two different methods of abstracting the DOM and not always compatible.

    For instance in

    import StocksSearch from './stocksSearch'
    
    const locators = {
      strocksSearch: '[data-cy=stock-search-field]',
    };
    
    let stocksSearch = new StocksSearch();      // this is not returned below
    
    class StocksTradePage {
      getStocksSearch() {
        stocksSearch = cy.get(locators.strocksSearch);
        return stocksSearch;     // this is a Cypress Chainable not the class instance
      }
    }
    
    module.exports = StocksTradePage;
    

    you instantiate a StocksSearch instance, but never use it. The return stocksSearch line actually returns a Cypress Chainable object, not the object with the getInputField() method.

    You spend a lot of time flip-flopping between classes trying to find errors like this. Also the classes that work for one test might break on the next, because the Cypress semantics like get, find, within are buried behind method names that don’t give you a clear picture of what happens inside the method.

    You really want to ditch the complexisty of page objects and just set up your locators in one central object.

    const locators = {
      stocksSearch: '[data-cy=stock-search-field]',
      inputField: 'input',
    };
    
    describe('global nav test', () => {
      it('test input field', () => {
        cy.visit('http://localhost:3000/trade');
        cy.get(locators.stocksSearch)
          .find(locators.inputField)    // here we use .find()
                                        // in another test we can use .get()
                                        // - it's more flexible
          .type('aaaa');
      });
    });
    

    To make the locators global to all tests, set then up in /cypress/support/index.js

    Cypress.locators = {
      stocksSearch: '[data-cy=stock-search-field]',
      inputField: 'input',
    };
    

    then in a test

    cy.get(Cypress.locators.stocksSearch)
      .find(Cypress.locators.inputField)
    
    Reply

Leave a Comment