Untitled
unknown
plain_text
3 years ago
9.8 kB
5
Indexable
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { from, Observable, of } from 'rxjs';
import { catchError, map, switchMap } from 'rxjs/operators';
import { environment } from 'src/environments/environment';
import { SETTINGS } from '../app.settings';
import { AALocation, ILocationCheckResponse, ILocationResult, LocationErrorCode } from '../models';
import { ICustomerDetails } from '../models/policy.model';
import { RaboRoutes } from '../routing/rabo-routes.model';
import { EnvService } from './env.service';
@Injectable({ providedIn: 'root' })
export class AALocationService {
constructor(private http: HttpClient, private router: Router, private envService: EnvService) {}
getGeolocation(): Observable<ILocationResult> {
return new Observable<ILocationResult>((observer) => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
({ coords }) => {
observer.next({ location: new AALocation(coords) });
observer.complete();
},
(error) => {
if (error.code === error.PERMISSION_DENIED) {
observer.next({ error: LocationErrorCode.noPermission });
observer.complete();
}
if (error.code === error.POSITION_UNAVAILABLE) {
observer.next({ error: LocationErrorCode.notAvailable });
observer.complete();
}
},
SETTINGS.positionOptions
);
} else {
observer.next({ error: LocationErrorCode.unknown });
observer.complete();
}
});
}
getLocationFromGeolocation(): Observable<ILocationResult> {
return this.getGeolocation().pipe(
switchMap((loc) => {
return !loc.error ? this.processLocationResult(loc) : of(loc);
})
);
}
private processLocationResult(loc: ILocationResult): Observable<ILocationResult> {
loc.location.isAllowed = true;
loc.location.minAccuracy = SETTINGS.googleMaps.mapOptions.minAccuracy;
return loc.location.isAccurate() ? this.checkLocationFromLocation(loc.location) : of({ location: loc.location });
}
checkLocationFromLocation(location: AALocation): Observable<ILocationResult> {
return this.checkLocation(location).pipe(
map((result) => {
if (result && result.location) {
location.latitude = result.location.coordinates.latitude;
location.longitude = result.location.coordinates.longitude;
location.dangerousLocation = result.dangerousLocation;
location.motorway = result.motorway;
location.area = result.location.area;
location.text = result.location.text;
location.formattedAddressFromGeoLocation = result.formatted_address;
return { location };
} else {
this.router.navigate([RaboRoutes.Error, 'TryAgainErrorPage'], { queryParamsHandling: 'preserve' });
return { error: LocationErrorCode.nullLocationResponse };
}
})
);
}
checkLocation({ longitude, latitude }: AALocation): Observable<ILocationCheckResponse> {
const params: HttpParams = new HttpParams().set('lat', latitude?.toString()).set('lng', longitude?.toString());
return this.http
.get<ILocationCheckResponse>(environment.locationCheckURL, { params })
.pipe(catchError(() => of({} as ILocationCheckResponse)));
}
getLocationFromAddress$(postCode: string, firstLineOfAddress?: string): Observable<AALocation> {
return from(this.getLocationFromAddress(postCode, firstLineOfAddress));
}
async getLocationFromAddress(postCode: string, firstLineOfAddress?: string): Promise<AALocation> {
const geocoder = new google.maps.Geocoder();
postCode = postCode.trim().replace(/\s+/g, ' ').toUpperCase();
return new Promise((resolve, reject) => {
const address = firstLineOfAddress ? `${firstLineOfAddress}, ${postCode}` : postCode;
geocoder.geocode(
{
address,
componentRestrictions: { country: 'UK' },
},
(results, status) => {
if (status === 'OK') {
const slicedPostCode = new RegExp(postCode.replace(/\s.*$/, '').slice(0, 4), 'i');
if (slicedPostCode.test(results[0].formatted_address)) {
resolve({
latitude: results[0].geometry.location.lat(),
longitude: results[0].geometry.location.lng(),
});
} else if (firstLineOfAddress) {
resolve(this.getLocationFromAddress(postCode));
} else {
reject({ error: status });
}
} else if (status === 'ZERO_RESULTS' && firstLineOfAddress) {
resolve(this.getLocationFromAddress(postCode));
} else {
reject({ error: status });
}
}
);
});
}
getPoliciesDetails(): Observable<ICustomerDetails> {
return this.http.get<ICustomerDetails>(this.envService.customerPoliciesURL).pipe(
map((value: any) => value.customerDetails as ICustomerDetails),
catchError(() => of(null))
);
}
}
.
.
.
.
.
.
import { HttpClient } from '@angular/common/http';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { TestBed } from '@angular/core/testing';
import { Router } from '@angular/router';
import { of } from 'rxjs';
import { mockLocationCheckResponse } from 'src/app/mocks/location.mock';
import { AALocation } from '../models';
import { EnvService } from './env.service';
import { AALocationService } from './location.service';
describe('AALocationService', () => {
let aaLocationService: AALocationService;
let httpClientSpy: jasmine.SpyObj<HttpClient>;
let routerSpy: jasmine.SpyObj<Router>;
let envServiceSpy: jasmine.SpyObj<EnvService>;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
});
httpClientSpy = jasmine.createSpyObj('HttpClient', ['get']);
envServiceSpy = jasmine.createSpyObj('EnvService', ['']);
envServiceSpy.customerPoliciesURL = '/test';
routerSpy = jasmine.createSpyObj('Router', ['']);
routerSpy.navigate = jasmine.createSpy();
httpClientSpy.get = jasmine.createSpy().and.returnValue(of(mockLocationCheckResponse));
aaLocationService = new AALocationService(httpClientSpy, routerSpy, envServiceSpy);
});
it('should be created', () => {
expect(aaLocationService).toBeTruthy();
});
it('should call getGeolocation', () => {
spyOn(navigator.geolocation, 'getCurrentPosition').and.callFake((...args: any[]) => {
const position = { coords: { latitude: 0, longitude: 0 } };
args[0](position);
});
aaLocationService.getGeolocation().subscribe((data) => {
expect(data.location.latitude).toBe(0);
expect(data.location.longitude).toBe(0);
});
});
it('should call getGeolocation with error', () => {
spyOn(navigator.geolocation, 'getCurrentPosition').and.callFake((...args: any[]) => {
const error = {
code: 'noPermission',
};
args[1](error.code);
});
aaLocationService.getGeolocation().subscribe((errorObj) => {
expect(errorObj.error).toBe('noPermission');
});
});
it('should call checkLocation', () => {
aaLocationService.checkLocation({ latitude: 1, longitude: 1 }).subscribe((data) => {
expect(data).toEqual(mockLocationCheckResponse);
});
});
it('should call checkLocationFromLocation', () => {
spyOn(aaLocationService, 'checkLocation').and.returnValue(of(mockLocationCheckResponse));
aaLocationService.checkLocationFromLocation(mockLocationCheckResponse as AALocation);
expect(aaLocationService.checkLocation).toHaveBeenCalled();
});
it('should call checkLocationFromLocation', () => {
spyOn(aaLocationService, 'checkLocation').and.returnValue(of(mockLocationCheckResponse));
aaLocationService.checkLocationFromLocation(mockLocationCheckResponse as AALocation).subscribe((_x) => {
expect(aaLocationService.checkLocation).toHaveBeenCalled();
});
});
it('should call checkLocationFromLocation', () => {
spyOn(aaLocationService, 'checkLocation').and.returnValue(of(null));
aaLocationService.checkLocationFromLocation(mockLocationCheckResponse as AALocation).subscribe((_x) => {
expect(aaLocationService.checkLocation).toHaveBeenCalled();
});
});
it('should call getLocationFromGeolocationOnce', () => {
spyOn(aaLocationService, 'getGeolocation').and.returnValue(of(mockLocationCheckResponse));
aaLocationService.getLocationFromGeolocation();
expect(aaLocationService.getGeolocation).toHaveBeenCalled();
});
it('should call processLocationResult', () => {
let loc = {
location: {
isAllowed: false,
minAccuracy: 1,
isAccurate: function () {
return true;
},
},
};
spyOn(aaLocationService, 'checkLocationFromLocation');
aaLocationService['processLocationResult'](loc);
expect(aaLocationService.checkLocationFromLocation).toHaveBeenCalledWith(loc.location);
});
it('getLocationFromAddress$', async () => {
spyOn(aaLocationService, 'getLocationFromAddress').and.returnValue(of({}).toPromise());
aaLocationService.getLocationFromAddress$('456677').subscribe((_x) => {
expect(aaLocationService.getLocationFromAddress).toHaveBeenCalled();
});
});
});
Editor is loading...