【问题标题】:test case not detecting update in ViewContainerRef测试用例未检测到 ViewContainerRef 中的更新
【发布时间】:2019-02-01 14:17:03
【问题描述】:

我的html 使用ng-template。模板是用来创建缩略图的。

 <ng-template #thumbnailTemplate let-option="option">

      <div id="{{option.divId}}"> <!-- top level div of thumbnail. This will have ids thumbnail-1, thumbnail-2 etc.-->
        <img id="{{option.imgId}}" src="{{option.imgSrc}}"> <!-- this will have width, height=80-->
        <a href="#" id="{{option.closeId}}" (click)="deleteThumbnail(option)"></a> <!-- the X button is created using CSS. This will have ids close-button-1, close-button-2. They'll also containn reference to the parent div id (thumbnail-1, thumbnail-2 ) -->
      </div>
    </ng-template>

input 元素中选择文件时会创建缩略图。 FileReader 发送 load 事件并调用我的事件处理程序,它应该通过在容器中添加视图来创建缩略图

handleReaderLoaded(event:FileReaderProgressEvent) {
    console.log("got load event of file reader ",event);
    let thumbnailTemplateViewRef:EmbeddedViewRef<any>;

    let imageString = event.target.result;//this will be like data:image/png;base64,ZGQ=ZGF0YTppbWFnZS9wbmc7YmFzZTY0LFpHUT0=

    console.log("result from file load: ",imageString);
    console.log("consecutive generator is ",this.consecutiveIdGenerator);
    //create new ids for div, img and a in the template
    ++this.consecutiveIdGenerator;
    let divId = "thumbnail-"+(this.consecutiveIdGenerator);
    console.log("div id "+divId);

    let imgId = "img-"+(this.consecutiveIdGenerator);
    console.log("img id "+imgId);


    let closeId = "close-button-"+(this.consecutiveIdGenerator);

    console.log("close Id is "+closeId);
    console.log("thumbnail container length was "+this.thumbnailContainerRef.length);

    //TODOM - define context as a class so that it can be used in new question and question details
    thumbnailTemplateViewRef = this.thumbnailContainerRef.createEmbeddedView(this.thumbnailTemplateRef,{option:{divId:divId,
        imgId:imgId,
        closeId:closeId,
        imgSrc:imageString}});

    //store the reference of the view in context of the template. This will be used later to retrive the index of the view when deleting the thumbnail
    thumbnailTemplateViewRef.context.option.viewRefId = thumbnailTemplateViewRef;
    console.log("thumbnail container length is "+this.thumbnailContainerRef.length);
  }

现在我想测试handleReaderLoaded 并通过在其中添加thumbnailTemplateViewRef 来检查它是否更新了thumbnailContainerRef

我写的规范是

fit('should upload image if user selects an image', () => {
    let newPracticeQuestionComponent = component;
    expect(newPracticeQuestionComponent.currentImageAttachmentCount).toBe(0);
    expect(newPracticeQuestionComponent.thumbnailContainerRef.length).toBe(0);

    let file1 = new File(["foo1"], "foo1.txt");

    let reader = newPracticeQuestionComponent.handleFileSelect([file1]);//the callback for FileReader load method is assigned in this function. The callback is handleReaderLoaded
fixture.detectChanges();
    expect(newPracticeQuestionComponent.currentImageAttachmentCount).toBe(1);
    expect(newPracticeQuestionComponent.thumbnailContainerRef.length).toBe(1);
    done(); //wait
console.log('done here');
  });

我的测试用例失败了,因为 expect(newPracticeQuestionComponent.thumbnailContainerRef.length).toBe(1); 显示为 0。

我做错了什么?

【问题讨论】:

    标签: angular6


    【解决方案1】:

    看来,我没有正确理解done 的用途。我想如果我使用done,脚本会自动等待但它不会(从以下跟踪中可以清楚地看出)

    reading file --> 这是在 handleFileSelect 中 context.js:1972 done here --> 在 handleFileSelect 中 context.js:1972 got load event of file reader ProgressEvent {isTrusted: true, lengthComputable: true, loaded: 4, total: 4, type: "load", …} --> 这是在回调句柄ReaderLoaded 中。所以规范在回调被调用之前就完成了。

    done 在 Jasmine 中充当检查站。当Jasmine 看到一个规范使用done 时,它知道除非调用了包含done 的代码段,否则它不能继续下一步(比如运行下一个规范)。

    我使用done 重写了规范并创建了检查点,如下所示

    it('should upload image if user selects an image', (done) => {
        let newPracticeQuestionComponent = component;
        expect(newPracticeQuestionComponent.currentImageAttachmentCount).toBe(0);
        expect(newPracticeQuestionComponent.thumbnailContainerRef.length).toBe(0);
    
        let imageThumbnailDiv = fixture.debugElement.query(By.css("#thumbnail-1"));
        let imageThumbnailImg = fixture.debugElement.query(By.css('#img-1'));
        let imageThumbnailClose = fixture.debugElement.query(By.css('#close-button-1'));
    
    //there should not be any HTML code which contains thumbnail
        expect(imageThumbnailDiv).toBeFalsy();
        expect(imageThumbnailImg).toBeFalsy();
        expect(imageThumbnailClose).toBeFalsy();
    
        let file1 = new File(["foo1"], "foo1.txt");
        let reader = newPracticeQuestionComponent.handleFileSelect([file1]);
    //file upload is async. so give time for `load` event of FileReader to be triggered and handled
        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(1);
    //the html for thumbnail should be created now
          let imageThumbnailDiv2 = fixture.debugElement.query(By.css("#thumbnail-1"));
          let imageThumbnailImg2= fixture.debugElement.query(By.css('#img-1'));
          let imageThumbnailClose2 = fixture.debugElement.query(By.css('#close-button-1'));
    
          expect(imageThumbnailDiv2).toBeTruthy();
          expect(imageThumbnailImg2).toBeTruthy();
          expect(imageThumbnailClose2).toBeTruthy();
          done();//without done, jasmine will finish this test spec without checking the assertions in the timeout
        }, 2000);
    
    
        //if done is not use, jasmine will just finish the current spec without checking any assertions
    
      });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      • 2017-05-14
      相关资源
      最近更新 更多