transactional_capybara 0.1.0.pre.3 → 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.
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