Skip to content

Commit

Permalink
test: improve tests
Browse files Browse the repository at this point in the history
  • Loading branch information
susisu committed Sep 21, 2024
1 parent e9d1478 commit 17911ee
Showing 1 changed file with 71 additions and 51 deletions.
122 changes: 71 additions & 51 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,83 @@ declare module "." {
}
}

describe("perform, run", () => {
function identity<T>(value: T): Effectful<"index.test/identity", T> {
return perform({
id: "index.test/identity",
data: value,
});
}

function call<T>(func: () => T): Effectful<"index.test/call", T> {
return perform({
id: "index.test/call",
data: func,
});
}

describe("map", () => {
it("maps the return value of a computation", () => {
const comp = pure<never, number>(42);
const func = (x: number): string => x.toString();
const res = run(map(comp, func), (x) => x, {});
expect(res).toBe("42");
});
});

describe("pure", () => {
it("creates a computation that returns the given value without performing any effect", () => {
const comp = pure<never, number>(42);
const res = run(comp, (x) => x, {});
expect(res).toBe(42);
});
});

describe("bind", () => {
it("composes two computations sequentially", () => {
const comp = pure<never, number>(42);
const func = (x: number): Effectful<never, string> => pure(x.toString());
const res = run(bind(comp, func), (x) => x, {});
expect(res).toBe("42");
});
});

describe("run", () => {
function* main(): Effectful<"index.test/identity", number> {
const x = yield* perform<"index.test/identity", number>({
id: "index.test/identity",
data: 42,
});
const x = yield* identity(42);
return x;
}

it("runs an effectful computation", () => {
const res = run(main(), (x) => x, {
"index.test/identity": (eff, resume) => resume(eff.data),
"index.test/identity"(eff, resume) {
return resume(eff.data);
},
});
expect(res).toBe(42);
});

it("allows the return handler to modify the return value of the computation", () => {
const res = run(main(), (x) => x.toString(), {
"index.test/identity": (eff, resume) => resume(eff.data),
"index.test/identity"(eff, resume) {
return resume(eff.data);
},
});
expect(res).toBe("42");
});

it("allows the effect handlers to abort the computation", () => {
const res = run(main(), (x) => x, {
"index.test/identity": () => 666,
"index.test/identity"(_eff, _resume) {
return 666;
},
});
expect(res).toBe(666);
});

it("throws if resume is called more than once", () => {
expect(() => {
run(main(), (x) => x, {
"index.test/identity": (eff, resume) => {
"index.test/identity"(eff, resume) {
resume(eff.data);
return resume(eff.data);
},
Expand All @@ -51,65 +94,42 @@ describe("perform, run", () => {
});
});

describe("map", () => {
it("maps the return value of a computation", () => {
const comp = pure<never, number>(42);
const func = (x: number): string => x.toString();
const res = run(map(comp, func), (x) => x, {});
expect(res).toBe("42");
});
});

describe("pure", () => {
it("creates a computation that returns the given value without performing any effect", () => {
const comp = pure<never, number>(42);
const res = run(comp, (x) => x, {});
expect(res).toBe(42);
});
});

describe("bind", () => {
it("composes two computations sequentially", () => {
const comp = pure<never, number>(42);
const func = (x: number): Effectful<never, string> => pure(x.toString());
const res = run(bind(comp, func), (x) => x, {});
expect(res).toBe("42");
});
});

describe("interpose", () => {
function* main(): Effectful<"index.test/identity" | "index.test/call", number> {
const x = yield* perform<"index.test/call", number>({
id: "index.test/call",
data: () => 42,
});
const y = yield* perform<"index.test/identity", number>({
id: "index.test/identity",
data: 2,
});
return x * y;
const x = yield* identity(1);
const y = yield* call(() => 2);
const z = yield* identity(4);
const w = yield* call(() => 8);
return x + y + z + w;
}

it("re-interprets a subset of effects", () => {
const comp = interpose(main(), {
"index.test/call": (eff, resume) => resume(eff.data()),
*"index.test/call"(eff, resume) {
const v = yield* identity(eff.data());
return yield* resume(v);
},
});
const res = run(comp, (x) => x, {
"index.test/identity": (eff, resume) => resume(eff.data),
"index.test/identity"(eff, resume) {
return resume(eff.data);
},
});
expect(res).toBe(84);
expect(res).toBe(15);
});

it("throws if resume is called more than once", () => {
const comp = interpose(main(), {
"index.test/call": (eff, resume) => {
resume(eff.data());
return resume(eff.data());
*"index.test/call"(eff, resume) {
yield* resume(eff.data());
return yield* resume(eff.data());
},
});
expect(() => {
run(comp, (x) => x, {
"index.test/identity": (eff, resume) => resume(eff.data),
"index.test/identity"(eff, resume) {
return resume(eff.data);
},
});
}).toThrow("resume cannot be called more than once");
});
Expand Down

0 comments on commit 17911ee

Please sign in to comment.