test(opencode): simplify share layer wiring (#31811)
This commit is contained in:
parent
51891d56e7
commit
20bf18ffb4
@ -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" } } },
|
||||
),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user