Created
July 15, 2022 07:02
-
-
Save vincaslt/f47787ebc91f1bf78f432b64efbb9831 to your computer and use it in GitHub Desktop.
Test for the custom Promise implementation for codefrontend.com article
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Futurable from "./Futurable"; | |
describe("Futurable <constructor>", () => { | |
it("returns a promise-like object, that resolves it's chain after invoking <resolve>", (done) => { | |
new Futurable<string>((resolve) => { | |
setTimeout(() => { | |
resolve("testing"); | |
}, 20); | |
}).then((val) => { | |
expect(val).toBe("testing"); | |
done(); | |
}); | |
}); | |
it("is always asynchronous", () => { | |
let value = "no"; | |
new Futurable<string>((resolve) => { | |
value = "yes;"; | |
resolve(value); | |
}); | |
expect(value).toBe("no"); | |
}); | |
it("resolves with the returned value", (done) => { | |
new Futurable<string>((resolve) => resolve("testing")).then((val) => { | |
expect(val).toBe("testing"); | |
done(); | |
}); | |
}); | |
it("resolves a Futurable before calling <then>", (done) => { | |
new Futurable<string>((resolve) => | |
resolve(new Futurable((resolve) => resolve("testing"))) | |
).then((val) => { | |
expect(val).toBe("testing"); | |
done(); | |
}); | |
}); | |
it("resolves a Futurable before calling <catch>", (done) => { | |
new Futurable<string>((resolve) => | |
resolve(new Futurable((_, reject) => reject("fail"))) | |
).catch((reason) => { | |
expect(reason).toBe("fail"); | |
done(); | |
}); | |
}); | |
it("catches errors from <reject>", (done) => { | |
const error = new Error("Why u fail?"); | |
new Futurable((_, reject) => { | |
return reject(error); | |
}).catch((err: Error) => { | |
expect(err).toBe(error); | |
done(); | |
}); | |
}); | |
it("catches errors from <throw>", (done) => { | |
const error = new Error("Why u fail?"); | |
new Futurable(() => { | |
throw error; | |
}).catch((err) => { | |
expect(err).toBe(error); | |
done(); | |
}); | |
}); | |
it("does not change state anymore after promise is fulfilled", (done) => { | |
new Futurable((resolve, reject) => { | |
resolve("success"); | |
reject("fail"); | |
}) | |
.catch(() => { | |
done.fail(new Error("Should not be called")); | |
}) | |
.then((value) => { | |
expect(value).toBe("success"); | |
done(); | |
}); | |
}); | |
it("does not change state anymore after promise is rejected", (done) => { | |
new Futurable((resolve, reject) => { | |
reject("fail"); | |
resolve("success"); | |
}) | |
.then(() => { | |
done.fail(new Error("Should not be called")); | |
}) | |
.catch((err) => { | |
expect(err).toBe("fail"); | |
done(); | |
}); | |
}); | |
}); | |
describe("Futurable chaining", () => { | |
it("resolves chained <then>", (done) => { | |
new Futurable<number>((resolve) => { | |
resolve(0); | |
}) | |
.then((value) => value + 1) | |
.then((value) => value + 1) | |
.then((value) => value + 1) | |
.then((value) => { | |
expect(value).toBe(3); | |
done(); | |
}); | |
}); | |
it("resolves <then> chain after <catch>", (done) => { | |
new Futurable<number>(() => { | |
throw new Error("Why u fail?"); | |
}) | |
.catch(() => { | |
return "testing"; | |
}) | |
.then((value) => { | |
expect(value).toBe("testing"); | |
done(); | |
}); | |
}); | |
it("catches errors thrown in <then>", (done) => { | |
const error = new Error("Why u fail?"); | |
new Futurable((resolve) => { | |
resolve(); | |
}) | |
.then(() => { | |
throw error; | |
}) | |
.catch((err) => { | |
expect(err).toBe(error); | |
done(); | |
}); | |
}); | |
it("catches errors thrown in <catch>", (done) => { | |
const error = new Error("Final error"); | |
new Futurable((_, reject) => { | |
reject(new Error("Initial error")); | |
}) | |
.catch(() => { | |
throw error; | |
}) | |
.catch((err) => { | |
expect(err).toBe(error); | |
done(); | |
}); | |
}); | |
it("short-circuits <then> chain on error", (done) => { | |
const error = new Error("Why u fail?"); | |
new Futurable(() => { | |
throw error; | |
}) | |
.then(() => { | |
done.fail(new Error("Should not be called")); | |
}) | |
.catch((err) => { | |
expect(err).toBe(error); | |
done(); | |
}); | |
}); | |
it("passes value through undefined <then>", (done) => { | |
new Futurable((resolve) => { | |
resolve("testing"); | |
}) | |
.then() | |
.then((value) => { | |
expect(value).toBe("testing"); | |
done(); | |
}); | |
}); | |
it("passes value through undefined <catch>", (done) => { | |
const error = new Error("Why u fail?"); | |
new Futurable((_, reject) => { | |
reject(error); | |
}) | |
.catch() | |
.catch((err) => { | |
expect(err).toBe(error); | |
done(); | |
}); | |
}); | |
}); | |
describe("Futurable <finally>", () => { | |
it("it is called when Futurable is resolved", (done) => { | |
new Futurable((resolve) => resolve("success")).finally(() => { | |
done(); | |
}); | |
}); | |
it("it is called when Futurable is rejected", (done) => { | |
new Futurable((_, reject) => reject("fail")).finally(() => { | |
done(); | |
}); | |
}); | |
it("it preserves a resolved promise state", (done) => { | |
let finallyCalledTimes = 0; | |
new Futurable((resolve) => resolve("success")) | |
.finally(() => { | |
finallyCalledTimes += 1; | |
}) | |
.then((value) => { | |
expect(value).toBe("success"); | |
expect(finallyCalledTimes).toBe(1); | |
done(); | |
}); | |
}); | |
it("it preserves a rejected promise state", (done) => { | |
let finallyCalledTimes = 0; | |
new Futurable((_, reject) => reject("fail")) | |
.finally(() => { | |
finallyCalledTimes += 1; | |
}) | |
.catch((reason) => { | |
expect(reason).toBe("fail"); | |
expect(finallyCalledTimes).toBe(1); | |
done(); | |
}); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment