Remove DVM tests
This commit is contained in:
@@ -1,288 +0,0 @@
|
|||||||
import {publish, subscribe} from "@welshman/net"
|
|
||||||
import type {StampedEvent, TrustedEvent} from "@welshman/util"
|
|
||||||
import {finalizeEvent} from "nostr-tools/pure"
|
|
||||||
import {afterAll, beforeEach, describe, expect, it, vi} from "vitest"
|
|
||||||
import {DVM, type DVMHandler, type DVMOpts} from "../src/handler"
|
|
||||||
import {now} from "@welshman/lib"
|
|
||||||
|
|
||||||
// Mock dependencies
|
|
||||||
vi.mock("nostr-tools/pure", () => ({
|
|
||||||
getPublicKey: vi.fn().mockReturnValue("ee".repeat(32)),
|
|
||||||
finalizeEvent: vi.fn(template => ({...template, sig: "ff".repeat(64)})),
|
|
||||||
}))
|
|
||||||
|
|
||||||
vi.mock("@welshman/net", () => ({
|
|
||||||
subscribe: vi.fn(),
|
|
||||||
publish: vi.fn(),
|
|
||||||
}))
|
|
||||||
|
|
||||||
describe("DVM", () => {
|
|
||||||
let dvm: DVM
|
|
||||||
let mockHandler: DVMHandler
|
|
||||||
let mockSubscription: any
|
|
||||||
let mockPublish: any
|
|
||||||
|
|
||||||
const sk = "ff".repeat(32)
|
|
||||||
const id = "dd".repeat(32)
|
|
||||||
const pubkey = "ee".repeat(32)
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
// Reset mocks
|
|
||||||
vi.clearAllMocks()
|
|
||||||
|
|
||||||
vi.useFakeTimers()
|
|
||||||
|
|
||||||
// Setup mock handler
|
|
||||||
mockHandler = {
|
|
||||||
handleEvent: vi.fn().mockImplementation(async function* (e: TrustedEvent) {
|
|
||||||
yield {kind: 1, tags: [], content: "response"} as StampedEvent
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup mock subscription
|
|
||||||
mockSubscription = {
|
|
||||||
on: vi.fn((event, callback) => {
|
|
||||||
if (event === "complete") {
|
|
||||||
// Simulate completion after a delay
|
|
||||||
setTimeout(callback, 0)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
vi.mocked(subscribe).mockReturnValue(mockSubscription)
|
|
||||||
|
|
||||||
// Setup mock publish
|
|
||||||
mockPublish = {
|
|
||||||
emitter: {
|
|
||||||
on: vi.fn((event, callback) => {
|
|
||||||
if (event === "success") {
|
|
||||||
callback()
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
vi.mocked(publish).mockReturnValue(mockPublish)
|
|
||||||
|
|
||||||
// Create DVM instance
|
|
||||||
const opts: DVMOpts = {
|
|
||||||
sk: sk,
|
|
||||||
relays: ["relay1", "relay2"],
|
|
||||||
handlers: {
|
|
||||||
"1": () => mockHandler,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
dvm = new DVM(opts)
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(() => {
|
|
||||||
vi.useRealTimers()
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("initialization", () => {
|
|
||||||
it("should initialize with provided handlers", () => {
|
|
||||||
expect(dvm.handlers.get(1)).toBeDefined()
|
|
||||||
expect(dvm.active).toBe(false)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should parse handler kinds as integers", () => {
|
|
||||||
const dvm = new DVM({
|
|
||||||
sk,
|
|
||||||
relays: [],
|
|
||||||
handlers: {"1": () => mockHandler},
|
|
||||||
})
|
|
||||||
expect(dvm.handlers.get(1)).toBeDefined()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("start", () => {
|
|
||||||
it("should start subscription with correct filters", async () => {
|
|
||||||
await Promise.all([
|
|
||||||
dvm.start(),
|
|
||||||
vi.advanceTimersByTimeAsync(1000),
|
|
||||||
new Promise(resolve => setTimeout(() => resolve(dvm.stop()), 1000)),
|
|
||||||
])
|
|
||||||
|
|
||||||
expect(subscribe).toHaveBeenCalledWith({
|
|
||||||
relays: ["relay1", "relay2"],
|
|
||||||
filters: [{kinds: [1], since: now()}],
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should include pubkey filter when requireMention is true", async () => {
|
|
||||||
dvm = new DVM({
|
|
||||||
sk,
|
|
||||||
relays: ["relay1"],
|
|
||||||
handlers: {"1": () => mockHandler},
|
|
||||||
requireMention: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
await Promise.all([
|
|
||||||
dvm.start(),
|
|
||||||
vi.advanceTimersByTimeAsync(1000),
|
|
||||||
new Promise(resolve => setTimeout(() => resolve(dvm.stop()), 1000)),
|
|
||||||
])
|
|
||||||
|
|
||||||
expect(subscribe).toHaveBeenCalledWith({
|
|
||||||
relays: ["relay1"],
|
|
||||||
filters: [
|
|
||||||
{
|
|
||||||
kinds: [1],
|
|
||||||
since: now() - 1,
|
|
||||||
"#p": [pubkey],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("event handling", () => {
|
|
||||||
it("should ignore duplicate events", async () => {
|
|
||||||
const event = {id, kind: 1, tags: [], content: ""} as any
|
|
||||||
|
|
||||||
await dvm.onEvent(event)
|
|
||||||
await dvm.onEvent(event)
|
|
||||||
|
|
||||||
expect(mockHandler.handleEvent).toHaveBeenCalledTimes(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should ignore events without handlers", async () => {
|
|
||||||
const event = {id, kind: 2} as TrustedEvent
|
|
||||||
|
|
||||||
await dvm.onEvent(event)
|
|
||||||
|
|
||||||
expect(mockHandler.handleEvent).not.toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should add required tags to response events", async () => {
|
|
||||||
const request = {
|
|
||||||
id,
|
|
||||||
kind: 1,
|
|
||||||
pubkey,
|
|
||||||
tags: [["i", "input123"]],
|
|
||||||
} as TrustedEvent
|
|
||||||
|
|
||||||
mockHandler.handleEvent.mockImplementation(async function* () {
|
|
||||||
yield {kind: 1, tags: []} as StampedEvent
|
|
||||||
})
|
|
||||||
|
|
||||||
await dvm.onEvent(request)
|
|
||||||
|
|
||||||
vi.advanceTimersByTimeAsync(100)
|
|
||||||
|
|
||||||
expect(publish).toHaveBeenCalledWith(
|
|
||||||
expect.objectContaining({
|
|
||||||
event: expect.objectContaining({
|
|
||||||
tags: expect.arrayContaining([
|
|
||||||
["request", expect.any(String)],
|
|
||||||
["i", "input123"],
|
|
||||||
["p", pubkey],
|
|
||||||
["e", id],
|
|
||||||
["expiration", (now() + 60 * 60).toString()], // default expireAfter is 1 hour
|
|
||||||
]),
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should not add request tag to job status events", async () => {
|
|
||||||
const request = {
|
|
||||||
id,
|
|
||||||
kind: 1,
|
|
||||||
pubkey,
|
|
||||||
tags: [],
|
|
||||||
} as any
|
|
||||||
|
|
||||||
mockHandler.handleEvent.mockImplementation(async function* () {
|
|
||||||
yield {kind: 7000, tags: []} as StampedEvent
|
|
||||||
})
|
|
||||||
|
|
||||||
await dvm.onEvent(request)
|
|
||||||
|
|
||||||
const publishedEvent = vi.mocked(publish).mock.calls[0][0].event
|
|
||||||
expect(publishedEvent.tags).not.toContainEqual(expect.arrayContaining(["request"]))
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should handle custom expiration time", async () => {
|
|
||||||
dvm = new DVM({
|
|
||||||
sk,
|
|
||||||
relays: ["relay1"],
|
|
||||||
handlers: {"1": () => mockHandler},
|
|
||||||
expireAfter: 120, // 2 minutes
|
|
||||||
})
|
|
||||||
|
|
||||||
const request = {
|
|
||||||
id,
|
|
||||||
kind: 1,
|
|
||||||
pubkey,
|
|
||||||
tags: [],
|
|
||||||
} as any
|
|
||||||
|
|
||||||
await dvm.onEvent(request)
|
|
||||||
|
|
||||||
expect(publish).toHaveBeenCalledWith(
|
|
||||||
expect.objectContaining({
|
|
||||||
event: expect.objectContaining({
|
|
||||||
tags: expect.arrayContaining([["expiration", (now() + 120).toString()]]),
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("publish", () => {
|
|
||||||
it("should finalize and publish events", async () => {
|
|
||||||
const template = {
|
|
||||||
kind: 1,
|
|
||||||
tags: [],
|
|
||||||
content: "test",
|
|
||||||
} as any
|
|
||||||
|
|
||||||
await dvm.publish(template)
|
|
||||||
|
|
||||||
expect(finalizeEvent).toHaveBeenCalledWith(template, expect.any(Uint8Array))
|
|
||||||
expect(publish).toHaveBeenCalledWith({
|
|
||||||
event: expect.any(Object),
|
|
||||||
relays: ["relay1", "relay2"],
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("cleanup", () => {
|
|
||||||
it("should stop all handlers", () => {
|
|
||||||
const stopHandler = {
|
|
||||||
stop: vi.fn(),
|
|
||||||
handleEvent: vi.fn(),
|
|
||||||
}
|
|
||||||
|
|
||||||
dvm = new DVM({
|
|
||||||
sk: sk,
|
|
||||||
relays: ["relay1"],
|
|
||||||
handlers: {"1": () => stopHandler},
|
|
||||||
})
|
|
||||||
|
|
||||||
dvm.stop()
|
|
||||||
|
|
||||||
expect(stopHandler.stop).toHaveBeenCalled()
|
|
||||||
expect(dvm.active).toBe(false)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("logging", () => {
|
|
||||||
it("should log events when enabled", async () => {
|
|
||||||
const consoleSpy = vi.spyOn(console, "info")
|
|
||||||
dvm.logEvents = true
|
|
||||||
|
|
||||||
const request = {
|
|
||||||
id: "req123",
|
|
||||||
kind: 1,
|
|
||||||
pubkey: "pub123",
|
|
||||||
tags: [],
|
|
||||||
} as any
|
|
||||||
|
|
||||||
await dvm.onEvent(request)
|
|
||||||
|
|
||||||
expect(consoleSpy).toHaveBeenCalledWith("Handling request", request)
|
|
||||||
expect(consoleSpy).toHaveBeenCalledWith("Publishing event", expect.any(Object))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,219 +0,0 @@
|
|||||||
import {now} from "@welshman/lib"
|
|
||||||
import {subscribe, publish, SubscriptionEvent} from "@welshman/net"
|
|
||||||
import type {SignedEvent, TrustedEvent} from "@welshman/util"
|
|
||||||
import {vi, describe, it, expect, beforeEach} from "vitest"
|
|
||||||
import {makeDvmRequest, DVMEvent} from "../src/request"
|
|
||||||
|
|
||||||
// Mock dependencies
|
|
||||||
vi.mock(import("@welshman/lib"), async importOriginal => ({
|
|
||||||
...(await importOriginal()),
|
|
||||||
Emitter: vi.fn().mockImplementation(() => ({
|
|
||||||
emit: vi.fn(),
|
|
||||||
on: vi.fn(),
|
|
||||||
})),
|
|
||||||
}))
|
|
||||||
|
|
||||||
vi.mock("@welshman/net", () => ({
|
|
||||||
subscribe: vi.fn(),
|
|
||||||
publish: vi.fn(),
|
|
||||||
SubscriptionEvent: {
|
|
||||||
Event: "event",
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
|
|
||||||
describe("DVM Request", () => {
|
|
||||||
let mockSubscription: any
|
|
||||||
let mockPublish: any
|
|
||||||
let baseEvent: SignedEvent
|
|
||||||
|
|
||||||
const id = "dd".repeat(32)
|
|
||||||
const pubkey = "ee".repeat(32)
|
|
||||||
const sig = "ff".repeat(64)
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
vi.clearAllMocks()
|
|
||||||
|
|
||||||
// Setup mock subscription
|
|
||||||
mockSubscription = {
|
|
||||||
on: vi.fn(),
|
|
||||||
close: vi.fn(),
|
|
||||||
}
|
|
||||||
vi.mocked(subscribe).mockReturnValue(mockSubscription)
|
|
||||||
|
|
||||||
// Setup mock publish
|
|
||||||
mockPublish = {
|
|
||||||
emitter: {on: vi.fn()},
|
|
||||||
}
|
|
||||||
vi.mocked(publish).mockReturnValue(mockPublish)
|
|
||||||
|
|
||||||
// Base event for testing
|
|
||||||
baseEvent = {
|
|
||||||
id,
|
|
||||||
kind: 5000,
|
|
||||||
pubkey,
|
|
||||||
content: "",
|
|
||||||
tags: [],
|
|
||||||
created_at: now(),
|
|
||||||
sig,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("makeDvmRequest", () => {
|
|
||||||
it("should create subscription with correct filters", () => {
|
|
||||||
const request = makeDvmRequest({
|
|
||||||
event: baseEvent,
|
|
||||||
relays: ["relay1", "relay2"],
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(subscribe).toHaveBeenCalledWith({
|
|
||||||
relays: ["relay1", "relay2"],
|
|
||||||
timeout: 30000,
|
|
||||||
filters: [
|
|
||||||
{
|
|
||||||
kinds: [6000, 7000], // kind + 1000 and progress events
|
|
||||||
since: now() - 60, // now() - 60
|
|
||||||
"#e": [id],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should respect custom timeout", () => {
|
|
||||||
const request = makeDvmRequest({
|
|
||||||
event: baseEvent,
|
|
||||||
relays: ["relay1"],
|
|
||||||
timeout: 5000,
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(subscribe).toHaveBeenCalledWith(
|
|
||||||
expect.objectContaining({
|
|
||||||
timeout: 5000,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should disable progress events when reportProgress is false", () => {
|
|
||||||
makeDvmRequest({
|
|
||||||
event: baseEvent,
|
|
||||||
relays: ["relay1"],
|
|
||||||
reportProgress: false,
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(subscribe).toHaveBeenCalledWith(
|
|
||||||
expect.objectContaining({
|
|
||||||
filters: [
|
|
||||||
{
|
|
||||||
kinds: [6000], // Only result kind, no progress events
|
|
||||||
since: expect.any(Number),
|
|
||||||
"#e": [baseEvent.id],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should publish request event", () => {
|
|
||||||
makeDvmRequest({
|
|
||||||
event: baseEvent,
|
|
||||||
relays: ["relay1"],
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(publish).toHaveBeenCalledWith({
|
|
||||||
event: baseEvent,
|
|
||||||
relays: ["relay1"],
|
|
||||||
timeout: 30000,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("event handling", () => {
|
|
||||||
it("should emit progress events", () => {
|
|
||||||
const request = makeDvmRequest({
|
|
||||||
event: baseEvent,
|
|
||||||
relays: ["relay1"],
|
|
||||||
})
|
|
||||||
|
|
||||||
// Get the event handler
|
|
||||||
const eventHandler = mockSubscription.on.mock.calls.find(
|
|
||||||
call => call[0] === SubscriptionEvent.Event,
|
|
||||||
)[1]
|
|
||||||
|
|
||||||
// Simulate progress event
|
|
||||||
const progressEvent = {
|
|
||||||
kind: 7000,
|
|
||||||
content: "progress",
|
|
||||||
} as TrustedEvent
|
|
||||||
|
|
||||||
eventHandler("relay1", progressEvent)
|
|
||||||
|
|
||||||
expect(request.emitter.emit).toHaveBeenCalledWith(DVMEvent.Progress, "relay1", progressEvent)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should emit and auto-close on result events", () => {
|
|
||||||
const request = makeDvmRequest({
|
|
||||||
event: baseEvent,
|
|
||||||
relays: ["relay1"],
|
|
||||||
})
|
|
||||||
|
|
||||||
// Get the event handler
|
|
||||||
const eventHandler = mockSubscription.on.mock.calls.find(
|
|
||||||
call => call[0] === SubscriptionEvent.Event,
|
|
||||||
)[1]
|
|
||||||
|
|
||||||
// Simulate result event
|
|
||||||
const resultEvent = {
|
|
||||||
kind: 6000,
|
|
||||||
content: "result",
|
|
||||||
} as TrustedEvent
|
|
||||||
|
|
||||||
eventHandler("relay1", resultEvent)
|
|
||||||
|
|
||||||
expect(request.emitter.emit).toHaveBeenCalledWith(DVMEvent.Result, "relay1", resultEvent)
|
|
||||||
expect(request.sub.close).toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should not auto-close when autoClose is false", () => {
|
|
||||||
const request = makeDvmRequest({
|
|
||||||
event: baseEvent,
|
|
||||||
relays: ["relay1"],
|
|
||||||
autoClose: false,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Get the event handler
|
|
||||||
const eventHandler = mockSubscription.on.mock.calls.find(
|
|
||||||
call => call[0] === SubscriptionEvent.Event,
|
|
||||||
)[1]
|
|
||||||
|
|
||||||
// Simulate result event
|
|
||||||
const resultEvent = {
|
|
||||||
kind: 6000,
|
|
||||||
content: "result",
|
|
||||||
} as TrustedEvent
|
|
||||||
|
|
||||||
eventHandler("relay1", resultEvent)
|
|
||||||
|
|
||||||
expect(request.sub.close).not.toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("request object structure", () => {
|
|
||||||
it("should return correctly structured request object", () => {
|
|
||||||
const requestOpts = {
|
|
||||||
event: baseEvent,
|
|
||||||
relays: ["relay1"],
|
|
||||||
timeout: 5000,
|
|
||||||
autoClose: false,
|
|
||||||
reportProgress: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
const request = makeDvmRequest(requestOpts)
|
|
||||||
|
|
||||||
expect(request).toEqual({
|
|
||||||
request: requestOpts,
|
|
||||||
emitter: expect.any(Object),
|
|
||||||
sub: mockSubscription,
|
|
||||||
pub: mockPublish,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
Reference in New Issue
Block a user