on-test-spec 0.2.6 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +10 -0
- data/VERSION.yml +3 -3
- data/lib/test/spec/rails.rb +42 -26
- data/lib/test/spec/rails/controller_helpers.rb +3 -7
- data/lib/test/spec/rails/expectations.rb +200 -180
- data/lib/test/spec/rails/macros.rb +62 -66
- data/lib/test/spec/rails/macros/authorization.rb +64 -68
- data/lib/test/spec/rails/macros/response.rb +40 -44
- data/lib/test/spec/rails/request_helpers.rb +3 -7
- data/lib/test/spec/rails/response_helpers.rb +33 -37
- data/lib/test/spec/rails/spec_responder.rb +4 -10
- data/lib/test/spec/share.rb +1 -0
- data/test/expectations_test.rb +60 -0
- metadata +5 -5
data/Rakefile
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rake/testtask'
|
2
|
+
require 'rake/rdoctask'
|
2
3
|
|
3
4
|
desc "By default run all tests"
|
4
5
|
task :default => :test
|
@@ -9,6 +10,15 @@ Rake::TestTask.new do |t|
|
|
9
10
|
t.verbose = true
|
10
11
|
end
|
11
12
|
|
13
|
+
desc 'Generate documentation'
|
14
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
15
|
+
rdoc.rdoc_dir = 'rdoc'
|
16
|
+
rdoc.title = 'On Test-spec'
|
17
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
18
|
+
rdoc.rdoc_files.include('README')
|
19
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
20
|
+
end
|
21
|
+
|
12
22
|
begin
|
13
23
|
require 'jeweler'
|
14
24
|
Jeweler::Tasks.new do |s|
|
data/VERSION.yml
CHANGED
data/lib/test/spec/rails.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'test/spec'
|
2
2
|
|
3
|
+
require 'active_support'
|
3
4
|
require 'active_support/test_case'
|
4
5
|
|
5
6
|
require 'active_record'
|
@@ -11,36 +12,51 @@ require 'action_controller/test_case'
|
|
11
12
|
require 'action_view'
|
12
13
|
require 'action_view/test_case'
|
13
14
|
|
14
|
-
%w(test_spec_ext spec_responder expectations).each { |lib| require "test/spec/rails/#{lib}" }
|
15
|
-
Dir[File.dirname(__FILE__) + '/rails/**/*_helpers.rb'].each { |lib| require lib }
|
16
|
-
|
17
15
|
module Test
|
18
16
|
module Spec
|
19
17
|
module Rails
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
23
21
|
|
24
|
-
|
25
|
-
|
22
|
+
require 'test/spec/rails/test_spec_ext'
|
23
|
+
require 'test/spec/rails/spec_responder'
|
24
|
+
require 'test/spec/rails/expectations'
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
26
|
+
require 'test/spec/rails/request_helpers'
|
27
|
+
require 'test/spec/rails/response_helpers'
|
28
|
+
require 'test/spec/rails/controller_helpers'
|
29
|
+
|
30
|
+
|
31
|
+
module Test::Spec::Rails
|
32
|
+
# Returns the test class for a definition line in a spec.
|
33
|
+
#
|
34
|
+
# extract_test_case_args(["A", User, "concerning validation"]) # => ActiveRecord::TestCase
|
35
|
+
def self.extract_test_case_args(args)
|
36
|
+
class_to_test = args.find { |a| a.is_a?(Module) }
|
37
|
+
superclass = test_case_for_class(class_to_test)
|
38
|
+
|
39
|
+
args.delete(class_to_test) if superclass == class_to_test
|
40
|
+
name = args.map { |a| a.to_s }.join(' ')
|
41
|
+
|
42
|
+
[name, class_to_test, superclass]
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns the test class for a class
|
46
|
+
#
|
47
|
+
# extract_test_case_for_class(UsersController) # => ActionController::TestCase
|
48
|
+
def self.test_case_for_class(klass)
|
49
|
+
if klass
|
50
|
+
if klass.ancestors.include?(ActiveRecord::Base)
|
51
|
+
ActiveRecord::TestCase
|
52
|
+
elsif klass.ancestors.include?(ActionController::Base)
|
53
|
+
ActionController::TestCase
|
54
|
+
elsif klass.ancestors.include?(ActiveSupport::TestCase)
|
55
|
+
klass
|
56
|
+
elsif !klass.is_a?(Class) && klass.to_s.ends_with?('Helper')
|
57
|
+
ActionView::TestCase
|
42
58
|
end
|
43
|
-
end
|
59
|
+
end || ActiveSupport::TestCase
|
44
60
|
end
|
45
61
|
end
|
46
62
|
|
@@ -89,12 +105,12 @@ module Kernel
|
|
89
105
|
spec.testcase.class_eval(&block)
|
90
106
|
spec
|
91
107
|
end
|
92
|
-
|
108
|
+
|
93
109
|
def xcontext(*args, &block)
|
94
110
|
name, _, superclass = Test::Spec::Rails.extract_test_case_args(args)
|
95
111
|
xcontext_before_on_test_spec(name, superclass, &block)
|
96
112
|
end
|
97
|
-
|
113
|
+
|
98
114
|
private :context, :xcontext
|
99
115
|
|
100
116
|
alias :describe :context
|
@@ -1,189 +1,209 @@
|
|
1
|
-
module Test
|
2
|
-
module
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
unless secure == true or secure == false
|
28
|
-
raise ArgumentError, ":secure option should be a boolean"
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
@object.instance_eval { test_case.assert_redirected_to *args }
|
33
|
-
if secure == true
|
34
|
-
test_case.assert redirect_url.starts_with?('https:')
|
35
|
-
elsif secure == false
|
36
|
-
test_case.assert redirect_url.starts_with?('http:')
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
alias :redirect_to :redirect
|
41
|
-
|
42
|
-
# Tests whether a redirect back to the HTTP_REFERER was send.
|
43
|
-
#
|
44
|
-
# lambda { delete :destroy, :id => 1 }.should.redirect_back_to(articles_url)
|
45
|
-
# lambda { delete :destroy, :id => 1 }.should.redirect_back_to(:action => :index)
|
46
|
-
def redirect_back_to(url_options)
|
47
|
-
test_case = eval("self", @object.binding)
|
48
|
-
url = test_case.controller.url_for(url_options)
|
49
|
-
test_case.controller.request.env["HTTP_REFERER"] = url
|
50
|
-
|
51
|
-
block_result = @object.call
|
52
|
-
test_case.should.redirect_to(url)
|
53
|
-
|
54
|
-
block_result
|
55
|
-
end
|
56
|
-
|
57
|
-
# Test that the object is valid
|
58
|
-
def validate
|
59
|
-
test_case.assert_valid @object
|
60
|
-
end
|
61
|
-
|
62
|
-
# Tests whether the evaluation of the expression changes.
|
63
|
-
#
|
64
|
-
# lambda { Norm.create }.should.differ('Norm.count')
|
65
|
-
# lambda { Norm.create; Norm.create }.should.differ('Norm.count', +2)
|
66
|
-
# lambda { Norm.create; Option.create }.should.differ('Norm.count', +2, 'Option.count', +1)
|
67
|
-
#
|
68
|
-
# norm = lambda { Norm.create }.should.differ('Norm.count')
|
69
|
-
# norm.name.should == 'Latency'
|
70
|
-
def differ(*expected)
|
71
|
-
block_binding = @object.send(:binding)
|
72
|
-
before = expected.in_groups_of(2).map do |expression, _|
|
73
|
-
eval(expression, block_binding)
|
74
|
-
end
|
75
|
-
|
76
|
-
block_result = @object.call
|
77
|
-
|
78
|
-
expected.in_groups_of(2).each_with_index do |(expression, difference), index|
|
79
|
-
difference = 1 if difference.nil?
|
80
|
-
error = "#{expression.inspect} didn't change by #{difference}"
|
81
|
-
test_case.assert_equal(before[index] + difference, eval(expression, block_binding), error)
|
82
|
-
end
|
83
|
-
|
84
|
-
block_result
|
85
|
-
end
|
86
|
-
alias change differ
|
87
|
-
|
88
|
-
# Tests whether certain pages are cached.
|
89
|
-
#
|
90
|
-
# lambda { get :index }.should.cache_pages(posts_path)
|
91
|
-
# lambda { get :show, :id => post }.should.cache_pages(post_path(post), formatted_posts_path(:js, post))
|
92
|
-
def cache_pages(*pages, &block)
|
93
|
-
if block
|
94
|
-
block.call
|
95
|
-
else
|
96
|
-
@object.call
|
97
|
-
end
|
98
|
-
cache_dir = ActionController::Base.page_cache_directory
|
99
|
-
files = Dir.glob("#{cache_dir}/**/*").map do |filename|
|
100
|
-
filename[cache_dir.length..-1]
|
1
|
+
module Test::Spec::Rails
|
2
|
+
module Helpers
|
3
|
+
def self.inspect_records(records)
|
4
|
+
"[#{records.map { |record| "#{record.class}[#{record.id}]" }.join(', ')}]"
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
module ShouldExpectations
|
9
|
+
# Test that we were redirected somewhere:
|
10
|
+
# should.redirect
|
11
|
+
#
|
12
|
+
# Test that we were redirected to a specific url:
|
13
|
+
# should.redirect :controller => 'foo', :action => 'bar'
|
14
|
+
# or:
|
15
|
+
# should.redirect_to :controller => 'foo', :action => 'bar', :secure => true
|
16
|
+
def redirect(*args)
|
17
|
+
redirect_url = @object.response.respond_to?(:redirect_url) ? @object.response.redirect_url : @object.response.redirected_to
|
18
|
+
if args.empty?
|
19
|
+
test_case.assert_response redirect_url, :redirect
|
20
|
+
elsif args.length == 1 and args.first.is_a?(String)
|
21
|
+
test_case.assert_equal args.first, redirect_url
|
22
|
+
else
|
23
|
+
options = args.extract_options!
|
24
|
+
if secure = options.delete(:secure)
|
25
|
+
unless secure == true or secure == false
|
26
|
+
raise ArgumentError, ":secure option should be a boolean"
|
101
27
|
end
|
102
|
-
test_case.assert pages.all? { |page| files.include?(page) }
|
103
28
|
end
|
104
29
|
|
105
|
-
|
106
|
-
|
107
|
-
test_case.
|
108
|
-
|
109
|
-
|
110
|
-
# Tests if the array of records is the same, order may vary
|
111
|
-
def equal_set(expected)
|
112
|
-
message = "#{Helpers.inspect_records(@object)} does not have the same records as #{Helpers.inspect_records(expected)}"
|
113
|
-
|
114
|
-
left = @object.map(&:id).sort
|
115
|
-
right = expected.map(&:id).sort
|
116
|
-
|
117
|
-
test_case.assert(left == right, message)
|
118
|
-
end
|
119
|
-
|
120
|
-
# Tests if the array of records is the same, order must be the same
|
121
|
-
def equal_list(expected)
|
122
|
-
message = "#{Helpers.inspect_records(@object)} does not have the same records as #{Helpers.inspect_records(expected)}"
|
123
|
-
|
124
|
-
left = @object.map(&:id)
|
125
|
-
right = expected.map(&:id)
|
126
|
-
|
127
|
-
test_case.assert(left == right, message)
|
30
|
+
@object.instance_eval { test_case.assert_redirected_to *args }
|
31
|
+
if secure == true
|
32
|
+
test_case.assert redirect_url.starts_with?('https:')
|
33
|
+
elsif secure == false
|
34
|
+
test_case.assert redirect_url.starts_with?('http:')
|
128
35
|
end
|
129
36
|
end
|
37
|
+
end
|
38
|
+
alias :redirect_to :redirect
|
39
|
+
|
40
|
+
# Tests whether a redirect back to the HTTP_REFERER was send.
|
41
|
+
#
|
42
|
+
# lambda { delete :destroy, :id => 1 }.should.redirect_back_to(articles_url)
|
43
|
+
# lambda { delete :destroy, :id => 1 }.should.redirect_back_to(:action => :index)
|
44
|
+
def redirect_back_to(url_options)
|
45
|
+
test_case = eval("self", @object.binding)
|
46
|
+
url = test_case.controller.url_for(url_options)
|
47
|
+
test_case.controller.request.env["HTTP_REFERER"] = url
|
130
48
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
49
|
+
block_result = @object.call
|
50
|
+
test_case.should.redirect_to(url)
|
51
|
+
|
52
|
+
block_result
|
53
|
+
end
|
54
|
+
|
55
|
+
# Test that the object is valid
|
56
|
+
def validate
|
57
|
+
test_case.assert_valid @object
|
58
|
+
end
|
59
|
+
|
60
|
+
# Tests whether the evaluation of the expression changes.
|
61
|
+
#
|
62
|
+
# lambda { Norm.create }.should.differ('Norm.count')
|
63
|
+
# lambda { Norm.create; Norm.create }.should.differ('Norm.count', +2)
|
64
|
+
# lambda { Norm.create; Option.create }.should.differ('Norm.count', +2, 'Option.count', +1)
|
65
|
+
#
|
66
|
+
# norm = lambda { Norm.create }.should.differ('Norm.count')
|
67
|
+
# norm.name.should == 'Latency'
|
68
|
+
def differ(*expected)
|
69
|
+
block_binding = @object.send(:binding)
|
70
|
+
before = expected.in_groups_of(2).map do |expression, _|
|
71
|
+
eval(expression, block_binding)
|
72
|
+
end
|
73
|
+
|
74
|
+
block_result = @object.call
|
75
|
+
|
76
|
+
expected.in_groups_of(2).each_with_index do |(expression, difference), index|
|
77
|
+
difference = 1 if difference.nil?
|
78
|
+
error = "#{expression.inspect} didn't change by #{difference}"
|
79
|
+
test_case.assert_equal(before[index] + difference, eval(expression, block_binding), error)
|
80
|
+
end
|
81
|
+
|
82
|
+
block_result
|
83
|
+
end
|
84
|
+
alias change differ
|
85
|
+
|
86
|
+
# Tests whether certain pages are cached.
|
87
|
+
#
|
88
|
+
# lambda { get :index }.should.cache_pages(posts_path)
|
89
|
+
# lambda { get :show, :id => post }.should.cache_pages(post_path(post), formatted_posts_path(:js, post))
|
90
|
+
def cache_pages(*pages, &block)
|
91
|
+
if block
|
92
|
+
block.call
|
93
|
+
else
|
94
|
+
@object.call
|
95
|
+
end
|
96
|
+
cache_dir = ActionController::Base.page_cache_directory
|
97
|
+
files = Dir.glob("#{cache_dir}/**/*").map do |filename|
|
98
|
+
filename[cache_dir.length..-1]
|
99
|
+
end
|
100
|
+
test_case.assert pages.all? { |page| files.include?(page) }
|
101
|
+
end
|
102
|
+
|
103
|
+
# Test two HTML strings for equivalency (e.g., identical up to reordering of attributes)
|
104
|
+
def dom_equal(expected)
|
105
|
+
test_case.assert_dom_equal expected, @object
|
106
|
+
end
|
107
|
+
|
108
|
+
# Tests if the array of records is the same, order may vary
|
109
|
+
def equal_set(expected)
|
110
|
+
message = "#{Helpers.inspect_records(@object)} does not have the same records as #{Helpers.inspect_records(expected)}"
|
111
|
+
|
112
|
+
left = @object.map(&:id).sort
|
113
|
+
right = expected.map(&:id).sort
|
114
|
+
|
115
|
+
test_case.assert(left == right, message)
|
116
|
+
end
|
117
|
+
|
118
|
+
# Tests if the array of records is the same, order must be the same
|
119
|
+
def equal_list(expected)
|
120
|
+
message = "#{Helpers.inspect_records(@object)} does not have the same records as #{Helpers.inspect_records(expected)}"
|
121
|
+
|
122
|
+
left = @object.map(&:id)
|
123
|
+
right = expected.map(&:id)
|
124
|
+
|
125
|
+
test_case.assert(left == right, message)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Tests if the model has errors on the attribute after validation for the presented value
|
129
|
+
def validate_with(attribute, value)
|
130
|
+
message = "Expected #{attribute.inspect} with value `#{value.inspect}' to validate"
|
131
|
+
@object.send("#{attribute}=", value)
|
132
|
+
@object.valid?
|
133
|
+
if @object.errors[attribute].kind_of?(Array)
|
134
|
+
test_case.assert(@object.errors[attribute].empty?, message)
|
135
|
+
else
|
136
|
+
test_case.assert(@object.errors.on(attribute).nil?, message)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
module ShouldNotExpectations
|
142
|
+
# Test that an object is not valid
|
143
|
+
def validate
|
144
|
+
test_case.assert !@object.valid?
|
145
|
+
end
|
146
|
+
|
147
|
+
# Tests that the evaluation of the expression shouldn't change
|
148
|
+
#
|
149
|
+
# lambda { Norm.new }.should.not.differ('Norm.count')
|
150
|
+
# lambda { Norm.new }.should.not.differ('Norm.count', 'Option.count')
|
151
|
+
#
|
152
|
+
# norm = lambda { Norm.new }.should.not.differ('Norm.count')
|
153
|
+
# norm.token.should.match /(\d\w){4}/
|
154
|
+
def differ(*expected)
|
155
|
+
block_binding = @object.send(:binding)
|
156
|
+
before = expected.map do |expression|
|
157
|
+
eval(expression, block_binding)
|
158
|
+
end
|
159
|
+
|
160
|
+
block_result = @object.call
|
161
|
+
|
162
|
+
expected.each_with_index do |expression, index|
|
163
|
+
difference = eval(expression, block_binding) - before[index]
|
164
|
+
error = "#{expression.inspect} changed by #{difference}, expected no change"
|
165
|
+
test_case.assert_equal(0, difference, error)
|
166
|
+
end
|
167
|
+
|
168
|
+
block_result
|
169
|
+
|
170
|
+
end
|
171
|
+
alias change differ
|
172
|
+
|
173
|
+
# Test that two HTML strings are not equivalent
|
174
|
+
def dom_equal(expected)
|
175
|
+
test_case.assert_dom_not_equal expected, @object
|
176
|
+
end
|
177
|
+
|
178
|
+
# Tests if the array of records is not the same, order may vary
|
179
|
+
def equal_set(expected)
|
180
|
+
message = "#{Helpers.inspect_records(@object)} has the same records as #{Helpers.inspect_records(expected)}"
|
181
|
+
|
182
|
+
left = @object.map(&:id).sort
|
183
|
+
right = expected.map(&:id).sort
|
184
|
+
|
185
|
+
test_case.assert(left != right, message)
|
186
|
+
end
|
187
|
+
|
188
|
+
# Tests if the array of records is not the same, order may vary
|
189
|
+
def equal_list(expected)
|
190
|
+
message = "#{Helpers.inspect_records(@object)} has the same records as #{Helpers.inspect_records(expected)}"
|
191
|
+
|
192
|
+
left = @object.map(&:id)
|
193
|
+
right = expected.map(&:id)
|
194
|
+
|
195
|
+
test_case.assert(left != right, message)
|
196
|
+
end
|
197
|
+
|
198
|
+
# Tests if the model has errors on the attribute after validation for the presented value
|
199
|
+
def validate_with(attribute, value)
|
200
|
+
message = "Expected errors on #{attribute.inspect} with value `#{value.inspect}' after validation"
|
201
|
+
@object.send("#{attribute}=", value)
|
202
|
+
@object.valid?
|
203
|
+
if @object.errors[attribute].kind_of?(Array)
|
204
|
+
test_case.assert(!@object.errors[attribute].empty?, message)
|
205
|
+
else
|
206
|
+
test_case.assert(!@object.errors.on(attribute).nil?, message)
|
187
207
|
end
|
188
208
|
end
|
189
209
|
end
|
@@ -1,72 +1,68 @@
|
|
1
|
-
module Test
|
2
|
-
module
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
else
|
46
|
-
super
|
47
|
-
end
|
48
|
-
end
|
1
|
+
module Test::Spec::Rails
|
2
|
+
module Macros
|
3
|
+
# Base class for all the proxy classes defined in the macros
|
4
|
+
class Proxy
|
5
|
+
attr_accessor :test_case
|
6
|
+
|
7
|
+
def initialize(test_case)
|
8
|
+
self.test_case = test_case
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Macros define methods on the Should class if they want to be called from the test case.
|
13
|
+
class Should < Proxy
|
14
|
+
end
|
15
|
+
|
16
|
+
# Stores expression to be evaluated later in the correct binding
|
17
|
+
class LazyValue
|
18
|
+
attr_accessor :value
|
19
|
+
def initialize(value)
|
20
|
+
self.value = value
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module ClassMethods
|
25
|
+
# Returns an instance of the Should class, this allows you to call macros from the test
|
26
|
+
# case is a nice way:
|
27
|
+
#
|
28
|
+
# should.disallow.get :index
|
29
|
+
def should
|
30
|
+
Test::Spec::Rails::Macros::Should.new(self)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns true when the passed name is a known table, we assume known tables also have fixtures
|
34
|
+
def known_fixture?(name)
|
35
|
+
respond_to?(:fixture_table_names) && fixture_table_names.include?(name.to_s)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Filter calls to fixture methods so we can use them in the definitions
|
39
|
+
def method_missing(method, *arguments, &block)
|
40
|
+
if known_fixture?(method)
|
41
|
+
arguments = arguments.map { |a| a.inspect }
|
42
|
+
Test::Spec::Rails::Macros::LazyValue.new("#{method}(#{arguments.join(', ')})")
|
43
|
+
else
|
44
|
+
super
|
49
45
|
end
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
result
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
module InstanceMethods
|
50
|
+
# Interpret the non-immediate values in params and replace them
|
51
|
+
def immediate_values(params)
|
52
|
+
result = {}
|
53
|
+
params.each do |key, value|
|
54
|
+
result[key] = case value
|
55
|
+
when Hash
|
56
|
+
immediate_values(value)
|
57
|
+
when Test::Spec::Rails::Macros::LazyValue
|
58
|
+
eval(value.value).to_param
|
59
|
+
when Proc
|
60
|
+
value.call
|
61
|
+
else
|
62
|
+
value
|
68
63
|
end
|
69
64
|
end
|
65
|
+
result
|
70
66
|
end
|
71
67
|
end
|
72
68
|
end
|
@@ -1,77 +1,73 @@
|
|
1
|
-
module Test
|
2
|
-
module
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
1
|
+
module Test::Spec::Rails
|
2
|
+
module Macros
|
3
|
+
class Should
|
4
|
+
# Generates a test which tests authorization code. It assumes a method called <code>access_denied?</code>
|
5
|
+
# on the test case. The <code>access_denied?</code> method should return true when access is denied
|
6
|
+
# (ie. a 403 status code) and false in other cases.
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
# should.disallow.get :index
|
10
|
+
def disallow
|
11
|
+
Test::Spec::Rails::Macros::Authorization::TestGenerator.new(test_case,
|
12
|
+
:access_denied?, true,
|
13
|
+
'Expected access to be denied'
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Generates a test which tests authorization code. It assumes a method called <code>access_denied?</code>
|
18
|
+
# on the test case. The <code>access_denied?</code> method should return true when access is denied
|
19
|
+
# (ie. a 403 status code) and false in other cases.
|
20
|
+
#
|
21
|
+
# Example:
|
22
|
+
# should.allow.get :index
|
23
|
+
def allow
|
24
|
+
Test::Spec::Rails::Macros::Authorization::TestGenerator.new(test_case,
|
25
|
+
:access_denied?, false,
|
26
|
+
'Expected access to be allowed'
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Generates a test which tests authorization code. It assumes a method called <code>access_denied?</code>
|
31
|
+
# on the test case. The <code>login_required?</code> method should return true when the visitor was
|
32
|
+
# asked for credentials (ie. a 401 status code or a redirect to a login page) and false in other cases.
|
33
|
+
#
|
34
|
+
# Example:
|
35
|
+
# should.require_login.get :index
|
36
|
+
def require_login
|
37
|
+
Test::Spec::Rails::Macros::Authorization::TestGenerator.new(test_case,
|
38
|
+
:login_required?, true,
|
39
|
+
'Expected login to be required'
|
40
|
+
)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
module Authorization
|
45
|
+
class TestGenerator < Proxy
|
46
|
+
attr_accessor :validation_method, :message, :expected
|
47
|
+
|
48
|
+
def initialize(test_case, validation_method, expected, message)
|
49
|
+
self.validation_method = validation_method
|
50
|
+
self.expected = expected
|
51
|
+
self.message = message
|
31
52
|
|
32
|
-
|
33
|
-
# on the test case. The <code>login_required?</code> method should return true when the visitor was
|
34
|
-
# asked for credentials (ie. a 401 status code or a redirect to a login page) and false in other cases.
|
35
|
-
#
|
36
|
-
# Example:
|
37
|
-
# should.require_login.get :index
|
38
|
-
def require_login
|
39
|
-
Test::Spec::Rails::Macros::Authorization::TestGenerator.new(test_case,
|
40
|
-
:login_required?, true,
|
41
|
-
'Expected login to be required'
|
42
|
-
)
|
43
|
-
end
|
53
|
+
super(test_case)
|
44
54
|
end
|
45
55
|
|
46
|
-
|
47
|
-
|
48
|
-
|
56
|
+
def method_missing(verb, action, params={})
|
57
|
+
if [:get, :post, :put, :delete, :options].include?(verb.to_sym)
|
58
|
+
description = "should disallow #{verb.to_s.upcase} on `#{action}'"
|
59
|
+
description << " #{params.inspect}" unless params.blank?
|
49
60
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
self.message = message
|
54
|
-
|
55
|
-
super(test_case)
|
56
|
-
end
|
61
|
+
validation_method = self.validation_method
|
62
|
+
expected = self.expected
|
63
|
+
message = self.message
|
57
64
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
description << " #{params.inspect}" unless params.blank?
|
62
|
-
|
63
|
-
validation_method = self.validation_method
|
64
|
-
expected = self.expected
|
65
|
-
message = self.message
|
66
|
-
|
67
|
-
test_case.it description do
|
68
|
-
send(verb, action, immediate_values(params))
|
69
|
-
send(validation_method).should.messaging(message) == expected
|
70
|
-
end
|
71
|
-
else
|
72
|
-
super
|
73
|
-
end
|
65
|
+
test_case.it description do
|
66
|
+
send(verb, action, immediate_values(params))
|
67
|
+
send(validation_method).should.messaging(message) == expected
|
74
68
|
end
|
69
|
+
else
|
70
|
+
super
|
75
71
|
end
|
76
72
|
end
|
77
73
|
end
|
@@ -1,54 +1,50 @@
|
|
1
|
-
module Test
|
2
|
-
module
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
class TestGenerator < Proxy
|
16
|
-
attr_accessor :status, :message, :expected
|
1
|
+
module Test::Spec::Rails
|
2
|
+
module Macros
|
3
|
+
class Should
|
4
|
+
def not_find
|
5
|
+
Test::Spec::Rails::Macros::Response::TestGenerator.new(test_case,
|
6
|
+
:not_found,
|
7
|
+
'Expected to not find a resource'
|
8
|
+
)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module Response
|
13
|
+
class TestGenerator < Proxy
|
14
|
+
attr_accessor :status, :message, :expected
|
17
15
|
|
18
|
-
|
19
|
-
|
20
|
-
|
16
|
+
def initialize(test_case, status, message)
|
17
|
+
self.status = status
|
18
|
+
self.message = message
|
21
19
|
|
22
|
-
|
23
|
-
|
20
|
+
super(test_case)
|
21
|
+
end
|
24
22
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
23
|
+
def method_missing(verb, action, params={})
|
24
|
+
if [:get, :post, :put, :delete, :options].include?(verb.to_sym)
|
25
|
+
description = "should not find resource with #{verb.to_s.upcase} on `#{action}'"
|
26
|
+
description << " #{params.inspect}" unless params.blank?
|
29
27
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
41
|
-
end
|
42
|
-
else
|
43
|
-
test_case.it description do
|
44
|
-
send(verb, action, immediate_values(params))
|
45
|
-
status.should.messaging(message) == status
|
46
|
-
end
|
28
|
+
status = self.status
|
29
|
+
message = self.message
|
30
|
+
|
31
|
+
if defined?(:ActiveRecord)
|
32
|
+
test_case.it description do
|
33
|
+
begin
|
34
|
+
send(verb, action, immediate_values(params))
|
35
|
+
status.should.messaging(message) == status
|
36
|
+
rescue ActiveRecord::RecordNotFound
|
37
|
+
:not_found.should.messaging(message) == status
|
47
38
|
end
|
48
|
-
|
49
|
-
|
39
|
+
end
|
40
|
+
else
|
41
|
+
test_case.it description do
|
42
|
+
send(verb, action, immediate_values(params))
|
43
|
+
status.should.messaging(message) == status
|
50
44
|
end
|
51
45
|
end
|
46
|
+
else
|
47
|
+
super
|
52
48
|
end
|
53
49
|
end
|
54
50
|
end
|
@@ -1,40 +1,36 @@
|
|
1
|
-
module Test
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
def layout
|
35
|
-
Test::Spec::Rails::Layout.new(self)
|
36
|
-
end
|
37
|
-
end
|
1
|
+
module Test::Spec::Rails
|
2
|
+
class Status < SpecResponder
|
3
|
+
def should_equal(status, message=nil)
|
4
|
+
@test_case.send(:assert_response, status, message)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
class Template < SpecResponder
|
9
|
+
def should_equal(template, message=nil)
|
10
|
+
@test_case.send(:assert_template, template, message)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Layout < SpecResponder
|
15
|
+
def should_equal(layout, message=nil)
|
16
|
+
rendered_layout = @test_case.response.layout.gsub(/layouts\//, '')
|
17
|
+
@test_case.send(:assert_equal, layout, rendered_layout, message)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module ResponseHelpers
|
22
|
+
attr_reader :response
|
23
|
+
|
24
|
+
def status
|
25
|
+
Test::Spec::Rails::Status.new(self)
|
26
|
+
end
|
27
|
+
|
28
|
+
def template
|
29
|
+
Test::Spec::Rails::Template.new(self)
|
30
|
+
end
|
31
|
+
|
32
|
+
def layout
|
33
|
+
Test::Spec::Rails::Layout.new(self)
|
38
34
|
end
|
39
35
|
end
|
40
36
|
end
|
@@ -1,12 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
attr_accessor :test_case
|
6
|
-
def initialize(test_case)
|
7
|
-
self.test_case = test_case
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
1
|
+
class Test::Spec::Rails::SpecResponder
|
2
|
+
attr_accessor :test_case
|
3
|
+
def initialize(test_case)
|
4
|
+
self.test_case = test_case
|
11
5
|
end
|
12
6
|
end
|
data/lib/test/spec/share.rb
CHANGED
data/test/expectations_test.rb
CHANGED
@@ -395,6 +395,66 @@ describe "Record expectations" do
|
|
395
395
|
end
|
396
396
|
end
|
397
397
|
|
398
|
+
class Account < ActiveRecord::Base
|
399
|
+
validates_presence_of :username
|
400
|
+
end
|
401
|
+
|
402
|
+
describe "Validation expectations" do
|
403
|
+
include AssertionAssertions
|
404
|
+
|
405
|
+
def configure_database
|
406
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
407
|
+
ActiveRecord::Migration.verbose = false
|
408
|
+
end
|
409
|
+
|
410
|
+
def setup_database
|
411
|
+
ActiveRecord::Schema.define(:version => 1) do
|
412
|
+
create_table :accounts do |t|
|
413
|
+
t.column :fullname, :string
|
414
|
+
t.column :email, :string
|
415
|
+
t.column :username, :string
|
416
|
+
t.column :password, :string
|
417
|
+
end
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
def teardown_database
|
422
|
+
ActiveRecord::Base.connection.tables.each do |table|
|
423
|
+
ActiveRecord::Base.connection.drop_table(table)
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
before(:all) { configure_database }
|
428
|
+
|
429
|
+
before do
|
430
|
+
setup_database
|
431
|
+
TestingAssertionsThemselves.setup
|
432
|
+
@account = Account.new
|
433
|
+
end
|
434
|
+
|
435
|
+
after { teardown_database }
|
436
|
+
|
437
|
+
it "succeeds when there are no validation errors on the attribute and there were no expected" do
|
438
|
+
@account.should.validate_with(:username, 'admin')
|
439
|
+
assert_assert_success
|
440
|
+
end
|
441
|
+
|
442
|
+
it "fails when there are no validation errors on the attribute and there was one expected" do
|
443
|
+
@account.should.not.validate_with(:email, '')
|
444
|
+
assert_assert_failure("Expected errors on :email with value `\"\"' after validation")
|
445
|
+
end
|
446
|
+
|
447
|
+
it "succeeds when there is a validation error on the attribute and there was one expected" do
|
448
|
+
@account.should.not.validate_with(:username, '')
|
449
|
+
assert_assert_success
|
450
|
+
end
|
451
|
+
|
452
|
+
it "fails when there is a validation error on the attribute and there were no expected" do
|
453
|
+
@account.should.validate_with(:username, '')
|
454
|
+
assert_assert_failure("Expected :username with value `\"\"' to validate")
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
398
458
|
class TestController
|
399
459
|
def request
|
400
460
|
unless @request
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: on-test-spec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 3
|
9
|
+
- 0
|
10
|
+
version: 0.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Manfred Stienstra
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2011-
|
20
|
+
date: 2011-03-23 00:00:00 +01:00
|
21
21
|
default_executable:
|
22
22
|
dependencies: []
|
23
23
|
|