rspec-rails23 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +45 -0
- data/README +25 -0
- data/RSPEC-LICENSE +23 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/lib/rspec/rails23/configuration.rb +48 -0
- data/lib/rspec/rails23/controllers.rb +86 -0
- data/lib/rspec/rails23/extensions/active_record.rb +19 -0
- data/lib/rspec/rails23/helpers.rb +99 -0
- data/lib/rspec/rails23/matchers/controllers/redirect_to.rb +115 -0
- data/lib/rspec/rails23/matchers/controllers/render_template.rb +116 -0
- data/lib/rspec/rails23/mocking/model_stubber.rb +24 -0
- data/lib/rspec/rails23/mocking/with_mocha.rb +72 -0
- data/lib/rspec/rails23/mocking/with_rr.rb +44 -0
- data/lib/rspec/rails23/transactional_database_support.rb +39 -0
- data/lib/rspec-rails23.rb +17 -0
- data/spec/lib/rspec/rails23/configuration_spec.rb +46 -0
- data/spec/spec_helper.rb +48 -0
- metadata +109 -0
data/LICENSE
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
Copyright (c) 2010 Rob Sanheim & Chad Humphries
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
|
23
|
+
The matchers and expectations are licensed:
|
24
|
+
(The MIT License)
|
25
|
+
|
26
|
+
Copyright (c) 2005-2008 The RSpec Development Team
|
27
|
+
|
28
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
29
|
+
a copy of this software and associated documentation files (the
|
30
|
+
"Software"), to deal in the Software without restriction, including
|
31
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
32
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
33
|
+
permit persons to whom the Software is furnished to do so, subject to
|
34
|
+
the following conditions:
|
35
|
+
|
36
|
+
The above copyright notice and this permission notice shall be
|
37
|
+
included in all copies or substantial portions of the Software.
|
38
|
+
|
39
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
40
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
41
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
42
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
43
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
44
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
45
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
= Rspec-Rails23
|
2
|
+
|
3
|
+
Rspec 2 (prerelease) support for Rails 2.3.5.
|
4
|
+
|
5
|
+
This is being released based on production development and use at Relevance (http://thinkrelevance.com), based on an extraction from micronaut-rails that was developed for Rails 2.3.x As such, and based on Rails 2.3 days being numbered, it will most likely never have much of the features of the legacy rspec-rails (such as fixtures, integration tests, etc).
|
6
|
+
|
7
|
+
== DESCRIPTION:
|
8
|
+
|
9
|
+
== REQUIREMENTS:
|
10
|
+
|
11
|
+
* Ruby 1.8.6+
|
12
|
+
* Rails 2.3.5
|
13
|
+
* Rspec 2 (get it with "gem install rspec --prerelease")
|
14
|
+
|
15
|
+
== ISSUES
|
16
|
+
|
17
|
+
* No support for pure Rails fixtures at all, and no plans to add it - we use Factory Girl/Fixture Replacement instead.
|
18
|
+
* No support for Rails integration tests -- use Cucumber (http://github.com/aslakhellesoy/cucumber) instead!
|
19
|
+
* No support for < 2.3.5 - it may work, it may not. Not tested.
|
20
|
+
|
21
|
+
== CREDITS:
|
22
|
+
|
23
|
+
* RSpec for the great ideas and matchers
|
24
|
+
* Chad Humphries for Micronaut
|
25
|
+
* David Chelimsky and the Rspec-core team for Rspec
|
data/RSPEC-LICENSE
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright (c) 2005-2008 The RSpec Development Team
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
21
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
Jeweler::Tasks.new do |s|
|
4
|
+
s.name = "rspec-rails23"
|
5
|
+
s.summary = "Rspec Rails for 2.3.5"
|
6
|
+
s.email = "rsanheim@gmail.com"
|
7
|
+
s.homepage = "http://github.com/rsanheim/rspec-rails23"
|
8
|
+
s.description = "Rails 2.3.5 Extension for Rspec 2"
|
9
|
+
s.authors = ["Rob Sanheim"]
|
10
|
+
s.files = FileList["[A-Z]*", "{bin,lib,spec}/**/*"]
|
11
|
+
s.add_dependency "actionpack", '~> 2.3.0'
|
12
|
+
s.add_dependency "rspec", '~> 2.0.0.beta'
|
13
|
+
end
|
14
|
+
Jeweler::GemcutterTasks.new
|
15
|
+
rescue LoadError
|
16
|
+
puts "Jeweler, or one of its dependencies, is not available. Install it with: gem install jeweler"
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'rspec/core/rake_task'
|
20
|
+
|
21
|
+
desc "Run all specs"
|
22
|
+
Rspec::Core::RakeTask.new :spec do |t|
|
23
|
+
t.pattern = "spec/**/*_spec.rb"
|
24
|
+
end
|
25
|
+
|
26
|
+
namespace :spec do
|
27
|
+
desc "Run all specs using rcov"
|
28
|
+
Rspec::Core::RakeTask.new :coverage do |t|
|
29
|
+
t.pattern = "spec/**/*_spec.rb"
|
30
|
+
t.rcov = true
|
31
|
+
t.rcov_opts = %[--exclude "spec/*,gems/*,db/*,/Library/Ruby/*,config/*" --text-summary --sort coverage]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
task :default => [:check_dependencies, :spec]
|
36
|
+
|
37
|
+
begin
|
38
|
+
%w{sdoc sdoc-helpers rdiscount}.each { |name| gem name }
|
39
|
+
require 'sdoc_helpers'
|
40
|
+
rescue LoadError => ex
|
41
|
+
puts "sdoc support not enabled:"
|
42
|
+
puts ex.inspect
|
43
|
+
end
|
44
|
+
|
45
|
+
require 'rake/rdoctask'
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
47
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ''
|
48
|
+
rdoc.rdoc_dir = 'rdoc'
|
49
|
+
rdoc.title = "Rspec-Rails #{version}"
|
50
|
+
rdoc.rdoc_files.include('README*')
|
51
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
52
|
+
end
|
53
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Rspec
|
2
|
+
module Rails23
|
3
|
+
|
4
|
+
module Configuration
|
5
|
+
|
6
|
+
def rails
|
7
|
+
self
|
8
|
+
end
|
9
|
+
|
10
|
+
# :behaviour => { :describes => lambda { |dt| dt < ActiveRecord::Base }
|
11
|
+
def enable_active_record_transactional_support(filter_options={})
|
12
|
+
Rspec.configuration.extend(::Rspec::Rails23::TransactionalDatabaseSupport, filter_options)
|
13
|
+
end
|
14
|
+
|
15
|
+
# :behaviour => { :describes => lambda { |dt| dt.to_s.ends_with?('Helper') }
|
16
|
+
def enable_helper_support(filter_options={})
|
17
|
+
Rspec.configuration.extend(::Rspec::Rails23::Helpers, filter_options)
|
18
|
+
end
|
19
|
+
|
20
|
+
# :behaviour => { :describes => lambda { |dt| dt < ActionController::Base }
|
21
|
+
def enable_controller_support(filter_options={})
|
22
|
+
Rspec.configuration.extend(::Rspec::Rails23::Controllers, filter_options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def enable_rails_specific_mocking_extensions(filter_options={})
|
26
|
+
case Rspec.configuration.options[:mock_framework].to_s
|
27
|
+
when /mocha/i
|
28
|
+
require 'rspec/rails23/mocking/with_mocha'
|
29
|
+
Rspec.configuration.include(::Rspec::Rails23::Mocking::WithMocha, filter_options)
|
30
|
+
when /rr/i
|
31
|
+
require 'rspec/rails23/mocking/with_rr'
|
32
|
+
Rspec.configuration.include(::Rspec::Rails23::Mocking::WithRR, filter_options)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def enable_reasonable_defaults!
|
37
|
+
enable_active_record_transactional_support
|
38
|
+
enable_helper_support :behaviour => { :describes => lambda { |dt| dt.to_s.ends_with?('Helper') } }
|
39
|
+
enable_controller_support :behaviour => { :describes => lambda { |dt| dt < ::ActionController::Base } }
|
40
|
+
enable_rails_specific_mocking_extensions
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
::Rspec::Core::Configuration.send(:include, ::Rspec::Rails23::Configuration)
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'action_controller'
|
2
|
+
require 'action_controller/test_process'
|
3
|
+
|
4
|
+
module Rspec
|
5
|
+
module Rails23
|
6
|
+
module Controllers
|
7
|
+
|
8
|
+
module InstanceMethods
|
9
|
+
attr_reader :request, :response, :controller
|
10
|
+
|
11
|
+
def route_for(options)
|
12
|
+
ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty?
|
13
|
+
ActionController::Routing::Routes.generate(options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def params_from(method, path)
|
17
|
+
ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty?
|
18
|
+
ActionController::Routing::Routes.recognize_path(path, :method => method)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
module TemplateIsolationExtensions
|
24
|
+
def file_exists?(ignore); true; end
|
25
|
+
|
26
|
+
def render_file(*args)
|
27
|
+
@first_render ||= args[0] unless args[0] =~ /^layouts/
|
28
|
+
end
|
29
|
+
|
30
|
+
def render(*args)
|
31
|
+
return super if Hash === args.last && args.last[:inline]
|
32
|
+
record_render(args[0])
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def record_render(opts)
|
38
|
+
@_rendered ||= {}
|
39
|
+
(@_rendered[:template] ||= opts[:file]) if opts[:file]
|
40
|
+
(@_rendered[:partials][opts[:partial]] += 1) if opts[:partial]
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
module RenderOverrides
|
47
|
+
|
48
|
+
def render_views!
|
49
|
+
@render_views = true
|
50
|
+
end
|
51
|
+
|
52
|
+
def rendering_views?
|
53
|
+
@render_views
|
54
|
+
end
|
55
|
+
|
56
|
+
def render(options=nil, extra_options={}, &block)
|
57
|
+
unless block_given?
|
58
|
+
unless rendering_views?
|
59
|
+
@template.extend TemplateIsolationExtensions
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
super
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.extended(extended_behaviour)
|
69
|
+
extended_behaviour.send :include, ::ActionController::TestProcess, InstanceMethods, ::Rspec::Rails23::Matchers::Controllers
|
70
|
+
extended_behaviour.describes.send :include, RenderOverrides, ::ActionController::TestCase::RaiseActionExceptions
|
71
|
+
|
72
|
+
extended_behaviour.before do
|
73
|
+
@request = ::ActionController::TestRequest.new
|
74
|
+
@response = ::ActionController::TestResponse.new
|
75
|
+
@controller = self.class.describes.new
|
76
|
+
|
77
|
+
@controller.request = @request
|
78
|
+
@controller.params = {}
|
79
|
+
@controller.send(:initialize_current_url)
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Rspec
|
2
|
+
module Rails23
|
3
|
+
module Extensions
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
def errors_on(attribute)
|
7
|
+
self.valid?
|
8
|
+
[self.errors.on(attribute)].flatten.compact
|
9
|
+
end
|
10
|
+
alias :error_on :errors_on
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
if defined?(::ActiveRecord::Base)
|
18
|
+
::ActiveRecord::Base.send(:include, ::Rspec::Rails23::Extensions::ActiveRecord)
|
19
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Rspec
|
2
|
+
module Rails23
|
3
|
+
module Helpers
|
4
|
+
|
5
|
+
class HelperController < ActionController::Base; end
|
6
|
+
|
7
|
+
module InstanceMethods
|
8
|
+
|
9
|
+
class HelperObject < ActionView::Base
|
10
|
+
def protect_against_forgery?
|
11
|
+
false
|
12
|
+
end
|
13
|
+
|
14
|
+
def session=(session)
|
15
|
+
@session = session
|
16
|
+
end
|
17
|
+
|
18
|
+
def request=(request)
|
19
|
+
@request = request
|
20
|
+
end
|
21
|
+
|
22
|
+
def flash=(flash)
|
23
|
+
@flash = flash
|
24
|
+
end
|
25
|
+
|
26
|
+
def params=(params)
|
27
|
+
@params = params
|
28
|
+
end
|
29
|
+
|
30
|
+
def controller=(controller)
|
31
|
+
@controller = controller
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
attr_reader :session, :request, :flash, :params, :controller
|
36
|
+
end
|
37
|
+
|
38
|
+
def helper
|
39
|
+
@helper_object ||= returning HelperObject.new do |helper_object|
|
40
|
+
if self.class.describes.class == Module
|
41
|
+
helper_object.extend self.class.describes
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def params
|
47
|
+
request.parameters
|
48
|
+
end
|
49
|
+
|
50
|
+
def flash
|
51
|
+
response.flash
|
52
|
+
end
|
53
|
+
|
54
|
+
def session
|
55
|
+
response.session
|
56
|
+
end
|
57
|
+
|
58
|
+
def method_missing(sym, *args)
|
59
|
+
if helper.respond_to?(sym)
|
60
|
+
helper.send(sym, *args)
|
61
|
+
else
|
62
|
+
super
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.extended(kls)
|
69
|
+
kls.send(:include, InstanceMethods)
|
70
|
+
|
71
|
+
kls.send(:attr_reader, :request, :response)
|
72
|
+
|
73
|
+
ActionView::Base.included_modules.reverse.each do |mod|
|
74
|
+
kls.send(:include, mod) if mod.parents.include?(ActionView::Helpers)
|
75
|
+
end
|
76
|
+
|
77
|
+
kls.before do
|
78
|
+
@controller = ::Rspec::Rails23::Helpers::HelperController.new
|
79
|
+
@request = ActionController::TestRequest.new
|
80
|
+
@response = ActionController::TestResponse.new
|
81
|
+
@response.session = @request.session
|
82
|
+
@controller.request = @request
|
83
|
+
@flash = ActionController::Flash::FlashHash.new
|
84
|
+
@response.session['flash'] = @flash
|
85
|
+
|
86
|
+
ActionView::Helpers::AssetTagHelper::reset_javascript_include_default
|
87
|
+
|
88
|
+
helper.session = @response.session
|
89
|
+
helper.request = @request
|
90
|
+
helper.flash = @flash
|
91
|
+
helper.params = params
|
92
|
+
helper.controller = @controller
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module Rspec
|
2
|
+
module Rails23
|
3
|
+
module Matchers
|
4
|
+
module Controllers
|
5
|
+
|
6
|
+
class RedirectTo #:nodoc:
|
7
|
+
|
8
|
+
def initialize(request, expected)
|
9
|
+
@expected = expected
|
10
|
+
@request = request
|
11
|
+
end
|
12
|
+
|
13
|
+
def matches?(response)
|
14
|
+
@redirected = response.redirect?
|
15
|
+
@actual = response.redirect_url
|
16
|
+
return false unless @redirected
|
17
|
+
if @expected.instance_of? Hash
|
18
|
+
return false unless @actual =~ %r{^\w+://#{@request.host}}
|
19
|
+
return false unless actual_redirect_to_valid_route
|
20
|
+
return actual_hash == expected_hash
|
21
|
+
else
|
22
|
+
return @actual == expected_url
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def actual_hash
|
27
|
+
hash_from_url @actual
|
28
|
+
end
|
29
|
+
|
30
|
+
def expected_hash
|
31
|
+
hash_from_url expected_url
|
32
|
+
end
|
33
|
+
|
34
|
+
def actual_redirect_to_valid_route
|
35
|
+
actual_hash
|
36
|
+
end
|
37
|
+
|
38
|
+
def hash_from_url(url)
|
39
|
+
query_hash(url).merge(path_hash(url)).with_indifferent_access
|
40
|
+
end
|
41
|
+
|
42
|
+
def path_hash(url)
|
43
|
+
path = url.sub(%r{^\w+://#{@request.host}(?::\d+)?}, "").split("?", 2)[0]
|
44
|
+
ActionController::Routing::Routes.recognize_path path
|
45
|
+
end
|
46
|
+
|
47
|
+
def query_hash(url)
|
48
|
+
query = url.split("?", 2)[1] || ""
|
49
|
+
QueryParameterParser.parse_query_parameters(query, @request)
|
50
|
+
end
|
51
|
+
|
52
|
+
def expected_url
|
53
|
+
case @expected
|
54
|
+
when Hash
|
55
|
+
return ActionController::UrlRewriter.new(@request, {}).rewrite(@expected)
|
56
|
+
when :back
|
57
|
+
return @request.env['HTTP_REFERER']
|
58
|
+
when %r{^\w+://.*}
|
59
|
+
return @expected
|
60
|
+
else
|
61
|
+
return "http://#{@request.host}" + (@expected.split('')[0] == '/' ? '' : '/') + @expected
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def failure_message
|
66
|
+
if @redirected
|
67
|
+
return %Q{expected redirect to #{@expected.inspect}, got redirect to #{@actual.inspect}}
|
68
|
+
else
|
69
|
+
return %Q{expected redirect to #{@expected.inspect}, got no redirect}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def negative_failure_message
|
74
|
+
return %Q{expected not to be redirected to #{@expected.inspect}, but was} if @redirected
|
75
|
+
end
|
76
|
+
|
77
|
+
def description
|
78
|
+
"redirect to #{@actual.inspect}"
|
79
|
+
end
|
80
|
+
|
81
|
+
class QueryParameterParser
|
82
|
+
def self.parse_query_parameters(query, request)
|
83
|
+
if defined?(CGIMethods)
|
84
|
+
CGIMethods.parse_query_parameters(query)
|
85
|
+
else
|
86
|
+
request.class.parse_query_parameters(query)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# :call-seq:
|
93
|
+
# response.should redirect_to(url)
|
94
|
+
# response.should redirect_to(:action => action_name)
|
95
|
+
# response.should redirect_to(:controller => controller_name, :action => action_name)
|
96
|
+
# response.should_not redirect_to(url)
|
97
|
+
# response.should_not redirect_to(:action => action_name)
|
98
|
+
# response.should_not redirect_to(:controller => controller_name, :action => action_name)
|
99
|
+
#
|
100
|
+
# Passes if the response is a redirect to the url, action or controller/action.
|
101
|
+
# Useful in controller specs (integration or isolation mode).
|
102
|
+
#
|
103
|
+
# == Examples
|
104
|
+
#
|
105
|
+
# response.should redirect_to("path/to/action")
|
106
|
+
# response.should redirect_to("http://test.host/path/to/action")
|
107
|
+
# response.should redirect_to(:action => 'list')
|
108
|
+
def redirect_to(opts)
|
109
|
+
RedirectTo.new(request, opts)
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module Rspec
|
2
|
+
module Rails23
|
3
|
+
module Matchers
|
4
|
+
module Controllers
|
5
|
+
|
6
|
+
class RenderTemplate #:nodoc:
|
7
|
+
|
8
|
+
def initialize(expected, controller)
|
9
|
+
@controller = controller
|
10
|
+
@expected = expected
|
11
|
+
end
|
12
|
+
|
13
|
+
def matches?(response_or_controller)
|
14
|
+
response = response_or_controller.respond_to?(:response) ?
|
15
|
+
response_or_controller.response :
|
16
|
+
response_or_controller
|
17
|
+
|
18
|
+
if response.respond_to?(:rendered_file)
|
19
|
+
@actual = response.rendered_file
|
20
|
+
elsif response.respond_to?(:rendered)
|
21
|
+
case template = response.rendered[:template]
|
22
|
+
when nil
|
23
|
+
unless response.rendered[:partials].empty?
|
24
|
+
@actual = path_and_file(response.rendered[:partials].keys.first).join("/_")
|
25
|
+
end
|
26
|
+
when ActionView::Template
|
27
|
+
@actual = template.path
|
28
|
+
when String
|
29
|
+
@actual = template
|
30
|
+
end
|
31
|
+
else
|
32
|
+
@actual = response.rendered_template.to_s
|
33
|
+
end
|
34
|
+
return false if @actual.blank?
|
35
|
+
given_controller_path, given_file = path_and_file(@actual)
|
36
|
+
expected_controller_path, expected_file = path_and_file(@expected)
|
37
|
+
given_controller_path == expected_controller_path && given_file.match(expected_file)
|
38
|
+
end
|
39
|
+
|
40
|
+
def failure_message
|
41
|
+
"expected #{@expected.inspect}, got #{@actual.inspect}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def negative_failure_message
|
45
|
+
"expected not to render #{@expected.inspect}, but did"
|
46
|
+
end
|
47
|
+
|
48
|
+
def description
|
49
|
+
"render template #{@expected.inspect}"
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
def path_and_file(path)
|
54
|
+
parts = path.split('/')
|
55
|
+
file = parts.pop
|
56
|
+
controller = parts.empty? ? current_controller_path : parts.join('/')
|
57
|
+
return controller, file
|
58
|
+
end
|
59
|
+
|
60
|
+
def controller_path_from(path)
|
61
|
+
parts = path.split('/')
|
62
|
+
parts.pop
|
63
|
+
parts.join('/')
|
64
|
+
end
|
65
|
+
|
66
|
+
def current_controller_path
|
67
|
+
@controller.class.to_s.underscore.gsub(/_controller$/,'')
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
# :call-seq:
|
73
|
+
# response.should render_template(template)
|
74
|
+
# response.should_not render_template(template)
|
75
|
+
#
|
76
|
+
# For use in controller code examples (integration or isolation mode).
|
77
|
+
#
|
78
|
+
# Passes if the specified template (view file) is rendered by the
|
79
|
+
# response. This file can be any view file, including a partial. However
|
80
|
+
# if it is a partial it must be rendered directly i.e. you can't detect
|
81
|
+
# that a partial has been rendered as part of a view using
|
82
|
+
# render_template. For that you should use a message expectation
|
83
|
+
# (mock) instead:
|
84
|
+
#
|
85
|
+
# controller.should_receive(:render).with(:partial => 'path/to/partial')
|
86
|
+
#
|
87
|
+
# <code>template</code> can include the controller path. It can also
|
88
|
+
# include an optional extension, which you only need to use when there
|
89
|
+
# is ambiguity.
|
90
|
+
#
|
91
|
+
# Note that partials must be spelled with the preceding underscore.
|
92
|
+
#
|
93
|
+
# == Examples
|
94
|
+
#
|
95
|
+
# response.should render_template('list')
|
96
|
+
# response.should render_template('same_controller/list')
|
97
|
+
# response.should render_template('other_controller/list')
|
98
|
+
#
|
99
|
+
# # with extensions
|
100
|
+
# response.should render_template('list.rjs')
|
101
|
+
# response.should render_template('list.haml')
|
102
|
+
# response.should render_template('same_controller/list.rjs')
|
103
|
+
# response.should render_template('other_controller/list.rjs')
|
104
|
+
#
|
105
|
+
# # partials
|
106
|
+
# response.should render_template('_a_partial')
|
107
|
+
# response.should render_template('same_controller/_a_partial')
|
108
|
+
# response.should render_template('other_controller/_a_partial')
|
109
|
+
def render_template(path)
|
110
|
+
RenderTemplate.new(path.to_s, @controller)
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Rspec
|
2
|
+
module Rails23
|
3
|
+
module Mocking
|
4
|
+
|
5
|
+
module ModelStubber
|
6
|
+
|
7
|
+
def connection
|
8
|
+
raise ::Rspec::Rails23::IllegalDataAccessException.new("stubbed/mocked models are not allowed to access the database")
|
9
|
+
end
|
10
|
+
|
11
|
+
def new_record?
|
12
|
+
id.nil?
|
13
|
+
end
|
14
|
+
|
15
|
+
def as_new_record
|
16
|
+
self.id = nil
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Rspec
|
2
|
+
module Rails23
|
3
|
+
module Mocking
|
4
|
+
module WithMocha
|
5
|
+
|
6
|
+
def stub_model(model_class, params = {})
|
7
|
+
params = params.dup
|
8
|
+
model = model_class.new
|
9
|
+
model.id = params.delete(:id) || next_id
|
10
|
+
model.extend ::Rspec::Rails23::Mocking::ModelStubber
|
11
|
+
|
12
|
+
params.keys.each do |prop|
|
13
|
+
model[prop] = params.delete(prop) if model.has_attribute?(prop)
|
14
|
+
end
|
15
|
+
add_stubs(model, params)
|
16
|
+
|
17
|
+
yield model if block_given?
|
18
|
+
model
|
19
|
+
end
|
20
|
+
|
21
|
+
# Stubs methods on +object+ (if +object+ is a symbol or string a new mock
|
22
|
+
# with that name will be created). +stubs+ is a Hash of +method=>value+
|
23
|
+
def add_stubs(object, params) # :nodoc:
|
24
|
+
m = [String, Symbol].include?(object.class) ? mock(object.to_s) : object
|
25
|
+
params.each { |prop, value| m.stubs(prop).returns(value) }
|
26
|
+
m
|
27
|
+
end
|
28
|
+
|
29
|
+
def mock_model(model_class, params = {})
|
30
|
+
id = params[:id] || next_id
|
31
|
+
model = stub("#{model_class.name}_#{id}", {
|
32
|
+
:id => id,
|
33
|
+
:to_param => id.to_s,
|
34
|
+
:new_record? => false,
|
35
|
+
:errors => stub("errors", :count => 0)
|
36
|
+
}.update(params))
|
37
|
+
|
38
|
+
model.instance_eval <<-CODE
|
39
|
+
def as_new_record
|
40
|
+
self.stubs(:id).returns(nil)
|
41
|
+
self.stubs(:to_param).returns(nil)
|
42
|
+
self.stubs(:new_record?).returns(true)
|
43
|
+
self
|
44
|
+
end
|
45
|
+
def is_a?(other)
|
46
|
+
#{model_class}.ancestors.include?(other)
|
47
|
+
end
|
48
|
+
def kind_of?(other)
|
49
|
+
#{model_class}.ancestors.include?(other)
|
50
|
+
end
|
51
|
+
def instance_of?(other)
|
52
|
+
other == #{model_class}
|
53
|
+
end
|
54
|
+
def class
|
55
|
+
#{model_class}
|
56
|
+
end
|
57
|
+
CODE
|
58
|
+
|
59
|
+
yield model if block_given?
|
60
|
+
return model
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
@@model_id = 1000
|
65
|
+
def next_id
|
66
|
+
@@model_id += 1
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Rspec
|
2
|
+
module Rails23
|
3
|
+
module Mocking
|
4
|
+
|
5
|
+
module WithRR
|
6
|
+
# Creates a mock object instance for a +model_class+ with common
|
7
|
+
# methods stubbed out. Additional methods may be easily stubbed (via
|
8
|
+
# add_stubs) if +stubs+ is passed.
|
9
|
+
def mock_or_stub_model(model_class, mock_or_stub, options = {})
|
10
|
+
model = model_class.new
|
11
|
+
model.extend ::Rspec::Rails23::Mocking::ModelStubber
|
12
|
+
model_id = next_id
|
13
|
+
|
14
|
+
stub(errors_stub = Object.new).count.returns(0)
|
15
|
+
full_params = { :id => model_id, :new_record? => false, :errors => errors_stub }.update(options)
|
16
|
+
|
17
|
+
full_params.each do |method, value|
|
18
|
+
eval "#{mock_or_stub}(model).#{method}.returns(value)", binding, __FILE__, __LINE__
|
19
|
+
end
|
20
|
+
|
21
|
+
yield model if block_given?
|
22
|
+
model
|
23
|
+
end
|
24
|
+
|
25
|
+
def mock_model(model_class, options = {})
|
26
|
+
mock_or_stub_model(model_class, 'mock', options)
|
27
|
+
end
|
28
|
+
|
29
|
+
def stub_model(model_class, options = {})
|
30
|
+
mock_or_stub_model(model_class, 'stub', options)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
@@model_id = 1000
|
36
|
+
def next_id
|
37
|
+
@@model_id += 1
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Rspec
|
2
|
+
module Rails23
|
3
|
+
module TransactionalDatabaseSupport
|
4
|
+
|
5
|
+
module InstanceMethods
|
6
|
+
|
7
|
+
def active_record_configured?
|
8
|
+
defined?(::ActiveRecord) && !::ActiveRecord::Base.configurations.blank?
|
9
|
+
end
|
10
|
+
|
11
|
+
def transactional_protection_start
|
12
|
+
return unless active_record_configured?
|
13
|
+
|
14
|
+
::ActiveRecord::Base.connection.increment_open_transactions
|
15
|
+
::ActiveRecord::Base.connection.begin_db_transaction
|
16
|
+
end
|
17
|
+
|
18
|
+
def transactional_protection_cleanup
|
19
|
+
return unless active_record_configured?
|
20
|
+
|
21
|
+
if ::ActiveRecord::Base.connection.open_transactions != 0
|
22
|
+
::ActiveRecord::Base.connection.rollback_db_transaction
|
23
|
+
::ActiveRecord::Base.connection.decrement_open_transactions
|
24
|
+
end
|
25
|
+
|
26
|
+
::ActiveRecord::Base.clear_active_connections!
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.extended(kls)
|
32
|
+
kls.send(:include, InstanceMethods)
|
33
|
+
kls.before { transactional_protection_start }
|
34
|
+
kls.after { transactional_protection_cleanup }
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rspec/core'
|
2
|
+
require 'rspec/rails23/configuration'
|
3
|
+
require 'rspec/rails23/matchers/controllers/redirect_to'
|
4
|
+
require 'rspec/rails23/matchers/controllers/render_template'
|
5
|
+
require 'rspec/rails23/transactional_database_support'
|
6
|
+
require 'rspec/rails23/controllers'
|
7
|
+
require 'rspec/rails23/helpers'
|
8
|
+
require 'rspec/rails23/extensions/active_record'
|
9
|
+
require 'rspec/rails23/mocking/model_stubber'
|
10
|
+
|
11
|
+
module Rspec
|
12
|
+
module Rails23
|
13
|
+
class IllegalDataAccessException < StandardError; end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../../../spec_helper")
|
2
|
+
|
3
|
+
describe Rspec::Core::Configuration do
|
4
|
+
|
5
|
+
example "loading rspec rails23 includes it in the configuration class" do
|
6
|
+
Rspec::Core::Configuration.included_modules.should include(Rspec::Rails23::Configuration)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "adds a #rails method" do
|
10
|
+
Rspec::Core::Configuration.new.should respond_to(:rails)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "adds an #enable_active_record_transactional_support method" do
|
14
|
+
Rspec::Core::Configuration.new.should respond_to(:enable_active_record_transactional_support)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "helpers for standard Rails23 testing support" do
|
18
|
+
Rspec::Core::Configuration.class_eval do
|
19
|
+
attr_reader :include_or_extend_modules
|
20
|
+
end
|
21
|
+
method_to_modules = { :enable_helper_support => Rspec::Rails23::Helpers,
|
22
|
+
:enable_active_record_transactional_support => Rspec::Rails23::TransactionalDatabaseSupport,
|
23
|
+
:enable_controller_support => Rspec::Rails23::Controllers
|
24
|
+
}
|
25
|
+
method_to_modules.each do |method, mod|
|
26
|
+
example "##{method} with no filter options" do
|
27
|
+
Rspec.configuration.send(method)
|
28
|
+
Rspec.configuration.include_or_extend_modules.should include([:extend, mod, {}])
|
29
|
+
end
|
30
|
+
|
31
|
+
example "##{method} with filter options" do
|
32
|
+
filter_options = {:options => { "foo" => "bar" } }
|
33
|
+
Rspec.configuration.send(method, filter_options)
|
34
|
+
Rspec.configuration.include_or_extend_modules.should include([:extend, mod, filter_options])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
example "#enable_Rails23_specific_mocking_extensions for mocha with no filter options" do
|
39
|
+
Rspec.configuration.mock_with :mocha
|
40
|
+
Rspec.configuration.enable_rails_specific_mocking_extensions
|
41
|
+
Rspec.configuration.include_or_extend_modules.should include([:include, Rspec::Rails23::Mocking::WithMocha, {}])
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
lib_path = File.expand_path(File.dirname(__FILE__) + "/../lib")
|
2
|
+
$LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path)
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
gem "actionpack", '~> 2.3'
|
6
|
+
require 'action_controller'
|
7
|
+
|
8
|
+
gem "rspec-core", "~> 2.0.0.beta"
|
9
|
+
require 'rspec/core'
|
10
|
+
require 'rspec-rails23'
|
11
|
+
|
12
|
+
gem "mocha"
|
13
|
+
|
14
|
+
module Rspec
|
15
|
+
module Core
|
16
|
+
module Matchers
|
17
|
+
def fail
|
18
|
+
raise_error(::Rspec::Expectations::ExpectationNotMetError)
|
19
|
+
end
|
20
|
+
|
21
|
+
def fail_with(message)
|
22
|
+
raise_error(::Rspec::Expectations::ExpectationNotMetError, message)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def remove_last_describe_from_world
|
29
|
+
Rspec::Core.world.example_groups.pop
|
30
|
+
end
|
31
|
+
|
32
|
+
class DummyFormatter < Rspec::Core::Formatters::BaseTextFormatter; end
|
33
|
+
|
34
|
+
def dummy_reporter
|
35
|
+
DummyFormatter.new({}, StringIO.new)
|
36
|
+
end
|
37
|
+
|
38
|
+
def use_color?
|
39
|
+
!ENV.has_key?('TM_MODE')
|
40
|
+
end
|
41
|
+
|
42
|
+
Rspec.configure do |config|
|
43
|
+
config.mock_with :mocha
|
44
|
+
config.color_enabled = use_color?
|
45
|
+
config.formatter = :documentation
|
46
|
+
config.filter_run :focused => true
|
47
|
+
config.run_all_when_everything_filtered = true
|
48
|
+
end
|
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rspec-rails23
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Rob Sanheim
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-04-06 00:00:00 -04:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: actionpack
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ~>
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 2
|
29
|
+
- 3
|
30
|
+
- 0
|
31
|
+
version: 2.3.0
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rspec
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ~>
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 2
|
43
|
+
- 0
|
44
|
+
- 0
|
45
|
+
- beta
|
46
|
+
version: 2.0.0.beta
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id002
|
49
|
+
description: Rails 2.3.5 Extension for Rspec 2
|
50
|
+
email: rsanheim@gmail.com
|
51
|
+
executables: []
|
52
|
+
|
53
|
+
extensions: []
|
54
|
+
|
55
|
+
extra_rdoc_files:
|
56
|
+
- LICENSE
|
57
|
+
- README
|
58
|
+
files:
|
59
|
+
- LICENSE
|
60
|
+
- README
|
61
|
+
- RSPEC-LICENSE
|
62
|
+
- Rakefile
|
63
|
+
- VERSION
|
64
|
+
- lib/rspec-rails23.rb
|
65
|
+
- lib/rspec/rails23/configuration.rb
|
66
|
+
- lib/rspec/rails23/controllers.rb
|
67
|
+
- lib/rspec/rails23/extensions/active_record.rb
|
68
|
+
- lib/rspec/rails23/helpers.rb
|
69
|
+
- lib/rspec/rails23/matchers/controllers/redirect_to.rb
|
70
|
+
- lib/rspec/rails23/matchers/controllers/render_template.rb
|
71
|
+
- lib/rspec/rails23/mocking/model_stubber.rb
|
72
|
+
- lib/rspec/rails23/mocking/with_mocha.rb
|
73
|
+
- lib/rspec/rails23/mocking/with_rr.rb
|
74
|
+
- lib/rspec/rails23/transactional_database_support.rb
|
75
|
+
- spec/lib/rspec/rails23/configuration_spec.rb
|
76
|
+
- spec/spec_helper.rb
|
77
|
+
has_rdoc: true
|
78
|
+
homepage: http://github.com/rsanheim/rspec-rails23
|
79
|
+
licenses: []
|
80
|
+
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options:
|
83
|
+
- --charset=UTF-8
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
segments:
|
91
|
+
- 0
|
92
|
+
version: "0"
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
segments:
|
98
|
+
- 0
|
99
|
+
version: "0"
|
100
|
+
requirements: []
|
101
|
+
|
102
|
+
rubyforge_project:
|
103
|
+
rubygems_version: 1.3.6
|
104
|
+
signing_key:
|
105
|
+
specification_version: 3
|
106
|
+
summary: Rspec Rails for 2.3.5
|
107
|
+
test_files:
|
108
|
+
- spec/lib/rspec/rails23/configuration_spec.rb
|
109
|
+
- spec/spec_helper.rb
|