transactional_capybara 0.1.0.pre.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1734358fb0654defcb9c353940bf2e34ab7da006
4
- data.tar.gz: caa82834cde32a345c9fd643b037d30e26d333f9
3
+ metadata.gz: b47fe9a7d758b60e2a61d02a9efc54683c04c958
4
+ data.tar.gz: 2fad7e2694272847292391264521c9edac1ec55b
5
5
  SHA512:
6
- metadata.gz: 20c099399240513932b8814c8d5f18a40c77c59066768329014e4bef6592daeed2381c8f38a14832e109df98588b490017d372748d605b7890ced743578f02cf
7
- data.tar.gz: 6a21b2f64c446f345ba7d2ecc5a43ed2ca1232c373c5a35ab45cc078e9e988af29a5637a28353c6a360a0560924d77cd32e7d32523468b39ccaccf573ba11fa1
6
+ metadata.gz: 489e7e2d50f51dcb9d15fe8eb9198d2b09c71b394157e704ecbe9360e8070b63f8890f60834f9889ec560ced5fe84881610b7b35cf19a4be325d391272597672
7
+ data.tar.gz: d2fd46c45b0cc39fa8acfe71b538be2988cd9fa956571693378936e4a9a7f319462245122927b3eb074eea7296bbb25527743ca1cb46b31a21a129b880949c01
data/.gitignore CHANGED
@@ -3,7 +3,6 @@
3
3
  .bundle
4
4
  .config
5
5
  .yardoc
6
- Gemfile.lock
7
6
  InstalledFiles
8
7
  _yardoc
9
8
  coverage
@@ -1 +1 @@
1
- 2.2.2
1
+ 2.3.1
@@ -4,6 +4,7 @@ rvm:
4
4
  - "2.0"
5
5
  - "2.1"
6
6
  - "2.2"
7
+ - "2.3.1"
7
8
  before_install:
8
9
  - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16"
9
10
  - "export DISPLAY=:99.0"
@@ -12,4 +13,4 @@ before_script:
12
13
  - psql -c 'create database transactional_capybara_test;' -U postgres
13
14
  - "cp spec/{.travis.,}config.yml"
14
15
  script: bundle exec rake test:all
15
- sudo: false
16
+ cache: bundler
@@ -0,0 +1,113 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ transactional_capybara (0.1.0.pre.3)
5
+ capybara
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activemodel (4.2.4)
11
+ activesupport (= 4.2.4)
12
+ builder (~> 3.1)
13
+ activerecord (4.2.4)
14
+ activemodel (= 4.2.4)
15
+ activesupport (= 4.2.4)
16
+ arel (~> 6.0)
17
+ activesupport (4.2.4)
18
+ i18n (~> 0.7)
19
+ json (~> 1.7, >= 1.7.7)
20
+ minitest (~> 5.1)
21
+ thread_safe (~> 0.3, >= 0.3.4)
22
+ tzinfo (~> 1.1)
23
+ arel (6.0.3)
24
+ builder (3.2.2)
25
+ capybara (2.4.4)
26
+ mime-types (>= 1.16)
27
+ nokogiri (>= 1.3.3)
28
+ rack (>= 1.0.0)
29
+ rack-test (>= 0.5.4)
30
+ xpath (~> 2.0)
31
+ capybara-webkit (1.6.0)
32
+ capybara (>= 2.3.0, < 2.5.0)
33
+ json
34
+ childprocess (0.5.6)
35
+ ffi (~> 1.0, >= 1.0.11)
36
+ cliver (0.3.2)
37
+ diff-lcs (1.2.5)
38
+ ffi (1.9.10)
39
+ i18n (0.7.0)
40
+ json (1.8.3)
41
+ mime-types (2.6.1)
42
+ mini_portile (0.6.2)
43
+ minitest (5.8.0)
44
+ multi_json (1.11.2)
45
+ mysql2 (0.3.20)
46
+ nokogiri (1.6.6.2)
47
+ mini_portile (~> 0.6.0)
48
+ pg (0.18.2)
49
+ poltergeist (1.6.0)
50
+ capybara (~> 2.1)
51
+ cliver (~> 0.3.1)
52
+ multi_json (~> 1.0)
53
+ websocket-driver (>= 0.2.0)
54
+ rack (1.6.4)
55
+ rack-protection (1.5.3)
56
+ rack
57
+ rack-test (0.6.3)
58
+ rack (>= 1.0)
59
+ rake (10.4.2)
60
+ rspec (3.3.0)
61
+ rspec-core (~> 3.3.0)
62
+ rspec-expectations (~> 3.3.0)
63
+ rspec-mocks (~> 3.3.0)
64
+ rspec-core (3.3.1)
65
+ rspec-support (~> 3.3.0)
66
+ rspec-expectations (3.3.0)
67
+ diff-lcs (>= 1.2.0, < 2.0)
68
+ rspec-support (~> 3.3.0)
69
+ rspec-mocks (3.3.1)
70
+ diff-lcs (>= 1.2.0, < 2.0)
71
+ rspec-support (~> 3.3.0)
72
+ rspec-support (3.3.0)
73
+ rubyzip (1.1.7)
74
+ selenium-webdriver (2.47.1)
75
+ childprocess (~> 0.5)
76
+ multi_json (~> 1.0)
77
+ rubyzip (~> 1.0)
78
+ websocket (~> 1.0)
79
+ sinatra (1.4.6)
80
+ rack (~> 1.4)
81
+ rack-protection (~> 1.4)
82
+ tilt (>= 1.3, < 3)
83
+ sqlite3 (1.3.10)
84
+ thread_safe (0.3.5)
85
+ tilt (2.0.1)
86
+ tzinfo (1.2.2)
87
+ thread_safe (~> 0.1)
88
+ websocket (1.2.2)
89
+ websocket-driver (0.6.2)
90
+ websocket-extensions (>= 0.1.0)
91
+ websocket-extensions (0.1.2)
92
+ xpath (2.0.0)
93
+ nokogiri (~> 1.3)
94
+
95
+ PLATFORMS
96
+ ruby
97
+
98
+ DEPENDENCIES
99
+ activerecord
100
+ bundler (~> 1.3)
101
+ capybara-webkit
102
+ mysql2
103
+ pg
104
+ poltergeist
105
+ rake
106
+ rspec
107
+ selenium-webdriver
108
+ sinatra
109
+ sqlite3
110
+ transactional_capybara!
111
+
112
+ BUNDLED WITH
113
+ 1.12.5
data/README.md CHANGED
@@ -1,12 +1,16 @@
1
1
  # Database Transactions 💜 Capybara
2
2
 
3
- You want your specs to use transactions for speed 🐎🐎🐎.
3
+ [![Build Status]](https://travis-ci.org/iangreenleaf/transactional_capybara)
4
4
 
5
- But as soon as you try it with Capybara, things go wrong 💻💥.
5
+ You want your specs to use transactions for speed 🐎🐎🐎
6
+
7
+ But as soon as you try it with Capybara, things go wrong 💻💥
6
8
 
7
9
  Don't flip tables.
8
10
  Use this instead.
9
11
 
12
+ For a detailed explanation of how this works, refer to the [introductory blog post].
13
+
10
14
  ## Setup ##
11
15
 
12
16
  Add it to your Gemfile, of course:
@@ -47,6 +51,50 @@ after :each do
47
51
  end
48
52
  ```
49
53
 
54
+ ## Manually waiting for AJAX ##
55
+
56
+ You might have situations where you need to wait for AJAX calls to complete at times other than teardown.
57
+ For example, you might have a pattern like this if you access models directly for either setup or verification of results:
58
+
59
+ ```ruby
60
+ visit "/page-that-fires-ajax"
61
+ Model.where(whatever).first
62
+ ```
63
+
64
+ This can still fail!
65
+ The ideal solution is to avoid direct database manipulation in integration tests.
66
+ However, if you insist on doing this, you can stay safe by waiting for AJAX to complete before continuing:
67
+
68
+ ```ruby
69
+ visit "/page-that-fires-ajax"
70
+ TransactionalCapybara::AjaxHelpers.wait_for_ajax(page)
71
+ Model.where(whatever).first
72
+ ```
73
+
74
+ If you'd like the helper more easily accessible, just mix the `AjaxHelpers` module into your test suite.
75
+ In RSpec, you can do this in the config block:
76
+
77
+ ```ruby
78
+ RSpec.configure do |config|
79
+ config.include TransactionalCapybara::AjaxHelpers
80
+ end
81
+ ```
82
+ Or in any example group:
83
+
84
+ ```ruby
85
+ describe "awesome web stuff" do
86
+ include TransactionalCapybara::AjaxHelpers
87
+ end
88
+ ```
89
+
90
+ Now the helper is easily available:
91
+
92
+ ```ruby
93
+ visit "/page-that-fires-ajax"
94
+ wait_for_ajax
95
+ Model.where(whatever).first
96
+ ```
97
+
50
98
  ## DatabaseCleaner ##
51
99
 
52
100
  For this gem to be able to help with AJAX, it needs to be invoked *before* DatabaseCleaner rolls back the transaction.
@@ -99,6 +147,8 @@ Right now this gem automatically fixes the following things:
99
147
  * jQuery
100
148
  * Angular
101
149
 
150
+ Tested on Capybara 2.4.x, may not work on other major versions.
151
+
102
152
  Don't see something you want?
103
153
  I'd love a pull request, or even just a friendly inquiry!
104
154
 
@@ -106,9 +156,9 @@ I'd love a pull request, or even just a friendly inquiry!
106
156
 
107
157
  1. Fork it
108
158
  2. Create your feature branch (`git checkout -b my-new-feature`)
159
+ 3. Make your changes. Don't forget to add a test!
109
160
  3. Commit your changes (`git commit -am 'Add some feature'`)
110
161
  4. Push to the branch (`git push origin my-new-feature`)
111
- 5. Think about how I'm a bad person for not writing any tests yet
112
162
  6. Create new Pull Request
113
163
 
114
164
  ### Running the tests ###
@@ -119,3 +169,6 @@ DB=sqlite rspec spec
119
169
  ```
120
170
 
121
171
  You can run the specs with other databases as well, but you will have to create the databases and users manually first.
172
+
173
+ [Build Status]: https://travis-ci.org/iangreenleaf/transactional_capybara.svg?branch=master
174
+ [introductory blog post]: http://technotes.iangreenleaf.com/posts/the-one-true-guide-to-database-transactions-with-capybara.html
data/Rakefile CHANGED
@@ -11,7 +11,7 @@ namespace :test do
11
11
  db_config = YAML.load_file(File.join(File.dirname(__FILE__), "spec/config.yml"))
12
12
  db_config["database"].keys.each do |db_name|
13
13
  ENV['DB'] = db_name
14
- %w[selenium webkit].each do |driver|
14
+ %w[selenium webkit poltergeist].each do |driver|
15
15
  ENV['DRIVER'] = driver
16
16
  puts ENV.to_hash.slice 'DRIVER', 'DB'
17
17
  Rake::Task['test:rspec'].reenable
@@ -19,4 +19,19 @@ namespace :test do
19
19
  end
20
20
  end
21
21
  end
22
+
23
+ desc "Run the test server for manual debugging"
24
+ task :server do
25
+ db_type = ENV['DB'] || 'sqlite'
26
+ db_config = YAML.load_file(File.join(File.dirname(__FILE__), "spec/config.yml"))
27
+ db = db_config["database"][db_type]
28
+ require 'active_record'
29
+ ActiveRecord::Base.establish_connection(db)
30
+ load File.join(File.dirname(__FILE__), "spec/support/schema.rb")
31
+ require_relative './spec/support/server'
32
+ require_relative './spec/support/model'
33
+ TestValue.create! content: "This is a server response"
34
+ AjaxServer.should_return_from_ajax = true
35
+ AjaxServer.run!
36
+ end
22
37
  end
@@ -20,14 +20,11 @@ module TransactionalCapybara
20
20
  end
21
21
 
22
22
  def finished_ajax_requests?
23
- (
24
- angular_requests
25
- + jquery_requests
26
- ).zero?
23
+ ( angular_requests + jquery_requests ).zero?
27
24
  end
28
25
 
29
26
  # TODO: timeout each individual session
30
- def wait_until(timeout=Capybara.default_wait_time)
27
+ def wait_until(timeout=default_timeout)
31
28
  Timeout.timeout(timeout) do
32
29
  until yield
33
30
  sleep(0.01)
@@ -44,6 +41,16 @@ module TransactionalCapybara
44
41
  Capybara.send :session_pool
45
42
  end
46
43
 
44
+ # Handle Capybara.default_wait_time deprecation
45
+ # https://github.com/jnicklas/capybara/pull/1502
46
+ def default_timeout
47
+ @default_timeout ||= begin
48
+ Capybara.respond_to?(:default_max_wait_time) ?
49
+ Capybara.default_max_wait_time :
50
+ Capybara.default_wait_time
51
+ end
52
+ end
53
+
47
54
  # Another hack, to see if Capybara sessions have been used
48
55
  def is_session_touched?(session)
49
56
  session.instance_variable_get(:@touched)
@@ -54,12 +61,12 @@ module TransactionalCapybara
54
61
  end
55
62
 
56
63
  def angular?
57
- run_js("!!window.angular") && run_js("angular.element('[ng-app]').length") > 0
64
+ run_js("!!window.angular") && run_js("!!document.querySelector('[ng-app]')")
58
65
  end
59
66
 
60
67
  def angular_requests
61
68
  if angular?
62
- run_js("angular.element('[ng-app]').injector().get('$http').pendingRequests.length")
69
+ run_js("angular.element(document.querySelector('[ng-app]')).injector().get('$http').pendingRequests.length")
63
70
  else
64
71
  0
65
72
  end
@@ -1,3 +1,3 @@
1
1
  module TransactionalCapybara
2
- VERSION = "0.1.0.pre.3"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -9,9 +9,10 @@ RSpec.describe "server with AJAX", type: :feature, js: true do
9
9
  TestValue.create! content: @expected_message
10
10
  end
11
11
 
12
- it "waits for AJAX" do
13
- visit "/page_with_ajax"
12
+ it "waits for AJAX from jQuery" do
13
+ visit "/ajax/jquery"
14
14
  expect(page).to have_content("Hello")
15
+ click_link "Do AJAX"
15
16
  Thread.fork do
16
17
  sleep 0.5
17
18
  AjaxServer.should_return_from_ajax = true
@@ -21,10 +22,40 @@ RSpec.describe "server with AJAX", type: :feature, js: true do
21
22
  expect(find(".message").text).to eq(@expected_message)
22
23
  end
23
24
 
25
+ it "waits for AJAX from Angular" do
26
+ visit "/ajax/angular"
27
+ expect(page).to have_content("Hello")
28
+ click_link "Do AJAX"
29
+ Thread.fork do
30
+ sleep 0.5
31
+ AjaxServer.should_return_from_ajax = true
32
+ end
33
+ expect(find(".message").text).not_to eq(@expected_message)
34
+ TransactionalCapybara::AjaxHelpers.wait_for_ajax(page)
35
+ expect(find(".message").text).to eq(@expected_message)
36
+ end
37
+
38
+ context "mixed in" do
39
+ include TransactionalCapybara::AjaxHelpers
40
+ it "provides wait_for_ajax helper" do
41
+ visit "/ajax/jquery"
42
+ expect(page).to have_content("Hello")
43
+ click_link "Do AJAX"
44
+ Thread.fork do
45
+ sleep 0.5
46
+ AjaxServer.should_return_from_ajax = true
47
+ end
48
+ expect(find(".message").text).not_to eq(@expected_message)
49
+ wait_for_ajax
50
+ expect(find(".message").text).to eq(@expected_message)
51
+ end
52
+ end
53
+
24
54
  context "after hook", check_result_after: true do
25
55
  it "automatically waits for AJAX" do
26
- visit "/page_with_ajax"
56
+ visit "/ajax/jquery"
27
57
  expect(page).to have_content("Hello")
58
+ click_link "Do AJAX"
28
59
  Thread.fork do
29
60
  sleep 0.5
30
61
  AjaxServer.should_return_from_ajax = true
@@ -35,8 +66,9 @@ RSpec.describe "server with AJAX", type: :feature, js: true do
35
66
 
36
67
  it "waits on all sessions" do
37
68
  using_session :foo do
38
- visit "/page_with_ajax"
69
+ visit "/ajax/jquery"
39
70
  expect(page).to have_content("Hello")
71
+ click_link "Do AJAX"
40
72
  end
41
73
 
42
74
  using_session :bar do
@@ -57,8 +89,9 @@ RSpec.describe "server with AJAX", type: :feature, js: true do
57
89
  AjaxServer.should_return_from_ajax = false
58
90
 
59
91
  using_session :bar do
60
- visit "/page_with_ajax"
92
+ visit "/ajax/jquery"
61
93
  expect(page).to have_content("Hello")
94
+ click_link "Do AJAX"
62
95
  end
63
96
 
64
97
  Thread.fork do
@@ -71,4 +104,18 @@ RSpec.describe "server with AJAX", type: :feature, js: true do
71
104
  expect(find(".message").text).to eq(@expected_message)
72
105
  end
73
106
  end
107
+
108
+ it "uses Capybara.default_max_wait_time if available" do
109
+ allow(Capybara).to receive(:default_max_wait_time).and_return(5)
110
+ expect(Capybara).to receive(:default_max_wait_time).at_least(:once)
111
+
112
+ TransactionalCapybara::AjaxHelpers.wait_for_ajax(page)
113
+ end
114
+
115
+ it "fallbacks on deprecated Capybara.default_wait_time" do
116
+ allow(Capybara).to receive(:respond_to?).with(:default_max_wait_time).and_return(false)
117
+ expect(Capybara).to receive(:default_wait_time).at_least(:once)
118
+
119
+ TransactionalCapybara::AjaxHelpers.wait_for_ajax(page)
120
+ end
74
121
  end
@@ -8,6 +8,7 @@ ActiveRecord::Base.establish_connection(db)
8
8
  load File.join(File.dirname(__FILE__), "support/schema.rb")
9
9
 
10
10
  require 'capybara/rspec'
11
+ require 'capybara/poltergeist'
11
12
  require 'capybara-webkit'
12
13
 
13
14
  capybara_driver = ENV['DRIVER'] || 'selenium'
@@ -3,17 +3,23 @@ require 'tilt/erb'
3
3
  require_relative 'model'
4
4
 
5
5
  class AjaxServer < Sinatra::Base
6
+ set :public_folder, File.dirname(__FILE__) + '/vendor'
7
+
6
8
  cattr_accessor :should_return_from_ajax
7
9
 
8
10
  get "/boring_page" do
9
11
  erb "Hi", layout: :basic
10
12
  end
11
13
 
12
- get "/page_with_ajax" do
13
- erb :page_with_ajax, layout: :basic
14
+ get "/ajax/jquery" do
15
+ erb :jquery, layout: :basic
16
+ end
17
+
18
+ get "/ajax/angular" do
19
+ erb :angular, layout: :basic
14
20
  end
15
21
 
16
- get "/ajax_endpoint" do
22
+ get "/ajax/endpoint" do
17
23
  until AjaxServer.should_return_from_ajax do
18
24
  sleep 0.01
19
25
  end