如果您使用 material 表单,请在 Angular 中使用 cypress 进行选择

Make selection using cypress in Angular if you're using material forms

我有一个看起来像这样的表格:

<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>
...

当我尝试使用 cypress select 下拉菜单时,它告诉我它不可见。当我按照 cypress 提供的解释 URL 时,它建议我在我的点击中使用 {force: true} 。这让我的测试通过了,但实际上似乎从未 select 项目。

我也遵循了 提供的解决方案,并在实际选项上实现了 jQuery 单击(请注意,我的 select 和选项标签不是 md-select 和 md-option 标签)

sample.spec.js 在我的 cypress 目录中:

...
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();
    });
...

我想有两件事我不太明白:

  1. 为什么实际上 select 没有一个选项?
  2. 尽管如此,为什么测试还是通过了?

我在下面提供了一个包含我的确切问题的回购协议:

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

在 /src/app 中创建一个 api-keys.ts 文件,并用后面的文本填充它

npm install
ng serve

(在单独的终端选项卡中)

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: ""
};

我发现以下测试适用于您的存储库(最新提交 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')
  });
});

从Cypress test runner可以看出确实选择了Female选项,所以我相信它涵盖了你原来测试的目的。

如果我尝试像这样使用 click()

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

赛普拉斯给出消息

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

因此,按照此说明并使用

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

给出以下关于可见性的错误消息,这似乎是使用 material 设计的 select 的标准(angular-material 和 material大小).

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

所以在 cy.select() 上使用 { force: true } 选项可以解决这个问题。

我理解可见性问题的发生是因为 material 设计用选项列表覆盖了父级,而 Cypress 使用基于父级的可见性标准(参见此 ),尽管现在 force 选项有效(使用 Cypress v3.0.3)。

对于 Angular 7+ 中的 mat-select,您必须使用 promises 来等待模态 cdk-overlay 中的选项可用。

这里有一个复用辅助函数:

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);
    });
  });
}

调用函数:

selectMaterialDropDown('myMatSelectControlName', 'OptionTextToSelect');

对于 Angular 9,此代码适用于我:

 cy.get('.selector').children('mat-form-field').click()
 cy.get('mat-option').contains('Option text').click()