yetanothernguyen-shoulda-matchers 1.0.0.beta3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. data/Appraisals +12 -0
  2. data/CONTRIBUTION_GUIDELINES.rdoc +10 -0
  3. data/Gemfile +5 -0
  4. data/MIT-LICENSE +22 -0
  5. data/README.rdoc +78 -0
  6. data/Rakefile +55 -0
  7. data/lib/shoulda-matchers.rb +1 -0
  8. data/lib/shoulda/matchers.rb +8 -0
  9. data/lib/shoulda/matchers/action_controller.rb +38 -0
  10. data/lib/shoulda/matchers/action_controller/assign_to_matcher.rb +114 -0
  11. data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +50 -0
  12. data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +62 -0
  13. data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +54 -0
  14. data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +99 -0
  15. data/lib/shoulda/matchers/action_controller/respond_with_content_type_matcher.rb +74 -0
  16. data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +85 -0
  17. data/lib/shoulda/matchers/action_controller/route_matcher.rb +93 -0
  18. data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +98 -0
  19. data/lib/shoulda/matchers/action_controller/set_the_flash_matcher.rb +94 -0
  20. data/lib/shoulda/matchers/action_mailer.rb +22 -0
  21. data/lib/shoulda/matchers/action_mailer/have_sent_email.rb +166 -0
  22. data/lib/shoulda/matchers/active_model.rb +33 -0
  23. data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +83 -0
  24. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +110 -0
  25. data/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb +87 -0
  26. data/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb +141 -0
  27. data/lib/shoulda/matchers/active_model/helpers.rb +29 -0
  28. data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +41 -0
  29. data/lib/shoulda/matchers/active_model/validate_format_of_matcher.rb +65 -0
  30. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +39 -0
  31. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +61 -0
  32. data/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb +148 -0
  33. data/lib/shoulda/matchers/active_model/validation_matcher.rb +56 -0
  34. data/lib/shoulda/matchers/active_record.rb +24 -0
  35. data/lib/shoulda/matchers/active_record/association_matcher.rb +226 -0
  36. data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +169 -0
  37. data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +112 -0
  38. data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +59 -0
  39. data/lib/shoulda/matchers/assertion_error.rb +11 -0
  40. data/lib/shoulda/matchers/integrations/rspec.rb +38 -0
  41. data/lib/shoulda/matchers/integrations/test_unit.rb +54 -0
  42. data/lib/shoulda/matchers/version.rb +5 -0
  43. metadata +169 -0
@@ -0,0 +1,54 @@
1
+ module Shoulda # :nodoc:
2
+ module Matchers
3
+ module ActionController # :nodoc:
4
+
5
+ # Ensures a controller rendered the given template.
6
+ #
7
+ # Example:
8
+ #
9
+ # it { should render_template(:show) }
10
+ def render_template(template)
11
+ RenderTemplateMatcher.new(template, self)
12
+ end
13
+
14
+ class RenderTemplateMatcher # :nodoc:
15
+
16
+ def initialize(template, context)
17
+ @template = template.to_s
18
+ @context = context
19
+ end
20
+
21
+ def matches?(controller)
22
+ @controller = controller
23
+ renders_template?
24
+ end
25
+
26
+ attr_reader :failure_message, :negative_failure_message
27
+
28
+ def description
29
+ "render template #{@template}"
30
+ end
31
+
32
+ def in_context(context)
33
+ @context = context
34
+ self
35
+ end
36
+
37
+ private
38
+
39
+ def renders_template?
40
+ begin
41
+ @context.send(:assert_template, @template)
42
+ @negative_failure_message = "Didn't expect to render #{@template}"
43
+ true
44
+ rescue Shoulda::Matchers::AssertionError => error
45
+ @failure_message = error.message
46
+ false
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,99 @@
1
+ module Shoulda # :nodoc:
2
+ module Matchers
3
+ module ActionController # :nodoc:
4
+
5
+ # Ensures that the controller rendered with the given layout.
6
+ #
7
+ # Example:
8
+ #
9
+ # it { should render_with_layout }
10
+ # it { should render_with_layout(:special) }
11
+ # it { should_not render_with_layout }
12
+ def render_with_layout(expected_layout = nil)
13
+ RenderWithLayoutMatcher.new(expected_layout).in_context(self)
14
+ end
15
+
16
+ class RenderWithLayoutMatcher # :nodoc:
17
+
18
+ def initialize(expected_layout)
19
+ @expected_layout = expected_layout.to_s unless expected_layout.nil?
20
+ end
21
+
22
+ # Used to provide access to layouts recorded by
23
+ # ActionController::TemplateAssertions in Rails 3
24
+ def in_context(context)
25
+ @context = context
26
+ self
27
+ end
28
+
29
+ def matches?(controller)
30
+ @controller = controller
31
+ rendered_with_layout? && rendered_with_expected_layout?
32
+ end
33
+
34
+ def failure_message
35
+ "Expected #{expectation}, but #{result}"
36
+ end
37
+
38
+ def negative_failure_message
39
+ "Did not expect #{expectation}, but #{result}"
40
+ end
41
+
42
+ def description
43
+ description = "render with "
44
+ if @expected_layout.nil?
45
+ description << "a layout"
46
+ else
47
+ description << "the #{@expected_layout.inspect} layout"
48
+ end
49
+ description
50
+ end
51
+
52
+ private
53
+
54
+ def rendered_with_layout?
55
+ !rendered_layouts.empty?
56
+ end
57
+
58
+ def rendered_with_expected_layout?
59
+ return true if @expected_layout.nil?
60
+ rendered_layouts.include?(@expected_layout)
61
+ end
62
+
63
+ def rendered_layouts
64
+ if recorded_layouts
65
+ recorded_layouts.keys.compact.map { |layout| layout.sub(%r{^layouts/}, '') }
66
+ else
67
+ layout = @controller.response.layout
68
+ if layout.nil?
69
+ []
70
+ else
71
+ [layout.split('/').last]
72
+ end
73
+ end
74
+ end
75
+
76
+ def recorded_layouts
77
+ if @context
78
+ @context.instance_variable_get('@layouts')
79
+ end
80
+ end
81
+
82
+ def expectation
83
+ "to #{description}"
84
+ end
85
+
86
+ def result
87
+ if rendered_with_layout?
88
+ "rendered with " <<
89
+ rendered_layouts.map { |layout| layout.inspect }.join(", ")
90
+ else
91
+ "rendered without a layout"
92
+ end
93
+ end
94
+
95
+ end
96
+
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,74 @@
1
+ module Shoulda # :nodoc:
2
+ module Matchers
3
+ module ActionController # :nodoc:
4
+
5
+ # Ensures a controller responded with expected 'response' content type.
6
+ #
7
+ # You can pass an explicit content type such as 'application/rss+xml'
8
+ # or its symbolic equivalent :rss
9
+ # or a regular expression such as /rss/
10
+ #
11
+ # Example:
12
+ #
13
+ # it { should respond_with_content_type(:xml) }
14
+ # it { should respond_with_content_type(:csv) }
15
+ # it { should respond_with_content_type(:atom) }
16
+ # it { should respond_with_content_type(:yaml) }
17
+ # it { should respond_with_content_type(:text) }
18
+ # it { should respond_with_content_type('application/rss+xml') }
19
+ # it { should respond_with_content_type(/json/) }
20
+ def respond_with_content_type(content_type)
21
+ RespondWithContentTypeMatcher.new(content_type)
22
+ end
23
+
24
+ class RespondWithContentTypeMatcher # :nodoc:
25
+
26
+ def initialize(content_type)
27
+ @content_type = if content_type.is_a?(Symbol)
28
+ lookup_by_extension(content_type)
29
+ else
30
+ content_type
31
+ end
32
+ end
33
+
34
+ def description
35
+ "respond with content type of #{@content_type}"
36
+ end
37
+
38
+ def matches?(controller)
39
+ @controller = controller
40
+ if @content_type.is_a?(Regexp)
41
+ response_content_type =~ @content_type
42
+ else
43
+ response_content_type == @content_type
44
+ end
45
+ end
46
+
47
+ def failure_message
48
+ "Expected #{expectation}"
49
+ end
50
+
51
+ def negative_failure_message
52
+ "Did not expect #{expectation}"
53
+ end
54
+
55
+ protected
56
+
57
+ def response_content_type
58
+ @controller.response.content_type.to_s
59
+ end
60
+
61
+ def lookup_by_extension(extension)
62
+ Mime::Type.lookup_by_extension(extension.to_s).to_s
63
+ end
64
+
65
+ def expectation
66
+ "content type to be #{@content_type}, " <<
67
+ "but was #{response_content_type}"
68
+ end
69
+
70
+ end
71
+
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,85 @@
1
+ module Shoulda # :nodoc:
2
+ module Matchers
3
+ module ActionController # :nodoc:
4
+
5
+ # Ensures a controller responded with expected 'response' status code.
6
+ #
7
+ # You can pass an explicit status number like 200, 301, 404, 500
8
+ # or its symbolic equivalent :success, :redirect, :missing, :error.
9
+ # See ActionController::StatusCodes for a full list.
10
+ #
11
+ # Example:
12
+ #
13
+ # it { should respond_with(:success) }
14
+ # it { should respond_with(:redirect) }
15
+ # it { should respond_with(:missing) }
16
+ # it { should respond_with(:error) }
17
+ # it { should respond_with(501) }
18
+ def respond_with(status)
19
+ RespondWithMatcher.new(status)
20
+ end
21
+
22
+ class RespondWithMatcher # :nodoc:
23
+
24
+ def initialize(status)
25
+ @status = symbol_to_status_code(status)
26
+ end
27
+
28
+ def matches?(controller)
29
+ @controller = controller
30
+ correct_status_code? || correct_status_code_range?
31
+ end
32
+
33
+ def failure_message
34
+ "Expected #{expectation}"
35
+ end
36
+
37
+ def negative_failure_message
38
+ "Did not expect #{expectation}"
39
+ end
40
+
41
+ def description
42
+ "respond with #{@status}"
43
+ end
44
+
45
+ protected
46
+
47
+ def correct_status_code?
48
+ response_code == @status
49
+ end
50
+
51
+ def correct_status_code_range?
52
+ @status.is_a?(Range) &&
53
+ @status.include?(response_code)
54
+ end
55
+
56
+ def response_code
57
+ @controller.response.response_code
58
+ end
59
+
60
+ def symbol_to_status_code(potential_symbol)
61
+ case potential_symbol
62
+ when :success then 200
63
+ when :redirect then 300..399
64
+ when :missing then 404
65
+ when :error then 500..599
66
+ when Symbol
67
+ if defined?(::Rack::Utils::SYMBOL_TO_STATUS_CODE)
68
+ ::Rack::Utils::SYMBOL_TO_STATUS_CODE[potential_symbol]
69
+ else
70
+ ::ActionController::Base::SYMBOL_TO_STATUS_CODE[potential_symbol]
71
+ end
72
+ else
73
+ potential_symbol
74
+ end
75
+ end
76
+
77
+ def expectation
78
+ "response to be a #{@status}, but was #{response_code}"
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,93 @@
1
+ module Shoulda # :nodoc:
2
+ module Matchers
3
+ module ActionController # :nodoc:
4
+
5
+ # Ensures that requesting +path+ using +method+ routes to +options+.
6
+ #
7
+ # If you don't specify a controller, it will use the controller from the
8
+ # example group.
9
+ #
10
+ # +to_param+ is called on the +options+ given.
11
+ #
12
+ # Examples:
13
+ #
14
+ # it { should route(:get, "/posts").
15
+ # to(:controller => :posts, :action => :index) }
16
+ # it { should route(:get, "/posts/new").to(:action => :new) }
17
+ # it { should route(:post, "/posts").to(:action => :create) }
18
+ # it { should route(:get, "/posts/1").to(:action => :show, :id => 1) }
19
+ # it { should route(:edit, "/posts/1").to(:action => :show, :id => 1) }
20
+ # it { should route(:put, "/posts/1").to(:action => :update, :id => 1) }
21
+ # it { should route(:delete, "/posts/1").
22
+ # to(:action => :destroy, :id => 1) }
23
+ # it { should route(:get, "/users/1/posts/1").
24
+ # to(:action => :show, :id => 1, :user_id => 1) }
25
+ def route(method, path)
26
+ RouteMatcher.new(method, path, self)
27
+ end
28
+
29
+ class RouteMatcher # :nodoc:
30
+
31
+ def initialize(method, path, context)
32
+ @method = method
33
+ @path = path
34
+ @context = context
35
+ end
36
+
37
+ def to(params)
38
+ @params = params
39
+ stringify_params!
40
+ self
41
+ end
42
+
43
+ def in_context(context)
44
+ @context = context
45
+ self
46
+ end
47
+
48
+ def matches?(controller)
49
+ @controller = controller
50
+ guess_controller!
51
+ route_recognized?
52
+ end
53
+
54
+ attr_reader :failure_message, :negative_failure_message
55
+
56
+ def description
57
+ "route #{@method.to_s.upcase} #{@path} to/from #{@params.inspect}"
58
+ end
59
+
60
+ private
61
+
62
+ def guess_controller!
63
+ @params[:controller] ||= @controller.controller_path
64
+ end
65
+
66
+ def stringify_params!
67
+ @params.each do |key, value|
68
+ @params[key] = value.is_a?(Array) ? value.collect {|v| v.to_param } : value.to_param
69
+ end
70
+ end
71
+
72
+ def route_recognized?
73
+ begin
74
+ @context.send(:assert_routing,
75
+ { :method => @method, :path => @path },
76
+ @params)
77
+
78
+ @negative_failure_message = "Didn't expect to #{description}"
79
+ true
80
+ rescue ::ActionController::RoutingError => error
81
+ @failure_message = error.message
82
+ false
83
+ rescue Shoulda::Matchers::AssertionError => error
84
+ @failure_message = error.message
85
+ false
86
+ end
87
+ end
88
+
89
+ end
90
+
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,98 @@
1
+ module Shoulda # :nodoc:
2
+ module Matchers
3
+ module ActionController # :nodoc:
4
+
5
+ # Ensures that a session key was set to the expected value.
6
+ #
7
+ # Example:
8
+ #
9
+ # it { should set_session(:message) }
10
+ # it { should set_session(:user_id).to(@user.id) }
11
+ # it { should_not set_session(:user_id) }
12
+ def set_session(key)
13
+ SetSessionMatcher.new(key)
14
+ end
15
+
16
+ class SetSessionMatcher # :nodoc:
17
+
18
+ def initialize(key)
19
+ @key = key.to_s
20
+ end
21
+
22
+ def to(value = nil, &block)
23
+ @value = value
24
+ @value_block = block
25
+ self
26
+ end
27
+
28
+ def matches?(controller)
29
+ @controller = controller
30
+ @value = @context.instance_eval(&@value_block) if @value_block
31
+ (assigned_value? && assigned_correct_value?) || cleared_value?
32
+ end
33
+
34
+ def failure_message
35
+ "Expected #{expectation}, but #{result}"
36
+ end
37
+
38
+ def negative_failure_message
39
+ "Didn't expect #{expectation}, but #{result}"
40
+ end
41
+
42
+ def description
43
+ description = "set session variable #{@key.inspect}"
44
+ description << " to #{@value.inspect}" if defined?(@value)
45
+ description
46
+ end
47
+
48
+ def in_context(context)
49
+ @context = context
50
+ self
51
+ end
52
+
53
+ private
54
+
55
+ def assigned_value?
56
+ !assigned_value.nil?
57
+ end
58
+
59
+ def cleared_value?
60
+ defined?(@value) && @value.nil? && assigned_value.nil?
61
+ end
62
+
63
+ def assigned_correct_value?
64
+ return true if @value.nil?
65
+ assigned_value == @value
66
+ end
67
+
68
+ def assigned_value
69
+ session[@key]
70
+ end
71
+
72
+ def session
73
+ if @controller.request.respond_to?(:session)
74
+ @controller.request.session.to_hash
75
+ else
76
+ @controller.response.session.data
77
+ end
78
+ end
79
+
80
+ def expectation
81
+ expectation = "session variable #{@key} to be set"
82
+ expectation << " to #{@value.inspect}" if @value
83
+ expectation
84
+ end
85
+
86
+ def result
87
+ if session.empty?
88
+ "no session variables were set"
89
+ else
90
+ "the session was #{session.inspect}"
91
+ end
92
+ end
93
+
94
+ end
95
+
96
+ end
97
+ end
98
+ end