Module: RemoteHttpTesting

Defined in:
lib/remote_http_testing.rb,
lib/remote_http_testing/version.rb

Overview

This module helps write integration tests which make HTTP requests to remote servers. Unlike Rack::Test, it doesn’t make requests to an in-process Rack server. Include it into your test case class.

This module’s API should match the API of Rack::Test. In the future, we should consider whether it’s just as easy to amend Rack::Test so that it can make requests to remote servers, since Rack::Test has supoprt for other desirable features.

Constant Summary collapse

VERSION =
"0.1.4"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#headers_for_requestObject

You can set this to be a Hash, and these HTTP headers will be added to all requests.



19
20
21
# File 'lib/remote_http_testing.rb', line 19

def headers_for_request
  @headers_for_request
end

#last_requestObject

Returns the value of attribute last_request.



17
18
19
# File 'lib/remote_http_testing.rb', line 17

def last_request
  @last_request
end

#last_responseObject

Returns the value of attribute last_response.



16
17
18
# File 'lib/remote_http_testing.rb', line 16

def last_response
  @last_response
end

Class Method Details

.populate_uri_with_querystring(uri, query_string_hash) ⇒ Object



104
105
106
107
108
# File 'lib/remote_http_testing.rb', line 104

def self.populate_uri_with_querystring(uri, query_string_hash)
  return if query_string_hash.nil? || query_string_hash == ""
  key_values = query_string_hash.map { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
  uri.query = uri.query.to_s.empty? ? key_values : "&" + key_values # uri.query can be nil
end

Instance Method Details

#adjust_response_encoding(response) ⇒ Object



139
140
141
142
143
144
145
# File 'lib/remote_http_testing.rb', line 139

def adjust_response_encoding(response)
  unless response["content-type"].nil?
    split_response = response["content-type"].split("charset=")
    response.body = response.body.force_encoding(split_response[1]) unless split_response[1].nil?
  end
  response
end

#assert_content_include?(string) ⇒ Boolean

Returns:

  • (Boolean)


114
115
116
# File 'lib/remote_http_testing.rb', line 114

def assert_content_include?(string)
  assert_block("Failed: content did not include the string: #{string}") { content_include?(string) }
end

#assert_content_not_include?(string) ⇒ Boolean

Returns:

  • (Boolean)


118
119
120
121
122
# File 'lib/remote_http_testing.rb', line 118

def assert_content_not_include?(string)
  assert_block("Failed: content should not have included this string but it did: #{string}") do
    !content_include?(string)
  end
end

#assert_select(css_selector, options = {}) ⇒ Object

This is intended to provide similar functionality to the Rails assert_select helper. With no additional options, “assert_select(‘my_selector’)” just ensures there’s an element matching the given selector, assuming the response is structured like XML.



132
133
134
135
136
137
# File 'lib/remote_http_testing.rb', line 132

def assert_select(css_selector, options = {})
  raise "You're trying to assert_select when there hasn't been a response yet." unless dom_response
  assert_block("There were no elements matching #{css_selector}") do
    !dom_response.css(css_selector).empty?
  end
end

#assert_status(status_code, helpful_message = last_response.body) ⇒ Object



110
111
112
# File 'lib/remote_http_testing.rb', line 110

def assert_status(status_code, helpful_message = last_response.body)
  assert_equal(status_code.to_i, last_response.code.to_i, helpful_message)
end

#content_include?(string) ⇒ Boolean

Returns:

  • (Boolean)


124
125
126
127
# File 'lib/remote_http_testing.rb', line 124

def content_include?(string)
  raise "No request was made yet, or no response was returned" unless last_response
  last_response.body.include?(string)
end

#create_request(url, http_method, params = {}, request_body = nil) ⇒ Object

Used by perform_request. This can be overridden by integration tests to append things to the request, like adding a login cookie.



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/remote_http_testing.rb', line 75

def create_request(url, http_method, params = {}, request_body = nil)
  uri = URI.parse(url)
  RemoteHttpTesting::populate_uri_with_querystring(uri, params)
  request_class = case http_method
    when :delete then Net::HTTP::Delete
    when :get then Net::HTTP::Get
    when :post then Net::HTTP::Post
    when :put then Net::HTTP::Put
    when :patch then Net::HTTP::Patch
  end
  request = request_class.new(uri.request_uri)
  request.body = request_body if request_body
  headers_for_request.each { |key, value| request.add_field(key, value) } if headers_for_request
  request
end

#current_serverObject



42
# File 'lib/remote_http_testing.rb', line 42

def current_server() (@temporary_server || self.server) end

#delete(url, params = {}, request_body = nil) ⇒ Object



67
# File 'lib/remote_http_testing.rb', line 67

def delete(url, params = {}, request_body = nil) perform_request(url, :delete, params, request_body) end

#dom_responseObject



24
25
26
# File 'lib/remote_http_testing.rb', line 24

def dom_response
  @dom_response ||= Nokogiri::HTML(last_response.body)
end

#ensure_reachable!(server_url, server_display_name = nil) ⇒ Object

Prints out an error message and exits the program (to avoid running subsequent tests which are just going to fail) if the server is not reachable.



46
47
48
49
50
51
52
# File 'lib/remote_http_testing.rb', line 46

def ensure_reachable!(server_url, server_display_name = nil)
  unless server_reachable?(server_url)
    failure_message = server_display_name ? "#{server_display_name} at #{server_url}" : server_url
    puts "FAIL: Unable to connect to #{failure_message}"
    exit 1
  end
end

#get(url, params = {}, request_body = nil) ⇒ Object



68
# File 'lib/remote_http_testing.rb', line 68

def get(url, params = {}, request_body = nil) perform_request(url, :get, params, request_body) end

#json_responseObject



28
29
30
# File 'lib/remote_http_testing.rb', line 28

def json_response
  @json_response ||= JSON.parse(last_response.body)
end

#patch(url, params = {}, request_body = nil) ⇒ Object



71
# File 'lib/remote_http_testing.rb', line 71

def patch(url, params = {}, request_body = nil) perform_request(url, :patch, params, request_body) end

#perform_request(url, http_method, params = {}, request_body = nil) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/remote_http_testing.rb', line 91

def perform_request(url, http_method, params = {}, request_body = nil)
  self.last_response = @dom_response = @json_response = nil
  url = current_server + url
  uri = URI.parse(url)
  self.last_request = create_request(url, http_method, params, request_body)
  begin
    response = Net::HTTP.new(uri.host, uri.port).request(self.last_request)
  rescue Errno::ECONNREFUSED => error
    raise "Unable to connect to #{self.current_server}"
  end
  self.last_response = adjust_response_encoding(response)
end

#post(url, params = {}, request_body = nil) ⇒ Object



69
# File 'lib/remote_http_testing.rb', line 69

def post(url, params = {}, request_body = nil) perform_request(url, :post, params, request_body) end

#put(url, params = {}, request_body = nil) ⇒ Object



70
# File 'lib/remote_http_testing.rb', line 70

def put(url, params = {}, request_body = nil) perform_request(url, :put, params, request_body) end

#serverObject

Define this method to return the URL of the HTTP server to talk to, e.g. “localhost:3000



22
# File 'lib/remote_http_testing.rb', line 22

def server() raise "You need to define a server() method." end

#server_reachable?(server_url) ⇒ Boolean

True if the server is reachable. Fails if the server can’t be contacted within 2 seconds.

Returns:

  • (Boolean)


55
56
57
58
59
60
61
62
63
64
65
# File 'lib/remote_http_testing.rb', line 55

def server_reachable?(server_url)
  uri = URI.parse(server_url)
  request = Net::HTTP.new(uri.host, uri.port)
  request.read_timeout = 2
  response = nil
  begin
    response = request.request(create_request(server_url, :get))
  rescue StandardError, Timeout::Error
  end
  !response.nil? && response.code.to_i == 200
end

#use_server(server, &block) ⇒ Object

Temporarily make requests to a different server than the one specified by your server() method.



33
34
35
36
37
38
39
40
# File 'lib/remote_http_testing.rb', line 33

def use_server(server, &block)
  @temporary_server = server
  begin
    yield
  ensure
    @temporary_server = nil
  end
end