angular5 - TypeError:在角度 5 中进行单元测试时无法读取未定义问题的属性“路径”
问题描述
我正在尝试对我的 angular5 应用程序进行单元测试。每次输入“ng test”命令时,它都会显示一些错误并解决它。但现在它返回一个新错误。
Chrome 64.0.3282 (Linux 0.0.0) ChannelsComponent should create FAILED
TypeError: Cannot read property 'path' of undefined
at new ChannelsComponent src/app/rcyc-components/rcyc-channels/rcyc-channels.component.ts:71:53)
我在我的组件中使用 activateRoute 来检索当前 url
this.currentUrlPathAsArray= this.activatedRoute.snapshot.url;
this.currentUrlKey= this.currentUrlPathAsArray[0].path;
在上面使用激活路由的路径属性的代码中,我正在存储当前的 url。在我的应用程序上进行单元测试时,它会返回未定义错误的“路径”。
规格
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ChannelsComponent } from './rcyc-channels.component';
import { RouterModule } from "@angular/router";
import { NgxCarouselModule } from "ngx-carousel";
import { RcycDecodeHtmlPipe } from '../../rcyc-pipes/rcyc-decode-html/rcyc-decode-html.pipe';
import { RcycLimitPipe } from "../../rcyc-pipes/rcyc-limit/rcyc-limit.pipe";
import { RcycDefaultImagePipe } from '../../rcyc-pipes/rcyc-default-image/rcyc-default-image.pipe';
import { HttpClientModule } from '@angular/common/http';
import { RouterTestingModule } from '@angular/router/testing';
import { RcycCommonService } from '../../rcyc-services/rcyc-common/rcyc-common.service';
import { RcycChannelsService } from "./rcyc-channels.service";
describe('ChannelsComponent', () => {
let component: ChannelsComponent;
let fixture: ComponentFixture<ChannelsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports:[RouterModule,NgxCarouselModule,HttpClientModule,RouterTestingModule],
declarations: [ ChannelsComponent,RcycDecodeHtmlPipe,RcycLimitPipe,RcycDefaultImagePipe ],
schemas:[CUSTOM_ELEMENTS_SCHEMA],
providers:[RcycCommonService,RcycChannelsService]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ChannelsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
组件.ts
import { Component, OnInit, ViewEncapsulation } from "@angular/core";
// import { NgxCarousel , NgxCarouselStore} from "ngx-carousel";
import { Router, NavigationEnd, ActivatedRoute } from "@angular/router";
import { RcycChannelsService } from "./rcyc-channels.service";
import { AppConfig } from "../../rcyc-config/config";
import { RcycCommonService } from '../../rcyc-services/rcyc-common/rcyc-common.service';
import { NguCarousel,NguCarouselStore } from '@ngu/carousel';
@Component({
selector: "app-channels",
templateUrl: "./rcyc-channels.component.html",
styleUrls: ["./rcyc-channels.component.css"],
encapsulation: ViewEncapsulation.None,
providers: [RcycChannelsService]
})
export class ChannelsComponent implements OnInit {
public carouselOne: NguCarousel;
deckTabObject: any;
API_BASE_URL: any = AppConfig.API_BASE_URL;
IMG_BASE_URL: any = AppConfig.IMG_BASE_URL;
ELASTIC_API_BASE_URL: any = AppConfig.ELASTIC_API_BASE_URL;
tabcontent: any;
basepath: any;
apiResponseA: any;
apiResponseB: any;
apiResponseC: any;
apiResponseD: any;
apiResponseE: any;
apiResponseATemp: any=[];
apiResponseBTemp: any=[];
apiResponseCTemp: any=[];
apiResponseDTemp: any=[];
apiResponseETemp: any=[];
apiResponseAStatus: any = false;
apiResponseBStatus: any = false;
apiResponseCStatus: any = false;
apiResponseDStatus: any = false;
apiResponseEStatus: any = false;
apiUrlA: any;
apiUrlB: any;
apiUrlC: any;
apiUrlD: any;
apiUrlE: any;
apiUrlMetatag: any;
currentUrlPathAsArray: any;
currentUrlKey: any;
currentComponentName: any;
currentSlide:number = 0;
constructor(
private router: Router,
private rcycChannelsService: RcycChannelsService,
private rcycCommonService: RcycCommonService,
private activatedRoute: ActivatedRoute,
) {
// this.currentComponentName = this.activatedRoute.routeConfig.component.name;
this.currentComponentName = "RcycChannelsComponent";
// Current subHeader Status
this.rcycCommonService.changeSubHeaderStatus(true);
this.currentUrlPathAsArray= this.activatedRoute.snapshot.url;
this.currentUrlKey= this.currentUrlPathAsArray[0].path;
// To scroll up page
this.router.events.subscribe(evt => {
if (!(evt instanceof NavigationEnd)) {
return;
}
window.scrollTo(0, 0);
});
var switchKey= this.currentUrlKey;
switch(switchKey) {
case "cruise-ports":
// change changeCurrentComponent
this.rcycCommonService.changeCurrentComponent(this.currentComponentName);
// Call get Metatag function
this.apiUrlMetatag= "/api/v1/meta/destinations?_format=json";
this.rcycCommonService.getMetaTags(this.apiUrlMetatag);
this.rcycDestinationsContent();
break;
case "experience":
// Call get Metatag function
this.apiUrlMetatag= "/api/v1/meta/experience?_format=json";
this.rcycCommonService.getMetaTags(this.apiUrlMetatag);
this.rcycExperienceContent();
break;
case "presailing":
// Call get Metatag function
this.apiUrlMetatag= "/api/v1/meta/presailing?_format=json";
this.rcycCommonService.getMetaTags(this.apiUrlMetatag);
this.rcycPresailingContent();
break;
default:
break;
}
}
ngOnInit() {
// split url and redirection
/*if(this.currentUrlKey == "cruise-ports") {
this.rcycDestinationsContent();
} else {
this.rcycExperienceContent();
}*/
//Carousel settings
this.carouselOne = {
grid: { xs: 1, sm: 1, md: 1, lg: 1, all: 0 },
slide: 1,
speed: 500,
interval: 300000,
point: {
visible: false
},
load: 3,
touch: true,
loop: true,
custom: "banner"
};
//Tab options
this.deckTabObject = [
{
name: "Onboard",
class: "tab-link tab-link_suites is-active",
contentClass: "tab-pane is-visible",
active: true
},
{
name: "Ashore",
class: "tab-link",
contentClass: "tab-pane",
active: false
}
];
}
/* =============================================================================================================================================
Function to display Full Api Urls of Destination
=============================================================================================================================================== */
rcycDestinationsContent() {
this.apiUrlA = "/api/v1/destinations/header/a?_format=json";
this.apiUrlB = "/api/v1/destinations/content/b?_format=json";
this.apiUrlC = "/api/v1/destinations/content/c?_format=json";
this.apiUrlD = "/api/v1/regions?_format=json";
this.rcycChannelContent();
}
/* =============================================================================================================================================
Function to display Full Api Urls of Experience
=============================================================================================================================================== */
rcycExperienceContent() {
this.apiUrlA = "/api/v1/experience/header/a?_format=json";
this.apiUrlB = "/api/v1/experience/content/b?_format=json";
this.apiUrlC = "/api/v1/experience/content/c?_format=json";
this.apiUrlD = "/api/v1/experience/content/d?_format=json";
this.rcycChannelContent();
}
/* =============================================================================================================================================
Function to display Full Api Urls of Presailing
=============================================================================================================================================== */
rcycPresailingContent() {
this.apiUrlA = "/api/v1/presailing/header/a?_format=json";
this.apiUrlB = "/api/v1/presailing/content/b?_format=json";
this.apiUrlC = "/api/v1/presailing/content/c?_format=json";
this.apiUrlD = "/api/v1/presailing/content/d?_format=json";
this.rcycChannelContent();
}
/* =============================================================================================================================================
Function to display Full Apis Channels
=============================================================================================================================================== */
rcycChannelContent() {
/****************** Section A********************/
this.rcycChannelsService.channels(this.apiUrlA).subscribe(
response => {
this.apiResponseATemp = response;
if(this.apiResponseATemp.length) {
// var res= Object.values(response);
var res= Object.keys(response).map(function(key) {
return response[key];
});
if(res.length) {
this.apiResponseAStatus = true;
this.apiResponseA = response[0];
// Changing subheader A value
this.rcycCommonService.changeSubHeaderDataArray_A(this.apiResponseA);
} else {
// Changing subheader A value
this.rcycCommonService.changeSubHeaderDataArray_A([]);
}
} else {
// Changing subheader A value
this.rcycCommonService.changeSubHeaderDataArray_A([]);
}
},
err => {
console.log(err);
}
);
/******************Header Section B********************/
this.rcycChannelsService.channels(this.apiUrlB).subscribe(
response => {
this.apiResponseBTemp = response;
if(this.apiResponseBTemp.length) {
// var res= Object.values(response);
var res= Object.keys(response).map(function(key) {
return response[key];
});
if(res.length) {
var resArray=[];
for(let index in res) {
var factor= res[index];
if(factor.field_image) {
factor.field_image= this.IMG_BASE_URL+factor.field_image;
let imgTitle= this.rcycCommonService.imageNameAltSplit(factor.field_image);
factor.altTextBannerImg= factor.title+ " "+ imgTitle;
factor.titleTextBannerImg= factor.title+ " "+ imgTitle;
}else {
factor.altTextBannerImg= factor.title;
factor.titleTextBannerImg= factor.title;
}
resArray.push(factor);
if( parseInt(index)+1 == res.length ) {
this.apiResponseBStatus = true;
this.apiResponseB = resArray;
}
}
}
}
},
err => {
console.log(err);
}
);
/****************** Section C********************/
this.rcycChannelsService.channels(this.apiUrlC).subscribe(
response => {
this.apiResponseCTemp = response;
if(this.apiResponseCTemp.length) {
// var res= Object.values(response);
var res= Object.keys(response).map(function(key) {
return response[key];
});
if(res.length) {
this.apiResponseCStatus = true;
this.apiResponseC = response[0];
}
}
},
err => {
console.log(err);
}
);
/****************** Section D********************/
this.rcycChannelsService.channels(this.apiUrlD).subscribe(
response => {
this.apiResponseDTemp = response;
if(this.apiResponseDTemp.length) {
// var res= Object.values(response);
var res= Object.keys(response).map(function(key) {
return response[key];
});
if(res.length) {
var resArray= [];
for(let index in res) {
var factor= res[index];
if(factor.field_image) {
factor.field_image= this.IMG_BASE_URL+factor.field_image;
let imgTitle= this.rcycCommonService.imageNameAltSplit(factor.field_image);
factor.altTextOnBoardImg= factor.title+ " "+ imgTitle;
factor.titleTextOnBoardImg= factor.title+ " "+ imgTitle;
}else {
factor.altTextOnBoardImg= factor.title;
factor.titleTextOnBoardImg= factor.title;
}
if(this.currentUrlKey == 'cruise-ports') {
let field_group_url_keyNew= factor.field_group_url_key.toLowerCase();
factor.channelUrl="/luxury-"+field_group_url_keyNew+"-cruises";
} else if(this.currentUrlKey == 'experience') {
let field_url_keyNew= factor.field_url_key.toLowerCase();
factor.channelUrl="/experience/"+field_url_keyNew;
}
resArray.push(factor);
if( parseInt(index)+1 == res.length ) {
this.apiResponseDStatus = true;
this.apiResponseD = resArray;
}
}
}
}
},
err => {
console.log(err);
}
);
}
// Function on Learn more click
learnMoreClick(event, item) {
/****************** Section E********************/
}
nextCarouselload(ev) {
// console.log(ev);
}
onmoveFn(data: NguCarouselStore) {
this.currentSlide = data.currentSlide;
}
clickFn(data: NguCarouselStore){
this.currentSlide = data.currentSlide-1;
}
}
我该如何解决这个问题?
解决方案
推荐阅读
- javascript - 后台选项卡中的播放器不播放下一个播放列表曲目(自动播放策略?)
- android - Android - 如何从 Mapbox 中的 SymbolManager 中删除单个 SymbolOptions
- python - 如何修复烧瓶登录记住我不工作
- jmeter - 如何从请求在 JMeter 中失败的 URL 中捕获动态 ID?
- linux - Linux有没有办法列出存储库和子存储库中指定数量的行
- python-3.x - 下载服务器上的所有文件,但只有文件访问权限,没有 root 访问权限
- three.js - 如何在 Three.js 中创建带圆角的架子?
- python-3.x - 有没有办法使用 AWS CDK 中的标签导入现有安全组?
- gnuplot - 在gnuplot中计算曲线下的面积
- sql-server - 用于从两个不同节点的 SOAP 1.1 中提取数据的 SQL Server 查询