test(opencode): simplify share layer wiring (#31811)

This commit is contained in:
James Long 2026-06-10 22:19:06 -04:00 committed by GitHub
parent 51891d56e7
commit 20bf18ffb4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,15 +1,14 @@
import { NodeFileSystem } from "@effect/platform-node"
import { beforeEach, describe, expect } from "bun:test"
import { Effect, Exit, Layer, Option } from "effect"
import { HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http"
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
import { httpClient } from "@opencode-ai/core/effect/layer-node-platform"
import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
import { SessionProjector } from "@opencode-ai/core/session/projector"
import { AccessToken, AccountID, OrgID, RefreshToken } from "../../src/account/schema"
import { Account } from "../../src/account/account"
import { AccountRepo } from "../../src/account/repo"
import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
import { EventV2Bridge } from "../../src/event-v2-bridge"
import { Config } from "@/config/config"
import { Provider } from "@/provider/provider"
import { Session } from "@/session/session"
import type { SessionID } from "../../src/session/schema"
import { ShareNext } from "@/share/share-next"
@ -20,13 +19,7 @@ import { provideTmpdirInstance } from "../fixture/fixture"
import { resetDatabase } from "../fixture/db"
import { pollWithTimeout, testEffect } from "../lib/effect"
const env = Layer.mergeAll(
Session.defaultLayer,
AccountRepo.defaultLayer,
Database.defaultLayer,
NodeFileSystem.layer,
CrossSpawnSpawner.defaultLayer,
)
const env = LayerNode.buildLayer(CrossSpawnSpawner.node)
const it = testEffect(env)
const json = (req: Parameters<typeof HttpClientResponse.fromWeb>[0], body: unknown, status = 200) =>
@ -40,35 +33,28 @@ const json = (req: Parameters<typeof HttpClientResponse.fromWeb>[0], body: unkno
const none = HttpClient.make(() => Effect.die("unexpected http call"))
function live(client: HttpClient.HttpClient) {
const http = Layer.succeed(HttpClient.HttpClient, client)
return ShareNext.layer.pipe(
Layer.provide(EventV2Bridge.defaultLayer),
Layer.provide(Account.layer.pipe(Layer.provide(AccountRepo.defaultLayer), Layer.provide(http))),
Layer.provide(Config.defaultLayer),
Layer.provide(Database.defaultLayer),
Layer.provide(http),
Layer.provide(Provider.defaultLayer),
Layer.provide(Session.defaultLayer),
function requestLayer(client: HttpClient.HttpClient) {
return LayerNode.buildLayer(
LayerNode.group([ShareNext.node, AccountRepo.node]),
{
replacements: [LayerNode.replace(httpClient, Layer.succeed(HttpClient.HttpClient, client))],
},
)
}
function wired(client: HttpClient.HttpClient) {
const http = Layer.succeed(HttpClient.HttpClient, client)
return Layer.mergeAll(
EventV2Bridge.defaultLayer,
ShareNext.layer,
Session.defaultLayer,
AccountRepo.defaultLayer,
Database.defaultLayer,
NodeFileSystem.layer,
CrossSpawnSpawner.defaultLayer,
).pipe(
Layer.provide(EventV2Bridge.defaultLayer),
Layer.provide(Account.layer.pipe(Layer.provide(AccountRepo.defaultLayer), Layer.provide(http))),
Layer.provide(Config.defaultLayer),
Layer.provide(http),
Layer.provide(Provider.defaultLayer),
function integrationLayer(client: HttpClient.HttpClient) {
return LayerNode.buildLayer(
LayerNode.group([
ShareNext.node,
EventV2Bridge.node,
Session.node,
SessionProjector.node,
AccountRepo.node,
Database.node,
]),
{
replacements: [LayerNode.replace(httpClient, Layer.succeed(HttpClient.HttpClient, client))],
},
)
}
@ -115,7 +101,7 @@ describe("ShareNext", () => {
expect(req.baseUrl).toBe("https://legacy-share.example.com")
expect(req.headers).toEqual({})
}),
).pipe(Effect.provide(live(none))),
).pipe(Effect.provide(requestLayer(none))),
{ config: { enterprise: { url: "https://legacy-share.example.com" } } },
),
)
@ -130,7 +116,7 @@ describe("ShareNext", () => {
expect(req.api.create).toBe("/api/share")
expect(req.headers).toEqual({})
}),
).pipe(Effect.provide(live(none))),
).pipe(Effect.provide(requestLayer(none))),
),
)
@ -139,7 +125,7 @@ describe("ShareNext", () => {
Effect.gen(function* () {
yield* seed("https://control.example.com", "org-1")
const req = yield* ShareNext.use.request().pipe(Effect.provide(live(none)))
const req = yield* ShareNext.use.request()
expect(req.api.create).toBe("/api/shares")
expect(req.api.sync("shr_123")).toBe("/api/shares/shr_123/sync")
@ -150,31 +136,31 @@ describe("ShareNext", () => {
authorization: "Bearer st_test_token",
"x-org-id": "org-1",
})
}),
}).pipe(Effect.provide(requestLayer(none))),
),
)
it.live("create posts share, persists it, and returns the result", () =>
provideTmpdirInstance(
() =>
Effect.gen(function* () {
const session = yield* Session.use.create({ title: "test" })
const seen: HttpClientRequest.HttpClientRequest[] = []
const client = HttpClient.make((req) => {
seen.push(req)
if (req.url.endsWith("/api/share")) {
return Effect.succeed(
json(req, {
id: "shr_abc",
url: "https://legacy-share.example.com/share/abc",
secret: "sec_123",
}),
)
}
return Effect.succeed(json(req, { ok: true }))
})
() => {
const seen: HttpClientRequest.HttpClientRequest[] = []
const client = HttpClient.make((req) => {
seen.push(req)
if (req.url.endsWith("/api/share")) {
return Effect.succeed(
json(req, {
id: "shr_abc",
url: "https://legacy-share.example.com/share/abc",
secret: "sec_123",
}),
)
}
return Effect.succeed(json(req, { ok: true }))
})
return Effect.gen(function* () {
const session = yield* (yield* Session.Service).create({ title: "test" })
const result = yield* ShareNext.use.create(session.id).pipe(Effect.provide(live(client)))
const result = yield* (yield* ShareNext.Service).create(session.id)
expect(result.id).toBe("shr_abc")
expect(result.url).toBe("https://legacy-share.example.com/share/abc")
@ -188,60 +174,59 @@ describe("ShareNext", () => {
expect(seen).toHaveLength(1)
expect(seen[0].method).toBe("POST")
expect(seen[0].url).toBe("https://legacy-share.example.com/api/share")
}),
}).pipe(Effect.provide(integrationLayer(client)))
},
{ config: { enterprise: { url: "https://legacy-share.example.com" } } },
),
)
it.live("remove deletes the persisted share and calls the delete endpoint", () =>
provideTmpdirInstance(
() =>
Effect.gen(function* () {
const session = yield* Session.use.create({ title: "test" })
const seen: HttpClientRequest.HttpClientRequest[] = []
const client = HttpClient.make((req) => {
seen.push(req)
if (req.method === "POST") {
return Effect.succeed(
json(req, {
id: "shr_abc",
url: "https://legacy-share.example.com/share/abc",
secret: "sec_123",
}),
)
}
return Effect.succeed(HttpClientResponse.fromWeb(req, new Response(null, { status: 200 })))
})
() => {
const seen: HttpClientRequest.HttpClientRequest[] = []
const client = HttpClient.make((req) => {
seen.push(req)
if (req.method === "POST") {
return Effect.succeed(
json(req, {
id: "shr_abc",
url: "https://legacy-share.example.com/share/abc",
secret: "sec_123",
}),
)
}
return Effect.succeed(HttpClientResponse.fromWeb(req, new Response(null, { status: 200 })))
})
return Effect.gen(function* () {
const session = yield* (yield* Session.Service).create({ title: "test" })
const service = yield* ShareNext.Service
yield* Effect.gen(function* () {
yield* ShareNext.use.create(session.id)
yield* ShareNext.use.remove(session.id)
}).pipe(Effect.provide(live(client)))
yield* service.create(session.id)
yield* service.remove(session.id)
expect(yield* share(session.id)).toBeUndefined()
expect(seen.map((req) => [req.method, req.url])).toEqual([
["POST", "https://legacy-share.example.com/api/share"],
["DELETE", "https://legacy-share.example.com/api/share/shr_abc"],
])
}),
}).pipe(Effect.provide(integrationLayer(client)))
},
{ config: { enterprise: { url: "https://legacy-share.example.com" } } },
),
)
it.live("create fails on a non-ok response and does not persist a share", () =>
provideTmpdirInstance(() =>
Effect.gen(function* () {
const session = yield* Session.use.create({ title: "test" })
const client = HttpClient.make((req) => Effect.succeed(json(req, { error: "bad" }, 500)))
provideTmpdirInstance(() => {
const client = HttpClient.make((req) => Effect.succeed(json(req, { error: "bad" }, 500)))
return Effect.gen(function* () {
const session = yield* (yield* Session.Service).create({ title: "test" })
const exit = yield* ShareNext.Service.use((svc) => Effect.exit(svc.create(session.id))).pipe(
Effect.provide(live(client)),
)
const exit = yield* ShareNext.Service.use((svc) => Effect.exit(svc.create(session.id)))
expect(Exit.isFailure(exit)).toBe(true)
expect(yield* share(session.id)).toBeUndefined()
}),
),
}).pipe(Effect.provide(integrationLayer(client)))
}),
)
it.live("ShareNext coalesces rapid diff events into one delayed sync with latest data", () =>
@ -336,7 +321,7 @@ describe("ShareNext", () => {
status: "modified",
},
])
}).pipe(Effect.provide(wired(client)))
}).pipe(Effect.provide(integrationLayer(client)))
},
{ config: { enterprise: { url: "https://legacy-share.example.com" } } },
),