exiftool-vendored
Version:
Efficient, cross-platform access to ExifTool
135 lines • 5.68 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const AsyncRetry_1 = require("./AsyncRetry");
const _chai_spec_1 = require("./_chai.spec");
describe("AsyncRetry", () => {
it("returns simple passing thunk", async () => {
(0, _chai_spec_1.expect)(await (0, AsyncRetry_1.retryOnReject)(() => "hello", 0)).to.eql("hello");
});
it("rejects fail/pass thunk", async () => {
const results = [new Error("boom"), 123];
return (0, _chai_spec_1.expect)((0, AsyncRetry_1.retryOnReject)(() => {
const r = results.shift();
if (r != null && r instanceof Error)
throw r;
else
return r;
}, 0)).to.be.rejectedWith(/boom/);
});
it("accepts fail/pass thunk if retries > 0", async () => {
const results = [new Error("boom"), 123];
return (0, _chai_spec_1.expect)((0, AsyncRetry_1.retryOnReject)(() => {
const r = results.shift();
if (r != null && r instanceof Error)
throw r;
else
return r;
}, 1)).to.eventually.eql(123);
});
it("succeeds immediately with synchronous success", async () => {
const result = await (0, AsyncRetry_1.retryOnReject)(() => "success", 3);
(0, _chai_spec_1.expect)(result).to.eql("success");
});
it("succeeds immediately with asynchronous success", async () => {
const result = await (0, AsyncRetry_1.retryOnReject)(async () => Promise.resolve("async success"), 3);
(0, _chai_spec_1.expect)(result).to.eql("async success");
});
it("retries until success", async () => {
let attempts = 0;
const result = await (0, AsyncRetry_1.retryOnReject)(() => {
attempts++;
if (attempts < 3) {
throw new Error("temporary failure");
}
return "eventual success";
}, 3);
(0, _chai_spec_1.expect)(attempts).to.eql(3);
(0, _chai_spec_1.expect)(result).to.eql("eventual success");
});
it("fails after exhausting retries", async () => {
let attempts = 0;
const operation = (0, AsyncRetry_1.retryOnReject)(() => {
attempts++;
throw new Error("persistent failure");
}, 2);
await (0, _chai_spec_1.expect)(operation).to.be.rejectedWith("persistent failure");
(0, _chai_spec_1.expect)(attempts).to.eql(3); // Initial + 2 retries
});
it("preserves error types", async () => {
class CustomError extends Error {
constructor(message) {
super(message);
this.name = "CustomError";
}
}
const operation = (0, AsyncRetry_1.retryOnReject)(() => {
throw new CustomError("custom error");
}, 1);
try {
await operation;
_chai_spec_1.expect.fail("Should have thrown");
}
catch (error) {
(0, _chai_spec_1.expect)(error).to.be.instanceOf(CustomError);
(0, _chai_spec_1.expect)(error.message).to.eql("custom error");
}
});
it("handles async errors", async () => {
let attempts = 0;
const operation = (0, AsyncRetry_1.retryOnReject)(async () => {
attempts++;
return Promise.reject(new Error("async failure"));
}, 2);
await (0, _chai_spec_1.expect)(operation).to.be.rejectedWith("async failure");
(0, _chai_spec_1.expect)(attempts).to.eql(3);
});
it("works with zero retries", async () => {
let attempts = 0;
const operation = (0, AsyncRetry_1.retryOnReject)(() => {
attempts++;
throw new Error("fail");
}, 0);
await (0, _chai_spec_1.expect)(operation).to.be.rejectedWith("fail");
(0, _chai_spec_1.expect)(attempts).to.eql(1); // Only initial attempt
});
it("handles mixed sync/async successes", async () => {
let attempts = 0;
const result = await (0, AsyncRetry_1.retryOnReject)(async () => {
attempts++;
if (attempts === 1)
return "sync";
if (attempts === 2)
return Promise.resolve("async");
throw new Error("should not reach here");
}, 2);
(0, _chai_spec_1.expect)(attempts).to.eql(1);
(0, _chai_spec_1.expect)(result).to.eql("sync");
});
it("handles null/undefined returns", async () => {
const nullResult = await (0, AsyncRetry_1.retryOnReject)(() => null, 1);
(0, _chai_spec_1.expect)(nullResult).to.eql(null);
const undefinedResult = await (0, AsyncRetry_1.retryOnReject)(() => undefined, 1);
(0, _chai_spec_1.expect)(undefinedResult).to.eql(undefined);
});
it("retries with increasing durations", async () => {
const timestamps = [];
try {
await (0, AsyncRetry_1.retryOnReject)(() => {
timestamps.push(Date.now());
throw new Error("retry");
}, 2, 50);
}
catch {
(0, _chai_spec_1.expect)(timestamps).to.have.length(3);
const [t0, t1, t2] = timestamps;
// First retry delay should be ~50ms, second should be ~100ms
const delay1 = t1 - t0;
const delay2 = t2 - t1;
(0, _chai_spec_1.expect)(delay1).to.be.gte(45);
(0, _chai_spec_1.expect)(delay2).to.be.gte(90);
// Second delay should be roughly double the first
(0, _chai_spec_1.expect)(delay2).to.be.gte(delay1 * 1.5);
}
});
});
//# sourceMappingURL=AsyncRetry.spec.js.map