to navigateEnterto select Escto close

    Selectors and texts

    • Create a separate folder "constants" under cypress. In "constants" folder, create two folders - "selectors" and "texts" and store all the selectors and texts respectively in those folders. Please refer:


    • In a selector file, create an object for storing all the related DOM selectors and export that object in other files where we need to use it.
    • Always use meaningful variable names for storing selectors, and also keys in the object. It helps us to to locate them easily and make the tests more readable. For example, if we need to test login functionality. The selector name can be loginSelectors, placed at constants/selectors/login.js. It can have keys as emailTextField, passwordTextField and submitButton.

    Please refer another example below:

    1// constants/selectors/signup.js
    3export const signupSelectors = {
    4  emailTextField: "[data-cy=signup-email-text-field]",
    5  emailSubmitButton: "[data-cy=signup-email-submit-button]",
    6  firstNameTextField: "[data-cy=signup-profile-first-name-text-field]",
    7  lastNameTextField: "[data-cy=signup-profile-last-name-text-field]",
    8  profileSubmitButton: "[data-cy=signup-profile-submit-button]"
    • Avoid prefixing the key with the name of the test file name as we already prefixed the selector object with it.
    • Please refer the example below:
    1// Incorrect
    2export const clientsSelectors = {
    3  clientCancelButton: dataCy("client-cancel-button")
    6// Correct
    7export const clientsSelectors = {
    8  cancelButton: dataCy("client-cancel-button")
    • Avoid repeating same selectors in multiple files. Instead create a common file and keep all of them in common selectors. The best possible scenario for this is header elements. The header elements might be required in multiple test specs. However, we can keep them under selectors/common.js with an object named as headerSelectors.
    • While choosing selectors always give priority as below in neeto projects:
      1. data-cy
      2. data-test
      3. data-test-id
    • In cases, if we need to use class selectors, it should be specific. Avoid using generic classes. And in some cases, we may need to use them with some parent element to make them specific. e.g. .content-body-wrapper .heading.


    • We will follow the same conventions as selectors for storing the texts as well.
    • In text file, create a variable for storing all texts and export that variable in other files where we need to use those texts.
    • The variable names for storing texts should also be meaningful and easy to understand. Please refer the example below:
    2export const commonTexts = {
    3  generalError: "Something went wrong.",
    7export const loginTexts = {
    8  heading: "Sign In",
    9  passwordRequiredMessage: "Password is required",
    10  emailRequiredMessage: "Email is required",

    Importing selectors and texts variables

    • We need to import variables from selectors and texts. Please refer the example below:
    1import {
    2  navSelectors,
    3  commonSelectors
    4} from "../../constants/selectors/common";
    5import { loginSelectors } from "../../constants/selectors/login";
    6import { CommonTexts } from "../../constants/texts/common";
    7import { profileSettingsTexts } from "../../constants/texts/profileSettings";


    Our tests are organized functionality wise. We need to specify relative path i.e. ../../. If they are deeply nested, it becomes to difficult to specify path. When we move any file to other location, we need to update them again. So, it's better to use the aliases instead. Webpack aliases allows us to create aliases to import or require certain modules more easily. Instead of doing:

    1import { commonSelectors } from "../../constants/selectors/common";

    We can define an alias for the selectors folder so that it can be accessed from any component without having to do relative import. To do so, add aliases to the webpack.config.js as follows:

    1var path = require("path");
    3module.exports = {
    4  resolve: {
    5    alias: {
    6      Selectors: path.resolve(__dirname, "constants/selectors")
    7    }
    8  }

    Now we can do

    1import { commonSelectors } from "Selectors/common";

    The problem mentioning the directory using combination of dots and slashes is that this is very error prone. Using aliases makes code clean and readable.