On This Page

Effect Testing

Import from @neontechspace/fluxerly/effect/testing

Test Fluxer bots built with the Effect API without a network, a token or a Fluxer account

Import from @neontechspace/fluxerly/effect/testing in application tests

A test client is a real client from the native createClient whose HTTP and WebSocket traffic goes to an in-memory transport through the transport option. Events therefore pass through the SDK's own decoders, caches, handlers and logging. The fake gateway speaks protocol v1: It sends HELLO, answers Identify with READY and Resume with RESUMED, acknowledges heartbeats and delivers emitted dispatches with increasing sequence numbers. The fake HTTP side serves hosted Fluxer's discovery document, with presigned uploads off so attachments arrive as one multipart request, answers requests from registered responses and records every request without its Authorization header. Message sends and edits without a registered response receive an echoed bot message, and other unmatched requests receive a Fluxer-shaped 404 and a testing.unmatchedRequest Warn record. Waits such as idle and TestRoute.next have no deadline unless timeoutMs is passed, so the test runner's timeout bounds a test that hangs. Log records go to logs() and to any sinks in the logging option instead of the Effect logger. Closing the creating scope stops the client and closes the transport, leaving no sockets, timers or listeners behind, and dies with UnhandledTestFailuresError when a handler or command failed without an onError hook and the test did not read that failure from failures(). The fixture builders and their types are shared with @neontechspace/fluxerly/testing

TypeScript
import { Effect } from "effect"
import { createTestClient } from "@neontechspace/fluxerly/effect/testing"

export const pingTest = Effect.scoped(
    Effect.gen(function* () {
        const test = yield* createTestClient()
        const replies = test.rest.respond("POST /channels/:id/messages", {
            body: test.fixtures.message({ content: "Pong!" }),
        })
        yield* test.client.on("messageCreate", (message) =>
            message.content === "!ping" ? test.client.messages.reply(message, { content: "Pong!" }) : Effect.void,
        )
        yield* test.ready()
        yield* test.emit("MESSAGE_CREATE", test.fixtures.message({ content: "!ping" }))
        // Handlers run after emit returns, so wait for the reply before the Scope closes the client
        const reply = yield* replies.next()
        // A message the bot ignores sends nothing, which idle confirms without a fixed sleep
        yield* test.emit("MESSAGE_CREATE", test.fixtures.message({ content: "hello" }))
        yield* test.idle()
        return { reply, requests: replies.requests().length }
    }),
)

Categories#

  • Testing

    36 symbols

    createFixtures createTestBot createTestClient TestTimeoutError UnhandledTestFailuresError FluxerTestClient