Class: Terminus::Browser

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Timeouts
Defined in:
lib/terminus/browser.rb

Constant Summary

Constants included from Timeouts

Timeouts::TIMEOUT

Instance Method Summary collapse

Methods included from Timeouts

#wait_with_timeout

Constructor Details

#initialize(controller) ⇒ Browser

Returns a new instance of Browser.



10
11
12
13
14
15
16
17
18
19
# File 'lib/terminus/browser.rb', line 10

def initialize(controller)
  @controller = controller
  @attributes = {}
  @docked     = false
  @frames     = Set.new
  @namespace  = Faye::Namespace.new
  @results    = {}
  
  add_timeout(:dead, Timeouts::TIMEOUT) { drop_dead! }
end

Instance Method Details

#===(params) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/terminus/browser.rb', line 21

def ===(params)
  return docked? if params == :docked
  return params == id if String === params
  return false if @parent
  return false unless @user_agent
  
  params.all? do |name, value|
    property = __send__(name).to_s
    case value
    when Regexp then property =~ value
    when String then property == value
    end
  end
end

#ask(command, retries = RETRY_LIMIT) ⇒ Object



36
37
38
39
40
41
42
43
# File 'lib/terminus/browser.rb', line 36

def ask(command, retries = RETRY_LIMIT)
  id = tell(command)
  result_hash = wait_with_timeout(:result) { result(id) }
  result_hash[:value]
rescue Timeouts::TimeoutError => e
  raise e if retries.zero?
  ask(command, retries - 1)
end

#bodyObject



45
46
47
# File 'lib/terminus/browser.rb', line 45

def body
  ask([:body])
end

#current_pathObject



49
50
51
52
# File 'lib/terminus/browser.rb', line 49

def current_path
  return nil unless url = @attributes['url']
  URI.parse(url).path
end

#current_urlObject



54
55
56
# File 'lib/terminus/browser.rb', line 54

def current_url
  @attributes['url'] || ''
end

#docked?Boolean

Returns:

  • (Boolean)


58
59
60
# File 'lib/terminus/browser.rb', line 58

def docked?
  @docked
end

#evaluate_script(expression) ⇒ Object



62
63
64
# File 'lib/terminus/browser.rb', line 62

def evaluate_script(expression)
  ask([:evaluate, expression])
end

#execute_script(expression) ⇒ Object



66
67
68
69
# File 'lib/terminus/browser.rb', line 66

def execute_script(expression)
  tell([:execute, expression])
  nil
end

#find(xpath, driver = nil) ⇒ Object



71
72
73
# File 'lib/terminus/browser.rb', line 71

def find(xpath, driver = nil)
  ask([:find, xpath, false]).map { |id| Node.new(self, id, driver) }
end

#frame!(frame_browser) ⇒ Object



75
76
77
# File 'lib/terminus/browser.rb', line 75

def frame!(frame_browser)
  @frames.add(frame_browser)
end

#frame_src(name) ⇒ Object



83
84
85
# File 'lib/terminus/browser.rb', line 83

def frame_src(name)
  ask([:frame_src, name])
end

#framesObject



79
80
81
# File 'lib/terminus/browser.rb', line 79

def frames
  @frames.to_a
end

#idObject



87
88
89
# File 'lib/terminus/browser.rb', line 87

def id
  @attributes['id']
end

#page_idObject



91
92
93
# File 'lib/terminus/browser.rb', line 91

def page_id
  @attributes['page']
end

#ping!(message) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/terminus/browser.rb', line 95

def ping!(message)
  p message if Terminus.debug
  remove_timeout(:dead)
  add_timeout(:dead, Timeouts::TIMEOUT) { drop_dead! }
  
  uri = @controller.rewrite_local(message['url'], @dock_host)
  message['url'] = uri.to_s
  
  @attributes = @attributes.merge(message)
  @user_agent = UserAgent.parse(message['ua'])
  detect_dock_host
  
  @infinite_redirect = message['infinite']
  
  if parent = message['parent']
    @parent = Terminus.browser(parent)
    @parent.frame!(self) unless @parent == self
  end
  
  @ping = true
end

#reset!Object



117
118
119
120
121
122
123
124
# File 'lib/terminus/browser.rb', line 117

def reset!
  if url = @attributes['url']
    uri = URI.parse(url)
    visit("http://#{uri.host}:#{uri.port}")
  end
  ask([:clear_cookies])
  @attributes.delete('url')
end

#response_headersObject



126
127
128
# File 'lib/terminus/browser.rb', line 126

def response_headers
  evaluate_script('TERMINUS_HEADERS')
end

#result(id) ⇒ Object



135
136
137
138
# File 'lib/terminus/browser.rb', line 135

def result(id)
  return nil unless @results.has_key?(id)
  {:value => @results.delete(id)}
end

#result!(message) ⇒ Object



130
131
132
133
# File 'lib/terminus/browser.rb', line 130

def result!(message)
  p message if Terminus.debug
  @results[message['commandId']] = message['result']
end

#return_to_dockObject



140
141
142
# File 'lib/terminus/browser.rb', line 140

def return_to_dock
  visit "http://#{@dock_host}:#{Terminus.port}/"
end

#sourceObject



144
145
146
# File 'lib/terminus/browser.rb', line 144

def source
  evaluate_script('TERMINUS_SOURCE')
end

#status_codeObject



148
149
150
# File 'lib/terminus/browser.rb', line 148

def status_code
  evaluate_script('TERMINUS_STATUS')
end

#tell(command) ⇒ Object



152
153
154
155
156
157
# File 'lib/terminus/browser.rb', line 152

def tell(command)
  id = @namespace.generate
  p [id, command] if Terminus.debug
  messenger.publish(channel, 'command' => command, 'commandId' => id)
  id
end

#to_sObject Also known as: inspect



181
182
183
# File 'lib/terminus/browser.rb', line 181

def to_s
  "<#{self.class.name} #{name} #{version} (#{os})>"
end

#visit(url, retries = RETRY_LIMIT) ⇒ Object



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/terminus/browser.rb', line 159

def visit(url, retries = RETRY_LIMIT)
  close_frames!
  uri = @controller.rewrite_remote(url, @dock_host)
  uri.host = @dock_host if uri.host =~ LOCALHOST
  tell([:visit, uri.to_s])
  wait_for_ping
  
  if @infinite_redirect
    @infinite_redirect = nil
    raise Capybara::InfiniteRedirectError
  end
  
rescue Timeouts::TimeoutError => e
  raise e if retries.zero?
  visit(url, retries - 1)
end

#wait_for_pingObject



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

def wait_for_ping
  @ping = false
  wait_with_timeout(:ping) { @ping or @dead }
end