capybara-webkit 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. data/.gitignore +3 -1
  2. data/Gemfile.lock +5 -4
  3. data/NEWS.md +11 -0
  4. data/README.md +42 -0
  5. data/lib/capybara/driver/webkit.rb +7 -2
  6. data/lib/capybara/driver/webkit/browser.rb +22 -96
  7. data/lib/capybara/driver/webkit/connection.rb +120 -0
  8. data/lib/capybara/driver/webkit/version.rb +1 -1
  9. data/lib/capybara/webkit/matchers.rb +2 -4
  10. data/lib/capybara_webkit_builder.rb +22 -4
  11. data/spec/browser_spec.rb +19 -29
  12. data/spec/connection_spec.rb +54 -0
  13. data/spec/driver_resize_window_spec.rb +59 -0
  14. data/spec/driver_spec.rb +175 -27
  15. data/spec/spec_helper.rb +9 -2
  16. data/src/Body.h +2 -2
  17. data/src/ClearCookies.cpp +2 -5
  18. data/src/ClearCookies.h +2 -2
  19. data/src/Command.cpp +7 -3
  20. data/src/Command.h +4 -2
  21. data/src/CommandFactory.cpp +7 -2
  22. data/src/CommandFactory.h +1 -1
  23. data/src/CommandParser.cpp +13 -5
  24. data/src/CommandParser.h +6 -2
  25. data/src/Connection.cpp +18 -47
  26. data/src/Connection.h +5 -7
  27. data/src/ConsoleMessages.cpp +2 -3
  28. data/src/ConsoleMessages.h +2 -2
  29. data/src/CurrentUrl.cpp +3 -6
  30. data/src/CurrentUrl.h +2 -2
  31. data/src/Evaluate.cpp +3 -3
  32. data/src/Evaluate.h +2 -2
  33. data/src/Execute.cpp +4 -4
  34. data/src/Execute.h +2 -2
  35. data/src/Find.cpp +4 -4
  36. data/src/Find.h +2 -2
  37. data/src/FrameFocus.cpp +7 -7
  38. data/src/FrameFocus.h +2 -2
  39. data/src/GetCookies.cpp +2 -4
  40. data/src/GetCookies.h +2 -2
  41. data/src/Header.cpp +4 -4
  42. data/src/Header.h +2 -2
  43. data/src/Headers.cpp +2 -3
  44. data/src/Headers.h +2 -2
  45. data/src/IgnoreSslErrors.cpp +12 -0
  46. data/src/IgnoreSslErrors.h +12 -0
  47. data/src/NetworkAccessManager.cpp +4 -0
  48. data/src/NetworkAccessManager.h +2 -1
  49. data/src/Node.cpp +3 -3
  50. data/src/Node.h +2 -2
  51. data/src/NullCommand.cpp +10 -0
  52. data/src/NullCommand.h +11 -0
  53. data/src/PageLoadingCommand.cpp +46 -0
  54. data/src/PageLoadingCommand.h +40 -0
  55. data/src/Render.cpp +5 -6
  56. data/src/Render.h +2 -2
  57. data/src/RequestedUrl.cpp +3 -6
  58. data/src/RequestedUrl.h +2 -2
  59. data/src/Reset.cpp +8 -7
  60. data/src/Reset.h +2 -2
  61. data/src/ResizeWindow.cpp +16 -0
  62. data/src/ResizeWindow.h +12 -0
  63. data/src/Response.cpp +6 -1
  64. data/src/Response.h +4 -2
  65. data/src/Server.cpp +2 -3
  66. data/src/Server.h +1 -1
  67. data/src/SetCookie.cpp +3 -5
  68. data/src/SetCookie.h +2 -2
  69. data/src/SetProxy.cpp +7 -9
  70. data/src/SetProxy.h +2 -2
  71. data/src/Source.cpp +2 -4
  72. data/src/Source.h +2 -2
  73. data/src/Status.cpp +2 -3
  74. data/src/Status.h +2 -2
  75. data/src/Url.cpp +3 -6
  76. data/src/Url.h +2 -2
  77. data/src/Visit.cpp +4 -13
  78. data/src/Visit.h +2 -5
  79. data/src/WebPage.cpp +11 -9
  80. data/src/WebPage.h +3 -3
  81. data/src/body.cpp +2 -3
  82. data/src/capybara.js +58 -3
  83. data/src/find_command.h +3 -1
  84. data/src/main.cpp +1 -2
  85. data/src/webkit_server.pro +8 -0
  86. metadata +29 -16
@@ -22,29 +22,47 @@ module CapybaraWebkitBuilder
22
22
  "linux-g++"
23
23
  when /freebsd/
24
24
  "freebsd-g++"
25
+ when /mingw32/
26
+ "win32-g++"
25
27
  else
26
28
  "macx-g++"
27
29
  end
28
30
  end
29
31
 
30
32
  def makefile
31
- system("LANG='en_US.UTF-8' #{qmake_bin} -spec #{spec}")
33
+ system("#{qmake_bin} -spec #{spec}")
32
34
  end
33
35
 
34
36
  def qmake
35
- system("LANG='en_US.UTF-8' #{make_bin} qmake")
37
+ system("#{make_bin} qmake")
38
+ end
39
+
40
+ def path_to_binary
41
+ case RUBY_PLATFORM
42
+ when /mingw32/
43
+ "src/debug/webkit_server.exe"
44
+ else
45
+ "src/webkit_server"
46
+ end
36
47
  end
37
48
 
38
49
  def build
39
50
  system(make_bin) or return false
40
51
 
41
52
  FileUtils.mkdir("bin") unless File.directory?("bin")
42
- FileUtils.cp("src/webkit_server", "bin", :preserve => true)
53
+ FileUtils.cp(path_to_binary, "bin", :preserve => true)
54
+ end
55
+
56
+ def clean
57
+ File.open("Makefile", "w") do |file|
58
+ file.print "all:\n\t@echo ok\ninstall:\n\t@echo ok"
59
+ end
43
60
  end
44
61
 
45
62
  def build_all
46
63
  makefile &&
47
64
  qmake &&
48
- build
65
+ build &&
66
+ clean
49
67
  end
50
68
  end
data/spec/browser_spec.rb CHANGED
@@ -2,42 +2,19 @@ require 'spec_helper'
2
2
  require 'self_signed_ssl_cert'
3
3
  require 'stringio'
4
4
  require 'capybara/driver/webkit/browser'
5
+ require 'capybara/driver/webkit/connection'
5
6
  require 'socket'
6
7
  require 'base64'
7
8
 
8
9
  describe Capybara::Driver::Webkit::Browser do
9
10
 
10
- let(:browser) { Capybara::Driver::Webkit::Browser.new }
11
- let(:browser_ignore_ssl_err) {
12
- Capybara::Driver::Webkit::Browser.new(:ignore_ssl_errors => true)
13
- }
14
-
15
- describe '#server_port' do
16
- subject { browser.server_port }
17
- it 'returns a valid port number' do
18
- should be_a(Integer)
19
- end
20
-
21
- it 'returns a port in the allowed range' do
22
- should be_between 0x400, 0xffff
11
+ let(:browser) { Capybara::Driver::Webkit::Browser.new(Capybara::Driver::Webkit::Connection.new) }
12
+ let(:browser_ignore_ssl_err) do
13
+ Capybara::Driver::Webkit::Browser.new(Capybara::Driver::Webkit::Connection.new).tap do |browser|
14
+ browser.ignore_ssl_errors
23
15
  end
24
16
  end
25
17
 
26
- context 'random port' do
27
- it 'chooses a new port number for a new browser instance' do
28
- new_browser = Capybara::Driver::Webkit::Browser.new
29
- new_browser.server_port.should_not == browser.server_port
30
- end
31
- end
32
-
33
- it 'forwards stdout to the given IO object' do
34
- io = StringIO.new
35
- new_browser = Capybara::Driver::Webkit::Browser.new(:stdout => io)
36
- new_browser.execute_script('console.log("hello world")')
37
- sleep(0.5)
38
- io.string.should include "hello world\n"
39
- end
40
-
41
18
  context 'handling of SSL validation errors' do
42
19
  before do
43
20
  # set up minimal HTTPS server
@@ -81,7 +58,8 @@ describe Capybara::Driver::Webkit::Browser do
81
58
  browser_ignore_ssl_err.visit "https://#{@host}:#{@port}/"
82
59
  end
83
60
  end
84
- describe "forking" do
61
+
62
+ describe "forking", :skip_on_windows => true do
85
63
  it "only shuts down the server from the main process" do
86
64
  browser.reset!
87
65
  pid = fork {}
@@ -180,4 +158,16 @@ describe Capybara::Driver::Webkit::Browser do
180
158
  @proxy_requests.size.should == 0
181
159
  end
182
160
  end
161
+
162
+ it "doesn't try to read an empty response" do
163
+ connection = stub("connection")
164
+ connection.stub(:puts)
165
+ connection.stub(:print)
166
+ connection.stub(:gets).and_return("ok\n", "0\n")
167
+ connection.stub(:read).and_raise(StandardError.new("tried to read empty response"))
168
+
169
+ browser = Capybara::Driver::Webkit::Browser.new(connection)
170
+
171
+ expect { browser.visit("/") }.not_to raise_error(/empty response/)
172
+ end
183
173
  end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+ require 'capybara/driver/webkit/connection'
3
+
4
+ describe Capybara::Driver::Webkit::Connection do
5
+ it "boots a server to talk to" do
6
+ url = @rack_server.url("/")
7
+ connection.puts "Visit"
8
+ connection.puts 1
9
+ connection.puts url.to_s.bytesize
10
+ connection.print url
11
+ connection.gets.should == "ok\n"
12
+ connection.gets.should == "0\n"
13
+ connection.puts "Body"
14
+ connection.puts 0
15
+ connection.gets.should == "ok\n"
16
+ response_length = connection.gets.to_i
17
+ response = connection.read(response_length)
18
+ response.should include("Hey there")
19
+ end
20
+
21
+ it 'forwards stdout to the given IO object' do
22
+ io = StringIO.new
23
+ redirected_connection = Capybara::Driver::Webkit::Connection.new(:stdout => io)
24
+ script = 'console.log("hello world")'
25
+ redirected_connection.puts "Execute"
26
+ redirected_connection.puts 1
27
+ redirected_connection.puts script.to_s.bytesize
28
+ redirected_connection.print script
29
+ sleep(0.5)
30
+ io.string.should include "hello world\n"
31
+ end
32
+
33
+ it "returns the server port" do
34
+ connection.port.should be_between 0x400, 0xffff
35
+ end
36
+
37
+ it "chooses a new port number for a new connection" do
38
+ new_connection = Capybara::Driver::Webkit::Connection.new
39
+ new_connection.port.should_not == connection.port
40
+ end
41
+
42
+ let(:connection) { Capybara::Driver::Webkit::Connection.new }
43
+
44
+ before(:all) do
45
+ @app = lambda do |env|
46
+ body = "<html><body>Hey there</body></html>"
47
+ [200,
48
+ { 'Content-Type' => 'text/html', 'Content-Length' => body.size.to_s },
49
+ [body]]
50
+ end
51
+ @rack_server = Capybara::Server.new(@app)
52
+ @rack_server.boot
53
+ end
54
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+ require 'capybara/driver/webkit'
3
+
4
+ describe Capybara::Driver::Webkit, "#resize_window(width, height)" do
5
+
6
+ before(:all) do
7
+ app = lambda do |env|
8
+ body = <<-HTML
9
+ <html>
10
+ <body>
11
+ <h1 id="dimentions">UNKNOWN</h1>
12
+
13
+ <script>
14
+ window.onload = window.onresize = function(){
15
+ document.getElementById("dimentions").innerHTML = "[" + window.innerWidth + "x" + window.innerHeight + "]";
16
+ };
17
+ </script>
18
+
19
+ </body>
20
+ </html>
21
+ HTML
22
+
23
+ [
24
+ 200,
25
+ { 'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s },
26
+ [body]
27
+ ]
28
+ end
29
+
30
+ @driver = Capybara::Driver::Webkit.new(app, :browser => $webkit_browser)
31
+ end
32
+
33
+ DEFAULT_DIMENTIONS = "[1680x1050]"
34
+
35
+ it "resizes the window to the specified size" do
36
+ @driver.visit("/")
37
+
38
+ @driver.resize_window(800, 600)
39
+ @driver.body.should include("[800x600]")
40
+
41
+ @driver.resize_window(300, 100)
42
+ @driver.body.should include("[300x100]")
43
+ end
44
+
45
+ it "resizes the window to the specified size even before the document has loaded" do
46
+ @driver.resize_window(800, 600)
47
+ @driver.visit("/")
48
+ @driver.body.should include("[800x600]")
49
+ end
50
+
51
+ it "resets the window to the default size when the driver is reset" do
52
+ @driver.resize_window(800, 600)
53
+ @driver.reset!
54
+ @driver.visit("/")
55
+ @driver.body.should include(DEFAULT_DIMENTIONS)
56
+ end
57
+
58
+ after(:all) { @driver.reset! }
59
+ end
data/spec/driver_spec.rb CHANGED
@@ -659,6 +659,7 @@ describe Capybara::Driver::Webkit do
659
659
  element.addEventListener("keydown", recordEvent);
660
660
  element.addEventListener("keypress", recordEvent);
661
661
  element.addEventListener("keyup", recordEvent);
662
+ element.addEventListener("input", recordEvent);
662
663
  element.addEventListener("change", recordEvent);
663
664
  element.addEventListener("blur", recordEvent);
664
665
  element.addEventListener("mousedown", recordEvent);
@@ -678,7 +679,7 @@ describe Capybara::Driver::Webkit do
678
679
 
679
680
  let(:keyevents) do
680
681
  (%w{focus} +
681
- newtext.length.times.collect { %w{keydown keypress keyup} } +
682
+ newtext.length.times.collect { %w{keydown keypress keyup input} } +
682
683
  %w{change blur}).flatten
683
684
  end
684
685
 
@@ -987,15 +988,15 @@ describe Capybara::Driver::Webkit do
987
988
  end
988
989
 
989
990
  def make_the_server_come_back
990
- subject.browser.instance_variable_get(:@socket).unstub!(:gets)
991
- subject.browser.instance_variable_get(:@socket).unstub!(:puts)
992
- subject.browser.instance_variable_get(:@socket).unstub!(:print)
991
+ subject.browser.instance_variable_get(:@connection).unstub!(:gets)
992
+ subject.browser.instance_variable_get(:@connection).unstub!(:puts)
993
+ subject.browser.instance_variable_get(:@connection).unstub!(:print)
993
994
  end
994
995
 
995
996
  def make_the_server_go_away
996
- subject.browser.instance_variable_get(:@socket).stub!(:gets).and_return(nil)
997
- subject.browser.instance_variable_get(:@socket).stub!(:puts)
998
- subject.browser.instance_variable_get(:@socket).stub!(:print)
997
+ subject.browser.instance_variable_get(:@connection).stub!(:gets).and_return(nil)
998
+ subject.browser.instance_variable_get(:@connection).stub!(:puts)
999
+ subject.browser.instance_variable_get(:@connection).stub!(:print)
999
1000
  end
1000
1001
  end
1001
1002
 
@@ -1090,7 +1091,8 @@ describe Capybara::Driver::Webkit do
1090
1091
  context "with socket debugger" do
1091
1092
  let(:socket_debugger_class){ Capybara::Driver::Webkit::SocketDebugger }
1092
1093
  let(:browser_with_debugger){
1093
- Capybara::Driver::Webkit::Browser.new(:socket_class => socket_debugger_class)
1094
+ connection = Capybara::Driver::Webkit::Connection.new(:socket_class => socket_debugger_class)
1095
+ Capybara::Driver::Webkit::Browser.new(connection)
1094
1096
  }
1095
1097
  let(:driver_with_debugger){ Capybara::Driver::Webkit.new(@app, :browser => browser_with_debugger) }
1096
1098
 
@@ -1276,6 +1278,39 @@ describe Capybara::Driver::Webkit do
1276
1278
  end
1277
1279
  end
1278
1280
 
1281
+ context "localStorage works" do
1282
+ before(:all) do
1283
+ @app = lambda do |env|
1284
+ body = <<-HTML
1285
+ <html>
1286
+ <body>
1287
+ <span id='output'></span>
1288
+ <script type="text/javascript">
1289
+ if (typeof localStorage !== "undefined") {
1290
+ if (!localStorage.refreshCounter) {
1291
+ localStorage.refreshCounter = 0;
1292
+ }
1293
+ if (localStorage.refreshCounter++ > 0) {
1294
+ document.getElementById("output").innerHTML = "localStorage is enabled";
1295
+ }
1296
+ }
1297
+ </script>
1298
+ </body>
1299
+ </html>
1300
+ HTML
1301
+ [200,
1302
+ { 'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s },
1303
+ [body]]
1304
+ end
1305
+ end
1306
+
1307
+ it "displays the message on subsequent page loads" do
1308
+ subject.find("//span[contains(.,'localStorage is enabled')]").should be_empty
1309
+ subject.visit "/"
1310
+ subject.find("//span[contains(.,'localStorage is enabled')]").should_not be_empty
1311
+ end
1312
+ end
1313
+
1279
1314
  context "app with a lot of HTML tags" do
1280
1315
  before(:all) do
1281
1316
  @app = lambda do |env|
@@ -1372,33 +1407,146 @@ describe Capybara::Driver::Webkit do
1372
1407
  end
1373
1408
  end
1374
1409
 
1410
+ def key_app_body(event)
1411
+ body = <<-HTML
1412
+ <html>
1413
+ <head><title>Form</title></head>
1414
+ <body>
1415
+ <div id="charcode_value"></div>
1416
+ <div id="keycode_value"></div>
1417
+ <div id="which_value"></div>
1418
+ <input type="text" id="charcode" name="charcode" on#{event}="setcharcode" />
1419
+ <script type="text/javascript">
1420
+ var element = document.getElementById("charcode")
1421
+ element.addEventListener("#{event}", setcharcode);
1422
+ function setcharcode(event) {
1423
+ var element = document.getElementById("charcode_value");
1424
+ element.innerHTML = event.charCode;
1425
+ element = document.getElementById("keycode_value");
1426
+ element.innerHTML = event.keyCode;
1427
+ element = document.getElementById("which_value");
1428
+ element.innerHTML = event.which;
1429
+ }
1430
+ </script>
1431
+ </body>
1432
+ </html>
1433
+ HTML
1434
+ body
1435
+ end
1436
+
1437
+ def charCode_for(character)
1438
+ subject.find("//input")[0].set(character)
1439
+ subject.find("//div[@id='charcode_value']")[0].text
1440
+ end
1441
+
1442
+ def keyCode_for(character)
1443
+ subject.find("//input")[0].set(character)
1444
+ subject.find("//div[@id='keycode_value']")[0].text
1445
+ end
1446
+
1447
+ def which_for(character)
1448
+ subject.find("//input")[0].set(character)
1449
+ subject.find("//div[@id='which_value']")[0].text
1450
+ end
1451
+
1375
1452
  context "keypress app" do
1376
1453
  before(:all) do
1377
1454
  @app = lambda do |env|
1378
- body = <<-HTML
1379
- <html>
1380
- <head><title>Form</title></head>
1381
- <body>
1382
- <div id="charcode_value"></div>
1383
- <input type="text" id="charcode" name="charcode" onkeypress="setcharcode" />
1384
- <script type="text/javascript">
1385
- var element = document.getElementById("charcode")
1386
- element.addEventListener("keypress", setcharcode);
1387
- function setcharcode(event) {
1388
- var element = document.getElementById("charcode_value");
1389
- element.innerHTML = event.charCode;
1390
- }
1391
- </script>
1392
- </body>
1393
- </html>
1394
- HTML
1455
+ body = key_app_body("keypress")
1395
1456
  [200, { 'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s }, [body]]
1396
1457
  end
1397
1458
  end
1398
1459
 
1399
1460
  it "returns the charCode for the keypressed" do
1400
- subject.find("//input")[0].set("a")
1401
- subject.find("//div")[0].text.should == "97"
1461
+ charCode_for("a").should == "97"
1462
+ charCode_for("A").should == "65"
1463
+ charCode_for("\r").should == "13"
1464
+ charCode_for(",").should == "44"
1465
+ charCode_for("<").should == "60"
1466
+ charCode_for("0").should == "48"
1467
+ end
1468
+
1469
+ it "returns the keyCode for the keypressed" do
1470
+ keyCode_for("a").should == "97"
1471
+ keyCode_for("A").should == "65"
1472
+ keyCode_for("\r").should == "13"
1473
+ keyCode_for(",").should == "44"
1474
+ keyCode_for("<").should == "60"
1475
+ keyCode_for("0").should == "48"
1476
+ end
1477
+
1478
+ it "returns the which for the keypressed" do
1479
+ which_for("a").should == "97"
1480
+ which_for("A").should == "65"
1481
+ which_for("\r").should == "13"
1482
+ which_for(",").should == "44"
1483
+ which_for("<").should == "60"
1484
+ which_for("0").should == "48"
1485
+ end
1486
+ end
1487
+
1488
+ shared_examples "a keyupdown app" do
1489
+ it "returns a 0 charCode for the event" do
1490
+ charCode_for("a").should == "0"
1491
+ charCode_for("A").should == "0"
1492
+ charCode_for("\r").should == "0"
1493
+ charCode_for(",").should == "0"
1494
+ charCode_for("<").should == "0"
1495
+ charCode_for("0").should == "0"
1496
+ end
1497
+
1498
+ it "returns the keyCode for the event" do
1499
+ keyCode_for("a").should == "65"
1500
+ keyCode_for("A").should == "65"
1501
+ keyCode_for("\r").should == "13"
1502
+ keyCode_for(",").should == "188"
1503
+ keyCode_for("<").should == "188"
1504
+ keyCode_for("0").should == "48"
1505
+ end
1506
+
1507
+ it "returns the which for the event" do
1508
+ which_for("a").should == "65"
1509
+ which_for("A").should == "65"
1510
+ which_for("\r").should == "13"
1511
+ which_for(",").should == "188"
1512
+ which_for("<").should == "188"
1513
+ which_for("0").should == "48"
1514
+ end
1515
+ end
1516
+
1517
+ context "keydown app" do
1518
+ before(:all) do
1519
+ @app = lambda do |env|
1520
+ body = key_app_body("keydown")
1521
+ [200, { 'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s }, [body]]
1522
+ end
1523
+ end
1524
+ it_behaves_like "a keyupdown app"
1525
+ end
1526
+
1527
+ context "keyup app" do
1528
+ before(:all) do
1529
+ @app = lambda do |env|
1530
+ body = key_app_body("keyup")
1531
+ [200, { 'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s }, [body]]
1532
+ end
1533
+ end
1534
+
1535
+ it_behaves_like "a keyupdown app"
1536
+ end
1537
+
1538
+ context "null byte app" do
1539
+ before(:all) do
1540
+ @app = lambda do |env|
1541
+ body = "Hello\0World"
1542
+ [200,
1543
+ { 'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s },
1544
+ [body]]
1545
+ end
1546
+ end
1547
+
1548
+ it "should include all the bytes in the source" do
1549
+ subject.source.should == "Hello\0World"
1402
1550
  end
1403
1551
  end
1404
1552
  end