Class: Cybertrain::Test::Client

Inherits:
Object
  • Object
show all
Defined in:
cybertrain/test/client.rb

Overview

Drives an App (or a bare Router) in-process, the way Rails integration tests do: no socket, one Context per request, and a cookie jar that carries Set-Cookie values into the next request’s Cookie header.

Sessions, flash and CSRF behave as behind a browser: a form POST needs the authenticity_token from a page the client rendered. Redirects are not followed unless you call #follow_redirect!. Requires require "cybertrain/test/client" (which also loads Cybertrain::Test).

Examples:

# BLOG and BlogTest come from examples/blog/test/support/blog_test.rb
client = Cybertrain::Test::Client.new(BLOG)
client.get("/articles/new")
res = client.post("/articles", { "authenticity_token" => BlogTest.form_token(client),
                                 "article[title]" => "Hello Rails",
                                 "article[body]" => "I am on Rails! This is my first article." })
assert_response res, :see_other
client.follow_redirect!
assert_includes client.response.body, "Hello Rails"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app) ⇒ Client

Returns a new instance of Client.

Parameters:

  • app (Application) —

    a booted application (anything with call(ctx))



45
46
47
48
49
# File 'cybertrain/test/client.rb', line 45

def initialize(app)
  @app = app
  @response = Response.new
  @cookies = {}
end

Instance Attribute Details

#cookies ⇒ Hash{String => String} (readonly)

The cookie jar: name to raw (still percent-encoded) value.

Returns:

  • (Hash{String => String})


40
41
42
# File 'cybertrain/test/client.rb', line 40

def cookies
  @cookies
end

#response ⇒ Response (readonly)

The last response.

Returns:



35
36
37
# File 'cybertrain/test/client.rb', line 35

def response
  @response
end

Instance Method Details

#delete(path, params = {}, headers = {}) ⇒ Response

Parameters:

  • path (String)
  • params (Hash{String => String}) (defaults to: {})
  • headers (Hash{String => String}) (defaults to: {})

Returns:



94
95
96
# File 'cybertrain/test/client.rb', line 94

def delete(path, params = {}, headers = {})
  form_request("DELETE", path, params, headers)
end

#follow_redirect! ⇒ Response

GETs the Location of the last response; an absolute URL is reduced to its path so it stays inside the app.

Returns:

Raises:

  • (RuntimeError) —

    when the last response was not a redirect



127
128
129
130
131
132
133
134
# File 'cybertrain/test/client.rb', line 127

def follow_redirect!
  location = @response.header("Location")
  if location.nil? || @response.status < 300 || @response.status > 399
    raise "not a redirect: last response was #{@response.status}"
  end

  get(Client.local_path(location))
end

#get(path, headers = {}) ⇒ Response

Parameters:

  • path (String) —

    with its query string, if any ("/articles?page=2")

  • headers (Hash{String => String}) (defaults to: {})

Returns:



55
56
57
# File 'cybertrain/test/client.rb', line 55

def get(path, headers = {})
  request("GET", path, "", headers)
end

#patch(path, params = {}, headers = {}) ⇒ Response

Parameters:

  • path (String)
  • params (Hash{String => String}) (defaults to: {})
  • headers (Hash{String => String}) (defaults to: {})

Returns:



76
77
78
# File 'cybertrain/test/client.rb', line 76

def patch(path, params = {}, headers = {})
  form_request("PATCH", path, params, headers)
end

#post(path, params = {}, headers = {}) ⇒ Response

Sends params as a urlencoded form. Keys are written as a browser would ("article[title]"); for PATCH/DELETE from a form, add "_method" => "patch" or call #patch / #delete.

Parameters:

  • path (String)
  • params (Hash{String => String}) (defaults to: {})
  • headers (Hash{String => String}) (defaults to: {})

Returns:



67
68
69
# File 'cybertrain/test/client.rb', line 67

def post(path, params = {}, headers = {})
  form_request("POST", path, params, headers)
end

#put(path, params = {}, headers = {}) ⇒ Response

Parameters:

  • path (String)
  • params (Hash{String => String}) (defaults to: {})
  • headers (Hash{String => String}) (defaults to: {})

Returns:



85
86
87
# File 'cybertrain/test/client.rb', line 85

def put(path, params = {}, headers = {})
  form_request("PUT", path, params, headers)
end

#request(method, path, body = "", headers = {}) ⇒ Response

Runs one request through the app and returns (and remembers) its Response. Header names are lowercased as HttpParser would. Any method and body, e.g. a JSON request.

Examples:

client.request("POST", "/api/notes", '{"title":"x"}', { "content-type" => "application/json" })

Parameters:

  • method (String)
  • path (String)
  • body (String) (defaults to: "")
  • headers (Hash{String => String}) (defaults to: {})

Returns:



109
110
111
112
113
114
115
116
117
118
119
120
# File 'cybertrain/test/client.rb', line 109

def request(method, path, body = "", headers = {})
  head = {}
  headers.each { |k, v| head[k.downcase] = v }
  head["host"] = "www.example.com" unless head.key?("host")
  head["content-length"] = body.bytesize.to_s unless body.empty?
  head["cookie"] = cookie_header unless @cookies.empty? || head.key?("cookie")
  ctx = Context.new(Request.new(method, path, head, body, REMOTE_ADDR))
  @app.call(ctx)
  @response = ctx.response
  store_cookies(@response)
  @response
end