import {describe, expect, it, vi, beforeEach, afterEach} from "vitest" import {SinglePublish, MultiPublish, PublishEvent} from "../src/publish" import {MockAdapter} from "../src/adapter" import {ClientMessageType} from "../src/message" import {makeEvent} from "@welshman/util" import {Nip01Signer} from "@welshman/signer" describe("SinglePublish", () => { beforeEach(() => { vi.useFakeTimers() }) afterEach(() => { vi.useRealTimers() }) it("success works", async () => { const sendSpy = vi.fn() const adapter = new MockAdapter("1", sendSpy) const signer = Nip01Signer.ephemeral() const event = await signer.sign(makeEvent(1)) const pub = new SinglePublish({ relay: "1", context: {getAdapter: () => adapter}, event, }) const successSpy = vi.fn() const failureSpy = vi.fn() const completeSpy = vi.fn() pub.on(PublishEvent.Success, successSpy) pub.on(PublishEvent.Failure, failureSpy) pub.on(PublishEvent.Complete, completeSpy) await vi.advanceTimersByTimeAsync(200) expect(sendSpy).toHaveBeenCalledWith([ClientMessageType.Event, event]) adapter.receive(["OK", event.id, true, "hi"]) await vi.runAllTimers() expect(successSpy).toHaveBeenCalledWith(event.id, "hi") expect(failureSpy).not.toHaveBeenCalled() expect(completeSpy).toHaveBeenCalled() }) it("failure works", async () => { const sendSpy = vi.fn() const adapter = new MockAdapter("1", sendSpy) const signer = Nip01Signer.ephemeral() const event = await signer.sign(makeEvent(1)) const pub = new SinglePublish({ relay: "1", context: {getAdapter: () => adapter}, event, }) const successSpy = vi.fn() const failureSpy = vi.fn() const completeSpy = vi.fn() pub.on(PublishEvent.Success, successSpy) pub.on(PublishEvent.Failure, failureSpy) pub.on(PublishEvent.Complete, completeSpy) await vi.advanceTimersByTimeAsync(200) expect(sendSpy).toHaveBeenCalledWith([ClientMessageType.Event, event]) adapter.receive(["OK", event.id, false, "hi"]) await vi.runAllTimers() expect(successSpy).not.toHaveBeenCalled() expect(failureSpy).toHaveBeenCalledWith(event.id, "hi") expect(completeSpy).toHaveBeenCalled() }) it("timeout works", async () => { const sendSpy = vi.fn() const adapter = new MockAdapter("1", sendSpy) const signer = Nip01Signer.ephemeral() const event = await signer.sign(makeEvent(1)) const pub = new SinglePublish({ relay: "1", context: {getAdapter: () => adapter}, event, }) const successSpy = vi.fn() const failureSpy = vi.fn() const completeSpy = vi.fn() const timeoutSpy = vi.fn() pub.on(PublishEvent.Success, successSpy) pub.on(PublishEvent.Failure, failureSpy) pub.on(PublishEvent.Complete, completeSpy) pub.on(PublishEvent.Timeout, timeoutSpy) await vi.runAllTimers() expect(sendSpy).toHaveBeenCalledWith([ClientMessageType.Event, event]) await vi.runAllTimers() expect(successSpy).not.toHaveBeenCalled() expect(failureSpy).not.toHaveBeenCalled() expect(completeSpy).toHaveBeenCalled() expect(timeoutSpy).toHaveBeenCalled() }) it("abort works", async () => { const sendSpy = vi.fn() const adapter = new MockAdapter("1", sendSpy) const signer = Nip01Signer.ephemeral() const event = await signer.sign(makeEvent(1)) const pub = new SinglePublish({ relay: "1", context: {getAdapter: () => adapter}, event, }) const successSpy = vi.fn() const failureSpy = vi.fn() const completeSpy = vi.fn() const abortSpy = vi.fn() pub.on(PublishEvent.Success, successSpy) pub.on(PublishEvent.Failure, failureSpy) pub.on(PublishEvent.Complete, completeSpy) pub.on(PublishEvent.Timeout, abortSpy) await vi.runAllTimers() expect(sendSpy).toHaveBeenCalledWith([ClientMessageType.Event, event]) pub.abort() await vi.runAllTimers() expect(successSpy).not.toHaveBeenCalled() expect(failureSpy).not.toHaveBeenCalled() expect(completeSpy).toHaveBeenCalled() expect(abortSpy).toHaveBeenCalled() }) }) describe("MultiPublish", () => { beforeEach(() => { vi.useFakeTimers() }) afterEach(() => { vi.useRealTimers() }) it("should all basically work", async () => { const send1Spy = vi.fn() const adapter1 = new MockAdapter("1", send1Spy) const send2Spy = vi.fn() const adapter2 = new MockAdapter("2", send2Spy) const send3Spy = vi.fn() const adapter3 = new MockAdapter("3", send3Spy) const signer = Nip01Signer.ephemeral() const event = await signer.sign(makeEvent(1)) const pub = new MultiPublish({ event, relays: ["1", "2", "3"], context: { getAdapter: (url: string) => { switch (url) { case "1": return adapter1 case "2": return adapter2 case "3": return adapter3 default: throw new Error(`Unknown relay: ${url}`) } }, }, }) const successSpy = vi.fn() const failureSpy = vi.fn() const completeSpy = vi.fn() const timeoutSpy = vi.fn() pub.on(PublishEvent.Success, successSpy) pub.on(PublishEvent.Failure, failureSpy) pub.on(PublishEvent.Complete, completeSpy) pub.on(PublishEvent.Timeout, timeoutSpy) adapter1.receive(["OK", event.id, true, "hi"]) adapter2.receive(["OK", event.id, false, "hi"]) await vi.runAllTimers() expect(successSpy).toHaveBeenCalledWith(event.id, "hi", "1") expect(failureSpy).toHaveBeenCalledWith(event.id, "hi", "2") expect(completeSpy).toHaveBeenCalledTimes(1) expect(timeoutSpy).toHaveBeenCalledWith("3") }) })