webkit_remote 0.1.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.
@@ -0,0 +1,31 @@
1
+ # Top-level namespace.
2
+ module WebkitRemote
3
+ # Launches a WebKit process locally, and sets up a debugger client for it.
4
+ #
5
+ # @param (see WebkitRemote::Process#initialize)
6
+ # @return [WebkitRemote::Client] a debugging client connected to a local
7
+ # WebKit process; the client will automatically stop the process when
8
+ # closed
9
+ def self.local(opts = {})
10
+ process = WebkitRemote::Process.new opts
11
+ browser = process.start
12
+ browser.stop_process = true
13
+ client = WebkitRemote::Client.new tab: browser.tabs.first,
14
+ close_browser: true
15
+ client
16
+ end
17
+
18
+ # Connects to a Webkit process, and sets up a debugger client for it.
19
+ #
20
+ # @param (see WebkitRemote::Browser#initialize)
21
+ # @return [WebkitRemote::Client] a debugging client connected to the remote
22
+ # WebKit process; the connection will be automatically terminated when
23
+ # the debugging client is closed
24
+ def self.remote(opts = {})
25
+ browser = WebkitRemote::Browser.new opts
26
+ # NOTE: connecting to the last tab to avoid internal tabs and whatnot
27
+ client = WebkitRemote::Client.new tab: browser.tabs.last,
28
+ close_browser: true
29
+ client
30
+ end
31
+ end # namespace WebkitRemote
@@ -0,0 +1,12 @@
1
+ module WebkitRemote; end
2
+ require 'webkit_remote/top_level.rb'
3
+
4
+ require 'webkit_remote/browser.rb'
5
+ require 'webkit_remote/process.rb'
6
+ require 'webkit_remote/rpc.rb'
7
+
8
+ require 'webkit_remote/client.rb'
9
+ require 'webkit_remote/event.rb'
10
+ require 'webkit_remote/client/page.rb'
11
+ require 'webkit_remote/client/page_events.rb'
12
+ require 'webkit_remote/client/runtime.rb'
@@ -0,0 +1,12 @@
1
+ require 'bundler'
2
+ Bundler.setup :default, :development
3
+
4
+ use Rack::Static, urls: ['/html'], root: 'test/fixtures'
5
+ app = lambda do |env|
6
+ [
7
+ 200,
8
+ {'Content-Type' => 'text/plain'},
9
+ ['Fixture app catch-all page. Invalid test URL.']
10
+ ]
11
+ end
12
+ run app
@@ -0,0 +1,7 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head><title>WebkitRemote load test</title></head>
4
+ <body>
5
+ <p>tbd</p>
6
+ </body>
7
+ </html>
@@ -0,0 +1,31 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <title>WebkitRemote Runtime test</title>
5
+ <script type="text/javascript">
6
+ (function() {
7
+ window.test_fn = function(hello, ruby) {
8
+ return hello + ruby;
9
+ };
10
+ var TestClass = function (hello) {
11
+ this.hello = hello;
12
+ };
13
+ TestClass.prototype.number = 42;
14
+ TestClass.prototype.add3 = function(hello, again, ruby) {
15
+ return this.hello + hello + again + ruby;
16
+ };
17
+ TestClass.prototype.greetings = function(arg1, arg2) {
18
+ return new TestClass(this.hello + ', ' + arg1.hello + ' and ' +
19
+ arg2.hello);
20
+ };
21
+ TestClass.prototype.toString = function() {
22
+ return this.hello;
23
+ };
24
+ window.TestClass = TestClass;
25
+ })();
26
+ </script>
27
+ </head>
28
+ <body>
29
+ <p>tbd</p>
30
+ </body>
31
+ </html>
data/test/helper.rb ADDED
@@ -0,0 +1,44 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'minitest/unit'
11
+ require 'minitest/spec'
12
+
13
+ require 'simplecov'
14
+ SimpleCov.start
15
+
16
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
17
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
18
+ require 'webkit_remote'
19
+
20
+ require 'thread'
21
+ Thread.abort_on_exception = true
22
+
23
+ # Launch a dev server and wait until it starts.
24
+ pid = Process.spawn 'bundle exec puma --port 9969 --quiet test/fixtures/config.ru',
25
+ :in => '/dev/null', :out => '/dev/null'
26
+ Process.detach pid
27
+ at_exit { Process.kill 'TERM', pid }
28
+ loop do
29
+ begin
30
+ response = Net::HTTP.get_response URI.parse('http://localhost:9969')
31
+ break if response.kind_of?(Net::HTTPSuccess)
32
+ rescue SystemCallError
33
+ sleep 0.1
34
+ end
35
+ end
36
+
37
+ class MiniTest::Unit::TestCase
38
+ # URL for a file in the test/fixtures directory.
39
+ def fixture_url(name)
40
+ "http://localhost:9969/html/#{name}.html"
41
+ end
42
+ end
43
+
44
+ MiniTest::Unit.autorun
@@ -0,0 +1,80 @@
1
+ require File.expand_path('../helper.rb', File.dirname(__FILE__))
2
+
3
+ describe WebkitRemote::Browser do
4
+ before :each do
5
+ @process = WebkitRemote::Process.new port: 9669
6
+ @process.start
7
+ end
8
+ after :each do
9
+ @process.stop if @process
10
+ end
11
+
12
+ describe 'with process' do
13
+ before :each do
14
+ @browser = WebkitRemote::Browser.new process: @process
15
+ end
16
+ after :each do
17
+ @browser.close if @browser
18
+ end
19
+
20
+ it 'sets the host and port correctly' do
21
+ @browser.host.must_equal 'localhost'
22
+ @browser.port.must_equal 9669
23
+ end
24
+
25
+ it 'enumerates the browser tabs correctly' do
26
+ tabs = @browser.tabs
27
+ tabs.length.must_equal 1
28
+ tabs.first.must_be_kind_of WebkitRemote::Browser::Tab
29
+ tabs.first.browser.must_equal @browser
30
+ tabs.first.debug_url.must_match(/^ws:\/\/localhost:9669\//)
31
+ tabs.first.url.must_equal 'about:blank'
32
+ end
33
+
34
+ it 'does not auto-stop the process by default' do
35
+ @browser.stop_process?.must_equal false
36
+ @browser.close
37
+ @browser.closed?.must_equal true
38
+ @process.running?.must_equal true
39
+ end
40
+
41
+ describe 'with process auto-stopping' do
42
+ before do
43
+ @browser.stop_process = true
44
+ end
45
+
46
+ it 'stops the process when closed' do
47
+ @browser.stop_process?.must_equal true
48
+ @browser.close
49
+ @browser.closed?.must_equal true
50
+ @process.running?.must_equal false
51
+ end
52
+ end
53
+ end
54
+
55
+ describe 'with host/port' do
56
+ before :each do
57
+ @browser = WebkitRemote::Browser.new host: 'localhost', port: 9669
58
+ end
59
+ after :each do
60
+ @browser.close if @browser
61
+ end
62
+
63
+ it "does not support process auto-stopping" do
64
+ @browser.stop_process.must_equal false
65
+ lambda {
66
+ @browser.stop_process = true
67
+ }.must_raise ArgumentError
68
+ @browser.stop_process.must_equal false
69
+ end
70
+
71
+ it 'enumerates the browser tabs correctly' do
72
+ tabs = @browser.tabs
73
+ tabs.length.must_equal 1
74
+ tabs.first.must_be_kind_of WebkitRemote::Browser::Tab
75
+ tabs.first.browser.must_equal @browser
76
+ tabs.first.debug_url.must_match(/^ws:\/\/localhost:9669\//)
77
+ tabs.first.url.must_equal 'about:blank'
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,31 @@
1
+ require File.expand_path('../../helper.rb', File.dirname(__FILE__))
2
+
3
+ describe WebkitRemote::Client::Page do
4
+ before do
5
+ @client = WebkitRemote.local port: 9669
6
+ end
7
+ after do
8
+ @client.close
9
+ end
10
+
11
+ describe 'navigate' do
12
+ before do
13
+ @url = fixture_url(:load)
14
+ @client.page_events = true
15
+ @client.navigate_to @url
16
+ @events = []
17
+ @client.each_event do |event|
18
+ @events << event
19
+ break if event.kind_of?(WebkitRemote::Event::PageLoaded)
20
+ end
21
+ end
22
+
23
+ it 'changes the tab URL' do
24
+ @client.browser.tabs.map(&:url).must_include @url
25
+ end
26
+
27
+ it 'fires a PageLoaded event' do
28
+ @events.map(&:class).must_include WebkitRemote::Event::PageLoaded
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,81 @@
1
+ require File.expand_path('../../helper.rb', File.dirname(__FILE__))
2
+
3
+ describe WebkitRemote::Client::RemoteObjectGroup do
4
+ before :each do
5
+ @client = WebkitRemote.local port: 9669
6
+ @client.page_events = true
7
+ @client.navigate_to fixture_url(:runtime)
8
+ @client.wait_for type: WebkitRemote::Event::PageLoaded
9
+
10
+ @object1 = @client.remote_eval '({})', group: 'g1'
11
+ @object2 = @client.remote_eval '({})', group: 'g1'
12
+ @object3 = @client.remote_eval '({})', group: 'g2'
13
+ @group1 = @client.object_group 'g1'
14
+ @group2 = @client.object_group 'g2'
15
+ end
16
+ after :each do
17
+ @group1.release_all if @group1
18
+ @group2.release_all if @group2
19
+ @client.close
20
+ end
21
+
22
+ describe 'include?' do
23
+ it 'is true for objects in the group' do
24
+ @group1.include?(@object1).must_equal true
25
+ @group1.include?(@object2).must_equal true
26
+ @group2.include?(@object3).must_equal true
27
+ end
28
+ it 'is false for objects in different groups' do
29
+ @group2.include?(@object2).must_equal false
30
+ @group1.include?(@object3).must_equal false
31
+ @group2.include?(@object1).must_equal false
32
+ end
33
+ end
34
+
35
+ describe 'after an object release' do
36
+ before :each do
37
+ @object1.release
38
+ end
39
+
40
+ it 'does not include the released object' do
41
+ @group1.include?(@object1).must_equal false
42
+ end
43
+ it 'includes unreleased objects' do
44
+ @group1.include?(@object2).must_equal true
45
+ end
46
+ it 'does not release the whole group' do
47
+ @group1.released?.must_equal false
48
+ end
49
+
50
+ describe 'after releasing the only other object in the group' do
51
+ before :each do
52
+ @object2.release
53
+ end
54
+
55
+ it 'released the whole group' do
56
+ @group1.released?.must_equal true
57
+ end
58
+ it 'removes the group from the client' do
59
+ @client.object_group('g1').must_equal nil
60
+ end
61
+ end
62
+ end
63
+
64
+ describe '#release_all' do
65
+ before :each do
66
+ @group1.release_all
67
+ end
68
+
69
+ it 'releases all the objects in the group' do
70
+ @object1.released?.must_equal true
71
+ @object2.released?.must_equal true
72
+ end
73
+ it 'does not release objects in other groups' do
74
+ @object3.released?.must_equal false
75
+ end
76
+ it 'releases the group and removes the group from the client' do
77
+ @group1.released?.must_equal true
78
+ @client.object_group('g1').must_equal nil
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,133 @@
1
+ require File.expand_path('../../helper.rb', File.dirname(__FILE__))
2
+
3
+ describe WebkitRemote::Client::RemoteObject do
4
+ before :each do
5
+ @client = WebkitRemote.local port: 9669
6
+ @client.page_events = true
7
+ @client.navigate_to fixture_url(:runtime)
8
+ @client.wait_for type: WebkitRemote::Event::PageLoaded
9
+ end
10
+ after :each do
11
+ @client.close
12
+ end
13
+
14
+ describe 'properties' do
15
+ describe 'with simple JSON' do
16
+ before :each do
17
+ @object = @client.remote_eval 'window.t = ({answer: 42, test: true})'
18
+ end
19
+
20
+ it 'enumerates the properties correctly' do
21
+ @object.properties[:answer].name.must_equal :answer
22
+ @object.properties[:test].name.must_equal :test
23
+ @object.properties[:other].must_equal nil
24
+ end
25
+
26
+ it 'gets the correct values' do
27
+ @object.properties[:answer].value.must_equal 42
28
+ @object.properties[:test].value.must_equal true
29
+ end
30
+
31
+ it 'sets owner correctly' do
32
+ @object.properties[:answer].owner.must_equal @object
33
+ end
34
+
35
+ it 'does not have extra properties' do
36
+ @object.properties.select { |name, property| property.enumerable? }.
37
+ keys.sort.must_equal [:answer, :test]
38
+ end
39
+
40
+ it 'recognizes writable properties' do
41
+ @object.properties[:answer].writable?.must_equal true
42
+ @object.properties[:constructor].writable?.must_equal false
43
+ end
44
+
45
+ it 'recognizes configurable properties' do
46
+ @object.properties[:answer].configurable?.must_equal true
47
+ @object.properties[:constructor].configurable?.must_equal false
48
+ end
49
+
50
+ it 'recognizes enumerable properties' do
51
+ @object.properties[:answer].enumerable?.must_equal true
52
+ @object.properties[:constructor].enumerable?.must_equal false
53
+ end
54
+
55
+ describe 'after property update' do
56
+ before do
57
+ @object.properties[:DONE]
58
+ @client.remote_eval 'window.t.test = "updated"'
59
+ end
60
+ it 'does not automatically refresh' do
61
+ @object.properties[:test].value.must_equal true
62
+ end
63
+ it 'refreshes when properties! is called' do
64
+ @object.properties![:test].value.must_equal 'updated'
65
+ end
66
+ end
67
+ end
68
+
69
+ describe 'with the XMHttpRequest built-in' do
70
+ before :each do
71
+ @object = @client.remote_eval 'XMLHttpRequest'
72
+ end
73
+
74
+ it 'recognizes configurable, non-writable, enumerable properties' do
75
+ @object.properties[:DONE].configurable?.must_equal true
76
+ @object.properties[:DONE].writable?.must_equal false
77
+ @object.properties[:DONE].enumerable?.must_equal true
78
+ end
79
+ end
80
+ end
81
+
82
+ describe 'bound_call' do
83
+ before :each do
84
+ @object = @client.remote_eval 'new TestClass("hello ruby")', group: 'g1'
85
+ end
86
+ after :each do
87
+ group = @client.object_group 'g1'
88
+ group.release_all if group
89
+ end
90
+
91
+ describe 'with a function that operates on primitives' do
92
+ before :each do
93
+ @result = @object.bound_call 'TestClass.prototype.add3',
94
+ ' answer:', 4, 2
95
+ end
96
+ it 'returns a native primitive type' do
97
+ @result.must_equal 'hello ruby answer:42'
98
+ end
99
+ end
100
+
101
+ describe 'with a function that returns a primitive' do
102
+ before :each do
103
+ @arg1 = @client.remote_eval 'new TestClass(" again")', group: 'g1'
104
+ @arg2 = @client.remote_eval 'new TestClass(" ruby")', group: 'g2'
105
+ @result = @object.bound_call 'TestClass.prototype.add3', ' hello',
106
+ @arg1, @arg2
107
+ end
108
+ it 'returns a native primitive type' do
109
+ @result.must_equal 'hello ruby hello again ruby'
110
+ end
111
+ end
112
+
113
+ describe 'with objects' do
114
+ before :each do
115
+ @arg1 = @client.remote_eval '({hello: "rbx", goodbye: "java"})',
116
+ group: 'g1'
117
+ @arg2 = @client.remote_eval '({hello: "jruby", goodbye: "java2"})',
118
+ group: 'g2'
119
+ @result = @object.bound_call 'TestClass.prototype.greetings',
120
+ @arg1, @arg2
121
+ end
122
+ it 'passes the objects and returns an object correctly' do
123
+ @result.must_be_kind_of WebkitRemote::Client::RemoteObject
124
+ @result.js_class_name.must_equal 'TestClass'
125
+ @result.bound_call('TestClass.prototype.toString').
126
+ must_equal 'hello ruby, rbx and jruby'
127
+ end
128
+ it 'adds the result to the target group' do
129
+ @result.group.must_equal @object.group
130
+ end
131
+ end
132
+ end
133
+ end