Компонент тестирования Angular 2 выдает ошибку: не перехвачено (в обещании): ошибка: ошибки синтаксического анализа шаблона

Недавно я сделал приложение ng2 (использующее 2.0.1) с несколькими компонентами и службами. Я нахожусь в процессе тестирования (Карма Жасмин) моего HeaderComponent, который содержит мой UserService (который использует расширенный класс Http).

Я скопировал простые тесты из Angular.io Docs, чтобы следить за службы и дождитесь завершения инициализации компонента, чтобы проверить, была ли запущена функция службы и ее содержимое. Каждый раз, когда я запускаю последний тест с использованием fakeAsync (и async), который проверяет содержимое переменной currentUser в header.component, я получаю следующую ошибку ...

 Error: Uncaught (in promise): Error: Template parse errors:
    'header-section' is not a known element:
    1. If 'header-section' is an Angular component, then verify that it is part of this module.
    2. If 'header-section' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("
      [ERROR ->]<header-section></header-section>
      <router-outlet></router-outlet>
      <footer-section></footer-sectio"): AppComponent@1:2
    'router-outlet' is not a known element:
    1. If 'router-outlet' is an Angular component, then verify that it is part of this module.
    2. If 'router-outlet' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("
      <header-section></header-section>
      [ERROR ->]<router-outlet></router-outlet>
      <footer-section></footer-section>"): AppComponent@2:2
    'footer-section' is not a known element:
    1. If 'footer-section' is an Angular component, then verify that it is part of this module.
    2. If 'footer-section' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("
      <header-section></header-section>
      <router-outlet></router-outlet>
      [ERROR ->]<footer-section></footer-section>"): AppComponent@3:2

Эти селекторы взяты из моего компонента приложения ...

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'my-app',
  moduleId: module.id,
  template: `
  <header-section></header-section>
  <router-outlet></router-outlet>
  <footer-section></footer-section>`
})

export class AppComponent {

  constructor() {}

  test(): string {
    return 'this is a test';
  }
}

Мой header.component.spec ...

import { Http, Request, RequestOptionsArgs, Response, XHRBackend, RequestOptions, ConnectionBackend, Headers } from '@angular/http';
import { HttpIntercept } from '../../services/auth/auth.service';


import { BrowserModule } from '@angular/platform-browser';
import { HttpModule, JsonpModule } from '@angular/http';
import { FormsModule } from '@angular/forms';

import { RouterTestingModule } from "@angular/router/testing";
import { appRoutes } from '../../routes';

import { Cookie } from 'ng2-cookies/ng2-cookies';

import { AppComponent } from '../app/app.component';
import { HeaderComponent } from './header.component';
import { FooterComponent } from '../footer/footer.component';
import { HomeComponent }        from '../home/home.component';
import { Four0FourComponent }   from '../404/four0four.component';
import { UserProfileComponent }   from '../user-profile/user-profile.component';

import { UserService } from '../../services/user/user.service';
import { ClockService } from '../../services/clock/clock.service';
import { Observable } from 'rxjs/Observable';

import { TestBed, async, fakeAsync, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';

import { User } from '../../models/user/user.model';

class MockRouter { public navigate() { }; }

describe('HeaderComponent Test', () => {
  let fixture;
  let comp;
  let userService;
  let spy;

  let user = new User({
    _id: 123456,
    userName: 'testName',
    firstName: 'testFirst',
    lastName: 'testLast',
    email: '[email protected]',
    create: 'now',
    role: 'user'
  });

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        BrowserModule,
        HttpModule,
        FormsModule,
        JsonpModule,
        RouterTestingModule.withRoutes(appRoutes)
      ],
      declarations: [
        HomeComponent,
        UserProfileComponent,
        Four0FourComponent,
        FooterComponent,
        HeaderComponent,
        AppComponent
      ],
      providers: [
        {
          provide: Http,
          useFactory: (
            backend: XHRBackend,
            defaultOptions: RequestOptions) =>
            new HttpIntercept(backend, defaultOptions),
          deps: [XHRBackend, RequestOptions]
        },
        Cookie
      ]
    });

    fixture = TestBed.createComponent(HeaderComponent);
    comp = fixture.componentInstance;

    userService = fixture.debugElement.injector.get(UserService);

    spy = spyOn(userService, 'getMe')
      .and.returnValue(Observable.of(user));

  });

  it('should instantiate component', () => {
    expect(fixture.componentInstance instanceof HeaderComponent).toBe(true);
  });

  it('should not show currentUser before OnInit', () => {
    expect(spy.calls.any()).toBe(false, 'getMe not yet called');
  });

  it('should still not show currentUser after component initialized', () => {
    // Set cookie token, for the getMe to call
    Cookie.set('token', 'test_token_alpha');

    fixture.detectChanges();
    expect(spy.calls.any()).toBe(true, 'getMe called');
  });

  //The problem test is bellow
  it('should show currentUser after getMe promise', fakeAsync(() => {  
    fixture.detectChanges();
    tick();
    fixture.detectChanges();
    expect(comp.currentUser).toEqual(user);
  }));
});

Вот мой header.component ...

import { Component } from '@angular/core';
import { Cookie }    from 'ng2-cookies/ng2-cookies';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/interval';

import { UserService }  from '../../services/user/user.service';
import { ClockService } from '../../services/clock/clock.service';

import { User } from '../../models/user/user.model';

@Component({
  selector: 'header-section',
  providers: [
    UserService,
    ClockService
  ],
  moduleId: module.id,
  template: `
  <style>
    header{
      background: rgb(55, 129, 215);
      position: relative;
    }
    .user-sign{
      position: absolute;
      top:0;
      right:0;
      margin: 23px 5%;
    }
    .app-title{
      font-family: cursive;
      padding: 15px;
      text-align: center;
      font-size: 36px;
      color: white;
    }
    .user-sign button:hover{
      cursor: pointer;
    }
    .active{
      color: orange;
    }
  </style>
  <header>
    <a routerLink='/' routerLinkActive='active'>Home</a>
    <a routerLink='/profile' routerLinkActive='active'>Profile</a>
    <a routerLink='/yoloswaq69420blazeitfgt' routerLinkActive='active'>404</a>
    <div class='user-sign'>
      <h3 *ngIf='currentUser'>Welcome, {{currentUser.userName}}</h3>
      <button *ngIf='!currentUser' type='button' (click)='testRegisterUser()'>Sign up</button>
      <button *ngIf='!currentUser' type='button' (click)='testUser()'>Sign in</button>
      <button type='button' (click)='logout()'>Sign out</button>
    </div>
    <h1 class='app-title'>MEA2N Fullstack</h1>
  </header>`
})

export class HeaderComponent {
  errorMessage: string;
  public currentUser: User;
  clock = this.clockService.currentTime;

  constructor(private userService: UserService, private clockService: ClockService) { }

  ngOnInit() {
    let token = Cookie.get('token');
    if (token)
      this.userService.getMe().subscribe(user => this.currentUser = user);
  }

  login(email: string, password: string) {
    this.userService.login(email, password)
      .subscribe(() => {
        return this.userService.getMe()
          .subscribe(user => {
            this.currentUser = user;
          })
      });
  }

  logout() {
    this.userService.logout();
    this.currentUser = null;
  }

  registerUser(username: string, email: string, password: string) {
    this.userService.signup(username, email, password)
      .subscribe(() => {
        return this.userService.getMe()
          .subscribe(user => {
            this.currentUser = user;
          })
      });
  }

  testUser() {
    this.login('[email protected]', 'flight1855');
  }

  testRegisterUser() {
    this.registerUser('Jason', '[email protected]', 'flight1855');
  }
}

Я подозревал, что эта ошибка возникает из-за того, как я инициализирую свой TestBed.configureTestingModule ().

Я пробовал...

  1. Изменение порядка объявлений модулей app.module и TestBed
  2. добавление схемы: [CUSTOM_ELEMENTS_SCHEMA] в оба модуля

person Atheteo    schedule 08.10.2016    source источник
comment
Возможный дубликат компонента Angular 2 Karma Test '- name 'не является известным элементом   -  person Kim Kern    schedule 12.01.2018


Ответы (1)


Поскольку в этом случае вы выполняете модульное тестирование компонента Header, нет необходимости включать другие модули и компоненты.

TestBed может выглядеть так:

beforeEach(() => {
    TestBed.configureTestingModule({
        imports: [
            AppModule
        ],
        providers: [
            {provide: UserService, useClass: MockUserService},
            {provide: ClockService, useClass: MockClockService}
        ]
    });
    fixture = TestBed.createComponent(HeaderComponent);
});

В этом примере были смоделированы службы, но за ними тоже можно шпионить, как вы правильно сделали для UserService.

person qdivision    schedule 08.10.2016
comment
Я очень ценю ответ! Я попробовал ваше предложение, и это дало другую ошибку. Ошибка: ошибка в классе client / app / components / header / header.component.js HeaderComponent - встроенный шаблон: 27: 4, вызванный: не задано базовое значение href. Укажите значение для токена APP_BASE_HREF или добавьте в документ базовый элемент. Ошибка: не задан базовый href. Укажите значение для токена APP_BASE_HREF или добавьте в документ базовый элемент. - person Atheteo; 08.10.2016
comment
Поэтому я добавил {provide: APP_BASE_HREF, useValue: '/'} в список поставщиков, и теперь я получаю следующее: Ошибка: ошибка в client / app / components / header / header.component.js class HeaderComponent - встроенный шаблон: 27 : 4 вызвано: Загрузите хотя бы один компонент перед внедрением маршрутизатора - person Atheteo; 09.10.2016
comment
Извините, не могу помочь, не взглянув на код. Как выглядит ваш AppModule? Вы можете создать плункер? - person qdivision; 09.10.2016
comment
Вот ссылка на файл . . Спасибо за помощь, я очень ценю это :) AppModule по сути такой же, как и модуль TestBed моих исходных сообщений, за исключением маршрутизации - person Atheteo; 09.10.2016