aboutsummaryrefslogtreecommitdiffstats
path: root/node_modules/exponential-backoff/src/backoff.spec.ts
diff options
context:
space:
mode:
authorpack <pack@packgekko.xyz>2026-08-09 10:37:07 +0000
committerpack <pack@packgekko.xyz>2026-08-09 10:37:07 +0000
commit55a4f1fc869e41aca748c63d3018f0448b1606e0 (patch)
treed132d1d01772b6d53faee3e63c534dea5706b78a /node_modules/exponential-backoff/src/backoff.spec.ts
downloadcrud-55a4f1fc869e41aca748c63d3018f0448b1606e0.tar.gz
first commit
Diffstat (limited to 'node_modules/exponential-backoff/src/backoff.spec.ts')
-rw-r--r--node_modules/exponential-backoff/src/backoff.spec.ts194
1 files changed, 194 insertions, 0 deletions
diff --git a/node_modules/exponential-backoff/src/backoff.spec.ts b/node_modules/exponential-backoff/src/backoff.spec.ts
new file mode 100644
index 0000000..24fd95b
--- /dev/null
+++ b/node_modules/exponential-backoff/src/backoff.spec.ts
@@ -0,0 +1,194 @@
+import { backOff } from "./backoff";
+import { BackoffOptions } from "./options";
+
+describe("BackOff", () => {
+ const mockSuccessResponse = { success: true };
+ const mockFailResponse = { success: false };
+ let backOffRequest: () => Promise<any>;
+ let backOffOptions: BackoffOptions;
+
+ function initBackOff() {
+ return backOff(backOffRequest, backOffOptions);
+ }
+
+ function promiseThatIsResolved() {
+ return () => Promise.resolve(mockSuccessResponse);
+ }
+
+ function promiseThatIsRejected() {
+ return () => Promise.reject(mockFailResponse);
+ }
+
+ function promiseThatFailsOnceThenSucceeds() {
+ return (() => {
+ let firstAttempt = true;
+
+ const request = () => {
+ if (firstAttempt) {
+ firstAttempt = false;
+ return Promise.reject(mockFailResponse);
+ }
+
+ return Promise.resolve(mockSuccessResponse);
+ };
+
+ return request;
+ })();
+ }
+
+ beforeEach(() => {
+ backOffOptions = { startingDelay: 0 };
+ backOffRequest = jest.fn(promiseThatIsResolved());
+ });
+
+ describe("when request function is a promise that resolves", () => {
+ it("returns the resolved value", () => {
+ const request = initBackOff();
+ return request.then(response =>
+ expect(response).toBe(mockSuccessResponse)
+ );
+ });
+
+ it("calls the request function only once", () => {
+ const request = initBackOff();
+ return request.then(() =>
+ expect(backOffRequest).toHaveBeenCalledTimes(1)
+ );
+ });
+
+ it(`when the #backOffOptions.numOfAttempts is 0,
+ it overrides the value and calls the method only once`, () => {
+ backOffOptions.numOfAttempts = 0;
+ const request = initBackOff();
+
+ return request.then(() =>
+ expect(backOffRequest).toHaveBeenCalledTimes(1)
+ );
+ });
+ });
+
+ describe(`when the #backOffOptions.startingDelay is 100ms`, () => {
+ const startingDelay = 100;
+
+ beforeEach(() => (backOffOptions.startingDelay = startingDelay));
+
+ it(`does not delay the first attempt`, () => {
+ const startTime = Date.now();
+ const request = initBackOff();
+
+ return request.then(() => {
+ const endTime = Date.now();
+ const duration = endTime - startTime;
+ const roundedDuration = Math.round(duration / 100) * 100;
+
+ expect(roundedDuration).toBe(0);
+ });
+ });
+
+ it(`when #backOffOptions.delayFirstAttempt is 'true',
+ it delays the first attempt`, () => {
+ backOffOptions.delayFirstAttempt = true;
+ const startTime = Date.now();
+ const request = initBackOff();
+
+ return request.then(() => {
+ const endTime = Date.now();
+ const duration = endTime - startTime;
+ const roundedDuration = Math.round(duration / 100) * 100;
+
+ expect(roundedDuration).toBe(startingDelay);
+ });
+ });
+ });
+
+ describe("when request function is a promise that is rejected", () => {
+ beforeEach(() => (backOffRequest = promiseThatIsRejected()));
+
+ it("returns the rejected value", () => {
+ const request = initBackOff();
+ return request.catch(err => expect(err).toBe(mockFailResponse));
+ });
+
+ it("retries the request as many times as specified in #BackOffOptions.numOfAttempts", async () => {
+ const numOfAttemps = 2;
+ backOffOptions.numOfAttempts = numOfAttemps;
+ backOffRequest = jest.fn(() => Promise.reject(mockFailResponse));
+
+ try {
+ await initBackOff();
+ } catch {
+ expect(backOffRequest).toHaveBeenCalledTimes(numOfAttemps);
+ }
+ });
+
+ it(`when the #BackOffOptions.retry function is set to always return false,
+ it only calls request function one time`, async () => {
+ backOffOptions.retry = () => false;
+ backOffOptions.numOfAttempts = 2;
+ backOffRequest = jest.fn(() => Promise.reject(mockFailResponse));
+
+ try {
+ await initBackOff();
+ } catch {
+ expect(backOffRequest).toHaveBeenCalledTimes(1);
+ }
+ });
+ });
+
+ it("when the #BackOffOptions.retry function returns a promise, it awaits it", async () => {
+ const retryDuration = 100;
+ backOffOptions.retry = () =>
+ new Promise(resolve => setTimeout(() => resolve(true), retryDuration));
+ backOffRequest = promiseThatFailsOnceThenSucceeds();
+
+ const start = Date.now();
+ await initBackOff();
+ const end = Date.now();
+
+ const duration = end - start;
+ const roundedDuration =
+ Math.round(duration / retryDuration) * retryDuration;
+
+ expect(roundedDuration).toBe(retryDuration);
+ });
+
+ describe(`when calling #backOff with a function that throws an error the first time, and succeeds the second time`, () => {
+ beforeEach(
+ () => (backOffRequest = jest.fn(promiseThatFailsOnceThenSucceeds()))
+ );
+
+ it(`returns a successful response`, () => {
+ const request = initBackOff();
+ return request.then(response =>
+ expect(response).toBe(mockSuccessResponse)
+ );
+ });
+
+ it("calls the request function two times", async () => {
+ await initBackOff();
+ expect(backOffRequest).toHaveBeenCalledTimes(2);
+ });
+
+ it(`when setting the #BackOffOption.timeMultiple to a value,
+ when setting the #BackOffOption.delayFirstAttempt to true,
+ it applies a delay between the first and the second call`, async () => {
+ const startingDelay = 100;
+ const timeMultiple = 3;
+ const totalExpectedDelay = startingDelay + timeMultiple * startingDelay;
+
+ backOffOptions.startingDelay = startingDelay;
+ backOffOptions.timeMultiple = timeMultiple;
+ backOffOptions.delayFirstAttempt = true;
+
+ const start = Date.now();
+ await initBackOff();
+ const end = Date.now();
+
+ const duration = end - start;
+ const roundedDuration =
+ Math.round(duration / startingDelay) * startingDelay;
+
+ expect(roundedDuration).toBe(totalExpectedDelay);
+ });
+ });
+});