Skip to content

Instantly share code, notes, and snippets.

@vincaslt
Created July 15, 2022 07:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vincaslt/f47787ebc91f1bf78f432b64efbb9831 to your computer and use it in GitHub Desktop.
Save vincaslt/f47787ebc91f1bf78f432b64efbb9831 to your computer and use it in GitHub Desktop.
Test for the custom Promise implementation for codefrontend.com article
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