zoukankan      html  css  js  c++  java
  • [Unit testing Angular] Complete component code

    The component we test against:

    import {Component, OnInit} from '@angular/core';
    import {Course} from "../model/course";
    import {Observable} from "rxjs";
    import {CoursesService} from "../services/courses.service";
    import {map} from "rxjs/operators";
    import {sortCoursesBySeqNo} from './sort-course-by-seq';
    
    @Component({
        selector: 'home',
        templateUrl: './home.component.html',
        styleUrls: ['./home.component.css']
    })
    export class HomeComponent implements OnInit {
    
        beginnerCourses$: Observable<Course[]>;
    
        advancedCourses$: Observable<Course[]>;
    
        constructor(private coursesService: CoursesService) {
    
        }
    
        ngOnInit() {
    
          this.reloadCourses();
    
        }
    
    
        reloadCourses() {
    
          const courses$ = this.coursesService.findAllCourses();
    
          this.beginnerCourses$ = this.filterByCategory(courses$, 'BEGINNER');
    
          this.advancedCourses$ = this.filterByCategory(courses$, 'ADVANCED');
    
        }
    
        filterByCategory(courses$: Observable<Course[]>, category:string) {
          return courses$.pipe(
            map(courses => courses.filter(course => course.category === category).sort(sortCoursesBySeqNo) )
          );
        }
    
    }

    Template:

    <div class="container">
      <h3>All Courses</h3>
    
      <mat-tab-group>
        <ng-container *ngIf="beginnerCourses$ | async as beginnerCourses">
          <mat-tab label="Beginners" *ngIf="beginnerCourses?.length > 0">
            <courses-card-list
              (courseEdited)="reloadCourses()"
              [courses]="beginnerCourses"
            >
            </courses-card-list>
          </mat-tab>
        </ng-container>
    
        <ng-container *ngIf="advancedCourses$ | async as advancedCourses">
          <mat-tab label="Advanced" *ngIf="advancedCourses?.length > 0">
            <courses-card-list
              (courseEdited)="reloadCourses()"
              [courses]="advancedCourses"
            >
            </courses-card-list>
          </mat-tab>
        </ng-container>
      </mat-tab-group>
    </div>

    Testing code:

    import {
      async,
      ComponentFixture,
      fakeAsync,
      flush,
      flushMicrotasks,
      TestBed,
      tick
    } from "@angular/core/testing";
    import { CoursesModule } from "../courses.module";
    import { DebugElement } from "@angular/core";
    
    import { HomeComponent } from "./home.component";
    import { CoursesService } from "../services/courses.service";
    import { setupCourses } from "../common/setup-test-data";
    import { By } from "@angular/platform-browser";
    import { of } from "rxjs";
    import { NoopAnimationsModule } from "@angular/platform-browser/animations";
    import { click, textContent } from "../common/test-utils";
    
    describe("HomeComponent", () => {
      let fixture: ComponentFixture<HomeComponent>,
        component: HomeComponent,
        el: DebugElement,
        coursesService: any; // TestBed.inject(CoursesService) will fix type issue
    
      const beginnerCourses = setupCourses().filter(
        cs => cs.category === "BEGINNER"
      );
      const advancedCourses = setupCourses().filter(
        cs => cs.category === "ADVANCED"
      );
    
      beforeEach(async(() => {
        const coursesServiceSpy = jasmine.createSpyObj("CoursesService", [
          "findAllCourses"
        ]);
    
        TestBed.configureTestingModule({
          imports: [CoursesModule, NoopAnimationsModule],
          providers: [{ provide: CoursesService, useValue: coursesServiceSpy }]
        })
          .compileComponents()
          .then(() => {
            fixture = TestBed.createComponent(HomeComponent);
            component = fixture.componentInstance;
            el = fixture.debugElement;
            coursesService = TestBed.get(CoursesService);
          });
      }));
    
      it("should create the component", () => {
        expect(component).toBeTruthy();
      });
    
      it("should display only beginner courses", () => {
        coursesService.findAllCourses.and.returnValue(of(beginnerCourses));
        fixture.detectChanges();
    
        // only one tab available
        const tabs = el.queryAll(By.css(".mat-tab-label"));
        expect(tabs.length).toEqual(1, "Unexpect number of tabs");
      });
    
      it("should display only advanced courses", () => {
        coursesService.findAllCourses.and.returnValue(of(advancedCourses));
        fixture.detectChanges();
    
        const tabs = el.queryAll(By.css(".mat-tab-label"));
        expect(tabs.length).toEqual(1, "Unexpect number of tabs");
      });
    
      it("should display both tabs", () => {
        coursesService.findAllCourses.and.returnValue(of(setupCourses()));
        fixture.detectChanges();
    
        const tabs = el.queryAll(By.css(".mat-tab-label"));
        expect(tabs.length).toEqual(2, "Unexpect number of tabs");
      });
    
      /**
       *
       * async vs fakeAsync
       *
       * Depends on whether you need to call real http, if yes, then async
       * Otherwise, always fakeAsync
       */
      it("should display advanced courses when tab clicked - fakeAsync", fakeAsync(() => {
        coursesService.findAllCourses.and.returnValue(of(setupCourses()));
        fixture.detectChanges();
        const tabs = el.queryAll(By.css(".mat-tab-label"));
        click(tabs[1]);
        fixture.detectChanges();
        flush();
        const cardTitles = el.queryAll(By.css(".mat-card-title"));
        expect(cardTitles.length).toBeGreaterThan(0, "Could not find card titles");
        expect(textContent(cardTitles[0])).toContain("Angular Security Course");
      }));
    
      it("should display advanced courses when tab clicked - async", async(() => {
        coursesService.findAllCourses.and.returnValue(of(setupCourses()));
        fixture.detectChanges();
        const tabs = el.queryAll(By.css(".mat-tab-label"));
        click(tabs[1]);
        fixture.detectChanges();
        // async will tigger whenStable callback
        fixture.whenStable().then(() => {
          const cardTitles = el.queryAll(By.css(".mat-card-title"));
          expect(cardTitles.length).toBeGreaterThan(
            0,
            "Could not find card titles"
          );
          expect(textContent(cardTitles[0])).toContain("Angular Security Course");
        });
      }));
    });
  • 相关阅读:
    char*”类型的值不能用于初始化“LPTSTR , Const char*”类型的值不能用于初始化“LPCTSTR
    LPCTSTR和LPTSTR和char *
    C++ char*,const char*,string的相互转换(转)
    vs2017 开发 C++ 操作mysql的动态库
    VS2017 创建C++Dll动态库(二)
    VS2017中托管C++程序调用托管C++生成的动态库,程序无法调试的问题(转)
    win10 MySQLroot 远程连接
    c++中c_str()的用法详解(转)
    【605】Python的开发环境相关 (不同版本python、pip)
    【604】Python class __dict__.update的使用
  • 原文地址:https://www.cnblogs.com/Answer1215/p/12363450.html
Copyright © 2011-2022 走看看