我正在测试这个函数,它被认为是从ViewContainerRef中删除一个EmbeddedViewRef。
deleteThumbnail(thumbnailContext:ThumbnailContext){
console.log("delete thumbnail clicked with context ",thumbnailContext);
let wasConfirmed = confirm("Are you sure you want to delete the attachment?");
if(wasConfirmed) {
console.log("deleting index ", thumbnailContext.index);
this.thumbnailContainerRef.remove(thumbnailContext.index);
return false; /*returning false cancels the click and thus cancels further navigation and prevents the browser from going to the page specified (in this case #).*/
}
}以下是测试用例。它上传了3个文件( handleFileSelect方法将创建嵌入的视图),然后调用deleteThumbnail方法将它们从视图中删除
fit('should delete the correct image if multiple images are present and the user deletes a thumbnail', (done) => {
let newPracticeQuestionComponent = component;
//expect(newPracticeQuestionComponent.currentImageAttachmentCount).toBe(0);
expect(newPracticeQuestionComponent.thumbnailContainerRef.length).toBe(0);
let imageThumbnailDiv1 = fixture.debugElement.query(By.css("#thumbnail-1"));
let imageThumbnailImg1 = fixture.debugElement.query(By.css('#img-1'));
let imageThumbnailClose1 = fixture.debugElement.query(By.css('#close-button-1'));
let imageThumbnailDiv2 = fixture.debugElement.query(By.css("#thumbnail-2"));
let imageThumbnailImg2 = fixture.debugElement.query(By.css('#img-2'));
let imageThumbnailClose2 = fixture.debugElement.query(By.css('#close-button-2'));
let imageThumbnailDiv3 = fixture.debugElement.query(By.css("#thumbnail-3"));
let imageThumbnailImg3 = fixture.debugElement.query(By.css('#img-3'));
let imageThumbnailClose3 = fixture.debugElement.query(By.css('#close-button-3'));
expect(imageThumbnailDiv1).toBeFalsy();
expect(imageThumbnailImg1).toBeFalsy();
expect(imageThumbnailClose1).toBeFalsy();
expect(imageThumbnailDiv2).toBeFalsy();
expect(imageThumbnailImg2).toBeFalsy();
expect(imageThumbnailClose2).toBeFalsy();
expect(imageThumbnailDiv3).toBeFalsy();
expect(imageThumbnailImg3).toBeFalsy();
expect(imageThumbnailClose3).toBeFalsy();
let file1 = new File(["foo1"], "foo1.txt",{type: "image/png"});
let file2 = new File(["foo2"], "foo2.txt",{type: "image/png"});
let file3 = new File(["foo3"], "foo3.txt",{type: "image/png"});
let fileSelectControl = (fixture.debugElement.query(By.css("#question-file-upload"))).nativeElement as HTMLInputElement;
let reader1= newPracticeQuestionComponent.handleFileSelect(fileSelectControl,[file1]);
let reader2 = newPracticeQuestionComponent.handleFileSelect(fileSelectControl,[file2]);
let reader3 = newPracticeQuestionComponent.handleFileSelect(fileSelectControl,[file3]);
setTimeout(function() {
console.log("in timeout");
fixture.detectChanges();//without this, the view will not be updated with model
//expect(newPracticeQuestionComponent.currentImageAttachmentCount).toBe(1);
expect(newPracticeQuestionComponent.thumbnailContainerRef.length).toBe(3);
let imageThumbnailDiv11 = fixture.debugElement.query(By.css("#thumbnail-1"));
let imageThumbnailImg12= fixture.debugElement.query(By.css('#img-1'));
let imageThumbnailClose13 = fixture.debugElement.query(By.css('#close-button-1'));
let imageThumbnailDiv21 = fixture.debugElement.query(By.css("#thumbnail-2"));
let imageThumbnailImg22= fixture.debugElement.query(By.css('#img-2'));
let imageThumbnailClose23 = fixture.debugElement.query(By.css('#close-button-2'));
let imageThumbnailDiv31 = fixture.debugElement.query(By.css("#thumbnail-3"));
let imageThumbnailImg32= fixture.debugElement.query(By.css('#img-3'));
let imageThumbnailClose33 = fixture.debugElement.query(By.css('#close-button-3'));
expect(imageThumbnailDiv11).toBeTruthy();
expect(imageThumbnailImg12).toBeTruthy();
expect(imageThumbnailClose13).toBeTruthy();
expect(imageThumbnailDiv21).toBeTruthy();
expect(imageThumbnailImg22).toBeTruthy();
expect(imageThumbnailClose23).toBeTruthy();
expect(imageThumbnailDiv31).toBeTruthy();
expect(imageThumbnailImg32).toBeTruthy();
expect(imageThumbnailClose33).toBeTruthy();
//delete 2nd thumbnail first
let thumbnailViewRef2:EmbeddedViewRef<ThumbnailContext> = newPracticeQuestionComponent.thumbnailContainerRef.get(1) as EmbeddedViewRef<ThumbnailContext>;
console.log("will delete 2nd thumbnail with context ",thumbnailViewRef2);
newPracticeQuestionComponent.deleteThumbnail(thumbnailViewRef2.context);
console.log("continuing deleting other images. Ref ",newPracticeQuestionComponent.thumbnailContainerRef);
expect(newPracticeQuestionComponent.thumbnailContainerRef.length).toBe(2);
console.log("even further.");
let imageThumbnailDiv211 = fixture.debugElement.query(By.css("#thumbnail-2"));
let imageThumbnailImg222 = fixture.debugElement.query(By.css('#img-2'));
let imageThumbnailClose233 = fixture.debugElement.query(By.css('#close-button-2'));
console.log("here now ",imageThumbnailDiv211);
console.log("here now ",imageThumbnailImg222);
console.log("here now ",imageThumbnailClose233);
expect(imageThumbnailDiv211).toBeFalsy();
expect(imageThumbnailImg222).toBeFalsy();
expect(imageThumbnailClose233).toBeFalsy();
//as 2nd was deleted, 3rd now becomes 2nd, 1st stays as 1
console.log("will delete 1st thumbnail with context ");
let thumbnailViewRef1:EmbeddedViewRef<ThumbnailContext> = newPracticeQuestionComponent.thumbnailContainerRef.get(0) as EmbeddedViewRef<ThumbnailContext>;
console.log("repeat will delete 1st thumbnail with context ",thumbnailViewRef1);
newPracticeQuestionComponent.deleteThumbnail(thumbnailViewRef1.context);
expect(newPracticeQuestionComponent.thumbnailContainerRef.length).toBe(1);
let imageThumbnailDiv111 = fixture.debugElement.query(By.css("#thumbnail-1"));
let imageThumbnailImg122 = fixture.debugElement.query(By.css('#img-1'));
let imageThumbnailClose133 = fixture.debugElement.query(By.css('#close-button-1'));
expect(imageThumbnailDiv111).toBeFalsy();
expect(imageThumbnailImg122).toBeFalsy();
expect(imageThumbnailClose133).toBeFalsy();
//delete the last thumbnail
let thumbnailViewRef3:EmbeddedViewRef<ThumbnailContext> = newPracticeQuestionComponent.thumbnailContainerRef.get(0) as EmbeddedViewRef<ThumbnailContext>;
console.log("will delete 3rd thumbnail with context ",thumbnailViewRef3);
newPracticeQuestionComponent.deleteThumbnail(thumbnailViewRef3.context);
expect(newPracticeQuestionComponent.thumbnailContainerRef.length).toBe(0);
let imageThumbnailDiv311 = fixture.debugElement.query(By.css("#thumbnail-3"));
let imageThumbnailImg322 = fixture.debugElement.query(By.css('#img-3'));
let imageThumbnailClose333 = fixture.debugElement.query(By.css('#close-button-3'));
expect(imageThumbnailDiv311).toBeFalsy();
expect(imageThumbnailImg322).toBeFalsy();
expect(imageThumbnailClose333).toBeFalsy();
//console.log("before done call")
done();//without done, jasmine will finish this test spec without checking the assertions in the timeout
//console.log("after timeout call")
}, 2000);
//if done is not use, jasmine will just finish the current spec without checking any assertions
//console.log("It is done")
});在第一次调用deleteThumnbnail之后,测试执行停止了一段时间,过了一段时间,浏览器崩溃了(见图)。测试执行到达了第三次console.log("here now ",imageThumbnailClose233);打印的地方。

在这张图片中,您会注意到传递给deleteThumbnail的Thumbnail引用有一个值,但后来index的值变成了undefined

我认为expect(imageThumbnailDiv211).toBeFalsy();行可能是问题所在,请仔细查看以下堆栈跟踪

发布于 2019-09-15 02:03:04
如果您删除一个项目,Angular将更新索引。您正在通过索引访问列表中的项,但一旦删除索引2处的项,索引3处的项就会重新分配到索引2。
你可以在这里看到它是如何工作的:https://next.plnkr.co/edit/aBRRw2q8LlhbTNAo
https://stackoverflow.com/questions/57937817
复制相似问题