Cypress Workshop Part 6: Elements manipulation - Lists, Date picker
Tags: qa, testing, cypress, javascript
Published: 2023-05-20 16:44:21

## Lists

As you have already seen in almost every application you used, developed, tested, lists are very common web elements. Menus, Dropdowns and similar selections are a common component for web applications. 

:information_source: Learn more about lists actions: 
[select](https://docs.cypress.io/api/commands/select)
[testing lists](https://www.cypress.io/blog/2020/04/23/guest-post-testing-lists-of-items/)
[each](https://docs.cypress.io/api/commands/each)

So, let’s write some tests for lists: 

1: Create a new test file under `e2e/elements_manipulation` and call it, for example, `lists.cy.js`.

2: Write the following tests inside: 

```javascript
/// <reference types="Cypress" />

describe('Lists: Lists actions', () => {
  beforeEach('Navigate to lists page', () => {
    cy.visit('/select-menu');
  });

  it('Check selection of all list options - select method - colors menu', () => {
    // Load colors fixure json file to assert if all colors are present
    cy.fixture('colors').then((colors) => {
      // Get all options in the menu, get each option and indexes
      cy.get('#oldSelectMenu option').each((option, index) => {
        // Get option text
        const optionText = option.text();
        // Select each option and assert that it has correct option value and text
        cy.get('#oldSelectMenu')
          .select(optionText)
          .should('have.value', option.val())
          .contains(colors[index]);
      });
    });
  });

  it('Check selection of single list option - click method - title menu', () => {
    // Click on dropdown
    cy.get('#selectOne').click();
    // Select one option
    cy.get('#react-select-3-option-0-4').click();
    // Assert that dropdown has correct text after selection
    cy.get('#selectOne').contains('Prof.');
  });
});

```
3: Delete `example.json` file in `cypress/fixtures` folder, and create new one called `colors.json`. Write following data in it. 

```json
{
  "0": "Red",
  "1": "Blue",
  "2": "Green",
  "3": "Yellow",
  "4": "Purple",
  "5": "Black",
  "6": "White",
  "7": "Voilet",
  "8": "Indigo",
  "9": "Magenta",
  "10": "Aqua"
}
```

**Code explanation:**

In our test file, we are first visiting our app’s page dedicated for testing lists-menus before each test starts [page](https://demoqa.com/select-menu).

- In the first test case, the test subject is the menu with colours (Old Style Select Menu). We want to test values and text of each option in the menu.

Line 10: We are wrapping the entire action/assertion with a fixture, because we want to load and use its content (from `colors.json` file) for colour results assertions. (Loading once instead of each time assertion is called, that is why we call it outside the selection loop.)

Line 12: We are getting dropdown options and for each option we are getting its value and index. 

Line 14: For each option we are getting the text (Red, Blue, etc.)

Line 16-17: We are using Cypress option `select()` instead of `click()` to select each value, and we are able to use this because this element has select tag in DOM. Because we are inside the loop, this will not select all options at once, but one after another. 

Line 18-19: For each option selection, we are asserting that it contains the proper value and that colours by indexes match with our fixture file content (colour names) in that particular order. 

- In the second test case, we just want to select one option in the menu of titles. For this particular example, we can’t use `select()` function because this app does not provide select tag for this menu. There is no need for looping here, since we want to check only one option.

Line 26: We are clicking on the menu to open it.

Line 28: We are clicking on one option in the menu.

Line 30: We are asserting that menu element has a selection that we chose. 

:information_source: Learn more about fixtures: [fixtures](https://docs.cypress.io/api/commands/fixture)

:information_source: Learn more about different types of JS loops you can also use in the tests: [loops](https://www.w3schools.com/js/js_loop_for.asp)

:point_right: It is very important to understand loop logic. As someone who writes test automation, you will often have situations where you will have to tests different options in lists, tables etc, so loops are an excellent method to avoid code repetition and make test execution faster. 

## Date picker

Date picker elements let users select a date or range of dates. They are usually tied to the input field. Now that we know how to perform actions over buttons, input fields and lists, let’s write a few date picker tests that are a combination of what we learned before. 

1: Create a new test file under `e2e/elements_manipulation` and call it, for example, `datepicker.cy.js`. Write the following test inside.

```javascript
/// <reference types="Cypress" />

describe('Date picker: Date picker actions', () => {
  beforeEach('Navigate to date picker page', () => {
    cy.visit('/date-picker');
  });

  it('Check fixed date selection', () => {
    // Open date picker
    cy.get('#datePickerMonthYearInput').click();
    // Select year
    cy.get('.react-datepicker__year-select').select('2030');
    // Select month
    cy.get('.react-datepicker__month-select').select('June');
    // Select day
    cy.get(`.react-datepicker__day--0${23}`).first().click();
    // Assert input date value
    cy.get('#datePickerMonthYearInput').should('have.value', '06/23/2030');
  });

  it('Check dynamic date selection', () => {
    // Increment Date by 1 month
    const date = new Date();
    date.setMonth(date.getMonth() + 1);
    // Set date to 23rd day of next month
    const year = date.getFullYear();
    const month = date.getMonth();
    const day = 23;
    // Open date picker
    cy.get('#datePickerMonthYearInput').click();
    // Select year
    cy.get('.react-datepicker__year-select').select(`${year}`);
    // Select month
    cy.get('.react-datepicker__month-select').select(`${month}`);
    // Select day
    cy.get(`.react-datepicker__day--0${day}`).first().click();
    // Assert input date value
    cy.get('#datePickerMonthYearInput').should(
      'have.value',
      `${`${month + 1}`.padStart(2, '0')}/${day}/${year}`
    );
  });

  it('Check applying date value directly in the input field', () => {
    // Clear date input and type new date
    cy.get('#datePickerMonthYearInput').clear().type('06/23/2030');
    // Assert input date value
    cy.get('#datePickerMonthYearInput').should('have.value', '06/23/2030');
  });
});

```
**Code explanation:**

In our test file, we are first visiting our app’s page dedicated for testing date pickers before each test starts [page](https://demoqa.com/date-picker).

- _Test 1_ (we are selecting fixed date value): 

Line 10: First, we are clicking on date picker input to open it. 

Line 12: We are selecting fixed value for the year. 

Line 14: We are selecting fixed value for the month.

Line 16: We are selecting fixed value for date, and taking first one, in case that date picker shows duplicate value for next/previous month.

Line 18: We are asserting that date input has a new value - our selected value. 

- _Test 2_ (we are selecting date dynamically):

Line 23: We are initiating Date object. 

Line 24: We are setting month in Date object to always be increased by 1 month from current month. 

Line 26: We are getting year from Date object

Line 27: We are getting month from Date object

Line 28: We are creating constant to be used as value of the day

Line 30: We are opening date picker

Lines 32 - 36: We are selecting year, month, day in date picker

Lines 38 - 41: We are asserting that date input has the correct value that we have set for the date. Because of different indexing of month from Date object and dropdown value, we are adding 1 to the month and if value is less than 10, we are adding 0 in order to respect formatting of date input field. 

- _Test 3_ (we are inserting fixed date value directly in the input field without selection):

Line 46: We are clearing the default value from the input field, and we are typing a new fixed value. 

Line 48: We are asserting that date input has a new value - our selected value. 

:point_right: It is always advisable NOT to use fixed values for dates because tests will fail once that date is passed etc. depending on use case on the project. Whenever possible use calculations, dynamic values and native JS Date object, or other library such as [moment.js](https://momentjs.com/). We have fixed examples here just for learning purposes, to be familiar with multiple ways of how you can interact with date pickers.

:information_source: Learn more about JS Date Objects: [date objects](https://www.w3schools.com/js/js_dates.asp)

## HOMEWORK:

- Add more scenarios that will check other lists on our lists page, or other dropdowns in our Demo app. Play with selections and assertions. Try to automate multi-select list.

- Add more scenarios for date picker. Try to navigate through different months using left/right arrow navigation. Try to automate second date picker that contains time as well. Play with time calculations. 

Don’t forget to push everything you did today on Github :wink: Remember git commands?

`git add .`

`git commit -am "add: lists, date pickers tests"`

`git push`

<img width="100%" style="width:100%" src="https://media.tenor.com/IFMw1kJnVu0AAAAC/monday-garfield.gif">

SEE YOU IN LESSON 7!

[Completed code for this lesson](https://github.com/ViktorijaFilipov/cypress-workshop/tree/main/LESSON_6)

If you have learned something new, feel free to support my work by buying me a coffee :coffee:

[![Buy Me A Coffee][2]][1]

[1]: https://www.buymeacoffee.com/viktorija3141
[2]: https://cdn.buymeacoffee.com/buttons/default-black.png