webkit_remote 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|