Búsqueda de sitios web

javascript - ¿Cómo puedo hacer pruebas unitarias a componentes en AngularJS2 "final"?


Actualmente estoy intentando escribir una prueba unitaria para un componente muy simple de AngularJs2.

Esto es el Typescript:

// cell.component.ts
import { Component, Input } from '@angular/core';
import Cell from './cell';

@Component({
    moduleId: module.id,
    selector: 'cell',
    templateUrl: 'cell.component.html',
    styleUrls: ['cell.component.css']
})

export class CellComponent {
    @Input()
    cell = Cell;
}

Este es el modelo:

<!-- cell.component.html -->
<div class="ticTacToe--board-cell ticTacToe--board-cell--{{cell.background}}">
    <div class="ticTacToe--board-cell--{{cell.displayMarker()}}">{{cell.displayMarker()}}</div>
</div>

Y aquí está mi prueba actual:

// cell.component.spec.ts
    import { async, inject, TestBed } from '@angular/core/testing';
    import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
    import { ReflectiveInjector } from '@angular/core';

    import { CellComponent } from './cell.component';
    import Cell from './cell';
    import Marker from './marker.enum';

    //TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());

    describe('CellComponent', () => {
        beforeEach(() => {
            TestBed.configureTestingModule({
                declarations: [CellComponent]
            });
        });

        it ('should render a cell', async(() => {
            TestBed.compileComponents().then(() => {
                // Arrange
                const fixture = TestBed.createComponent(CellComponent);
                const componentUnderTest = fixture.nativeElement;
                const testId = 1; 
                const testMarker = Marker.X;
                const testCell = new Cell(1);
                testCell['marker'] = testMarker;

                // Act
                componentUnderTest.cell = testCell;

                // Assert
                fixture.detectChanges();
                expect(componentUnderTest.querySelectorAll('div.ticTacToe--board-cell').length).toBe(1);
                expect(componentUnderTest.querySelectorAll('div.ticTacToe--board-cell--background').length).toBe(1);
                expect(componentUnderTest.querySelectorAll('div.ticTacToe--board-cell--X').length).toBe(1);
                expect(componentUnderTest.querySelectorAll('div.ticTacToe--board-cell--X')[0].innerText).toBe('X');
            });
        }));
    });

Esto falla con:

Chrome 49.0.2623 (Windows XP 0.0.0) CellComponent debería renderizar una celda FALLADO1] [1] Falló: No capturado (en promesa): Error: Error en app/cell.component.html:1:9 causado por: self.context.cell.displayMarker no es una función [1] Error: No capturado (en promesa): Error: Error en app/cell.component.html:1:9 causado por: self.context.cell.displayMarker no es una función

Pero displayMarker es una función en mi clase Cell:

import  Marker  from './marker.enum';

export class Cell {
    id: number;
    private marker: Marker;
    private background = 'background';

    constructor(id: number) {
        this.id = id;
    }

    displayMarker() {
        return Marker[this.marker];
    }

    getMarker() {
        return this.marker;
    }

    setMarker(marker: Marker) {
        if (!this.marker) {
            this.marker = marker;
        }
    }

    declareWinner() {
        this.background = 'winner';
    }

    isEmpty() {
        return this.marker === undefined;
    }

  }

export default Cell;

... y cuando se prueba manualmente (en lugar de a través de Karma/Jasmine) esto funciona bien.

¿Alguna idea de cómo puedo hacer que mi prueba unitaria funcione?

Respuesta #1

Un par de errores.

  1. export class CellComponent {
        @Input()
        cell = Cell;  <===========
    }
    

    Estás asignando la function Cell a cell. Funciona cuando se prueba manualmente porque la información de tipo se ha perdido, y puedes asignarle lo que sea. Así que cuando realmente pasas una instancia de Cell a esto, entonces está bien. Pero debería cambiarse para usar la sintaxis de tipo

    @Input() cell: Cell;
    
  2. const fixture = TestBed.createComponent(CellComponent);
    const componentUnderTest = fixture.nativeElement;
    

    fixture.nativeElement no te da el componente en prueba, te da el elemento del DOM. ¿Por qué crees que puedes hacer componentUnderTest.querySelectorAll?

    En su lugar, deberías estar usando fixture.componentInstance para obtener el componente bajo prueba.