Cypress – 无法与列表中的内容进行交互

huangapple go评论77阅读模式
英文:

Cypress - Can't interact with a content in a list

问题

我是你的中文翻译助手,以下是翻译好的内容:

我是Cypress的新手,还在学习中。

我在使用一个列表进行测试时遇到了一些困难,例如从列表中点击按钮。

这是我的代码:
session.cy.ts:

it('should display Create Button and click on Detail button', () => {
    // 找到它
    cy.get('.list button[routerLink="create"]').should('exist');
    // 找不到
    cy.get('.items .item button[routerLink="detail"]').click();
    cy.url().should('include', '/sessions/detail/1');
});

list.component.html:

<div class="list">
  <mat-card>
    <mat-card-header fxLayout="row" fxLayoutAlign="space-between center">
      <mat-card-title class="m0">Rentals available</mat-card-title>
      <button *ngIf="user!.admin" mat-raised-button color="primary" routerLink="create">
        <mat-icon>add</mat-icon>
        <span class="ml1">Create</span>
      </button>
    </mat-card-header>
    <div class="items mt2" fxLayout="row wrap" fxLayout.lt-md="column">
      <mat-card class="item" *ngFor="let session of (sessions$ | async)" fxFlex>
        <mat-card-header>
          <mat-card-title>{{ session.name }}</mat-card-title>
          <mat-card-subtitle>
            Session on {{ session.date | date: 'longDate'}}
          </mat-card-subtitle>
        </mat-card-header>
        <div mat-card-image fxLayoutAlign="center center">
          <img class="picture" src="assets/sessions.png" alt="Yoga session">
        </div>
        <mat-card-content>
          <p>
            {{ session.description }}
          </p>
        </mat-card-content>
        <mat-card-actions>
          <button mat-raised-button color="primary" [routerLink]="['detail',session.id]">
            <mat-icon>search</mat-icon>
            <span class="ml1">Detail</span>
          </button>
          <button *ngIf="user!.admin" mat-raised-button color="primary"[routerLink]="['update',session.id]">
            <mat-icon>edit</mat-icon>
            <span class="ml1">Edit</span>
          </button>
        </mat-card-actions>
      </mat-card>
    </div>
  </mat-card>
</div>

我唯一看到的区别是routerlink:

  • 对于create,它是routerLink="create"
  • 但对于detail,有一些[] [routerLink]="['detail',session.id]

我想知道是否有另一种方法来测试点击Detail,而不需要修改HTML,只在测试文件中添加一个唯一的类,例如class='detailButton'

英文:

I'm new on Cypress and still learning.

I have some difficult to make a test with a list like click button from a list.

Here my code
session.cy.ts :

it(&#39;should display Create Button and click on Detail button&#39;, () =&gt; {
    // Found it
    cy.get(&#39;.list button[routerLink=&quot;create&quot;]&#39;).should(&#39;exist&#39;);
    // Not found
    cy.get(&#39;.items .item button[routerLink=&quot;detail&quot;]&#39;).click();
    cy.url().should(&#39;include&#39;, &#39;/sessions/detail/1&#39;);
  });

list.component.html :

&lt;div class=&quot;list&quot;&gt;
  &lt;mat-card&gt;
    &lt;mat-card-header fxLayout=&quot;row&quot; fxLayoutAlign=&quot;space-between center&quot;&gt;
      &lt;mat-card-title class=&quot;m0&quot;&gt;Rentals available&lt;/mat-card-title&gt;
      &lt;button *ngIf=&quot;user!.admin&quot; mat-raised-button color=&quot;primary&quot; routerLink=&quot;create&quot;&gt;
        &lt;mat-icon&gt;add&lt;/mat-icon&gt;
        &lt;span class=&quot;ml1&quot;&gt;Create&lt;/span&gt;
      &lt;/button&gt;
    &lt;/mat-card-header&gt;
    &lt;div class=&quot;items mt2&quot; fxLayout=&quot;row wrap&quot; fxLayout.lt-md=&quot;column&quot;&gt;
      &lt;mat-card class=&quot;item&quot; *ngFor=&quot;let session of (sessions$ | async)&quot; fxFlex&gt;
        &lt;mat-card-header&gt;
          &lt;mat-card-title&gt;{{ session.name }}&lt;/mat-card-title&gt;
          &lt;mat-card-subtitle&gt;
            Session on {{ session.date | date: &#39;longDate&#39;}}
          &lt;/mat-card-subtitle&gt;
        &lt;/mat-card-header&gt;
        &lt;div mat-card-image fxLayoutAlign=&quot;center center&quot;&gt;
          &lt;img class=&quot;picture&quot; src=&quot;assets/sessions.png&quot; alt=&quot;Yoga session&quot;&gt;
        &lt;/div&gt;
        &lt;mat-card-content&gt;
          &lt;p&gt;
            {{ session.description }}
          &lt;/p&gt;
        &lt;/mat-card-content&gt;
        &lt;mat-card-actions&gt;
          &lt;button mat-raised-button color=&quot;primary&quot; [routerLink]=&quot;[&#39;detail&#39;,session.id]&quot;&gt;
            &lt;mat-icon&gt;search&lt;/mat-icon&gt;
            &lt;span class=&quot;ml1&quot;&gt;Detail&lt;/span&gt;
          &lt;/button&gt;
          &lt;button *ngIf=&quot;user!.admin&quot; mat-raised-button color=&quot;primary&quot;[routerLink]=&quot;[&#39;update&#39;,session.id]&quot;&gt;
            &lt;mat-icon&gt;edit&lt;/mat-icon&gt;
            &lt;span class=&quot;ml1&quot;&gt;Edit&lt;/span&gt;
          &lt;/button&gt;
        &lt;/mat-card-actions&gt;
      &lt;/mat-card&gt;
    &lt;/div&gt;
  &lt;/mat-card&gt;
&lt;/div&gt;

The only differences I see are the routerlink :

  • for the create it is routerLink=&quot;create&quot;
  • but for the detail there is some [] [routerLink]=&quot;[&#39;detail&#39;,session.id]

I want to know if there's another way to test the click Detail without modifying the html by adding an unique class like class=&#39;detailButton but just the test file ?

答案1

得分: 2

列表中的routerLink属性有点奇怪,因为它还包括session.id

无论session.id的值是什么,你都需要将其包含在选择器中。假设它等于123,那么选择器将是

cy.get('.items .item button[ng-reflect-router-link="detail,123"]')

为了进行实验,可以访问Angular示例网页,并在app.component.html中将Heros链接更改为[routerLink]="['detail',123]"

这是生成的HTML(在开发工具中检查):

<nav _ngcontent-ng-c1547112614="" class="ng-tns-c1547112614-0">
  <a
    _ngcontent-ng-c1547112614=""
    routerlink="/crisis-center"                 // 这是一个简单的routerLink
    routerlinkactive="active"
    ariacurrentwhenactive="page"
    class="ng-tns-c1547112614-0"
    ng-reflect-router-link="/crisis-center"
    ng-reflect-router-link-active="active"
    ng-reflect-aria-current-when-active="page"
    href="/crisis-center"
    >Crisis Center</a>
  <a
    _ngcontent-ng-c1547112614=""
    routerlinkactive="active"
    ariacurrentwhenactive="page"
    class="ng-tns-c1547112614-0"
    ng-reflect-router-link-active="active"
    ng-reflect-aria-current-when-active="page"
    ng-reflect-router-link="detail,123"         // 这是带有session.id的链接
    href="/detail/123"
    >Heroes</a>
</nav>

如果你不知道session.id的值,可以尝试使用部分属性选择器。^=运算符表示“以...开始”:

cy.get('.items .item button[ng-reflect-router-link^="detail,"]')

或者使用*=运算符,表示“包含”

cy.get('.items .item button[href*="detail"]')  // href是另一种选择

或者尝试使用按钮内部的文本

cy.contains('.items .item button', 'Detail')
英文:

The routerLink attribute inside the list is a little funky because it also includes the session.id.

Whatever the value of session.id is, you would need to include it in the selector. Say it equals 123, then the selector would be

cy.get(&#39;.items .item button[ng-reflect-router-link=&quot;detail,123&quot;]&#39;)

For experimentation purposes, go to the Angular sample webcontainer and on the app.component.html change the Heros link to [routerLink]=&quot;[&#39;detail&#39;,123]&quot;.

This is the HTML generated (inspecting in dev-tools):

&lt;nav _ngcontent-ng-c1547112614=&quot;&quot; class=&quot;ng-tns-c1547112614-0&quot;&gt;
  &lt;a
    _ngcontent-ng-c1547112614=&quot;&quot;
    routerlink=&quot;/crisis-center&quot;                 // this is a simple routerLink
    routerlinkactive=&quot;active&quot;
    ariacurrentwhenactive=&quot;page&quot;
    class=&quot;ng-tns-c1547112614-0&quot;
    ng-reflect-router-link=&quot;/crisis-center&quot;
    ng-reflect-router-link-active=&quot;active&quot;
    ng-reflect-aria-current-when-active=&quot;page&quot;
    href=&quot;/crisis-center&quot;
    &gt;Crisis Center&lt;/a&gt;
  &lt;a
    _ngcontent-ng-c1547112614=&quot;&quot;
    routerlinkactive=&quot;active&quot;
    ariacurrentwhenactive=&quot;page&quot;
    class=&quot;ng-tns-c1547112614-0&quot;
    ng-reflect-router-link-active=&quot;active&quot;
    ng-reflect-aria-current-when-active=&quot;page&quot;
    ng-reflect-router-link=&quot;detail,123&quot;         // this is with session.id in link
    href=&quot;/detail/123&quot;
    &gt;Heroes&lt;/a&gt;
&lt;/nav&gt;

If you don't know the session.id value, try using a partial attribute selector. The ^= operator means "begins with":

cy.get(&#39;.items .item button[ng-reflect-router-link^=&quot;detail,&quot;]&#39;)

or the *= operator, which means "contains"

cy.get(&#39;.items .item button[href*=&quot;detail&quot;]&#39;)  // href is an alternative

Or try using the text inside the button

cy.contains(&#39;.items .item button&#39;, &#39;Detail&#39;)

答案2

得分: 0

根据提供的HTML片段,你只有一个"创建"按钮,但是根据会话的数量,你正在迭代会话列表以渲染包括此按钮的卡片。

因此,Cypress无法解析cy.get('.items .item'),就像JavaScript无法在没有首先定位到正确项的情况下访问列表项的属性一样:

const list = [{value: 'foo'}];

// 无法工作
console.log(list.value)

根据你的策略,你需要使用Cypress API(eq、first、last等)来定位预期的项。

英文:

Based on the html snippet provided, you have only 1 'Create' button but as many 'detail' button as sessions given you are iterating over your session list to render cards including this button.

So Cypress can't resolve cy.get(&#39;.items .item&#39;) the same way Javascript can't resolve accessing the property of an item of a list without firstly targetting the proper item:

const list = [{value: &#39;foo}];

// cannot work
console.log(list.value)

Depending on your strategy, you need to target the expected item with the Cypress API (eq, first, last...).

huangapple
  • 本文由 发表于 2023年8月9日 07:43:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76863752.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定