capybara-faraday 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,89 @@
1
+ Capybara-restfulie
2
+ ==================
3
+
4
+ This gems makes it possible to use [Faraday](http://github.com/technoweenie/faraday) for remote testing.
5
+
6
+ This gem is a [Capybara](http://github.com/jnicklas/capybara) extension. The structure of the gem is taken from the work done on [Capybara-mechanize](http://github.com/jeroenvandijk/capybara-mechanize).
7
+
8
+ ### Installation
9
+
10
+ gem install capybara-faraday
11
+
12
+ ### Usage without Cucumber
13
+
14
+ require 'capybara/faraday'
15
+
16
+ ### Usage with Cucumber and tags
17
+
18
+ A @faraday tag is added to your hooks when you add the following line to your env.rb
19
+
20
+ require 'capybara/faraday/cucumber'
21
+
22
+ The following scenario will then be using the Faraday driver
23
+
24
+ @faraday
25
+ Scenario: do something with the API
26
+ Given I send and accept JSON
27
+ When I send a GET request to /users
28
+
29
+ If you want to use a specific faraday supported adapter, you need to install the dependency and then specify the tag matching it:
30
+
31
+ To use Typhoeus
32
+
33
+ @faraday_typhoeus
34
+ Scenario: do something with the API
35
+ Given I send and accept JSON
36
+ When I send a GET request to /users
37
+
38
+ To use Patron
39
+
40
+ @faraday_patron
41
+ Scenario: do something with the API
42
+ Given I send and accept JSON
43
+ When I send a GET request to /users
44
+
45
+ ### Remote testing
46
+
47
+ When you want to use this driver to test a remote application. You have to set the app_host:
48
+
49
+ Capybara.app_host = "http://www.yourapp.com"
50
+
51
+ Note that I haven't tested this case for my self yet. The Capybara tests pass for this situation though so it should work! Please provide me with feedback if it doesn't.
52
+
53
+ ## Running tests
54
+
55
+ For the tests to make sense, you need to simulate a remote server, simply add this line to your hosts file:
56
+
57
+ 127.0.0.1 capybara-testapp.heroku.com
58
+
59
+ Run bundler
60
+
61
+ bundle install
62
+
63
+ Then you are ready to run the test like so
64
+
65
+ rake spec
66
+
67
+ Caveats
68
+ -------
69
+
70
+ The focus being to provide a working driver to test APIs, not all Capybara goodness are implemented.
71
+ Everything related to submitting forms, clicking buttons, clicking checkboxes or javascript will not work with this driver.
72
+
73
+ Todo
74
+ ----
75
+
76
+ Note on Patches/Pull Requests
77
+ -----------------------------
78
+
79
+ * Fork the project.
80
+ * Make your feature addition or bug fix.
81
+ * Add tests for it. This is important so I don't break it in a
82
+ future version unintentionally.
83
+ * Commit, do not mess with rakefile, version, or history.
84
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
85
+ * Send me a pull request. Bonus points for topic branches.
86
+
87
+ Copyright
88
+ ---------
89
+ Copyright (c) 2010 Tron Jonathan and HALTER Joseph. See LICENSE for details.
@@ -0,0 +1,185 @@
1
+ require "faraday"
2
+
3
+ class Capybara::Driver::Faraday < Capybara::Driver::Base
4
+ class Node < Capybara::RackTest::Node
5
+ def click
6
+ driver.process(:get, self[:href].to_s) if self[:href] && self[:href] != ""
7
+ end
8
+ end
9
+
10
+ attr_writer :as, :with_headers, :with_params, :with_options
11
+ attr_reader :app, :adapter, :rack_server, :options, :response, :login, :password
12
+
13
+ def client
14
+ @client ||= Faraday::Connection.new{|c| c.adapter adapter}
15
+ end
16
+
17
+ def initialize(app, options={})
18
+ @app = app
19
+ @adapter = options.delete(:adapter) || :net_http
20
+ @options = {
21
+ :timeout => 3, # 3 seconds
22
+ }.merge options
23
+ @rack_server = Capybara::Server.new(@app)
24
+ @rack_server.boot if Capybara.run_server
25
+ end
26
+
27
+ def visit(url, params = {})
28
+ reset_cache
29
+ process :get, url, params
30
+ end
31
+
32
+ def get(url, params = {}, headers = {})
33
+ reset_cache
34
+ process :get, url, params, headers
35
+ end
36
+
37
+ def post(url, params = {}, headers = {})
38
+ reset_cache
39
+ process :post, url, params, headers
40
+ end
41
+
42
+ def put(url, params = {}, headers = {})
43
+ reset_cache
44
+ process :put, url, params, headers
45
+ end
46
+
47
+ def delete(url, params = {}, headers = {})
48
+ reset_cache
49
+ process :delete, url, params, headers
50
+ end
51
+
52
+ def head(url, params = {}, headers = {})
53
+ reset_cache
54
+ process :head, url, params, headers
55
+ end
56
+
57
+ def patch(url, params = {}, headers = {})
58
+ reset_cache
59
+ process :patch, url, params, headers
60
+ end
61
+
62
+ def request(url, params = {}, headers = {})
63
+ reset_cache
64
+ process :request, url, params, headers
65
+ end
66
+
67
+ def submit(method, path, attributes)
68
+ path = request.path if not path or path.empty?
69
+ process method.to_sym, path, attributes
70
+ end
71
+
72
+ def find(selector)
73
+ dom.xpath(selector).map { |node| Node.new(self, node) }
74
+ end
75
+
76
+ def html
77
+ @html ||= Nokogiri::HTML body
78
+ end
79
+
80
+ def xml
81
+ @xml ||= Nokogiri::XML body
82
+ end
83
+
84
+ def json
85
+ @json ||= Yajl::Parser.parse body
86
+ end
87
+
88
+ def body
89
+ response.body
90
+ end
91
+ alias_method :source, :body
92
+
93
+ def response_headers
94
+ response.headers["Content-Type"] = response.headers["content-type"]
95
+ response.headers
96
+ end
97
+
98
+ def status_code
99
+ response.status
100
+ end
101
+
102
+ def current_url
103
+ @current_uri.to_s
104
+ end
105
+
106
+ def reset!
107
+ @client = nil
108
+ @response = nil
109
+ @current_uri = nil
110
+ @login = nil
111
+ @password = nil
112
+ reset_cache
113
+ end
114
+
115
+ def reset_with!
116
+ @with_headers = {}
117
+ @with_params = {}
118
+ @with_options = {}
119
+ end
120
+
121
+ def as
122
+ @as ||= "application/json"
123
+ end
124
+
125
+ def with_headers
126
+ @with_headers ||= {}
127
+ end
128
+
129
+ def with_params
130
+ @with_params ||= {}
131
+ end
132
+
133
+ def with_options
134
+ @with_options ||= {}
135
+ end
136
+
137
+ def authenticate_with(login, password)
138
+ @login, @password = login, password
139
+ end
140
+
141
+ def auth?
142
+ login && password
143
+ end
144
+
145
+ def process(method, path, params = {}, headers = {})
146
+ client.basic_auth login, password if auth?
147
+ response = client.send(method) do |req|
148
+ if method == :get
149
+ req.url url(path), params
150
+ else
151
+ req.url url(path)
152
+ req.body = params
153
+ end
154
+ req.headers.merge!(headers.merge("Content-Type" => as, "Accept" => as))
155
+ req.options = options
156
+ end
157
+ @current_uri = url(path)
158
+ @response = response
159
+ end
160
+
161
+ def url(path)
162
+ rack_server.url(path)
163
+ end
164
+
165
+ def dom
166
+ content_type = response_headers["Content-Type"]
167
+ case content_type.to_s[/\A[^;]+/]
168
+ when "application/xml", "text/xml"
169
+ xml
170
+ when "text/html"
171
+ html
172
+ else
173
+ raise "Content-Type: #{content_type} is not handling xpath search"
174
+ end
175
+ end
176
+
177
+ private
178
+
179
+ def reset_cache
180
+ @xml = nil
181
+ @html = nil
182
+ @json = nil
183
+ end
184
+
185
+ end
@@ -0,0 +1,27 @@
1
+ require "capybara"
2
+
3
+ module Capybara
4
+ module Driver
5
+ autoload :Faraday, 'capybara/driver/faraday_driver'
6
+ end
7
+ end
8
+
9
+ Capybara.register_driver :faraday do |app|
10
+ Capybara::Driver::Faraday.new(app) # Net::HTTP
11
+ end
12
+
13
+ Capybara.register_driver :faraday_excon do |app|
14
+ Capybara::Driver::Faraday.new(app, :adapter => :excon)
15
+ end
16
+
17
+ Capybara.register_driver :faraday_typhoeus do |app|
18
+ Capybara::Driver::Faraday.new(app, :adapter => :typhoeus)
19
+ end
20
+
21
+ Capybara.register_driver :faraday_patron do |app|
22
+ Capybara::Driver::Faraday.new(app, :adapter => :patron)
23
+ end
24
+
25
+ Capybara.register_driver :faraday_em_http do |app|
26
+ Capybara::Driver::Faraday.new(app, :adapter => :em_http)
27
+ end
@@ -0,0 +1,26 @@
1
+ require 'capybara/faraday'
2
+
3
+ Before('@faraday') do
4
+ Capybara.current_driver = :faraday
5
+ page.driver.reset_with!
6
+ end
7
+
8
+ Before('@faraday_excon') do
9
+ Capybara.current_driver = :faraday_excon
10
+ page.driver.reset_with!
11
+ end
12
+
13
+ Before('@faraday_typhoeus') do
14
+ Capybara.current_driver = :faraday_typhoeus
15
+ page.driver.reset_with!
16
+ end
17
+
18
+ Before('@faraday_patron') do
19
+ Capybara.current_driver = :faraday_patron
20
+ page.driver.reset_with!
21
+ end
22
+
23
+ Before('@faraday_em_http') do
24
+ Capybara.current_driver = :faraday_em_http
25
+ page.driver.reset_with!
26
+ end
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+
3
+ describe Capybara::Driver::Faraday do
4
+ before do
5
+ @driver = described_class.new TestApp
6
+ end
7
+
8
+ context "in remote mode" do
9
+ it_should_behave_like "driver"
10
+ it_should_behave_like "driver with header support"
11
+ it_should_behave_like "driver with status code support"
12
+ # neither supports cookies nor follows redirect automatically
13
+ end
14
+
15
+ context "basic authentication" do
16
+ subject do
17
+ app = Sinatra.new do
18
+ use Rack::Auth::Basic do |username, password|
19
+ username=="admin" && password=="secret"
20
+ end
21
+ get("/"){ "Success!" }
22
+ end
23
+ described_class.new app
24
+ end
25
+
26
+ it "allow access with right credentials" do
27
+ subject.authenticate_with "admin", "secret"
28
+ subject.get "/"
29
+ subject.status_code.should be 200
30
+ subject.source.should == "Success!"
31
+ end
32
+
33
+ it "deny access with wrong credentials" do
34
+ subject.authenticate_with "admin", "admin"
35
+ subject.get "/"
36
+ subject.status_code.should be 401
37
+ end
38
+ end
39
+
40
+ context "timeout" do
41
+ context "default" do
42
+ subject do
43
+ driver = described_class.new TestApp
44
+ end
45
+
46
+ it "is 3 seconds" do
47
+ subject.options[:timeout].should == 3
48
+ end
49
+
50
+ it "is used during request" do
51
+ expect do
52
+ subject.get "/slow_response"
53
+ end.to_not raise_error
54
+ end
55
+ end
56
+
57
+ context "accepts custom timeout" do
58
+ subject do
59
+ driver = described_class.new TestApp, timeout: 1
60
+ end
61
+
62
+ it "is stored in options" do
63
+ subject.options[:timeout].should == 1
64
+ end
65
+
66
+ it "is used during request" do
67
+ expect do
68
+ subject.get "/slow_response"
69
+ end.to raise_error Faraday::Error::TimeoutError
70
+ end
71
+ end
72
+ end
73
+
74
+ end
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ module TestSessions
4
+ Faraday = Capybara::Session.new :faraday, TestApp
5
+ end
6
+
7
+ describe Capybara::Session do
8
+ context 'with faraday driver' do
9
+ before(:all) do
10
+ @session = TestSessions::Faraday
11
+ end
12
+
13
+ after do
14
+ @session.reset_session!
15
+ end
16
+
17
+ def extract_results(session)
18
+ YAML.load Nokogiri::HTML(session.body).xpath("//pre[@id='results']").first.text
19
+ end
20
+
21
+ describe '#driver' do
22
+ it "should be a typhoeus driver" do
23
+ @session.driver.should be_an_instance_of Capybara::Driver::Faraday
24
+ end
25
+ end
26
+
27
+ describe '#mode' do
28
+ it "should remember the mode" do
29
+ @session.mode.should == :faraday
30
+ end
31
+ end
32
+
33
+ describe '#app' do
34
+ it "should remember the application" do
35
+ @session.app.should == TestApp
36
+ end
37
+ end
38
+
39
+ describe '#visit' do
40
+ it "should fetch a response from the driver" do
41
+ @session.visit('/')
42
+ @session.body.should include('Hello world!')
43
+ @session.visit('/foo')
44
+ @session.body.should include('Another World')
45
+ end
46
+ end
47
+
48
+ describe '#body' do
49
+ it "should return the unmodified page body" do
50
+ @session.visit('/')
51
+ @session.body.should include('Hello world!')
52
+ end
53
+ end
54
+
55
+ describe '#source' do
56
+ it "should return the unmodified page source" do
57
+ @session.visit('/')
58
+ @session.source.should include('Hello world!')
59
+ end
60
+ end
61
+
62
+ it_should_behave_like "all"
63
+ it_should_behave_like "first"
64
+ it_should_behave_like "find_button"
65
+ it_should_behave_like "find_field"
66
+ it_should_behave_like "find_link"
67
+ it_should_behave_like "find_by_id"
68
+ it_should_behave_like "has_content"
69
+ it_should_behave_like "has_css"
70
+ it_should_behave_like "has_selector"
71
+ it_should_behave_like "has_xpath"
72
+ it_should_behave_like "has_link"
73
+ it_should_behave_like "has_button"
74
+ it_should_behave_like "has_field"
75
+ it_should_behave_like "has_select"
76
+ it_should_behave_like "has_table"
77
+ it_should_behave_like "current_url"
78
+ it_should_behave_like "session without javascript support"
79
+ it_should_behave_like "session with headers support"
80
+ it_should_behave_like "session with status code support"
81
+ end
82
+ end
@@ -0,0 +1,16 @@
1
+ require 'bundler/setup'
2
+ require 'capybara'
3
+ require 'capybara/faraday'
4
+ require 'capybara/spec/test_app'
5
+ require 'capybara/spec/driver'
6
+ require 'capybara/spec/session'
7
+
8
+ alias :running :lambda
9
+
10
+ Capybara.default_wait_time = 0 # less timeout so tests run faster
11
+
12
+ RSpec.configure do |config|
13
+ config.after do
14
+ Capybara.default_selector = :xpath
15
+ end
16
+ end
metadata ADDED
@@ -0,0 +1,165 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capybara-faraday
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jonathan Tron
9
+ - Joseph HALTER
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2010-10-21 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: capybara
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: 1.1.2
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ version: 1.1.2
31
+ - !ruby/object:Gem::Dependency
32
+ name: faraday
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - '='
37
+ - !ruby/object:Gem::Version
38
+ version: 0.8.7
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - '='
45
+ - !ruby/object:Gem::Version
46
+ version: 0.8.7
47
+ - !ruby/object:Gem::Dependency
48
+ name: yajl-ruby
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ version: '1.0'
63
+ - !ruby/object:Gem::Dependency
64
+ name: rake
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ - !ruby/object:Gem::Dependency
80
+ name: rspec
81
+ requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ type: :development
88
+ prerelease: false
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ - !ruby/object:Gem::Dependency
96
+ name: rack
97
+ requirement: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: sinatra
113
+ requirement: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ! '>='
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ! '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ description: Faraday driver for Capybara, allowing testing of REST APIs
128
+ email: team@openhood.com
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - lib/capybara/driver/faraday_driver.rb
134
+ - lib/capybara/faraday/cucumber.rb
135
+ - lib/capybara/faraday.rb
136
+ - spec/driver/faraday_driver_spec.rb
137
+ - spec/session/faraday_spec.rb
138
+ - spec/spec_helper.rb
139
+ - README.md
140
+ homepage: http://github.com/openhood/capybara-faraday
141
+ licenses: []
142
+ post_install_message:
143
+ rdoc_options:
144
+ - --charset=UTF-8
145
+ require_paths:
146
+ - lib
147
+ required_ruby_version: !ruby/object:Gem::Requirement
148
+ none: false
149
+ requirements:
150
+ - - ! '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ required_rubygems_version: !ruby/object:Gem::Requirement
154
+ none: false
155
+ requirements:
156
+ - - ! '>='
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ requirements: []
160
+ rubyforge_project:
161
+ rubygems_version: 1.8.23
162
+ signing_key:
163
+ specification_version: 3
164
+ summary: Faraday driver for Capybara
165
+ test_files: []