GVKun编程网logo

单元测试 – Angular 2 TestModuleMetadata没有EntryComponents属性(angular cannot find module)

13

想了解单元测试–Angular2TestModuleMetadata没有EntryComponents属性的新动态吗?本文将为您提供详细的信息,我们还将为您解答关于angularcannotfindm

想了解单元测试 – Angular 2 TestModuleMetadata没有EntryComponents属性的新动态吗?本文将为您提供详细的信息,我们还将为您解答关于angular cannot find module的相关问题,此外,我们还将为您介绍关于Angular 2 CLI“ng generate component”命令找不到app.module、Angular 2 – (SystemJS)模块’GalleryModule’导入的意外指令’ViewerComponent’、Angular 2 –aot导致AnimationEntryMetadata失败、Angular 4.3中的单元测试HttpClientModule:来自HttpTestingController.expectOne(url)的未定义返回值的新知识。

本文目录一览:

单元测试 – Angular 2 TestModuleMetadata没有EntryComponents属性(angular cannot find module)

单元测试 – Angular 2 TestModuleMetadata没有EntryComponents属性(angular cannot find module)

我正在使用Angular CLI 1.0.0-beta.32.2并正在为Angular 2服务编写单元测试,该服务动态创建一个Component并将其插入另一个Component.

在我的单元测试中,我尝试创建一个模拟组件来测试我的服务,但ng测试的输出抛出一个错误,说明我的模拟组件在entryComponents属性中指定.当我尝试将Component添加到TestModuleMetadata对象的entryComponents属性中时,如下所示:Testbed.createTestingModule({… entryComponents:[TestDialogComponent] …})我看到以下错误说明entryComponents属性不存在.

Chrome 56.0.2924(Windows 10 0.0.0)DialogService应在打开Failed时创建子组件
错误:找不到TestDialogComponent的组件工厂.你有没有把它添加到@ NgModule.entryComponents?

查看TestModuleMetadata定义显示entryComponents属性不存在.那么如何在Angular 2和Jasmine的单元测试中动态创建一个Component呢?

解决方法

据我所知,它还没有得到支持.作为解决方法,您可以使用entryComponent创建假模块并将其导入测试模块

@NgModule({
  imports: [CommonModule],declarations: [TestDialogComponent],entryComponents: [TestDialogComponent]
})
export class FakeTestDialogModule {}

然后

Testbed.configureTestingModule({
    imports: [FakeTestDialogModule]

Angular 2 CLI“ng generate component”命令找不到app.module

Angular 2 CLI“ng generate component”命令找不到app.module

我一直在尝试使用Angular2的CLI工具使用此命令生成新组件:

ng generate component test

执行后,会生成新的组件文件,但引用不会添加到app.module.ts文件中:

No app module found. Please add your new class to your component.

enter image description here

我试图找到解决方案来解决这个问题所以我不必总是导入新组件并手动将其添加到声明中,但我在网上找不到任何关于此问题的信息.

我认为它可能与我的angular-cli.json文件有关,但似乎没问题:

enter image description here

有任何想法吗?

更新:
这是我的项目文件夹结构,简单.我删除了不相关的文件夹:

enter image description here

app.module.ts中的代码如下:

import { NgModule }         from '@angular/core';
import { browserModule }    from '@angular/platform-browser';
import { HttpModule }       from '@angular/http';
import { AppComponent }     from './app.component';
import { SearchComponent }  from './search/search.component';

@
NgModule({
    declarations: [
        AppComponent,SearchComponent
    ],imports: [
        browserModule,HttpModule
    ],providers: [
    ],bootstrap: [
        AppComponent
    ]
})
export class AppModule { }

解决方法

angular-cli无法找到app模块的问题是“@”符号和“NgModule”名称不在同一行.这不会导致代码在执行时失败,但会阻止CLI检测模块:

@
NgModule({

如果你在同一行上写两个,cli就能成功找到模块:

@NgModule({

Angular 2 – (SystemJS)模块’GalleryModule’导入的意外指令’ViewerComponent’

Angular 2 – (SystemJS)模块’GalleryModule’导入的意外指令’ViewerComponent’

我收到以下错误,不知道该怎么做:

(SystemJS) Unexpected directive ViewerComponent imported by the module galleryModule

感谢您提供有关可能导致错误的任何帮助.
在主应用程序中,它导入库模块.
gallery组件将viewer组件作为子组件.

图库组件:

import {Component,ngzone,ViewChild,ElementRef} from '@angular/core';
import {Http,Response} from '@angular/http';
import { ViewerComponent } from '../viewer/viewer.component';
import 'rxjs/Rx';

interface IImage {
  url: string;
  thumbnail: string;
  date: string;
  width: number;
  height: number;
}

@Component({
  selector: 'sd-gallery',templateUrl: 'gallery.component.html',styleUrls: ['gallery.component.css']
})
export class galleryComponent {;
  @ViewChild('galleryContainer') galleryContainer: ElementRef;
  @ViewChild('asyncLoadingContainer') asyncLoadingContainer: ElementRef;

  thumbnailBasePath = 'assets/img/gallery/preview_xxs/';
  currentIdx: number = 0;
  galleryBasePath: string = 'assets/img/gallery/';
  showBig: boolean = false;
  images: any[] = [{ url: '' }];
  gallery: any[] = [];
  imgIterations = 1;
  allImagesLoaded = false;

  // TypeScript public modifiers
  constructor(private _ngzone: ngzone,private http: Http) {

  }

  private ngAfterContentinit() {
    this.fetchDataAndRender();
  }

  private fetchDataAndRender() {
    this.http.get(this.galleryBasePath + 'data.json')
      .map((res: Response) => res.json())
      .subscribe(
      data => {
        this.images = data;
        this.render();
      },err => console.error(err),() => undefined);
  }

  private render() {
    let tempRow = [this.images[0]];
    let rowIndex = 0;
    let i = 0;

    for (i; i < this.imgIterations && i < this.images.length; i++) {
      while (this.images[i + 1] && this.shouldAddCandidate(tempRow,this.images[i + 1])) {
        i++;
      }
      if (this.images[i + 1]) {
        tempRow.pop();
      }
      this.gallery[rowIndex++] = tempRow;

      tempRow = [this.images[i + 1]];
    }

    this.scalegallery();

    if (i >= this.images.length) {
      this.allImagesLoaded = true;
    }
    else {
      this.checkForAsyncReload();
    }
  }

  private shouldAddCandidate(imgRow: IImage[],candidate: IImage): boolean {
    let oldDifference = this.calcIdealHeight() - this.calcRowHeight(imgRow);
    imgRow.push(candidate);
    let newDifference = this.calcIdealHeight() - this.calcRowHeight(imgRow);

    return Math.abs(oldDifference) > Math.abs(newDifference);
  }

  private calcRowHeight(imgRow: IImage[]) {
    let xsum = this.calcOriginalRowWidth(imgRow);

    let ratio = this.getgalleryWidth() / xsum;
    let rowHeight = imgRow[0].height * ratio;

    return rowHeight;
  }

  private scalegallery() {
    this.gallery.forEach((imgRow) => {
      let xsum = this.calcOriginalRowWidth(imgRow);

      if (imgRow != this.gallery[this.gallery.length - 1]) {
        let ratio = this.getgalleryWidth() / xsum;

        imgRow.forEach((img: any) => {
          img.width = img.width * ratio;
          img.height = img.height * ratio;
        })
      }
    })
  }

  private calcOriginalRowWidth(imgRow: IImage[]) {
    let xsum = 0;
    imgRow.forEach((img) => {
      let individualRatio = this.calcIdealHeight() / img.height;
      img.width = img.width * individualRatio;
      img.height = this.calcIdealHeight();
      xsum += img.width + 1;
    });

    return xsum;
  }

  private calcIdealHeight() {
      return (this.getgalleryWidth() / 8) + 70;
  }

  private openImageViewer(img: any) {
    this.showBig = undefined;
    this.showBig = true;
    this.currentIdx = this.images.indexOf(img);
  }

  private getgalleryWidth() {
    if (this.galleryContainer.nativeElement.clientWidth === 0) {
      // IE11
      return this.galleryContainer.nativeElement.scrollWidth;
    }
    return this.galleryContainer.nativeElement.clientWidth;
  }

  private checkForAsyncReload() {
    if (!this.allImagesLoaded) {
      var loadingDiv: any = this.asyncLoadingContainer.nativeElement;

      var elmTop = loadingDiv.getBoundingClientRect().top;
      var elmBottom = loadingDiv.getBoundingClientRect().bottom;

      var isVisible = (elmTop >= 0) && (elmBottom <= window.innerHeight);

      if (isVisible) {
        this.imgIterations += 5;
        this.fetchDataAndRender();
      }
    }
  }

  private onClose() {
    this.showBig = false;
  }

  private onResize() {
    this.render();
  }
}

图库模块:

import { browserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { ViewerComponent } from '../viewer/viewer.component';
import { galleryComponent } from './gallery.component';

@NgModule({
  imports: [browserModule,FormsModule,HttpModule,ViewerComponent],declarations: [galleryComponent],exports: [galleryModule],providers: []
})
export class galleryModule { }

查看器HTML:

<div(window:resize)="onResize($event)" [hidden]="!showViewer">
  <img [ngClass]="{'activeArrow': leftArrowActive}"[src]="arrows[0]" (click)="navigate(-1,false)" [hidden]="!showViewer || !leftArrowVisible" />
  <img [ngClass]="{'activeArrow': rightArrowActive}"[src]="arrows[1]" (click)="navigate(1,false)" [hidden]="!showViewer || !rightArrowVisible" />
  <div[hidden]="!showViewer">
    <span(click)="openFullsize()" [hidden]="!showViewer">100%</span>
    <imgsrc="assets/img/icon/close.svg" (click)="closeViewer()" [hidden]="!showViewer" />
  </div>
  <div(click)="showNavigationArrows()" (swipeleft)="navigate(1,true)" (swiperight)="navigate(-1,true)" [hidden]="!showViewer">
    <img[src]="previewImagePath" [hidden]="!showViewer" />
  </div>
</div>

查看器组件:

import {Component,ElementRef,Input,Output,EventEmitter} from '@angular/core';
import {Http,Response} from '@angular/http';
import 'rxjs/Rx';

interface IImage {
  url: string;
  thumbnail: string;
  date: string;
  width: number;
  height: number;
}

@Component({
  selector: 'sd-viewer',templateUrl: 'viewer.component.html',styleUrls: ['viewer.component.css']
})
//  host: {
 //   '(document:keydown)': 'onKeydown($event)',//  }
export class ViewerComponent {
  @input() images: any[];
  @input() currentIdx: number;
  @input() showViewer: boolean;
  @Output() onClose = new EventEmitter<boolean>();

  arrows: string[] = ['assets/img/icon/left.svg','assets/img/icon/right.svg'];
  leftArrowActive: boolean = true;
  rightArrowActive: boolean = true;
  leftArrowVisible: boolean = true;
  rightArrowVisible: boolean = true;
  previewImagePath = '';

  // TypeScript public modifiers
  constructor(private _ngzone: ngzone,private http: Http) {
  }

  ngOnChanges(changes: any) {
    if (this.images[this.currentIdx].name) {
      this.updatePreviewImage();
    }
  }

  ngAfterContentinit() {
  }

  onKeydown(event: KeyboardEvent) {
    let prevent = [37,39,27]
      .find(no => no === event.keyCode);
    if (prevent) event.preventDefault();

    switch (prevent) {
      case 37:
        // navigate left
        this.navigate(-1,false);
        break;
      case 39:
        // navigate right
        this.navigate(1,false);
        break;
      case 27:
        // esc
        this.closeViewer();
        break;
    }
  }

  updateArrowActivation() {
    if (this.currentIdx <= 0) {
      this.leftArrowActive = false;
    }
    else {
      this.leftArrowActive = true;
    }
    if (this.currentIdx >= this.images.length - 1) {
      this.rightArrowActive = false;
    }
    else {
      this.rightArrowActive = true;
    }
  }

  /**
  * direction (-1: left,1: right)
  * swipe (user swiped)
  */
  navigate(direction : number,swipe : boolean) {
    if ((direction === 1 && this.currentIdx < this.images.length - 1) ||
       (direction === -1 && this.currentIdx > 0)) {
      // increases or decreases the counter
      this.currentIdx += direction;
      if (swipe) {
        this.hideNavigationArrows();
      }
      else {
        this.updateArrowActivation();
        this.showNavigationArrows();
      }
      this.updatePreviewImage();
    }
  }

  hideNavigationArrows() {
    this.leftArrowVisible = false;
    this.rightArrowVisible = false;
  }

  showNavigationArrows() {
    this.leftArrowVisible = true;
    this.rightArrowVisible = true;
  }

  openFullsize() {
    window.location.href = 'assets/img/gallery/raw/' + this.images[this.currentIdx].name;
  }

  private closeViewer() {
    this.showViewer = false;
    this.onClose.emit(false);
  }

  private updatePreviewImage() {
    let height = window.innerHeight;
    let basePath = 'assets/img/gallery/';

    if (height <= 375) {
      basePath += 'preview_xxs/';
    } else if (height <= 768) {
      basePath += 'preview_xs/';
    } else if (height <= 1080) {
      basePath += 'preview_s/';
    } else if (height <= 1600) {
      basePath += 'preview_m/';
    } else if (height <= 2160) {
      basePath += 'preview_l/';
    } else if (height <= 2880) {
      basePath += 'preview_xl/';
    } else {
      basePath += 'raw';
    }

    this.previewImagePath = basePath + this.images[this.currentIdx].name;
  }

  private onResize() {
    this.updatePreviewImage();
  }
}
将ViewerComponent从galleryModule的导入移动到声明.只能将模块添加到模块的导入中.组件,指令和管道放在模块的声明中:
@NgModule({
  imports: [browserModule,HttpModule],declarations: [galleryComponent,providers: []
})

export class galleryModule { }

检查Angular 2 Modules以获取更多信息.

Angular 2 –aot导致AnimationEntryMetadata失败

Angular 2 –aot导致AnimationEntryMetadata失败

我的代码适用于ng build和ng build –prod howerver,当我添加–aot到命令时,它失败并出现以下错误:

未捕获的错误:模块构建失败:错误:C:/Users/dremache/Code/control-f2/client/src/app/transitions.ts(11,14):导出的变量’pageTransitions’已经或正在使用名称’AnimationEntryMetadata’来自外部模块“C:/ Users / dremache / Code / control-f2 / client / node_modules / @ angular / core / src / animation / Metadata”但无法命名.)

这是transitions.ts:

import { trigger,state,style,transition,animate,keyframes } from '@angular/core';


export const pageTransitions = 

  trigger('slideInOut',[

    state('in',style({transform: 'translateX(0)'})),transition('void => *',[
      style({transform: 'translateX(-60px)',opacity: '0'}),animate('300ms ease-out')
    ]),transition('* => void',[
      animate('300ms ease-out',style({transform: 'translateX(-60px)'}))
    ])
  ]);

这是导入它的组件:

//other imports
import { pageTransitions } from './transitions';

@Component({
  //other properties
  animations: [ pageTransitions,trigger('items',[
         // states and transitions here.. removing for cleanliness
      ]
  })

有任何想法吗?我这样做是为了避免重新定义相同的动画.这些动画正应用于来自void =>的组件. *创建页面过渡动画.

解决方法

固定它!

在我的transitions.ts文件中,我需要更改:

export const pageTransitions =

至:

export const pageTransitions: AnimationEntryMetadata =

(以及从@ angular / core导入AnimationEntryMetadata)

Angular 4.3中的单元测试HttpClientModule:来自HttpTestingController.expectOne(url)的未定义返回值

Angular 4.3中的单元测试HttpClientModule:来自HttpTestingController.expectOne(url)的未定义返回值

我试图了解如何使用作为新HttpClientModule的一部分提供的模拟功能.我的测试代码几乎完全匹配现有文档中显示的内容.但是,doc示例并不完整 – 例如,至少缺少TestBad和inject的import语句.我假设来自@ angular / common / http的HttpClient也是如此.我的测试代码添加了这些.

此测试失败,因为在httpMock.expectOne调用之后req最终未定义.我很欣赏为什么会这样.

import { Testbed,inject } from '@angular/core/testing';
import { HttpClient } from '@angular/common/http';
import { HttpClientTestingModule,HttpTestingController } from '@angular/common/http/testing';

describe('HttpClientTestingModule',() => {
  beforeEach(() => Testbed.configureTestingModule({
    imports: [ HttpClientTestingModule ],providers: [ HttpClient,HttpTestingController]
  }));

  it('expects a GET request',inject([HttpClient,HttpTestingController],(http: HttpClient,httpMock: HttpTestingController) => {
    http
      .get('/data')
      .subscribe(data => expect(data['name']).toEqual('Test Data'));

    const req = httpMock.expectOne('/data');
    expect(req).tobedefined();
    expect(req.request.method).toEqual('GET');
    req.flush({name: 'Test Data'});
    httpMock.verify();
  }));
});

解决方法

虽然我不明白为什么会这样,但我通过从Testbed.configureTestingModule中删除以下内容来实现它:

提供者:[HttpClient,HttpTestingController]

我欢迎任何深入了解为什么我需要将自己的服务添加到providers集合,而不是HttpClient,HttpTestingController.

我们今天的关于单元测试 – Angular 2 TestModuleMetadata没有EntryComponents属性angular cannot find module的分享就到这里,谢谢您的阅读,如果想了解更多关于Angular 2 CLI“ng generate component”命令找不到app.module、Angular 2 – (SystemJS)模块’GalleryModule’导入的意外指令’ViewerComponent’、Angular 2 –aot导致AnimationEntryMetadata失败、Angular 4.3中的单元测试HttpClientModule:来自HttpTestingController.expectOne(url)的未定义返回值的相关信息,可以在本站进行搜索。

本文标签: