2016-12-03 55 views
0

我试图测试一个角2成分输入外部模板角2组分变量不更新HTML模板,通过我的测试

以下是部分:

@Component({ 
    selector: 'text-counter', 
    templateUrl: 'text-counter.component.html', 
    styleUrls: ['text-counter.component.css'] 
}) 
export class TextCounterComponent implements OnChanges { 

    @Input() inputText: string; 
    @Input() min: number; 
    @Input() max: number; 
    @Input() tolerance: number = 20; 

    message: string; 
    messageClass: string; 

    constructor() { 
    } 

    ngOnChanges(changes: SimpleChanges) { 

    const input: string = changes['inputText'].currentValue; 

    function expandMessage(rawMessage, n) { 
     return rawMessage.replace('%', n); 
    } 

    const settings = { 
     initialPrompt: 'saisissez au moins % caractères', 
     nToGoPrompt: 'il manque % caractères', 
     nLeftPrompt: 'encore % caractères autorisés', 
     tooLongByPrompt: 'trop long de % caractères' 
    }; 

    const length = input ? input.length : 0; 

    this.messageClass = 'lightblue'; 

    if (length === 0) { 
     this.message = expandMessage(settings.initialPrompt, this.min); 
    } 
    else if (length > 0 && length < this.min) { 
     this.message = expandMessage(settings.nToGoPrompt, this.min - length); 
    } 
    else if (length >= this.min && length <= this.max) { 
     if (length > this.max - this.tolerance) { 
     this.messageClass = 'Gold'; 
     } 
     this.message = expandMessage(settings.nLeftPrompt, this.max - length); 
    } 
    else { 
     this.messageClass = 'Red'; 
     this.message = expandMessage(settings.tooLongByPrompt, length - this.max); 
    } 
    } 
} 

和它的模板:

<span class="form-text" [ngClass]="messageClass"> 
    {{message}} 
</span> 

message变量从未在模板由测试更新虽然ngOnChanges实际上是所谓的...

这里是测试:

@Component({ 
    selector: `test-host-component`, 
    template: `<div> 
      <text-counter 
       [inputText]="valueFromHost" 
       [min]="2" 
       [max]="500"> 
      </text-counter> 
      </div>` 
}) 
export class TestHostComponent { 
    /* using viewChild we get access to the TestComponent which is a child of TestHostComponent */ 
    @ViewChild(TextCounterComponent) 
    public textCounterComponent: any; 
    /* this is the variable which is passed as input to the TestComponent */ 
    public valueFromHost: string; 
} 

describe('Component: TextCounter',() => { 

    beforeEach(async(() => { 
    TestBed.configureTestingModule({ 
     declarations: [TextCounterComponent, TestHostComponent] 
    }) 
     .compileComponents(); 
    })); 

    it('should indicate min message',() => { 
    const hostComponentFixture = TestBed.createComponent(TestHostComponent); 
    const textCounterComponentFixture = TestBed.createComponent(TextCounterComponent); 

    const de: DebugElement = textCounterComponentFixture.debugElement.query(By.css('span')); 
    const el: HTMLElement = de.nativeElement; 
    let testHostComponent = hostComponentFixture.componentInstance; 

    testHostComponent.valueFromHost = 'a'; 

    spyOn(testHostComponent.textCounterComponent, 'ngOnChanges').and.callThrough(); 
    hostComponentFixture.detectChanges(); 
    textCounterComponentFixture.detectChanges(); 
    expect(testHostComponent.textCounterComponent.ngOnChanges).toHaveBeenCalled(); 

    expect(el.textContent).toContain('il manque');//This fails!! 
    }); 
}); 

这里是失败的断言:

Chrome 54.0.2840 (Mac OS X 10.12.1) Component: TextCounter should indicate min message FAILED 
     Expected ' 

     ' to contain 'il manque'. 

任何人都可以请帮助?

编辑1:我试图通过夹具detectChanges()后移动的elHTMLElement检索如下改变我的代码:

... 
const de: DebugElement = textCounterComponentFixture.debugElement.query(By.css('span')); 
const el: HTMLElement = de.nativeElement; 

expect(el.textContent).toContain('il manque'); 

无济于事......

+0

我只有在这里的观点是,你之前得到''el' fixture.detectChanges()'。尝试在'fixture.detectChanges'之后获得'el'。 – putonspectacles

回答

3

当你”重新调用TestBed.createComponent方法将前一个组件从DOM中删除。

步骤1

TestBad.createComponent

... 
const rootElId = `root${_nextRootElementId++}`; 
testComponentRenderer.insertRootElement(rootElId); <== see this line 

https://github.com/angular/angular/blob/2.2.4/modules/%40angular/core/testing/test_bed.ts#L358

步骤2

打开@角/平台的浏览器的动态/检测/ dom_tes t_component_renderer.ts

insertRootElement() { 
    ... 
    // TODO(juliemr): can/should this be optional? 
    const oldRoots = getDOM().querySelectorAll(this._doc, '[id^=root]'); 
    for (let i = 0; i < oldRoots.length; i++) { 
    getDOM().remove(oldRoots[i]); 
    } 
    ... 

https://github.com/angular/angular/blob/2.2.4/modules/%40angular/platform-browser-dynamic/testing/dom_test_component_renderer.ts#L27-L30

我想如下写:

it('should indicate min message',() => { 
    const hostComponentFixture = TestBed.createComponent(TestHostComponent); 
    //const textCounterComponentFixture = TestBed.createComponent(TextCounterComponent); 

    const de: DebugElement = hostComponentFixture.debugElement 
    .query(By.css('text-counter > span')); 
    const el: HTMLElement = de.nativeElement; 
    let testHostComponent = hostComponentFixture.componentInstance; 

    testHostComponent.valueFromHost = 'a'; 
    hostComponentFixture.detectChanges(); 

    expect(el.textContent).toContain('il manque');//This should work!! 
}); 

Plunker Example

+0

谢谢Yurzui!发现。出于纯粹的好奇心,你能告诉我你正在描述的行为在哪里被记录(先前的组件已从DOM中删除)吗? – balteo

+1

我已经添加了关于它的信息 – yurzui