Class: Waw::WSpec::Browser

Inherits:
Object show all
Includes:
HTMLAnalysis
Defined in:
lib/waw/wspec/browser.rb

Overview

A fake browser for waw application testing

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from HTMLAnalysis

#all_external_links, #all_internal_links, #all_links, #all_tags, #decode_attributes_string, #each_tag, #first_link, #first_tag, #form, #has_link?, #has_tag?, #i_see?

Constructor Details

#initialize(location = nil) ⇒ Browser

Creates a browser instance



19
20
21
# File 'lib/waw/wspec/browser.rb', line 19

def initialize(location = nil)
  self.location = location if location
end

Instance Attribute Details

#last_action_resultObject (readonly)

The last action result



16
17
18
# File 'lib/waw/wspec/browser.rb', line 16

def last_action_result
  @last_action_result
end

#locationObject

Current browser location



10
11
12
# File 'lib/waw/wspec/browser.rb', line 10

def location
  @location
end

#responseObject (readonly)

Current server response



13
14
15
# File 'lib/waw/wspec/browser.rb', line 13

def response
  @response
end

Instance Method Details

#apply_action_routing(action, result) ⇒ Object

Applies the action routing for a given action



150
151
152
153
154
155
# File 'lib/waw/wspec/browser.rb', line 150

def apply_action_routing(action, result)
  @last_action_result = result
  action.routing.apply_on_browser(result, self) if action.routing
  result.extend(Waw::Routing::Methods)
  result
end

#baseObject

Looks for the base of the website



64
65
66
# File 'lib/waw/wspec/browser.rb', line 64

def base
  find_base
end

#clean_post_fetchObject

Private section Clean cache after fetch



183
184
185
# File 'lib/waw/wspec/browser.rb', line 183

def clean_post_fetch
  @base = nil
end

#click_href(href) ⇒ Object

Simulates a click. Support relative as well as absolute paths. Raises a URI::InvalidURIError if the given href seems invalid.



133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/waw/wspec/browser.rb', line 133

def click_href(href)
  uri = URI.parse(href)
  if uri.relative?
    go_relative(uri)
  else
    case uri.scheme
      when "http"
        self.location = href
      else
        raise ArgumentError, "This browser does not support #{href} location"
    end
  end
end

#contentsObject Also known as: browser_contents

Returns the current shown contents



90
91
92
# File 'lib/waw/wspec/browser.rb', line 90

def contents
  response ? response.read_body : nil
end

#dupObject

Duplicates this browser instance, with internal state



235
236
237
# File 'lib/waw/wspec/browser.rb', line 235

def dup
  Browser.new.install_context(@location, @response, @cookie)
end

#ensure_uri(uri) ⇒ Object

Ensures that something is an uri or convert it.

Raises:

  • (ArgumentError)


31
32
33
34
# File 'lib/waw/wspec/browser.rb', line 31

def ensure_uri(uri)
  raise ArgumentError, "ensure_uri: uri may not be nil" if uri.nil?
  is_uri?(uri) ? uri : URI.parse(uri)
end

#extract_base(uri) ⇒ Object

Extracts the base of an URI

Raises:

  • (ArgumentError)


37
38
39
40
# File 'lib/waw/wspec/browser.rb', line 37

def extract_base(uri)
  raise ArgumentError, "extract_base: uri may not be nil" if uri.nil?
  ensure_uri("#{uri.scheme}://#{uri.host}#{uri.port ? (':' + uri.port.to_s) : ''}/")
end

#fetch(uri, method = :get, data = {}, limit = 10) ⇒ Object

Fetchs a given location



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/waw/wspec/browser.rb', line 188

def fetch(uri, method = :get, data = {}, limit = 10)
  # You should choose better exception.
  raise 'HTTP redirect too deep' if limit == 0

  # Fetch the result at that location
  location = ensure_uri(uri)
  response = Net::HTTP.start(location.host, location.port) do |http|
    headers = @cookie ? {'Cookie' => @cookie} : {}
    case method
      when :get
        path = location.path
        path += '?' + location.query if location.query
        http.request_get(path, headers)
      when :post
        req = Net::HTTP::Post.new(location.path, headers)
        req.form_data = data.unsymbolize_keys
        http.request(req)
      else
        raise ArgumentError, "Invalid fetch method #{method}"
    end
  end
  
  # If a cookie is requested save it
  @cookie = response['set-cookie']
  
  # Catch the response, following redirections
  result = case response
    when Net::HTTPRedirection 
      fetch(response['location'] || response['Location'], :get, {}, limit - 1)
    else
      [location, response]
  end
  
  # Cleans cache and returns result
  clean_post_fetch
  result
end

#find_baseObject

Finds the base of the current location



69
70
71
72
73
74
75
# File 'lib/waw/wspec/browser.rb', line 69

def find_base
  if contents and (found = tag("base", {:href => /.*/}, contents))
    ensure_uri(found[:href])
  else
    extract_base(location)
  end
end

#go_relative(uri) ⇒ Object

Go to a relative position



98
99
100
# File 'lib/waw/wspec/browser.rb', line 98

def go_relative(uri)
  self.location = relative_uri(uri)
end

#headers_fetch(uri) ⇒ Object

Fetches the headers only and returns it without keeping the result in browser state



114
115
116
117
118
119
120
121
122
123
124
# File 'lib/waw/wspec/browser.rb', line 114

def headers_fetch(uri)
  # Fetch the result at that location
  if (loc = ensure_uri(uri)).relative?
    headers_fetch(relative_uri(uri))
  else
    response = Net::HTTP.start(loc.host, loc.port) do |http|
      headers = @cookie ? {'Cookie' => @cookie} : {}
      http.head(loc.path, headers)
    end
  end
end

#install_context(location, response, cookie) ⇒ Object

Installs the browser context



229
230
231
232
# File 'lib/waw/wspec/browser.rb', line 229

def install_context(location, response, cookie)
  @location, @response, @cookie = location, response, cookie
  self
end

#invoke_action(action, args = {}) ⇒ Object

Invokes an action server side, decodes json response an applies action routing. Returns the action result.

Raises:

  • (ArgumentError)


159
160
161
162
163
164
165
# File 'lib/waw/wspec/browser.rb', line 159

def invoke_action(action, args = {})
  raise ArgumentError, "Browser.invoke_action expects an ActionController::Action as first parameter"\
    unless ::Waw::ActionController::Action===action
  location, response = fetch(relative_uri(action.uri), :post, args)
  apply_action_routing(action, JSON.parse(response.body))
  self.response
end

#invoke_service(service, args = {}) ⇒ Object

Invokes a service server side and returns HTTP response

Raises:

  • (ArgumentError)


168
169
170
171
172
173
# File 'lib/waw/wspec/browser.rb', line 168

def invoke_service(service, args = {})
  raise ArgumentError, "Browser.invoke_service expects a String as first parameter"\
    unless String===service
  location, response = fetch(relative_uri(service), :post, args)
  self.response
end

#is200Object Also known as: is200?

Checks if the last request waw answered by a 200 OK



84
85
86
# File 'lib/waw/wspec/browser.rb', line 84

def is200
  (Net::HTTPSuccess === response)
end

#is404Object Also known as: is404?

Checks if the last request waw answered by a 404 not found



78
79
80
# File 'lib/waw/wspec/browser.rb', line 78

def is404
  (Net::HTTPNotFound === response)
end

#is_uri?(uri) ⇒ Boolean

Checks if something is an URI

Returns:



26
27
28
# File 'lib/waw/wspec/browser.rb', line 26

def is_uri?(uri)
  URI::Generic===uri
end

#refreshObject

Refreshes the browser



127
128
129
# File 'lib/waw/wspec/browser.rb', line 127

def refresh
  self.location = location
end

#relative_uri(uri) ⇒ Object

Computes the new location if a relative uri is followed

Raises:

  • (ArgumentError)


43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/waw/wspec/browser.rb', line 43

def relative_uri(uri)
  raise ArgumentError, "relative_uri: uri may not be nil" if uri.nil?
  uri = ensure_uri(uri)
  new_location = nil
  if uri.path[0...1] == '/'
    new_location = base.dup
    new_location.path = uri.path
    new_location.query = uri.query
    new_location
  else
    new_location = base.dup
    new_location.path = File.dirname(new_location.path) + '/' + uri.path
    new_location.query = uri.query
    new_location
  end
  new_location
end

#server_invoke(service, args, decode_method = nil) ⇒ Object

Invokes a server service with arguments and decoding method



176
177
178
179
# File 'lib/waw/wspec/browser.rb', line 176

def server_invoke(service, args, decode_method = nil)
  location, response = fetch(relative_uri(service), :post, args)
  response
end