微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Angular 中的深度测试组件和使用 debugElement 访问 html 的问题

如何解决Angular 中的深度测试组件和使用 debugElement 访问 html 的问题

我的 angular 应用程序中有一个组件层次结构,如下所示:

BookmarkContainer 具有以下子组件:

  • BookmarksListComponent
  • CreateBookmarkComponent

BookmarksListComponentngForBookmarkItemComponent

我正在尝试使用 BookmarkItemComponent 及其 BookmarkContainer 方法DebugElement 的测试中访问 query() 的模板。

这是 BookmarkContainer代码

@Component({
  selector: 'app-bookmarks-container',templateUrl: './bookmarks.container.html',styleUrls: ['./bookmarks.container.scss']
})
export class BookmarksContainerComponent implements OnInit {
  bookmarks$: Observable<Bookmark[]>;
  newBookmark: Bookmark;
  deletedBookmarkId: number;

  constructor(private bookmarkService: BookmarkService) {}

  ngOnInit(): void {
    this.setBookmarks();
  }

  private setBookmarks() {
    this.bookmarks$ = this.bookmarkService
      .currentUser()
      .pipe(
        mergeMap(session => this.bookmarkService.search({ account: session.user.uid }))
      );
  }
}

这里是相应的测试:

describe('BookmarkContainerComponent',() => {
  let component: BookmarksContainerComponent;
  let fixture: ComponentFixture<BookmarksContainerComponent>;
  let httpTestingController: HttpTestingController;

  const aBookmark: Bookmark = {
    id: 42,title: 'a bookmark',url: 'http://www.example.com',account: '1'
  };
  const anotherBookmark: Bookmark = {
    id: 43,title: 'another bookmark',url: 'http://www.example.fr',account: '1'
  };

  beforeEach(async(() => {
    Testbed.configureTestingModule({
      imports: [HttpClientTestingModule,ReactiveFormsModule],declarations: [BookmarksContainerComponent,BookmarksListComponent,BookmarkItemComponent,CreateBookmarkComponent],}).compileComponents();
  }));

  beforeEach(() => {
    fixture = Testbed.createComponent(BookmarksContainerComponent);
    component = fixture.componentInstance;
    httpTestingController = Testbed.inject(HttpTestingController);
    fixture.detectChanges();
  });

  it('should create',() => {
    expect(component).toBeTruthy();
  });

  it('should search bookmarks',fakeAsync(() => {
    const sessionRequest = httpTestingController.expectOne('/api/system/connect');
    sessionRequest.flush({ user: { uid: '1' } });

    const bookmarksRequest = httpTestingController.expectOne('/api/bookmarks_link/search');
    bookmarksRequest.flush([aBookmark,anotherBookmark]);

    //Here I am not sure how to access the li(s) from the BookmarkItemComponent
    const item = fixture.debugElement.query(By.directive(BookmarkItemComponent));

});

我尝试从 li(s) 访问 BookmarkItemComponent 但没有成功:item 始终是 null。我怀疑这与 BookmarkItemComponent 的嵌套级别有关...有人可以帮忙吗?

编辑

BookmarkContainer 的模板:

<app-bookmarks-list
  [bookmarks]="bookmarks$ | async"
  [newBookmark]="newBookmark"
  [updatedBookmark]="updatedBookmark"
  [deletedBookmark]="deletedBookmarkId"
  (deleteBookmarkEvt)="confirmDeleteBookmark($event)"
  (updateBookmarkEvt)="openUpdateForm($event)">
</app-bookmarks-list>
...

BookmarksListComponent 的模板:

<ng-container *ngFor="let bookmark of bookmarks">
  <div class="bookmark">
    <div class="">
      <ul class="bookmark-list">
        <app-bookmark-item
          [bookmark]="bookmark"
          (deleteBookmarkEvt)="deleteBookmark($event)"
          (updateBookmarkEvt)="updateBookmark($event)"
        >
        </app-bookmark-item>
      </ul>
    </div>
  </div>
</ng-container>

BookmarkItemComponent 的模板:

<li class="bookmark-item bookmark-item-{{ bookmark.id }}">
  <span class="bookmark-icon"></span>
  <span class="bookmark-text">
    <a href="{{ bookmark.url }}" target="_blank" title="{{ 'BOOKMARKS.OPEN' | translate}}">
    {{bookmark.title}}
    </a>
  </span>
  <span class="bookmark-actions">
    <a title="{{ 'GLOBAL.UPDATE' | translate}}" (click)="updateBookmark(bookmark)">
      <i class="glyphicon glyphicon-pencil"></i>
    </a>
    <a title="{{ 'GLOBAL.DELETE' | translate}}" (click)="deleteBookmark(bookmark.id)">
      <i class="glyphicon glyphicon-remove "></i>
    </a>
  </span>
</li>

解决方法

为了查看 DOM 中出现的 http 响应数据,您需要在 fixture.detectChanges() 之后执行一个 request.flush(...)。另外,我会删除 fakeAsync 包装。应该不需要。

例如,

it('should search bookmarks',function() {
    const sessionRequest = httpTestingController.expectOne('/api/system/connect');
    sessionRequest.flush({ user: { uid: '1' } });

    const bookmarksRequest = httpTestingController.expectOne('/api/bookmarks_link/search');
    bookmarksRequest.flush([aBookmark,anotherBookmark]);

    // add detectChanges here
    fixture.detectChanges();

    // item should be defined now.
    const item = fixture.debugElement.query(By.directive(BookmarkItemComponent));
});

,

您可以尝试在 beforeEach 上添加 async 吗?

beforeEach(async() => {
    fixture = TestBed.createComponent(BookmarksContainerComponent);
    component = fixture.componentInstance;
    httpTestingController = TestBed.inject(HttpTestingController);
    fixture.detectChanges();
  });

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。