Pudu programming language
Menu
Package

@chrismichaelps / pudu-lang-httpclient

Named HTTP clients for Pudu: a client factory, delegating handlers, pooled keep-alive connections, handler lifetimes, logging, and resilience

0.1.1Apache-2.01

InstallClose

EndpointTest.pudu

Pudu49 lines3.1 KB

GitHub ↗
1/** @Test.Endpoint.Suite — declarative endpoints filled, sent, and read */2module PuduLangHttpClient.EndpointTest34import Std.Http as Http5import Std.Io as Io6import Std.Json as Json7import Std.Result as Result8import Std.Test as Test9import PuduLangHttpClient.Client as Client10import PuduLangHttpClient.Content as Content11import PuduLangHttpClient.Endpoint as Endpoint12import PuduLangHttpClient as HttpClient13import PuduLangHttpClient.Request as Request14import PuduLangHttpClient.Response as Response15import PuduLangHttpClient.Stub as Stub1617/** @Test.Endpoint.Todo — one item read and written through derived implementations */18type Todo = { userId: Int, title: Str } derives Json.Encode, Json.Decode1920/// Runs the suite.21fn main() -> Int {22  let stub = Stub.create()23  Stub.when(&stub, |request: Request.Request| request.uri.contains("/users/7/todos"), fn(request: Request.Request) -> HttpClient.Outcome[Response.Response] {24      let body = match request.content {25        case Some(found) => Result.unwrapOr(Content.readText(&found), "")26        case None => "\{\"userId\":7,\"title\":\"" + Http.methodName(&request.method) + "\"\}"27      }28      Ok(Response.answer(&request, 200).withContent(Content.text(body, "application/json")))29    })30  let client = Client.create(Stub.send(&stub)).withBaseAddress("https://api.test/")31  let listing = Endpoint.get("users/:userId/todos?q=:query")32  let creating = Endpoint.post("users/:userId/todos")33  let checks = Test.suite("Endpoint", &[34      Test.equals("slots are filled with encoded arguments", &Endpoint.fill(&listing, &[("query", "a b/c?"), ("userId", "7")]), &Ok("users/7/todos?q=a%20b%2Fc%3F")),35      Test.equals("a slot without an argument is refused", &Endpoint.fill(&listing, &[("userId", "7")]), &Err(HttpClient.InvalidRequest("the template slot 'query' has no argument"))),36      Test.equals("a colon that does not start a name is kept", &(Endpoint.fill(&Endpoint.get("health"), &[]), Endpoint.fill(&Endpoint.get("http://h:8080/a:/:_x:1"), &[])), &(Ok("health"), Ok("http://h:8080/a:/:_x:1"))),37      Test.equals("a call reads a derived value", &Endpoint.call[Todo](&client, &listing, &[("userId", "7"), ("query", "x")]), &Ok(Todo{userId: 7, title: "GET"})),38      Test.equals("a call with a body writes one", &Endpoint.callWith[Todo, Todo](&client, &creating, &[("userId", "7")], &Todo{userId: 7, title: "new"}), &Ok(Todo{userId: 7, title: "new"})),39      Test.equals("each verb names its method", &[Endpoint.get("x").method, Endpoint.post("x").method, Endpoint.put("x").method, Endpoint.patch("x").method, Endpoint.delete("x").method], &[Http.Get, Http.Post, Http.Put, Http.Patch, Http.Delete]),40      Test.equals("a failed status is not decoded", &Endpoint.call[Todo](&client, &Endpoint.delete("users/:id"), &[("id", "1")]), &Err(HttpClient.Unsuccessful(404, "Not Found"))),41      Test.equals("an endpoint request asks for JSON", &Result.map(Endpoint.request(&client, &creating, &[("userId", "1")]), |r: Request.Request| Request.header(&r, "accept")), &Ok(Some("application/json")))42    ])43  let ran = Test.run(&checks)44  for failure in Test.failuresOf(&ran) {45    let _reported = Io.writeErrorLine(failure)46  }47  Test.report(&ran)48}49