angular


Angular 2 - test for change in route params


I have a component in angular 2 which responds to changes in the route parameters (the component doesn't reload from scratch because we're not moving out of the main route. Here's the component code:
export class MyComponent{
ngOnInit() {
this._routeInfo.params.forEach((params: Params) => {
if (params['area']){
this._pageToShow =params['area'];
}
});
}
}
This works a treat and _pageToShow is set appropriate on navigation.
I'm trying to test the behaviour on a change to the route (so a second trigger of the observable but it's refusing to work for me.) Here's my attempt:
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");
}));
But this throws a TypeError: Cannot read property 'subscribe' of undefined exception when I run it. If I run it without the fixture.detectChanges(); line it fails as the second expectation fails.
Firstly, you should use a Subject instead of an Observable. The observable only gets subscribed to once. So it will only emit the first set of params. With a Subject, you can keep emitting items, and the single subscription will keep getting them.
let params: Subject<Params>;
beforeEach(() => {
params = new Subject<Params>();
TestBed.configureTestingModule({
providers: [
{ provide: ActivatedRoute, useValue: { params: params }}
]
})
})
Then in your test just emit new values with params.next(newValue).
Secondly, you need to make sure to call tick(). This is how fakeAsync works. You control asynchronous task resolution. Since the observable as asychrounous, the moment we sent the event, it will not get to the subscriber synchronously. So we need to force synchronous behavior with tick()
Here is a complete test (Subject is imported from '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');
}));
});

Related Links

How to configure and use Auth-0 in Angular4
How to get meta tags work correctly in angular 2? [closed]
Angular2-highcharts switching option
How to make ViewChild work in a unit test
Angular 2 AOT: Getting lot of errors in index.d.ts
Angular2 doesn't work Custom Reuse Strategy with Lazy module loading
view not updated while changing class variable value angular2
Using Angular 2, how can I allow robots.txt to be viewed without angular routing being triggered?
Angular2 Google sign
Angular2 : Async Pipe and conditional styling. How to refactor my code?
Angular 2 attribute directive to clear textbox?
How to get asynchronous data from one Angular component to another
Looping using ngFor and skip nth element
How to populate a dropdown list default value from API in Angular2 Model based form
Async pipe where no element
How to trigger PrimeNG Accordion Click programmatically in Angular 2.0?

Categories

HOME
highcharts
instagram
function
accounting
luigi
slack
mariadb
access-token
graphviz
autofixture
spark-dataframe
jestjs
codecvt
cognos-10
google-login
nlog
intercept
cdb
pki
touch
coap
amazon-lightsail
webcam
size-classes
vowpalwabbit
mahapps.metro
ggiraph
reactive-streams
phpexcel-1.8.0
appery.io
fixtures
google-tv
apache-hive
meta-tags
oracle-ebs
keyword-search
sw-precache
burn
mosync
rufus-scheduler
orika
generated
dispy
use-case
report-viewer2012
countdowntimer
mockery
strstream
post-commit
mapfragment
google-plus-domains
little-endian
graphic-effects
stl-format
jseparator
adobe-flash-cs3
jedit
jlist
build-dependencies
html5builder
aloha-editor
mpmediapickercontroller
moovweb
smslib
custom-validators
kiosk-mode
jquery-dynatree
dcraw
uploadifive
navigationbar
curator
code-metrics
option
buttonclick
worklight-studio
texmacs
fluent-security
nodejitsu
citrix-access-gateway
circular-reference
mib
hyperterminal
robohelp
nservicebus3
enctype
alpha-five
primefaces-extensions
utl-file
.lrc
scopes
wymeditor
assetslibrary
spaces
pasteboard
cgpoint
layar
silverlight-embedded
widechar
windows-2000
installshield-2008
microsoft.build

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App