Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Commit 25c6a21

Browse files
authoredMar 9, 2018
fix: simulated HTTP errors now delayed as expected (#182)
closes #180 also fixes type error (#180)
1 parent f673b1c commit 25c6a21

17 files changed

+8153
-21
lines changed
 

‎CHANGELOG.md

+14-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,20 @@ because this is a development tool, not a production product.
88
We do try to tell you about such changes in this `CHANGELOG.md`
99
and we fix bugs as fast as we can.
1010

11-
<a id="0.5.2"></a>
11+
<a id="0.5.4"></a>
12+
## 0.5.4 (2018-03-09)
13+
14+
Simulated HTTP error responses were not delaying the prescribed time when using RxJS `delay()`
15+
because it was short-circuited by the ErrorResponse.
16+
New `delayResponse` function does it right.
17+
Should not break you unless you incorrectly expected no delay for errors.
18+
19+
Also, this library no longer calls RxJS `delay()` which may make testing with it easier
20+
(Angular TestBed does not handle RxJS `delay()` well because that operator uses `interval()`).
21+
22+
Also fixes type error (issue #180).
23+
24+
<a id="0.5.3"></a>
1225
## 0.5.3 (2018-01-06)
1326
Can make use of `HttpParams` which yields a `request.urlWithParams`.
1427
Added supporting `HeroService.searchHeroes(term: string)` and test.

‎backend.service.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎backend.service.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎bundles/in-memory-web-api.umd.js

+32-6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎delay-response.d.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { Observable } from 'rxjs/Observable';
2+
/** adds specified delay (in ms) to both next and error channels of the response observable */
3+
export declare function delayResponse<T>(response$: Observable<T>, delayMs: number): Observable<T>;

‎delay-response.js

+27
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎delay-response.js.map

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎delay-response.metadata.json

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{"__symbolic":"module","version":3,"metadata":{"delayResponse":{"__symbolic":"function","parameters":["response$","delayMs"],"value":{"__symbolic":"error","message":"Function call not supported","line":5,"character":27}}}},{"__symbolic":"module","version":1,"metadata":{"delayResponse":{"__symbolic":"function","parameters":["response$","delayMs"],"value":{"__symbolic":"error","message":"Function call not supported","line":5,"character":27}}}}]

‎http-client-backend.service.d.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { HttpBackend, HttpHeaders, HttpRequest, HttpResponse, HttpXhrBackend, XhrFactory } from '@angular/common/http';
1+
import { HttpBackend, HttpEvent, HttpHeaders, HttpRequest, HttpResponse, HttpXhrBackend, XhrFactory } from '@angular/common/http';
22
import { Observable } from 'rxjs/Observable';
33
import { InMemoryBackendConfigArgs, InMemoryDbService, ResponseOptions } from './interfaces';
44
import { BackendService } from './backend.service';
@@ -32,7 +32,7 @@ import { BackendService } from './backend.service';
3232
export declare class HttpClientBackendService extends BackendService implements HttpBackend {
3333
private xhrFactory;
3434
constructor(inMemDbService: InMemoryDbService, config: InMemoryBackendConfigArgs, xhrFactory: XhrFactory);
35-
handle(req: HttpRequest<any>): Observable<HttpResponse<any>>;
35+
handle(req: HttpRequest<any>): Observable<HttpEvent<any>>;
3636
protected getJsonBody(req: HttpRequest<any>): any;
3737
protected getRequestMethod(req: HttpRequest<any>): string;
3838
protected createHeaders(headers: {

‎http-client-backend.service.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package-lock.json

+7,989
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "angular-in-memory-web-api",
3-
"version": "0.5.3",
3+
"version": "0.5.4",
44
"description": "An in-memory web api for Angular demos and tests",
55
"main": "bundles/in-memory-web-api.umd.js",
66
"module": "index.js",

‎src/in-mem/backend.service.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ import { fromPromise } from 'rxjs/observable/fromPromise';
77
import { isPromise } from 'rxjs/util/isPromise';
88

99
import { concatMap } from 'rxjs/operator/concatMap';
10-
import { delay } from 'rxjs/operator/delay';
1110
import { first } from 'rxjs/operator/first';
1211

1312
import { getStatusText, isSuccess, STATUS } from './http-status-codes';
13+
import { delayResponse } from './delay-response';
1414

1515
import {
1616
HeadersCore,
@@ -160,7 +160,7 @@ export abstract class BackendService {
160160
*/
161161
protected addDelay(response: Observable<any>): Observable<any> {
162162
const d = this.config.delay;
163-
return d === 0 ? response : delay.call(response, d || 500);
163+
return d === 0 ? response : delayResponse(response, d || 500);
164164
}
165165

166166
/**

‎src/in-mem/delay-response.ts

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Observable } from 'rxjs/Observable';
2+
3+
// Replaces use of RxJS delay. See v0.5.4.
4+
/** adds specified delay (in ms) to both next and error channels of the response observable */
5+
export function delayResponse<T>(response$: Observable<T>, delayMs: number): Observable<T> {
6+
return new Observable<T>(observer => {
7+
let completePending = false;
8+
let nextPending = false;
9+
const subscription = response$.subscribe(
10+
value => {
11+
nextPending = true;
12+
setTimeout(() => {
13+
observer.next(value);
14+
if (completePending) {
15+
observer.complete();
16+
}
17+
}, delayMs);
18+
},
19+
error => setTimeout(() => observer.error(error), delayMs),
20+
() => {
21+
completePending = true;
22+
if (!nextPending) {
23+
observer.complete();
24+
}
25+
}
26+
);
27+
return () => {
28+
return subscription.unsubscribe();
29+
};
30+
});
31+
}

‎src/in-mem/http-backend.service.spec.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,23 @@ describe('Http Backend Service', () => {
7373
);
7474
}));
7575

76+
it('GET should wait until after delay to respond', async(() => {
77+
// to make test fail, set `delay=0` above
78+
let gotResponse = false;
79+
80+
http.get('api/heroes')
81+
.map(res => res.json() as Hero[])
82+
.subscribe(
83+
heroes => {
84+
gotResponse = true;
85+
expect(heroes.length).toBeGreaterThan(0, 'should have heroes');
86+
},
87+
failure
88+
);
89+
90+
expect(gotResponse).toBe(false, 'should delay before response');
91+
}));
92+
7693
it('can get heroes (w/ a different base path)', async(() => {
7794
http.get('some-base-path/heroes')
7895
.map(res => res.json() as Hero[])
@@ -85,7 +102,8 @@ describe('Http Backend Service', () => {
85102
);
86103
}));
87104

88-
it('should 404 when GET unknown collection', async(() => {
105+
it('should 404 when GET unknown collection (after delay)', async(() => {
106+
let gotError = false;
89107
const url = 'api/unknown-collection';
90108
http.get(url)
91109
.subscribe(
@@ -94,9 +112,12 @@ describe('Http Backend Service', () => {
94112
fail(`should not have found data for '${url}'`);
95113
},
96114
err => {
115+
gotError = true;
97116
expect(err.status).toBe(404, 'should have 404 status');
98117
}
99118
);
119+
120+
expect(gotError).toBe(false, 'should not get error until after delay');
100121
}));
101122

102123
it('should return the hero w/id=1 for GET app/heroes/1', async(() => {

‎src/in-mem/http-client-backend.service.spec.ts

+22-3
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,21 @@ describe('HttpClient Backend Service', () => {
106106
);
107107
}));
108108

109+
it('GET should wait until after delay to respond', async(() => {
110+
// to make test fail, set `delay=0` above
111+
let gotResponse = false;
112+
113+
http.get<Hero[]>('api/heroes').subscribe(
114+
heroes => {
115+
gotResponse = true;
116+
expect(heroes.length).toBeGreaterThan(0, 'should have heroes');
117+
},
118+
failure
119+
);
120+
121+
expect(gotResponse).toBe(false, 'should delay before response');
122+
}));
123+
109124
it('Should only initialize the db once', async(() => {
110125
const httpBackend = TestBed.get(HttpBackend);
111126

@@ -134,18 +149,21 @@ describe('HttpClient Backend Service', () => {
134149
);
135150
}));
136151

137-
it('should 404 when GET unknown collection', async(() => {
152+
it('should 404 when GET unknown collection (after delay)', async(() => {
153+
let gotError = false;
138154
const url = 'api/unknown-collection';
139-
http.get<Hero[]>(url)
140-
.subscribe(
155+
http.get<Hero[]>(url).subscribe(
141156
_ => {
142157
console.log(_);
143158
fail(`should not have found data for '${url}'`);
144159
},
145160
err => {
161+
gotError = true;
146162
expect(err.status).toBe(404, 'should have 404 status');
147163
}
148164
);
165+
166+
expect(gotError).toBe(false, 'should not get error until after delay');
149167
}));
150168

151169
it('should return the hero w/id=1 for GET app/heroes/1', async(() => {
@@ -364,6 +382,7 @@ describe('HttpClient Backend Service', () => {
364382
}
365383
);
366384
}));
385+
367386
it('should 404 when GET unknown collection', async(() => {
368387
const url = 'api/unknown-collection';
369388
http.get<Hero[]>(url)

‎src/in-mem/http-client-backend.service.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Inject, Injectable, Optional } from '@angular/core';
22
import {
33
HttpBackend,
4+
HttpEvent,
45
HttpHeaders,
56
HttpParams,
67
HttpRequest,
@@ -61,7 +62,7 @@ export class HttpClientBackendService extends BackendService implements HttpBack
6162
super(inMemDbService, config);
6263
}
6364

64-
handle(req: HttpRequest<any>): Observable<HttpResponse<any>> {
65+
handle(req: HttpRequest<any>): Observable<HttpEvent<any>> {
6566
try {
6667
return this.handleRequest(req);
6768

0 commit comments

Comments
 (0)
This repository has been archived.