9

Mam element kątowy 2, który reaguje na zmiany parametrów trasy (komponent nie ładuje się od zera, ponieważ nie wyprowadzamy z głównej trasy. Kod komponent:Angular 2 - test zmiany parametrów trasy

export class MyComponent{ 
    ngOnInit() { 
     this._routeInfo.params.forEach((params: Params) => { 
      if (params['area']){ 
       this._pageToShow =params['area']; 
      } 
     }); 
    } 
} 

to działa wspaniale i _pageToShow ustawiony jest odpowiedni na nawigacji

Próbuję przetestować zachowanie na zmianę trasy (a więc drugi spust obserwowalne ale to. odmowa pracy dla mnie.) Oto moja próba:

it('sets PageToShow to new area if params.area is changed', fakeAsync(() => { 
    let routes : Params[] = [{ 'area': "Terry" }]; 
    TestBed.overrideComponent(MyComponent, { 
     set: { 
      providers: [{ provide: ActivatedRoute, 
       useValue: { 'params': Observable.from(routes)}}] 
     } 
    }); 

    let fixture = TestBed.createComponent(MyComponent); 
    let comp = fixture.componentInstance; 
    let route: ActivatedRoute = fixture.debugElement.injector.get(ActivatedRoute); 
    comp.ngOnInit(); 

    expect(comp.PageToShow).toBe("Terry"); 
    routes.splice(2,0,{ 'area': "Billy" }); 

    fixture.detectChanges(); 
    expect(comp.PageToShow).toBe("Billy"); 
})); 

Ale to rzuca wyjątek TypeError: Cannot read property 'subscribe' of undefined po uruchomieniu go. Jeśli uruchomię go bez linii fixture.detectChanges();, to się nie powiedzie, ponieważ drugie oczekiwanie się nie powiedzie.

Odpowiedz

14

Najpierw należy użyć Subject zamiast Observable. Obserwowalne zostaje zasubskrybowane tylko raz. Tak więc wyemituje tylko pierwszy zestaw parametrów. Dzięki Subject możesz emitować przedmioty, a subskrypcja pojedyncza będzie je nadal otrzymywać.

let params: Subject<Params>; 

beforeEach(() => { 
    params = new Subject<Params>(); 
    TestBed.configureTestingModule({ 
    providers: [ 
     { provide: ActivatedRoute, useValue: { params: params }} 
    ] 
    }) 
}) 

Następnie w teście tylko emitować nowe wartości z params.next(newValue).

Po drugie, należy się upewnić, aby zadzwonić pod numer tick(). Tak działa fakeAsync. Użytkownik kontroluje asynchroniczne rozwiązywanie zadań. Ponieważ obserwowalne jako asychrounous, w chwili wysłania zdarzenia, nie dostanie się do subskrybenta synchronicznie. Więc musimy zmusić synchronicznego zachowania z tick()

Powyżej znajduje się pełna testu (Subject jest importowany z 'rxjs/Subject')

@Component({ 
    selector: 'test', 
    template: ` 
    ` 
}) 
export class TestComponent implements OnInit { 

    _pageToShow: string; 

    constructor(private _route: ActivatedRoute) { 
    } 

    ngOnInit() { 
    this._route.params.forEach((params: Params) => { 
     if (params['area']) { 
     this._pageToShow = params['area']; 
     } 
    }); 
    } 
} 

describe('TestComponent',() => { 
    let fixture: ComponentFixture<TestComponent>; 
    let component: TestComponent; 
    let params: Subject<Params>; 

    beforeEach(() => { 
    params = new Subject<Params>(); 
    TestBed.configureTestingModule({ 
     declarations: [ TestComponent ], 
     providers: [ 
     { provide: ActivatedRoute, useValue: { params: params } } 
     ] 
    }); 
    fixture = TestBed.createComponent(TestComponent); 
    component = fixture.componentInstance; 
    }); 

    it('should change on route param change', fakeAsync(() => { 
    // this calls ngOnInit and we subscribe 
    fixture.detectChanges(); 

    params.next({ 'area': 'Terry' }); 

    // tick to make sure the async observable resolves 
    tick(); 

    expect(component._pageToShow).toBe('Terry'); 

    params.next({ 'area': 'Billy' }); 
    tick(); 

    expect(component._pageToShow).toBe('Billy'); 
    })); 
}); 
+1

Upewnij się, aby przewinąć w dół w tym roztworze do umieszczenia na 'kleszcza() funkcji' ! Zupełnie za tym tęskniłem. Dzięki za rozwiązanie, to zadziałało dla mnie :) –

+0

Byłem w stanie użyć tego podejścia dla 'fragment' również dla linków wewnętrznych:' fragment = nowy Temat (); ', który jest odpowiedni do ukrywania/pokazywania zawartości zakładki , na przykład. –