micronaut-rails 0.3.3
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 +37 -0
- data/VERSION.yml +4 -0
- data/examples/example_helper.rb +56 -0
- data/examples/lib/micronaut/rails/configuration_example.rb +44 -0
- data/examples/lib/micronaut-rails_example.rb +16 -0
- data/lib/micronaut/rails/configuration.rb +48 -0
- data/lib/micronaut/rails/controllers.rb +86 -0
- data/lib/micronaut/rails/extensions/active_record.rb +19 -0
- data/lib/micronaut/rails/helpers.rb +99 -0
- data/lib/micronaut/rails/matchers/controllers/redirect_to.rb +115 -0
- data/lib/micronaut/rails/matchers/controllers/render_template.rb +116 -0
- data/lib/micronaut/rails/mocking/model_stubber.rb +24 -0
- data/lib/micronaut/rails/mocking/with_mocha.rb +72 -0
- data/lib/micronaut/rails/mocking/with_rr.rb +44 -0
- data/lib/micronaut/rails/transactional_database_support.rb +39 -0
- data/lib/micronaut-rails.rb +16 -0
- metadata +95 -0
data/LICENSE
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
Copyright (c) 2008 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
|
+
= Micronaut Rails
|
2
|
+
|
3
|
+
* http://github.com/spicycode/micronaut-rails
|
4
|
+
* http://relevance.lighthouseapp.com/projects/22819-micronaut
|
5
|
+
|
6
|
+
== DESCRIPTION:
|
7
|
+
|
8
|
+
Micronaut Rails is a set of extension to deal with rails mode testing. For the moment think of it is a prototype of
|
9
|
+
RSpec lite. Definitely pre alpha at the moment.
|
10
|
+
|
11
|
+
== REQUIREMENTS:
|
12
|
+
|
13
|
+
* Ruby 1.8.6+
|
14
|
+
* ActionPack
|
15
|
+
* Micronaut (via spicycode-micronaut on GitHub)
|
16
|
+
|
17
|
+
== ISSUES
|
18
|
+
|
19
|
+
* No support for pure Rails fixtures, and no plans to add it - we use Factory Girl/Fixture Replacement instead, so send a patch if you want support for this).
|
20
|
+
* No support for Rails integration tests -- use Cucumber (http://github.com/aslakhellesoy/cucumber) instead!
|
21
|
+
* In use in real-world projects on Rails 2.3+ - older versions may have issues.
|
22
|
+
|
23
|
+
== CREDITS:
|
24
|
+
|
25
|
+
* RSpec for the great ideas and matchers
|
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,37 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
Jeweler::Tasks.new do |s|
|
4
|
+
s.name = "micronaut-rails"
|
5
|
+
s.summary = "An excellent replacement for the wheel on rails..."
|
6
|
+
s.email = "chad@spicycode.com"
|
7
|
+
s.homepage = "http://github.com/spicycode/micronaut-rails"
|
8
|
+
s.description = "An excellent replacement for the wheel on rails..."
|
9
|
+
s.authors = ["Chad Humphries"]
|
10
|
+
s.files = FileList["[A-Z]*", "{bin,lib,examples}/**/*"]
|
11
|
+
s.add_dependency "actionpack", '>= 2.3.0'
|
12
|
+
s.add_dependency "micronaut", '>= 0.3.0'
|
13
|
+
end
|
14
|
+
rescue LoadError
|
15
|
+
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
16
|
+
end
|
17
|
+
|
18
|
+
gem 'micronaut'
|
19
|
+
require 'micronaut/rake_task'
|
20
|
+
|
21
|
+
desc "Run all micronaut examples"
|
22
|
+
Micronaut::RakeTask.new :examples do |t|
|
23
|
+
t.pattern = "examples/**/*_example.rb"
|
24
|
+
end
|
25
|
+
|
26
|
+
namespace :examples do
|
27
|
+
|
28
|
+
desc "Run all micronaut examples using rcov"
|
29
|
+
Micronaut::RakeTask.new :coverage do |t|
|
30
|
+
t.pattern = "examples/**/*_example.rb"
|
31
|
+
t.rcov = true
|
32
|
+
t.rcov_opts = %[--exclude "examples/*,gems/*,db/*,/Library/Ruby/*,config/*" --text-summary --sort coverage]
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
task :default => 'examples:coverage'
|
data/VERSION.yml
ADDED
@@ -0,0 +1,56 @@
|
|
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
|
+
|
6
|
+
begin
|
7
|
+
gem "micronaut", ">= 0.3.0"
|
8
|
+
rescue LoadError => e
|
9
|
+
puts "\nERROR - This version of micronaut-rails requires micronaut 0.2.2 or higher."
|
10
|
+
puts "gem install micronaut --version 0.2.2"
|
11
|
+
puts
|
12
|
+
exit(1)
|
13
|
+
end
|
14
|
+
require 'action_controller'
|
15
|
+
require 'micronaut'
|
16
|
+
require 'micronaut-rails'
|
17
|
+
|
18
|
+
gem "mocha"
|
19
|
+
|
20
|
+
module Micronaut
|
21
|
+
module Matchers
|
22
|
+
def fail
|
23
|
+
raise_error(::Micronaut::Expectations::ExpectationNotMetError)
|
24
|
+
end
|
25
|
+
|
26
|
+
def fail_with(message)
|
27
|
+
raise_error(::Micronaut::Expectations::ExpectationNotMetError, message)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def remove_last_describe_from_world
|
33
|
+
Micronaut.world.behaviours.pop
|
34
|
+
end
|
35
|
+
|
36
|
+
class DummyFormatter < Micronaut::Formatters::BaseTextFormatter; end
|
37
|
+
|
38
|
+
def dummy_reporter
|
39
|
+
DummyFormatter.new({}, StringIO.new)
|
40
|
+
end
|
41
|
+
|
42
|
+
def use_color?
|
43
|
+
!ENV.has_key?('TM_MODE')
|
44
|
+
end
|
45
|
+
|
46
|
+
# allow including links to lighthouse tickets in examples, for regression tests, pending features, etc.
|
47
|
+
def ticket(number)
|
48
|
+
%[http://relevance.lighthouseapp.com/projects/22819-micronaut/tickets/#{number}]
|
49
|
+
end
|
50
|
+
|
51
|
+
Micronaut.configure do |config|
|
52
|
+
config.mock_with :mocha
|
53
|
+
config.color_enabled = use_color?
|
54
|
+
config.formatter = :documentation
|
55
|
+
config.filter_run :focused => true
|
56
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../../../example_helper")
|
2
|
+
|
3
|
+
describe Micronaut::Rails::Configuration do
|
4
|
+
|
5
|
+
example "loading micronaut rails include it in the micronaut configuration class" do
|
6
|
+
Micronaut::Configuration.included_modules.should include(Micronaut::Rails::Configuration)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should add a #rails method" do
|
10
|
+
Micronaut.configuration.should respond_to(:rails)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should add an #enable_active_record_transactional_support method" do
|
14
|
+
Micronaut.configuration.should respond_to(:enable_active_record_transactional_support)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "helpers for standard Rails testing support" do
|
18
|
+
|
19
|
+
method_to_modules = { :enable_helper_support => Micronaut::Rails::Helpers,
|
20
|
+
:enable_active_record_transactional_support => Micronaut::Rails::TransactionalDatabaseSupport,
|
21
|
+
:enable_controller_support => Micronaut::Rails::Controllers
|
22
|
+
}
|
23
|
+
method_to_modules.each do |method, mod|
|
24
|
+
example "##{method} with no filter options" do
|
25
|
+
Micronaut.configuration.send(method)
|
26
|
+
Micronaut.configuration.include_or_extend_modules.should include([:extend, mod, {}])
|
27
|
+
end
|
28
|
+
|
29
|
+
example "##{method} with filter options" do
|
30
|
+
filter_options = {:options => { "foo" => "bar" } }
|
31
|
+
Micronaut.configuration.send(method, filter_options)
|
32
|
+
Micronaut.configuration.include_or_extend_modules.should include([:extend, mod, filter_options])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
example "#enable_rails_specific_mocking_extensions for mocha with no filter options" do
|
37
|
+
Micronaut.configuration.mock_with :mocha
|
38
|
+
Micronaut.configuration.enable_rails_specific_mocking_extensions
|
39
|
+
Micronaut.configuration.include_or_extend_modules.should include([:include, Micronaut::Rails::Mocking::WithMocha, {}])
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../example_helper")
|
2
|
+
|
3
|
+
describe Micronaut::Rails do
|
4
|
+
|
5
|
+
pending "should never include lib/autotest in the gemspec, as it breaks autotest for Micronaut - see #{ticket 4}
|
6
|
+
PENDING due to jeweler changing the gemspec tasks..." do
|
7
|
+
# We jump through hoops to make sure the Rake deprecation notice doesn't show up in the build (via stderr) or
|
8
|
+
# in the gemspec itself
|
9
|
+
silence_stream(STDERR) do
|
10
|
+
@spec_string = `rake --silent gemspec`
|
11
|
+
end
|
12
|
+
@spec_string.gsub! /Gem::manage_gems is deprecated/, ""
|
13
|
+
gem_spec = eval(@spec_string)
|
14
|
+
gem_spec.files.each { |f| f.should_not match(%r|lib/autotest|) }
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Micronaut
|
2
|
+
module Rails
|
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
|
+
::Micronaut.configuration.extend(::Micronaut::Rails::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
|
+
::Micronaut.configuration.extend(::Micronaut::Rails::Helpers, filter_options)
|
18
|
+
end
|
19
|
+
|
20
|
+
# :behaviour => { :describes => lambda { |dt| dt < ActionController::Base }
|
21
|
+
def enable_controller_support(filter_options={})
|
22
|
+
::Micronaut.configuration.extend(::Micronaut::Rails::Controllers, filter_options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def enable_rails_specific_mocking_extensions(filter_options={})
|
26
|
+
case ::Micronaut.configuration.mock_framework.to_s
|
27
|
+
when /mocha/i
|
28
|
+
require 'micronaut/rails/mocking/with_mocha'
|
29
|
+
::Micronaut.configuration.include(::Micronaut::Rails::Mocking::WithMocha, filter_options)
|
30
|
+
when /rr/i
|
31
|
+
require 'micronaut/rails/mocking/with_rr'
|
32
|
+
::Micronaut.configuration.include(::Micronaut::Rails::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
|
+
::Micronaut::Configuration.send(:include, ::Micronaut::Rails::Configuration)
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'action_controller'
|
2
|
+
require 'action_controller/test_process'
|
3
|
+
|
4
|
+
module Micronaut
|
5
|
+
module Rails
|
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, ::Micronaut::Rails::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 Micronaut
|
2
|
+
module Rails
|
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, ::Micronaut::Rails::Extensions::ActiveRecord)
|
19
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Micronaut
|
2
|
+
module Rails
|
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 = ::Micronaut::Rails::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 Micronaut
|
2
|
+
module Rails
|
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 Micronaut
|
2
|
+
module Rails
|
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 Micronaut
|
2
|
+
module Rails
|
3
|
+
module Mocking
|
4
|
+
|
5
|
+
module ModelStubber
|
6
|
+
|
7
|
+
def connection
|
8
|
+
raise ::Micronaut::Rails::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 Micronaut
|
2
|
+
module Rails
|
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 ::Micronaut::Rails::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 Micronaut
|
2
|
+
module Rails
|
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 ::Micronaut::Rails::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 Micronaut
|
2
|
+
module Rails
|
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,16 @@
|
|
1
|
+
require 'micronaut/rails/configuration'
|
2
|
+
require 'micronaut/rails/matchers/controllers/redirect_to'
|
3
|
+
require 'micronaut/rails/matchers/controllers/render_template'
|
4
|
+
require 'micronaut/rails/transactional_database_support'
|
5
|
+
require 'micronaut/rails/controllers'
|
6
|
+
require 'micronaut/rails/helpers'
|
7
|
+
require 'micronaut/rails/extensions/active_record'
|
8
|
+
require 'micronaut/rails/mocking/model_stubber'
|
9
|
+
|
10
|
+
module Micronaut
|
11
|
+
module Rails
|
12
|
+
class IllegalDataAccessException < StandardError; end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: micronaut-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chad Humphries
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-10-09 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: actionpack
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.3.0
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: micronaut
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.3.0
|
34
|
+
version:
|
35
|
+
description: An excellent replacement for the wheel on rails...
|
36
|
+
email: chad@spicycode.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- LICENSE
|
43
|
+
- README
|
44
|
+
files:
|
45
|
+
- LICENSE
|
46
|
+
- README
|
47
|
+
- RSPEC-LICENSE
|
48
|
+
- Rakefile
|
49
|
+
- VERSION.yml
|
50
|
+
- examples/example_helper.rb
|
51
|
+
- examples/lib/micronaut-rails_example.rb
|
52
|
+
- examples/lib/micronaut/rails/configuration_example.rb
|
53
|
+
- lib/micronaut-rails.rb
|
54
|
+
- lib/micronaut/rails/configuration.rb
|
55
|
+
- lib/micronaut/rails/controllers.rb
|
56
|
+
- lib/micronaut/rails/extensions/active_record.rb
|
57
|
+
- lib/micronaut/rails/helpers.rb
|
58
|
+
- lib/micronaut/rails/matchers/controllers/redirect_to.rb
|
59
|
+
- lib/micronaut/rails/matchers/controllers/render_template.rb
|
60
|
+
- lib/micronaut/rails/mocking/model_stubber.rb
|
61
|
+
- lib/micronaut/rails/mocking/with_mocha.rb
|
62
|
+
- lib/micronaut/rails/mocking/with_rr.rb
|
63
|
+
- lib/micronaut/rails/transactional_database_support.rb
|
64
|
+
has_rdoc: true
|
65
|
+
homepage: http://github.com/spicycode/micronaut-rails
|
66
|
+
licenses: []
|
67
|
+
|
68
|
+
post_install_message:
|
69
|
+
rdoc_options:
|
70
|
+
- --charset=UTF-8
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: "0"
|
78
|
+
version:
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: "0"
|
84
|
+
version:
|
85
|
+
requirements: []
|
86
|
+
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 1.3.5
|
89
|
+
signing_key:
|
90
|
+
specification_version: 3
|
91
|
+
summary: An excellent replacement for the wheel on rails...
|
92
|
+
test_files:
|
93
|
+
- examples/example_helper.rb
|
94
|
+
- examples/lib/micronaut/rails/configuration_example.rb
|
95
|
+
- examples/lib/micronaut-rails_example.rb
|