2016-06-23 17 views
4

親コンポーネントから子コンポーネントに渡されたデータのテストの例はほとんどありませんでした。現在、Angular2 docsでは、子コンポーネントのDOM値を調べることによって、親コンポーネントから子にデータが渡されたかどうかを確認するテストが行​​われています()。私がこのアプローチで持っている問題は、親コンポーネントが子コンポーネントのhtml構造を知っていることです。親コンポーネントのジョブは、にデータを渡すためにちょうどです。それは@Componentデコレータでdirectives配列のAlbumCoverコンポーネントの依存関係を持ってい親コンポーネントから子コンポーネントへ角2ユニットテストデータが渡されました

'use strict'; 

import {Component, OnInit, Input} from '@angular/core'; 
import {StoryService} from '../../services/story.service'; 
import {StoryModel} from '../../models/story-model'; 
import {AlbumCover} from './album-cover/album-cover'; 
import {Author} from "./author/author"; 
import {StoryDuration} from "./story-duration/story-duration"; 

@Component({ 
    selector: 'story', 
    templateUrl: 'build/components/story/story.html', 
    providers: [StoryService], 
    directives: [AlbumCover, Author, StoryDuration] 
}) 

export class Story implements OnInit { 
    @Input('id') id:number; 
    public story:StoryModel; 

    constructor(private storyService:StoryService) {} 

    ngOnInit() { 
     this.getStory(); 
    } 

    private getStory() { 
     this.storyService.getStory(this.id).subscribe(story => this.story = story); 
    } 
} 

お知らせ方法:次のように例...

私はストーリーのコンポーネントを持っています。

<div *ngIf="story"> 
    <album-cover [image]="story.albumCover" [title]="story.title"></album-cover> 
    <div class="author-duration-container"> 
     <author [avatar]="story.author.avatar" [name]="story.author.name"></author> 
     <story-duration [word-count]="story.wordCount"></story-duration> 
    </div> 
</div> 

お知らせ私はAlbumCoverimageプロパティにStoryコントローラからstory.albumCoverを結合してい<album-cover [image]="story.albumCover" [title]="story.title"></album-cover>ライン:

は、ここに私の物語テンプレートです。これは完全に機能しています。今すぐテストのため:

import {provide} from '@angular/core'; 
import {beforeEach, beforeEachProviders, describe, expect, injectAsync, it, setBaseTestProviders, resetBaseTestProviders} from '@angular/core/testing'; 
import {HTTP_PROVIDERS} from '@angular/http'; 
import {BROWSER_APP_DYNAMIC_PROVIDERS} from "@angular/platform-browser-dynamic"; 
import {TEST_BROWSER_STATIC_PLATFORM_PROVIDERS, ADDITIONAL_TEST_BROWSER_PROVIDERS} from '@angular/platform-browser/testing'; 
import {ComponentFixture, TestComponentBuilder} from '@angular/compiler/testing'; 
import {Observable} from 'rxjs/Observable'; 

// TODO: this pattern of importing 'of' can probably go away once rxjs is fixed 
// https://github.com/ReactiveX/rxjs/issues/1713 
import 'rxjs/add/observable/of'; 

resetBaseTestProviders(); 
setBaseTestProviders(
    TEST_BROWSER_STATIC_PLATFORM_PROVIDERS, 
    [BROWSER_APP_DYNAMIC_PROVIDERS, ADDITIONAL_TEST_BROWSER_PROVIDERS] 
); 

import {Story} from './story'; 
import {StoryModel} from '../../models/story-model'; 
import {StoryService} from '../../services/story.service'; 

var mockStory = { 
    id: 1, 
    title: 'Benefit', 
    albumCover: 'images/placeholders/story-4.jpg', 
    author: { 
     id: 2, 
     name: 'Brett Beach', 
     avatar: 'images/placeholders/author-1.jpg' 
    }, 
    wordCount: 4340, 
    content: '<p>This is going to be a great book! I <strong>swear!</strong></p>' 
}; 

class MockStoryService { 
    public getStory(id):Observable<StoryModel> { 
     return Observable.of(mockStory); 
    } 
} 

describe('Story',() => { 
    var storyFixture, 
     story, 
     storyEl; 

    beforeEachProviders(() => [ 
     HTTP_PROVIDERS 
    ]); 

    beforeEach(injectAsync([TestComponentBuilder], (tcb:TestComponentBuilder) => { 
     return tcb 
      .overrideProviders(Story, [ 
       provide(StoryService, { 
        useClass: MockStoryService 
       }) 
      ]) 
      .createAsync(Story) 
      .then((componentFixture:ComponentFixture<Story>) => { 
       storyFixture = componentFixture; 
       story = componentFixture.componentInstance; 
       storyEl = componentFixture.nativeElement; 
       componentFixture.detectChanges(); 
      }); 
    })); 

    describe(`ngOnInit`,() => { 
     describe(`storyService.getStory`,() => { 
      it(`should be called, and on success, set this.story`,() => { 
       spyOn(story.storyService, 'getStory').and.callThrough(); 
       story.ngOnInit(); 
       expect(story.storyService.getStory).toHaveBeenCalled(); 
       expect(story.story.title).toBe('Benefit'); 
      }); 
     }); 
    }); 

    it('should not show the story component if story does not exist',() => { 
     story.story = null; 
     storyFixture.detectChanges(); 
     expect(storyEl.children.length).toBe(0); 
    }); 

    it('should show the story component if story exists',() => { 
     story.story = mockStory; 
     storyFixture.detectChanges(); 
     expect(storyEl.children.length).not.toBe(0); 
    }); 

    describe('story components',() => { 
     beforeEach(() => { 
      story.story = mockStory; 
      storyFixture.detectChanges(); 
     }); 

     describe('album cover',() => { 
      var element, 
       img; 

      beforeEach(() => { 
       element = storyEl.querySelector('album-cover'); 
       img = element.querySelector('img'); 
      }); 

      it(`should be passed the story albumCover and title to the album cover component`,() => { 
       expect(img.attributes.src.value).toBe(mockStory.albumCover); 
       expect(img.attributes.alt.value).toBe(mockStory.title); 
      }); 
     }); 

     describe('author',() => { 
      var element, 
       img, 
       nameEl; 

      beforeEach(() => { 
       element = storyEl.querySelector('author'); 
       img = element.querySelector('img'); 
       nameEl = element.querySelector('.name'); 
      }); 

      it(`should be passed the author name and avatar`,() => { 
       expect(img.attributes.src.value).toBe(story.story.author.avatar); 
       expect(img.attributes.alt.value).toBe(story.story.author.name); 
       expect(nameEl.innerText).toBe(story.story.author.name); 
      }); 
     }); 

     describe('story duration',() => { 
      var element; 

      beforeEach(() => { 
       element = storyEl.querySelector('.story-duration'); 
      }); 

      it(`should be passed the word count to generate the total read time`,() => { 
       story.story.wordCount = 234234; 
       storyFixture.detectChanges(); 
       expect(element.innerText).toBe(`852 min read`); 
      }); 
     }); 
    }); 
}); 

私のdescribe('album cover'...を見てください。私がこの期待に応えているのは、<album-cover>要素を見つけて、<img>タグを見つけて、<img>のDOM属性をチェックしていることです。私には、このexpectionはalbum-cover.spec.tsの中にあるべきです - story.spec.tsではありません。

私の質問はです:親コンポーネントがDOMコンポーネントの読み込みに頼ることなく子コンポーネントにデータを渡したかどうかをテストする方法はありますか?

答えて

6

overrideTemplateを使用すると、テスト用のビューだけを渡すことができます。

return tcb 
     .overrideTemplate(AlbumCover, '<div>{{valueFromParent}}</div>') 
     .overrideProviders(Story, [ 
+1

ガンター、これは私が探していたものです。ちょうど私のテストを更新し、それは完全に働いた。ありがとうございました!!!! – dwilt

+0

聞いて嬉しいです:) –

関連する問題