webkit_remote 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/{README.rdoc → README.md} +45 -3
- data/VERSION +1 -1
- data/lib/webkit_remote.rb +2 -0
- data/lib/webkit_remote/client.rb +7 -8
- data/lib/webkit_remote/client/console.rb +42 -0
- data/lib/webkit_remote/client/console_events.rb +156 -0
- data/lib/webkit_remote/client/page.rb +3 -2
- data/lib/webkit_remote/client/page_events.rb +4 -4
- data/lib/webkit_remote/client/runtime.rb +44 -5
- data/lib/webkit_remote/event.rb +8 -3
- data/test/fixtures/html/console.html +25 -0
- data/test/fixtures/html/load.html +1 -1
- data/test/fixtures/html/runtime.html +1 -1
- data/test/webkit_remote/client/console_test.rb +95 -0
- data/test/webkit_remote/client/runtime_test.rb +48 -0
- data/test/webkit_remote/client_test.rb +4 -3
- data/webkit_remote.gemspec +108 -0
- metadata +10 -5
data/{README.rdoc → README.md}
RENAMED
@@ -6,6 +6,29 @@ WebKit-based browsers via the
|
|
6
6
|
[WebKit remote debugging protocol](https://www.webkit.org/blog/1875/announcing-remote-debugging-protocol-v1-0/).
|
7
7
|
|
8
8
|
|
9
|
+
## Features
|
10
|
+
|
11
|
+
This gem can be used to test Web pages in real browsers with minimal intrusion.
|
12
|
+
|
13
|
+
Compared to [PhantomJS](http://phantomjs.org/), `webkit_remote` tests will take
|
14
|
+
longer, but provide assurance that the code will run as intended on desktop and
|
15
|
+
mobile browsers, and can exercise HTML5 features that are not yet
|
16
|
+
[supported by Phantom](http://code.google.com/p/phantomjs/wiki/SupportedFeatures).
|
17
|
+
|
18
|
+
Compared to [Selenium](http://seleniumhq.org/), `webkit_remote` is less mature,
|
19
|
+
and only supports WebKit-based browsers. In return, the gem can support
|
20
|
+
(either directly or via extensions) features that have not made their way into
|
21
|
+
Selenium's [WebDriver](http://www.w3.org/TR/webdriver/).
|
22
|
+
|
23
|
+
Currently, the following sections of the
|
24
|
+
[WebKit remote debugging protocol](https://developers.google.com/chrome-developer-tools/docs/protocol/1.0/)
|
25
|
+
have been implemented:
|
26
|
+
|
27
|
+
* Console
|
28
|
+
* Page
|
29
|
+
* Remote
|
30
|
+
|
31
|
+
|
9
32
|
## Requirements
|
10
33
|
|
11
34
|
The gem is tested against the OSX and Linux builds of Google Chrome. The only
|
@@ -26,7 +49,7 @@ gem install webkit_remote
|
|
26
49
|
## Usage
|
27
50
|
|
28
51
|
This section only showcases a few features. Read the
|
29
|
-
[
|
52
|
+
[YARD docs](http://rdoc.info/github/pwnall/webkit_remote)
|
30
53
|
to see everything this gem has to offer.
|
31
54
|
|
32
55
|
### Session Setup
|
@@ -38,7 +61,6 @@ client = WebkitRemote.local
|
|
38
61
|
launches a separate instance of Google Chrome that is not connected to your
|
39
62
|
profile, and sets up a connection to it. Alternatively,
|
40
63
|
|
41
|
-
|
42
64
|
```ruby
|
43
65
|
client = WebkitRemote.remote host: 'phone-ip-here', port: 9222
|
44
66
|
```
|
@@ -51,7 +73,7 @@ connects to a remote WebKit instance
|
|
51
73
|
```ruby
|
52
74
|
client.page_events = true
|
53
75
|
client.navigate_to 'http://translate.google.com'
|
54
|
-
client.wait_for
|
76
|
+
client.wait_for(type: WebkitRemote::Event::PageLoaded).last
|
55
77
|
```
|
56
78
|
|
57
79
|
### Run JavaScript
|
@@ -89,6 +111,26 @@ Finally, release the JavaScript objects that the debugger is holding onto.
|
|
89
111
|
element.group.release_all
|
90
112
|
```
|
91
113
|
|
114
|
+
### Read the Console
|
115
|
+
|
116
|
+
Produce some console output.
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
client.console_events = true
|
120
|
+
client.remote_eval '(function() { console.warn("hello ruby"); })();'
|
121
|
+
```
|
122
|
+
|
123
|
+
Take a look at it.
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
message = client.wait_for(type: WebkitRemote::Event::ConsoleMessage).first
|
127
|
+
message.text
|
128
|
+
message.level
|
129
|
+
message.params
|
130
|
+
message.stack_trace
|
131
|
+
```
|
132
|
+
|
133
|
+
|
92
134
|
### Clean Up
|
93
135
|
|
94
136
|
```ruby
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/webkit_remote.rb
CHANGED
@@ -7,6 +7,8 @@ require 'webkit_remote/rpc.rb'
|
|
7
7
|
|
8
8
|
require 'webkit_remote/client.rb'
|
9
9
|
require 'webkit_remote/event.rb'
|
10
|
+
require 'webkit_remote/client/console.rb'
|
11
|
+
require 'webkit_remote/client/console_events.rb'
|
10
12
|
require 'webkit_remote/client/page.rb'
|
11
13
|
require 'webkit_remote/client/page_events.rb'
|
12
14
|
require 'webkit_remote/client/runtime.rb'
|
data/lib/webkit_remote/client.rb
CHANGED
@@ -58,7 +58,7 @@ class Client
|
|
58
58
|
# @return [WebkitRemote::Client] self
|
59
59
|
def each_event
|
60
60
|
@rpc.each_event do |rpc_event|
|
61
|
-
yield WebkitRemote::Event.for(rpc_event)
|
61
|
+
yield WebkitRemote::Event.for(rpc_event, self)
|
62
62
|
end
|
63
63
|
self
|
64
64
|
end
|
@@ -66,20 +66,19 @@ class Client
|
|
66
66
|
# Waits for the remote debugging server to send a specific event.
|
67
67
|
#
|
68
68
|
# @param (see WebkitRemote::Event#matches?)
|
69
|
-
# @return [WebkitRemote::Event] the
|
69
|
+
# @return [Array<WebkitRemote::Event>] all the events received, including the
|
70
|
+
# event that matches the class requirement
|
70
71
|
def wait_for(conditions)
|
71
72
|
unless WebkitRemote::Event.can_receive? self, conditions
|
72
73
|
raise ArgumentError, "Cannot receive event with #{conditions.inspect}"
|
73
74
|
end
|
74
75
|
|
75
|
-
|
76
|
+
events = []
|
76
77
|
each_event do |event|
|
77
|
-
|
78
|
-
|
79
|
-
break
|
80
|
-
end
|
78
|
+
events << event
|
79
|
+
break if event.matches?(conditions)
|
81
80
|
end
|
82
|
-
|
81
|
+
events
|
83
82
|
end
|
84
83
|
|
85
84
|
# @return [WebkitRemote::Rpc] the WebSocket RPC client; useful for making raw
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module WebkitRemote
|
2
|
+
|
3
|
+
class Client
|
4
|
+
|
5
|
+
# API for the Console domain.
|
6
|
+
module Console
|
7
|
+
# Removes all the messages in the console.
|
8
|
+
#
|
9
|
+
# @return [WebkitRemote::Client] self
|
10
|
+
def clear_console
|
11
|
+
@rpc.call 'Console.clearMessages'
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
# Enables or disables the generation of events in the Console domain.
|
16
|
+
#
|
17
|
+
# @param [Boolean] new_console_events if true, the browser debugger will
|
18
|
+
# generate Console.* events
|
19
|
+
def console_events=(new_console_events)
|
20
|
+
new_console_events = !!new_console_events
|
21
|
+
if new_console_events != console_events
|
22
|
+
@console_events = new_console_events
|
23
|
+
@rpc.call(@console_events ? 'Console.enable' : 'Console.disable')
|
24
|
+
end
|
25
|
+
new_console_events
|
26
|
+
end
|
27
|
+
|
28
|
+
# @return [Boolean] true if the debugger generates Console.* events
|
29
|
+
attr_reader :console_events
|
30
|
+
|
31
|
+
# @private Called by the Client constructor to set up Console data.
|
32
|
+
def initialize_console
|
33
|
+
@console_events = nil
|
34
|
+
end
|
35
|
+
end # module WebkitRemote::Client::Console
|
36
|
+
|
37
|
+
initializer :initialize_console
|
38
|
+
include WebkitRemote::Client::Console
|
39
|
+
|
40
|
+
end # namespace WebkitRemote::Client
|
41
|
+
|
42
|
+
end # namespace WebkitRemote
|
@@ -0,0 +1,156 @@
|
|
1
|
+
module WebkitRemote
|
2
|
+
|
3
|
+
class Event
|
4
|
+
|
5
|
+
# Emitted when a console message is produced.
|
6
|
+
class ConsoleMessage < WebkitRemote::Event
|
7
|
+
register 'Console.messageAdded'
|
8
|
+
|
9
|
+
# @return [String] the message text
|
10
|
+
attr_reader :text
|
11
|
+
|
12
|
+
# @return [Array<WebkitRemote::Client::RemoteObject>] extra arguments given
|
13
|
+
# to the message
|
14
|
+
attr_reader :params
|
15
|
+
|
16
|
+
# @return [Symbol] message severity
|
17
|
+
#
|
18
|
+
# The documented values are :debug, :error, :log, :tip, and :warning.
|
19
|
+
attr_reader :level
|
20
|
+
|
21
|
+
# @return [Integer] how many times this message was repeated
|
22
|
+
attr_reader :count
|
23
|
+
|
24
|
+
# @return [Symbol] the component that produced this message
|
25
|
+
#
|
26
|
+
# The documented values are :console_api, :html, :javascript, :network,
|
27
|
+
# :other, :wml, and :xml.
|
28
|
+
attr_reader :reason
|
29
|
+
|
30
|
+
# @return [Symbol] the behavior that produced this message
|
31
|
+
#
|
32
|
+
# The documented values are :assert, :dir, :dirxml, :endGroup, :log,
|
33
|
+
# :startGroup, :startGroupCollapsed, and :trace.
|
34
|
+
attr_reader :type
|
35
|
+
|
36
|
+
# @return [String] the URL of the file that caused this message
|
37
|
+
attr_reader :source_url
|
38
|
+
|
39
|
+
# @return [Integer] the line number of the statement that caused this message
|
40
|
+
attr_reader :source_line
|
41
|
+
|
42
|
+
# @return [Array<Hash<Symbol, Object>>] JavaScript stack trace to the
|
43
|
+
# statement that caused this message
|
44
|
+
attr_reader :stack_trace
|
45
|
+
|
46
|
+
# @private Use Event#for instead of calling this constructor directly.
|
47
|
+
def initialize(rpc_event, client)
|
48
|
+
super
|
49
|
+
|
50
|
+
if raw_message = raw_data['message']
|
51
|
+
@level = (raw_message['level'] || 'error').to_sym
|
52
|
+
@source_line = raw_message['line'] ? raw_message['line'].to_i : nil
|
53
|
+
# TODO(pwnall): parse networkRequestId when Network is implemented
|
54
|
+
if raw_message['parameters']
|
55
|
+
@params = raw_message['parameters'].map do |raw_object|
|
56
|
+
WebkitRemote::Client::RemoteObject.for raw_object, client, nil
|
57
|
+
end
|
58
|
+
else
|
59
|
+
@params = []
|
60
|
+
end
|
61
|
+
@params.freeze
|
62
|
+
@count = raw_message['repeatCount'] ? raw_message['repeatCount'].to_i : 1
|
63
|
+
if raw_message['source']
|
64
|
+
@reason = raw_message['source'].gsub('-', '_').to_sym
|
65
|
+
else
|
66
|
+
@reason = :other
|
67
|
+
end
|
68
|
+
if raw_message['stackTrace']
|
69
|
+
@stack_trace = raw_message['stackTrace'].map do |raw_frame|
|
70
|
+
frame = {}
|
71
|
+
if raw_frame['columnNumber']
|
72
|
+
frame[:column] = raw_frame['columnNumber'].to_i
|
73
|
+
end
|
74
|
+
if raw_frame['lineNumber']
|
75
|
+
frame[:line] = raw_frame['lineNumber'].to_i
|
76
|
+
end
|
77
|
+
if raw_frame['functionName']
|
78
|
+
frame[:function] = raw_frame['functionName']
|
79
|
+
end
|
80
|
+
if raw_frame['url']
|
81
|
+
frame[:url] = raw_frame['url']
|
82
|
+
end
|
83
|
+
frame
|
84
|
+
end
|
85
|
+
else
|
86
|
+
@trace = nil
|
87
|
+
end
|
88
|
+
@text = raw_message['text']
|
89
|
+
@type = raw_message['type'] ? raw_message['type'].to_sym : nil
|
90
|
+
@source_url = raw_message['url']
|
91
|
+
end
|
92
|
+
|
93
|
+
# NOTE(pwnall): if the client will keep track of console messages, this is
|
94
|
+
# the right place to call into the client and register the message
|
95
|
+
end
|
96
|
+
|
97
|
+
# Releases the JavaScript objects referenced by this message's parameters.
|
98
|
+
def release_params()
|
99
|
+
@params.each do |param|
|
100
|
+
if param.kind_of?(WebkitRemote::Client::RemoteObject)
|
101
|
+
param.release
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# @private Use Event#can_receive instead of calling this directly.
|
107
|
+
def self.can_reach?(client)
|
108
|
+
client.console_events
|
109
|
+
end
|
110
|
+
end # class WebkitRemote::Event::ConsoleMessage
|
111
|
+
|
112
|
+
# Emitted when the same console message is produced repeatedly.
|
113
|
+
class ConsoleMessageRepeated < WebkitRemote::Event
|
114
|
+
register 'Console.messageRepeatCountUpdated'
|
115
|
+
|
116
|
+
# @return [Number] the number of times that the message was repeated
|
117
|
+
attr_reader :count
|
118
|
+
|
119
|
+
# @private Use Event#for instead of calling this constructor directly.
|
120
|
+
def initialize(rpc_event, client)
|
121
|
+
super
|
122
|
+
@count = raw_data['count'] ? raw_data['count'].to_i : nil
|
123
|
+
|
124
|
+
# NOTE(pwnall): if the client will keep track of console messages, this is
|
125
|
+
# the right place to call into the client and have it update the repeat
|
126
|
+
# count of the most recent message that it received
|
127
|
+
end
|
128
|
+
|
129
|
+
# @private Use Event#can_receive instead of calling this directly.
|
130
|
+
def self.can_reach?(client)
|
131
|
+
client.console_events
|
132
|
+
end
|
133
|
+
end # class WebkitRemote::Event::ConsoleMessageRepeated
|
134
|
+
|
135
|
+
# Emitted when the console is cleared.
|
136
|
+
class ConsoleCleared < WebkitRemote::Event
|
137
|
+
register 'Console.messagesCleared'
|
138
|
+
|
139
|
+
# @private Use Event#for instead of calling this constructor directly.
|
140
|
+
def initialize(rpc_event, client)
|
141
|
+
super
|
142
|
+
|
143
|
+
# NOTE(pwnall): if the client will keep track of console messages, this is
|
144
|
+
# the right place to call into the client and have it wipe its message
|
145
|
+
# list, and call #release_params on the messages
|
146
|
+
end
|
147
|
+
|
148
|
+
# @private Use Event#can_receive instead of calling this directly.
|
149
|
+
def self.can_reach?(client)
|
150
|
+
client.console_events
|
151
|
+
end
|
152
|
+
end # class WebkitRemote::Event::ConsoleCleared
|
153
|
+
|
154
|
+
end # namespace WebkitRemote::Event
|
155
|
+
|
156
|
+
end # namepspace WebkitRemote
|
@@ -34,8 +34,9 @@ module Page
|
|
34
34
|
# @param [Boolean] new_page_events if true, the browser debugger will
|
35
35
|
# generate Page.* events
|
36
36
|
def page_events=(new_page_events)
|
37
|
-
|
38
|
-
|
37
|
+
new_page_events = !!new_page_events
|
38
|
+
if new_page_events != page_events
|
39
|
+
@page_events = new_page_events
|
39
40
|
@rpc.call(@page_events ? 'Page.enable' : 'Page.disable')
|
40
41
|
end
|
41
42
|
new_page_events
|
@@ -10,14 +10,14 @@ class PageLoaded < WebkitRemote::Event
|
|
10
10
|
attr_reader :timestamp
|
11
11
|
|
12
12
|
# @private Use Event#for instead of calling this constructor directly.
|
13
|
-
def initialize(rpc_event)
|
13
|
+
def initialize(rpc_event, client)
|
14
14
|
super
|
15
15
|
@timestamp = raw_data['timestamp']
|
16
16
|
end
|
17
17
|
|
18
18
|
# @private Use Event#can_receive instead of calling this directly.
|
19
19
|
def self.can_reach?(client)
|
20
|
-
|
20
|
+
client.page_events
|
21
21
|
end
|
22
22
|
end # class WebkitRemote::Event::PageLoaded
|
23
23
|
|
@@ -29,14 +29,14 @@ class PageDomReady < WebkitRemote::Event
|
|
29
29
|
attr_reader :timestamp
|
30
30
|
|
31
31
|
# @private Use Event#for instead of calling this constructor directly.
|
32
|
-
def initialize(rpc_event)
|
32
|
+
def initialize(rpc_event, client)
|
33
33
|
super
|
34
34
|
@timestamp = raw_data['timestamp']
|
35
35
|
end
|
36
36
|
|
37
37
|
# @private Use Event#can_receive instead of calling this directly.
|
38
38
|
def self.can_reach?(client)
|
39
|
-
|
39
|
+
client.page_events
|
40
40
|
end
|
41
41
|
end # class WebkitRemote::Event::PageDomReady
|
42
42
|
|
@@ -39,7 +39,7 @@ module Runtime
|
|
39
39
|
# standard Ruby classes, and objects get wrapped by RemoteObject
|
40
40
|
# instances
|
41
41
|
def object_group(group_name, create = false)
|
42
|
-
group_name = group_name.to_s
|
42
|
+
group_name = group_name.nil? ? nil : group_name.to_s
|
43
43
|
group = @runtime_groups[group_name]
|
44
44
|
return group if group
|
45
45
|
if create
|
@@ -69,6 +69,47 @@ end # module WebkitRemote::Client::Runtime
|
|
69
69
|
initializer :initialize_runtime
|
70
70
|
include Runtime
|
71
71
|
|
72
|
+
# The class of the JavaScript undefined object.
|
73
|
+
class UndefinedClass
|
74
|
+
def js_undefined?
|
75
|
+
true
|
76
|
+
end
|
77
|
+
|
78
|
+
def empty?
|
79
|
+
true
|
80
|
+
end
|
81
|
+
|
82
|
+
def blank?
|
83
|
+
true
|
84
|
+
end
|
85
|
+
|
86
|
+
def nil?
|
87
|
+
true
|
88
|
+
end
|
89
|
+
|
90
|
+
def to_a
|
91
|
+
[]
|
92
|
+
end
|
93
|
+
|
94
|
+
def to_s
|
95
|
+
''
|
96
|
+
end
|
97
|
+
|
98
|
+
def to_i
|
99
|
+
0
|
100
|
+
end
|
101
|
+
|
102
|
+
def to_f
|
103
|
+
0.0
|
104
|
+
end
|
105
|
+
|
106
|
+
def inspect
|
107
|
+
'JavaScript undefined'
|
108
|
+
end
|
109
|
+
end # class WebkitRemote::Client::UndefinedClass
|
110
|
+
|
111
|
+
Undefined = UndefinedClass.new
|
112
|
+
|
72
113
|
# Mirrors a RemoteObject, defined in the Runtime domain.
|
73
114
|
class RemoteObject
|
74
115
|
# @return [String] the class name computed by WebKit for this object
|
@@ -205,15 +246,13 @@ class RemoteObject
|
|
205
246
|
when :boolean, :number, :string
|
206
247
|
return raw_object['value']
|
207
248
|
when :undefined
|
208
|
-
|
209
|
-
when :function
|
210
|
-
# TODO(pwnall): Not sure what to do here.
|
249
|
+
return WebkitRemote::Client::Undefined
|
211
250
|
when :object
|
212
251
|
case raw_object['subtype'] ? raw_object['subtype'].to_sym : nil
|
213
252
|
when :null
|
214
253
|
return nil
|
215
254
|
end
|
216
|
-
# TODO(pwnall):
|
255
|
+
# TODO(pwnall): Any other exceptions?
|
217
256
|
end
|
218
257
|
end
|
219
258
|
raise RuntimeError, "Unable to parse #{raw_object.inspect}"
|
data/lib/webkit_remote/event.rb
CHANGED
@@ -64,11 +64,12 @@ class Event
|
|
64
64
|
#
|
65
65
|
# @param [Hash<Symbol, Object>] rpc_event event information yielded by a call
|
66
66
|
# to WebkitRemote::Rpc.each_event
|
67
|
+
# @param [WebkitRemote::Client] the client that received this message
|
67
68
|
# @return [WebkitRemote::Event] an instance of an Event subclass that best
|
68
69
|
# represents the given event
|
69
|
-
def self.for(rpc_event)
|
70
|
+
def self.for(rpc_event, client)
|
70
71
|
klass = class_for rpc_event[:name]
|
71
|
-
klass.new rpc_event
|
72
|
+
klass.new rpc_event, client
|
72
73
|
end
|
73
74
|
|
74
75
|
# The WebkitRemote::Event subclass registered to handle an event.
|
@@ -87,9 +88,13 @@ class Event
|
|
87
88
|
# @private API clients should use Event#for instead of calling the
|
88
89
|
# constructor directly.
|
89
90
|
#
|
91
|
+
# If at all possible, subclasses should avoid using the WebkitRemote::Client
|
92
|
+
# instance, to avoid tight coupling.
|
93
|
+
#
|
90
94
|
# @param [Hash<Symbol, Object>] rpc_event event information yielded by a call
|
91
95
|
# to WebkitRemote::Rpc.each_event
|
92
|
-
|
96
|
+
# @param [WebkitRemote::Client] the client that received this message
|
97
|
+
def initialize(rpc_event, client)
|
93
98
|
@name = rpc_event[:name]
|
94
99
|
@domain = rpc_event[:name].split('.', 2).first
|
95
100
|
@raw_data = rpc_event[:data] || {}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>WebkitRemote Console test</title>
|
5
|
+
<script type="text/javascript">
|
6
|
+
// Raw test.
|
7
|
+
console.warn("hello ruby");
|
8
|
+
// Stack test.
|
9
|
+
(function() {
|
10
|
+
function f1() {
|
11
|
+
console.log("stack test");
|
12
|
+
};
|
13
|
+
function f2() {
|
14
|
+
f1();
|
15
|
+
};
|
16
|
+
f2();
|
17
|
+
})();
|
18
|
+
// Arguments test.
|
19
|
+
console.error("params ", 42, true, { hello: "ruby" });
|
20
|
+
</script>
|
21
|
+
</head>
|
22
|
+
<body>
|
23
|
+
<p>Runtime test loaded</p>
|
24
|
+
</body>
|
25
|
+
</html>
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require File.expand_path('../../helper.rb', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe WebkitRemote::Client::Console do
|
4
|
+
before :all do
|
5
|
+
@client = WebkitRemote.local port: 9669
|
6
|
+
@client.page_events = true
|
7
|
+
end
|
8
|
+
after :all do
|
9
|
+
@client.close
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'without console events enabled' do
|
13
|
+
before :all do
|
14
|
+
@client.console_events = false
|
15
|
+
@client.navigate_to fixture_url(:console)
|
16
|
+
@events = @client.wait_for type: WebkitRemote::Event::PageLoaded
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'does not receive any console event' do
|
20
|
+
@events.each do |event|
|
21
|
+
@event.wont_be_kind_of WebkitRemote::Event::ConsoleMessage
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'cannot wait for console events' do
|
26
|
+
lambda {
|
27
|
+
@client.wait_for type: WebkitRemote::Event::ConsoleMessage
|
28
|
+
}.must_raise ArgumentError
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'with console events enabled' do
|
33
|
+
before :all do
|
34
|
+
@client.console_events = true
|
35
|
+
@client.navigate_to fixture_url(:console)
|
36
|
+
@events = @client.wait_for type: WebkitRemote::Event::PageLoaded
|
37
|
+
@messages = @events.select do |event|
|
38
|
+
event.kind_of? WebkitRemote::Event::ConsoleMessage
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
after :all do
|
43
|
+
@messages.each(&:release_params)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'receives console events' do
|
47
|
+
@messages.wont_be :empty?
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'parses text correctly' do
|
51
|
+
@messages[0].text.must_equal 'hello ruby'
|
52
|
+
@messages[0].params.must_equal ['hello ruby']
|
53
|
+
@messages[0].level.must_equal :warning
|
54
|
+
@messages[0].count.must_equal 1
|
55
|
+
@messages[0].reason.must_equal :console_api
|
56
|
+
@messages[0].type.must_equal :log
|
57
|
+
@messages[0].source_url.must_equal fixture_url(:console)
|
58
|
+
@messages[0].source_line.must_equal 7
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
it 'parses the stack trace correctly' do
|
63
|
+
@messages[1].text.must_equal 'stack test'
|
64
|
+
@messages[1].level.must_equal :log
|
65
|
+
@messages[1].stack_trace.must_equal [
|
66
|
+
{ url: fixture_url(:console), line: 11, column: 19, function: 'f1' },
|
67
|
+
{ url: fixture_url(:console), line: 14, column: 11, function: 'f2' },
|
68
|
+
{ url: fixture_url(:console), line: 16, column: 9, function: '' },
|
69
|
+
{ url: fixture_url(:console), line: 17, column: 9, function: '' },
|
70
|
+
]
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'parses parameters correctly' do
|
74
|
+
@messages[2].text.must_match(/^params /)
|
75
|
+
@messages[2].level.must_equal :error
|
76
|
+
@messages[2].params[0, 3].must_equal ['params ', 42, true]
|
77
|
+
@messages[2].params.length.must_equal 4
|
78
|
+
|
79
|
+
@messages[2].params[3].must_be_kind_of WebkitRemote::Client::RemoteObject
|
80
|
+
@messages[2].params[3].properties[:hello].value.must_equal 'ruby'
|
81
|
+
@messages[2].params[3].group.name.must_equal nil
|
82
|
+
end
|
83
|
+
|
84
|
+
describe 'clear_console' do
|
85
|
+
before :all do
|
86
|
+
@client.clear_console
|
87
|
+
@events = @client.wait_for type: WebkitRemote::Event::ConsoleCleared
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'emits a ConsoleCleared event' do
|
91
|
+
@events.last.must_be_kind_of WebkitRemote::Event::ConsoleCleared
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -62,6 +62,28 @@ describe WebkitRemote::Client::Runtime do
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
+
describe 'for undefined' do
|
66
|
+
before :each do
|
67
|
+
@undefined = @client.remote_eval '(function() {})()', group: 'no'
|
68
|
+
end
|
69
|
+
it 'returns an Undefined object' do
|
70
|
+
@undefined.js_undefined?.must_equal true
|
71
|
+
@undefined.to_s.must_equal ''
|
72
|
+
@undefined.inspect.must_equal 'JavaScript undefined'
|
73
|
+
@undefined.to_a.must_equal []
|
74
|
+
@undefined.to_i.must_equal 0
|
75
|
+
@undefined.to_f.must_equal 0.0
|
76
|
+
@undefined.blank?.must_equal true
|
77
|
+
@undefined.empty?.must_equal true
|
78
|
+
end
|
79
|
+
it 'does not create an object group' do
|
80
|
+
@client.object_group('no').must_equal nil
|
81
|
+
end
|
82
|
+
it 'is idempotent' do
|
83
|
+
@undefined.must_equal @client.remote_eval('(function(){})()')
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
65
87
|
describe 'for an object created via new' do
|
66
88
|
before :each do
|
67
89
|
@object = @client.remote_eval 'new TestClass("hello Ruby")',
|
@@ -105,5 +127,31 @@ describe WebkitRemote::Client::Runtime do
|
|
105
127
|
@client.object_group('yes').released?.must_equal false
|
106
128
|
end
|
107
129
|
end
|
130
|
+
|
131
|
+
describe 'for a function' do
|
132
|
+
before :each do
|
133
|
+
@function = @client.remote_eval '(function (a, b) { return a + b; })',
|
134
|
+
group: 'yes'
|
135
|
+
end
|
136
|
+
after :each do
|
137
|
+
group = @client.object_group('yes')
|
138
|
+
group.release_all if group
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'returns a RemoteObject instance' do
|
142
|
+
@function.must_be_kind_of WebkitRemote::Client::RemoteObject
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'sets the object properties correctly' do
|
146
|
+
@function.js_class_name.must_equal 'Object'
|
147
|
+
@function.js_type.must_equal :function
|
148
|
+
@function.description.must_equal 'function (a, b) { return a + b; }'
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'creates a non-released group' do
|
152
|
+
@client.object_group('yes').wont_equal nil
|
153
|
+
@client.object_group('yes').released?.must_equal false
|
154
|
+
end
|
155
|
+
end
|
108
156
|
end
|
109
157
|
end
|
@@ -61,11 +61,12 @@ describe WebkitRemote::Client do
|
|
61
61
|
before do
|
62
62
|
@client.page_events = true
|
63
63
|
@client.rpc.call 'Page.navigate', url: fixture_url(:load)
|
64
|
+
@events = @client.wait_for type: WebkitRemote::Event::PageLoaded
|
64
65
|
end
|
65
66
|
|
66
|
-
it 'returns a PageLoaded instance' do
|
67
|
-
@
|
68
|
-
|
67
|
+
it 'returns an array ending with a PageLoaded instance' do
|
68
|
+
@events.wont_be :empty?
|
69
|
+
@events.last.must_be_kind_of WebkitRemote::Event::PageLoaded
|
69
70
|
end
|
70
71
|
end
|
71
72
|
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "webkit_remote"
|
8
|
+
s.version = "0.2.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Victor Costan"]
|
12
|
+
s.date = "2012-10-31"
|
13
|
+
s.description = "Launches Google Chrome instances and controls them via the Remote Debugging server"
|
14
|
+
s.email = "victor@costan.us"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.md"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
"Gemfile",
|
22
|
+
"Gemfile.lock",
|
23
|
+
"LICENSE.txt",
|
24
|
+
"README.md",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"lib/webkit_remote.rb",
|
28
|
+
"lib/webkit_remote/browser.rb",
|
29
|
+
"lib/webkit_remote/client.rb",
|
30
|
+
"lib/webkit_remote/client/console.rb",
|
31
|
+
"lib/webkit_remote/client/console_events.rb",
|
32
|
+
"lib/webkit_remote/client/page.rb",
|
33
|
+
"lib/webkit_remote/client/page_events.rb",
|
34
|
+
"lib/webkit_remote/client/runtime.rb",
|
35
|
+
"lib/webkit_remote/event.rb",
|
36
|
+
"lib/webkit_remote/process.rb",
|
37
|
+
"lib/webkit_remote/rpc.rb",
|
38
|
+
"lib/webkit_remote/top_level.rb",
|
39
|
+
"test/fixtures/config.ru",
|
40
|
+
"test/fixtures/html/console.html",
|
41
|
+
"test/fixtures/html/load.html",
|
42
|
+
"test/fixtures/html/runtime.html",
|
43
|
+
"test/helper.rb",
|
44
|
+
"test/webkit_remote/browser_test.rb",
|
45
|
+
"test/webkit_remote/client/console_test.rb",
|
46
|
+
"test/webkit_remote/client/page_test.rb",
|
47
|
+
"test/webkit_remote/client/remote_object_group_test.rb",
|
48
|
+
"test/webkit_remote/client/remote_object_test.rb",
|
49
|
+
"test/webkit_remote/client/runtime_test.rb",
|
50
|
+
"test/webkit_remote/client_test.rb",
|
51
|
+
"test/webkit_remote/event_test.rb",
|
52
|
+
"test/webkit_remote/process_test.rb",
|
53
|
+
"test/webkit_remote/rpc_test.rb",
|
54
|
+
"test/webkit_remote_test.rb",
|
55
|
+
"webkit_remote.gemspec"
|
56
|
+
]
|
57
|
+
s.homepage = "http://github.com/pwnall/webkit_remote"
|
58
|
+
s.licenses = ["MIT"]
|
59
|
+
s.require_paths = ["lib"]
|
60
|
+
s.rubygems_version = "1.8.24"
|
61
|
+
s.summary = "Client for the Webkit Remote Debugging server"
|
62
|
+
|
63
|
+
if s.respond_to? :specification_version then
|
64
|
+
s.specification_version = 3
|
65
|
+
|
66
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
67
|
+
s.add_runtime_dependency(%q<eventmachine>, [">= 1.0.0"])
|
68
|
+
s.add_runtime_dependency(%q<faye-websocket>, [">= 0.4.6"])
|
69
|
+
s.add_runtime_dependency(%q<posix-spawn>, [">= 0.3.6"])
|
70
|
+
s.add_development_dependency(%q<bundler>, [">= 1.2.1"])
|
71
|
+
s.add_development_dependency(%q<jeweler>, [">= 1.8.4"])
|
72
|
+
s.add_development_dependency(%q<minitest>, [">= 4.1.0"])
|
73
|
+
s.add_development_dependency(%q<puma>, [">= 1.6.3"])
|
74
|
+
s.add_development_dependency(%q<rack>, [">= 1.4.1"])
|
75
|
+
s.add_development_dependency(%q<rdoc>, [">= 3.12"])
|
76
|
+
s.add_development_dependency(%q<ruby-prof>, [">= 0.11.2"])
|
77
|
+
s.add_development_dependency(%q<simplecov>, [">= 0.7.1"])
|
78
|
+
s.add_development_dependency(%q<yard>, [">= 0.8.3"])
|
79
|
+
else
|
80
|
+
s.add_dependency(%q<eventmachine>, [">= 1.0.0"])
|
81
|
+
s.add_dependency(%q<faye-websocket>, [">= 0.4.6"])
|
82
|
+
s.add_dependency(%q<posix-spawn>, [">= 0.3.6"])
|
83
|
+
s.add_dependency(%q<bundler>, [">= 1.2.1"])
|
84
|
+
s.add_dependency(%q<jeweler>, [">= 1.8.4"])
|
85
|
+
s.add_dependency(%q<minitest>, [">= 4.1.0"])
|
86
|
+
s.add_dependency(%q<puma>, [">= 1.6.3"])
|
87
|
+
s.add_dependency(%q<rack>, [">= 1.4.1"])
|
88
|
+
s.add_dependency(%q<rdoc>, [">= 3.12"])
|
89
|
+
s.add_dependency(%q<ruby-prof>, [">= 0.11.2"])
|
90
|
+
s.add_dependency(%q<simplecov>, [">= 0.7.1"])
|
91
|
+
s.add_dependency(%q<yard>, [">= 0.8.3"])
|
92
|
+
end
|
93
|
+
else
|
94
|
+
s.add_dependency(%q<eventmachine>, [">= 1.0.0"])
|
95
|
+
s.add_dependency(%q<faye-websocket>, [">= 0.4.6"])
|
96
|
+
s.add_dependency(%q<posix-spawn>, [">= 0.3.6"])
|
97
|
+
s.add_dependency(%q<bundler>, [">= 1.2.1"])
|
98
|
+
s.add_dependency(%q<jeweler>, [">= 1.8.4"])
|
99
|
+
s.add_dependency(%q<minitest>, [">= 4.1.0"])
|
100
|
+
s.add_dependency(%q<puma>, [">= 1.6.3"])
|
101
|
+
s.add_dependency(%q<rack>, [">= 1.4.1"])
|
102
|
+
s.add_dependency(%q<rdoc>, [">= 3.12"])
|
103
|
+
s.add_dependency(%q<ruby-prof>, [">= 0.11.2"])
|
104
|
+
s.add_dependency(%q<simplecov>, [">= 0.7.1"])
|
105
|
+
s.add_dependency(%q<yard>, [">= 0.8.3"])
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
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.
|
4
|
+
version: 0.2.0
|
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-10-
|
12
|
+
date: 2012-10-31 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: eventmachine
|
@@ -210,18 +210,20 @@ executables: []
|
|
210
210
|
extensions: []
|
211
211
|
extra_rdoc_files:
|
212
212
|
- LICENSE.txt
|
213
|
-
- README.
|
213
|
+
- README.md
|
214
214
|
files:
|
215
215
|
- .document
|
216
216
|
- Gemfile
|
217
217
|
- Gemfile.lock
|
218
218
|
- LICENSE.txt
|
219
|
-
- README.
|
219
|
+
- README.md
|
220
220
|
- Rakefile
|
221
221
|
- VERSION
|
222
222
|
- lib/webkit_remote.rb
|
223
223
|
- lib/webkit_remote/browser.rb
|
224
224
|
- lib/webkit_remote/client.rb
|
225
|
+
- lib/webkit_remote/client/console.rb
|
226
|
+
- lib/webkit_remote/client/console_events.rb
|
225
227
|
- lib/webkit_remote/client/page.rb
|
226
228
|
- lib/webkit_remote/client/page_events.rb
|
227
229
|
- lib/webkit_remote/client/runtime.rb
|
@@ -230,10 +232,12 @@ files:
|
|
230
232
|
- lib/webkit_remote/rpc.rb
|
231
233
|
- lib/webkit_remote/top_level.rb
|
232
234
|
- test/fixtures/config.ru
|
235
|
+
- test/fixtures/html/console.html
|
233
236
|
- test/fixtures/html/load.html
|
234
237
|
- test/fixtures/html/runtime.html
|
235
238
|
- test/helper.rb
|
236
239
|
- test/webkit_remote/browser_test.rb
|
240
|
+
- test/webkit_remote/client/console_test.rb
|
237
241
|
- test/webkit_remote/client/page_test.rb
|
238
242
|
- test/webkit_remote/client/remote_object_group_test.rb
|
239
243
|
- test/webkit_remote/client/remote_object_test.rb
|
@@ -243,6 +247,7 @@ files:
|
|
243
247
|
- test/webkit_remote/process_test.rb
|
244
248
|
- test/webkit_remote/rpc_test.rb
|
245
249
|
- test/webkit_remote_test.rb
|
250
|
+
- webkit_remote.gemspec
|
246
251
|
homepage: http://github.com/pwnall/webkit_remote
|
247
252
|
licenses:
|
248
253
|
- MIT
|
@@ -258,7 +263,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
258
263
|
version: '0'
|
259
264
|
segments:
|
260
265
|
- 0
|
261
|
-
hash: -
|
266
|
+
hash: -1503511080774862725
|
262
267
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
263
268
|
none: false
|
264
269
|
requirements:
|