7

I have a form that looks something like this:

<form class="col s12" materialize [formGroup]="newUserForm">
...
    <div class="row">
    <div class="input-field col m4 s12">
        <select formControlName="genderBound" materialize="material_select" id="gender" name="test">
            <option value="" disabled selected name="chooseGender">Choose gender</option>
            <option *ngFor="let gender of genders">{{gender}}</option>
        </select>
        <label for="gender">Gender</label>
    </div>
...

When I try to use cypress to select the dropdown menu, it tells me that it's not visible. When I follow the explanatory URL that cypress provides, it suggest that I use {force: true} inside my click. This allowed my test to pass, but never actually seemed to select the items.

I also followed the solutions provided here, and implemented a jQuery click on the actual option (Note that my select and option tags are not md-select and md-option tags)

sample.spec.js in my cypress directory:

...
it('signs up a new user', () =>{
    cy.get('button[id=new-account-button]').click();
    cy.get('input[id=affiliation]').type(affiliation);
    cy.get('input[id=password]').type(pass);
    cy.get('input[id=userName]').type(name);
    cy.get('input[id=email]').type(email);

    //Now the options
    cy.get('[name="chooseGender"]').click({force: true});
    cy.get('option').contains("Female").then(option =>{
      cy.wrap(option).contains("Female");
      option[0].click();
    });
...

I suppose there's two things I don't quite understand:

  1. Why wasn't an option actually selected?
  2. Why did the test pass despite this?

I provide a repo with my exact issue below:

git clone https://github.com/Atticus29/dataJitsu.git
cd dataJitsu
git checkout cypress-SO

Make an api-keys.ts file in /src/app and populate it with the text to follow

npm install
ng serve

(In a separate terminal tab)

npm run e2e

api-keys.ts:

export var masterFirebaseConfig = {
    apiKey: "AIzaSyCaYbzcG2lcWg9InMZdb10pL_3d1LBqE1A",
    authDomain: "dataJitsu.firebaseapp.com",
    databaseURL: "https://datajitsu.firebaseio.com",
    storageBucket: "",
    messagingSenderId: "495992924984"
  };

export var masterStripeConfig = {
  publicApiTestKey: "pk_test_NKyjLSwnMosdX0mIgQaRRHbS",
  secretApiTestKey: "sk_test_6YWZDNhzfMq3UWZwdvcaOwSa",
  publicApiKey: "",
  secretApiKey: ""
};
Atticus29
  • 4,190
  • 18
  • 47
  • 84
  • 1
    I appreciate you providing a working example! However, the `npm install` command failed for me. It's been hanging for the past few minutes at this line: `[############......] | extract: sill pacote rxjs@https://registry.npmjs.org/rxjs/-/rxjs-6.2.1.tgz extracted in 112447ms` – Joshua Wade Aug 06 '18 at 13:55
  • When you're targeting the element for clicking that Cypress thinks isn't clickable, are you targeting the same element that highlights when you right click -> inspect element in Chrome? – Joshua Wade Aug 06 '18 at 13:57
  • @JoshuaWade I'm not at my computer to address the first question, but regarding the second question, when I use the element inspector, it highlights elements that aren't in my html file (and hence can't assign names or ids). That's part of the issue in the first place. – Atticus29 Aug 06 '18 at 20:49
  • @JoshuaWade, I just tried the npm install from a fresh clone of the repo. Seems to work for me. Have you updated npm recently? What version are you working with? – Atticus29 Aug 06 '18 at 22:30
  • I'm using node 10, installed a few weeks ago. `npm --version` gives back `5.6.0`. – Joshua Wade Aug 07 '18 at 13:17
  • Hmm... What happens if you update npm? I'm working with version 6.x – Atticus29 Aug 07 '18 at 17:23
  • That worked, I got further this time. Now I'm getting an error when running `npx ng serve`: `ERROR in src/app/app.module.ts(6,38): error TS2307: Cannot find module './api-keys'.` and then `i 「wdm」: Failed to compile.` – Joshua Wade Aug 07 '18 at 18:01
  • @JoshuaWade I purposefully excluded the api-keys file from my repo...I'll add it to the details above and just change my API keys when this gets resolved. – Atticus29 Aug 08 '18 at 01:45
  • 1
    Alright, thanks - nginx is up and running! Just FYI, it looks like you accidentally removed a couple of commands when you added the API stuff. After putting in the `api-keys.ts` file, I ran `npm install --save-dev` and then `npx ng serve`, and then I ran `npm run e2e` to start Cypress. I had to specify the integration folder as `"e2e"` in the `cypress.json`. However, I have run into another error at this point. When running `app.e2e-spec.ts`, Cypress gives back a parse error on the first import: `ParseError: 'import' and 'export' may appear only with 'sourceType: module'`` – Joshua Wade Aug 08 '18 at 14:34
  • My apologies if this should be a simple error to fix. I'm much more comfortable with vanilla Javascript than with Typescript. – Joshua Wade Aug 08 '18 at 14:35
  • @JoshuaWade what if you change the e2e: "..." to e2e: "cypress open" in package.json? – Atticus29 Aug 09 '18 at 17:31
  • I just checked the file, that's what it says right now. – Joshua Wade Aug 10 '18 at 13:12
  • The error I'm getting is actually in the cypress window. It doesn't load any tests and instead shows a parse error. – Joshua Wade Aug 10 '18 at 13:14
  • Hmm. I don't know what to tell you, @JoshuaWade. A search of that error points to missing packages being a culprit (e.g. https://stackoverflow.com/questions/40029113/syntaxerror-import-and-export-may-appear-only-with-sourcetype-module-w)? All I can say is that it works for me. Maybe the issue is that you have an older or newer version of cypress installed globally than I'm specifying in package.json. Maybe the browser matters? I'm using Chrome. – Atticus29 Aug 10 '18 at 17:44
  • I was using electron 59, so maybe that had to do with it. Glad the question got answered. Sorry for taking so much of your time! – Joshua Wade Aug 13 '18 at 14:05

3 Answers3

9

For mat-select in Angular 7+ you have to use promises to wait for the options in the modal cdk-overlay to become available.

Here is a helper function for reuse:

function selectMaterialDropDown(formControlName, selectOption) {
  cy.get(`[formcontrolname="${formControlName}"]`).click().then(() => {
    cy.get(`.cdk-overlay-container .mat-select-panel .mat-option-text`).should('contain', selectOption);
    cy.get(`.cdk-overlay-container .mat-select-panel .mat-option-text:contains("${selectOption}")`).first().click().then(() => {
      // After click, mat-select should contain the text of the selected option
      cy.get(`[formcontrolname="${formControlName}"]`).contains(selectOption);
    });
  });
}

Call function:

selectMaterialDropDown('myMatSelectControlName', 'OptionTextToSelect');

Enrico Saunders
  • 109
  • 1
  • 3
5

I found the following test to work with your repository (Latest commit 353633c),

describe('Test Gender Select', () => {

  before(function () {
    cy.visit('http://localhost:4200/')
  })

  it('signs up a new user', () => {
    cy.get('button').contains('Create New Account').click();

    cy.get('#gender').select('Female', {
      force: true
    });
    cy.get('#gender').contains('Female')
  });
});

You can see from the Cypress test runner that it has indeed selected the Female option, so I believe it covers the aim of your original test.

If I try to use click() like so

cy.get('#gender').click({
  force: true
});

cypress gives the message

CypressError: cy.click() cannot be called on a element. Use cy.select() command instead to change the value.

So, following this instruction and using

cy.get('#gender').select('Female');

gives the following error message about visibility, which seems to be standard for a select using material design (both angular-material and materialize).

CypressError: Timed out retrying: cy.select() failed because this element is not visible ... Fix this problem, or use {force: true} to disable error checking.

so using { force: true } option on cy.select() fixes this problem.

I understand the visibility issue occurs because material design covers the parent with the options list, and Cypress uses criteria for visibility based on the parent (see this question), although now the force option works (with Cypress v3.0.3).

Richard Matsen
  • 20,671
  • 3
  • 43
  • 77
0

For Angular 9, this code works for me:

 cy.get('.selector').children('mat-form-field').click()
 cy.get('mat-option').contains('Option text').click()
Yair Cohen
  • 2,032
  • 7
  • 13