How do I mock data for the subscriber - angular

I am running a unit test on angular app, I want to pass on data to subscribe as shown in the code below, I tried many ways let me know which one is correct
getData() {
this.http.post<Transactions[]>('/api/getrecords', this.filter)
.subscribe(res => {
if (res['status'] == "FAILURE") {
//do something
} else {
console.log(res['status']);
this.data = res['data'];
}
}
tried to pass on getData like this
mockService.getData=of(mockUsageRecords);//tried this
mockService.getData=mockUsageRecords;//tried this
mockService.getData.and.returnValue(of(mockUsageRecords));//this one gives error

Related

Angular 6 how to wait for httpclient to return

I am trying to call a function on my flask interface from Angular 6. A function that should verify some credentials upon a click and according to the response either show an error or navigate to a page.
Thought I can not seem to be able to find a way to wait for the response before executing the next line of code. This causes a bug where the button needs to be pressed twice for the navigation to happen.
I tried using asyc/await, tried using .then, tried switching the subscribe to map but nothing works.
I guess I am missing something critical.
onClick() {
let data = {
// some data
}
let response = this.login(data);
if (response["valid"] === true) {
this.router.navigate(['/cool_page']);
}
}
login(data) {
let login_data = {}
this.httpClient.post('http://somedomain.com/login', JSON.stringify(data)).subscribe( response => {
login_data = response;
});
return login_data; //this remains empty
}
It require small correction related to Subscription.
onClick() {
let data = {
// some data
}
let response = this.login(data).subscribe( response => {
if (response["valid"] === true) {
this.router.navigate(['/cool_page']);
}
});
}
login(data) {
let login_data = {}
return this.httpClient.post('http://somedomain.com/login', JSON.stringify(data));
}

Missing my next() when replacing my services with ngrx effects in my angular app

In my app I get my data from a web api. I have my service, which looks like this:
getVehicles(): Observable<Vehicle[]> {
return this.http.get<Vehicle[]>(this.API_URL).pipe(
tap(() => this.log(`fetched vehicles`)),
catchError(this.handleError('getVehicles', []))
);
}
And I used to have a function in my component which looked like this:
getVehicles(): Observable<Vehicle[]> {
const details = this.vehicleService.getVehicles();
return details;
}
In my ngOnInit I could then do something smooth like this
this.getVehicleDetails().subscribe(data => {
this.vehicleDetails = data;
this.setMarkers();
})
Now however I am using ngrx and my code is looking quite differently for obvious reasons.
ngOnInit() {
// getvehicles
this.vehicles$ = this.store.select(fromStore.getAllVehicles);
this.store.dispatch(new fromStore.LoadVehicles());
}
The problem is that I used to be able to use my next() method in my ngOnInit to set my markers on my map with my function setMarkers(). When I called my setMarkers() outside of my old getVehicles function it used to return nothing, since my vehicles are undefined for the first seconds of initialization of the app. By using it inside the next method I could avoid that.
This is not the case anymore however, and I wonder if there is something similar I can do to be able to use my function setMarkers(), now when I have changed my code?
For anyone who is interested I solved this by subscribing to the store, inside of my ngOnInit and dispatching whenever the data was called for (such as on my update button function)
// init selected vehicle details inside of my ngOnInit
ngOnInit() {
this.store.select(fromStore.getAllVehicleDetail).subscribe(data => {
this.vehicleDetail = data;
if (this.vehicleDetail.position) {
this.setMap();
this.setMarkers();
} else {
this.failSetMap();
this.setMarkers();
}
});
}
click() {
this.store.dispatch(new fromStore.LoadVehicleDetail());
}

Angular : After data binding component variable going out of scope

I am facing a strange issue. Refer the following code.
// Variables at page level
nonAuthorizedResponse: INonAuthorizedResponse;
authorizedResponse: IAuthorizedResponse;
borrowersNonAuthorized: IBorrower[];
borrowersNonAuthsFiltered: IBorrower[];
authorizedData: IAuthorizedData[];
ngOnInit() {
// Get Data From Server
this.getDataFromServer();
//Setting Paging Data Source
this.setPagingSourceAfterDataLoad();
}
Following is the call to server:-
getDataFromServer(){
this.nregMainPageHttpService.getBorrowListForMyActiveProfiles().subscribe(
data => {
this.nonAuthorizedResponse = data;
this.borrowersNonAuthorized = this.nonAuthorizedResponse.borrowers;
this.totalRecords = this.nonAuthorizedResponse.totalRecords;
},
error => this.errorMessage = <any>error, () => { }
);
}
Following is the method:-
setPagingSourceAfterDataLoad(){
// this.borrowersNonAuthorized is showing undefined on debugging
if (this.borrowersNonAuthorized && this.borrowersNonAuthorized.length > 0) {
this.nregMainPageBusinessLogicService.setPagingSourceProperties(this.totalRecords, this.pagingSourceForBorrowLevel);
}
}
The 2nd call is got paging component. This call is after getDataFromServer();
Modified version:-
ngOnInit() {
// Get Data From Server
this.getDataFromServer();
// code commented moved inside getDataFromServer()
//this.setPagingSourceAfterDataLoad();
}
getDataFromServer(){
this.nregMainPageHttpService.getBorrowListForMyActiveProfiles().subscribe(
data => {
this.nonAuthorizedResponse = data;
this.borrowersNonAuthorized = this.nonAuthorizedResponse.borrowers;
this.totalRecords = this.nonAuthorizedResponse.totalRecords;
// call added
this.setPagingSourceAfterDataLoad();
},
error => this.errorMessage = <any>error, () => { }
);
}
Now the paging component works.
I fail to understand the issue why variable this.borrowersNonAuthorized becomes "undefined"
best regards,
Sidd
Isn't this.getDataFromServer() an async operation? As johnny mention in his comment, your method this.setPagingSourceAfterDataLoad() is being hit before the server callback and populate your data...
To fix it, you will have to await the server call to finish.
Assuming you are using Angular HttpClient to make server call, you will have to either use .toPromise() or subscribe to the callback.
something like the following:
1) If getDataFromServer returns a promise
this.getDataFromServer().then(() => {
this.setPagingSourceAfterDataLoad();
}
2) If getDataFromServer returns an observable
this.sub = this.getDataFromServer().subscribe(() => {
this.setPagingSourceAfterDataLoad();
}
UPDATE:
As suggested in the comment below, when one Server call is dependent on another, You should chain them together. The modified works because you are calling setPagingSourceAfterDataLoad within you subscription of getDataFromServer.
As for why you have undefined in your borrowersNonAuthorized I would debug you code and make sure data has a property borrower, my guess is that it is not defined.
Although the example above works, it is flawed as it will introduce memory leak. You need to hold a reference to your subscription and unsubscribe when you are done. If you do not unsubscribe, each subscription will continue watching for changes.
Base on the above code, i suggest the following small modification.
ngOnInit() {
// Get Data From Server
this.sub = this.getDataFromServer();
}
ngOnDestroy() {
this.sub.unsubscribe();
}
getDataFromServer(){
return this.nregMainPageHttpService.getBorrowListForMyActiveProfiles().subscribe(
data => {
this.nonAuthorizedResponse = data;
this.borrowersNonAuthorized = this.nonAuthorizedResponse.borrowers;
this.totalRecords = this.nonAuthorizedResponse.totalRecords;
// call added
this.setPagingSourceAfterDataLoad();
},
error => this.errorMessage = <any>error, () => { }
);
}

How do you unit test if statements in angular

I have a function that subscribes a response from the NGRX store then uses the variable provided to change a message.
How do I test that the message changes when the variable updates?
getData() {
this.service.getPreferences().subscribe(res => {
this.mypreference$ = res.mypreference;
});
if (this.mypreference$ == false) {
(this.mypreferenceType = 'noPreference');
} else {
(this.mypreferenceType = 'Preference');
}
}
getPreferences() { return this.store.select('user').map((state: User) => state); }
To do the kind of test you are looking for, you just need to stub the getPreferences method of your service. So something like this should test one of the paths in the function:
it('getData should set mypreferenceType to noPreference when getPreferences returns false', async(() => {
let service = TestBed.get(Service);
let component = TestBed.createComponent(Component).componentInstance;
spyOn(service, 'getPreferences').and.returnValue(Observable.of(false));
component.getData();
expect(component.mypreferenceType).toEqual('noPreference');
}));
However as mickaelw said in a comment I'm pretty sure you'll find that the test will fail. The if statement will run before the code in the subscribe function.

How to subscribe to service in Angular 2 few times in one component?

My service works just fine the first time. When it's called again later it doesn't work. I have the service in NgModule
Here is my code
this._portService.getPortList().subscribe(
(data) => {
this.len = data['interfaces-state'].length;
for (this.i = 0; this.i<this.len;this.i++){
this.portListJson.push(data['interfaces-state'][this.i].interface);
}
this.removeONUPorts();
this.addNames();
});
And my constructor
constructor(private _portService:PortsService, private elRef: ElementRef){
}
When I try to call the same code from different function it doesn't work.
My service
getPortList(){
return this._http.get(environment.api + "restconf/data/ietf-interfaces:interfaces-state/interface?fields=")
.map(response => response.json());
};
My second call
setONUList(port: Port){
this.clearLists();
this._portService.getPortList().subscribe(
(data) => {
this.len = data['interfaces-state'].length;
for (this.i = 0; this.i<this.len;this.i++){
this.portListJson.push(data['interfaces-state'][this.i].interface);
}
this.removeONUPorts();
this.addNames();
});
}
I'm not sure what you're trying to accomplish here. I don't understand why you need 2 subscriptions from the same component. Typically I instantiate my subscriptions in a component's constructor or ngOnInit method, then map the value from the subscription to a local value in the component, which can then be accessed from any component method.
So I would do something like this:
this._portService.getPortList().subscribe(
(data) => {
this.localDataVar = data;
...
});
then in your component method you can access your localDataVar variable
setONUList(port: Port){
this.clearLists();
this.someFunction(this.localDataVar); //here you'll have last emitted value of data
}
Or another way is to simply access the current observable value in your subsequent methods like this:
setONUList(port: Port){
this.clearLists();
let curVal = this._portService.getPortList().getValue();
}
I don't understand why you would need or want two identical subscriptions from the same component.

Resources