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

JsonTest.pudu

Pudu53 lines3.0 KB

GitHub ↗
1/** @Test.Client.Json.Suite — requests and responses whose bodies are JSON */2module PuduLangHttpClient.Client.JsonTest34import 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.Client.Json as JsonClient11import PuduLangHttpClient.Content as Content12import PuduLangHttpClient as HttpClient13import PuduLangHttpClient.Request as Request14import PuduLangHttpClient.Response as Response15import PuduLangHttpClient.Stub as Stub1617/** @Test.Client.Json.Todo — one item, written and read through derived implementations */18type Todo = { id: Int, title: Str, done: Bool } derives Json.Encode, Json.Decode1920/// A response echoing the request's method, accept header, and body as JSON.21fn echo(request: Request.Request) -> HttpClient.Outcome[Response.Response] {22  let body = match request.content {23    case Some(found) => Result.unwrapOr(Content.readText(&found), "")24    case None => "\{\"id\":1,\"title\":\"" + Http.methodName(&request.method) + " " + match Request.header(&request, "accept") { case Some(found) => found case None => "" } + "\",\"done\":false\}"25  }26  Ok(Response.answer(&request, 200).withContent(Content.text(body, "application/json")))27}2829/// Runs the suite.30fn main() -> Int {31  let stub = Stub.create()32  Stub.when(&stub, |request: Request.Request| request.uri.endsWith("/todos/1"), echo)33  Stub.respond(&stub, Http.Get, "/broken", 200, "not json")34  let client = Client.create(Stub.send(&stub)).withBaseAddress("http://api.test/")35  let todo = Todo{id: 2, title: "write docs", done: true}36  let checks = Test.suite("Client.Json", &[37      Test.equals("a get reads a derived value and asks for JSON", &JsonClient.getFromJson[Todo](&client, "todos/1"), &Ok(Todo{id: 1, title: "GET application/json", done: false})),38      Test.equals("a get reads a document", &Result.map(JsonClient.getJson(&client, "todos/1"), |value: Json.Json| Json.field(&value, "id")), &Ok(Some(Json.Number(1)))),39      Test.equals("a delete reads a derived value", &JsonClient.deleteFromJson[Todo](&client, "todos/1"), &Ok(Todo{id: 1, title: "DELETE application/json", done: false})),40      Test.equals("a post, put, and patch write a derived value", &[JsonClient.postAsJson(&client, "todos/1", &todo), JsonClient.putAsJson(&client, "todos/1", &todo), JsonClient.patchAsJson(&client, "todos/1", &todo)].map(|outcome: HttpClient.Outcome[Response.Response]| Result.andThen(outcome, |r: Response.Response| Response.readAs[Todo](&r))), &[Ok(todo), Ok(todo), Ok(todo)]),41      Test.equals("a missing resource is unsuccessful", &JsonClient.getFromJson[Todo](&client, "todos/2"), &Err(HttpClient.Unsuccessful(404, "Not Found"))),42      Test.that("a body that is not JSON is unreadable", match JsonClient.getJson(&client, "broken") {43          case Err(HttpClient.Unreadable(_)) => true44          case _ => false45        })46    ])47  let ran = Test.run(&checks)48  for failure in Test.failuresOf(&ran) {49    let _reported = Io.writeErrorLine(failure)50  }51  Test.report(&ran)52}53