From 2b80560aa848e99262118b99e9037decd90ad17d Mon Sep 17 00:00:00 2001 From: Louis Christopher Date: Sat, 14 Nov 2020 18:44:55 +0530 Subject: [PATCH] feat: reset retry mechanism on failure with next loader --- src/index.test.ts | 48 +++++++++++++++++++++++++++++++++++++++++++++++ src/index.ts | 10 ++++++++++ 2 files changed, 58 insertions(+) diff --git a/src/index.test.ts b/src/index.test.ts index 77746077..b0c86254 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -139,7 +139,9 @@ test("script onerror should reject promise with multiple loaders", async () => { expect(loader["done"]).toBeTruthy(); expect(loader["loading"]).toBeFalsy(); expect(loader["onerrorEvent"]).toBeInstanceOf(ErrorEvent); + rejection = expect(extraLoader.load()).rejects.toBeInstanceOf(ErrorEvent); + loader["loadErrorCallback"](document.createEvent("ErrorEvent")); await rejection; expect(extraLoader["done"]).toBeTruthy(); @@ -165,6 +167,52 @@ test("script onerror should retry", async () => { expect(console.log).toHaveBeenCalledTimes(loader.retries); }); +test("script onerror should reset retry mechanism with next loader", async () => { + const loader = new Loader({ apiKey: "foo", retries: 1 }); + const deleteScript = jest.spyOn(loader, "deleteScript"); + // eslint-disable-next-line @typescript-eslint/no-empty-function + console.log = jest.fn(); + + let rejection = expect(loader.load()).rejects.toBeInstanceOf(ErrorEvent); + loader["loadErrorCallback"](document.createEvent("ErrorEvent")); + loader["loadErrorCallback"](document.createEvent("ErrorEvent")); + jest.runAllTimers(); + await rejection; + + rejection = expect(loader.load()).rejects.toBeInstanceOf(ErrorEvent); + expect(loader["done"]).toBeFalsy(); + expect(loader["loading"]).toBeTruthy(); + expect(loader["errors"].length).toBe(0); + + loader["loadErrorCallback"](document.createEvent("ErrorEvent")); + loader["loadErrorCallback"](document.createEvent("ErrorEvent")); + jest.runAllTimers(); + + await rejection; + expect(deleteScript).toHaveBeenCalledTimes(3); + expect(console.log).toHaveBeenCalledTimes(loader.retries * 2); +}); + +test("script onerror should not reset retry mechanism with parallel loaders", async () => { + const loader = new Loader({ apiKey: "foo", retries: 1 }); + const deleteScript = jest.spyOn(loader, "deleteScript"); + // eslint-disable-next-line @typescript-eslint/no-empty-function + console.log = jest.fn(); + + const rejection1 = expect(loader.load()).rejects.toBeInstanceOf(ErrorEvent); + const rejection2 = expect(loader.load()).rejects.toBeInstanceOf(ErrorEvent); + loader["loadErrorCallback"](document.createEvent("ErrorEvent")); + loader["loadErrorCallback"](document.createEvent("ErrorEvent")); + jest.runAllTimers(); + + await Promise.all([rejection1, rejection2]); + expect(loader["done"]).toBeTruthy(); + expect(loader["loading"]).toBeFalsy(); + expect(loader["errors"].length).toBe(2); + expect(deleteScript).toHaveBeenCalledTimes(1); + expect(console.log).toHaveBeenCalledTimes(loader.retries); +}); + test("singleton should be used", () => { const loader = new Loader({ apiKey: "foo" }); const extraLoader = new Loader({ apiKey: "foo" }); diff --git a/src/index.ts b/src/index.ts index 4dd06c8f..f8a4ed7b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -426,6 +426,15 @@ export class Loader { } } + private resetIfRetryingFailed(): void { + if (this.done && !this.loading && this.errors.length >= this.retries) { + this.deleteScript(); + this.done = false; + this.loading = false; + this.errors = []; + } + } + private loadErrorCallback(e: ErrorEvent): void { this.errors.push(e); @@ -470,6 +479,7 @@ export class Loader { this.callback(); } + this.resetIfRetryingFailed(); if (this.done) { this.callback(); } else {