Files
anomalyco_opencode/packages/opencode/test/project/state.test.ts
T
Kit Langton 395a9580bd refactor(state): replace ScopedState with InstanceState
Replace the generic ScopedState (keyed by caller-provided root) with
InstanceState that hardcodes Instance.directory and integrates with
the instance dispose/reload lifecycle via a global task registry.

- Parallelize State + InstanceState disposal in reload/dispose
- Use Effect's Record.map and Struct.pick in auth-service
- Flatten nested Effect.gen in OAuth callback flow
- Add docstrings to ProviderAuthService interface
- Add State and InstanceState tests
2026-03-12 16:33:50 -04:00

88 lines
1.6 KiB
TypeScript

import { expect, test } from "bun:test"
import { State } from "../../src/project/state"
test("State.create caches values for the same key", async () => {
let key = "a"
let n = 0
const state = State.create(
() => key,
() => ({ n: ++n }),
)
const a = state()
const b = state()
expect(a).toBe(b)
expect(n).toBe(1)
await State.dispose("a")
})
test("State.create isolates values by key", async () => {
let key = "a"
let n = 0
const state = State.create(
() => key,
() => ({ n: ++n }),
)
const a = state()
key = "b"
const b = state()
key = "a"
const c = state()
expect(a).toBe(c)
expect(a).not.toBe(b)
expect(n).toBe(2)
await State.dispose("a")
await State.dispose("b")
})
test("State.dispose clears a key and runs cleanup", async () => {
const seen: string[] = []
let key = "a"
let n = 0
const state = State.create(
() => key,
() => ({ n: ++n }),
async (value) => {
seen.push(String(value.n))
},
)
const a = state()
await State.dispose("a")
const b = state()
expect(a).not.toBe(b)
expect(seen).toEqual(["1"])
await State.dispose("a")
})
test("State.create dedupes concurrent promise initialization", async () => {
const gate = Promise.withResolvers<void>()
let n = 0
const state = State.create(
() => "a",
async () => {
n += 1
await gate.promise
return { n }
},
)
const task = Promise.all([state(), state()])
await Promise.resolve()
expect(n).toBe(1)
gate.resolve()
const [a, b] = await task
expect(a).toBe(b)
await State.dispose("a")
})