想了解单元测试–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 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)
在我的单元测试中,我尝试创建一个模拟组件来测试我的服务,但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呢?
解决方法
@NgModule({ imports: [CommonModule],declarations: [TestDialogComponent],entryComponents: [TestDialogComponent] }) export class FakeTestDialogModule {}
然后
Testbed.configureTestingModule({ imports: [FakeTestDialogModule]
Angular 2 CLI“ng generate component”命令找不到app.module
ng generate component test
执行后,会生成新的组件文件,但引用不会添加到app.module.ts文件中:
No app module found. Please add your new class to your component.
我试图找到解决方案来解决这个问题所以我不必总是导入新组件并手动将其添加到声明中,但我在网上找不到任何关于此问题的信息.
我认为它可能与我的angular-cli.json文件有关,但似乎没问题:
有任何想法吗?
更新:
这是我的项目文件夹结构,简单.我删除了不相关的文件夹:
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 { }
解决方法
@ NgModule({
如果你在同一行上写两个,cli就能成功找到模块:
@NgModule({
Angular 2 – (SystemJS)模块’GalleryModule’导入的意外指令’ViewerComponent’
(SystemJS) Unexpected directive
ViewerComponent
imported by the modulegalleryModule
感谢您提供有关可能导致错误的任何帮助.
在主应用程序中,它导入库模块.
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(); } }
@NgModule({ imports: [browserModule,HttpModule],declarations: [galleryComponent,providers: [] }) export class galleryModule { }
检查Angular 2 Modules以获取更多信息.
Angular 2 –aot导致AnimationEntryMetadata失败
未捕获的错误:模块构建失败:错误: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)的未定义返回值
此测试失败,因为在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(); })); });
解决方法
提供者:[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)的未定义返回值的相关信息,可以在本站进行搜索。
本文标签: