test(core): cover Effect Schema event definitions

Exercise the new SyncEvent and BusEvent Schema overloads end to end and use Schema.isSchema for the conversion check so the mixed-schema path stays explicit and covered.
This commit is contained in:
Kit Langton
2026-04-23 08:43:35 -04:00
parent 3085279724
commit 96039bdb83
4 changed files with 67 additions and 6 deletions

View File

@@ -23,16 +23,12 @@ export function define<Type extends string, P extends ZodType>(
properties: P,
): { type: Type; properties: P }
export function define(type: string, properties: unknown) {
const zodProperties = isEffectSchema(properties) ? zod(properties) : (properties as ZodType)
const zodProperties = Schema.isSchema(properties) ? zod(properties) : (properties as ZodType)
const result = { type, properties: zodProperties }
registry.set(type, result as Definition)
return result
}
function isEffectSchema(value: unknown): value is Schema.Top {
return typeof value === "object" && value !== null && "ast" in value
}
export function payloads() {
return registry
.entries()

View File

@@ -117,7 +117,7 @@ export function define<
}
function toZodObject(value: ZodObject | Schema.Top): z.ZodObject {
if (typeof value === "object" && value !== null && "ast" in value) {
if (Schema.isSchema(value)) {
return zod(value as Schema.Top) as unknown as z.ZodObject
}
return value as z.ZodObject

View File

@@ -1,4 +1,5 @@
import { afterEach, describe, expect, test } from "bun:test"
import { Schema } from "effect"
import z from "zod"
import { Bus } from "../../src/bus"
import { BusEvent } from "../../src/bus/bus-event"
@@ -10,6 +11,8 @@ const TestEvent = {
Pong: BusEvent.define("test.pong", z.object({ message: z.string() })),
}
const EffectTestEvent = BusEvent.define("test.effect-schema.ping", Schema.Struct({ value: Schema.Number }))
function withInstance(directory: string, fn: () => Promise<void>) {
return Instance.provide({ directory, fn })
}
@@ -76,6 +79,22 @@ describe("Bus", () => {
await Bus.publish(TestEvent.Ping, { value: 1 })
})
})
test("accepts Effect Schema event definitions", async () => {
await using tmp = await tmpdir()
const received: number[] = []
await withInstance(tmp.path, async () => {
Bus.subscribe(EffectTestEvent, (evt) => {
received.push(evt.properties.value)
})
await Bun.sleep(10)
await Bus.publish(EffectTestEvent, { value: 42 })
await Bun.sleep(10)
})
expect(received).toEqual([42])
})
})
describe("unsubscribe", () => {

View File

@@ -1,4 +1,5 @@
import { describe, test, expect, beforeEach, afterEach, afterAll } from "bun:test"
import { Schema } from "effect"
import { tmpdir } from "../fixture/fixture"
import z from "zod"
import { Bus } from "../../src/bus"
@@ -128,6 +129,51 @@ describe("SyncEvent", () => {
})
}),
)
test(
"accepts Effect Schema event definitions",
withInstance(async () => {
SyncEvent.reset()
try {
const Created = SyncEvent.define({
type: "item.effect.created",
version: 1,
aggregate: "id",
schema: Schema.Struct({ id: Schema.String, name: Schema.String }),
})
SyncEvent.init({
projectors: [SyncEvent.project(Created, () => {})],
})
const events: Array<{
type: string
properties: { id: string; name: string }
}> = []
const received = new Promise<void>((resolve) => {
Bus.subscribeAll((event) => {
events.push(event)
resolve()
})
})
SyncEvent.run(Created, { id: "evt_1", name: "schema" })
await received
expect(events).toEqual([
{
type: "item.effect.created",
properties: {
id: "evt_1",
name: "schema",
},
},
])
} finally {
setup()
}
}),
)
})
describe("replay", () => {