| /******************************************************************************** |
| * Copyright (c) 2020 Contributors to the Eclipse Foundation |
| * |
| * See the NOTICE file(s) distributed with this work for additional |
| * information regarding copyright ownership. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0 |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| ********************************************************************************/ |
| |
| import {fakeAsync, tick} from "@angular/core/testing"; |
| import {concat, of, throwError, timer} from "rxjs"; |
| import {map, toArray} from "rxjs/operators"; |
| import {emitOnComplete, endWithObservable, ignoreError, retryAfter} from "./rxjs.util"; |
| |
| describe("retryAfter", () => { |
| |
| const timeInMs = 100; |
| |
| it("should not have effects when no error is thrown", fakeAsync(() => { |
| const random = Math.random(); |
| const success$ = of(random); |
| |
| let gotResult = false; |
| let hasFinished = false; |
| |
| const subscription = success$.pipe( |
| retryAfter(timeInMs) |
| ).subscribe({ |
| next: (result) => gotResult = result === random, |
| complete: () => hasFinished = true |
| }); |
| |
| tick(); |
| |
| expect(gotResult).toBeTrue(); |
| expect(hasFinished).toBeTrue(); |
| |
| subscription.unsubscribe(); |
| })); |
| |
| it("should only retry after a specific time", fakeAsync(() => { |
| const error = new Error("" + Math.random()); |
| |
| let counter = 0; |
| |
| const throw$ = of(0).pipe( |
| map(() => { |
| counter++; |
| throw error; |
| }), |
| retryAfter(timeInMs) |
| ); |
| |
| const subscription = throw$.subscribe(); |
| |
| expect(counter).toBe(1); |
| |
| for (let i = 0; i < 100; i++) { |
| tick(timeInMs - 1); |
| expect(counter).toBe(i + 1); |
| tick(1); |
| expect(counter).toBe(i + 2); |
| } |
| |
| subscription.unsubscribe(); |
| })); |
| |
| it("should only retry a specific amount of times if specified", fakeAsync(() => { |
| const retryCount = 3; |
| |
| let lastError: any; |
| let counter = 0; |
| let hasFinished = false; |
| let hasError = false; |
| |
| const throw$ = of(0).pipe( |
| map(() => { |
| counter++; |
| lastError = new Error("" + Math.random()); |
| throw lastError; |
| }), |
| retryAfter(timeInMs, 2) |
| ); |
| |
| const subscription = throw$.subscribe({ |
| error: (err) => hasError = lastError === err, |
| complete: () => hasFinished = true |
| }); |
| |
| tick(retryCount * timeInMs - 1); |
| |
| expect(hasFinished).toBeFalse(); |
| expect(hasError).toBeFalse(); |
| |
| tick(1); |
| |
| expect(hasFinished).toBeFalse(); |
| expect(hasError).toBeTrue(); |
| expect(counter - 1).toBe(retryCount); |
| |
| subscription.unsubscribe(); |
| })); |
| |
| }); |
| |
| describe("ignoreError", () => { |
| |
| it("should complete an throwing observable", async () => { |
| const observable = throwError(new Error("Test Error")).pipe(ignoreError()); |
| const result = await observable.toPromise().catch(() => false); |
| expect(result).not.toBeDefined(); |
| }); |
| |
| }); |
| |
| describe("endWithObservable", () => { |
| |
| it("should end an observable with another observable", async () => { |
| const observable$ = of(0).pipe( |
| endWithObservable(() => of(1)), |
| toArray() |
| ); |
| const result = await observable$.toPromise(); |
| expect(result).toEqual([0, 1]); |
| }); |
| |
| }); |
| |
| describe("emitOnComplete", () => { |
| |
| it("should emit all values on completion", fakeAsync(() => { |
| const observable$ = concat( |
| of("start"), |
| timer(1000) |
| ).pipe(emitOnComplete()); |
| |
| const result: any[] = []; |
| const subscription = observable$.subscribe((_) => result.push(_)); |
| |
| tick(999); |
| expect(subscription.closed).toBeFalse(); |
| expect(result).toEqual([]); |
| tick(1); |
| expect(subscription.closed).toBeTrue(); |
| expect(result).toEqual(["start", 0]); |
| })); |
| |
| }); |