Skip to content

Commit 3efe386

Browse files
author
vakrilov
committed
refactor: Extract common http methods
1 parent 5e6264a commit 3efe386

File tree

5 files changed

+118
-123
lines changed

5 files changed

+118
-123
lines changed

Diff for: nativescript-angular/http-client/http-utils.ts

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { NSFileSystem } from "../file-system/ns-file-system";
2+
3+
import { Observable } from "rxjs/Observable";
4+
import { Observer } from "rxjs/Observer";
5+
import { path } from "tns-core-modules/file-system/file-system";
6+
7+
export type httpResponseFactory<T> = (url: string, body: any, status: number) => T;
8+
export type httpErrorFactory = (url: string, body: any, status: number) => any;
9+
10+
export function isLocalRequest(url: string): boolean {
11+
return url.indexOf("~") === 0 || url.indexOf("/") === 0;
12+
}
13+
14+
export function getAbsolutePath(url: string, nsFileSystem: NSFileSystem): string {
15+
url = url.replace("~", "").replace("/", "");
16+
url = path.join(nsFileSystem.currentApp().path, url);
17+
return url;
18+
}
19+
20+
export function handleLocalRequest<T>(
21+
url: string,
22+
nsFileSystem: NSFileSystem,
23+
successResponse: httpResponseFactory<T>,
24+
errorResponse: httpErrorFactory): Observable<T> {
25+
26+
url = getAbsolutePath(url, nsFileSystem);
27+
28+
// request from local app resources
29+
return new Observable((observer: Observer<T>) => {
30+
if (nsFileSystem.fileExists(url)) {
31+
const localFile = nsFileSystem.fileFromPath(url);
32+
localFile.readText()
33+
.then((data) => {
34+
try {
35+
const json = JSON.parse(data);
36+
observer.next(successResponse(url, json, 200));
37+
observer.complete();
38+
} catch (error) {
39+
// Even though the response status was 2xx, this is still an error.
40+
// The parse error contains the text of the body that failed to parse.
41+
const errorResult = { error, text: data };
42+
observer.error(errorResponse(url, errorResult, 200));
43+
}
44+
}, (err: Object) => {
45+
observer.error(errorResponse(url, err, 400));
46+
47+
});
48+
} else {
49+
observer.error(errorResponse(url, "Not Found", 404));
50+
}
51+
});
52+
}

Diff for: nativescript-angular/http-client/ns-http-backend.ts

+15-40
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ import {
55
HttpErrorResponse, HttpXhrBackend
66
} from "@angular/common/http";
77
import { Observable } from "rxjs/Observable";
8-
import { Observer } from "rxjs/Observer";
98

109
import { NSFileSystem } from "../file-system/ns-file-system";
11-
import { path } from "tns-core-modules/file-system";
10+
import { isLocalRequest, handleLocalRequest } from "./http-utils";
1211

1312
@Injectable()
1413
export class NsHttpBackEnd extends HttpXhrBackend {
@@ -28,47 +27,20 @@ export class NsHttpBackEnd extends HttpXhrBackend {
2827
return result;
2928
}
3029

31-
private getAbsolutePath(url: string): string {
32-
url = url.replace("~", "").replace("/", "");
33-
url = path.join(this.nsFileSystem.currentApp().path, url);
34-
return url;
35-
}
36-
3730
private handleLocalRequest(url: string): Observable<HttpEvent<any>> {
38-
url = this.getAbsolutePath(url);
39-
40-
// request from local app resources
41-
return new Observable((observer: Observer<HttpEvent<any>>) => {
42-
if (this.nsFileSystem.fileExists(url)) {
43-
const localFile = this.nsFileSystem.fileFromPath(url);
44-
localFile.readText()
45-
.then((data) => {
46-
try {
47-
const json = JSON.parse(data);
48-
observer.next(createSuccessResponse(url, json, 200));
49-
observer.complete();
50-
} catch (error) {
51-
// Even though the response status was 2xx, this is still an error.
52-
// The parse error contains the text of the body that failed to parse.
53-
const errorResult = { error, text: data };
54-
observer.error(createErrorResponse(url, errorResult, 200));
55-
}
56-
}, (err: Object) => {
57-
observer.error(createErrorResponse(url, err, 400));
58-
59-
});
60-
} else {
61-
observer.error(createErrorResponse(url, "Not Found", 404));
62-
}
63-
});
31+
return handleLocalRequest(
32+
url,
33+
this.nsFileSystem,
34+
createSuccessResponse,
35+
createErrorResponse
36+
);
6437
}
6538
}
6639

67-
function isLocalRequest(url: string): boolean {
68-
return url.indexOf("~") === 0 || url.indexOf("/") === 0;
69-
}
70-
71-
function createSuccessResponse(url: string, body: any, status: number): HttpEvent<any> {
40+
function createSuccessResponse(
41+
url: string,
42+
body: any,
43+
status: number): HttpEvent<any> {
7244
return new HttpResponse({
7345
url,
7446
body,
@@ -77,7 +49,10 @@ function createSuccessResponse(url: string, body: any, status: number): HttpEven
7749
});
7850
}
7951

80-
function createErrorResponse(url: string, body: any, status: number): HttpErrorResponse {
52+
function createErrorResponse(
53+
url: string,
54+
body: any,
55+
status: number): HttpErrorResponse {
8156
return new HttpErrorResponse({
8257
url,
8358
error: body,

Diff for: nativescript-angular/http/ns-http.ts

+13-32
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import {
1111
} from "@angular/http";
1212
import { Observable } from "rxjs/Observable";
1313
import "rxjs/add/observable/fromPromise";
14+
15+
import { isLocalRequest, handleLocalRequest } from "../http-client/http-utils";
16+
1417
import { NSFileSystem } from "../file-system/ns-file-system";
1518

1619
export class NSXSRFStrategy {
@@ -31,7 +34,7 @@ export class NSHttp extends Http {
3134
request(req: string | Request, options?: RequestOptionsArgs): Observable<Response> {
3235
const urlString = typeof req === "string" ? req : req.url;
3336
if (isLocalRequest(urlString)) {
34-
return this._requestLocalUrl(urlString);
37+
return this.handleLocalRequest(urlString);
3538
} else {
3639
return super.request(req, options);
3740
}
@@ -42,45 +45,23 @@ export class NSHttp extends Http {
4245
*/
4346
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
4447
if (isLocalRequest(url)) {
45-
return this._requestLocalUrl(url);
48+
return this.handleLocalRequest(url);
4649
} else {
4750
return super.get(url, options);
4851
}
4952
}
5053

51-
/**
52-
* Uses a local file if `~/` resource is requested.
53-
* @param url
54-
*/
55-
private _requestLocalUrl(url: string): Observable<Response> {
56-
url = normalizeLocalUrl(url);
57-
58-
// request from local app resources
59-
return Observable.fromPromise<Response>(new Promise((resolve, reject) => {
60-
let app = this.nsFileSystem.currentApp();
61-
let localFile = app.getFile(url);
62-
if (localFile) {
63-
localFile.readText().then((data) => {
64-
resolve(responseOptions(data, 200, url));
65-
}, (err: Object) => {
66-
reject(responseOptions(err, 400, url));
67-
});
68-
} else {
69-
reject(responseOptions("Not Found", 404, url));
70-
}
71-
}));
54+
private handleLocalRequest(url: string): Observable<Response> {
55+
return handleLocalRequest(
56+
url,
57+
this.nsFileSystem,
58+
createResponse,
59+
createResponse
60+
);
7261
}
7362
}
7463

75-
function isLocalRequest(url: string): boolean {
76-
return url.indexOf("~") === 0 || url.indexOf("/") === 0;
77-
}
78-
79-
function normalizeLocalUrl(url: string): string {
80-
return url.replace("~", "").replace("/", "");
81-
}
82-
83-
function responseOptions(body: string | Object, status: number, url: string): Response {
64+
function createResponse(url: string, body: string | Object, status: number): Response {
8465
return new Response(new ResponseOptions({
8566
body: body,
8667
status: status,

Diff for: tests/app/tests/http.ts

+38-15
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,39 @@
11
// make sure you import mocha-config before @angular/core
2-
import {assert} from "./test-config";
2+
import { assert } from "./test-config";
33
import {
44
async,
55
inject,
66
} from "@angular/core/testing";
7-
import {ReflectiveInjector} from "@angular/core";
8-
import {Request, BaseRequestOptions, ConnectionBackend, Http, Response, ResponseOptions} from "@angular/http";
7+
import { ReflectiveInjector, Injectable } from "@angular/core";
8+
import { Request, BaseRequestOptions, ConnectionBackend, Http, Response, ResponseOptions } from "@angular/http";
99
import "rxjs/add/operator/map";
10-
import {MockBackend} from "@angular/http/testing";
11-
import {NSHttp} from "nativescript-angular/http/ns-http";
12-
import {NSFileSystem} from "nativescript-angular/file-system/ns-file-system";
13-
import {NSFileSystemMock, FileResponses} from "./mocks/ns-file-system.mock";
10+
import { MockBackend } from "@angular/http/testing";
11+
import { NSHttp } from "nativescript-angular/http/ns-http";
12+
import { NSFileSystem } from "nativescript-angular/file-system/ns-file-system";
13+
14+
const AWESOME_TEAM: string = '[{"name":"Alex"}, {"name":"Rosen"}, {"name":"Panayot"}]';
15+
16+
// Filesystem mock
17+
@Injectable()
18+
export class NSFileSystemMock implements NSFileSystem {
19+
public currentApp(): any {
20+
return { path: "/app/dir" };
21+
}
22+
23+
public fileFromPath(path: string): any {
24+
if (path === "/app/dir/test.json") {
25+
return {
26+
readText: () => { return Promise.resolve(AWESOME_TEAM); }
27+
};
28+
}
29+
throw new Error("Opening non-existing file");
30+
}
31+
32+
public fileExists(path: string): boolean {
33+
return path === "/app/dir/test.json";
34+
}
35+
36+
}
1437

1538
describe("Http", () => {
1639
let http: Http;
@@ -22,15 +45,15 @@ describe("Http", () => {
2245
MockBackend,
2346
{ provide: NSFileSystem, useClass: NSFileSystemMock },
2447
{
25-
provide: Http,
26-
useFactory: function (
27-
connectionBackend: ConnectionBackend,
28-
defaultOptions: BaseRequestOptions,
29-
nsFileSystem: NSFileSystem) {
48+
provide: Http,
49+
useFactory: function (
50+
connectionBackend: ConnectionBackend,
51+
defaultOptions: BaseRequestOptions,
52+
nsFileSystem: NSFileSystem) {
3053
// HACK: cast backend to any to work around an angular typings problem
3154
return new NSHttp(<any>connectionBackend, defaultOptions, nsFileSystem);
32-
},
33-
deps: [MockBackend, BaseRequestOptions, NSFileSystem]
55+
},
56+
deps: [MockBackend, BaseRequestOptions, NSFileSystem]
3457
}
3558
]);
3659

@@ -78,6 +101,6 @@ describe("Http", () => {
78101
assert.strictEqual(3, response.length);
79102
assert.strictEqual("Rosen", response[1].name);
80103
});
81-
connection.mockRespond(new Response(new ResponseOptions({ body: FileResponses.AWESOME_TEAM })));
104+
connection.mockRespond(new Response(new ResponseOptions({ body: AWESOME_TEAM })));
82105
});
83106
});

Diff for: tests/app/tests/mocks/ns-file-system.mock.ts

-36
This file was deleted.

0 commit comments

Comments
 (0)