Description:
added rspec_on_rails plugin not as svn externals (frozen) git-svn-id: http://theory.cpe.ku.ac.th/grader/web/trunk@134 6386c4cd-e34a-4fa8-8920-d93eb39b512e
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r60:f8c242fd7c91 - - 145 files changed: 6096 inserted, 0 deleted

@@ -0,0 +1,4
1 + #!/usr/bin/env ruby
2 + $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../vendor/plugins/rspec/lib"))
3 + require 'spec'
4 + exit ::Spec::Runner::CommandLine.run(::Spec::Runner::OptionParser.parse(ARGV, STDERR, STDOUT))
@@ -0,0 +1,102
1 + #!/usr/bin/env ruby
2 + $LOAD_PATH.unshift File.dirname(__FILE__) + '/../../rspec/lib' # For svn
3 + $LOAD_PATH.unshift File.dirname(__FILE__) + '/../vendor/plugins/rspec/lib' # For rspec installed as plugin
4 + require 'rubygems'
5 + require 'drb/drb'
6 + require 'rbconfig'
7 + require 'spec'
8 + require 'optparse'
9 +
10 + # This is based on Florian Weber's TDDMate
11 + module Spec
12 + module Runner
13 + class RailsSpecServer
14 + def run(argv, stderr, stdout)
15 + $stdout = stdout
16 + $stderr = stderr
17 +
18 + base = ActiveRecord::Base
19 + def base.clear_reloadable_connections!
20 + active_connections.each do |name, conn|
21 + if conn.requires_reloading?
22 + conn.disconnect!
23 + active_connections.delete(name)
24 + end
25 + end
26 + end
27 +
28 + if ActionController.const_defined?(:Dispatcher)
29 + dispatcher = ::ActionController::Dispatcher.new($stdout)
30 + dispatcher.cleanup_application(true)
31 + elsif ::Dispatcher.respond_to?(:reset_application!)
32 + ::Dispatcher.reset_application!
33 + else
34 + raise "Application reloading failed"
35 + end
36 + ::Dependencies.mechanism = :load
37 + require_dependency('application.rb') unless Object.const_defined?(:ApplicationController)
38 + load File.dirname(__FILE__) + '/../spec/spec_helper.rb'
39 +
40 + ::Spec::Runner::CommandLine.run(
41 + ::Spec::Runner::OptionParser.parse(
42 + argv,
43 + $stderr,
44 + $stdout
45 + )
46 + )
47 + end
48 + end
49 + end
50 + end
51 + puts "Loading Rails environment"
52 +
53 + ENV["RAILS_ENV"] = "test"
54 + require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
55 + require 'dispatcher'
56 +
57 + def restart_test_server
58 + puts "restarting"
59 + config = ::Config::CONFIG
60 + ruby = File::join(config['bindir'], config['ruby_install_name']) + config['EXEEXT']
61 + command_line = [ruby, $0, ARGV].flatten.join(' ')
62 + exec(command_line)
63 + end
64 +
65 + def daemonize(pid_file = nil)
66 + return yield if $DEBUG
67 + pid = Process.fork{
68 + Process.setsid
69 + Dir.chdir(RAILS_ROOT)
70 + trap("SIGINT"){ exit! 0 }
71 + trap("SIGTERM"){ exit! 0 }
72 + trap("SIGHUP"){ restart_test_server }
73 + File.open("/dev/null"){|f|
74 + STDERR.reopen f
75 + STDIN.reopen f
76 + STDOUT.reopen f
77 + }
78 + yield
79 + }
80 + puts "spec_server launched. (PID: %d)" % pid
81 + File.open(pid_file,"w"){|f| f.puts pid } if pid_file
82 + exit! 0
83 + end
84 +
85 + options = Hash.new
86 + opts = OptionParser.new
87 + opts.on("-d", "--daemon"){|v| options[:daemon] = true }
88 + opts.on("-p", "--pid PIDFILE"){|v| options[:pid] = v }
89 + opts.parse!(ARGV)
90 +
91 + puts "Ready"
92 + exec_server = lambda {
93 + trap("USR2") { restart_test_server } if Signal.list.has_key?("USR2")
94 + DRb.start_service("druby://localhost:8989", Spec::Runner::RailsSpecServer.new)
95 + DRb.thread.join
96 + }
97 +
98 + if options[:daemon]
99 + daemonize(options[:pid], &exec_server)
100 + else
101 + exec_server.call
102 + end
@@ -0,0 +1,2
1 + --exclude "spec/*,gems/*"
2 + --rails No newline at end of file
@@ -0,0 +1,6
1 + --colour
2 + --format
3 + progress
4 + --loadby
5 + mtime
6 + --reverse
@@ -0,0 +1,39
1 + # This file is copied to ~/spec when you run 'ruby script/generate rspec'
2 + # from the project root directory.
3 + ENV["RAILS_ENV"] = "test"
4 + require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
5 + require 'spec'
6 + require 'spec/rails'
7 +
8 + Spec::Runner.configure do |config|
9 + # If you're not using ActiveRecord you should remove these
10 + # lines, delete config/database.yml and disable :active_record
11 + # in your config/boot.rb
12 + config.use_transactional_fixtures = true
13 + config.use_instantiated_fixtures = false
14 + config.fixture_path = RAILS_ROOT + '/spec/fixtures/'
15 +
16 + # == Fixtures
17 + #
18 + # You can declare fixtures for each example_group like this:
19 + # describe "...." do
20 + # fixtures :table_a, :table_b
21 + #
22 + # Alternatively, if you prefer to declare them only once, you can
23 + # do so right here. Just uncomment the next line and replace the fixture
24 + # names with your fixtures.
25 + #
26 + # config.global_fixtures = :table_a, :table_b
27 + #
28 + # If you declare global fixtures, be aware that they will be declared
29 + # for all of your examples, even those that don't use them.
30 + #
31 + # == Mock Framework
32 + #
33 + # RSpec uses it's own mocking framework by default. If you prefer to
34 + # use mocha, flexmock or RR, uncomment the appropriate line:
35 + #
36 + # config.mock_with :mocha
37 + # config.mock_with :flexmock
38 + # config.mock_with :rr
39 + end
@@ -0,0 +1,4
1 + dir = File.dirname(__FILE__)
2 + Dir[File.expand_path("#{dir}/**/*.rb")].uniq.each do |file|
3 + require file
4 + end No newline at end of file
@@ -0,0 +1,3
1 + ENV["RAILS_ENV"] = "test"
2 + require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
3 + require 'spec/rails/story_adapter' No newline at end of file
@@ -0,0 +1,31
1 + ====================================================================
2 + == RSpec
3 + Copyright (c) 2005-2007 The RSpec Development Team
4 + ====================================================================
5 + == ARTS
6 + Copyright (c) 2006 Kevin Clark, Jake Howerton
7 + ====================================================================
8 + == ZenTest
9 + Copyright (c) 2001-2006 Ryan Davis, Eric Hodel, Zen Spider Software
10 + ====================================================================
11 + == AssertSelect
12 + Copyright (c) 2006 Assaf Arkin
13 + ====================================================================
14 +
15 + Permission is hereby granted, free of charge, to any person obtaining a copy of
16 + this software and associated documentation files (the "Software"), to deal in
17 + the Software without restriction, including without limitation the rights to
18 + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
19 + of the Software, and to permit persons to whom the Software is furnished to do
20 + so, subject to the following conditions:
21 +
22 + The above copyright notice and this permission notice shall be included in all
23 + copies or substantial portions of the Software.
24 +
25 + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28 + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30 + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 + SOFTWARE.
@@ -0,0 +1,3
1 + See the rdoc for Spec::Rails for usage documentation.
2 +
3 + See ~/rspec/README for instructions on running rspec_on_rails' examples. No newline at end of file
@@ -0,0 +1,9
1 + require 'rake'
2 + require 'rake/rdoctask'
3 +
4 + desc 'Generate RDoc'
5 + rd = Rake::RDocTask.new do |rdoc|
6 + rdoc.rdoc_dir = '../doc/output/rdoc-rails'
7 + rdoc.options << '--title' << 'Spec::Rails' << '--line-numbers' << '--inline-source' << '--main' << 'Spec::Rails'
8 + rdoc.rdoc_files.include('MIT-LICENSE', 'lib/**/*.rb')
9 + end
@@ -0,0 +1,1
1 + Please refer to the CHANGES file for RSpec's core No newline at end of file
@@ -0,0 +1,35
1 + require 'rbconfig'
2 +
3 + # This generator bootstraps a Rails project for use with RSpec
4 + class RspecGenerator < Rails::Generator::Base
5 + DEFAULT_SHEBANG = File.join(Config::CONFIG['bindir'],
6 + Config::CONFIG['ruby_install_name'])
7 +
8 + def initialize(runtime_args, runtime_options = {})
9 + super
10 + end
11 +
12 + def manifest
13 + record do |m|
14 + script_options = { :chmod => 0755, :shebang => options[:shebang] == DEFAULT_SHEBANG ? nil : options[:shebang] }
15 +
16 + m.directory 'spec'
17 + m.template 'spec_helper.rb', 'spec/spec_helper.rb'
18 + m.file 'spec.opts', 'spec/spec.opts'
19 + m.file 'rcov.opts', 'spec/rcov.opts'
20 + m.file 'script/spec_server', 'script/spec_server', script_options
21 + m.file 'script/spec', 'script/spec', script_options
22 +
23 + m.directory 'stories'
24 + m.file 'all_stories.rb', 'stories/all.rb'
25 + m.file 'stories_helper.rb', 'stories/helper.rb'
26 + end
27 + end
28 +
29 + protected
30 +
31 + def banner
32 + "Usage: #{$0} rspec"
33 + end
34 +
35 + end
@@ -0,0 +1,4
1 + dir = File.dirname(__FILE__)
2 + Dir[File.expand_path("#{dir}/**/*.rb")].uniq.each do |file|
3 + require file
4 + end No newline at end of file
new file 100644
@@ -0,0 +1,2
1 + --exclude "spec/*,gems/*"
2 + --rails No newline at end of file
@@ -0,0 +1,4
1 + #!/usr/bin/env ruby
2 + $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../vendor/plugins/rspec/lib"))
3 + require 'spec'
4 + exit ::Spec::Runner::CommandLine.run(::Spec::Runner::OptionParser.parse(ARGV, STDERR, STDOUT))
@@ -0,0 +1,102
1 + #!/usr/bin/env ruby
2 + $LOAD_PATH.unshift File.dirname(__FILE__) + '/../../rspec/lib' # For svn
3 + $LOAD_PATH.unshift File.dirname(__FILE__) + '/../vendor/plugins/rspec/lib' # For rspec installed as plugin
4 + require 'rubygems'
5 + require 'drb/drb'
6 + require 'rbconfig'
7 + require 'spec'
8 + require 'optparse'
9 +
10 + # This is based on Florian Weber's TDDMate
11 + module Spec
12 + module Runner
13 + class RailsSpecServer
14 + def run(argv, stderr, stdout)
15 + $stdout = stdout
16 + $stderr = stderr
17 +
18 + base = ActiveRecord::Base
19 + def base.clear_reloadable_connections!
20 + active_connections.each do |name, conn|
21 + if conn.requires_reloading?
22 + conn.disconnect!
23 + active_connections.delete(name)
24 + end
25 + end
26 + end
27 +
28 + if ActionController.const_defined?(:Dispatcher)
29 + dispatcher = ::ActionController::Dispatcher.new($stdout)
30 + dispatcher.cleanup_application(true)
31 + elsif ::Dispatcher.respond_to?(:reset_application!)
32 + ::Dispatcher.reset_application!
33 + else
34 + raise "Application reloading failed"
35 + end
36 + ::Dependencies.mechanism = :load
37 + require_dependency('application.rb') unless Object.const_defined?(:ApplicationController)
38 + load File.dirname(__FILE__) + '/../spec/spec_helper.rb'
39 +
40 + ::Spec::Runner::CommandLine.run(
41 + ::Spec::Runner::OptionParser.parse(
42 + argv,
43 + $stderr,
44 + $stdout
45 + )
46 + )
47 + end
48 + end
49 + end
50 + end
51 + puts "Loading Rails environment"
52 +
53 + ENV["RAILS_ENV"] = "test"
54 + require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
55 + require 'dispatcher'
56 +
57 + def restart_test_server
58 + puts "restarting"
59 + config = ::Config::CONFIG
60 + ruby = File::join(config['bindir'], config['ruby_install_name']) + config['EXEEXT']
61 + command_line = [ruby, $0, ARGV].flatten.join(' ')
62 + exec(command_line)
63 + end
64 +
65 + def daemonize(pid_file = nil)
66 + return yield if $DEBUG
67 + pid = Process.fork{
68 + Process.setsid
69 + Dir.chdir(RAILS_ROOT)
70 + trap("SIGINT"){ exit! 0 }
71 + trap("SIGTERM"){ exit! 0 }
72 + trap("SIGHUP"){ restart_test_server }
73 + File.open("/dev/null"){|f|
74 + STDERR.reopen f
75 + STDIN.reopen f
76 + STDOUT.reopen f
77 + }
78 + yield
79 + }
80 + puts "spec_server launched. (PID: %d)" % pid
81 + File.open(pid_file,"w"){|f| f.puts pid } if pid_file
82 + exit! 0
83 + end
84 +
85 + options = Hash.new
86 + opts = OptionParser.new
87 + opts.on("-d", "--daemon"){|v| options[:daemon] = true }
88 + opts.on("-p", "--pid PIDFILE"){|v| options[:pid] = v }
89 + opts.parse!(ARGV)
90 +
91 + puts "Ready"
92 + exec_server = lambda {
93 + trap("USR2") { restart_test_server } if Signal.list.has_key?("USR2")
94 + DRb.start_service("druby://localhost:8989", Spec::Runner::RailsSpecServer.new)
95 + DRb.thread.join
96 + }
97 +
98 + if options[:daemon]
99 + daemonize(options[:pid], &exec_server)
100 + else
101 + exec_server.call
102 + end
@@ -0,0 +1,6
1 + --colour
2 + --format
3 + progress
4 + --loadby
5 + mtime
6 + --reverse
@@ -0,0 +1,39
1 + # This file is copied to ~/spec when you run 'ruby script/generate rspec'
2 + # from the project root directory.
3 + ENV["RAILS_ENV"] = "test"
4 + require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
5 + require 'spec'
6 + require 'spec/rails'
7 +
8 + Spec::Runner.configure do |config|
9 + # If you're not using ActiveRecord you should remove these
10 + # lines, delete config/database.yml and disable :active_record
11 + # in your config/boot.rb
12 + config.use_transactional_fixtures = true
13 + config.use_instantiated_fixtures = false
14 + config.fixture_path = RAILS_ROOT + '/spec/fixtures/'
15 +
16 + # == Fixtures
17 + #
18 + # You can declare fixtures for each example_group like this:
19 + # describe "...." do
20 + # fixtures :table_a, :table_b
21 + #
22 + # Alternatively, if you prefer to declare them only once, you can
23 + # do so right here. Just uncomment the next line and replace the fixture
24 + # names with your fixtures.
25 + #
26 + # config.global_fixtures = :table_a, :table_b
27 + #
28 + # If you declare global fixtures, be aware that they will be declared
29 + # for all of your examples, even those that don't use them.
30 + #
31 + # == Mock Framework
32 + #
33 + # RSpec uses it's own mocking framework by default. If you prefer to
34 + # use mocha, flexmock or RR, uncomment the appropriate line:
35 + #
36 + # config.mock_with :mocha
37 + # config.mock_with :flexmock
38 + # config.mock_with :rr
39 + end
@@ -0,0 +1,3
1 + ENV["RAILS_ENV"] = "test"
2 + require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
3 + require 'spec/rails/story_adapter' No newline at end of file
@@ -0,0 +1,33
1 + Description:
2 + The rspec_controller generator creates stub specs and files for a new
3 + controller and its views.
4 +
5 + The generator takes a controller name and a list of views as arguments.
6 + The controller name may be given in CamelCase or under_score and should
7 + not be suffixed with 'Controller'. To create a controller within a
8 + module, specify the controller name as 'module/controller'.
9 +
10 + The generator creates stubs for a controller (and spec), a view (and spec)
11 + for each view in the argument list, plus a helper.
12 +
13 + Example:
14 + ./script/generate rspec_controller dog bark fetch
15 + ...
16 + create spec/controllers/dog_controller_spec.rb
17 + create app/controllers/dog_controller.rb
18 + create app/helpers/dog_helper.rb
19 + create spec/views/dog/bark_view_spec.rb
20 + create app/views/dog/bark.rhtml
21 + create spec/views/dog/fetch_view_spec.rb
22 + create app/views/dog/fetch.rhtml
23 +
24 + Modules Example:
25 + ./script/generate rspec_controller 'pets/dog' bark fetch
26 + ...
27 + create spec/controllers/pets/dog_controller_spec.rb
28 + create app/controllers/pets/dog_controller.rb
29 + create app/helpers/pets/dog_helper.rb
30 + create spec/views/pets/dog/bark_view_spec.rb
31 + create app/views/pets/dog/bark.rhtml
32 + create spec/views/pets/dog/fetch_view_spec.rb
33 + create app/views/pets/dog/fetch.rhtml
@@ -0,0 +1,49
1 + require 'rails_generator/generators/components/controller/controller_generator'
2 +
3 + class RspecControllerGenerator < ControllerGenerator
4 +
5 + def manifest
6 + record do |m|
7 + # Check for class naming collisions.
8 + m.class_collisions class_path, "#{class_name}Controller", "#{class_name}Helper"
9 +
10 + # Controller, helper, views, and spec directories.
11 + m.directory File.join('app/controllers', class_path)
12 + m.directory File.join('app/helpers', class_path)
13 + m.directory File.join('app/views', class_path, file_name)
14 + m.directory File.join('spec/controllers', class_path)
15 + m.directory File.join('spec/helpers', class_path)
16 + m.directory File.join('spec/views', class_path, file_name)
17 +
18 + if Rails::VERSION::STRING < "2.0.0"
19 + @default_file_extension = "rhtml"
20 + else
21 + @default_file_extension = "html.erb"
22 + end
23 +
24 + # Controller spec, class, and helper.
25 + m.template 'controller_spec.rb',
26 + File.join('spec/controllers', class_path, "#{file_name}_controller_spec.rb")
27 +
28 + m.template 'helper_spec.rb',
29 + File.join('spec/helpers', class_path, "#{file_name}_helper_spec.rb")
30 +
31 + m.template 'controller:controller.rb',
32 + File.join('app/controllers', class_path, "#{file_name}_controller.rb")
33 +
34 + m.template 'controller:helper.rb',
35 + File.join('app/helpers', class_path, "#{file_name}_helper.rb")
36 +
37 + # Spec and view template for each action.
38 + actions.each do |action|
39 + m.template 'view_spec.rb',
40 + File.join('spec/views', class_path, file_name, "#{action}.#{@default_file_extension}_spec.rb"),
41 + :assigns => { :action => action, :model => file_name }
42 + path = File.join('app/views', class_path, file_name, "#{action}.#{@default_file_extension}")
43 + m.template "controller:view.#{@default_file_extension}",
44 + path,
45 + :assigns => { :action => action, :path => path }
46 + end
47 + end
48 + end
49 + end
@@ -0,0 +1,25
1 + require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../spec_helper'
2 +
3 + describe <%= class_name %>Controller do
4 +
5 + <% if actions.empty? -%>
6 + #Delete this example and add some real ones
7 + <% else -%>
8 + #Delete these examples and add some real ones
9 + <% end -%>
10 + it "should use <%= class_name %>Controller" do
11 + controller.should be_an_instance_of(<%= class_name %>Controller)
12 + end
13 +
14 + <% unless actions.empty? -%>
15 + <% for action in actions -%>
16 +
17 + describe "GET '<%= action %>'" do
18 + it "should be successful" do
19 + get '<%= action %>'
20 + response.should be_success
21 + end
22 + end
23 + <% end -%>
24 + <% end -%>
25 + end
@@ -0,0 +1,11
1 + require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../spec_helper'
2 +
3 + describe <%= class_name %>Helper do
4 +
5 + #Delete this example and add some real ones or delete this file
6 + it "should include the <%= class_name %>Helper" do
7 + included_modules = self.metaclass.send :included_modules
8 + included_modules.should include(<%= class_name %>Helper)
9 + end
10 +
11 + end
@@ -0,0 +1,12
1 + require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../../spec_helper'
2 +
3 + describe "/<%= class_name.underscore %>/<%= action %>" do
4 + before(:each) do
5 + render '<%= class_name.underscore %>/<%= action %>'
6 + end
7 +
8 + #Delete this example and add some real ones or delete this file
9 + it "should tell you where to find the file" do
10 + response.should have_tag('p', /Find me in app\/views\/<%= class_name.underscore %>\/<%= action %>/)
11 + end
12 + end
@@ -0,0 +1,18
1 + Description:
2 + The rspec_model generator creates stubs for a new model.
3 +
4 + The generator takes a model name as its argument. The model name may be
5 + given in CamelCase or under_score and should not be suffixed with 'Model'.
6 +
7 + The generator creates a model class in app/models, an RSpec spec in
8 + spec/models, database fixtures in spec/fixtures/plural_name.yml, and a migration
9 + in db/migrate.
10 +
11 + Example:
12 + ./script/generate rspec_model Account
13 +
14 + This will create an Account model:
15 + Model: app/models/account.rb
16 + Spec: spec/models/account_spec.rb
17 + Fixtures: spec/fixtures/accounts.yml
18 + Migration: db/migrate/XXX_add_accounts.rb
@@ -0,0 +1,30
1 + require 'rails_generator/generators/components/model/model_generator'
2 +
3 + class RspecModelGenerator < ModelGenerator
4 +
5 + def manifest
6 +
7 + record do |m|
8 + # Check for class naming collisions.
9 + m.class_collisions class_path, class_name
10 +
11 + # Model, spec, and fixture directories.
12 + m.directory File.join('app/models', class_path)
13 + m.directory File.join('spec/models', class_path)
14 + m.directory File.join('spec/fixtures', class_path)
15 +
16 + # Model class, spec and fixtures.
17 + m.template 'model:model.rb', File.join('app/models', class_path, "#{file_name}.rb")
18 + m.template 'model:fixtures.yml', File.join('spec/fixtures', class_path, "#{table_name}.yml")
19 + m.template 'model_spec.rb', File.join('spec/models', class_path, "#{file_name}_spec.rb")
20 +
21 + unless options[:skip_migration]
22 + m.migration_template 'model:migration.rb', 'db/migrate', :assigns => {
23 + :migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}"
24 + }, :migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}"
25 + end
26 +
27 + end
28 + end
29 +
30 + end
@@ -0,0 +1,11
1 + require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../spec_helper'
2 +
3 + describe <%= class_name %> do
4 + before(:each) do
5 + @<%= file_name %> = <%= class_name %>.new
6 + end
7 +
8 + it "should be valid" do
9 + @<%= file_name %>.should be_valid
10 + end
11 + end
@@ -0,0 +1,167
1 + class RspecScaffoldGenerator < Rails::Generator::NamedBase
2 + default_options :skip_migration => false
3 +
4 + attr_reader :controller_name,
5 + :controller_class_path,
6 + :controller_file_path,
7 + :controller_class_nesting,
8 + :controller_class_nesting_depth,
9 + :controller_class_name,
10 + :controller_singular_name,
11 + :controller_plural_name,
12 + :resource_edit_path,
13 + :default_file_extension
14 + alias_method :controller_file_name, :controller_singular_name
15 + alias_method :controller_table_name, :controller_plural_name
16 +
17 + def initialize(runtime_args, runtime_options = {})
18 + super
19 +
20 + @controller_name = @name.pluralize
21 +
22 + base_name, @controller_class_path, @controller_file_path, @controller_class_nesting, @controller_class_nesting_depth = extract_modules(@controller_name)
23 + @controller_class_name_without_nesting, @controller_singular_name, @controller_plural_name = inflect_names(base_name)
24 +
25 + if @controller_class_nesting.empty?
26 + @controller_class_name = @controller_class_name_without_nesting
27 + else
28 + @controller_class_name = "#{@controller_class_nesting}::#{@controller_class_name_without_nesting}"
29 + end
30 +
31 + if Rails::VERSION::STRING < "2.0.0"
32 + @resource_generator = "scaffold_resource"
33 + @default_file_extension = "rhtml"
34 + else
35 + @resource_generator = "scaffold"
36 + @default_file_extension = "html.erb"
37 + end
38 +
39 + if ActionController::Base.respond_to?(:resource_action_separator)
40 + @resource_edit_path = "/edit"
41 + else
42 + @resource_edit_path = ";edit"
43 + end
44 + end
45 +
46 + def manifest
47 + record do |m|
48 +
49 + # Check for class naming collisions.
50 + m.class_collisions(controller_class_path, "#{controller_class_name}Controller", "#{controller_class_name}Helper")
51 + m.class_collisions(class_path, "#{class_name}")
52 +
53 + # Controller, helper, views, and spec directories.
54 + m.directory(File.join('app/models', class_path))
55 + m.directory(File.join('app/controllers', controller_class_path))
56 + m.directory(File.join('app/helpers', controller_class_path))
57 + m.directory(File.join('app/views', controller_class_path, controller_file_name))
58 + m.directory(File.join('spec/controllers', controller_class_path))
59 + m.directory(File.join('spec/models', class_path))
60 + m.directory(File.join('spec/helpers', class_path))
61 + m.directory File.join('spec/fixtures', class_path)
62 + m.directory File.join('spec/views', controller_class_path, controller_file_name)
63 +
64 + # Controller spec, class, and helper.
65 + m.template 'rspec_scaffold:routing_spec.rb',
66 + File.join('spec/controllers', controller_class_path, "#{controller_file_name}_routing_spec.rb")
67 +
68 + m.template 'rspec_scaffold:controller_spec.rb',
69 + File.join('spec/controllers', controller_class_path, "#{controller_file_name}_controller_spec.rb")
70 +
71 + m.template "#{@resource_generator}:controller.rb",
72 + File.join('app/controllers', controller_class_path, "#{controller_file_name}_controller.rb")
73 +
74 + m.template 'rspec_scaffold:helper_spec.rb',
75 + File.join('spec/helpers', class_path, "#{controller_file_name}_helper_spec.rb")
76 +
77 + m.template "#{@resource_generator}:helper.rb",
78 + File.join('app/helpers', controller_class_path, "#{controller_file_name}_helper.rb")
79 +
80 + for action in scaffold_views
81 + m.template(
82 + "#{@resource_generator}:view_#{action}.#{@default_file_extension}",
83 + File.join('app/views', controller_class_path, controller_file_name, "#{action}.#{default_file_extension}")
84 + )
85 + end
86 +
87 + # Model class, unit test, and fixtures.
88 + m.template 'model:model.rb', File.join('app/models', class_path, "#{file_name}.rb")
89 + m.template 'model:fixtures.yml', File.join('spec/fixtures', class_path, "#{table_name}.yml")
90 + m.template 'rspec_model:model_spec.rb', File.join('spec/models', class_path, "#{file_name}_spec.rb")
91 +
92 + # View specs
93 + m.template "rspec_scaffold:edit_erb_spec.rb",
94 + File.join('spec/views', controller_class_path, controller_file_name, "edit.#{default_file_extension}_spec.rb")
95 + m.template "rspec_scaffold:index_erb_spec.rb",
96 + File.join('spec/views', controller_class_path, controller_file_name, "index.#{default_file_extension}_spec.rb")
97 + m.template "rspec_scaffold:new_erb_spec.rb",
98 + File.join('spec/views', controller_class_path, controller_file_name, "new.#{default_file_extension}_spec.rb")
99 + m.template "rspec_scaffold:show_erb_spec.rb",
100 + File.join('spec/views', controller_class_path, controller_file_name, "show.#{default_file_extension}_spec.rb")
101 +
102 + unless options[:skip_migration]
103 + m.migration_template(
104 + 'model:migration.rb', 'db/migrate',
105 + :assigns => {
106 + :migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}",
107 + :attributes => attributes
108 + },
109 + :migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}"
110 + )
111 + end
112 +
113 + m.route_resources controller_file_name
114 +
115 + end
116 + end
117 +
118 + protected
119 + # Override with your own usage banner.
120 + def banner
121 + "Usage: #{$0} rspec_scaffold ModelName [field:type field:type]"
122 + end
123 +
124 + def add_options!(opt)
125 + opt.separator ''
126 + opt.separator 'Options:'
127 + opt.on("--skip-migration",
128 + "Don't generate a migration file for this model") { |v| options[:skip_migration] = v }
129 + end
130 +
131 + def scaffold_views
132 + %w[ index show new edit ]
133 + end
134 +
135 + def model_name
136 + class_name.demodulize
137 + end
138 + end
139 +
140 + module Rails
141 + module Generator
142 + class GeneratedAttribute
143 + def default_value
144 + @default_value ||= case type
145 + when :int, :integer then "\"1\""
146 + when :float then "\"1.5\""
147 + when :decimal then "\"9.99\""
148 + when :datetime, :timestamp, :time then "Time.now"
149 + when :date then "Date.today"
150 + when :string then "\"MyString\""
151 + when :text then "\"MyText\""
152 + when :boolean then "false"
153 + else
154 + ""
155 + end
156 + end
157 +
158 + def input_type
159 + @input_type ||= case type
160 + when :text then "textarea"
161 + else
162 + "input"
163 + end
164 + end
165 + end
166 + end
167 + end
@@ -0,0 +1,313
1 + require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../spec_helper'
2 +
3 + describe <%= controller_class_name %>Controller do
4 + describe "handling GET /<%= table_name %>" do
5 +
6 + before(:each) do
7 + @<%= file_name %> = mock_model(<%= class_name %>)
8 + <%= class_name %>.stub!(:find).and_return([@<%= file_name %>])
9 + end
10 +
11 + def do_get
12 + get :index
13 + end
14 +
15 + it "should be successful" do
16 + do_get
17 + response.should be_success
18 + end
19 +
20 + it "should render index template" do
21 + do_get
22 + response.should render_template('index')
23 + end
24 +
25 + it "should find all <%= table_name %>" do
26 + <%= class_name %>.should_receive(:find).with(:all).and_return([@<%= file_name %>])
27 + do_get
28 + end
29 +
30 + it "should assign the found <%= table_name %> for the view" do
31 + do_get
32 + assigns[:<%= table_name %>].should == [@<%= file_name %>]
33 + end
34 + end
35 +
36 + describe "handling GET /<%= table_name %>.xml" do
37 +
38 + before(:each) do
39 + @<%= file_name %> = mock_model(<%= class_name %>, :to_xml => "XML")
40 + <%= class_name %>.stub!(:find).and_return(@<%= file_name %>)
41 + end
42 +
43 + def do_get
44 + @request.env["HTTP_ACCEPT"] = "application/xml"
45 + get :index
46 + end
47 +
48 + it "should be successful" do
49 + do_get
50 + response.should be_success
51 + end
52 +
53 + it "should find all <%= table_name %>" do
54 + <%= class_name %>.should_receive(:find).with(:all).and_return([@<%= file_name %>])
55 + do_get
56 + end
57 +
58 + it "should render the found <%= table_name %> as xml" do
59 + @<%= file_name %>.should_receive(:to_xml).and_return("XML")
60 + do_get
61 + response.body.should == "XML"
62 + end
63 + end
64 +
65 + describe "handling GET /<%= table_name %>/1" do
66 +
67 + before(:each) do
68 + @<%= file_name %> = mock_model(<%= class_name %>)
69 + <%= class_name %>.stub!(:find).and_return(@<%= file_name %>)
70 + end
71 +
72 + def do_get
73 + get :show, :id => "1"
74 + end
75 +
76 + it "should be successful" do
77 + do_get
78 + response.should be_success
79 + end
80 +
81 + it "should render show template" do
82 + do_get
83 + response.should render_template('show')
84 + end
85 +
86 + it "should find the <%= file_name %> requested" do
87 + <%= class_name %>.should_receive(:find).with("1").and_return(@<%= file_name %>)
88 + do_get
89 + end
90 +
91 + it "should assign the found <%= file_name %> for the view" do
92 + do_get
93 + assigns[:<%= file_name %>].should equal(@<%= file_name %>)
94 + end
95 + end
96 +
97 + describe "handling GET /<%= table_name %>/1.xml" do
98 +
99 + before(:each) do
100 + @<%= file_name %> = mock_model(<%= class_name %>, :to_xml => "XML")
101 + <%= class_name %>.stub!(:find).and_return(@<%= file_name %>)
102 + end
103 +
104 + def do_get
105 + @request.env["HTTP_ACCEPT"] = "application/xml"
106 + get :show, :id => "1"
107 + end
108 +
109 + it "should be successful" do
110 + do_get
111 + response.should be_success
112 + end
113 +
114 + it "should find the <%= file_name %> requested" do
115 + <%= class_name %>.should_receive(:find).with("1").and_return(@<%= file_name %>)
116 + do_get
117 + end
118 +
119 + it "should render the found <%= file_name %> as xml" do
120 + @<%= file_name %>.should_receive(:to_xml).and_return("XML")
121 + do_get
122 + response.body.should == "XML"
123 + end
124 + end
125 +
126 + describe "handling GET /<%= table_name %>/new" do
127 +
128 + before(:each) do
129 + @<%= file_name %> = mock_model(<%= class_name %>)
130 + <%= class_name %>.stub!(:new).and_return(@<%= file_name %>)
131 + end
132 +
133 + def do_get
134 + get :new
135 + end
136 +
137 + it "should be successful" do
138 + do_get
139 + response.should be_success
140 + end
141 +
142 + it "should render new template" do
143 + do_get
144 + response.should render_template('new')
145 + end
146 +
147 + it "should create an new <%= file_name %>" do
148 + <%= class_name %>.should_receive(:new).and_return(@<%= file_name %>)
149 + do_get
150 + end
151 +
152 + it "should not save the new <%= file_name %>" do
153 + @<%= file_name %>.should_not_receive(:save)
154 + do_get
155 + end
156 +
157 + it "should assign the new <%= file_name %> for the view" do
158 + do_get
159 + assigns[:<%= file_name %>].should equal(@<%= file_name %>)
160 + end
161 + end
162 +
163 + describe "handling GET /<%= table_name %>/1/edit" do
164 +
165 + before(:each) do
166 + @<%= file_name %> = mock_model(<%= class_name %>)
167 + <%= class_name %>.stub!(:find).and_return(@<%= file_name %>)
168 + end
169 +
170 + def do_get
171 + get :edit, :id => "1"
172 + end
173 +
174 + it "should be successful" do
175 + do_get
176 + response.should be_success
177 + end
178 +
179 + it "should render edit template" do
180 + do_get
181 + response.should render_template('edit')
182 + end
183 +
184 + it "should find the <%= file_name %> requested" do
185 + <%= class_name %>.should_receive(:find).and_return(@<%= file_name %>)
186 + do_get
187 + end
188 +
189 + it "should assign the found <%= class_name %> for the view" do
190 + do_get
191 + assigns[:<%= file_name %>].should equal(@<%= file_name %>)
192 + end
193 + end
194 +
195 + describe "handling POST /<%= table_name %>" do
196 +
197 + before(:each) do
198 + @<%= file_name %> = mock_model(<%= class_name %>, :to_param => "1")
199 + <%= class_name %>.stub!(:new).and_return(@<%= file_name %>)
200 + end
201 +
202 + describe "with successful save" do
203 +
204 + def do_post
205 + @<%= file_name %>.should_receive(:save).and_return(true)
206 + post :create, :<%= file_name %> => {}
207 + end
208 +
209 + it "should create a new <%= file_name %>" do
210 + <%= class_name %>.should_receive(:new).with({}).and_return(@<%= file_name %>)
211 + do_post
212 + end
213 +
214 + it "should redirect to the new <%= file_name %>" do
215 + do_post
216 + response.should redirect_to(<%= table_name.singularize %>_url("1"))
217 + end
218 +
219 + end
220 +
221 + describe "with failed save" do
222 +
223 + def do_post
224 + @<%= file_name %>.should_receive(:save).and_return(false)
225 + post :create, :<%= file_name %> => {}
226 + end
227 +
228 + it "should re-render 'new'" do
229 + do_post
230 + response.should render_template('new')
231 + end
232 +
233 + end
234 + end
235 +
236 + describe "handling PUT /<%= table_name %>/1" do
237 +
238 + before(:each) do
239 + @<%= file_name %> = mock_model(<%= class_name %>, :to_param => "1")
240 + <%= class_name %>.stub!(:find).and_return(@<%= file_name %>)
241 + end
242 +
243 + describe "with successful update" do
244 +
245 + def do_put
246 + @<%= file_name %>.should_receive(:update_attributes).and_return(true)
247 + put :update, :id => "1"
248 + end
249 +
250 + it "should find the <%= file_name %> requested" do
251 + <%= class_name %>.should_receive(:find).with("1").and_return(@<%= file_name %>)
252 + do_put
253 + end
254 +
255 + it "should update the found <%= file_name %>" do
256 + do_put
257 + assigns(:<%= file_name %>).should equal(@<%= file_name %>)
258 + end
259 +
260 + it "should assign the found <%= file_name %> for the view" do
261 + do_put
262 + assigns(:<%= file_name %>).should equal(@<%= file_name %>)
263 + end
264 +
265 + it "should redirect to the <%= file_name %>" do
266 + do_put
267 + response.should redirect_to(<%= table_name.singularize %>_url("1"))
268 + end
269 +
270 + end
271 +
272 + describe "with failed update" do
273 +
274 + def do_put
275 + @<%= file_name %>.should_receive(:update_attributes).and_return(false)
276 + put :update, :id => "1"
277 + end
278 +
279 + it "should re-render 'edit'" do
280 + do_put
281 + response.should render_template('edit')
282 + end
283 +
284 + end
285 + end
286 +
287 + describe "handling DELETE /<%= table_name %>/1" do
288 +
289 + before(:each) do
290 + @<%= file_name %> = mock_model(<%= class_name %>, :destroy => true)
291 + <%= class_name %>.stub!(:find).and_return(@<%= file_name %>)
292 + end
293 +
294 + def do_delete
295 + delete :destroy, :id => "1"
296 + end
297 +
298 + it "should find the <%= file_name %> requested" do
299 + <%= class_name %>.should_receive(:find).with("1").and_return(@<%= file_name %>)
300 + do_delete
301 + end
302 +
303 + it "should call destroy on the found <%= file_name %>" do
304 + @<%= file_name %>.should_receive(:destroy)
305 + do_delete
306 + end
307 +
308 + it "should redirect to the <%= table_name %> list" do
309 + do_delete
310 + response.should redirect_to(<%= table_name %>_url)
311 + end
312 + end
313 + end No newline at end of file
@@ -0,0 +1,25
1 + require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../../spec_helper'
2 +
3 + describe "/<%= table_name %>/edit.<%= default_file_extension %>" do
4 + include <%= controller_class_name %>Helper
5 +
6 + before do
7 + @<%= file_name %> = mock_model(<%= class_name %>)
8 + <% for attribute in attributes -%>
9 + @<%= file_name %>.stub!(:<%= attribute.name %>).and_return(<%= attribute.default_value %>)
10 + <% end -%>
11 + assigns[:<%= file_name %>] = @<%= file_name %>
12 + end
13 +
14 + it "should render edit form" do
15 + render "/<%= table_name %>/edit.<%= default_file_extension %>"
16 +
17 + response.should have_tag("form[action=#{<%= file_name %>_path(@<%= file_name %>)}][method=post]") do
18 + <% for attribute in attributes -%><% unless attribute.name =~ /_id/ || [:datetime, :timestamp, :time, :date].index(attribute.type) -%>
19 + with_tag('<%= attribute.input_type -%>#<%= file_name %>_<%= attribute.name %>[name=?]', "<%= file_name %>[<%= attribute.name %>]")
20 + <% end -%><% end -%>
21 + end
22 + end
23 + end
24 +
25 +
@@ -0,0 +1,11
1 + require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../spec_helper'
2 +
3 + describe <%= controller_class_name %>Helper do
4 +
5 + #Delete this example and add some real ones or delete this file
6 + it "should include the <%= class_name %>Helper" do
7 + included_modules = self.metaclass.send :included_modules
8 + included_modules.should include(<%= controller_class_name %>Helper)
9 + end
10 +
11 + end
@@ -0,0 +1,22
1 + require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../../spec_helper'
2 +
3 + describe "/<%= table_name %>/index.<%= default_file_extension %>" do
4 + include <%= controller_class_name %>Helper
5 +
6 + before(:each) do
7 + <% [98,99].each do |id| -%>
8 + <%= file_name %>_<%= id %> = mock_model(<%= class_name %>)
9 + <% for attribute in attributes -%>
10 + <%= file_name %>_<%= id %>.should_receive(:<%= attribute.name %>).and_return(<%= attribute.default_value %>)
11 + <% end -%><% end %>
12 + assigns[:<%= table_name %>] = [<%= file_name %>_98, <%= file_name %>_99]
13 + end
14 +
15 + it "should render list of <%= table_name %>" do
16 + render "/<%= table_name %>/index.<%= default_file_extension %>"
17 + <% for attribute in attributes -%><% unless attribute.name =~ /_id/ || [:datetime, :timestamp, :time, :date].index(attribute.type) -%>
18 + response.should have_tag("tr>td", <%= attribute.default_value %>, 2)
19 + <% end -%><% end -%>
20 + end
21 + end
22 +
@@ -0,0 +1,26
1 + require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../../spec_helper'
2 +
3 + describe "/<%= table_name %>/new.<%= default_file_extension %>" do
4 + include <%= controller_class_name %>Helper
5 +
6 + before(:each) do
7 + @<%= file_name %> = mock_model(<%= class_name %>)
8 + @<%= file_name %>.stub!(:new_record?).and_return(true)
9 + <% for attribute in attributes -%>
10 + @<%= file_name %>.stub!(:<%= attribute.name %>).and_return(<%= attribute.default_value %>)
11 + <% end -%>
12 + assigns[:<%= file_name %>] = @<%= file_name %>
13 + end
14 +
15 + it "should render new form" do
16 + render "/<%= table_name %>/new.<%= default_file_extension %>"
17 +
18 + response.should have_tag("form[action=?][method=post]", <%= table_name %>_path) do
19 + <% for attribute in attributes -%><% unless attribute.name =~ /_id/ || [:datetime, :timestamp, :time, :date].index(attribute.type) -%>
20 + with_tag("<%= attribute.input_type -%>#<%= file_name %>_<%= attribute.name %>[name=?]", "<%= file_name %>[<%= attribute.name %>]")
21 + <% end -%><% end -%>
22 + end
23 + end
24 + end
25 +
26 +
@@ -0,0 +1,61
1 + require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../spec_helper'
2 +
3 + describe <%= controller_class_name %>Controller do
4 + describe "route generation" do
5 +
6 + it "should map { :controller => '<%= table_name %>', :action => 'index' } to /<%= table_name %>" do
7 + route_for(:controller => "<%= table_name %>", :action => "index").should == "/<%= table_name %>"
8 + end
9 +
10 + it "should map { :controller => '<%= table_name %>', :action => 'new' } to /<%= table_name %>/new" do
11 + route_for(:controller => "<%= table_name %>", :action => "new").should == "/<%= table_name %>/new"
12 + end
13 +
14 + it "should map { :controller => '<%= table_name %>', :action => 'show', :id => 1 } to /<%= table_name %>/1" do
15 + route_for(:controller => "<%= table_name %>", :action => "show", :id => 1).should == "/<%= table_name %>/1"
16 + end
17 +
18 + it "should map { :controller => '<%= table_name %>', :action => 'edit', :id => 1 } to /<%= table_name %>/1<%= resource_edit_path %>" do
19 + route_for(:controller => "<%= table_name %>", :action => "edit", :id => 1).should == "/<%= table_name %>/1<%= resource_edit_path %>"
20 + end
21 +
22 + it "should map { :controller => '<%= table_name %>', :action => 'update', :id => 1} to /<%= table_name %>/1" do
23 + route_for(:controller => "<%= table_name %>", :action => "update", :id => 1).should == "/<%= table_name %>/1"
24 + end
25 +
26 + it "should map { :controller => '<%= table_name %>', :action => 'destroy', :id => 1} to /<%= table_name %>/1" do
27 + route_for(:controller => "<%= table_name %>", :action => "destroy", :id => 1).should == "/<%= table_name %>/1"
28 + end
29 + end
30 +
31 + describe "route recognition" do
32 +
33 + it "should generate params { :controller => '<%= table_name %>', action => 'index' } from GET /<%= table_name %>" do
34 + params_from(:get, "/<%= table_name %>").should == {:controller => "<%= table_name %>", :action => "index"}
35 + end
36 +
37 + it "should generate params { :controller => '<%= table_name %>', action => 'new' } from GET /<%= table_name %>/new" do
38 + params_from(:get, "/<%= table_name %>/new").should == {:controller => "<%= table_name %>", :action => "new"}
39 + end
40 +
41 + it "should generate params { :controller => '<%= table_name %>', action => 'create' } from POST /<%= table_name %>" do
42 + params_from(:post, "/<%= table_name %>").should == {:controller => "<%= table_name %>", :action => "create"}
43 + end
44 +
45 + it "should generate params { :controller => '<%= table_name %>', action => 'show', id => '1' } from GET /<%= table_name %>/1" do
46 + params_from(:get, "/<%= table_name %>/1").should == {:controller => "<%= table_name %>", :action => "show", :id => "1"}
47 + end
48 +
49 + it "should generate params { :controller => '<%= table_name %>', action => 'edit', id => '1' } from GET /<%= table_name %>/1;edit" do
50 + params_from(:get, "/<%= table_name %>/1<%= resource_edit_path %>").should == {:controller => "<%= table_name %>", :action => "edit", :id => "1"}
51 + end
52 +
53 + it "should generate params { :controller => '<%= table_name %>', action => 'update', id => '1' } from PUT /<%= table_name %>/1" do
54 + params_from(:put, "/<%= table_name %>/1").should == {:controller => "<%= table_name %>", :action => "update", :id => "1"}
55 + end
56 +
57 + it "should generate params { :controller => '<%= table_name %>', action => 'destroy', id => '1' } from DELETE /<%= table_name %>/1" do
58 + params_from(:delete, "/<%= table_name %>/1").should == {:controller => "<%= table_name %>", :action => "destroy", :id => "1"}
59 + end
60 + end
61 + end No newline at end of file
@@ -0,0 +1,22
1 + require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../../spec_helper'
2 +
3 + describe "/<%= table_name %>/show.<%= default_file_extension %>" do
4 + include <%= controller_class_name %>Helper
5 +
6 + before(:each) do
7 + @<%= file_name %> = mock_model(<%= class_name %>)
8 + <% for attribute in attributes -%>
9 + @<%= file_name %>.stub!(:<%= attribute.name %>).and_return(<%= attribute.default_value %>)
10 + <% end -%>
11 +
12 + assigns[:<%= file_name %>] = @<%= file_name %>
13 + end
14 +
15 + it "should render attributes in <p>" do
16 + render "/<%= table_name %>/show.<%= default_file_extension %>"
17 + <% for attribute in attributes -%><% unless attribute.name =~ /_id/ || [:datetime, :timestamp, :time, :date].index(attribute.type) -%>
18 + response.should have_text(/<%= Regexp.escape(attribute.default_value)[1..-2]%>/)
19 + <% end -%><% end -%>
20 + end
21 + end
22 +
@@ -0,0 +1,9
1 + # Placeholder to satisfy Rails.
2 + #
3 + # Do NOT add any require statements to this file. Doing
4 + # so will cause Rails to load this plugin all of the time.
5 + #
6 + # Running 'ruby script/generate rspec' will
7 + # generate spec/spec_helper.rb, which includes the necessary
8 + # require statements and configuration. This file should
9 + # be required by all of your spec files. No newline at end of file
@@ -0,0 +1,1
1 + # This needs to be here for >= ZenTest-3.9.0 to add this directory to the load path. No newline at end of file
@@ -0,0 +1,81
1 + # (c) Copyright 2006 Nick Sieger <nicksieger@gmail.com>
2 + #
3 + # Permission is hereby granted, free of charge, to any person
4 + # obtaining a copy of this software and associated documentation files
5 + # (the "Software"), to deal in the Software without restriction,
6 + # including without limitation the rights to use, copy, modify, merge,
7 + # publish, distribute, sublicense, and/or sell copies of the Software,
8 + # and to permit persons to whom the Software is furnished to do so,
9 + # subject to 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
18 + # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 + # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 + # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 + # SOFTWARE.
22 +
23 + $:.push(*Dir["vendor/rails/*/lib"])
24 +
25 + require 'active_support'
26 + require 'autotest/rspec'
27 +
28 + Autotest.add_hook :initialize do |at|
29 + %w{^config/ ^coverage/ ^db/ ^doc/ ^log/ ^public/ ^script ^vendor/rails ^vendor/plugins previous_failures.txt}.each do |exception|
30 + at.add_exception(exception)
31 + end
32 +
33 + at.clear_mappings
34 +
35 + at.add_mapping(%r%^(test|spec)/fixtures/(.*).yml$%) { |_, m|
36 + ["spec/models/#{m[2].singularize}_spec.rb"] + at.files_matching(%r%^spec\/views\/#{m[2]}/.*_spec\.rb$%)
37 + }
38 + at.add_mapping(%r%^spec/(models|controllers|views|helpers|lib)/.*rb$%) { |filename, _|
39 + filename
40 + }
41 + at.add_mapping(%r%^app/models/(.*)\.rb$%) { |_, m|
42 + ["spec/models/#{m[1]}_spec.rb"]
43 + }
44 + at.add_mapping(%r%^app/views/(.*)$%) { |_, m|
45 + at.files_matching %r%^spec/views/#{m[1]}_spec.rb$%
46 + }
47 + at.add_mapping(%r%^app/controllers/(.*)\.rb$%) { |_, m|
48 + if m[1] == "application"
49 + at.files_matching %r%^spec/controllers/.*_spec\.rb$%
50 + else
51 + ["spec/controllers/#{m[1]}_spec.rb"]
52 + end
53 + }
54 + at.add_mapping(%r%^app/helpers/(.*)_helper\.rb$%) { |_, m|
55 + if m[1] == "application" then
56 + at.files_matching(%r%^spec/(views|helpers)/.*_spec\.rb$%)
57 + else
58 + ["spec/helpers/#{m[1]}_helper_spec.rb"] + at.files_matching(%r%^spec\/views\/#{m[1]}/.*_spec\.rb$%)
59 + end
60 + }
61 + at.add_mapping(%r%^config/routes\.rb$%) {
62 + at.files_matching %r%^spec/(controllers|views|helpers)/.*_spec\.rb$%
63 + }
64 + at.add_mapping(%r%^config/database\.yml$%) { |_, m|
65 + at.files_matching %r%^spec/models/.*_spec\.rb$%
66 + }
67 + at.add_mapping(%r%^(spec/(spec_helper|shared/.*)|config/(boot|environment(s/test)?))\.rb$%) {
68 + at.files_matching %r%^spec/(models|controllers|views|helpers)/.*_spec\.rb$%
69 + }
70 + at.add_mapping(%r%^lib/(.*)\.rb$%) { |_, m|
71 + ["spec/lib/#{m[1]}_spec.rb"]
72 + }
73 + end
74 +
75 + class Autotest::RailsRspec < Autotest::Rspec
76 +
77 + def spec_command
78 + "script/spec"
79 + end
80 +
81 + end
@@ -0,0 +1,51
1 + silence_warnings { RAILS_ENV = "test" }
2 +
3 + require 'application'
4 + require 'action_controller/test_process'
5 + require 'action_controller/integration'
6 + require 'active_record/fixtures' if defined?(ActiveRecord::Base)
7 + require 'test/unit'
8 +
9 + require 'spec'
10 +
11 + require 'spec/rails/extensions'
12 + require 'spec/rails/example'
13 + require 'spec/rails/version'
14 + require 'spec/rails/matchers'
15 +
16 + module Spec
17 + # = Spec::Rails
18 + #
19 + # Spec::Rails (a.k.a. RSpec on Rails) is a Ruby on Rails plugin that allows you to drive the development
20 + # of your RoR application using RSpec, a framework that aims to enable Example Driven Development
21 + # in Ruby.
22 + #
23 + # == Features
24 + #
25 + # * Use RSpec to independently specify Rails Models, Views, Controllers and Helpers
26 + # * Integrated fixture loading
27 + # * Special generators for Resources, Models, Views and Controllers that generate Specs instead of Tests.
28 + #
29 + # == Vision
30 + #
31 + # For people for whom TDD is a brand new concept, the testing support built into Ruby on Rails
32 + # is a huge leap forward. The fact that it is built right in is fantastic, and Ruby on Rails
33 + # apps are generally much easier to maintain than they might have been without such support.
34 + #
35 + # For those of us coming from a history with TDD, and now BDD, the existing support presents some problems related to dependencies across specs. To that end, RSpec on Rails supports 4 types of specs. We’ve also built in first class mocking and stubbing support in order to break dependencies across these different concerns.
36 + #
37 + # == More Information
38 + #
39 + # See Spec::Rails::Runner for information about the different kinds of contexts
40 + # you can use to spec the different Rails components
41 + #
42 + # See Spec::Rails::Expectations for information about Rails-specific expectations
43 + # you can set on responses and models, etc.
44 + #
45 + # == License
46 + #
47 + # RSpec on Rails is licensed under the same license as RSpec itself,
48 + # the MIT-LICENSE.
49 + module Rails
50 + end
51 + end
@@ -0,0 +1,47
1 + dir = File.dirname(__FILE__)
2 +
3 + require 'spec/rails/example/ivar_proxy'
4 + require 'spec/rails/example/assigns_hash_proxy'
5 +
6 + require "spec/rails/example/render_observer"
7 + require "spec/rails/example/rails_example_group"
8 + require "spec/rails/example/model_example_group"
9 + require "spec/rails/example/functional_example_group"
10 + require "spec/rails/example/controller_example_group"
11 + require "spec/rails/example/helper_example_group"
12 + require "spec/rails/example/view_example_group"
13 +
14 + module Spec
15 + module Rails
16 + # Spec::Rails::Example extends Spec::Example (RSpec's core Example module) to provide
17 + # Rails-specific contexts for describing Rails Models, Views, Controllers and Helpers.
18 + #
19 + # == Model Examples
20 + #
21 + # These are the equivalent of unit tests in Rails' built in testing. Ironically (for the traditional TDD'er) these are the only specs that we feel should actually interact with the database.
22 + #
23 + # See Spec::Rails::Example::ModelExampleGroup
24 + #
25 + # == Controller Examples
26 + #
27 + # These align somewhat with functional tests in rails, except that they do not actually render views (though you can force rendering of views if you prefer). Instead of setting expectations about what goes on a page, you set expectations about what templates get rendered.
28 + #
29 + # See Spec::Rails::Example::ControllerExampleGroup
30 + #
31 + # == View Examples
32 + #
33 + # This is the other half of Rails functional testing. View specs allow you to set up assigns and render
34 + # a template. By assigning mock model data, you can specify view behaviour with no dependency on a database
35 + # or your real models.
36 + #
37 + # See Spec::Rails::Example::ViewExampleGroup
38 + #
39 + # == Helper Examples
40 + #
41 + # These let you specify directly methods that live in your helpers.
42 + #
43 + # See Spec::Rails::Example::HelperExampleGroup
44 + module Example
45 + end
46 + end
47 + end
@@ -0,0 +1,42
1 + module Spec
2 + module Rails
3 + module Example
4 + class AssignsHashProxy #:nodoc:
5 + def initialize(object)
6 + @object = object
7 + end
8 +
9 + def [](ivar)
10 + if assigns.include?(ivar.to_s)
11 + assigns[ivar.to_s]
12 + elsif assigns.include?(ivar)
13 + assigns[ivar]
14 + else
15 + nil
16 + end
17 + end
18 +
19 + def []=(ivar, val)
20 + assigns[ivar.to_s] = val
21 + end
22 +
23 + def delete(name)
24 + assigns.delete(name.to_s)
25 + end
26 +
27 + def each(&block)
28 + assigns.each &block
29 + end
30 +
31 + def has_key?(key)
32 + assigns.key?(key.to_s)
33 + end
34 +
35 + protected
36 + def assigns
37 + @object.assigns
38 + end
39 + end
40 + end
41 + end
42 + end
@@ -0,0 +1,255
1 + module Spec
2 + module Rails
3 + module Example
4 + # Controller Examples live in $RAILS_ROOT/spec/controllers/.
5 + #
6 + # Controller Examples use Spec::Rails::Example::ControllerExampleGroup, which supports running specs for
7 + # Controllers in two modes, which represent the tension between the more granular
8 + # testing common in TDD and the more high level testing built into
9 + # rails. BDD sits somewhere in between: we want to a balance between
10 + # specs that are close enough to the code to enable quick fault
11 + # isolation and far enough away from the code to enable refactoring
12 + # with minimal changes to the existing specs.
13 + #
14 + # == Isolation mode (default)
15 + #
16 + # No dependencies on views because none are ever rendered. The
17 + # benefit of this mode is that can spec the controller completely
18 + # independent of the view, allowing that responsibility to be
19 + # handled later, or by somebody else. Combined w/ separate view
20 + # specs, this also provides better fault isolation.
21 + #
22 + # == Integration mode
23 + #
24 + # To run in this mode, include the +integrate_views+ declaration
25 + # in your controller context:
26 + #
27 + # describe ThingController do
28 + # integrate_views
29 + # ...
30 + #
31 + # In this mode, controller specs are run in the same way that
32 + # rails functional tests run - one set of tests for both the
33 + # controllers and the views. The benefit of this approach is that
34 + # you get wider coverage from each spec. Experienced rails
35 + # developers may find this an easier approach to begin with, however
36 + # we encourage you to explore using the isolation mode and revel
37 + # in its benefits.
38 + #
39 + # == Expecting Errors
40 + #
41 + # Rspec on Rails will raise errors that occur in controller actions.
42 + # In contrast, Rails will swallow errors that are raised in controller
43 + # actions and return an error code in the header. If you wish to override
44 + # Rspec and have Rail's default behaviour,tell the controller to use
45 + # rails error handling ...
46 + #
47 + # before(:each) do
48 + # controller.use_rails_error_handling!
49 + # end
50 + #
51 + # When using Rail's error handling, you can expect error codes in headers ...
52 + #
53 + # it "should return an error in the header" do
54 + # response.should be_error
55 + # end
56 + #
57 + # it "should return a 501" do
58 + # response.response_code.should == 501
59 + # end
60 + #
61 + # it "should return a 501" do
62 + # response.code.should == "501"
63 + # end
64 + class ControllerExampleGroup < FunctionalExampleGroup
65 + class << self
66 +
67 + # Use this to instruct RSpec to render views in your controller examples (Integration Mode).
68 + #
69 + # describe ThingController do
70 + # integrate_views
71 + # ...
72 + #
73 + # See Spec::Rails::Example::ControllerExampleGroup for more information about
74 + # Integration and Isolation modes.
75 + def integrate_views
76 + @integrate_views = true
77 + end
78 + def integrate_views? # :nodoc:
79 + @integrate_views
80 + end
81 +
82 + # You MUST provide a controller_name within the context of
83 + # your controller specs:
84 + #
85 + # describe "ThingController" do
86 + # controller_name :thing
87 + # ...
88 + def controller_name(name)
89 + @controller_class_name = "#{name}_controller".camelize
90 + end
91 + attr_accessor :controller_class_name # :nodoc:
92 + end
93 +
94 + before(:each) do
95 + # Some Rails apps explicitly disable ActionMailer in environment.rb
96 + if defined?(ActionMailer)
97 + @deliveries = []
98 + ActionMailer::Base.deliveries = @deliveries
99 + end
100 +
101 + unless @controller.class.ancestors.include?(ActionController::Base)
102 + Spec::Expectations.fail_with <<-EOE
103 + You have to declare the controller name in controller specs. For example:
104 + describe "The ExampleController" do
105 + controller_name "example" #invokes the ExampleController
106 + end
107 + EOE
108 + end
109 + @controller.metaclass.class_eval do
110 + def controller_path #:nodoc:
111 + self.class.name.underscore.gsub('_controller', '')
112 + end
113 + include ControllerInstanceMethods
114 + end
115 + @controller.integrate_views! if @integrate_views
116 + @controller.session = session
117 + end
118 +
119 + attr_reader :response, :request, :controller
120 +
121 + def initialize(defined_description, &implementation) #:nodoc:
122 + super
123 + controller_class_name = self.class.controller_class_name
124 + if controller_class_name
125 + @controller_class_name = controller_class_name.to_s
126 + else
127 + @controller_class_name = self.class.described_type.to_s
128 + end
129 + @integrate_views = self.class.integrate_views?
130 + end
131 +
132 + # Uses ActionController::Routing::Routes to generate
133 + # the correct route for a given set of options.
134 + # == Example
135 + # route_for(:controller => 'registrations', :action => 'edit', :id => 1)
136 + # => '/registrations/1;edit'
137 + def route_for(options)
138 + ensure_that_routes_are_loaded
139 + ActionController::Routing::Routes.generate(options)
140 + end
141 +
142 + # Uses ActionController::Routing::Routes to parse
143 + # an incoming path so the parameters it generates can be checked
144 + # == Example
145 + # params_from(:get, '/registrations/1;edit')
146 + # => :controller => 'registrations', :action => 'edit', :id => 1
147 + def params_from(method, path)
148 + ensure_that_routes_are_loaded
149 + ActionController::Routing::Routes.recognize_path(path, :method => method)
150 + end
151 +
152 + protected
153 + def _controller_ivar_proxy
154 + @controller_ivar_proxy ||= AssignsHashProxy.new @controller
155 + end
156 +
157 + private
158 + def ensure_that_routes_are_loaded
159 + ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty?
160 + end
161 +
162 + module ControllerInstanceMethods #:nodoc:
163 + include Spec::Rails::Example::RenderObserver
164 +
165 + # === render(options = nil, deprecated_status = nil, &block)
166 + #
167 + # This gets added to the controller's singleton meta class,
168 + # allowing Controller Examples to run in two modes, freely switching
169 + # from context to context.
170 + def render(options=nil, deprecated_status=nil, &block)
171 + unless block_given?
172 + unless integrate_views?
173 + @template.metaclass.class_eval do
174 + define_method :file_exists? do
175 + true
176 + end
177 + define_method :render_file do |*args|
178 + @first_render ||= args[0]
179 + end
180 + end
181 + end
182 + end
183 +
184 + if matching_message_expectation_exists(options)
185 + expect_render_mock_proxy.render(options, &block)
186 + @performed_render = true
187 + else
188 + unless matching_stub_exists(options)
189 + super(options, deprecated_status, &block)
190 + end
191 + end
192 + end
193 +
194 + private
195 + def matching_message_expectation_exists(options)
196 + expect_render_mock_proxy.send(:__mock_proxy).send(:find_matching_expectation, :render, options)
197 + end
198 +
199 + def matching_stub_exists(options)
200 + expect_render_mock_proxy.send(:__mock_proxy).send(:find_matching_method_stub, :render, options)
201 + end
202 +
203 + public
204 + if self.respond_to?(:should_receive) && self.respond_to?(:stub!)
205 + self.send :alias_method, :orig_should_receive, :should_receive
206 + self.send :alias_method, :orig_stub!, :stub!
207 + def raise_with_disable_message(old_method, new_method)
208 + raise %Q|
209 + controller.#{old_method}(:render) has been disabled because it
210 + can often produce unexpected results. Instead, you should
211 + use the following (before the action):
212 +
213 + controller.#{new_method}(*args)
214 +
215 + See the rdoc for #{new_method} for more information.
216 + |
217 + end
218 + def should_receive(*args)
219 + if args[0] == :render
220 + raise_with_disable_message("should_receive", "expect_render")
221 + else
222 + orig_should_receive(*args)
223 + end
224 + end
225 + def stub!(*args)
226 + if args[0] == :render
227 + raise_with_disable_message("stub!", "stub_render")
228 + else
229 + orig_stub!(*args)
230 + end
231 + end
232 + end
233 +
234 + def response(&block)
235 + # NOTE - we're setting @update for the assert_select_spec - kinda weird, huh?
236 + @update = block
237 + @_response || @response
238 + end
239 +
240 + def integrate_views!
241 + @integrate_views = true
242 + end
243 +
244 + private
245 +
246 + def integrate_views?
247 + @integrate_views
248 + end
249 + end
250 +
251 + Spec::Example::ExampleGroupFactory.register(:controller, self)
252 + end
253 + end
254 + end
255 + end
@@ -0,0 +1,66
1 + module Spec
2 + module Rails
3 + module Example
4 + class FunctionalExampleGroup < RailsExampleGroup
5 + include ActionController::TestProcess
6 + include ActionController::Assertions
7 +
8 + attr_reader :request, :response
9 + before(:each) do
10 + @controller_class = Object.path2class @controller_class_name
11 + raise "Can't determine controller class for #{@controller_class_name}" if @controller_class.nil?
12 +
13 + @controller = @controller_class.new
14 +
15 + @request = ActionController::TestRequest.new
16 + @response = ActionController::TestResponse.new
17 + end
18 +
19 + def params
20 + request.parameters
21 + end
22 +
23 + def flash
24 + response.flash
25 + end
26 +
27 + def session
28 + request.session
29 + end
30 +
31 + # :call-seq:
32 + # assigns()
33 + #
34 + # Hash of instance variables to values that are made available to
35 + # views. == Examples
36 + #
37 + # #in thing_controller.rb
38 + # def new
39 + # @thing = Thing.new
40 + # end
41 + #
42 + # #in thing_controller_spec
43 + # get 'new'
44 + # assigns[:registration].should == Thing.new
45 + #--
46 + # NOTE - Even though docs only use assigns[:key] format, this supports
47 + # assigns(:key) in order to avoid breaking old specs.
48 + #++
49 + def assigns(key = nil)
50 + if key.nil?
51 + @controller.assigns
52 + _controller_ivar_proxy
53 + else
54 + @controller.assigns[key]
55 + _controller_ivar_proxy[key]
56 + end
57 + end
58 +
59 + protected
60 + def _controller_ivar_proxy
61 + @controller_ivar_proxy ||= IvarProxy.new @controller
62 + end
63 + end
64 + end
65 + end
66 + end
@@ -0,0 +1,82
1 + module Spec
2 + module Rails
3 + module Example
4 + # Helper Specs live in $RAILS_ROOT/spec/helpers/.
5 + #
6 + # Helper Specs use Spec::Rails::Example::HelperExampleGroup, which allows you to
7 + # include your Helper directly in the context and write specs directly
8 + # against its methods.
9 + #
10 + # HelperExampleGroup also includes the standard lot of ActionView::Helpers in case your
11 + # helpers rely on any of those.
12 + #
13 + # == Example
14 + #
15 + # class ThingHelper
16 + # def number_of_things
17 + # Thing.count
18 + # end
19 + # end
20 + #
21 + # describe "ThingHelper example_group" do
22 + # include ThingHelper
23 + # it "should tell you the number of things" do
24 + # Thing.should_receive(:count).and_return(37)
25 + # number_of_things.should == 37
26 + # end
27 + # end
28 + class HelperExampleGroup < FunctionalExampleGroup
29 + class << self
30 + # The helper name....
31 + def helper_name(name=nil)
32 + send :include, "#{name}_helper".camelize.constantize
33 + end
34 + end
35 +
36 + # Reverse the load order so that custom helpers which
37 + # are defined last are also loaded last.
38 + ActionView::Base.included_modules.reverse.each do |mod|
39 + include mod if mod.parents.include?(ActionView::Helpers)
40 + end
41 +
42 + before(:all) do
43 + @controller_class_name = 'Spec::Rails::Example::HelperBehaviourController'
44 + end
45 +
46 + before(:each) do
47 + @controller.request = @request
48 + @controller.url = ActionController::UrlRewriter.new @request, {} # url_for
49 +
50 + @flash = ActionController::Flash::FlashHash.new
51 + session['flash'] = @flash
52 +
53 + ActionView::Helpers::AssetTagHelper::reset_javascript_include_default
54 + end
55 +
56 + def flash
57 + @flash
58 + end
59 +
60 + def eval_erb(text)
61 + ERB.new(text).result(binding)
62 + end
63 +
64 +
65 + # TODO: BT - Helper Examples should proxy method_missing to a Rails View instance.
66 + # When that is done, remove this method
67 + def protect_against_forgery?
68 + false
69 + end
70 +
71 + Spec::Example::ExampleGroupFactory.register(:helper, self)
72 + end
73 +
74 + class HelperBehaviourController < ApplicationController #:nodoc:
75 + attr_accessor :request, :url
76 +
77 + # Re-raise errors
78 + def rescue_action(e); raise e; end
79 + end
80 + end
81 + end
82 + end
@@ -0,0 +1,62
1 + ##
2 + # A wrapper that allows instance variables to be manipulated using +[]+ and
3 + # +[]=+
4 +
5 + module Spec
6 + module Rails
7 + module Example
8 + class IvarProxy #:nodoc:
9 +
10 + ##
11 + # Wraps +object+ allowing its instance variables to be manipulated.
12 +
13 + def initialize(object)
14 + @object = object
15 + end
16 +
17 + ##
18 + # Retrieves +ivar+ from the wrapped object.
19 +
20 + def [](ivar)
21 + get_variable "@#{ivar}"
22 + end
23 +
24 + ##
25 + # Sets +ivar+ to +val+ on the wrapped object.
26 +
27 + def []=(ivar, val)
28 + set_variable "@#{ivar}", val
29 + end
30 +
31 + def each
32 + @object.instance_variables.each do |variable_full_name|
33 + variable_name = variable_full_name[1...variable_full_name.length]
34 + yield variable_name, get_variable(variable_full_name)
35 + end
36 + end
37 +
38 + def delete(key)
39 + var_name = "@#{key}"
40 + if @object.instance_variables.include?(var_name)
41 + @object.send(:remove_instance_variable, var_name)
42 + else
43 + return nil
44 + end
45 + end
46 +
47 + def has_key?(key)
48 + @object.instance_variables.include?("@#{key}")
49 + end
50 +
51 + protected
52 + def get_variable(name)
53 + @object.instance_variable_get name
54 + end
55 +
56 + def set_variable(name, value)
57 + @object.instance_variable_set name, value
58 + end
59 + end
60 + end
61 + end
62 + end
@@ -0,0 +1,14
1 + module Spec
2 + module Rails
3 + module Example
4 + # Model examples live in $RAILS_ROOT/spec/models/.
5 + #
6 + # Model examples use Spec::Rails::Example::ModelExampleGroup, which
7 + # provides support for fixtures and some custom expectations via extensions
8 + # to ActiveRecord::Base.
9 + class ModelExampleGroup < RailsExampleGroup
10 + Spec::Example::ExampleGroupFactory.register(:model, self)
11 + end
12 + end
13 + end
14 + end
@@ -0,0 +1,68
1 + require 'spec/interop/test'
2 +
3 + ActionView::Base.cache_template_extensions = false
4 +
5 + module Spec
6 + module Rails
7 + module Example
8 + class RailsExampleGroup < Test::Unit::TestCase
9 + # Rails >= r8570 uses setup/teardown_fixtures explicitly
10 + before(:each) do
11 + setup_fixtures if self.respond_to?(:setup_fixtures)
12 + end
13 + after(:each) do
14 + teardown_fixtures if self.respond_to?(:teardown_fixtures)
15 + end
16 +
17 + include Spec::Rails::Matchers
18 +
19 + @@model_id = 1000
20 + # Creates a mock object instance for a +model_class+ with common
21 + # methods stubbed out.
22 + # Additional methods may be easily stubbed (via add_stubs) if +stubs+ is passed.
23 + def mock_model(model_class, options_and_stubs = {})
24 + # null = options_and_stubs.delete(:null_object)
25 + # stubs = options_and_stubs
26 + id = @@model_id
27 + @@model_id += 1
28 + options_and_stubs = {
29 + :id => id,
30 + :to_param => id.to_s,
31 + :new_record? => false,
32 + :errors => stub("errors", :count => 0)
33 + }.merge(options_and_stubs)
34 + m = mock("#{model_class.name}_#{id}", options_and_stubs)
35 + m.send(:__mock_proxy).instance_eval <<-CODE
36 + def @target.is_a?(other)
37 + #{model_class}.ancestors.include?(other)
38 + end
39 + def @target.kind_of?(other)
40 + #{model_class}.ancestors.include?(other)
41 + end
42 + def @target.instance_of?(other)
43 + other == #{model_class}
44 + end
45 + def @target.class
46 + #{model_class}
47 + end
48 + CODE
49 + yield m if block_given?
50 + m
51 + end
52 +
53 + #--
54 + # TODO - Shouldn't this just be an extension of stub! ??
55 + # - object.stub!(:method => return_value, :method2 => return_value2, :etc => etc)
56 + #++
57 + # Stubs methods on +object+ (if +object+ is a symbol or string a new mock
58 + # with that name will be created). +stubs+ is a Hash of <tt>method=>value</tt>
59 + def add_stubs(object, stubs = {}) #:nodoc:
60 + m = [String, Symbol].index(object.class) ? mock(object.to_s) : object
61 + stubs.each {|k,v| m.stub!(k).and_return(v)}
62 + m
63 + end
64 + Spec::Example::ExampleGroupFactory.default(self)
65 + end
66 + end
67 + end
68 + end
@@ -0,0 +1,90
1 + require 'spec/mocks'
2 +
3 + module Spec
4 + module Rails
5 + module Example
6 + # Provides specialized mock-like behaviour for controller and view examples,
7 + # allowing you to mock or stub calls to render with specific arguments while
8 + # ignoring all other calls.
9 + module RenderObserver
10 +
11 + # Similar to mocking +render+ with the exception that calls to +render+ with
12 + # any other options are passed on to the receiver (i.e. controller in
13 + # controller examples, template in view examples).
14 + #
15 + # This is necessary because Rails uses the +render+ method on both
16 + # controllers and templates as a dispatcher to render different kinds of
17 + # things, sometimes resulting in many calls to the render method within one
18 + # request. This approach makes it impossible to use a normal mock object, which
19 + # is designed to observe all incoming messages with a given name.
20 + #
21 + # +expect_render+ is auto-verifying, so failures will be reported without
22 + # requiring you to explicitly request verification.
23 + #
24 + # Also, +expect_render+ uses parts of RSpec's mock expectation framework. Because
25 + # it wraps only a subset of the framework, using this will create no conflict with
26 + # other mock frameworks if you choose to use them. Additionally, the object returned
27 + # by expect_render is an RSpec mock object, which means that you can call any of the
28 + # chained methods available in RSpec's mocks.
29 + #
30 + # == Controller Examples
31 + #
32 + # controller.expect_render(:partial => 'thing', :object => thing)
33 + # controller.expect_render(:partial => 'thing', :collection => things).once
34 + #
35 + # controller.stub_render(:partial => 'thing', :object => thing)
36 + # controller.stub_render(:partial => 'thing', :collection => things).twice
37 + #
38 + # == View Examples
39 + #
40 + # template.expect_render(:partial => 'thing', :object => thing)
41 + # template.expect_render(:partial => 'thing', :collection => things)
42 + #
43 + # template.stub_render(:partial => 'thing', :object => thing)
44 + # template.stub_render(:partial => 'thing', :collection => things)
45 + #
46 + def expect_render(opts={})
47 + register_verify_after_each
48 + expect_render_mock_proxy.should_receive(:render, :expected_from => caller(1)[0]).with(opts)
49 + end
50 +
51 + # This is exactly like expect_render, with the exception that the call to render will not
52 + # be verified. Use this if you are trying to isolate your example from a complicated render
53 + # operation but don't care whether it is called or not.
54 + def stub_render(opts={})
55 + register_verify_after_each
56 + expect_render_mock_proxy.stub!(:render, :expected_from => caller(1)[0]).with(opts)
57 + end
58 +
59 + def verify_rendered # :nodoc:
60 + expect_render_mock_proxy.rspec_verify
61 + end
62 +
63 + def unregister_verify_after_each #:nodoc:
64 + proc = verify_rendered_proc
65 + Spec::Example::ExampleGroup.remove_after(:each, &proc)
66 + end
67 +
68 + protected
69 +
70 + def verify_rendered_proc #:nodoc:
71 + template = self
72 + @verify_rendered_proc ||= Proc.new do
73 + template.verify_rendered
74 + template.unregister_verify_after_each
75 + end
76 + end
77 +
78 + def register_verify_after_each #:nodoc:
79 + proc = verify_rendered_proc
80 + Spec::Example::ExampleGroup.after(:each, &proc)
81 + end
82 +
83 + def expect_render_mock_proxy #:nodoc:
84 + @expect_render_mock_proxy ||= Spec::Mocks::Mock.new("expect_render_mock_proxy")
85 + end
86 +
87 + end
88 + end
89 + end
90 + end
@@ -0,0 +1,171
1 + module Spec
2 + module Rails
3 + module Example
4 + # View Examples live in $RAILS_ROOT/spec/views/.
5 + #
6 + # View Specs use Spec::Rails::Example::ViewExampleGroup,
7 + # which provides access to views without invoking any of your controllers.
8 + # See Spec::Rails::Expectations::Matchers for information about specific
9 + # expectations that you can set on views.
10 + #
11 + # == Example
12 + #
13 + # describe "login/login" do
14 + # before do
15 + # render 'login/login'
16 + # end
17 + #
18 + # it "should display login form" do
19 + # response.should have_tag("form[action=/login]") do
20 + # with_tag("input[type=text][name=email]")
21 + # with_tag("input[type=password][name=password]")
22 + # with_tag("input[type=submit][value=Login]")
23 + # end
24 + # end
25 + # end
26 + class ViewExampleGroup < FunctionalExampleGroup
27 + before(:each) do
28 + ensure_that_flash_and_session_work_properly
29 + end
30 +
31 + after(:each) do
32 + ensure_that_base_view_path_is_not_set_across_example_groups
33 + end
34 +
35 + def initialize(defined_description, &implementation) #:nodoc:
36 + super
37 + @controller_class_name = "Spec::Rails::Example::ViewExampleGroupController"
38 + end
39 +
40 + def ensure_that_flash_and_session_work_properly #:nodoc:
41 + @controller.send :initialize_template_class, @response
42 + @controller.send :assign_shortcuts, @request, @response
43 + @session = @controller.session
44 + @controller.class.send :public, :flash
45 + end
46 +
47 + def ensure_that_base_view_path_is_not_set_across_example_groups #:nodoc:
48 + ActionView::Base.base_view_path = nil
49 + end
50 +
51 + def set_base_view_path(options) #:nodoc:
52 + ActionView::Base.base_view_path = base_view_path(options)
53 + end
54 +
55 + def base_view_path(options) #:nodoc:
56 + "/#{derived_controller_name(options)}/"
57 + end
58 +
59 + def derived_controller_name(options) #:nodoc:
60 + parts = subject_of_render(options).split('/').reject { |part| part.empty? }
61 + "#{parts[0..-2].join('/')}"
62 + end
63 +
64 + def derived_action_name(options) #:nodoc:
65 + parts = subject_of_render(options).split('/').reject { |part| part.empty? }
66 + "#{parts.last}"
67 + end
68 +
69 + def subject_of_render(options) #:nodoc:
70 + [:template, :partial, :file].each do |render_type|
71 + if options.has_key?(render_type)
72 + return options[render_type]
73 + end
74 + end
75 + raise Exception.new("Unhandled render type in view spec.")
76 + end
77 +
78 + def add_helpers(options) #:nodoc:
79 + @controller.add_helper("application")
80 + @controller.add_helper(derived_controller_name(options))
81 + @controller.add_helper(options[:helper]) if options[:helper]
82 + options[:helpers].each { |helper| @controller.add_helper(helper) } if options[:helpers]
83 + end
84 +
85 + # Renders a template for a View Spec, which then provides access to the result
86 + # through the +response+.
87 + #
88 + # == Examples
89 + #
90 + # render('/people/list')
91 + # render('/people/list', :helper => MyHelper)
92 + # render('/people/list', :helpers => [MyHelper, MyOtherHelper])
93 + # render(:partial => '/people/_address')
94 + #
95 + # See Spec::Rails::Example::ViewExampleGroup for more information.
96 + def render(*args)
97 + options = Hash === args.last ? args.pop : {}
98 + options[:template] = args.first.to_s unless args.empty?
99 +
100 + set_base_view_path(options)
101 + add_helpers(options)
102 +
103 + assigns[:action_name] = @action_name
104 +
105 + @request.path_parameters = {
106 + :controller => derived_controller_name(options),
107 + :action => derived_action_name(options)
108 + }
109 +
110 + defaults = { :layout => false }
111 + options = defaults.merge options
112 +
113 + @controller.instance_variable_set :@params, @request.parameters
114 +
115 + @controller.send :initialize_current_url
116 +
117 + @controller.class.instance_eval %{
118 + def controller_path
119 + "#{derived_controller_name(options)}"
120 + end
121 +
122 + def controller_name
123 + "#{derived_controller_name(options).split('/').last}"
124 + end
125 + }
126 +
127 + @controller.send :forget_variables_added_to_assigns
128 + @controller.send :render, options
129 + @controller.send :process_cleanup
130 + end
131 +
132 + # This provides the template. Use this to set mock
133 + # expectations for dealing with partials
134 + #
135 + # == Example
136 + #
137 + # describe "/person/new" do
138 + # it "should use the form partial" do
139 + # template.should_receive(:render).with(:partial => 'form')
140 + # render "/person/new"
141 + # end
142 + # end
143 + def template
144 + @controller.template
145 + end
146 +
147 + Spec::Example::ExampleGroupFactory.register(:view, self)
148 + end
149 +
150 + class ViewExampleGroupController < ApplicationController #:nodoc:
151 + include Spec::Rails::Example::RenderObserver
152 + attr_reader :template
153 +
154 + def add_helper_for(template_path)
155 + add_helper(template_path.split('/')[0])
156 + end
157 +
158 + def add_helper(name)
159 + begin
160 + helper_module = "#{name}_helper".camelize.constantize
161 + rescue
162 + return
163 + end
164 + template.metaclass.class_eval do
165 + include helper_module
166 + end
167 + end
168 + end
169 + end
170 + end
171 + end
@@ -0,0 +1,12
1 + require 'spec'
2 +
3 + require 'spec/rails/extensions/object'
4 +
5 + require 'spec/rails/extensions/spec/example/configuration'
6 + require 'spec/rails/extensions/spec/matchers/have'
7 +
8 + require 'spec/rails/extensions/active_record/base'
9 + require 'spec/rails/extensions/action_controller/base'
10 + require 'spec/rails/extensions/action_controller/rescue'
11 + require 'spec/rails/extensions/action_controller/test_response'
12 + require 'spec/rails/extensions/action_view/base'
@@ -0,0 +1,14
1 + module ActionController
2 + class Base
3 + class << self
4 + def set_view_path(path)
5 + [:append_view_path, :view_paths=, :template_root=].each do |method|
6 + if respond_to?(method)
7 + return send(method, path)
8 + end
9 + end
10 + end
11 + end
12 + end
13 + end
14 +
@@ -0,0 +1,21
1 + module ActionController
2 + module Rescue
3 + def use_rails_error_handling!
4 + @use_rails_error_handling = true
5 + end
6 +
7 + def use_rails_error_handling?
8 + @use_rails_error_handling ||= false
9 + end
10 +
11 + protected
12 + def rescue_action_with_fast_errors(exception)
13 + if use_rails_error_handling?
14 + rescue_action_without_fast_errors exception
15 + else
16 + raise exception
17 + end
18 + end
19 + alias_method_chain :rescue_action, :fast_errors
20 + end
21 + end
@@ -0,0 +1,11
1 + module ActionController #:nodoc:
2 + class TestResponse #:nodoc:
3 + attr_writer :controller_path
4 +
5 + def capture(name)
6 + template.instance_variable_get "@content_for_#{name.to_s}"
7 + end
8 + alias [] capture
9 +
10 + end
11 + end
@@ -0,0 +1,27
1 + module ActionView #:nodoc:
2 + class Base #:nodoc:
3 + include Spec::Rails::Example::RenderObserver
4 + cattr_accessor :base_view_path
5 + def render_partial(partial_path, local_assigns = nil, deprecated_local_assigns = nil) #:nodoc:
6 + if partial_path.is_a?(String)
7 + unless partial_path.include?("/")
8 + unless self.class.base_view_path.nil?
9 + partial_path = "#{self.class.base_view_path}/#{partial_path}"
10 + end
11 + end
12 + end
13 + super(partial_path, local_assigns, deprecated_local_assigns)
14 + end
15 +
16 + alias_method :orig_render, :render
17 + def render(options = {}, old_local_assigns = {}, &block)
18 + if expect_render_mock_proxy.send(:__mock_proxy).send(:find_matching_expectation, :render, options)
19 + expect_render_mock_proxy.render(options)
20 + else
21 + unless expect_render_mock_proxy.send(:__mock_proxy).send(:find_matching_method_stub, :render, options)
22 + orig_render(options, old_local_assigns, &block)
23 + end
24 + end
25 + end
26 + end
27 + end
@@ -0,0 +1,30
1 + if defined?(ActiveRecord::Base)
2 + module ActiveRecord #:nodoc:
3 + class Base
4 +
5 + (class << self; self; end).class_eval do
6 + # Extension for <tt>should have</tt> on AR Model classes
7 + #
8 + # ModelClass.should have(:no).records
9 + # ModelClass.should have(1).record
10 + # ModelClass.should have(n).records
11 + def records
12 + find(:all)
13 + end
14 + alias :record :records
15 + end
16 +
17 + # Extension for <tt>should have</tt> on AR Model instances
18 + #
19 + # model.should have(:no).errors_on(:attribute)
20 + # model.should have(1).error_on(:attribute)
21 + # model.should have(n).errors_on(:attribute)
22 + def errors_on(attribute)
23 + self.valid?
24 + [self.errors.on(attribute)].flatten.compact
25 + end
26 + alias :error_on :errors_on
27 +
28 + end
29 + end
30 + end No newline at end of file
@@ -0,0 +1,5
1 + class Object # :nodoc:
2 + def self.path2class(klassname)
3 + klassname.split('::').inject(Object) { |k,n| k.const_get n }
4 + end
5 + end
@@ -0,0 +1,66
1 + require 'spec/example/configuration'
2 +
3 + module Spec
4 + module Example
5 + class Configuration
6 + # Rails 1.2.3 does a copy of the @inheritable_attributes to the subclass when the subclass is
7 + # created. This causes an ordering issue when setting state on Configuration because the data is
8 + # already copied.
9 + # Iterating over EXAMPLE_GROUP_CLASSES causes the base ExampleGroup classes to have their
10 + # @inheritable_attributes updated.
11 + # TODO: BT - When we no longer support Rails 1.2.3, we can remove this functionality
12 + EXAMPLE_GROUP_CLASSES = [
13 + ::Test::Unit::TestCase,
14 + ::Spec::Rails::Example::RailsExampleGroup,
15 + ::Spec::Rails::Example::FunctionalExampleGroup,
16 + ::Spec::Rails::Example::ControllerExampleGroup,
17 + ::Spec::Rails::Example::ViewExampleGroup,
18 + ::Spec::Rails::Example::HelperExampleGroup,
19 + ::Spec::Rails::Example::ModelExampleGroup
20 + ]
21 + # All of this is ActiveRecord related and makes no sense if it's not used by the app
22 + if defined?(ActiveRecord::Base)
23 + def initialize
24 + super
25 + self.fixture_path = RAILS_ROOT + '/spec/fixtures'
26 + end
27 +
28 + def use_transactional_fixtures
29 + Test::Unit::TestCase.use_transactional_fixtures
30 + end
31 + def use_transactional_fixtures=(value)
32 + EXAMPLE_GROUP_CLASSES.each do |example_group|
33 + example_group.use_transactional_fixtures = value
34 + end
35 + end
36 +
37 + def use_instantiated_fixtures
38 + Test::Unit::TestCase.use_instantiated_fixtures
39 + end
40 + def use_instantiated_fixtures=(value)
41 + EXAMPLE_GROUP_CLASSES.each do |example_group|
42 + example_group.use_instantiated_fixtures = value
43 + end
44 + end
45 +
46 + def fixture_path
47 + Test::Unit::TestCase.fixture_path
48 + end
49 + def fixture_path=(path)
50 + EXAMPLE_GROUP_CLASSES.each do |example_group|
51 + example_group.fixture_path = path
52 + end
53 + end
54 +
55 + def global_fixtures
56 + ::Test::Unit::TestCase.fixture_table_names
57 + end
58 + def global_fixtures=(fixtures)
59 + EXAMPLE_GROUP_CLASSES.each do |example_group|
60 + example_group.fixtures(*fixtures)
61 + end
62 + end
63 + end
64 + end
65 + end
66 + end
@@ -0,0 +1,21
1 + require 'spec/matchers/have'
2 +
3 + module Spec #:nodoc:
4 + module Matchers #:nodoc:
5 + class Have #:nodoc:
6 + alias_method :__original_failure_message, :failure_message
7 + def failure_message
8 + return "expected #{relativities[@relativity]}#{@expected} errors on :#{@args[0]}, got #{@actual}" if @collection_name == :errors_on
9 + return "expected #{relativities[@relativity]}#{@expected} error on :#{@args[0]}, got #{@actual}" if @collection_name == :error_on
10 + return __original_failure_message
11 + end
12 +
13 + alias_method :__original_description, :description
14 + def description
15 + return "should have #{relativities[@relativity]}#{@expected} errors on :#{@args[0]}" if @collection_name == :errors_on
16 + return "should have #{relativities[@relativity]}#{@expected} error on :#{@args[0]}" if @collection_name == :error_on
17 + return __original_description
18 + end
19 + end
20 + end
21 + end
@@ -0,0 +1,29
1 + dir = File.dirname(__FILE__)
2 + require 'spec/rails/matchers/assert_select'
3 + require 'spec/rails/matchers/have_text'
4 + require 'spec/rails/matchers/redirect_to'
5 + require 'spec/rails/matchers/render_template'
6 +
7 + module Spec
8 + module Rails
9 + # Spec::Rails::Expectations::Matchers provides several expectation matchers
10 + # intended to work with Rails components like models and responses. For example:
11 + #
12 + # response.should redirect_to("some/url") #redirect_to(url) is the matcher.
13 + #
14 + # In addition to those you see below, the arbitrary predicate feature of RSpec
15 + # makes the following available as well:
16 + #
17 + # response.should be_success #passes if response.success?
18 + # response.should be_redirect #passes if response.redirect?
19 + #
20 + # Note that many of these matchers are part of a wrapper of <tt>assert_select</tt>, so
21 + # the documentation comes straight from that with some slight modifications.
22 + # <tt>assert_select</tt> is a Test::Unit extension originally contributed to the
23 + # Rails community as a plugin by Assaf Arkin and eventually shipped as part of Rails.
24 + #
25 + # For more info on <tt>assert_select</tt>, see the relevant Rails documentation.
26 + module Matchers
27 + end
28 + end
29 + end
@@ -0,0 +1,130
1 + # This is a wrapper of assert_select for rspec.
2 +
3 + module Spec # :nodoc:
4 + module Rails
5 + module Matchers
6 +
7 + class AssertSelect #:nodoc:
8 +
9 + def initialize(assertion, spec_scope, *args, &block)
10 + @assertion = assertion
11 + @spec_scope = spec_scope
12 + @args = args
13 + @block = block
14 + end
15 +
16 + def matches?(response_or_text, &block)
17 + if ActionController::TestResponse === response_or_text and
18 + response_or_text.headers.key?('Content-Type') and
19 + response_or_text.headers['Content-Type'].to_sym == :xml
20 + @args.unshift(HTML::Document.new(response_or_text.body, false, true).root)
21 + elsif String === response_or_text
22 + @args.unshift(HTML::Document.new(response_or_text).root)
23 + end
24 + @block = block if block
25 + begin
26 + @spec_scope.send(@assertion, *@args, &@block)
27 + rescue ::Test::Unit::AssertionFailedError => @error
28 + end
29 +
30 + @error.nil?
31 + end
32 +
33 + def failure_message; @error.message; end
34 + def negative_failure_message; "should not #{description}, but did"; end
35 +
36 + def description
37 + {
38 + :assert_select => "have tag#{format_args(*@args)}",
39 + :assert_select_email => "send email#{format_args(*@args)}",
40 + }[@assertion]
41 + end
42 +
43 + private
44 +
45 + def format_args(*args)
46 + return "" if args.empty?
47 + return "(#{arg_list(*args)})"
48 + end
49 +
50 + def arg_list(*args)
51 + args.collect do |arg|
52 + arg.respond_to?(:description) ? arg.description : arg.inspect
53 + end.join(", ")
54 + end
55 +
56 + end
57 +
58 + # :call-seq:
59 + # response.should have_tag(*args, &block)
60 + # string.should have_tag(*args, &block)
61 + #
62 + # wrapper for assert_select with additional support for using
63 + # css selectors to set expectation on Strings. Use this in
64 + # helper specs, for example, to set expectations on the results
65 + # of helper methods.
66 + #
67 + # == Examples
68 + #
69 + # # in a controller spec
70 + # response.should have_tag("div", "some text")
71 + #
72 + # # in a helper spec (person_address_tag is a method in the helper)
73 + # person_address_tag.should have_tag("input#person_address")
74 + #
75 + # see documentation for assert_select at http://api.rubyonrails.org/
76 + def have_tag(*args, &block)
77 + AssertSelect.new(:assert_select, self, *args, &block)
78 + end
79 +
80 + # wrapper for a nested assert_select
81 + #
82 + # response.should have_tag("div#form") do
83 + # with_tag("input#person_name[name=?]", "person[name]")
84 + # end
85 + #
86 + # see documentation for assert_select at http://api.rubyonrails.org/
87 + def with_tag(*args, &block)
88 + should have_tag(*args, &block)
89 + end
90 +
91 + # wrapper for a nested assert_select with false
92 + #
93 + # response.should have_tag("div#1") do
94 + # without_tag("span", "some text that shouldn't be there")
95 + # end
96 + #
97 + # see documentation for assert_select at http://api.rubyonrails.org/
98 + def without_tag(*args, &block)
99 + should_not have_tag(*args, &block)
100 + end
101 +
102 + # :call-seq:
103 + # response.should have_rjs(*args, &block)
104 + #
105 + # wrapper for assert_select_rjs
106 + #
107 + # see documentation for assert_select_rjs at http://api.rubyonrails.org/
108 + def have_rjs(*args, &block)
109 + AssertSelect.new(:assert_select_rjs, self, *args, &block)
110 + end
111 +
112 + # :call-seq:
113 + # response.should send_email(*args, &block)
114 + #
115 + # wrapper for assert_select_email
116 + #
117 + # see documentation for assert_select_email at http://api.rubyonrails.org/
118 + def send_email(*args, &block)
119 + AssertSelect.new(:assert_select_email, self, *args, &block)
120 + end
121 +
122 + # wrapper for assert_select_encoded
123 + #
124 + # see documentation for assert_select_encoded at http://api.rubyonrails.org/
125 + def with_encoded(*args, &block)
126 + should AssertSelect.new(:assert_select_encoded, self, *args, &block)
127 + end
128 + end
129 + end
130 + end
@@ -0,0 +1,55
1 + module Spec
2 + module Rails
3 + module Matchers
4 +
5 + class HaveText #:nodoc:
6 +
7 + def initialize(expected)
8 + @expected = expected
9 + end
10 +
11 + def matches?(response_or_text)
12 + @actual = response_or_text.respond_to?(:body) ? response_or_text.body : response_or_text
13 + return actual =~ expected if Regexp === expected
14 + return actual == expected unless Regexp === expected
15 + end
16 +
17 + def failure_message
18 + "expected #{expected.inspect}, got #{actual.inspect}"
19 + end
20 +
21 + def negative_failure_message
22 + "expected not to have text #{expected.inspect}"
23 + end
24 +
25 + def to_s
26 + "have text #{expected.inspect}"
27 + end
28 +
29 + private
30 + attr_reader :expected
31 + attr_reader :actual
32 +
33 + end
34 +
35 + # :call-seq:
36 + # response.should have_text(expected)
37 + # response.should_not have_text(expected)
38 + #
39 + # Accepts a String or a Regexp, matching a String using ==
40 + # and a Regexp using =~.
41 + #
42 + # Use this instead of <tt>response.should have_tag()</tt>
43 + # when you either don't know or don't care where on the page
44 + # this text appears.
45 + #
46 + # == Examples
47 + #
48 + # response.should have_text("This is the expected text")
49 + def have_text(text)
50 + HaveText.new(text)
51 + end
52 +
53 + end
54 + end
55 + end
@@ -0,0 +1,113
1 + module Spec
2 + module Rails
3 + module Matchers
4 +
5 + class RedirectTo #:nodoc:
6 +
7 + def initialize(request, expected)
8 + @expected = expected
9 + @request = request
10 + end
11 +
12 + def matches?(response)
13 + @redirected = response.redirect?
14 + @actual = response.redirect_url
15 + return false unless @redirected
16 + if @expected.instance_of? Hash
17 + return false unless @actual =~ %r{^\w+://#{@request.host}}
18 + return false unless actual_redirect_to_valid_route
19 + return actual_hash == expected_hash
20 + else
21 + return @actual == expected_url
22 + end
23 + end
24 +
25 + def actual_hash
26 + hash_from_url @actual
27 + end
28 +
29 + def expected_hash
30 + hash_from_url expected_url
31 + end
32 +
33 + def actual_redirect_to_valid_route
34 + actual_hash
35 + end
36 +
37 + def hash_from_url(url)
38 + query_hash(url).merge(path_hash(url)).with_indifferent_access
39 + end
40 +
41 + def path_hash(url)
42 + path = url.sub(%r{^\w+://#{@request.host}}, "").split("?", 2)[0]
43 + ActionController::Routing::Routes.recognize_path path
44 + end
45 +
46 + def query_hash(url)
47 + query = url.split("?", 2)[1] || ""
48 + QueryParameterParser.parse_query_parameters(query, @request)
49 + end
50 +
51 + def expected_url
52 + case @expected
53 + when Hash
54 + return ActionController::UrlRewriter.new(@request, {}).rewrite(@expected)
55 + when :back
56 + return @request.env['HTTP_REFERER']
57 + when %r{^\w+://.*}
58 + return @expected
59 + else
60 + return "http://#{@request.host}" + (@expected.split('')[0] == '/' ? '' : '/') + @expected
61 + end
62 + end
63 +
64 + def failure_message
65 + if @redirected
66 + return %Q{expected redirect to #{@expected.inspect}, got redirect to #{@actual.inspect}}
67 + else
68 + return %Q{expected redirect to #{@expected.inspect}, got no redirect}
69 + end
70 + end
71 +
72 + def negative_failure_message
73 + return %Q{expected not to be redirected to #{@expected.inspect}, but was} if @redirected
74 + end
75 +
76 + def description
77 + "redirect to #{@actual.inspect}"
78 + end
79 +
80 + class QueryParameterParser
81 + def self.parse_query_parameters(query, request)
82 + if defined?(CGIMethods)
83 + CGIMethods.parse_query_parameters(query)
84 + else
85 + request.class.parse_query_parameters(query)
86 + end
87 + end
88 + end
89 + end
90 +
91 + # :call-seq:
92 + # response.should redirect_to(url)
93 + # response.should redirect_to(:action => action_name)
94 + # response.should redirect_to(:controller => controller_name, :action => action_name)
95 + # response.should_not redirect_to(url)
96 + # response.should_not redirect_to(:action => action_name)
97 + # response.should_not redirect_to(:controller => controller_name, :action => action_name)
98 + #
99 + # Passes if the response is a redirect to the url, action or controller/action.
100 + # Useful in controller specs (integration or isolation mode).
101 + #
102 + # == Examples
103 + #
104 + # response.should redirect_to("path/to/action")
105 + # response.should redirect_to("http://test.host/path/to/action")
106 + # response.should redirect_to(:action => 'list')
107 + def redirect_to(opts)
108 + RedirectTo.new(request, opts)
109 + end
110 + end
111 +
112 + end
113 + end
@@ -0,0 +1,70
1 + module Spec
2 + module Rails
3 + module Matchers
4 +
5 + class RenderTemplate #:nodoc:
6 +
7 + def initialize(expected, controller)
8 + @controller = controller
9 + @expected = expected
10 + end
11 +
12 + def matches?(response)
13 + @actual = response.rendered_file
14 + full_path(@actual) == full_path(@expected)
15 + end
16 +
17 + def failure_message
18 + "expected #{@expected.inspect}, got #{@actual.inspect}"
19 + end
20 +
21 + def negative_failure_message
22 + "expected not to render #{@expected.inspect}, but did"
23 + end
24 +
25 + def description
26 + "render template #{@expected.inspect}"
27 + end
28 +
29 + private
30 + def full_path(path)
31 + return nil if path.nil?
32 + path.include?('/') ? path : "#{@controller.class.to_s.underscore.gsub('_controller','')}/#{path}"
33 + end
34 +
35 + end
36 +
37 + # :call-seq:
38 + # response.should render_template(path)
39 + # response.should_not render_template(path)
40 + #
41 + # Passes if the specified template is rendered by the response.
42 + # Useful in controller specs (integration or isolation mode).
43 + #
44 + # <code>path</code> can include the controller path or not. It
45 + # can also include an optional extension (no extension assumes .rhtml).
46 + #
47 + # Note that partials must be spelled with the preceding underscore.
48 + #
49 + # == Examples
50 + #
51 + # response.should render_template('list')
52 + # response.should render_template('same_controller/list')
53 + # response.should render_template('other_controller/list')
54 + #
55 + # #rjs
56 + # response.should render_template('list.rjs')
57 + # response.should render_template('same_controller/list.rjs')
58 + # response.should render_template('other_controller/list.rjs')
59 + #
60 + # #partials
61 + # response.should render_template('_a_partial')
62 + # response.should render_template('same_controller/_a_partial')
63 + # response.should render_template('other_controller/_a_partial')
64 + def render_template(path)
65 + RenderTemplate.new(path.to_s, @controller)
66 + end
67 +
68 + end
69 + end
70 + end
@@ -0,0 +1,71
1 + # WARNING - THIS IS PURELY EXPERIMENTAL AT THIS POINT
2 + # Courtesy of Brian Takita and Yurii Rashkovskii
3 +
4 + $:.unshift File.join(File.dirname(__FILE__), *%w[.. .. .. .. rspec lib])
5 + if defined?(ActiveRecord::Base)
6 + require 'test_help'
7 + else
8 + require 'action_controller/test_process'
9 + require 'action_controller/integration'
10 + end
11 + require 'test/unit/testresult'
12 + require 'spec'
13 + require 'spec/rails'
14 +
15 + Test::Unit.run = true
16 +
17 + ActionController::Integration::Session.send(:include, Spec::Matchers)
18 + ActionController::Integration::Session.send(:include, Spec::Rails::Matchers)
19 +
20 + class RailsStory < ActionController::IntegrationTest
21 + if defined?(ActiveRecord::Base)
22 + self.use_transactional_fixtures = true
23 + else
24 + def self.fixture_table_names; []; end # Workaround for projects that don't use ActiveRecord
25 + end
26 +
27 + def initialize #:nodoc:
28 + # TODO - eliminate this hack, which is here to stop
29 + # Rails Stories from dumping the example summary.
30 + Spec::Runner::Options.class_eval do
31 + def examples_should_be_run?
32 + false
33 + end
34 + end
35 + @_result = Test::Unit::TestResult.new
36 + end
37 + end
38 +
39 + class ActiveRecordSafetyListener
40 + include Singleton
41 + def scenario_started(*args)
42 + if defined?(ActiveRecord::Base)
43 + ActiveRecord::Base.send :increment_open_transactions unless Rails::VERSION::STRING == "1.1.6"
44 + ActiveRecord::Base.connection.begin_db_transaction
45 + end
46 + end
47 +
48 + def scenario_succeeded(*args)
49 + if defined?(ActiveRecord::Base)
50 + ActiveRecord::Base.connection.rollback_db_transaction
51 + ActiveRecord::Base.send :decrement_open_transactions unless Rails::VERSION::STRING == "1.1.6"
52 + end
53 + end
54 + alias :scenario_pending :scenario_succeeded
55 + alias :scenario_failed :scenario_succeeded
56 + end
57 +
58 + class Spec::Story::Runner::ScenarioRunner
59 + def initialize
60 + @listeners = [ActiveRecordSafetyListener.instance]
61 + end
62 + end
63 +
64 + class Spec::Story::GivenScenario
65 + def perform(instance, name = nil)
66 + scenario = Spec::Story::Runner::StoryRunner.scenario_from_current_story @name
67 + runner = Spec::Story::Runner::ScenarioRunner.new
68 + runner.instance_variable_set(:@listeners,[])
69 + runner.run(scenario, instance)
70 + end
71 + end
@@ -0,0 +1,23
1 + module Spec
2 + module Rails
3 + module VERSION #:nodoc:
4 + BUILD_TIME_UTC = 20080131122909
5 + end
6 + end
7 + end
8 +
9 + # Verify that the plugin has the same revision as RSpec
10 + if Spec::Rails::VERSION::BUILD_TIME_UTC != Spec::VERSION::BUILD_TIME_UTC
11 + raise <<-EOF
12 +
13 + ############################################################################
14 + Your RSpec on Rails plugin is incompatible with your installed RSpec.
15 +
16 + RSpec : #{Spec::VERSION::BUILD_TIME_UTC}
17 + RSpec on Rails : #{Spec::Rails::VERSION::BUILD_TIME_UTC}
18 +
19 + Make sure your RSpec on Rails plugin is compatible with your RSpec gem.
20 + See http://rspec.rubyforge.org/documentation/rails/install.html for details.
21 + ############################################################################
22 + EOF
23 + end
@@ -0,0 +1,36
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 + require File.join(File.dirname(__FILE__), *%w[.. .. .. lib autotest rails_rspec])
3 + require File.join(File.dirname(__FILE__), *%w[.. .. .. .. rspec spec autotest_matchers])
4 +
5 + describe Autotest::RailsRspec, "file mapping" do
6 + before(:each) do
7 + @autotest = Autotest::RailsRspec.new
8 + @autotest.hook :initialize
9 + end
10 +
11 + it "should map model example to model" do
12 + @autotest.should map_specs(['spec/models/thing_spec.rb']).
13 + to('app/models/thing.rb')
14 + end
15 +
16 + it "should map controller example to controller" do
17 + @autotest.should map_specs(['spec/controllers/things_controller_spec.rb']).
18 + to('app/controllers/things_controller.rb')
19 + end
20 +
21 + it "should map view.rhtml" do
22 + @autotest.should map_specs(['spec/views/things/index.rhtml_spec.rb']).
23 + to('app/views/things/index.rhtml')
24 + end
25 +
26 + it "should map view.rhtml with underscores in example filename" do
27 + @autotest.should map_specs(['spec/views/things/index_rhtml_spec.rb']).
28 + to('app/views/things/index.rhtml')
29 + end
30 +
31 + it "should map view.html.erb" do
32 + @autotest.should map_specs(['spec/views/things/index.html.erb_spec.rb']).
33 + to('app/views/things/index.html.erb')
34 + end
35 +
36 + end
@@ -0,0 +1,8
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 + require File.join(File.dirname(__FILE__), "..", "..", "..", "lib", "autotest", "rails_rspec")
3 +
4 + describe Autotest::RailsRspec do
5 + it "should provide the correct spec_command" do
6 + Autotest::RailsRspec.new.spec_command.should == "script/spec"
7 + end
8 + end
@@ -0,0 +1,55
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 +
3 + describe "An AssignsHashProxy" do
4 + before(:each) do
5 + @object = Object.new
6 + @assigns = Hash.new
7 + @object.stub!(:assigns).and_return(@assigns)
8 + @proxy = Spec::Rails::Example::AssignsHashProxy.new(@object)
9 + end
10 +
11 + it "has [] accessor" do
12 + @proxy['foo'] = 'bar'
13 + @assigns['foo'].should == 'bar'
14 + @proxy['foo'].should == 'bar'
15 + end
16 +
17 + it "works for symbol key" do
18 + @assigns[:foo] = 2
19 + @proxy[:foo].should == 2
20 + end
21 +
22 + it "checks for string key before symbol key" do
23 + @assigns['foo'] = false
24 + @assigns[:foo] = 2
25 + @proxy[:foo].should == false
26 + end
27 +
28 + it "each method iterates through each element like a Hash" do
29 + values = {
30 + 'foo' => 1,
31 + 'bar' => 2,
32 + 'baz' => 3
33 + }
34 + @proxy['foo'] = values['foo']
35 + @proxy['bar'] = values['bar']
36 + @proxy['baz'] = values['baz']
37 +
38 + @proxy.each do |key, value|
39 + key.should == key
40 + value.should == values[key]
41 + end
42 + end
43 +
44 + it "delete method deletes the element of passed in key" do
45 + @proxy['foo'] = 'bar'
46 + @proxy.delete('foo').should == 'bar'
47 + @proxy['foo'].should be_nil
48 + end
49 +
50 + it "has_key? detects the presence of a key" do
51 + @proxy['foo'] = 'bar'
52 + @proxy.has_key?('foo').should == true
53 + @proxy.has_key?('bar').should == false
54 + end
55 + end
@@ -0,0 +1,83
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 +
3 + module Spec
4 + module Example
5 + describe Configuration, :shared => true do
6 + before(:each) { @config = Configuration.new }
7 + end
8 +
9 + describe Configuration, "#use_transactional_fixtures" do
10 + it_should_behave_like "Spec::Example::Configuration"
11 +
12 + it "should return Test::Unit::TestCase.use_transactional_fixtures" do
13 + @config.use_transactional_fixtures.should == Test::Unit::TestCase.use_transactional_fixtures
14 + end
15 +
16 + it "should set Test::Unit::TestCase.use_transactional_fixtures to false" do
17 + Configuration::EXAMPLE_GROUP_CLASSES.each do |example_group|
18 + example_group.should_receive(:use_transactional_fixtures=).with(false)
19 + end
20 + @config.use_transactional_fixtures = false
21 + end
22 +
23 + it "should set Test::Unit::TestCase.use_transactional_fixtures to true" do
24 + Configuration::EXAMPLE_GROUP_CLASSES.each do |example_group|
25 + example_group.should_receive(:use_transactional_fixtures=).with(true)
26 + end
27 + @config.use_transactional_fixtures = true
28 + end
29 + end
30 +
31 + describe Configuration, "#use_instantiated_fixtures" do
32 + it_should_behave_like "Spec::Example::Configuration"
33 +
34 + it "should return Test::Unit::TestCase.use_transactional_fixtures" do
35 + @config.use_instantiated_fixtures.should == Test::Unit::TestCase.use_instantiated_fixtures
36 + end
37 +
38 + it "should set Test::Unit::TestCase.use_instantiated_fixtures to false" do
39 + Configuration::EXAMPLE_GROUP_CLASSES.each do |example_group|
40 + example_group.should_receive(:use_instantiated_fixtures=).with(false)
41 + end
42 + @config.use_instantiated_fixtures = false
43 + end
44 +
45 + it "should set Test::Unit::TestCase.use_instantiated_fixtures to true" do
46 + Configuration::EXAMPLE_GROUP_CLASSES.each do |example_group|
47 + example_group.should_receive(:use_instantiated_fixtures=).with(true)
48 + end
49 + @config.use_instantiated_fixtures = true
50 + end
51 + end
52 +
53 + describe Configuration, "#fixture_path" do
54 + it_should_behave_like "Spec::Example::Configuration"
55 +
56 + it "should default to RAILS_ROOT + '/spec/fixtures'" do
57 + @config.fixture_path.should == RAILS_ROOT + '/spec/fixtures'
58 + Configuration::EXAMPLE_GROUP_CLASSES.each do |example_group|
59 + example_group.fixture_path.should == RAILS_ROOT + '/spec/fixtures'
60 + end
61 + end
62 +
63 + it "should set fixture_path" do
64 + @config.fixture_path = "/new/path"
65 + @config.fixture_path.should == "/new/path"
66 + Configuration::EXAMPLE_GROUP_CLASSES.each do |example_group|
67 + example_group.fixture_path.should == "/new/path"
68 + end
69 + end
70 + end
71 +
72 + describe Configuration, "#global_fixtures" do
73 + it_should_behave_like "Spec::Example::Configuration"
74 +
75 + it "should set fixtures on TestCase" do
76 + Configuration::EXAMPLE_GROUP_CLASSES.each do |example_group|
77 + example_group.should_receive(:fixtures).with(:blah)
78 + end
79 + @config.global_fixtures = [:blah]
80 + end
81 + end
82 + end
83 + end
@@ -0,0 +1,43
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 + require 'controller_spec_controller'
3 +
4 + describe "a controller spec running in isolation mode", :type => :controller do
5 + controller_name :controller_spec
6 +
7 + it "should not care if the template doesn't exist" do
8 + get 'some_action'
9 + response.should be_success
10 + response.should render_template("template/that/does/not/actually/exist")
11 + end
12 +
13 + it "should not care if the template has errors" do
14 + get 'action_with_errors_in_template'
15 + response.should be_success
16 + response.should render_template("action_with_errors_in_template")
17 + end
18 + end
19 +
20 + describe "a controller spec running in integration mode", :type => :controller do
21 + controller_name :controller_spec
22 + integrate_views
23 +
24 + before(:each) do
25 + controller.class.send(:define_method, :rescue_action) { |e| raise e }
26 + end
27 +
28 + it "should render a template" do
29 + get 'action_with_template'
30 + response.should be_success
31 + response.should have_tag('div', 'This is action_with_template.rhtml')
32 + end
33 +
34 + it "should choke if the template doesn't exist" do
35 + lambda { get 'some_action' }.should raise_error(ActionController::MissingTemplate)
36 + response.should_not be_success
37 + end
38 +
39 + it "should choke if the template has errors" do
40 + lambda { get 'action_with_errors_in_template' }.should raise_error(ActionView::TemplateError)
41 + response.should_not be_success
42 + end
43 + end
@@ -0,0 +1,187
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 + require 'controller_spec_controller'
3 +
4 + ['integration', 'isolation'].each do |mode|
5 + describe "A controller example running in #{mode} mode", :type => :controller do
6 + controller_name :controller_spec
7 + integrate_views if mode == 'integration'
8 +
9 + it "should provide controller.session as session" do
10 + get 'action_with_template'
11 + session.should equal(controller.session)
12 + end
13 +
14 + it "should provide the same session object before and after the action" do
15 + session_before = session
16 + get 'action_with_template'
17 + session.should equal(session_before)
18 + end
19 +
20 + it "should ensure controller.session is NOT nil before the action" do
21 + controller.session.should_not be_nil
22 + get 'action_with_template'
23 + end
24 +
25 + it "should ensure controller.session is NOT nil after the action" do
26 + get 'action_with_template'
27 + controller.session.should_not be_nil
28 + end
29 +
30 + it "should allow specifying a partial with partial name only" do
31 + get 'action_with_partial'
32 + response.should render_template("_partial")
33 + end
34 +
35 + it "should allow specifying a partial with expect_render" do
36 + controller.expect_render(:partial => "controller_spec/partial")
37 + get 'action_with_partial'
38 + end
39 +
40 + it "should allow specifying a partial with expect_render with object" do
41 + controller.expect_render(:partial => "controller_spec/partial", :object => "something")
42 + get 'action_with_partial_with_object', :thing => "something"
43 + end
44 +
45 + it "should allow specifying a partial with expect_render with locals" do
46 + controller.expect_render(:partial => "controller_spec/partial", :locals => {:thing => "something"})
47 + get 'action_with_partial_with_locals', :thing => "something"
48 + end
49 +
50 + it "should yield to render :update" do
51 + template = stub("template")
52 + controller.expect_render(:update).and_yield(template)
53 + template.should_receive(:replace).with(:bottom, "replace_me", :partial => "non_existent_partial")
54 + get 'action_with_render_update'
55 + puts response.body
56 + end
57 +
58 + it "should allow a path relative to RAILS_ROOT/app/views/ when specifying a partial" do
59 + get 'action_with_partial'
60 + response.should render_template("controller_spec/_partial")
61 + end
62 +
63 + it "should provide access to flash" do
64 + get 'action_with_template'
65 + flash[:flash_key].should == "flash value"
66 + end
67 +
68 + it "should provide access to flash values set after a session reset" do
69 + get 'action_setting_flash_after_session_reset'
70 + flash[:after_reset].should == "available"
71 + end
72 +
73 + it "should not provide access to flash values set before a session reset" do
74 + get 'action_setting_flash_before_session_reset'
75 + flash[:before_reset].should_not == "available"
76 + end
77 +
78 + it "should provide access to session" do
79 + get 'action_with_template'
80 + session[:session_key].should == "session value"
81 + end
82 +
83 + it "should support custom routes" do
84 + route_for(:controller => "custom_route_spec", :action => "custom_route").should == "/custom_route"
85 + end
86 +
87 + it "should support existing routes" do
88 + route_for(:controller => "controller_spec", :action => "some_action").should == "/controller_spec/some_action"
89 + end
90 +
91 + it "should generate params for custom routes" do
92 + params_from(:get, '/custom_route').should == {:controller => "custom_route_spec", :action => "custom_route"}
93 + end
94 +
95 + it "should generate params for existing routes" do
96 + params_from(:get, '/controller_spec/some_action').should == {:controller => "controller_spec", :action => "some_action"}
97 + end
98 +
99 + it "should expose instance vars through the assigns hash" do
100 + get 'action_setting_the_assigns_hash'
101 + assigns[:indirect_assigns_key].should == :indirect_assigns_key_value
102 + end
103 +
104 + it "should expose the assigns hash directly" do
105 + get 'action_setting_the_assigns_hash'
106 + assigns[:direct_assigns_key].should == :direct_assigns_key_value
107 + end
108 +
109 + it "should complain when calling should_receive(:render) on the controller" do
110 + lambda {
111 + controller.should_receive(:render)
112 + }.should raise_error(RuntimeError, /should_receive\(:render\) has been disabled/)
113 + end
114 +
115 + it "should complain when calling stub!(:render) on the controller" do
116 + lambda {
117 + controller.stub!(:render)
118 + }.should raise_error(RuntimeError, /stub!\(:render\) has been disabled/)
119 + end
120 +
121 + it "should NOT complain when calling should_receive with arguments other than :render" do
122 + controller.should_receive(:anything_besides_render)
123 + lambda {
124 + controller.rspec_verify
125 + }.should raise_error(Exception, /expected :anything_besides_render/)
126 + end
127 + end
128 +
129 + describe "Given a controller spec for RedirectSpecController running in #{mode} mode", :type => :controller do
130 + controller_name :redirect_spec
131 + integrate_views if mode == 'integration'
132 +
133 + it "a redirect should ignore the absence of a template" do
134 + get 'action_with_redirect_to_somewhere'
135 + response.should be_redirect
136 + response.redirect_url.should == "http://test.host/redirect_spec/somewhere"
137 + response.should redirect_to("http://test.host/redirect_spec/somewhere")
138 + end
139 +
140 + it "a call to response.should redirect_to should fail if no redirect" do
141 + get 'action_with_no_redirect'
142 + lambda {
143 + response.redirect?.should be_true
144 + }.should fail
145 + lambda {
146 + response.should redirect_to("http://test.host/redirect_spec/somewhere")
147 + }.should fail_with("expected redirect to \"http://test.host/redirect_spec/somewhere\", got no redirect")
148 + end
149 + end
150 +
151 + describe "Given a controller spec running in #{mode} mode" do
152 + example_group = describe "A controller spec"
153 + # , :type => :controller do
154 + # integrate_views if mode == 'integration'
155 + it "a spec in a context without controller_name set should fail with a useful warning" do
156 + pending("need a new way to deal with examples that should_raise")
157 + # ,
158 + # :should_raise => [
159 + # Spec::Expectations::ExpectationNotMetError,
160 + # /You have to declare the controller name in controller specs/
161 + # ] do
162 + end
163 + end
164 +
165 + end
166 +
167 + describe ControllerSpecController, :type => :controller do
168 + it "should not require naming the controller if describe is passed a type" do
169 + end
170 + end
171 +
172 + module Spec
173 + module Rails
174 + module Example
175 + describe ControllerExampleGroup do
176 + it "should clear its name from the description" do
177 + group = describe("foo", :type => :controller) do
178 + $nested_group = describe("bar") do
179 + end
180 + end
181 + group.description.to_s.should == "foo"
182 + $nested_group.description.to_s.should == "foo bar"
183 + end
184 + end
185 + end
186 + end
187 + end No newline at end of file
@@ -0,0 +1,112
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 +
3 + module Spec
4 + module Example
5 + describe ExampleGroupFactory do
6 + it "should return a ModelExampleGroup when given :type => :model" do
7 + example_group = Spec::Example::ExampleGroupFactory.create_example_group(
8 + "name", :type => :model
9 + ) {}
10 + example_group.superclass.should == Spec::Rails::Example::ModelExampleGroup
11 + end
12 +
13 + it "should return a ModelExampleGroup when given :spec_path => '/blah/spec/models/'" do
14 + example_group = Spec::Example::ExampleGroupFactory.create_example_group(
15 + "name", :spec_path => '/blah/spec/models/blah.rb'
16 + ) {}
17 + example_group.superclass.should == Spec::Rails::Example::ModelExampleGroup
18 + end
19 +
20 + it "should return a ModelExampleGroup when given :spec_path => '\\blah\\spec\\models\\' (windows format)" do
21 + example_group = Spec::Example::ExampleGroupFactory.create_example_group(
22 + "name", :spec_path => '\\blah\\spec\\models\\blah.rb'
23 + ) {}
24 + example_group.superclass.should == Spec::Rails::Example::ModelExampleGroup
25 + end
26 +
27 + it "should return a RailsExampleGroup when given :spec_path => '/blah/spec/foo/' (anything other than controllers, views and helpers)" do
28 + example_group = Spec::Example::ExampleGroupFactory.create_example_group(
29 + "name", :spec_path => '/blah/spec/foo/blah.rb'
30 + ) {}
31 + example_group.superclass.should == Spec::Rails::Example::RailsExampleGroup
32 + end
33 +
34 + it "should return a RailsExampleGroup when given :spec_path => '\\blah\\spec\\foo\\' (windows format) (anything other than controllers, views and helpers)" do
35 + example_group = Spec::Example::ExampleGroupFactory.create_example_group(
36 + "name", :spec_path => '\\blah\\spec\\foo\\blah.rb'
37 + ) {}
38 + example_group.superclass.should == Spec::Rails::Example::RailsExampleGroup
39 + end
40 +
41 + it "should return a ViewExampleGroup when given :type => :model" do
42 + example_group = Spec::Example::ExampleGroupFactory.create_example_group(
43 + "name", :type => :view
44 + ) {}
45 + example_group.superclass.should == Spec::Rails::Example::ViewExampleGroup
46 + end
47 +
48 + it "should return a ViewExampleGroup when given :spec_path => '/blah/spec/views/'" do
49 + example_group = Spec::Example::ExampleGroupFactory.create_example_group(
50 + "name", :spec_path => '/blah/spec/views/blah.rb'
51 + ) {}
52 + example_group.superclass.should == Spec::Rails::Example::ViewExampleGroup
53 + end
54 +
55 + it "should return a ModelExampleGroup when given :spec_path => '\\blah\\spec\\views\\' (windows format)" do
56 + example_group = Spec::Example::ExampleGroupFactory.create_example_group(
57 + "name", :spec_path => '\\blah\\spec\\views\\blah.rb'
58 + ) {}
59 + example_group.superclass.should == Spec::Rails::Example::ViewExampleGroup
60 + end
61 +
62 + it "should return a HelperExampleGroup when given :type => :helper" do
63 + example_group = Spec::Example::ExampleGroupFactory.create_example_group(
64 + "name", :type => :helper
65 + ) {}
66 + example_group.superclass.should == Spec::Rails::Example::HelperExampleGroup
67 + end
68 +
69 + it "should return a HelperExampleGroup when given :spec_path => '/blah/spec/helpers/'" do
70 + example_group = Spec::Example::ExampleGroupFactory.create_example_group(
71 + "name", :spec_path => '/blah/spec/helpers/blah.rb'
72 + ) {}
73 + example_group.superclass.should == Spec::Rails::Example::HelperExampleGroup
74 + end
75 +
76 + it "should return a ModelExampleGroup when given :spec_path => '\\blah\\spec\\helpers\\' (windows format)" do
77 + example_group = Spec::Example::ExampleGroupFactory.create_example_group(
78 + "name", :spec_path => '\\blah\\spec\\helpers\\blah.rb'
79 + ) {}
80 + example_group.superclass.should == Spec::Rails::Example::HelperExampleGroup
81 + end
82 +
83 + it "should return a ControllerExampleGroup when given :type => :controller" do
84 + example_group = Spec::Example::ExampleGroupFactory.create_example_group(
85 + "name", :type => :controller
86 + ) {}
87 + example_group.superclass.should == Spec::Rails::Example::ControllerExampleGroup
88 + end
89 +
90 + it "should return a ControllerExampleGroup when given :spec_path => '/blah/spec/controllers/'" do
91 + example_group = Spec::Example::ExampleGroupFactory.create_example_group(
92 + "name", :spec_path => '/blah/spec/controllers/blah.rb'
93 + ) {}
94 + example_group.superclass.should == Spec::Rails::Example::ControllerExampleGroup
95 + end
96 +
97 + it "should return a ModelExampleGroup when given :spec_path => '\\blah\\spec\\controllers\\' (windows format)" do
98 + example_group = Spec::Example::ExampleGroupFactory.create_example_group(
99 + "name", :spec_path => '\\blah\\spec\\controllers\\blah.rb'
100 + ) {}
101 + example_group.superclass.should == Spec::Rails::Example::ControllerExampleGroup
102 + end
103 +
104 + it "should favor the :type over the :spec_path" do
105 + example_group = Spec::Example::ExampleGroupFactory.create_example_group(
106 + "name", :spec_path => '/blah/spec/models/blah.rb', :type => :controller
107 + ) {}
108 + example_group.superclass.should == Spec::Rails::Example::ControllerExampleGroup
109 + end
110 + end
111 + end
112 + end
@@ -0,0 +1,118
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 + Spec::Runner.configuration.global_fixtures = :people
3 +
4 + describe ExplicitHelper, :type => :helper do
5 + it "should not require naming the helper if describe is passed a type" do
6 + method_in_explicit_helper.should match(/text from a method/)
7 + end
8 + end
9 +
10 + module Spec
11 + module Rails
12 + module Example
13 + describe HelperExampleGroup, :type => :helper do
14 + helper_name :explicit
15 +
16 + it "should have direct access to methods defined in helpers" do
17 + method_in_explicit_helper.should =~ /text from a method/
18 + end
19 +
20 + it "should have access to named routes" do
21 + rspec_on_rails_specs_url.should == "http://test.host/rspec_on_rails_specs"
22 + rspec_on_rails_specs_path.should == "/rspec_on_rails_specs"
23 + end
24 +
25 + it "should fail if the helper method deson't exist" do
26 + lambda { non_existant_helper_method }.should raise_error(NameError)
27 + end
28 + end
29 +
30 +
31 + describe HelperExampleGroup, "#eval_erb", :type => :helper do
32 + helper_name :explicit
33 +
34 + it "should support methods that accept blocks" do
35 + eval_erb("<% prepend 'foo' do %>bar<% end %>").should == "foobar"
36 + end
37 + end
38 +
39 + describe HelperExampleGroup, ".fixtures", :type => :helper do
40 + helper_name :explicit
41 + fixtures :animals
42 +
43 + it "should load fixtures" do
44 + pig = animals(:pig)
45 + pig.class.should == Animal
46 + end
47 +
48 + it "should load global fixtures" do
49 + lachie = people(:lachie)
50 + lachie.class.should == Person
51 + end
52 + end
53 +
54 + describe HelperExampleGroup, "included modules", :type => :helper do
55 + helpers = [
56 + ActionView::Helpers::ActiveRecordHelper,
57 + ActionView::Helpers::AssetTagHelper,
58 + ActionView::Helpers::BenchmarkHelper,
59 + ActionView::Helpers::CacheHelper,
60 + ActionView::Helpers::CaptureHelper,
61 + ActionView::Helpers::DateHelper,
62 + ActionView::Helpers::DebugHelper,
63 + ActionView::Helpers::FormHelper,
64 + ActionView::Helpers::FormOptionsHelper,
65 + ActionView::Helpers::FormTagHelper,
66 + ActionView::Helpers::JavaScriptHelper,
67 + ActionView::Helpers::NumberHelper,
68 + ActionView::Helpers::PrototypeHelper,
69 + ActionView::Helpers::ScriptaculousHelper,
70 + ActionView::Helpers::TagHelper,
71 + ActionView::Helpers::TextHelper,
72 + ActionView::Helpers::UrlHelper
73 + ]
74 + helpers << ActionView::Helpers::PaginationHelper rescue nil #removed for 2.0
75 + helpers << ActionView::Helpers::JavaScriptMacrosHelper rescue nil #removed for 2.0
76 + helpers.each do |helper_module|
77 + it "should include #{helper_module}" do
78 + self.class.ancestors.should include(helper_module)
79 + end
80 + end
81 + end
82 +
83 + # TODO: BT - Helper Examples should proxy method_missing to a Rails View instance.
84 + # When that is done, remove this method
85 + describe HelperExampleGroup, "#protect_against_forgery?", :type => :helper do
86 + it "should return false" do
87 + protect_against_forgery?.should be_false
88 + end
89 + end
90 + end
91 + end
92 + end
93 +
94 + module Bug11223
95 + # see http://rubyforge.org/tracker/index.php?func=detail&aid=11223&group_id=797&atid=3149
96 + describe 'Accessing flash from helper spec', :type => :helper do
97 + it 'should not raise an error' do
98 + lambda { flash['test'] }.should_not raise_error
99 + end
100 + end
101 + end
102 +
103 + module Spec
104 + module Rails
105 + module Example
106 + describe HelperExampleGroup do
107 + it "should clear its name from the description" do
108 + group = describe("foo", :type => :helper) do
109 + $nested_group = describe("bar") do
110 + end
111 + end
112 + group.description.to_s.should == "foo"
113 + $nested_group.description.to_s.should == "foo bar"
114 + end
115 + end
116 + end
117 + end
118 + end No newline at end of file
@@ -0,0 +1,64
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 +
3 + describe "IvarProxy setup", :shared => true do
4 + before do
5 + @object = Object.new
6 + @proxy = Spec::Rails::Example::IvarProxy.new(@object)
7 + end
8 + end
9 +
10 + describe "IvarProxy" do
11 + it_should_behave_like "IvarProxy setup"
12 +
13 + it "has [] accessor" do
14 + @proxy['foo'] = 'bar'
15 + @object.instance_variable_get(:@foo).should == 'bar'
16 + @proxy['foo'].should == 'bar'
17 + end
18 +
19 + it "iterates through each element like a Hash" do
20 + values = {
21 + 'foo' => 1,
22 + 'bar' => 2,
23 + 'baz' => 3
24 + }
25 + @proxy['foo'] = values['foo']
26 + @proxy['bar'] = values['bar']
27 + @proxy['baz'] = values['baz']
28 +
29 + @proxy.each do |key, value|
30 + key.should == key
31 + value.should == values[key]
32 + end
33 + end
34 +
35 + it "detects the presence of a key" do
36 + @proxy['foo'] = 'bar'
37 + @proxy.has_key?('foo').should == true
38 + @proxy.has_key?('bar').should == false
39 + end
40 + end
41 +
42 + describe "IvarProxy", "#delete" do
43 + it_should_behave_like "IvarProxy setup"
44 +
45 + it "deletes the element with key" do
46 + @proxy['foo'] = 'bar'
47 + @proxy.delete('foo').should == 'bar'
48 + @proxy['foo'].should be_nil
49 + end
50 +
51 + it "deletes nil instance variables" do
52 + @proxy['foo'] = nil
53 + @object.instance_variables.should include("@foo")
54 + @proxy.delete('foo').should == nil
55 + @proxy['foo'].should be_nil
56 + @object.instance_variables.should_not include("@foo")
57 + end
58 +
59 + it "returns nil when key does not exist" do
60 + @proxy['foo'].should be_nil
61 + @proxy.delete('foo').should == nil
62 + @proxy['foo'].should be_nil
63 + end
64 + end
@@ -0,0 +1,18
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 +
3 + module Spec
4 + module Rails
5 + module Example
6 + describe ModelExampleGroup do
7 + it "should clear its name from the description" do
8 + group = describe("foo", :type => :model) do
9 + $nested_group = describe("bar") do
10 + end
11 + end
12 + group.description.to_s.should == "foo"
13 + $nested_group.description.to_s.should == "foo bar"
14 + end
15 + end
16 + end
17 + end
18 + end No newline at end of file
@@ -0,0 +1,16
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 +
3 + describe "A shared view example_group", :shared => true do
4 + it "should have some tag with some text" do
5 + response.should have_tag('div', 'This is text from a method in the ViewSpecHelper')
6 + end
7 + end
8 +
9 + describe "A view example_group", :type => :view do
10 + it_should_behave_like "A shared view example_group"
11 +
12 + before(:each) do
13 + render "view_spec/implicit_helper"
14 + end
15 + end
16 +
@@ -0,0 +1,33
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 +
3 + describe "assert_equal", :shared => true do
4 + it "like assert_equal" do
5 + assert_equal 1, 1
6 + lambda {
7 + assert_equal 1, 2
8 + }.should raise_error(Test::Unit::AssertionFailedError)
9 + end
10 + end
11 +
12 + describe "A model spec should be able to access 'test/unit' assertions", :type => :model do
13 + it_should_behave_like "assert_equal"
14 + end
15 +
16 + describe "A view spec should be able to access 'test/unit' assertions", :type => :view do
17 + it_should_behave_like "assert_equal"
18 + end
19 +
20 + describe "A helper spec should be able to access 'test/unit' assertions", :type => :helper do
21 + it_should_behave_like "assert_equal"
22 + end
23 +
24 + describe "A controller spec with integrated views should be able to access 'test/unit' assertions", :type => :controller do
25 + controller_name :controller_spec
26 + integrate_views
27 + it_should_behave_like "assert_equal"
28 + end
29 +
30 + describe "A controller spec should be able to access 'test/unit' assertions", :type => :controller do
31 + controller_name :controller_spec
32 + it_should_behave_like "assert_equal"
33 + end
@@ -0,0 +1,263
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 +
3 + describe "A template with an implicit helper", :type => :view do
4 + before(:each) do
5 + render "view_spec/implicit_helper"
6 + end
7 +
8 + it "should include the helper" do
9 + response.should have_tag('div', :content => "This is text from a method in the ViewSpecHelper")
10 + end
11 +
12 + it "should include the application helper" do
13 + response.should have_tag('div', :content => "This is text from a method in the ApplicationHelper")
14 + end
15 +
16 + it "should have access to named routes" do
17 + rspec_on_rails_specs_url.should == "http://test.host/rspec_on_rails_specs"
18 + rspec_on_rails_specs_path.should == "/rspec_on_rails_specs"
19 + end
20 + end
21 +
22 + describe "A template requiring an explicit helper", :type => :view do
23 + before(:each) do
24 + render "view_spec/explicit_helper", :helper => 'explicit'
25 + end
26 +
27 + it "should include the helper if specified" do
28 + response.should have_tag('div', :content => "This is text from a method in the ExplicitHelper")
29 + end
30 +
31 + it "should include the application helper" do
32 + response.should have_tag('div', :content => "This is text from a method in the ApplicationHelper")
33 + end
34 + end
35 +
36 + describe "A template requiring multiple explicit helpers", :type => :view do
37 + before(:each) do
38 + render "view_spec/multiple_helpers", :helpers => ['explicit', 'more_explicit']
39 + end
40 +
41 + it "should include all specified helpers" do
42 + response.should have_tag('div', :content => "This is text from a method in the ExplicitHelper")
43 + response.should have_tag('div', :content => "This is text from a method in the MoreExplicitHelper")
44 + end
45 +
46 + it "should include the application helper" do
47 + response.should have_tag('div', :content => "This is text from a method in the ApplicationHelper")
48 + end
49 + end
50 +
51 + describe "Message Expectations on helper methods", :type => :view do
52 + it "should work" do
53 + template.should_receive(:method_in_plugin_application_helper).and_return('alternate message 1')
54 + render "view_spec/implicit_helper"
55 + response.body.should =~ /alternate message 1/
56 + end
57 +
58 + it "should work twice" do
59 + template.should_receive(:method_in_plugin_application_helper).and_return('alternate message 2')
60 + render "view_spec/implicit_helper"
61 + response.body.should =~ /alternate message 2/
62 + end
63 + end
64 +
65 + describe "A template that includes a partial", :type => :view do
66 + def render!
67 + render "view_spec/template_with_partial"
68 + end
69 +
70 + it "should render the enclosing template" do
71 + render!
72 + response.should have_tag('div', "method_in_partial in ViewSpecHelper")
73 + end
74 +
75 + it "should render the partial" do
76 + render!
77 + response.should have_tag('div', "method_in_template_with_partial in ViewSpecHelper")
78 + end
79 +
80 + it "should include the application helper" do
81 + render!
82 + response.should have_tag('div', "This is text from a method in the ApplicationHelper")
83 + end
84 +
85 + it "should pass expect_render with the right partial" do
86 + template.expect_render(:partial => 'partial')
87 + render!
88 + template.verify_rendered
89 + end
90 +
91 + it "should fail expect_render with the wrong partial" do
92 + template.expect_render(:partial => 'non_existent')
93 + render!
94 + begin
95 + template.verify_rendered
96 + rescue Spec::Mocks::MockExpectationError => e
97 + ensure
98 + e.backtrace.find{|line| line =~ /view_spec_spec\.rb\:92/}.should_not be_nil
99 + end
100 + end
101 +
102 + it "should pass expect_render when a partial is expected twice and happens twice" do
103 + template.expect_render(:partial => 'partial_used_twice').twice
104 + render!
105 + template.verify_rendered
106 + end
107 +
108 + it "should pass expect_render when a partial is expected once and happens twice" do
109 + template.expect_render(:partial => 'partial_used_twice')
110 + render!
111 + begin
112 + template.verify_rendered
113 + rescue Spec::Mocks::MockExpectationError => e
114 + ensure
115 + e.backtrace.find{|line| line =~ /view_spec_spec\.rb\:109/}.should_not be_nil
116 + end
117 + end
118 +
119 + it "should fail expect_render with the right partial but wrong options" do
120 + template.expect_render(:partial => 'partial', :locals => {:thing => Object.new})
121 + render!
122 + lambda {template.verify_rendered}.should raise_error(Spec::Mocks::MockExpectationError)
123 + end
124 + end
125 +
126 + describe "A partial that includes a partial", :type => :view do
127 + it "should support expect_render with nested partial" do
128 + obj = Object.new
129 + template.expect_render(:partial => 'partial', :object => obj)
130 + render :partial => "view_spec/partial_with_sub_partial", :locals => { :partial => obj }
131 + end
132 + end
133 +
134 + describe "A view that includes a partial using :collection and :spacer_template", :type => :view do
135 + it "should render the partial w/ spacer_tamplate" do
136 + render "view_spec/template_with_partial_using_collection"
137 + response.should have_tag('div',/method_in_partial/)
138 + response.should have_tag('div',/ApplicationHelper/)
139 + response.should have_tag('div',/ViewSpecHelper/)
140 + response.should have_tag('hr#spacer')
141 + end
142 +
143 + it "should render the partial" do
144 + template.expect_render(:partial => 'partial',
145 + :collection => ['Alice', 'Bob'],
146 + :spacer_template => 'spacer')
147 + render "view_spec/template_with_partial_using_collection"
148 + end
149 +
150 + end
151 +
152 + describe "A view that includes a partial using an array as partial_path", :type => :view do
153 + before(:each) do
154 + module ActionView::Partials
155 + def render_template_with_partial_with_array_support(partial_path, local_assigns = nil, deprecated_local_assigns = nil)
156 + if partial_path.is_a?(Array)
157 + "Array Partial"
158 + else
159 + render_partial_without_array_support(partial_path, local_assigns, deprecated_local_assigns)
160 + end
161 + end
162 +
163 + alias :render_partial_without_array_support :render_partial
164 + alias :render_partial :render_template_with_partial_with_array_support
165 + end
166 +
167 + @array = ['Alice', 'Bob']
168 + assigns[:array] = @array
169 + end
170 +
171 + after(:each) do
172 + module ActionView::Partials
173 + alias :render_template_with_partial_with_array_support :render_partial
174 + alias :render_partial :render_partial_without_array_support
175 + undef render_template_with_partial_with_array_support
176 + end
177 + end
178 +
179 + it "should render have the array passed through to render_partial without modification" do
180 + render "view_spec/template_with_partial_with_array"
181 + response.body.should match(/^Array Partial$/)
182 + end
183 + end
184 +
185 + describe "Different types of renders (not :template)", :type => :view do
186 + it "should render partial with local" do
187 + render :partial => "view_spec/partial_with_local_variable", :locals => {:x => "Ender"}
188 + response.should have_tag('div', :content => "Ender")
189 + end
190 + end
191 +
192 + describe "A view", :type => :view do
193 + before(:each) do
194 + session[:key] = "session"
195 + params[:key] = "params"
196 + flash[:key] = "flash"
197 + render "view_spec/accessor"
198 + end
199 +
200 + it "should have access to session data" do
201 + response.should have_tag("div#session", "session")
202 + end
203 +
204 + specify "should have access to params data" do
205 + response.should have_tag("div#params", "params")
206 + end
207 +
208 + it "should have access to flash data" do
209 + response.should have_tag("div#flash", "flash")
210 + end
211 + end
212 +
213 + describe "A view with a form_tag", :type => :view do
214 + it "should render the right action" do
215 + render "view_spec/entry_form"
216 + response.should have_tag("form[action=?]","/view_spec/entry_form")
217 + end
218 + end
219 +
220 + describe "An instantiated ViewExampleGroupController", :type => :view do
221 + before do
222 + render "view_spec/foo/show"
223 + end
224 +
225 + it "should return the name of the real controller that it replaces" do
226 + @controller.controller_name.should == 'foo'
227 + end
228 +
229 + it "should return the path of the real controller that it replaces" do
230 + @controller.controller_path.should == 'view_spec/foo'
231 + end
232 + end
233 +
234 + module Spec
235 + module Rails
236 + module Example
237 + describe ViewExampleGroup do
238 + it "should clear its name from the description" do
239 + group = describe("foo", :type => :view) do
240 + $nested_group = describe("bar") do
241 + end
242 + end
243 + group.description.to_s.should == "foo"
244 + $nested_group.description.to_s.should == "foo bar"
245 + end
246 +
247 + it "should clear ActionView::Base.base_view_path on teardown" do
248 + ViewExampleGroup.class_eval do
249 + alias_method(:ensure_that_base_view_path_is_not_set_across_example_groups_orig,
250 + :ensure_that_base_view_path_is_not_set_across_example_groups)
251 + define_method(:ensure_that_base_view_path_is_not_set_across_example_groups){
252 + $base_view_path_cleared = true
253 + ensure_that_base_view_path_is_not_set_across_example_groups_orig
254 + }
255 + end
256 + describe("base_view_path_cleared flag", :type => :view) do
257 + it { $base_view_path_cleared.should be_true }
258 + end
259 + end
260 + end
261 + end
262 + end
263 + end
@@ -0,0 +1,54
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 +
3 + module ActionController
4 + describe "Rescue", "#rescue_action in default mode" do
5 + before(:each) do
6 + @fixture = Object.new
7 + @fixture.extend ActionController::Rescue
8 + class << @fixture
9 + public :rescue_action
10 + end
11 + end
12 +
13 + it "should raise the passed in exception so examples fail fast" do
14 + proc {@fixture.rescue_action(RuntimeError.new("Foobar"))}.should raise_error(RuntimeError, "Foobar")
15 + end
16 + end
17 +
18 + class RescueOverriddenController < ActionController::Base
19 + def rescue_action(error)
20 + "successfully overridden"
21 + end
22 + end
23 +
24 + describe "Rescue", "#rescue_action, when overridden" do
25 + before(:each) do
26 + @fixture = RescueOverriddenController.new
27 + end
28 +
29 + it "should do whatever the overridden method does" do
30 + @fixture.rescue_action(RuntimeError.new("Foobar")).should == "successfully overridden"
31 + end
32 + end
33 +
34 + class SearchController < ActionController::Base
35 + end
36 +
37 + describe "Rescue", "#rescue_action when told to use rails error handling" do
38 + before(:each) do
39 + @controller = SearchController.new
40 + @controller.use_rails_error_handling!
41 + class << @controller
42 + public :rescue_action
43 + end
44 + end
45 +
46 + it "should use Rails exception handling" do
47 + exception = RuntimeError.new("The Error")
48 + exception.stub!(:backtrace).and_return(caller)
49 + @controller.should_receive(:rescue_action_locally).with(exception)
50 +
51 + @controller.rescue_action(exception)
52 + end
53 + end
54 + end
@@ -0,0 +1,48
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 + require 'spec/mocks/errors'
3 +
4 + describe ActionView::Base, "with RSpec extensions:", :type => :view do
5 +
6 + describe "expect_render" do
7 + it "should not raise when render has been received" do
8 + template.expect_render(:partial => "name")
9 + template.render :partial => "name"
10 + end
11 +
12 + it "should raise when render has NOT been received" do
13 + template.expect_render(:partial => "name")
14 + lambda {
15 + template.verify_rendered
16 + }.should raise_error
17 + end
18 +
19 + it "should return something (like a normal mock)" do
20 + template.expect_render(:partial => "name").and_return("Little Johnny")
21 + result = template.render :partial => "name"
22 + result.should == "Little Johnny"
23 + end
24 + end
25 +
26 + describe "stub_render" do
27 + it "should not raise when stubbing and render has been received" do
28 + template.stub_render(:partial => "name")
29 + template.render :partial => "name"
30 + end
31 +
32 + it "should not raise when stubbing and render has NOT been received" do
33 + template.stub_render(:partial => "name")
34 + end
35 +
36 + it "should not raise when stubbing and render has been received with different options" do
37 + template.stub_render(:partial => "name")
38 + template.render :partial => "view_spec/spacer"
39 + end
40 +
41 + it "should not raise when stubbing and expecting and render has been received" do
42 + template.stub_render(:partial => "name")
43 + template.expect_render(:partial => "name")
44 + template.render(:partial => "name")
45 + end
46 + end
47 +
48 + end
@@ -0,0 +1,14
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 +
3 + describe "A model" do
4 + fixtures :things
5 + it "should tell you its required fields" do
6 + Thing.new.should have(1).error_on(:name)
7 + end
8 +
9 + it "should tell you how many records it has" do
10 + Thing.should have(:no).records
11 + Thing.create(:name => "THE THING")
12 + Thing.should have(1).record
13 + end
14 + end
This diff has been collapsed as it changes many lines, (783 lines changed) Show them Hide them
@@ -0,0 +1,783
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 +
3 + # assert_select plugins for Rails
4 + #
5 + # Copyright (c) 2006 Assaf Arkin, under Creative Commons Attribution and/or MIT License
6 + # Developed for http://co.mments.com
7 + # Code and documention: http://labnotes.org
8 +
9 + class AssertSelectController < ActionController::Base
10 +
11 + def response=(content)
12 + @content = content
13 + end
14 +
15 + #NOTE - this is commented because response is implemented in lib/spec/rails/context/controller
16 + # def response(&block)
17 + # @update = block
18 + # end
19 + #
20 + def html()
21 + render :text=>@content, :layout=>false, :content_type=>Mime::HTML
22 + @content = nil
23 + end
24 +
25 + def rjs()
26 + update = @update
27 + render :update do |page|
28 + update.call page
29 + end
30 + @update = nil
31 + end
32 +
33 + def xml()
34 + render :text=>@content, :layout=>false, :content_type=>Mime::XML
35 + @content = nil
36 + end
37 +
38 + def rescue_action(e)
39 + raise e
40 + end
41 +
42 + end
43 +
44 + class AssertSelectMailer < ActionMailer::Base
45 +
46 + def test(html)
47 + recipients "test <test@test.host>"
48 + from "test@test.host"
49 + subject "Test e-mail"
50 + part :content_type=>"text/html", :body=>html
51 + end
52 +
53 + end
54 +
55 + module AssertSelectSpecHelpers
56 + def render_html(html)
57 + @controller.response = html
58 + get :html
59 + end
60 +
61 + def render_rjs(&block)
62 + clear_response
63 + @controller.response &block
64 + get :rjs
65 + end
66 +
67 + def render_xml(xml)
68 + @controller.response = xml
69 + get :xml
70 + end
71 +
72 + def first_non_rspec_line_in_backtrace_of(error)
73 + rspec_path = File.join('rspec', 'lib', 'spec')
74 + error.backtrace.reject { |line|
75 + line =~ /#{rspec_path}/
76 + }.first
77 + end
78 +
79 + private
80 + # necessary for 1.2.1
81 + def clear_response
82 + render_html("")
83 + end
84 + end
85 +
86 + unless defined?(SpecFailed)
87 + SpecFailed = Spec::Expectations::ExpectationNotMetError
88 + end
89 +
90 + describe "should have_tag", :type => :controller do
91 + include AssertSelectSpecHelpers
92 + controller_name :assert_select
93 + integrate_views
94 +
95 + it "should find specific numbers of elements" do
96 + render_html %Q{<div id="1"></div><div id="2"></div>}
97 + response.should have_tag( "div" )
98 + response.should have_tag("div", 2)
99 + lambda { response.should_not have_tag("div") }.should raise_error(SpecFailed, "should not have tag(\"div\"), but did")
100 +
101 + lambda { response.should have_tag("div", 3) }.should raise_error(SpecFailed)
102 + lambda { response.should have_tag("p") }.should raise_error(SpecFailed)
103 + end
104 +
105 + it "should expect to find elements when using true" do
106 + render_html %Q{<div id="1"></div><div id="2"></div>}
107 + response.should have_tag( "div", true )
108 + lambda { response.should have_tag( "p", true )}.should raise_error(SpecFailed)
109 + end
110 +
111 + it "should expect to not find elements when using false" do
112 + render_html %Q{<div id="1"></div><div id="2"></div>}
113 + response.should have_tag( "p", false )
114 + lambda { response.should have_tag( "div", false )}.should raise_error(SpecFailed)
115 + end
116 +
117 +
118 + it "should match submitted text using text or regexp" do
119 + render_html %Q{<div id="1">foo</div><div id="2">foo</div>}
120 + response.should have_tag("div", "foo")
121 + response.should have_tag("div", /(foo|bar)/)
122 + response.should have_tag("div", :text=>"foo")
123 + response.should have_tag("div", :text=>/(foo|bar)/)
124 +
125 + lambda { response.should have_tag("div", "bar") }.should raise_error(SpecFailed)
126 + lambda { response.should have_tag("div", :text=>"bar") }.should raise_error(SpecFailed)
127 + lambda { response.should have_tag("p", :text=>"foo") }.should raise_error(SpecFailed)
128 +
129 + lambda { response.should have_tag("div", /foobar/) }.should raise_error(SpecFailed)
130 + lambda { response.should have_tag("div", :text=>/foobar/) }.should raise_error(SpecFailed)
131 + lambda { response.should have_tag("p", :text=>/foo/) }.should raise_error(SpecFailed)
132 + end
133 +
134 + it "should use submitted message" do
135 + render_html %Q{nothing here}
136 + lambda {
137 + response.should have_tag("div", {}, "custom message")
138 + }.should raise_error(SpecFailed, /custom message/)
139 + end
140 +
141 + it "should match submitted html" do
142 + render_html %Q{<p>\n<em>"This is <strong>not</strong> a big problem,"</em> he said.\n</p>}
143 + text = "\"This is not a big problem,\" he said."
144 + html = "<em>\"This is <strong>not</strong> a big problem,\"</em> he said."
145 + response.should have_tag("p", text)
146 + lambda { response.should have_tag("p", html) }.should raise_error(SpecFailed)
147 + response.should have_tag("p", :html=>html)
148 + lambda { response.should have_tag("p", :html=>text) }.should raise_error(SpecFailed)
149 +
150 + # # No stripping for pre.
151 + render_html %Q{<pre>\n<em>"This is <strong>not</strong> a big problem,"</em> he said.\n</pre>}
152 + text = "\n\"This is not a big problem,\" he said.\n"
153 + html = "\n<em>\"This is <strong>not</strong> a big problem,\"</em> he said.\n"
154 + response.should have_tag("pre", text)
155 + lambda { response.should have_tag("pre", html) }.should raise_error(SpecFailed)
156 + response.should have_tag("pre", :html=>html)
157 + lambda { response.should have_tag("pre", :html=>text) }.should raise_error(SpecFailed)
158 + end
159 +
160 + it "should match number of instances" do
161 + render_html %Q{<div id="1">foo</div><div id="2">foo</div>}
162 + response.should have_tag("div", 2)
163 + lambda { response.should have_tag("div", 3) }.should raise_error(SpecFailed)
164 + response.should have_tag("div", 1..2)
165 + lambda { response.should have_tag("div", 3..4) }.should raise_error(SpecFailed)
166 + response.should have_tag("div", :count=>2)
167 + lambda { response.should have_tag("div", :count=>3) }.should raise_error(SpecFailed)
168 + response.should have_tag("div", :minimum=>1)
169 + response.should have_tag("div", :minimum=>2)
170 + lambda { response.should have_tag("div", :minimum=>3) }.should raise_error(SpecFailed)
171 + response.should have_tag("div", :maximum=>2)
172 + response.should have_tag("div", :maximum=>3)
173 + lambda { response.should have_tag("div", :maximum=>1) }.should raise_error(SpecFailed)
174 + response.should have_tag("div", :minimum=>1, :maximum=>2)
175 + lambda { response.should have_tag("div", :minimum=>3, :maximum=>4) }.should raise_error(SpecFailed)
176 + end
177 +
178 + it "substitution values" do
179 + render_html %Q{<div id="1">foo</div><div id="2">foo</div><span id="3"></span>}
180 + response.should have_tag("div#?", /\d+/) do |elements| #using do/end
181 + elements.size.should == 2
182 + end
183 + response.should have_tag("div#?", /\d+/) { |elements| #using {}
184 + elements.size.should == 2
185 + }
186 + lambda {
187 + response.should have_tag("div#?", /\d+/) do |elements|
188 + elements.size.should == 3
189 + end
190 + }.should raise_error(SpecFailed, "expected: 3,\n got: 2 (using ==)")
191 +
192 + lambda {
193 + response.should have_tag("div#?", /\d+/) { |elements|
194 + elements.size.should == 3
195 + }
196 + }.should raise_error(SpecFailed, "expected: 3,\n got: 2 (using ==)")
197 +
198 + response.should have_tag("div#?", /\d+/) do |elements|
199 + elements.size.should == 2
200 + with_tag("#1")
201 + with_tag("#2")
202 + without_tag("#3")
203 + end
204 + end
205 +
206 + #added for RSpec
207 + it "nested tags in form" do
208 + render_html %Q{
209 + <form action="test">
210 + <input type="text" name="email">
211 + </form>
212 + <form action="other">
213 + <input type="text" name="other_input">
214 + </form>
215 + }
216 + response.should have_tag("form[action=test]") { |form|
217 + with_tag("input[type=text][name=email]")
218 + }
219 + response.should have_tag("form[action=test]") { |form|
220 + with_tag("input[type=text][name=email]")
221 + }
222 +
223 + lambda {
224 + response.should have_tag("form[action=test]") { |form|
225 + with_tag("input[type=text][name=other_input]")
226 + }
227 + }.should raise_error(SpecFailed)
228 +
229 + lambda {
230 + response.should have_tag("form[action=test]") {
231 + with_tag("input[type=text][name=other_input]")
232 + }
233 + }.should raise_error(SpecFailed)
234 + end
235 +
236 + it "should report the correct line number for a nested failed expectation" do
237 + render_html %Q{
238 + <form action="test">
239 + <input type="text" name="email">
240 + </form>
241 + }
242 + begin
243 + response.should have_tag("form[action=test]") {
244 + @expected_error_line = __LINE__; should have_tag("input[type=text][name=other_input]")
245 + }
246 + rescue => e
247 + first_non_rspec_line_in_backtrace_of(e).should =~
248 + /#{File.basename(__FILE__)}:#{@expected_error_line}/
249 + else
250 + fail
251 + end
252 + end
253 +
254 + it "should report the correct line number for a nested raised exception" do
255 + render_html %Q{
256 + <form action="test">
257 + <input type="text" name="email">
258 + </form>
259 + }
260 + begin
261 + response.should have_tag("form[action=test]") {
262 + @expected_error_line = __LINE__; raise "Failed!"
263 + }
264 + rescue => e
265 + first_non_rspec_line_in_backtrace_of(e).should =~
266 + /#{File.basename(__FILE__)}:#{@expected_error_line}/
267 + else
268 + fail
269 + end
270 + end
271 +
272 + it "should report the correct line number for a nested failed test/unit assertion" do
273 + pending "Doesn't work at the moment. Do we want to support this?" do
274 + render_html %Q{
275 + <form action="test">
276 + <input type="text" name="email">
277 + </form>
278 + }
279 + begin
280 + response.should have_tag("form[action=test]") {
281 + @expected_error_line = __LINE__; assert false
282 + }
283 + rescue => e
284 + first_non_rspec_line_in_backtrace_of(e).should =~
285 + /#{File.basename(__FILE__)}:#{@expected_error_line}/
286 + else
287 + fail
288 + end
289 + end
290 + end
291 +
292 +
293 + it "beatles" do
294 + unless defined?(BEATLES)
295 + BEATLES = [
296 + ["John", "Guitar"],
297 + ["George", "Guitar"],
298 + ["Paul", "Bass"],
299 + ["Ringo", "Drums"]
300 + ]
301 + end
302 +
303 + render_html %Q{
304 + <div id="beatles">
305 + <div class="beatle">
306 + <h2>John</h2><p>Guitar</p>
307 + </div>
308 + <div class="beatle">
309 + <h2>George</h2><p>Guitar</p>
310 + </div>
311 + <div class="beatle">
312 + <h2>Paul</h2><p>Bass</p>
313 + </div>
314 + <div class="beatle">
315 + <h2>Ringo</h2><p>Drums</p>
316 + </div>
317 + </div>
318 + }
319 + response.should have_tag("div#beatles>div[class=\"beatle\"]", 4)
320 +
321 + response.should have_tag("div#beatles>div.beatle") {
322 + BEATLES.each { |name, instrument|
323 + with_tag("div.beatle>h2", name)
324 + with_tag("div.beatle>p", instrument)
325 + without_tag("div.beatle>span")
326 + }
327 + }
328 + end
329 +
330 + it "assert_select_text_match" do
331 + render_html %Q{<div id="1"><span>foo</span></div><div id="2"><span>bar</span></div>}
332 + response.should have_tag("div") do |divs|
333 + with_tag("div", "foo")
334 + with_tag("div", "bar")
335 + with_tag("div", /\w*/)
336 + with_tag("div", /\w*/, :count=>2)
337 + without_tag("div", :text=>"foo", :count=>2)
338 + with_tag("div", :html=>"<span>bar</span>")
339 + with_tag("div", :html=>"<span>bar</span>")
340 + with_tag("div", :html=>/\w*/)
341 + with_tag("div", :html=>/\w*/, :count=>2)
342 + without_tag("div", :html=>"<span>foo</span>", :count=>2)
343 + end
344 + end
345 +
346 +
347 + it "assert_select_from_rjs with one item" do
348 + render_rjs do |page|
349 + page.replace_html "test", "<div id=\"1\">foo</div>\n<div id=\"2\">foo</div>"
350 + end
351 + response.should have_tag("div") { |elements|
352 + elements.size.should == 2
353 + with_tag("#1")
354 + with_tag("#2")
355 + }
356 +
357 + lambda {
358 + response.should have_tag("div") { |elements|
359 + elements.size.should == 2
360 + with_tag("#1")
361 + with_tag("#3")
362 + }
363 + }.should raise_error(SpecFailed)
364 +
365 + lambda {
366 + response.should have_tag("div") { |elements|
367 + elements.size.should == 2
368 + with_tag("#1")
369 + without_tag("#2")
370 + }
371 + }.should raise_error(SpecFailed, "should not have tag(\"#2\"), but did")
372 +
373 + lambda {
374 + response.should have_tag("div") { |elements|
375 + elements.size.should == 3
376 + with_tag("#1")
377 + with_tag("#2")
378 + }
379 + }.should raise_error(SpecFailed)
380 +
381 +
382 + response.should have_tag("div#?", /\d+/) { |elements|
383 + with_tag("#1")
384 + with_tag("#2")
385 + }
386 + end
387 +
388 + it "assert_select_from_rjs with multiple items" do
389 + render_rjs do |page|
390 + page.replace_html "test", "<div id=\"1\">foo</div>"
391 + page.replace_html "test2", "<div id=\"2\">foo</div>"
392 + end
393 + response.should have_tag("div")
394 + response.should have_tag("div") { |elements|
395 + elements.size.should == 2
396 + with_tag("#1")
397 + with_tag("#2")
398 + }
399 +
400 + lambda {
401 + response.should have_tag("div") { |elements|
402 + with_tag("#3")
403 + }
404 + }.should raise_error(SpecFailed)
405 + end
406 + end
407 +
408 + describe "css_select", :type => :controller do
409 + include AssertSelectSpecHelpers
410 + controller_name :assert_select
411 + integrate_views
412 +
413 + it "can select tags from html" do
414 + render_html %Q{<div id="1"></div><div id="2"></div>}
415 + css_select("div").size.should == 2
416 + css_select("p").size.should == 0
417 + end
418 +
419 +
420 + it "can select nested tags from html" do
421 + render_html %Q{<div id="1">foo</div><div id="2">foo</div>}
422 + response.should have_tag("div#?", /\d+/) { |elements|
423 + css_select(elements[0], "div").should have(1).element
424 + css_select(elements[1], "div").should have(1).element
425 + }
426 + response.should have_tag("div") {
427 + css_select("div").should have(2).elements
428 + css_select("div").each { |element|
429 + # Testing as a group is one thing
430 + css_select("#1,#2").should have(2).elements
431 + # Testing individually is another
432 + css_select("#1").should have(1).element
433 + css_select("#2").should have(1).element
434 + }
435 + }
436 + end
437 +
438 + it "can select nested tags from rjs (one result)" do
439 + render_rjs do |page|
440 + page.replace_html "test", "<div id=\"1\">foo</div>\n<div id=\"2\">foo</div>"
441 + end
442 + css_select("div").should have(2).elements
443 + css_select("#1").should have(1).element
444 + css_select("#2").should have(1).element
445 + end
446 +
447 + it "can select nested tags from rjs (two results)" do
448 + render_rjs do |page|
449 + page.replace_html "test", "<div id=\"1\">foo</div>"
450 + page.replace_html "test2", "<div id=\"2\">foo</div>"
451 + end
452 + css_select("div").should have(2).elements
453 + css_select("#1").should have(1).element
454 + css_select("#2").should have(1).element
455 + end
456 +
457 + end
458 +
459 + describe "have_rjs behaviour_type", :type => :controller do
460 + include AssertSelectSpecHelpers
461 + controller_name :assert_select
462 + integrate_views
463 +
464 + before(:each) do
465 + render_rjs do |page|
466 + page.replace "test1", "<div id=\"1\">foo</div>"
467 + page.replace_html "test2", "<div id=\"2\">bar</div><div id=\"3\">none</div>"
468 + page.insert_html :top, "test3", "<div id=\"4\">loopy</div>"
469 + page.hide "test4"
470 + page["test5"].hide
471 + end
472 + end
473 +
474 + it "should pass if any rjs exists" do
475 + response.should have_rjs
476 + end
477 +
478 + it "should fail if no rjs exists" do
479 + render_rjs do |page|
480 + end
481 + lambda do
482 + response.should have_rjs
483 + end.should raise_error(SpecFailed)
484 + end
485 +
486 + it "should find all rjs from multiple statements" do
487 + response.should have_rjs do
488 + with_tag("#1")
489 + with_tag("#2")
490 + with_tag("#3")
491 + # with_tag("#4")
492 + # with_tag("#5")
493 + end
494 + end
495 +
496 + it "should find by id" do
497 + response.should have_rjs("test1") { |rjs|
498 + rjs.size.should == 1
499 + with_tag("div", 1)
500 + with_tag("div#1", "foo")
501 + }
502 +
503 + lambda do
504 + response.should have_rjs("test1") { |rjs|
505 + rjs.size.should == 1
506 + without_tag("div#1", "foo")
507 + }
508 + end.should raise_error(SpecFailed, "should not have tag(\"div#1\", \"foo\"), but did")
509 +
510 + response.should have_rjs("test2") { |rjs|
511 + rjs.size.should == 2
512 + with_tag("div", 2)
513 + with_tag("div#2", "bar")
514 + with_tag("div#3", "none")
515 + }
516 + # response.should have_rjs("test4")
517 + # response.should have_rjs("test5")
518 + end
519 +
520 + # specify "should find rjs using :hide" do
521 + # response.should have_rjs(:hide)
522 + # response.should have_rjs(:hide, "test4")
523 + # response.should have_rjs(:hide, "test5")
524 + # lambda do
525 + # response.should have_rjs(:hide, "test3")
526 + # end.should raise_error(SpecFailed)
527 + # end
528 +
529 + it "should find rjs using :replace" do
530 + response.should have_rjs(:replace) { |rjs|
531 + with_tag("div", 1)
532 + with_tag("div#1", "foo")
533 + }
534 + response.should have_rjs(:replace, "test1") { |rjs|
535 + with_tag("div", 1)
536 + with_tag("div#1", "foo")
537 + }
538 + lambda {
539 + response.should have_rjs(:replace, "test2")
540 + }.should raise_error(SpecFailed)
541 +
542 + lambda {
543 + response.should have_rjs(:replace, "test3")
544 + }.should raise_error(SpecFailed)
545 + end
546 +
547 + it "should find rjs using :replace_html" do
548 + response.should have_rjs(:replace_html) { |rjs|
549 + with_tag("div", 2)
550 + with_tag("div#2", "bar")
551 + with_tag("div#3", "none")
552 + }
553 +
554 + response.should have_rjs(:replace_html, "test2") { |rjs|
555 + with_tag("div", 2)
556 + with_tag("div#2", "bar")
557 + with_tag("div#3", "none")
558 + }
559 +
560 + lambda {
561 + response.should have_rjs(:replace_html, "test1")
562 + }.should raise_error(SpecFailed)
563 +
564 + lambda {
565 + response.should have_rjs(:replace_html, "test3")
566 + }.should raise_error(SpecFailed)
567 + end
568 +
569 + it "should find rjs using :insert_html (non-positioned)" do
570 + response.should have_rjs(:insert_html) { |rjs|
571 + with_tag("div", 1)
572 + with_tag("div#4", "loopy")
573 + }
574 +
575 + response.should have_rjs(:insert_html, "test3") { |rjs|
576 + with_tag("div", 1)
577 + with_tag("div#4", "loopy")
578 + }
579 +
580 + lambda {
581 + response.should have_rjs(:insert_html, "test1")
582 + }.should raise_error(SpecFailed)
583 +
584 + lambda {
585 + response.should have_rjs(:insert_html, "test2")
586 + }.should raise_error(SpecFailed)
587 + end
588 +
589 + it "should find rjs using :insert (positioned)" do
590 + render_rjs do |page|
591 + page.insert_html :top, "test1", "<div id=\"1\">foo</div>"
592 + page.insert_html :bottom, "test2", "<div id=\"2\">bar</div>"
593 + page.insert_html :before, "test3", "<div id=\"3\">none</div>"
594 + page.insert_html :after, "test4", "<div id=\"4\">loopy</div>"
595 + end
596 + response.should have_rjs(:insert, :top) do
597 + with_tag("div", 1)
598 + with_tag("#1")
599 + end
600 + response.should have_rjs(:insert, :top, "test1") do
601 + with_tag("div", 1)
602 + with_tag("#1")
603 + end
604 + lambda {
605 + response.should have_rjs(:insert, :top, "test2")
606 + }.should raise_error(SpecFailed)
607 + response.should have_rjs(:insert, :bottom) {|rjs|
608 + with_tag("div", 1)
609 + with_tag("#2")
610 + }
611 + response.should have_rjs(:insert, :bottom, "test2") {|rjs|
612 + with_tag("div", 1)
613 + with_tag("#2")
614 + }
615 + response.should have_rjs(:insert, :before) {|rjs|
616 + with_tag("div", 1)
617 + with_tag("#3")
618 + }
619 + response.should have_rjs(:insert, :before, "test3") {|rjs|
620 + with_tag("div", 1)
621 + with_tag("#3")
622 + }
623 + response.should have_rjs(:insert, :after) {|rjs|
624 + with_tag("div", 1)
625 + with_tag("#4")
626 + }
627 + response.should have_rjs(:insert, :after, "test4") {|rjs|
628 + with_tag("div", 1)
629 + with_tag("#4")
630 + }
631 + end
632 + end
633 +
634 + describe "send_email behaviour_type", :type => :controller do
635 + include AssertSelectSpecHelpers
636 + controller_name :assert_select
637 + integrate_views
638 +
639 + before(:each) do
640 + ActionMailer::Base.delivery_method = :test
641 + ActionMailer::Base.perform_deliveries = true
642 + ActionMailer::Base.deliveries = []
643 + end
644 +
645 + after(:each) do
646 + ActionMailer::Base.deliveries.clear
647 + end
648 +
649 + it "should fail with nothing sent" do
650 + response.should_not send_email
651 + lambda {
652 + response.should send_email{}
653 + }.should raise_error(SpecFailed, /No e-mail in delivery list./)
654 + end
655 +
656 + it "should pass otherwise" do
657 + AssertSelectMailer.deliver_test "<div><p>foo</p><p>bar</p></div>"
658 + response.should send_email
659 + lambda {
660 + response.should_not send_email
661 + }.should raise_error(SpecFailed)
662 + response.should send_email{}
663 + response.should send_email {
664 + with_tag("div:root") {
665 + with_tag("p:first-child", "foo")
666 + with_tag("p:last-child", "bar")
667 + }
668 + }
669 +
670 + lambda {
671 + response.should_not send_email
672 + }.should raise_error(SpecFailed, "should not send email, but did")
673 + end
674 +
675 + end
676 +
677 + # describe "An rjs call to :visual_effect, a 'should have_rjs' spec with",
678 + # :type => :view do
679 + #
680 + # before do
681 + # render 'rjs_spec/visual_effect'
682 + # end
683 + #
684 + # it "should pass with the correct element name" do
685 + # response.should have_rjs(:effect, :fade, 'mydiv')
686 + # end
687 + #
688 + # it "should fail the wrong element name" do
689 + # lambda {
690 + # response.should have_rjs(:effect, :fade, 'wrongname')
691 + # }.should raise_error(SpecFailed)
692 + # end
693 + #
694 + # it "should fail with the correct element but the wrong command" do
695 + # lambda {
696 + # response.should have_rjs(:effect, :puff, 'mydiv')
697 + # }.should raise_error(SpecFailed)
698 + # end
699 + #
700 + # end
701 + #
702 + # describe "An rjs call to :visual_effect for a toggle, a 'should have_rjs' spec with",
703 + # :type => :view do
704 + #
705 + # before do
706 + # render 'rjs_spec/visual_toggle_effect'
707 + # end
708 + #
709 + # it "should pass with the correct element name" do
710 + # response.should have_rjs(:effect, :toggle_blind, 'mydiv')
711 + # end
712 + #
713 + # it "should fail with the wrong element name" do
714 + # lambda {
715 + # response.should have_rjs(:effect, :toggle_blind, 'wrongname')
716 + # }.should raise_error(SpecFailed)
717 + # end
718 + #
719 + # it "should fail the correct element but the wrong command" do
720 + # lambda {
721 + # response.should have_rjs(:effect, :puff, 'mydiv')
722 + # }.should raise_error(SpecFailed)
723 + # end
724 + #
725 + # end
726 +
727 + describe "string.should have_tag", :type => :helper do
728 + include AssertSelectSpecHelpers
729 +
730 + it "should find root element" do
731 + "<p>a paragraph</p>".should have_tag("p", "a paragraph")
732 + end
733 +
734 + it "should not find non-existent element" do
735 + lambda do
736 + "<p>a paragraph</p>".should have_tag("p", "wrong text")
737 + end.should raise_error(SpecFailed)
738 + end
739 +
740 + it "should find child element" do
741 + "<div><p>a paragraph</p></div>".should have_tag("p", "a paragraph")
742 + end
743 +
744 + it "should find nested element" do
745 + "<div><p>a paragraph</p></div>".should have_tag("div") do
746 + with_tag("p", "a paragraph")
747 + end
748 + end
749 +
750 + it "should not find wrong nested element" do
751 + lambda do
752 + "<div><p>a paragraph</p></div>".should have_tag("div") do
753 + with_tag("p", "wrong text")
754 + end
755 + end.should raise_error(SpecFailed)
756 + end
757 + end
758 +
759 + describe "have_tag", :type => :controller do
760 + include AssertSelectSpecHelpers
761 + controller_name :assert_select
762 + integrate_views
763 +
764 + it "should work exactly the same as assert_select" do
765 + render_html %Q{
766 + <div id="wrapper">foo
767 + <div class="piece">
768 + <h3>Text</h3>
769 + </div>
770 + <div class="piece">
771 + <h3>Another</h3>
772 + </div>
773 + </div>
774 + }
775 +
776 + assert_select "#wrapper .piece h3", :text => "Text"
777 + assert_select "#wrapper .piece h3", :text => "Another"
778 +
779 + response.should have_tag("#wrapper .piece h3", :text => "Text")
780 + response.should have_tag("#wrapper .piece h3", :text => "Another")
781 + end
782 + end
783 +
@@ -0,0 +1,37
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 +
3 + class DescriptionGenerationSpecController < ActionController::Base
4 + def render_action
5 + end
6 +
7 + def redirect_action
8 + redirect_to :action => :render_action
9 + end
10 + end
11 +
12 + describe "Description generation", :type => :controller do
13 + controller_name :description_generation_spec
14 +
15 + after(:each) do
16 + Spec::Matchers.clear_generated_description
17 + end
18 +
19 + it "should generate description for render_template" do
20 + get 'render_action'
21 + response.should render_template("render_action")
22 + Spec::Matchers.generated_description.should == "should render template \"render_action\""
23 + end
24 +
25 + it "should generate description for render_template with full path" do
26 + get 'render_action'
27 + response.should render_template("description_generation_spec/render_action")
28 + Spec::Matchers.generated_description.should == "should render template \"description_generation_spec/render_action\""
29 + end
30 +
31 + it "should generate description for redirect_to" do
32 + get 'redirect_action'
33 + response.should redirect_to("http://test.host/description_generation_spec/render_action")
34 + Spec::Matchers.generated_description.should == "should redirect to \"http://test.host/description_generation_spec/render_action\""
35 + end
36 +
37 + end
@@ -0,0 +1,13
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 +
3 + describe "error_on" do
4 + it "should provide a message including the name of what the error is on" do
5 + have(1).error_on(:whatever).description.should == "should have 1 error on :whatever"
6 + end
7 + end
8 +
9 + describe "errors_on" do
10 + it "should provide a message including the name of what the error is on" do
11 + have(2).errors_on(:whatever).description.should == "should have 2 errors on :whatever"
12 + end
13 + end
@@ -0,0 +1,62
1 + require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2 +
3 + describe "have_text" do
4 +
5 + describe "where target is a Regexp" do
6 + it 'should should match submitted text using a regexp' do
7 + string = 'foo'
8 + string.should have_text(/fo*/)
9 + end
10 + end
11 +
12 + describe "where target is a String" do
13 + it 'should match submitted text using a string' do
14 + string = 'foo'
15 + string.should have_text('foo')
16 + end
17 + end
18 +
19 + end
20 +
21 + describe "have_text",
22 + :type => :controller do
23 + ['isolation','integration'].each do |mode|
24 + if mode == 'integration'
25 + integrate_views
26 + end
27 +
28 + describe "where target is a response (in #{mode} mode)" do
29 + controller_name :render_spec
30 +
31 + it "should pass with exactly matching text" do
32 + post 'text_action'
33 + response.should have_text("this is the text for this action")
34 + end
35 +
36 + it "should pass with matching text (using Regexp)" do
37 + post 'text_action'
38 + response.should have_text(/is the text/)
39 + end
40 +
41 + it "should fail with matching text" do
42 + post 'text_action'
43 + lambda {
44 + response.should have_text("this is NOT the text for this action")
45 + }.should fail_with("expected \"this is NOT the text for this action\", got \"this is the text for this action\"")
46 + end
47 +
48 + it "should fail when a template is rendered" do
49 + post 'some_action'
50 + lambda {
51 + response.should have_text("this is the text for this action")
52 + }.should fail_with(/expected \"this is the text for this action\", got .*/)
53 + end
54 +
55 + it "should pass using should_not with incorrect text" do
56 + post 'text_action'
57 + response.should_not have_text("the accordian guy")
58 + end
59 + end
60 + end
61 + end
62 +
@@ -0,0 +1,203
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 +
3 + ['isolation','integration'].each do |mode|
4 + describe "redirect_to behaviour", :type => :controller do
5 + if mode == 'integration'
6 + integrate_views
7 + end
8 + controller_name :redirect_spec
9 +
10 + it "redirected to another action" do
11 + get 'action_with_redirect_to_somewhere'
12 + response.should redirect_to(:action => 'somewhere')
13 + end
14 +
15 + it "redirected to another controller and action" do
16 + get 'action_with_redirect_to_other_somewhere'
17 + response.should redirect_to(:controller => 'render_spec', :action => 'text_action')
18 + end
19 +
20 + it "redirected to another action (with 'and return')" do
21 + get 'action_with_redirect_to_somewhere_and_return'
22 + response.should redirect_to(:action => 'somewhere')
23 + end
24 +
25 + it "redirected to correct path with leading /" do
26 + get 'action_with_redirect_to_somewhere'
27 + response.should redirect_to('/redirect_spec/somewhere')
28 + end
29 +
30 + it "redirected to correct path without leading /" do
31 + get 'action_with_redirect_to_somewhere'
32 + response.should redirect_to('redirect_spec/somewhere')
33 + end
34 +
35 + it "redirected to correct internal URL" do
36 + get 'action_with_redirect_to_somewhere'
37 + response.should redirect_to("http://test.host/redirect_spec/somewhere")
38 + end
39 +
40 + it "redirected to correct external URL" do
41 + get 'action_with_redirect_to_rspec_site'
42 + response.should redirect_to("http://rspec.rubyforge.org")
43 + end
44 +
45 + it "redirected :back" do
46 + request.env['HTTP_REFERER'] = "http://test.host/previous/page"
47 + get 'action_with_redirect_back'
48 + response.should redirect_to(:back)
49 + end
50 +
51 + it "redirected :back and should redirect_to URL matches" do
52 + request.env['HTTP_REFERER'] = "http://test.host/previous/page"
53 + get 'action_with_redirect_back'
54 + response.should redirect_to("http://test.host/previous/page")
55 + end
56 +
57 + it "redirected from within a respond_to block" do
58 + get 'action_with_redirect_in_respond_to'
59 + response.should redirect_to('redirect_spec/somewhere')
60 + end
61 +
62 + params_as_hash = {:action => "somewhere", :id => 1111, :param1 => "value1", :param2 => "value2"}
63 +
64 + it "redirected to an internal URL containing a query string" do
65 + get "action_with_redirect_which_creates_query_string"
66 + response.should redirect_to(params_as_hash)
67 + end
68 +
69 + it "redirected to an internal URL containing a query string, one way it might be generated" do
70 + get "action_with_redirect_with_query_string_order1"
71 + response.should redirect_to(params_as_hash)
72 + end
73 +
74 + it "redirected to an internal URL containing a query string, another way it might be generated" do
75 + get "action_with_redirect_with_query_string_order2"
76 + response.should redirect_to(params_as_hash)
77 + end
78 +
79 + it "redirected to an internal URL which is unroutable but matched via a string" do
80 + get "action_with_redirect_to_unroutable_url_inside_app"
81 + response.should redirect_to("http://test.host/nonexistant/none")
82 + end
83 +
84 + end
85 +
86 +
87 + describe "redirect_to with a controller spec in #{mode} mode and a custom request.host", :type => :controller do
88 + if mode == 'integration'
89 + integrate_views
90 + end
91 + controller_name :redirect_spec
92 + before do
93 + request.host = "some.custom.host"
94 + end
95 +
96 + it "should pass when redirected to another action" do
97 + get 'action_with_redirect_to_somewhere'
98 + response.should redirect_to(:action => 'somewhere')
99 + end
100 + end
101 +
102 + describe "Given a controller spec in #{mode} mode", :type => :controller do
103 + if mode == 'integration'
104 + integrate_views
105 + end
106 + controller_name :redirect_spec
107 +
108 + it "an action that redirects should not result in an error if no should redirect_to expectation is called" do
109 + get 'action_with_redirect_to_somewhere'
110 + end
111 +
112 + it "an action that redirects should not result in an error if should_not redirect_to expectation was called, but not to that action" do
113 + get 'action_with_redirect_to_somewhere'
114 + response.should_not redirect_to(:action => 'another_destination')
115 + end
116 +
117 + it "an action that redirects should result in an error if should_not redirect_to expectation was called to that action" do
118 + get 'action_with_redirect_to_somewhere'
119 + lambda {
120 + response.should_not redirect_to(:action => 'somewhere')
121 + }.should fail_with("expected not to be redirected to {:action=>\"somewhere\"}, but was")
122 + end
123 +
124 + it "an action that does not redirects should not result in an error if should_not redirect_to expectation was called" do
125 + get 'action_with_no_redirect'
126 + response.should_not redirect_to(:action => 'any_destination')
127 + end
128 +
129 +
130 + end
131 +
132 + describe "Given a controller spec in #{mode} mode, should redirect_to should fail when", :type => :controller do
133 + if mode == 'integration'
134 + integrate_views
135 + end
136 + controller_name :redirect_spec
137 +
138 + it "redirected to wrong action" do
139 + get 'action_with_redirect_to_somewhere'
140 + lambda {
141 + response.should redirect_to(:action => 'somewhere_else')
142 + }.should fail_with("expected redirect to {:action=>\"somewhere_else\"}, got redirect to \"http://test.host/redirect_spec/somewhere\"")
143 + end
144 +
145 + it "redirected to incorrect path with leading /" do
146 + get 'action_with_redirect_to_somewhere'
147 + lambda {
148 + response.should redirect_to('/redirect_spec/somewhere_else')
149 + }.should fail_with('expected redirect to "/redirect_spec/somewhere_else", got redirect to "http://test.host/redirect_spec/somewhere"')
150 + end
151 +
152 + it "redirected to incorrect path without leading /" do
153 + get 'action_with_redirect_to_somewhere'
154 + lambda {
155 + response.should redirect_to('redirect_spec/somewhere_else')
156 + }.should fail_with('expected redirect to "redirect_spec/somewhere_else", got redirect to "http://test.host/redirect_spec/somewhere"')
157 + end
158 +
159 + it "redirected to incorrect internal URL (based on the action)" do
160 + get 'action_with_redirect_to_somewhere'
161 + lambda {
162 + response.should redirect_to("http://test.host/redirect_spec/somewhere_else")
163 + }.should fail_with('expected redirect to "http://test.host/redirect_spec/somewhere_else", got redirect to "http://test.host/redirect_spec/somewhere"')
164 + end
165 +
166 + it "redirected to wrong external URL" do
167 + get 'action_with_redirect_to_rspec_site'
168 + lambda {
169 + response.should redirect_to("http://test.unit.rubyforge.org")
170 + }.should fail_with('expected redirect to "http://test.unit.rubyforge.org", got redirect to "http://rspec.rubyforge.org"')
171 + end
172 +
173 + it "redirected to incorrect internal URL (based on the directory path)" do
174 + get 'action_with_redirect_to_somewhere'
175 + lambda {
176 + response.should redirect_to("http://test.host/non_existent_controller/somewhere")
177 + }.should fail_with('expected redirect to "http://test.host/non_existent_controller/somewhere", got redirect to "http://test.host/redirect_spec/somewhere"')
178 + end
179 +
180 + it "expected redirect :back, but redirected to a new URL" do
181 + get 'action_with_no_redirect'
182 + lambda {
183 + response.should redirect_to(:back)
184 + }.should fail_with('expected redirect to :back, got no redirect')
185 + end
186 +
187 + it "no redirect at all" do
188 + get 'action_with_no_redirect'
189 + lambda {
190 + response.should redirect_to(:action => 'nowhere')
191 + }.should fail_with("expected redirect to {:action=>\"nowhere\"}, got no redirect")
192 + end
193 +
194 + it "redirected to an internal URL which is unroutable and matched via a hash" do
195 + get "action_with_redirect_to_unroutable_url_inside_app"
196 + route = {:controller => "nonexistant", :action => "none"}
197 + lambda {
198 + response.should redirect_to(route)
199 + }.should raise_error(ActionController::RoutingError, /(no route found to match|No route matches) \"\/nonexistant\/none\" with \{\}/)
200 + end
201 +
202 + end
203 + end
@@ -0,0 +1,169
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 +
3 + ['isolation','integration'].each do |mode|
4 + describe "response.should render_template (in #{mode} mode)",
5 + :type => :controller do
6 + controller_name :render_spec
7 + if mode == 'integration'
8 + integrate_views
9 + end
10 +
11 + it "should match a simple path" do
12 + post 'some_action'
13 + response.should render_template('some_action')
14 + end
15 +
16 + it "should match a less simple path" do
17 + post 'some_action'
18 + response.should render_template('render_spec/some_action')
19 + end
20 +
21 + it "should match a less simple path to another controller" do
22 + post 'action_which_renders_template_from_other_controller'
23 + response.should render_template('controller_spec/action_with_template')
24 + end
25 +
26 + it "should match a symbol" do
27 + post 'some_action'
28 + response.should render_template(:some_action)
29 + end
30 +
31 + it "should match an rjs template" do
32 + xhr :post, 'some_action'
33 + if Rails::VERSION::STRING < "2.0.0"
34 + response.should render_template('render_spec/some_action.rjs')
35 + else
36 + response.should render_template('render_spec/some_action')
37 + end
38 + end
39 +
40 + it "should match a partial template (simple path)" do
41 + get 'action_with_partial'
42 + response.should render_template("_a_partial")
43 + end
44 +
45 + it "should match a partial template (complex path)" do
46 + get 'action_with_partial'
47 + response.should render_template("render_spec/_a_partial")
48 + end
49 +
50 + it "should fail when the wrong template is rendered" do
51 + post 'some_action'
52 + lambda do
53 + response.should render_template('non_existent_template')
54 + end.should fail_with("expected \"non_existent_template\", got \"render_spec/some_action\"")
55 + end
56 +
57 + it "should fail without full path when template is associated with a different controller" do
58 + post 'action_which_renders_template_from_other_controller'
59 + lambda do
60 + response.should render_template('action_with_template')
61 + end.should fail_with(%Q|expected "action_with_template", got "controller_spec/action_with_template"|)
62 + end
63 +
64 + it "should fail with incorrect full path when template is associated with a different controller" do
65 + post 'action_which_renders_template_from_other_controller'
66 + lambda do
67 + response.should render_template('render_spec/action_with_template')
68 + end.should fail_with(%Q|expected "render_spec/action_with_template", got "controller_spec/action_with_template"|)
69 + end
70 +
71 + it "should fail on the wrong extension (given rhtml)" do
72 + get 'some_action'
73 + lambda {
74 + response.should render_template('render_spec/some_action.rjs')
75 + }.should fail_with("expected \"render_spec/some_action.rjs\", got \"render_spec/some_action\"")
76 + end
77 +
78 + it "should fail when TEXT is rendered" do
79 + post 'text_action'
80 + lambda do
81 + response.should render_template('some_action')
82 + end.should fail_with("expected \"some_action\", got nil")
83 + end
84 + end
85 +
86 + describe "response.should_not render_template (in #{mode} mode)",
87 + :type => :controller do
88 + controller_name :render_spec
89 + if mode == 'integration'
90 + integrate_views
91 + end
92 +
93 + it "should pass when the action renders nothing" do
94 + post 'action_that_renders_nothing'
95 + response.should_not render_template('action_that_renders_nothing')
96 + end
97 +
98 + it "should pass when the action renders nothing (symbol)" do
99 + post 'action_that_renders_nothing'
100 + response.should_not render_template(:action_that_renders_nothing)
101 + end
102 +
103 + it "should pass when the action does not render the template" do
104 + post 'some_action'
105 + response.should_not render_template('some_other_template')
106 + end
107 +
108 + it "should pass when the action does not render the template (symbol)" do
109 + post 'some_action'
110 + response.should_not render_template(:some_other_template)
111 + end
112 +
113 + it "should pass when the action does not render the template (named with controller)" do
114 + post 'some_action'
115 + response.should_not render_template('render_spec/some_other_template')
116 + end
117 +
118 + it "should pass when the action renders the template with a different controller" do
119 + post 'action_which_renders_template_from_other_controller'
120 + response.should_not render_template('action_with_template')
121 + end
122 +
123 + it "should pass when the action renders the template (named with controller) with a different controller" do
124 + post 'action_which_renders_template_from_other_controller'
125 + response.should_not render_template('render_spec/action_with_template')
126 + end
127 +
128 + it "should pass when TEXT is rendered" do
129 + post 'text_action'
130 + response.should_not render_template('some_action')
131 + end
132 +
133 + it "should fail when the action renders the template" do
134 + post 'some_action'
135 + lambda do
136 + response.should_not render_template('some_action')
137 + end.should fail_with("expected not to render \"some_action\", but did")
138 + end
139 +
140 + it "should fail when the action renders the template (symbol)" do
141 + post 'some_action'
142 + lambda do
143 + response.should_not render_template(:some_action)
144 + end.should fail_with("expected not to render \"some_action\", but did")
145 + end
146 +
147 + it "should fail when the action renders the template (named with controller)" do
148 + post 'some_action'
149 + lambda do
150 + response.should_not render_template('render_spec/some_action')
151 + end.should fail_with("expected not to render \"render_spec/some_action\", but did")
152 + end
153 +
154 + it "should fail when the action renders the partial" do
155 + post 'action_with_partial'
156 + lambda do
157 + response.should_not render_template('_a_partial')
158 + end.should fail_with("expected not to render \"_a_partial\", but did")
159 + end
160 +
161 + it "should fail when the action renders the partial (named with controller)" do
162 + post 'action_with_partial'
163 + lambda do
164 + response.should_not render_template('render_spec/_a_partial')
165 + end.should fail_with("expected not to render \"render_spec/_a_partial\", but did")
166 + end
167 +
168 + end
169 + end
@@ -0,0 +1,65
1 + require File.dirname(__FILE__) + '/../../spec_helper'
2 +
3 + class MockableModel < ActiveRecord::Base
4 + has_one :associated_model
5 + end
6 +
7 + class SubMockableModel < MockableModel
8 + end
9 +
10 + class AssociatedModel < ActiveRecord::Base
11 + belongs_to :mockable_model
12 + end
13 +
14 + describe "mock_model", :type => :view do
15 + before(:each) do
16 + @model = mock_model(SubMockableModel)
17 + end
18 + it "should say it is_a? if it is" do
19 + @model.is_a?(SubMockableModel).should be(true)
20 + end
21 + it "should say it is_a? if it's ancestor is" do
22 + @model.is_a?(MockableModel).should be(true)
23 + end
24 + it "should say it is kind_of? if it is" do
25 + @model.kind_of?(SubMockableModel).should be(true)
26 + end
27 + it "should say it is kind_of? if it's ancestor is" do
28 + @model.kind_of?(MockableModel).should be(true)
29 + end
30 + it "should say it is instance_of? if it is" do
31 + @model.instance_of?(SubMockableModel).should be(true)
32 + end
33 + it "should not say it instance_of? if it isn't, even if it's ancestor is" do
34 + @model.instance_of?(MockableModel).should be(false)
35 + end
36 + end
37 +
38 + describe "mock_model with null_object", :type => :view do
39 + before(:each) do
40 + @model = mock_model(MockableModel, :null_object => true, :mocked_method => "mocked")
41 + end
42 +
43 + it "should be able to mock methods" do
44 + @model.mocked_method.should == "mocked"
45 + end
46 + it "should return itself to unmocked methods" do
47 + @model.unmocked_method.should equal(@model)
48 + end
49 + end
50 +
51 + describe "mock_model as association", :type => :view do
52 + before(:each) do
53 + @real = AssociatedModel.create!
54 + @mock_model = mock_model(MockableModel)
55 + @real.mockable_model = @mock_model
56 + end
57 +
58 + it "should pass associated_model == mock" do
59 + @mock_model.should == @real.mockable_model
60 + end
61 +
62 + it "should pass mock == associated_model" do
63 + @real.mockable_model.should == @mock_model
64 + end
65 + end
@@ -0,0 +1,7
1 + require File.dirname(__FILE__) + '/../spec_helper'
2 +
3 + describe "A sample spec" do
4 + it "should pass" do
5 + true.should === true
6 + end
7 + end No newline at end of file
@@ -0,0 +1,89
1 + require File.dirname(__FILE__) + '/../spec_helper'
2 +
3 + describe "script/spec_server file", :shared => true do
4 + attr_accessor :tmbundle_install_directory
5 +
6 + after do
7 + system "kill -9 #{@pid}"
8 + end
9 +
10 + it "runs a spec" do
11 + dir = File.dirname(__FILE__)
12 + output = ""
13 + Timeout.timeout(10) do
14 + loop do
15 + output = `#{RAILS_ROOT}/script/spec #{dir}/sample_spec.rb --drb 2>&1`
16 + break unless output.include?("No server is running")
17 + end
18 + end
19 +
20 + unless $?.exitstatus == 0
21 + flunk "command 'script/spec spec/sample_spec' failed\n#{output}"
22 + end
23 + end
24 +
25 + def start_spec_server
26 + create_spec_server_pid_file
27 + start_spec_server_process
28 + end
29 +
30 + def create_spec_server_pid_file
31 + current_dir = File.dirname(__FILE__)
32 + pid_dir = "#{Dir.tmpdir}/#{Time.now.to_i}"
33 + @spec_server_pid_file = "#{pid_dir}/spec_server.pid"
34 + FileUtils.mkdir_p pid_dir
35 + system "touch #{@spec_server_pid_file}"
36 + @rspec_path = File.expand_path("#{current_dir}/../../../rspec/lib")
37 + end
38 +
39 + def start_spec_server_process
40 + dir = File.dirname(__FILE__)
41 + spec_server_cmd = %Q|export HOME=#{Dir.tmpdir}; |
42 + spec_server_cmd << %Q|ruby -e 'system("echo " + Process.pid.to_s + " > #{@spec_server_pid_file}"); |
43 + spec_server_cmd << %Q|$LOAD_PATH.unshift("#{@rspec_path}"); require "spec"; |
44 + spec_server_cmd << %Q|load "#{RAILS_ROOT}/script/spec_server"' &|
45 + system spec_server_cmd
46 +
47 + file_content = ""
48 + Timeout.timeout(5) do
49 + loop do
50 + file_content = File.read(@spec_server_pid_file)
51 + break unless file_content.blank?
52 + end
53 + end
54 + @pid = Integer(File.read(@spec_server_pid_file))
55 + end
56 + end
57 +
58 + describe "script/spec_server file without TextMate bundle" do
59 + it_should_behave_like "script/spec_server file"
60 + before do
61 + start_spec_server
62 + end
63 + end
64 +
65 + describe "script/spec_server file with TextMate bundle" do
66 + it_should_behave_like "script/spec_server file"
67 + before do
68 + dir = File.dirname(__FILE__)
69 + @tmbundle_install_directory = File.expand_path("#{Dir.tmpdir}/Library/Application Support/TextMate/Bundles")
70 + @bundle_name = "RSpec.tmbundle"
71 + FileUtils.mkdir_p(tmbundle_install_directory)
72 + bundle_dir = File.expand_path("#{dir}/../../../../../../#{@bundle_name}")
73 + File.directory?(bundle_dir).should be_true
74 + unless system(%Q|ln -s #{bundle_dir} "#{tmbundle_install_directory}"|)
75 + raise "Creating link to Textmate Bundle"
76 + end
77 + start_spec_server
78 + end
79 +
80 + after do
81 + bundle_file_to_remove = "#{tmbundle_install_directory}/#{@bundle_name}"
82 + if bundle_file_to_remove == "/"
83 + raise "bundle file path resolved to '/' - could not call rm"
84 + end
85 + unless system(%Q|rm "#{bundle_file_to_remove}"|)
86 + raise "Removing Textmate bundle link failed"
87 + end
88 + end
89 + end
@@ -0,0 +1,11
1 + require File.dirname(__FILE__) + '/../spec_helper'
2 +
3 + describe "script/spec file" do
4 + it "should run a spec" do
5 + dir = File.dirname(__FILE__)
6 + output = `#{RAILS_ROOT}/script/spec #{dir}/sample_spec.rb`
7 + unless $?.exitstatus == 0
8 + flunk "command 'script/spec spec/sample_spec' failed\n#{output}"
9 + end
10 + end
11 + end No newline at end of file
@@ -0,0 +1,7
1 + dir = File.dirname(__FILE__)
2 + Dir["#{dir}/**/*_example.rb"].each do |file|
3 + require file
4 + end
5 + Dir["#{dir}/**/*_spec.rb"].each do |file|
6 + require file
7 + end
@@ -0,0 +1,46
1 + dir = File.dirname(__FILE__)
2 + $LOAD_PATH.unshift(File.expand_path("#{dir}/../rspec/lib"))
3 + $LOAD_PATH.unshift(File.expand_path("#{dir}/../spec_resources/controllers"))
4 + $LOAD_PATH.unshift(File.expand_path("#{dir}/../spec_resources/helpers"))
5 + require File.expand_path("#{dir}/../../../../spec/spec_helper")
6 + require File.expand_path("#{dir}/../spec_resources/controllers/render_spec_controller")
7 + require File.expand_path("#{dir}/../spec_resources/controllers/rjs_spec_controller")
8 + require File.expand_path("#{dir}/../spec_resources/controllers/redirect_spec_controller")
9 + require File.expand_path("#{dir}/../spec_resources/controllers/action_view_base_spec_controller")
10 + require File.expand_path("#{dir}/../spec_resources/helpers/explicit_helper")
11 + require File.expand_path("#{dir}/../spec_resources/helpers/more_explicit_helper")
12 + require File.expand_path("#{dir}/../spec_resources/helpers/view_spec_helper")
13 + require File.expand_path("#{dir}/../spec_resources/helpers/plugin_application_helper")
14 +
15 + ActionController::Routing.controller_paths << "#{dir}/../spec_resources/controllers"
16 +
17 + module Spec
18 + module Rails
19 + module Example
20 + class ViewExampleGroupController
21 + set_view_path File.join(File.dirname(__FILE__), "..", "spec_resources", "views")
22 + end
23 + end
24 + end
25 + end
26 +
27 + def fail()
28 + raise_error(Spec::Expectations::ExpectationNotMetError)
29 + end
30 +
31 + def fail_with(message)
32 + raise_error(Spec::Expectations::ExpectationNotMetError,message)
33 + end
34 +
35 + class Proc
36 + def should_pass
37 + lambda { self.call }.should_not raise_error
38 + end
39 + end
40 +
41 + ActionController::Routing::Routes.draw do |map|
42 + map.resources :rspec_on_rails_specs
43 + map.connect 'custom_route', :controller => 'custom_route_spec', :action => 'custom_route'
44 + map.connect ":controller/:action/:id"
45 + end
46 +
@@ -0,0 +1,2
1 + class ActionViewBaseSpecController < ActionController::Base
2 + end
@@ -0,0 +1,56
1 + class ControllerSpecController < ActionController::Base
2 + if ['edge','2.0.0'].include?(ENV['RSPEC_RAILS_VERSION'])
3 + set_view_path [File.join(File.dirname(__FILE__), "..", "views")]
4 + else
5 + set_view_path File.join(File.dirname(__FILE__), "..", "views")
6 + end
7 +
8 + def some_action
9 + render :template => "template/that/does/not/actually/exist"
10 + end
11 +
12 + def action_with_template
13 + session[:session_key] = "session value"
14 + flash[:flash_key] = "flash value"
15 + render :template => "controller_spec/action_with_template"
16 + end
17 +
18 + def action_with_partial
19 + render :partial => "controller_spec/partial"
20 + end
21 +
22 + def action_with_partial_with_object
23 + render :partial => "controller_spec/partial", :object => params[:thing]
24 + end
25 +
26 + def action_with_partial_with_locals
27 + render :partial => "controller_spec/partial", :locals => {:thing => params[:thing]}
28 + end
29 +
30 + def action_with_errors_in_template
31 + render :template => "controller_spec/action_with_errors_in_template"
32 + end
33 +
34 + def action_setting_the_assigns_hash
35 + assigns['direct_assigns_key'] = :direct_assigns_key_value
36 + @indirect_assigns_key = :indirect_assigns_key_value
37 + end
38 +
39 + def action_setting_flash_after_session_reset
40 + reset_session
41 + flash[:after_reset] = "available"
42 + end
43 +
44 + def action_setting_flash_before_session_reset
45 + flash[:before_reset] = 'available'
46 + reset_session
47 + end
48 +
49 + def action_with_render_update
50 + render :update do |page|
51 + page.replace :bottom, 'replace_me',
52 + :partial => 'non_existent_partial'
53 + end
54 + end
55 + end
56 +
@@ -0,0 +1,59
1 + class RedirectSpecController < ApplicationController
2 +
3 + def action_with_no_redirect
4 + render :text => "this is just here to keep this from causing a MissingTemplate error"
5 + end
6 +
7 + def action_with_redirect_to_somewhere
8 + redirect_to :action => 'somewhere'
9 + end
10 +
11 + def action_with_redirect_to_other_somewhere
12 + redirect_to :controller => 'render_spec', :action => 'text_action'
13 + end
14 +
15 + def action_with_redirect_to_somewhere_and_return
16 + redirect_to :action => 'somewhere' and return
17 + render :text => "this is after the return"
18 + end
19 +
20 + def somewhere
21 + render :text => "this is just here to keep this from causing a MissingTemplate error"
22 + end
23 +
24 + def action_with_redirect_to_rspec_site
25 + redirect_to "http://rspec.rubyforge.org"
26 + end
27 +
28 + def action_with_redirect_back
29 + redirect_to :back
30 + end
31 +
32 + def action_with_redirect_in_respond_to
33 + respond_to do |wants|
34 + wants.html { redirect_to :action => 'somewhere' }
35 + end
36 + end
37 +
38 + def action_with_redirect_which_creates_query_string
39 + redirect_to :action => "somewhere", :id => 1111, :param1 => "value1", :param2 => "value2"
40 + end
41 +
42 + # note: sometimes this is the URL which rails will generate from the hash in
43 + # action_with_redirect_which_creates_query_string
44 + def action_with_redirect_with_query_string_order1
45 + redirect_to "http://test.host/redirect_spec/somewhere/1111?param1=value1&param2=value2"
46 + end
47 +
48 + # note: sometimes this is the URL which rails will generate from the hash in
49 + # action_with_redirect_which_creates_query_string
50 + def action_with_redirect_with_query_string_order2
51 + redirect_to "http://test.host/redirect_spec/somewhere/1111?param2=value2&param1=value1"
52 + end
53 +
54 + def action_with_redirect_to_unroutable_url_inside_app
55 + redirect_to :controller => "nonexistant", :action => "none"
56 + end
57 +
58 + end
59 +
@@ -0,0 +1,26
1 + class RenderSpecController < ApplicationController
2 + set_view_path File.join(File.dirname(__FILE__), "..", "views")
3 +
4 + def some_action
5 + respond_to do |format|
6 + format.html
7 + format.js
8 + end
9 + end
10 +
11 + def action_which_renders_template_from_other_controller
12 + render :template => 'controller_spec/action_with_template'
13 + end
14 +
15 + def text_action
16 + render :text => "this is the text for this action"
17 + end
18 +
19 + def action_with_partial
20 + render :partial => "a_partial"
21 + end
22 +
23 + def action_that_renders_nothing
24 + render :nothing => true
25 + end
26 + end
@@ -0,0 +1,58
1 + class RjsSpecController < ApplicationController
2 + set_view_path File.join(File.dirname(__FILE__), "..", "views")
3 +
4 + def replace_html
5 + end
6 +
7 + def insert_html
8 + end
9 +
10 + def replace
11 + end
12 +
13 + def hide_div
14 + end
15 +
16 + def hide_page_element
17 + end
18 +
19 + def replace_html_with_partial
20 + end
21 +
22 + def render_replace_html
23 + render :update do |page|
24 + page.replace_html 'mydiv', 'replacement text'
25 + page.replace_html 'myotherdiv', 'other replacement text'
26 + end
27 + end
28 +
29 + def render_replace_html_with_partial
30 + render :update do |page|
31 + page.replace_html 'mydiv', :partial => 'rjs_spec/replacement_partial'
32 + end
33 + end
34 +
35 + def render_insert_html
36 + render :update do |page|
37 + page.insert_html 'mydiv', 'replacement text'
38 + end
39 + end
40 +
41 + def render_replace
42 + render :update do |page|
43 + page.replace 'mydiv', 'replacement text'
44 + end
45 + end
46 +
47 + def render_hide_div
48 + render :update do |page|
49 + page.hide 'mydiv'
50 + end
51 + end
52 +
53 + def render_hide_page_element
54 + render :update do |page|
55 + page['mydiv'].hide
56 + end
57 + end
58 + end
@@ -0,0 +1,10
1 + module ExplicitHelper
2 + def method_in_explicit_helper
3 + "<div>This is text from a method in the ExplicitHelper</div>"
4 + end
5 +
6 + # this is an example of a method spec'able with eval_erb in helper specs
7 + def prepend(arg, &block)
8 + concat(arg, block.binding) + block.call
9 + end
10 + end
@@ -0,0 +1,5
1 + module MoreExplicitHelper
2 + def method_in_more_explicit_helper
3 + "<div>This is text from a method in the MoreExplicitHelper</div>"
4 + end
5 + end
@@ -0,0 +1,6
1 + # Methods added to this helper will be available to all templates in the application.
2 + module ApplicationHelper
3 + def method_in_plugin_application_helper
4 + "<div>This is text from a method in the ApplicationHelper</div>"
5 + end
6 + end
@@ -0,0 +1,13
1 + module ViewSpecHelper
2 + def method_in_helper
3 + "<div>This is text from a method in the ViewSpecHelper</div>"
4 + end
5 +
6 + def method_in_template_with_partial
7 + "<div>method_in_template_with_partial in ViewSpecHelper</div>"
8 + end
9 +
10 + def method_in_partial
11 + "<div>method_in_partial in ViewSpecHelper</div>"
12 + end
13 + end
new file 100644
@@ -0,0 +1,1
1 +
@@ -0,0 +1,1
1 +
new file 100644
@@ -0,0 +1,1
1 + <% raise %> No newline at end of file
@@ -0,0 +1,1
1 + <div>This is action_with_template.rhtml</div>
new file 100644
@@ -0,0 +1,1
1 + # This is used for rails > 1.2.3 No newline at end of file
new file 100644
@@ -0,0 +1,1
1 + # This is used for rails <= 1.2.3
@@ -0,0 +1,1
1 + This is the text in the replacement partial. No newline at end of file
@@ -0,0 +1,1
1 + page.hide 'mydiv'
@@ -0,0 +1,1
1 + page['mydiv'].hide
@@ -0,0 +1,1
1 + page.insert_html 'mydiv', 'replacement text'
@@ -0,0 +1,1
1 + page.replace 'mydiv', 'replacement text'
@@ -0,0 +1,1
1 + page.replace_html 'mydiv', 'replacement text' No newline at end of file
@@ -0,0 +1,1
1 + page.replace_html 'mydiv', :partial => 'rjs_spec/replacement_partial' No newline at end of file
@@ -0,0 +1,1
1 + page.visual_effect :fade, 'mydiv'
@@ -0,0 +1,1
1 + page.visual_effect :toggle_blind, 'mydiv'
@@ -0,0 +1,1
1 + <!-THIS FILE HAS NO TAGS-> No newline at end of file
@@ -0,0 +1,1
1 + <div></div> No newline at end of file
@@ -0,0 +1,1
1 + <div key="value"></div> No newline at end of file
@@ -0,0 +1,2
1 + <%= method_in_plugin_application_helper %>
2 + <%= method_in_partial %> No newline at end of file
new file 100644
@@ -0,0 +1,1
1 + <div><%= x %></div> No newline at end of file
@@ -0,0 +1,1
1 + <%= render :partial => 'partial', :object => partial %> No newline at end of file
@@ -0,0 +1,1
1 + <hr id="spacer" />
@@ -0,0 +1,3
1 + <div id="session"><%= session[:key] %></div>
2 + <div id="params"><%= params[:key] %></div>
3 + <div id="flash"><%= flash[:key] %></div> No newline at end of file
@@ -0,0 +1,2
1 + <% form_tag do %>
2 + <% end %> No newline at end of file
@@ -0,0 +1,2
1 + <%= method_in_plugin_application_helper %>
2 + <%= method_in_explicit_helper %>
@@ -0,0 +1,1
1 + <%= method_in_plugin_application_helper %>
@@ -0,0 +1,2
1 + <%= method_in_plugin_application_helper %>
2 + <%= method_in_helper %>
@@ -0,0 +1,3
1 + <%= method_in_plugin_application_helper %>
2 + <%= method_in_explicit_helper %>
3 + <%= method_in_more_explicit_helper %> No newline at end of file
@@ -0,0 +1,5
1 + <%= method_in_template_with_partial %>
2 + <%= render :partial => 'partial' %>
3 +
4 + <%= render :partial => 'partial_used_twice' %>
5 + <%= render :partial => 'partial_used_twice' %>
@@ -0,0 +1,3
1 + <%= render :partial => 'partial',
2 + :collection => ['Alice', 'Bob'],
3 + :spacer_template => 'spacer' %>
@@ -0,0 +1,1
1 + <%= render :partial => @array %>
@@ -0,0 +1,10
1 + require File.join(File.dirname(__FILE__), *%w[helper])
2 + require File.join(File.dirname(__FILE__), *%w[steps people])
3 +
4 + # Run transactions_should_rollback in Ruby
5 + require File.join(File.dirname(__FILE__), *%w[transactions_should_rollback])
6 +
7 + # Run transactions_should_rollback in Plain Text
8 + with_steps_for :people do
9 + run File.join(File.dirname(__FILE__), *%w[transactions_should_rollback]), :type => RailsStory
10 + end No newline at end of file
@@ -0,0 +1,5
1 + dir = File.dirname(__FILE__)
2 + $LOAD_PATH.unshift File.expand_path("#{dir}/../lib")
3 + require File.expand_path("#{dir}/../../../../spec/spec_helper")
4 +
5 + require 'spec/rails/story_adapter' No newline at end of file
@@ -0,0 +1,8
1 + steps_for :people do
2 + When "I add a Person" do
3 + Person.create!(:name => "Foo")
4 + end
5 + Then "there should be one person" do
6 + Person.count.should == 1
7 + end
8 + end No newline at end of file
@@ -0,0 +1,15
1 + Story: transactions should rollback in plain text
2 + As an RSpec/Rails Story author
3 + I want transactions to roll back between scenarios in plain text
4 + So that I can have confidence in the state of the database
5 +
6 + Scenario: add one Person
7 + When I add a Person
8 +
9 + Scenario: add another person
10 + GivenScenario: add one Person
11 + Then there should be one person
12 +
13 + Scenario: add yet another person
14 + GivenScenario: add one Person
15 + Then there should be one person
@@ -0,0 +1,25
1 + require File.join(File.dirname(__FILE__), *%w[helper])
2 +
3 + Story "transactions should rollback", %{
4 + As an RSpec/Rails Story author
5 + I want transactions to roll back between scenarios
6 + So that I can have confidence in the state of the database
7 + }, :type => RailsStory do
8 + Scenario "add one Person" do
9 + When "I add a Person" do
10 + Person.create!(:name => "Foo")
11 + end
12 + end
13 +
14 + Scenario "add another person" do
15 + GivenScenario "add one Person"
16 + Then "there should be one person" do
17 + Person.count.should == 1
18 + end
19 + end
20 +
21 + Scenario "add yet another person" do
22 + GivenScenario "add one Person"
23 + Then "there should be one person"
24 + end
25 + end No newline at end of file
@@ -0,0 +1,137
1 + # In rails 1.2, plugins aren't available in the path until they're loaded.
2 + # Check to see if the rspec plugin is installed first and require
3 + # it if it is. If not, use the gem version.
4 + rspec_base = File.expand_path(File.dirname(__FILE__) + '/../../rspec/lib')
5 + $LOAD_PATH.unshift(rspec_base) if File.exist?(rspec_base)
6 + require 'spec/rake/spectask'
7 + require 'spec/translator'
8 +
9 + spec_prereq = File.exist?(File.join(RAILS_ROOT, 'config', 'database.yml')) ? "db:test:prepare" : :noop
10 + task :noop do
11 + end
12 +
13 + task :default => :spec
14 + task :stats => "spec:statsetup"
15 +
16 + desc "Run all specs in spec directory (excluding plugin specs)"
17 + Spec::Rake::SpecTask.new(:spec => spec_prereq) do |t|
18 + t.spec_opts = ['--options', "\"#{RAILS_ROOT}/spec/spec.opts\""]
19 + t.spec_files = FileList['spec/**/*_spec.rb']
20 + end
21 +
22 + namespace :spec do
23 + desc "Run all specs in spec directory with RCov (excluding plugin specs)"
24 + Spec::Rake::SpecTask.new(:rcov) do |t|
25 + t.spec_opts = ['--options', "\"#{RAILS_ROOT}/spec/spec.opts\""]
26 + t.spec_files = FileList['spec/**/*_spec.rb']
27 + t.rcov = true
28 + t.rcov_opts = lambda do
29 + IO.readlines("#{RAILS_ROOT}/spec/rcov.opts").map {|l| l.chomp.split " "}.flatten
30 + end
31 + end
32 +
33 + desc "Print Specdoc for all specs (excluding plugin specs)"
34 + Spec::Rake::SpecTask.new(:doc) do |t|
35 + t.spec_opts = ["--format", "specdoc", "--dry-run"]
36 + t.spec_files = FileList['spec/**/*_spec.rb']
37 + end
38 +
39 + desc "Print Specdoc for all plugin specs"
40 + Spec::Rake::SpecTask.new(:plugin_doc) do |t|
41 + t.spec_opts = ["--format", "specdoc", "--dry-run"]
42 + t.spec_files = FileList['vendor/plugins/**/spec/**/*_spec.rb'].exclude('vendor/plugins/rspec/*')
43 + end
44 +
45 + [:models, :controllers, :views, :helpers, :lib].each do |sub|
46 + desc "Run the specs under spec/#{sub}"
47 + Spec::Rake::SpecTask.new(sub => spec_prereq) do |t|
48 + t.spec_opts = ['--options', "\"#{RAILS_ROOT}/spec/spec.opts\""]
49 + t.spec_files = FileList["spec/#{sub}/**/*_spec.rb"]
50 + end
51 + end
52 +
53 + desc "Run the specs under vendor/plugins (except RSpec's own)"
54 + Spec::Rake::SpecTask.new(:plugins => spec_prereq) do |t|
55 + t.spec_opts = ['--options', "\"#{RAILS_ROOT}/spec/spec.opts\""]
56 + t.spec_files = FileList['vendor/plugins/**/spec/**/*_spec.rb'].exclude('vendor/plugins/rspec/*').exclude("vendor/plugins/rspec_on_rails/*")
57 + end
58 +
59 + namespace :plugins do
60 + desc "Runs the examples for rspec_on_rails"
61 + Spec::Rake::SpecTask.new(:rspec_on_rails) do |t|
62 + t.spec_opts = ['--options', "\"#{RAILS_ROOT}/spec/spec.opts\""]
63 + t.spec_files = FileList['vendor/plugins/rspec_on_rails/spec/**/*_spec.rb']
64 + end
65 + end
66 +
67 + desc "Translate/upgrade specs using the built-in translator"
68 + task :translate do
69 + translator = ::Spec::Translator.new
70 + dir = RAILS_ROOT + '/spec'
71 + translator.translate(dir, dir)
72 + end
73 +
74 + # Setup specs for stats
75 + task :statsetup do
76 + require 'code_statistics'
77 + ::STATS_DIRECTORIES << %w(Model\ specs spec/models) if File.exist?('spec/models')
78 + ::STATS_DIRECTORIES << %w(View\ specs spec/views) if File.exist?('spec/views')
79 + ::STATS_DIRECTORIES << %w(Controller\ specs spec/controllers) if File.exist?('spec/controllers')
80 + ::STATS_DIRECTORIES << %w(Helper\ specs spec/helpers) if File.exist?('spec/helpers')
81 + ::STATS_DIRECTORIES << %w(Library\ specs spec/lib) if File.exist?('spec/lib')
82 + ::CodeStatistics::TEST_TYPES << "Model specs" if File.exist?('spec/models')
83 + ::CodeStatistics::TEST_TYPES << "View specs" if File.exist?('spec/views')
84 + ::CodeStatistics::TEST_TYPES << "Controller specs" if File.exist?('spec/controllers')
85 + ::CodeStatistics::TEST_TYPES << "Helper specs" if File.exist?('spec/helpers')
86 + ::CodeStatistics::TEST_TYPES << "Library specs" if File.exist?('spec/lib')
87 + ::STATS_DIRECTORIES.delete_if {|a| a[0] =~ /test/}
88 + end
89 +
90 + namespace :db do
91 + namespace :fixtures do
92 + desc "Load fixtures (from spec/fixtures) into the current environment's database. Load specific fixtures using FIXTURES=x,y"
93 + task :load => :environment do
94 + require 'active_record/fixtures'
95 + ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
96 + (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'spec', 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
97 + Fixtures.create_fixtures('spec/fixtures', File.basename(fixture_file, '.*'))
98 + end
99 + end
100 + end
101 + end
102 +
103 + namespace :server do
104 + daemonized_server_pid = File.expand_path("spec_server.pid", RAILS_ROOT + "/tmp")
105 +
106 + desc "start spec_server."
107 + task :start do
108 + if File.exist?(daemonized_server_pid)
109 + $stderr.puts "spec_server is already running."
110 + else
111 + $stderr.puts "Starting up spec server."
112 + system("ruby", "script/spec_server", "--daemon", "--pid", daemonized_server_pid)
113 + end
114 + end
115 +
116 + desc "stop spec_server."
117 + task :stop do
118 + unless File.exist?(daemonized_server_pid)
119 + $stderr.puts "No server running."
120 + else
121 + $stderr.puts "Shutting down spec_server."
122 + system("kill", "-s", "TERM", File.read(daemonized_server_pid).strip) &&
123 + File.delete(daemonized_server_pid)
124 + end
125 + end
126 +
127 + desc "reload spec_server."
128 + task :restart do
129 + unless File.exist?(daemonized_server_pid)
130 + $stderr.puts "No server running."
131 + else
132 + $stderr.puts "Reloading down spec_server."
133 + system("kill", "-s", "USR2", File.read(daemonized_server_pid).strip)
134 + end
135 + end
136 + end
137 + end
You need to be logged in to leave comments. Login now