Sign in

    testdock

    Disposable Docker Compose environments for MoonBit tests

    docker
    test
    e2e
    web
    Download zip
    Version
    0.1.0
    License
    Apache-2.0
    Last updated
    5 hours ago
    Downloads
    1

    #testdock

    Disposable Docker Compose environments for MoonBit tests. Requires Docker Compose v2 with up --wait and a running Docker daemon.

    Import moonbit-community/testdock, moonbitlang/async/http and tonyfettes/url in your moon.pkg. The example's api service publishes port 3000 and returns ok from GET /health:

    ///|
    async test "GET /health" {
    let compose = @testdock.DockerCompose(config="compose.yml")
    defer compose.down() // Remove containers, networks and volumes after the test.
    compose.up(timeout=60_000) // Wait for running/healthy services; milliseconds.

    let api = compose.service("api")
    let port = api.get_host_port_ipv4("3000").unwrap()

    let endpoint = @url.Url::parse("http://localhost/health")
    endpoint.set_hostname(api.get_host())
    endpoint.set_port(port)

    let (_, body) = @http.get(endpoint.href())
    json_inspect(body.text(), content="ok")
    }

    See example/ for a complete HTTP + PostgreSQL test that creates and reads a message.

    Run it from this repository:

    moon test example/app

    Both services define their own health checks. Each run gets a fresh Compose project, a random HTTP port and a disposable database volume. The test uses defer compose.down() to clean up when it finishes or an assertion fails. The initial run downloads the images and MoonBit toolchain needed for the build.

    To run all tests:

    moon test --target native

    Client

    pub(all) enum Client {
    Local
    }

    Container

    type Container

    A container owned by a Compose project. This handle does not own cleanup.

    Container::get_bridge_ip_address

    async fn Container::get_bridge_ip_address(self : Container) -> String?

    IPv4 address on the default bridge, or the sole attached network. Multiple non-default networks are ambiguous and raise an error. A private container IP may not be reachable from the host on Docker Desktop.

    Container::get_host

    fn Container::get_host(self : Container) -> String

    Docker host without a port or IPv6 brackets, not the container's private IP.

    Container::get_host_port_ipv4

    async fn Container::get_host_port_ipv4(self : Container, port : String) -> String?

    Accepts "8080" (TCP), "8080/tcp" or "8080/udp". None means no IPv4 binding. Multiple distinct IPv4 host ports raise an error; use ports() to select one.

    Container::get_host_port_ipv6

    async fn Container::get_host_port_ipv6(self : Container, port : String) -> String?

    None means no IPv6 binding. Docker command failures are raised separately.

    Container::id

    fn Container::id(self : Container) -> String

    Container::ports

    async fn Container::ports(self : Container) -> Map[String, Array[(String, String)]]

    Published bindings: "8080/tcp" -> [(host IP, host port), ...]. Exposed but unpublished ports have an empty array. Ports remain strings.

    DockerCompose

    type DockerCompose

    One disposable Compose project. Serialize operations on the same handle.

    DockerCompose::DockerCompose

    fn DockerCompose::DockerCompose(config~ : String, env? : String, client? : Client, force_build? : Bool) -> DockerCompose

    config is a Compose file path. env is a Compose --env-file path. force_build=false keeps Compose's normal policy, rather than passing --no-build.

    DockerCompose::down

    async fn DockerCompose::down(self : DockerCompose) -> Unit

    Remove this project's containers, networks and volumes, keeping images. External volumes and bind-mounted files are not removed. Idempotent.

    DockerCompose::service

    async fn DockerCompose::service(self : DockerCompose, name : String) -> Container

    Look up one service container, including completed init containers. A replicated service raises an ambiguity error instead of choosing a replica.

    DockerCompose::up

    async fn DockerCompose::up(self : DockerCompose, timeout? : Int) -> Unit

    Wait for Compose's running/healthy state. Without a healthcheck, running is sufficient. timeout is in milliseconds; omit it for no startup deadline. Failed or timed-out startup attempts to remove the partially created project.

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io