brian-watkins / elm-spec / Spec.Http.Stub

Define and set up stubs for HTTP requests made during a spec.

If an HTTP request matches none of the stubs currently served, then elm-spec will respond with a 404 status code.

Create and Register Stubs


type HttpResponseStub

Represents the stubbed response for a particular HTTP request.

for : Spec.Http.Route.HttpRoute -> HttpResponseStub

Build a stubbed response for requests made to the given route.

By default, the stubbed response has:

serve : List HttpResponseStub -> Spec.Setup.Setup model msg -> Spec.Setup.Setup model msg

Set up a fake HTTP server with the given HttpResponseStubs.

When a matching HTTP request is made, the relevant stubbed response will be returned.

nowServe : List HttpResponseStub -> Spec.Step.Step model msg

A step that reconfigures the fake HTTP server to serve the given HttpResponseStubs.

Use this function if you want to change the stubs during a scenario.

For example, suppose you are writing a scenario that describes an application that polls some HTTP endpoint every 5 seconds. You could change the stubbed response during the scenario like so:

Spec.scenario "polling" (
  Spec.given (
    Spec.Setup.init (App.init testFlags)
      |> Spec.Setup.withView App.view
      |> Spec.Setup.withUpdate App.update
      |> Stub.serve [ pollFailsStub ]
  )
  |> when "time passes"
    [ Spec.Time.tick 5000
    , Spec.Time.tick 5000
    ]
  |> when "the poll succeeds"
    [ Spec.Http.Stub.nowServe [ pollSucceedsStub ]
    , Spec.Time.tick 5000
    ]
  |> it "does the right thing" (
    ...
  )
)

Note that Spec.Http.Stub.nowServe will clear any existing stubs and register only the ones provided.

Stub the Response Body


type HttpResponseBody

Represents the body of an HTTP response.

withBody : HttpResponseBody -> HttpResponseStub -> HttpResponseStub

Supply an HttpResponseBody for the stubbed response.

withText : String -> HttpResponseBody

Create an HttpResponseBody composed of the given text.

withJson : Json.Encode.Value -> HttpResponseBody

Create an HttpResponseBody composed of the given JSON value, stringified.

withBytes : Bytes -> HttpResponseBody

Create an HttpResponseBody composed of the given bytes.

withTextAtPath : String -> HttpResponseBody

Create an HttpResponseBody composed of the text from the file at the given path.

The path is typically relative to the current working directory of the elm-spec runner (but check the docs for the runner you are using).

withBytesAtPath : String -> HttpResponseBody

Create an HttpResponseBody composed of the bytes from the file at the given path.

The path is typically relative to the current working directory of the elm-spec runner (but check the docs for the runner you are using).

Stub Progress of an In-Flight Request


type HttpResponseProgress

Represents progress on an in-flight HTTP request.

sent : Basics.Int -> HttpResponseProgress

Specify the number of bytes that have been uploaded to the server so far.

Note that the total number of bytes is determined by the HTTP request body.

received : Basics.Int -> HttpResponseProgress

Specify the number of bytes received from the server so far.

Note that the total number of bytes is determined by the stubbed HTTP response body.

streamed : Basics.Int -> HttpResponseProgress

Specify the number of bytes received from the server so far, when the total content length is not known.

withProgress : HttpResponseProgress -> HttpResponseStub -> HttpResponseStub

Set the progress on an in-flight HTTP request.

When the request is processed, an appropriate progress event will be triggered.

No further processing of this request will take place after the progress event is triggered. So, use this function to describe a program's behavior when an HTTP request is not yet complete.

abstain : HttpResponseStub -> HttpResponseStub

Abstain from responding to requests to the route defined for the given HttpResponseStub.

It can be useful to abstain from responding if you want to describe the behavior of your program while waiting for a response.

Note: This function is equivalent to withProgress <| received 0

Stub Response Metadata

withStatus : Basics.Int -> HttpResponseStub -> HttpResponseStub

Supply a status code for the stubbed response.

withHeader : ( String, String ) -> HttpResponseStub -> HttpResponseStub

Supply a header (key, value) for the stubbed response.

Stub Errors

withNetworkError : HttpResponseStub -> HttpResponseStub

Set the stubbed response to trigger a network error.

withTimeout : HttpResponseStub -> HttpResponseStub

Set the stubbed response to trigger a timeout error.

Work with API Contracts

When you create stubs as part of a spec, you are simluating an HTTP API and thus making assumptions about the shape of that API -- what paths it defines, what response bodies should look like, what headers are required, etc. Without some external validation, it's easy to imagine that the assumptions made in your specs could fall out of sync with reality.

An API contract, like an OpenAPI document, can help you avoid this situation. An API contract describes the shape of an API in a format that can be shared by all parties interested in that API, so that each party -- the server, a mobile client, a web client, etc -- can check their own assumptions about that API against the very same description.

Use the functions below to create and associate an API contract with a stub so that all requests matching that stub and all responses returned by that stub are validated against that contract. By following this pattern, you can be confident that your stubs accurately describe the API integration they are simulating.


type Contract

Represents a contract with repsect to which HTTP requests and responses can be validated.

satisfies : Contract -> HttpResponseStub -> HttpResponseStub

Specify a contract that should be used to validate requests that match this stub as well as the response returned.

Consider creating a function that makes it easy to write stubs that should satisfy a particular contract:

funApiStubFor : HttpRoute -> HttpResponseStub
funApiStubFor route =
  Stub.for route
    |> Stub.satisfies funApiContract

Then you can use funApiStubFor anywhere you would use Spec.Http.Stub.for to define a stub.

openApiContractAt : String -> Contract

Create a Contract from an OpenAPI document at the given path.

OpenAPI version 2.0 (Swagger) and OpenAPI version 3.0 are supported. The document can be in YAML or JSON format.

The path is typically relative to the current working directory of the elm-spec runner (but check the docs for the runner you are using).