mciccotti.FSWalkthrough.Http 1.0.7

dotnet add package mciccotti.FSWalkthrough.Http --version 1.0.7
                    
NuGet\Install-Package mciccotti.FSWalkthrough.Http -Version 1.0.7
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="mciccotti.FSWalkthrough.Http" Version="1.0.7" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="mciccotti.FSWalkthrough.Http" Version="1.0.7" />
                    
Directory.Packages.props
<PackageReference Include="mciccotti.FSWalkthrough.Http" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add mciccotti.FSWalkthrough.Http --version 1.0.7
                    
#r "nuget: mciccotti.FSWalkthrough.Http, 1.0.7"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package mciccotti.FSWalkthrough.Http@1.0.7
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=mciccotti.FSWalkthrough.Http&version=1.0.7
                    
Install as a Cake Addin
#tool nuget:?package=mciccotti.FSWalkthrough.Http&version=1.0.7
                    
Install as a Cake Tool

FSWalkthrough

Write API integration tests as multi-step workflows in F#.

A test should read as something a consumer of your system can do — log in, create a user, place an order — not as a sequence of HTTP calls. FSWalkthrough gives you a computation expression for exactly that, with defaults covering everything a given test doesn't care about.

[<Fact>]
let ``NewUser CanPlaceOrder`` () =
    workflow {
        LoginRequest.Default
        CreateUserRequest.Default
        build AddOrderItem.Default
        let! order = CreateOrderRequest.Default
        Assert.Equal("pending", order.Status)
    } |> run (makeRunner ())

Every field a test names is a claim that the field matters to that test. Defaults are what keep that claim honest.

Packages

Package Contents
mciccotti.FSWalkthrough.Core Request and response types, the workflow CE, WorkflowRunner, field values
mciccotti.FSWalkthrough.Http HttpTarget and HttpStep — sends workflow requests over HTTP
dotnet add package mciccotti.FSWalkthrough.Http

mciccotti.FSWalkthrough.Http depends on mciccotti.FSWalkthrough.Core, so for HTTP workflows that one package is enough. Both target net10.0.

Package IDs carry the mciccotti. prefix; the namespaces do not. Install mciccotti.FSWalkthrough.Http, then open FSWalkthrough.Http.

Requests and steps

A request record describes the inputs to one step and the response it produces. Default supplies a value for every field:

type CreateUserRequest =
    { Email     : IFieldValue<string>
      FirstName : IFieldValue<string> }
    interface WorkflowRequest<UserResponse>
    static member Default =
        { Email     = FieldValues.generated (fun () -> $"user-{Guid.NewGuid():N}@test.com")
          FirstName = FieldValues.constant "Test" }

A step binds that request to a transport:

type CreateUserStep() =
    inherit HttpStep<CreateUserRequest, UserResponse>()
    override _.Method = HttpMethod.Post
    override _.Path   = "/users"

Path parameters are filled from {placeholder} segments automatically. Override MapBody, MapQuery, or MapHeaders when the wire shape differs from the record.

Field values

FieldValues.constant  "value"
FieldValues.generated (fun () -> Guid.NewGuid().ToString())
FieldValues.from      (fun ctx -> ctx.Get<UserResponse>("CreateUserRequest").Id)

from is how a later step reuses an earlier response. Referencing a prior value rather than hardcoding one keeps the test honest: it says this depends on that, not this particular string matters.

Running a workflow

Register steps on a target, then hand a runner to run:

let makeRunner () =
    let api =
        HttpTarget("http://localhost:4200")
            .Register<CreateUserStep>()
            .Register<CreateOrderStep>()

    WorkflowRunner(WorkflowContext(), [| api :> ITarget |])

Multiple targets dispatch by CanHandle, first match wins — which is how login and API calls can use different base URLs or carry different headers.

Inside the CE

workflow {
    // run and discard the result
    LoginRequest.Default

    // run and bind the result
    let! user = CreateUserRequest.Default

    // override a default
    { CreateUserRequest.Default with Role = FieldValues.constant "admin" }

    // accumulate array items, then the request that consumes them
    build AddOrderItem.Default
    let! order = CreateOrderRequest.Default

    // retry until a predicate holds
    let! settled = pollWith 100 5000 GetOrderRequest.Default (fun r -> r.Status = "settled")

    // status code and body, without throwing on non-2xx
    let! attempt = raw CreateOrderRequest.Default
} |> run (makeRunner ())

for and while work inside the CE, and let! / do! accept any Task, so assertions that query the database directly sit inline with the rest of the workflow.

build is required for every BuildableRequest. It reads static member AccumulationKey at compile time via SRTP, which is what lets several item types accumulate into one collection.

Guidance for coding agents

mciccotti.FSWalkthrough.Core ships its own usage and style guides inside the package. On build they are written into your project:

.claude/fswalkthrough/
├── claude.md         — library overview and testing philosophy
└── fsharp-style.md   — F# API patterns and conventions

To put them in front of an agent, import the entrypoint from your CLAUDE.md:

@import .claude/fswalkthrough/claude.md

The files are rewritten whenever the installed package version changes, so the guidance an agent reads always matches the version you actually have. Treat .claude/fswalkthrough/ as generated — edits there are overwritten on the next build.

License

MIT

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.7 102 8/28/2026