带有材质 UI 的 Angular 独立组件的塞浦路斯组件测试给出了 BrowserAnimationsModule 导入错误

问题描述 投票:0回答:2

我在我的角度应用程序的延迟加载路线中使用独立组件。当我提供应用程序时,一切正常。主应用程序使用模块,但所有其他组件都是独立的。

问题是当我尝试对这些懒惰的独立组件之一使用塞浦路斯组件测试时。

生成错误的组件使用材料 UI 元素(表格、输入、排序、分页等)。该组件中的某些内容在测试过程中给我带来了以下错误:

(未捕获的异常)错误:意外的合成侦听器 找到@arrowPosition.start。请确保:

  • BrowserAnimationsModule 或 NoopAnimationsModule 都会导入到您的应用程序中。
  • 在@Component的animations字段中定义了名为@arrowPosition.start的动画的相应配置 装饰器

这是我的代码:

import {
  AfterViewInit, ChangeDetectionStrategy, Component, EventEmitter, Input, Output,
  ViewChild,
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
import { MatPaginator } from '@angular/material/paginator';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatSort, MatSortModule } from '@angular/material/sort';
import { PersonalRecordListItem } from '@t3/data/domain/shared';
import { PrimaryContentCardComponent } from '@t3/training-tracker-web/ui-shared';
import { MatInputModule } from '@angular/material/input';

@Component({
  selector: 't3-personal-records-list',
  imports: [
    CommonModule,
    MatTableModule,
    MatPaginatorModule,
    MatSortModule,
    MatInputModule,
    PrimaryContentCardComponent,
  ],
  templateUrl: './personal-records-list.component.html',
  styleUrls: ['./personal-records-list.component.scss'],
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class PersonalRecordsListComponent implements AfterViewInit {
  @ViewChild(MatPaginator)
  paginator!: MatPaginator;
  @ViewChild(MatSort) sort!: MatSort;

  @Input() tabelData: PersonalRecordListItem[] = [];
  @Output() selectedRowChanged = new EventEmitter<string>();

  dataSource = new MatTableDataSource<PersonalRecordListItem>();
  displayedColumns: string[] = ['date', 'name', 'displayValue'];

  ngAfterViewInit() {
    this.dataSource = new MatTableDataSource(this.tabelData);
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }

  applyFilter(event: Event) {
    const filterValue = (event.target as HTMLInputElement).value;
    this.dataSource.filter = filterValue.trim().toLowerCase();

    if (this.dataSource.paginator) {
      this.dataSource.paginator.firstPage();
    }
  }

  selectRow(rowItem: PersonalRecordListItem) {
    this.selectedRowChanged.emit(rowItem.id);
  }
}

所以我尝试将以下内容添加到组件声明中:

提供者:[provideAnimations()],

但错误仍然存在

如果我将 BrowserAnimationsModule 添加到组件导入中,我会收到以下错误:

BrowserModule 中的提供程序已经加载。如果你需要 访问常见指令,例如 NgIf 和 NgFor,导入 改为 CommonModule。

BrowserAnimationsModule 被导入到主 app.module 中,这就是为什么在提供应用程序时不会出现错误,只有在测试其独立组件时才出现

编辑1:

我厌倦了将 ProvideAnimations() 添加到 cy.ts 文件中:

describe(PersonalRecordsListComponent.name, () => {
  beforeEach(() => {
    TestBed.overrideComponent(PersonalRecordsListComponent, {
      add: {
        imports: [],
        providers: [provideAnimations()],
      },
    });
  });

这并不能解决错误。

如果我将 AnimationsModule 添加到 cypress 文件中,如下所示:

    imports: [BrowserAnimationsModule],
    providers: [],

我收到了上面提到的已提供的错误。

有人可以帮助我在这里进行塞浦路斯组件测试吗?

angular angular-material cypress cypress-component-test-runner
2个回答
1
投票

解决此问题的方法是将 NoopAnimationsModule 添加到您的 cypress 测试文件中。我不使用 Testbed 进行 Cypress 组件测试,但您可以这样做:

beforeEach(() => {
    TestBed.overrideComponent(PersonalRecordsListComponent, {
      add: {
        imports: [NoopAnimationsModule],
      },
    });
  });

如果上述方法不起作用,请尝试以下操作: 在您的项目中,您应该有一个 cypress 文件夹。该文件夹内有一个文件:“commands.ts”

/cypress
|- /downloads
|- /fixtures
|- /support
|--- commands.ts // this is where you want to go
|--- component.ts

如果我没记错的话,这是自动设置的,但尽管如此,让我们检查一下是否是这样。

在该文件中,您可以声明自定义命令并为其添加类型,以便您可以使用它们。

我们正在寻找的是“mount”命令。所以该文件至少应该看起来像这样:

/// <reference types="cypress" />
import {mount} from 'cypress/angular'

// ***********************************************
// This example commands.ts shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
declare global {
  namespace Cypress {
    interface Chainable<Subject> {
      mount: typeof mount;
    }
  }
}

Cypress.Commands.add('mount', mount)

使用 cypress 的挂载功能,您可以轻松挂载组件并添加必要的导入、声明等。使用此功能,您可以将代码更改为如下所示:

describe(PersonalRecordsListComponent.name, () => {
  beforeEach(() => {
    cy.mount(PersonalRecordsListComponent, {
      imports: [NoopAnimationsModule, YourMaterialModules]
    })    
  });

  // your tests here

}

导入 NoopAnimationsModule 后,您应该不会遇到有关 Material UI 组件的任何问题。并且不要忘记将

YourMaterialModules
替换为您的组件所依赖的任何材料模块。

希望这有帮助!


0
投票

过了一会儿我又回到了这个问题。

问题在于,对于 cypress 组件测试,需要在单独的“it”测试中导入 NoopAnimationsModule。由于某种原因,将其添加到 overrideComponent 不起作用。

这是最终的效果,位于描述块内:

  it('should exist', () => {
    cy.mount(RowCellComponent, {
      imports: [NoopAnimationsModule],
    })
      .get('[cy-data="dropdown"]')
      .should('exist');
  });

简化代码

© www.soinside.com 2019 - 2024. All rights reserved.