Cypress: How to properly close a mat-select

Viewed 3887

So I'm using Cypress for testing our Angular application, but for some reason I always have an issue with closing mat-select components which are multiselect. Has anyone got a good solution for this?

function selectValue(id: string, value: string) {
    return cy.get(`mat-select[id="${id}"]`)
             .click()
             .then(() => 
                cy.get('mat-option')
                  .contains(value)
                  .click();
}
5 Answers

To close the list on a multi-select dropdown, do what a user does and click outside the list, e.g on the body

it('selects, closes, verifies', () => {

  cy.visit('https://material.angular.io/components/select/overview#multiple-selection')

  cy.get('div[role="listbox"]').should('not.exist')    // check list isn't open    

  cy.get('select-multiple-example').click()            // open
  cy.get('div[role="listbox"]').should('exist')        // check list is open    

  cy.contains('Extra cheese').click()                  // select an item
  cy.contains('Onion').click()                         // select an item
  cy.contains('Tomato').click()                        // select an item

  cy.get('body').click()                               // click outside the list

  cy.get('div[role="listbox"]').should('not.exist')    // check list isn't open    
  
  cy.get('select-multiple-example')
    .should('contain', 'Extra cheese, Onion, Tomato')  // verify
    
  cy.get('select-multiple-example')
    .should('not.contain', 'Mushroom')                 // verify contra
    
})

Another thing that worked in my case was

cy.get(`mat-select[data-testid="${dropdownTestId}"]`).focus().type('{esc}');

I suggest something like this:

Cypress.Commands.add('selectValue', (value) => {
  cy
      .get('mat-select').first().click()
      .get('.mat-option-text').contains(value).click()
      .get('.mat-option-text').should('not.visible')
      .get('.mat-select-value-text').first().should(([{ innerText }]) => {
        expect(innerText).equal(value)
      })
});

I tested it on https://material.angular.io/components/select/overview and it works on my local machine.

If something fails, feel free to ask questions

A better way is to use the new feature components harnesses

https://material.angular.io/cdk/test-harnesses/overview

for your problem it should work like this, first you create harness loader from the fixture in beforeEach statement

loader = TestbedHarnessEnvironment.loader(fixture);

then you can get the select harness by doing something like this

let selectHarness = await loader.getHarness(MatSelectHarness.with({selector: '#select-id'}));

now you can simply use the close method

selectHarness.close()

in my case it was not possible to click outside of the select box because overlay issue is blocking everything, for my case this "weird solution" worked:

cy.get('mat-option').contains(text).click().type('{end}').type('{esc}');
Related