| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- import { afterEach, describe, expect, test } from "bun:test"
- import { Effect } from "effect"
- import { runtime, runPromiseInstance } from "../../src/effect/runtime"
- import { Auth } from "../../src/auth/effect"
- import { Instances } from "../../src/effect/instances"
- import { Instance } from "../../src/project/instance"
- import { ProviderAuth } from "../../src/provider/auth"
- import { Vcs } from "../../src/project/vcs"
- import { Question } from "../../src/question"
- import { tmpdir } from "../fixture/fixture"
- /**
- * Integration tests for the Effect runtime and LayerMap-based instance system.
- *
- * Each instance service layer has `.pipe(Layer.fresh)` at its definition site
- * so it is always rebuilt per directory, while shared dependencies are provided
- * outside the fresh boundary and remain memoizable.
- *
- * These tests verify the invariants using object identity (===) on the real
- * production services — not mock services or return-value checks.
- */
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const grabInstance = (service: any) => runPromiseInstance(service.use(Effect.succeed))
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const grabGlobal = (service: any) => runtime.runPromise(service.use(Effect.succeed))
- describe("effect/runtime", () => {
- afterEach(async () => {
- await Instance.disposeAll()
- })
- test("global services are shared across directories", async () => {
- await using one = await tmpdir({ git: true })
- await using two = await tmpdir({ git: true })
- // Auth is a global service — it should be the exact same object
- // regardless of which directory we're in.
- const authOne = await Instance.provide({
- directory: one.path,
- fn: () => grabGlobal(Auth.Service),
- })
- const authTwo = await Instance.provide({
- directory: two.path,
- fn: () => grabGlobal(Auth.Service),
- })
- expect(authOne).toBe(authTwo)
- })
- test("instance services with global deps share the global (ProviderAuth → Auth)", async () => {
- await using one = await tmpdir({ git: true })
- await using two = await tmpdir({ git: true })
- // ProviderAuth depends on Auth via defaultLayer.
- // The instance service itself should be different per directory,
- // but the underlying Auth should be shared.
- const paOne = await Instance.provide({
- directory: one.path,
- fn: () => grabInstance(ProviderAuth.Service),
- })
- const paTwo = await Instance.provide({
- directory: two.path,
- fn: () => grabInstance(ProviderAuth.Service),
- })
- // Different directories → different ProviderAuth instances.
- expect(paOne).not.toBe(paTwo)
- // But the global Auth is the same object in both.
- const authOne = await Instance.provide({
- directory: one.path,
- fn: () => grabGlobal(Auth.Service),
- })
- const authTwo = await Instance.provide({
- directory: two.path,
- fn: () => grabGlobal(Auth.Service),
- })
- expect(authOne).toBe(authTwo)
- })
- test("instance services are shared within the same directory", async () => {
- await using tmp = await tmpdir({ git: true })
- await Instance.provide({
- directory: tmp.path,
- fn: async () => {
- expect(await grabInstance(Vcs.Service)).toBe(await grabInstance(Vcs.Service))
- expect(await grabInstance(Question.Service)).toBe(await grabInstance(Question.Service))
- },
- })
- })
- test("different directories get different service instances", async () => {
- await using one = await tmpdir({ git: true })
- await using two = await tmpdir({ git: true })
- const vcsOne = await Instance.provide({
- directory: one.path,
- fn: () => grabInstance(Vcs.Service),
- })
- const vcsTwo = await Instance.provide({
- directory: two.path,
- fn: () => grabInstance(Vcs.Service),
- })
- expect(vcsOne).not.toBe(vcsTwo)
- })
- test("disposal rebuilds services with a new instance", async () => {
- await using tmp = await tmpdir({ git: true })
- await Instance.provide({
- directory: tmp.path,
- fn: async () => {
- const before = await grabInstance(Question.Service)
- await runtime.runPromise(Instances.use((map) => map.invalidate(Instance.directory)))
- const after = await grabInstance(Question.Service)
- expect(after).not.toBe(before)
- },
- })
- })
- })
|