module Bezel::Testing

Testing an application through its endpoint, in the test's own task, without sockets: requests built in memory go through every plug, the router and the actions, and the responses come back to be checked.

class TPages < Bezel::Controller
  controller
  def home(conn: Bezel::Conn) -> Bezel::Conn = render(conn, Bezel.html { |h| h.h1("Hello") })
end

class TRouter < Bezel::Router
  routes do
    get "/", TPages, :home
  end
end

class TApp < Bezel::Endpoint
  def self.plugs -> Array[Bezel::Plug] = [TRouter.new]
end

res = Bezel::Testing.get(TApp, "/")
Bezel::Testing.html_response(res, 200).has_text?("Hello")   # => true

Testing.get and friends make one request each; a Testing::Client keeps cookies between requests, as a browser does (sessions, the flash, a login), and follows redirects. The applications they run in are test ones whose CSRF check is off (App#skip_csrf, a flag the program sets and prod refuses), so that a test posts without a token; Testing.app(skip_csrf: false) tests the check itself.

The response helpers check the status and raise Test::AssertionFailed otherwise, with the body's start, so that a test fails as an assertion does.

src/testing.qz:35

Classes and modules

Class methods

def self.app(name: String = …, *, pool: PG::Pool? = …, skip_csrf: Bool = …) -> Bezel::App

A test application named name, without a database (pool to give one: PG::Testing's), the CSRF check off unless skip_csrf is false.

src/testing.qz:39

def self.get(endpoint: Type[Bezel::Endpoint], path: String, *, params: Hash[String, String | Array[String]] = …, headers: Hash[String, String] = …, app: Bezel::App = …) -> HTTP::Server::Response

The response of endpoint to a GET of path (a query in it, or params added to it).

src/testing.qz:45

def self.post(endpoint: Type[Bezel::Endpoint], path: String, *, params: Hash[String, String | Array[String]] = …, json: JSON::Value? = …, headers: Hash[String, String] = …, app: Bezel::App = …) -> HTTP::Server::Response

The response of endpoint to a POST of params as a form (or json as a JSON body) to path.

src/testing.qz:52

def self.put(endpoint: Type[Bezel::Endpoint], path: String, *, params: Hash[String, String | Array[String]] = …, json: JSON::Value? = …, headers: Hash[String, String] = …, app: Bezel::App = …) -> HTTP::Server::Response

A PUT: post's arguments.

src/testing.qz:58

def self.patch(endpoint: Type[Bezel::Endpoint], path: String, *, params: Hash[String, String | Array[String]] = …, json: JSON::Value? = …, headers: Hash[String, String] = …, app: Bezel::App = …) -> HTTP::Server::Response

A PATCH: post's arguments.

src/testing.qz:64

def self.delete(endpoint: Type[Bezel::Endpoint], path: String, *, params: Hash[String, String | Array[String]] = …, json: JSON::Value? = …, headers: Hash[String, String] = …, app: Bezel::App = …) -> HTTP::Server::Response

A DELETE: post's arguments.

src/testing.qz:70

def self.html_response(res: HTTP::Server::Response, status: Int = …) -> Bezel::Testing::Doc

The page of res, parsed (Testing::Doc), after checking that its status is status and that it is HTML.

src/testing.qz:77

def self.json_response(res: HTTP::Server::Response, status: Int = …) -> JSON::Value

The JSON of res, after checking that its status is status and that it is JSON.

src/testing.qz:86

def self.text_response(res: HTTP::Server::Response, status: Int = …) -> String

The text of res, after checking that its status is status.

src/testing.qz:98

def self.redirected_to(res: HTTP::Server::Response, status: Int? = …) -> String

Where res redirects to, after checking that its status is status (302 by default; any 3xx with status: nil).

src/testing.qz:105

def self.body_of(res: HTTP::Server::Response) -> String

The body of res as text (empty for none).

src/testing.qz:116