0.2.5 #43
99
packages/effect-fc/src/Lens.test.ts
Normal file
99
packages/effect-fc/src/Lens.test.ts
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
import { describe, expect, test } from "bun:test"
|
||||||
|
import { Chunk, Effect, SubscriptionRef } from "effect"
|
||||||
|
import * as Lens from "./Lens.js"
|
||||||
|
|
||||||
|
|
||||||
|
describe("Lens", () => {
|
||||||
|
test("mapField focuses a nested property without touching other fields", async () => {
|
||||||
|
const [initialCount, updatedState] = await Effect.runPromise(
|
||||||
|
Effect.flatMap(
|
||||||
|
SubscriptionRef.make({ count: 1, label: "original" }),
|
||||||
|
parent => {
|
||||||
|
const countLens = Lens.mapField(Lens.fromSubscriptionRef(parent), "count")
|
||||||
|
return Effect.flatMap(
|
||||||
|
Lens.get(countLens),
|
||||||
|
count => Effect.flatMap(
|
||||||
|
Lens.set(countLens, count + 5),
|
||||||
|
() => Effect.map(parent.get, state => [count, state] as const),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(initialCount).toBe(1)
|
||||||
|
expect(updatedState).toEqual({ count: 6, label: "original" })
|
||||||
|
})
|
||||||
|
|
||||||
|
test("mapMutableField preserves the root identity when mutating in place", async () => {
|
||||||
|
const original = { detail: "keep" }
|
||||||
|
const updated = await Effect.runPromise(
|
||||||
|
Effect.flatMap(
|
||||||
|
SubscriptionRef.make(original),
|
||||||
|
parent => {
|
||||||
|
const detailLens = Lens.mapMutableField(Lens.fromSubscriptionRef(parent), "detail")
|
||||||
|
return Effect.flatMap(
|
||||||
|
Lens.set(detailLens, "mutated"),
|
||||||
|
() => parent.get,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(updated).toBe(original)
|
||||||
|
expect(updated.detail).toBe("mutated")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("mapArrayAt updates the selected index", async () => {
|
||||||
|
const updated = await Effect.runPromise(
|
||||||
|
Effect.flatMap(
|
||||||
|
SubscriptionRef.make([10, 20, 30]),
|
||||||
|
parent => {
|
||||||
|
const elementLens = Lens.mapArrayAt(Lens.fromSubscriptionRef(parent), 1)
|
||||||
|
return Effect.flatMap(
|
||||||
|
Lens.update(elementLens, value => value + 5),
|
||||||
|
() => parent.get,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(updated).toEqual([10, 25, 30])
|
||||||
|
})
|
||||||
|
|
||||||
|
test("mapMutableArrayAt mutates the array reference in place", async () => {
|
||||||
|
const original = ["foo", "bar"]
|
||||||
|
const updated = await Effect.runPromise(
|
||||||
|
Effect.flatMap(
|
||||||
|
SubscriptionRef.make(original),
|
||||||
|
parent => {
|
||||||
|
const elementLens = Lens.mapMutableArrayAt(Lens.fromSubscriptionRef(parent), 0)
|
||||||
|
return Effect.flatMap(
|
||||||
|
Lens.set(elementLens, "baz"),
|
||||||
|
() => parent.get,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(updated).toBe(original)
|
||||||
|
expect(updated).toEqual(["baz", "bar"])
|
||||||
|
})
|
||||||
|
|
||||||
|
test("mapChunkAt replaces the focused chunk element", async () => {
|
||||||
|
const updated = await Effect.runPromise(
|
||||||
|
Effect.flatMap(
|
||||||
|
SubscriptionRef.make(Chunk.make(1, 2, 3) as Chunk.Chunk<number>),
|
||||||
|
parent => {
|
||||||
|
const elementLens = Lens.mapChunkAt(Lens.fromSubscriptionRef(parent), 2)
|
||||||
|
return Effect.flatMap(
|
||||||
|
Lens.set(elementLens, 99),
|
||||||
|
() => parent.get,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(Chunk.toReadonlyArray(updated)).toEqual([1, 2, 99])
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user