webkit_remote 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -136,6 +136,42 @@ Again, release the WebKit state.
136
136
  client.clear_all
137
137
  ```
138
138
 
139
+ ### See Network Traffic
140
+
141
+ Record network requests and reload the page.
142
+
143
+ ```ruby
144
+ client.page_events = true
145
+ client.network_events = true
146
+ client.clear_cache
147
+ client.clear_cookies
148
+ client.navigate_to 'http://translate.google.com'
149
+ client.wait_for(type: WebkitRemote::Event::PageLoaded).last
150
+ ```
151
+
152
+ See the network traffic generated by the page.
153
+
154
+ ```ruby
155
+ client.network_resources.length
156
+ resource = client.network_resources.first
157
+ resource.canceled
158
+ resource.type
159
+ resource.request.url
160
+ resource.request.headers
161
+ resource.response.mime_type
162
+ resource.response.url
163
+ resource.response.status
164
+ resource.response.headers
165
+ resource.body
166
+ ```
167
+
168
+ Clean up.
169
+
170
+ ```ruby
171
+ client.clear_all
172
+ ```
173
+
174
+
139
175
  ### Close the Browser
140
176
 
141
177
  ```ruby
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.1
1
+ 0.3.2
@@ -1,3 +1,5 @@
1
+ require 'base64'
2
+
1
3
  module WebkitRemote
2
4
 
3
5
  class Event
@@ -129,7 +131,8 @@ class NetworkMemoryCacheHit < WebkitRemote::Event
129
131
  super
130
132
 
131
133
  if raw_data['resource']
132
- @cache_data = raw_data['resource']
134
+ @cache_data = WebkitRemote::Client::NetworkCacheEntry.new(
135
+ raw_data['resource'])
133
136
  end
134
137
  @document_url = raw_data['documentURL']
135
138
  if raw_data['initiator']
@@ -324,6 +327,24 @@ class NetworkResource
324
327
  @initiator = nil
325
328
  @canceled = false
326
329
  @last_event = nil
330
+ @body = false
331
+ end
332
+
333
+ # @return [String] the contents of the resource
334
+ def body
335
+ @body ||= body!
336
+ end
337
+
338
+ # Re-fetches the resource from the Webkit remote debugging server.
339
+ #
340
+ # @return [String] the contents of the resource
341
+ def body!
342
+ result = @client.rpc.call 'Network.getResponseBody', requestId: @remote_id
343
+ if result['base64Encoded']
344
+ @body = Base64.decode64 result['body']
345
+ else
346
+ @body = result['body']
347
+ end
327
348
  end
328
349
 
329
350
  # @private Rely on the event processing code to set this property.
@@ -168,7 +168,7 @@ class RemoteObject
168
168
  # @return [Webkit::Client::RemoteObject] self
169
169
  def release
170
170
  return if @released
171
- @rpc.call 'Runtime.releaseObject', objectId: @remote_id
171
+ @client.rpc.call 'Runtime.releaseObject', objectId: @remote_id
172
172
  @group.remove self
173
173
  released!
174
174
  end
@@ -191,7 +191,7 @@ class RemoteObject
191
191
  # @return [Hash<Symbol, Webkit::Client::RemoteProperty>] frozen Hash containg
192
192
  # the object's properties
193
193
  def properties!
194
- result = @rpc.call 'Runtime.getProperties', objectId: @remote_id
194
+ result = @client.rpc.call 'Runtime.getProperties', objectId: @remote_id
195
195
  @properties = Hash[
196
196
  result['result'].map do |raw_property|
197
197
  property = WebkitRemote::Client::RemoteProperty.new raw_property, self
@@ -218,7 +218,7 @@ class RemoteObject
218
218
  { value: arg }
219
219
  end
220
220
  end
221
- result = @rpc.call 'Runtime.callFunctionOn', objectId: @remote_id,
221
+ result = @client.rpc.call 'Runtime.callFunctionOn', objectId: @remote_id,
222
222
  functionDeclaration: function_expression, arguments: call_args,
223
223
  returnByValue: false
224
224
  object = WebkitRemote::Client::RemoteObject.for result['result'], @client,
@@ -277,7 +277,6 @@ class RemoteObject
277
277
  def initialize(raw_object, group)
278
278
  @group = group
279
279
  @client = group.client
280
- @rpc = client.rpc
281
280
  @released = false
282
281
 
283
282
  @raw_data = raw_object
@@ -329,7 +328,7 @@ class RemoteObjectGroup
329
328
  object.release
330
329
  end
331
330
  else
332
- @rpc.call 'Runtime.releaseObjectGroup', objectGroup: name
331
+ @client.rpc.call 'Runtime.releaseObjectGroup', objectGroup: name
333
332
  end
334
333
 
335
334
  @released = true
@@ -359,7 +358,6 @@ class RemoteObjectGroup
359
358
  def initialize(name, client)
360
359
  @name = name
361
360
  @client = client
362
- @rpc = client.rpc
363
361
  # TODO(pwnall): turn @objects into a set once equality is working
364
362
  @objects = {}
365
363
  @released = false
@@ -17,6 +17,7 @@ class Client
17
17
  raise ArgumentError, 'Target tab not specified'
18
18
  end
19
19
  @rpc = WebkitRemote::Rpc.new opts
20
+ @debug_url = @rpc.debug_url
20
21
  @browser = tab.browser
21
22
  @close_browser = opts.fetch :close_browser, false
22
23
  @closed = false
@@ -145,6 +146,14 @@ END_METHOD
145
146
  def clear_modules
146
147
  # NOTE: this gets called after all the module cleaners complete
147
148
  end
149
+
150
+ # Debugging output.
151
+ def inspect
152
+ result = self.to_s
153
+ result[-1, 0] =
154
+ " server=#{@debug_url.inspect} closed=#{@closed.inspect}"
155
+ result
156
+ end
148
157
  end # class WebkitRemote::Client
149
158
 
150
159
  end # namespace WebkitRemote
@@ -23,7 +23,8 @@ class Rpc
23
23
  @events = []
24
24
 
25
25
  self.class.em_start
26
- @web_socket = Faye::WebSocket::Client.new tab.debug_url
26
+ @debug_url = tab.debug_url
27
+ @web_socket = Faye::WebSocket::Client.new @debug_url
27
28
  setup_web_socket
28
29
  end
29
30
 
@@ -91,6 +92,9 @@ class Rpc
91
92
  attr_reader :closed
92
93
  alias_method :closed?, :closed
93
94
 
95
+ # @return [String] points to this client's Webkit remote debugging server
96
+ attr_reader :debug_url
97
+
94
98
  # Hooks up the event handlers of the WebSocket client.
95
99
  def setup_web_socket
96
100
  @web_socket.onopen = lambda do |event|
@@ -14,7 +14,7 @@ end
14
14
 
15
15
  # Cache headers for Network domain testing.
16
16
  use Rack::StaticCache, urls: ['/html', '/js', '/png'], root: 'test/fixtures',
17
- versioning: false
17
+ versioning: false, duration: 24 * 60 * 60
18
18
  app = lambda do |env|
19
19
  [
20
20
  200,
@@ -2,6 +2,7 @@
2
2
  <html>
3
3
  <head>
4
4
  <title>WebkitRemote Network test</title>
5
+ <script type="text/javascript" src="../js/network_not_found.js"></script>
5
6
  <script type="text/javascript" src="../js/network.js"></script>
6
7
  </head>
7
8
  <body>
data/test/helper.rb CHANGED
@@ -22,8 +22,8 @@ require 'thread'
22
22
  Thread.abort_on_exception = true
23
23
 
24
24
  # Launch a dev server and wait until it starts.
25
- pid = Process.spawn 'bundle exec puma --port 9969 --quiet test/fixtures/config.ru',
26
- :in => '/dev/null', :out => '/dev/null'
25
+ pid = Process.spawn 'bundle exec puma --port 9969 --quiet --threads 1:1 ' +
26
+ 'test/fixtures/config.ru', :in => '/dev/null', :out => '/dev/null'
27
27
  Process.detach pid
28
28
  at_exit { Process.kill 'TERM', pid }
29
29
  loop do
@@ -14,7 +14,8 @@ describe WebkitRemote::Client::Network do
14
14
  before :all do
15
15
  @client.network_events = false
16
16
  @client.navigate_to fixture_url(:network)
17
- @events = @client.wait_for type: WebkitRemote::Event::ConsoleMessage
17
+ @events = @client.wait_for type: WebkitRemote::Event::ConsoleMessage,
18
+ level: :log
18
19
  end
19
20
 
20
21
  it 'does not receive any network event' do
@@ -38,7 +39,8 @@ describe WebkitRemote::Client::Network do
38
39
  @client.disable_cache = true
39
40
  @client.network_events = true
40
41
  @client.navigate_to fixture_url(:network)
41
- @events = @client.wait_for type: WebkitRemote::Event::ConsoleMessage
42
+ @events = @client.wait_for type: WebkitRemote::Event::ConsoleMessage,
43
+ level: :log
42
44
  @requests = @events.select do |event|
43
45
  event.kind_of? WebkitRemote::Event::NetworkRequest
44
46
  end
@@ -51,6 +53,9 @@ describe WebkitRemote::Client::Network do
51
53
  @chunks = @events.select do |event|
52
54
  event.kind_of? WebkitRemote::Event::NetworkData
53
55
  end
56
+ @failures = @events.select do |event|
57
+ event.kind_of? WebkitRemote::Event::NetworkFailure
58
+ end
54
59
  @resources = @client.network_resources
55
60
  end
56
61
 
@@ -58,7 +63,7 @@ describe WebkitRemote::Client::Network do
58
63
  @requests.wont_be :empty?
59
64
  end
60
65
 
61
- it 'parses initial requests inside NetworkRequest events correctly' do
66
+ it 'parses initial requests inside NetworkRequest events' do
62
67
  @requests[0].request.must_be_kind_of WebkitRemote::Client::NetworkRequest
63
68
  @requests[0].request.url.must_equal fixture_url(:network)
64
69
  @requests[0].request.method.must_equal :get
@@ -68,18 +73,24 @@ describe WebkitRemote::Client::Network do
68
73
  @requests[0].initiator.stack_trace.must_equal nil
69
74
  end
70
75
 
71
- it 'parses derived requests inside NetworkRequest events correctly' do
76
+ it 'parses derived requests inside NetworkRequest events' do
72
77
  @requests[1].document_url.must_equal fixture_url(:network)
73
78
  @requests[1].request.must_be_kind_of WebkitRemote::Client::NetworkRequest
74
- @requests[1].request.url.must_equal fixture_url(:network, :js)
79
+ @requests[1].request.url.must_equal fixture_url(:network_not_found, :js)
75
80
  @requests[1].initiator.type.must_equal :parser
76
81
  @requests[1].initiator.stack_trace.must_equal nil
77
82
 
78
83
  @requests[2].document_url.must_equal fixture_url(:network)
79
84
  @requests[2].request.must_be_kind_of WebkitRemote::Client::NetworkRequest
80
- @requests[2].request.url.must_equal fixture_url(:network, :png)
81
- @requests[2].initiator.type.must_equal :script
82
- @requests[2].initiator.stack_trace.must_equal [
85
+ @requests[2].request.url.must_equal fixture_url(:network, :js)
86
+ @requests[2].initiator.type.must_equal :parser
87
+ @requests[2].initiator.stack_trace.must_equal nil
88
+
89
+ @requests[3].document_url.must_equal fixture_url(:network)
90
+ @requests[3].request.must_be_kind_of WebkitRemote::Client::NetworkRequest
91
+ @requests[3].request.url.must_equal fixture_url(:network, :png)
92
+ @requests[3].initiator.type.must_equal :script
93
+ @requests[3].initiator.stack_trace.must_equal [
83
94
  {column: 7, line: 10, function: "", url: fixture_url(:network, :js)},
84
95
  {column: 3, line: 11, function: "", url: fixture_url(:network, :js)},
85
96
  ]
@@ -89,7 +100,7 @@ describe WebkitRemote::Client::Network do
89
100
  @responses.wont_be :empty?
90
101
  end
91
102
 
92
- it 'parses initial NetworkRequest and NetworkResponse events correctly' do
103
+ it 'parses initial NetworkRequest and NetworkResponse events' do
93
104
  @responses[0].type.must_equal :document
94
105
  @requests[0].initiator.type.must_equal :other
95
106
  @requests[0].loader_id.wont_be :empty?
@@ -99,7 +110,7 @@ describe WebkitRemote::Client::Network do
99
110
  @requests[0].timestamp.must_be :<, @responses[0].timestamp
100
111
  end
101
112
 
102
- it 'parses the initial response inside NetworkResponse events correctly' do
113
+ it 'parses the initial response inside a NetworkResponse event' do
103
114
  @responses[0].type.must_equal :document
104
115
  @responses[0].response.
105
116
  must_be_kind_of WebkitRemote::Client::NetworkResponse
@@ -116,16 +127,34 @@ describe WebkitRemote::Client::Network do
116
127
  @responses[0].response.connection_reused.must_equal false
117
128
  end
118
129
 
119
- it 'parses derived responses inside NetworkResponse events correctly' do
130
+ it 'parses a 404 response inside a NetworkResponse event' do
131
+ @responses[1].type.must_equal :script
132
+ @responses[1].response.
133
+ must_be_kind_of WebkitRemote::Client::NetworkResponse
134
+ @responses[1].response.url.
135
+ must_equal fixture_url(:network_not_found, :js)
136
+ @responses[1].response.status.must_equal 404
137
+ @responses[1].response.status_text.must_match /not found/i
138
+ @responses[1].response.headers.must_include 'X-Unit-Test'
139
+ @responses[1].response.headers['X-Unit-Test'].must_equal 'webkit-remote'
140
+ @responses[1].response.mime_type.must_equal 'text/plain'
141
+ @responses[1].response.request_headers.must_include 'User-Agent'
142
+ @responses[1].response.request_headers['User-Agent']
143
+ .must_match(/webkit/i)
144
+ @responses[1].response.from_cache.must_equal false
145
+ end
146
+
147
+ it 'parses derived responses inside NetworkResponse events' do
120
148
  @responses[1].type.must_equal :script
121
- @responses[2].type.must_equal :xhr
149
+ @responses[2].type.must_equal :script
150
+ @responses[3].type.must_equal :xhr
122
151
  end
123
152
 
124
153
  it 'receives NetworkData events' do
125
154
  @chunks.wont_be :empty?
126
155
  end
127
156
 
128
- it 'parses NetworkData events correctly' do
157
+ it 'parses NetworkData events' do
129
158
  @chunks[0].resource.must_equal @chunks[0].resource
130
159
  @chunks[0].data_length.
131
160
  must_equal File.read(fixture_path(:network)).length
@@ -136,9 +165,19 @@ describe WebkitRemote::Client::Network do
136
165
  @loads.wont_be :empty?
137
166
  end
138
167
 
139
- it 'parses NetworkLoad events correctly' do
168
+ it 'parses NetworkLoad events' do
140
169
  @loads[0].resource.must_equal @requests[0].resource
141
- @loads[1].resource.must_equal @requests[1].resource
170
+ @loads[1].resource.must_equal @requests[2].resource
171
+ end
172
+
173
+ it 'receives NetworkFailure events' do
174
+ @failures.wont_be :empty?
175
+ end
176
+
177
+ it 'parses NetworkFailure events' do
178
+ @failures[0].resource.must_equal @requests[1].resource
179
+ @failures[0].error.wont_equal nil
180
+ @failures[0].canceled.must_equal true
142
181
  end
143
182
 
144
183
  it 'collects request and response data in NetworkResources' do
@@ -148,12 +187,79 @@ describe WebkitRemote::Client::Network do
148
187
  @resources[1].type.must_equal :script
149
188
  @resources[1].document_url.must_equal fixture_url(:network)
150
189
  @resources[1].initiator.must_equal @requests[1].initiator
151
- @resources[1].canceled.must_equal false
152
- @resources[1].error.must_equal nil
153
- @resources[1].last_event.must_equal @loads[1]
190
+ @resources[1].canceled.must_equal true
191
+ @resources[1].error.must_equal @failures[0].error
192
+ @resources[1].last_event.must_equal @failures[0]
154
193
  @resources[1].client.must_equal @client
155
194
 
195
+ @resources[2].must_equal @requests[2].resource
196
+ @resources[2].request.must_equal @requests[2].request
197
+ @resources[2].response.must_equal @responses[2].response
198
+ @resources[2].type.must_equal :script
199
+ @resources[2].document_url.must_equal fixture_url(:network)
200
+ @resources[2].initiator.must_equal @requests[2].initiator
201
+ @resources[2].canceled.must_equal false
202
+ @resources[2].error.must_equal nil
203
+ @resources[2].last_event.must_equal @loads[1]
204
+ @resources[2].client.must_equal @client
205
+
156
206
  @resources[-1].last_event.must_equal @chunks[-1]
157
207
  end
208
+
209
+ it 'retrieves the body for a text NetworkResource' do
210
+ @resources[0].body.must_equal File.read(fixture_path(:network))
211
+ end
212
+
213
+ it 'retrieves the body for a binary NetworkResource' do
214
+ skip 'waiting for http://crbug.com/160397'
215
+ @resources[2].body.must_equal File.binread(fixture_path(:network, :png))
216
+ end
217
+ end
218
+
219
+ describe 'and a cached request' do
220
+ before :all do
221
+ @client.disable_cache = false
222
+ @client.navigate_to fixture_url(:network)
223
+ @client.wait_for type: WebkitRemote::Event::ConsoleMessage, level: :log
224
+ @client.clear_all
225
+
226
+ @client.network_events = true
227
+ @client.navigate_to fixture_url(:network)
228
+ @events = @client.wait_for type: WebkitRemote::Event::ConsoleMessage,
229
+ level: :log
230
+ @requests = @events.select do |event|
231
+ event.kind_of? WebkitRemote::Event::NetworkRequest
232
+ end
233
+ @responses = @events.select do |event|
234
+ event.kind_of? WebkitRemote::Event::NetworkResponse
235
+ end
236
+ @loads = @events.select do |event|
237
+ event.kind_of? WebkitRemote::Event::NetworkLoad
238
+ end
239
+ @chunks = @events.select do |event|
240
+ event.kind_of? WebkitRemote::Event::NetworkData
241
+ end
242
+ @hits = @events.select do |event|
243
+ event.kind_of? WebkitRemote::Event::NetworkCacheHit
244
+ end
245
+ @memory_hits = @events.select do |event|
246
+ event.kind_of? WebkitRemote::Event::NetworkMemoryCacheHit
247
+ end
248
+
249
+ @resources = @client.network_resources
250
+ end
251
+
252
+ it 'receives NetworkCacheHit events' do
253
+ @hits.wont_be :empty?
254
+ end
255
+
256
+ it 'parses NetworkCacheHits events' do
257
+ @hits[0].resource.must_equal @requests[2].resource
258
+ end
259
+
260
+ it 'receives NetworkMemoryCacheHit events' do
261
+ skip 'waiting for http://crbug.com/160404'
262
+ @memory_hits.wont_be :empty?
263
+ end
158
264
  end
159
265
  end
@@ -32,6 +32,10 @@ describe WebkitRemote::Client do
32
32
  it 'closes the browser master debugging session' do
33
33
  @browser.closed?.must_equal true
34
34
  end
35
+
36
+ it 'still retuns a good inspect string' do
37
+ @client.inspect.must_match(/<.*WebkitRemote::Client.*>/)
38
+ end
35
39
  end
36
40
 
37
41
  describe 'each_event' do
@@ -102,5 +106,12 @@ describe WebkitRemote::Client do
102
106
  @client.clear_all
103
107
  end
104
108
  end
109
+
110
+ describe 'inspect' do
111
+ it 'includes the debugging URL and closed flag' do
112
+ @client.inspect.must_match(
113
+ /<WebkitRemote::Client:.*\s+server=".*"\s+closed=.+>/)
114
+ end
115
+ end
105
116
  end
106
117
 
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "webkit_remote"
8
- s.version = "0.3.1"
8
+ s.version = "0.3.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Victor Costan"]
12
- s.date = "2012-11-08"
12
+ s.date = "2012-11-10"
13
13
  s.description = "Launches Google Chrome instances and controls them via the Remote Debugging server"
14
14
  s.email = "victor@costan.us"
15
15
  s.extra_rdoc_files = [
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: webkit_remote
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-08 00:00:00.000000000 Z
12
+ date: 2012-11-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine
@@ -286,7 +286,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
286
286
  version: '0'
287
287
  segments:
288
288
  - 0
289
- hash: 2944886604051237369
289
+ hash: 3000124756786155400
290
290
  required_rubygems_version: !ruby/object:Gem::Requirement
291
291
  none: false
292
292
  requirements: