riot_rails 0.0.8 → 0.0.9.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/CHANGELOG +122 -0
  2. data/MIT-LICENSE +1 -1
  3. data/README.markdown +22 -7
  4. data/Rakefile +3 -2
  5. data/VERSION +1 -1
  6. data/lib/riot/action_controller/assertion_macros.rb +48 -34
  7. data/lib/riot/action_controller/context_helper.rb +12 -0
  8. data/lib/riot/action_controller/context_macros.rb +58 -12
  9. data/lib/riot/action_controller/situation_macros.rb +73 -6
  10. data/lib/riot/action_controller.rb +2 -0
  11. data/lib/riot/active_record/assertion_macros.rb +3 -158
  12. data/lib/riot/active_record/context_helper.rb +19 -0
  13. data/lib/riot/active_record/database_macros.rb +58 -0
  14. data/lib/riot/active_record/reflection_macros.rb +106 -0
  15. data/lib/riot/active_record/validation_macros.rb +187 -0
  16. data/lib/riot/active_record.rb +2 -0
  17. data/lib/riot/rails.rb +1 -2
  18. data/lib/riot/rails_context.rb +84 -0
  19. data/riot_rails.gemspec +35 -9
  20. data/test/action_controller/controller_context_test.rb +39 -9
  21. data/test/action_controller/redirected_to_test.rb +6 -11
  22. data/test/action_controller/renders_template_test.rb +7 -7
  23. data/test/action_controller/renders_test.rb +6 -6
  24. data/test/action_controller/response_status_test.rb +11 -11
  25. data/test/active_record/allowing_values_test.rb +9 -9
  26. data/test/active_record/attribute_is_invalid_test.rb +20 -0
  27. data/test/active_record/belongs_to_test.rb +22 -0
  28. data/test/active_record/has_and_belongs_to_many_test.rb +22 -0
  29. data/test/active_record/has_database_index_on_test.rb +73 -0
  30. data/test/active_record/has_many_test.rb +7 -3
  31. data/test/active_record/has_one_test.rb +22 -0
  32. data/test/active_record/validates_length_of_test.rb +31 -0
  33. data/test/active_record/validates_presence_of_test.rb +1 -1
  34. data/test/active_record/validates_uniqueness_of_test.rb +3 -3
  35. data/test/rails_context_test.rb +103 -0
  36. data/test/rails_root/config/environment.rb +46 -0
  37. data/test/rails_root/config/routes.rb +3 -4
  38. data/test/rails_root/db/schema.rb +1 -2
  39. data/test/teststrap.rb +44 -69
  40. metadata +39 -6
data/riot_rails.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{riot_rails}
8
- s.version = "0.0.8"
8
+ s.version = "0.0.9.pre"
9
9
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
10
+ s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Justin 'Gus' Knowlden"]
12
- s.date = %q{2009-12-29}
12
+ s.date = %q{2010-02-20}
13
13
  s.description = %q{Riot specific test support for Rails apps. Protest the slow app.}
14
14
  s.email = %q{gus@gusg.us}
15
15
  s.extra_rdoc_files = [
@@ -17,17 +17,24 @@ Gem::Specification.new do |s|
17
17
  ]
18
18
  s.files = [
19
19
  ".gitignore",
20
+ "CHANGELOG",
20
21
  "MIT-LICENSE",
21
22
  "README.markdown",
22
23
  "Rakefile",
23
24
  "VERSION",
24
25
  "lib/riot/action_controller.rb",
25
26
  "lib/riot/action_controller/assertion_macros.rb",
27
+ "lib/riot/action_controller/context_helper.rb",
26
28
  "lib/riot/action_controller/context_macros.rb",
27
29
  "lib/riot/action_controller/situation_macros.rb",
28
30
  "lib/riot/active_record.rb",
29
31
  "lib/riot/active_record/assertion_macros.rb",
32
+ "lib/riot/active_record/context_helper.rb",
33
+ "lib/riot/active_record/database_macros.rb",
34
+ "lib/riot/active_record/reflection_macros.rb",
35
+ "lib/riot/active_record/validation_macros.rb",
30
36
  "lib/riot/rails.rb",
37
+ "lib/riot/rails_context.rb",
31
38
  "rails/init.rb",
32
39
  "riot_rails.gemspec",
33
40
  "test/action_controller/controller_context_test.rb",
@@ -36,10 +43,18 @@ Gem::Specification.new do |s|
36
43
  "test/action_controller/renders_test.rb",
37
44
  "test/action_controller/response_status_test.rb",
38
45
  "test/active_record/allowing_values_test.rb",
46
+ "test/active_record/attribute_is_invalid_test.rb",
47
+ "test/active_record/belongs_to_test.rb",
48
+ "test/active_record/has_and_belongs_to_many_test.rb",
49
+ "test/active_record/has_database_index_on_test.rb",
39
50
  "test/active_record/has_many_test.rb",
51
+ "test/active_record/has_one_test.rb",
52
+ "test/active_record/validates_length_of_test.rb",
40
53
  "test/active_record/validates_presence_of_test.rb",
41
54
  "test/active_record/validates_uniqueness_of_test.rb",
55
+ "test/rails_context_test.rb",
42
56
  "test/rails_root/app/views/rendered_templates/foo_bar.html.erb",
57
+ "test/rails_root/config/environment.rb",
43
58
  "test/rails_root/config/routes.rb",
44
59
  "test/rails_root/db/schema.rb",
45
60
  "test/teststrap.rb"
@@ -56,9 +71,17 @@ Gem::Specification.new do |s|
56
71
  "test/action_controller/renders_test.rb",
57
72
  "test/action_controller/response_status_test.rb",
58
73
  "test/active_record/allowing_values_test.rb",
74
+ "test/active_record/attribute_is_invalid_test.rb",
75
+ "test/active_record/belongs_to_test.rb",
76
+ "test/active_record/has_and_belongs_to_many_test.rb",
77
+ "test/active_record/has_database_index_on_test.rb",
59
78
  "test/active_record/has_many_test.rb",
79
+ "test/active_record/has_one_test.rb",
80
+ "test/active_record/validates_length_of_test.rb",
60
81
  "test/active_record/validates_presence_of_test.rb",
61
82
  "test/active_record/validates_uniqueness_of_test.rb",
83
+ "test/rails_context_test.rb",
84
+ "test/rails_root/config/environment.rb",
62
85
  "test/rails_root/config/routes.rb",
63
86
  "test/rails_root/db/schema.rb",
64
87
  "test/teststrap.rb"
@@ -69,15 +92,18 @@ Gem::Specification.new do |s|
69
92
  s.specification_version = 3
70
93
 
71
94
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
72
- s.add_runtime_dependency(%q<riot>, [">= 0.10.2"])
73
- s.add_development_dependency(%q<activerecord>, [">= 2.3.2"])
95
+ s.add_runtime_dependency(%q<riot>, [">= 0.10.13.pre"])
96
+ s.add_development_dependency(%q<activerecord>, [">= 3.0.0.pre"])
97
+ s.add_development_dependency(%q<actionpack>, [">= 3.0.0.pre"])
74
98
  else
75
- s.add_dependency(%q<riot>, [">= 0.10.2"])
76
- s.add_dependency(%q<activerecord>, [">= 2.3.2"])
99
+ s.add_dependency(%q<riot>, [">= 0.10.13.pre"])
100
+ s.add_dependency(%q<activerecord>, [">= 3.0.0.pre"])
101
+ s.add_dependency(%q<actionpack>, [">= 3.0.0.pre"])
77
102
  end
78
103
  else
79
- s.add_dependency(%q<riot>, [">= 0.10.2"])
80
- s.add_dependency(%q<activerecord>, [">= 2.3.2"])
104
+ s.add_dependency(%q<riot>, [">= 0.10.13.pre"])
105
+ s.add_dependency(%q<activerecord>, [">= 3.0.0.pre"])
106
+ s.add_dependency(%q<actionpack>, [">= 3.0.0.pre"])
81
107
  end
82
108
  end
83
109
 
@@ -1,24 +1,54 @@
1
1
  require 'teststrap'
2
2
 
3
3
  class FoosController < ActionController::Base
4
+ def index
5
+ @thing = "hoo ray"
6
+ render :text => ''
7
+ end
4
8
  end
5
9
 
6
- context "A controller test" do
10
+ rails_context "A controller test" do
7
11
  controlling :foos
8
12
 
9
13
  asserts_controller.kind_of(FoosController)
14
+ asserts_topic.kind_of(FoosController)
10
15
 
11
- asserts("request is accessible") { request }.kind_of(::ActionController::TestRequest)
12
- asserts("response is accessible") { response }.kind_of(::ActionController::TestResponse)
16
+ asserts("request is accessible") { request }.kind_of(::ActionDispatch::TestRequest)
17
+ asserts("response is accessible") { response }.kind_of(::ActionDispatch::TestResponse)
13
18
  asserts("params is accessible") { controller.params }.equals({})
14
19
 
15
- asserts("http method shortcut for get") { self }.respond_to(:get)
16
- asserts("http method shortcut for post") { self }.respond_to(:post)
17
- asserts("http method shortcut for put") { self }.respond_to(:put)
18
- asserts("http method shortcut for delete") { self }.respond_to(:delete)
20
+ asserts("http method shortcut for get") { self }.responds_to(:get)
21
+ asserts("http method shortcut for post") { self }.responds_to(:post)
22
+ asserts("http method shortcut for put") { self }.responds_to(:put)
23
+ asserts("http method shortcut for delete") { self }.responds_to(:delete)
24
+ asserts("http method shortcut for xml_http_request") { self }.responds_to(:xml_http_request)
25
+ asserts("http method shortcut for xhr") { self }.responds_to(:xhr)
19
26
 
20
27
  asserts("an unknown action call") do
21
28
  get :burberry
22
- end.raises(::ActionController::UnknownAction, "No action responded to burberry")
29
+ end.raises(::ActionController::UnknownAction, "The action 'burberry' could not be found")
30
+ end # A controller test
23
31
 
24
- end # a controller test
32
+ rails_context "A controller test using class as argument" do
33
+ controlling FoosController
34
+
35
+ asserts_controller.kind_of(FoosController)
36
+ end # A controller test using class as argument
37
+
38
+ rails_context FoosController do
39
+ hookup do
40
+ @actual_class_name = topic.class.name
41
+ get :index
42
+ end
43
+
44
+ asserts("actual class name") { @actual_class_name }.equals("FoosController")
45
+
46
+ asserts_assigned(:thing).equals("hoo ray")
47
+ asserts_assigned(:that).nil
48
+
49
+ asserts_response.kind_of(::ActionDispatch::TestResponse)
50
+ asserts_response(:response_code).equals(200)
51
+
52
+ asserts_request.kind_of(::ActionDispatch::TestRequest)
53
+ asserts_request(:cookies).kind_of(Hash)
54
+ end # A controller test with a hookup using the controller
@@ -13,29 +13,24 @@ end
13
13
  context "Asserting the redirect of an action" do
14
14
  setup do
15
15
  @situation = Riot::Situation.new
16
- context = Riot::Context.new("redirected to") {}
16
+ context = RiotRails::RailsContext.new("redirected to") {}
17
17
  context.controlling(:redirected_to).run(@situation)
18
18
  context
19
19
  end
20
20
 
21
21
  context "when doing an actual redirect" do
22
- setup_for_assertion_test { get :index }
22
+ hookup_for_assertion_test { get :index }
23
23
 
24
- assertion_test_passes("when expected url matches actual redirect url", "redirected to /gremlins/new") do
25
- topic.asserts_controller.redirected_to { new_gremlin_path }
26
- end
27
-
28
- assertion_test_fails("when expected url does not exactly match actual redirect url",
29
- "expected to redirect to <http://test.host/gremlins/new>, not </gremlins/new>") do
30
- topic.asserts_controller.redirected_to { new_gremlin_url }
24
+ assertion_test_passes("when expected url matches actual redirect url", "redirected to http://test.host/gremlins/new") do
25
+ topic.asserts(:response).redirected_to { new_gremlin_url }
31
26
  end
32
27
  end # when doing an actual redirect
33
28
 
34
29
  context "when not actually doing a redirect" do
35
- setup_for_assertion_test { get :show }
30
+ hookup_for_assertion_test { get :show }
36
31
  assertion_test_fails("with message about expecting a redirect",
37
32
  "expected response to be a redirect, but was 200") do
38
- topic.asserts_controller.redirected_to { new_gremlin_path }
33
+ topic.asserts(:response).redirected_to { new_gremlin_path }
39
34
  end
40
35
  end # when not actually doing a redirect
41
36
  end # Asserting the redirect of an action
@@ -8,26 +8,26 @@ end
8
8
  context "Asserting the rendered template for an action" do
9
9
  setup do
10
10
  @situation = Riot::Situation.new
11
- context = Riot::Context.new("rendered_template") {}
11
+ context = RiotRails::RailsContext.new("rendered_template") {}
12
12
  context.controlling(:rendered_templates).run(@situation)
13
13
  context
14
14
  end
15
15
 
16
16
  context "that rendered a template" do
17
- setup_for_assertion_test { get :foo_bar }
17
+ hookup_for_assertion_test { get :foo_bar }
18
18
 
19
19
  assertion_test_passes("when rendered template name matches expectation", %Q{renders template "foo_bar"}) do
20
20
  topic.asserts_controller.renders_template('foo_bar')
21
21
  end
22
22
 
23
23
  assertion_test_fails("when rendered template does not match expectation",
24
- %Q{expected template "bar_foo", not "rendered_templates/foo_bar.html.erb"}) do
24
+ %Q{expected template "bar_foo", not "app/views/rendered_templates/foo_bar.html.erb"}) do
25
25
  topic.asserts_controller.renders_template('bar_foo')
26
26
  end
27
27
  end # that rendered a template
28
28
 
29
29
  context "that did not render a template, as was expected" do
30
- setup_for_assertion_test { get :text_me }
30
+ hookup_for_assertion_test { get :text_me }
31
31
 
32
32
  assertion_test_passes("when providing nil as expectation", %Q{renders template ""}) do
33
33
  topic.asserts_controller.renders_template(nil)
@@ -39,17 +39,17 @@ context "Asserting the rendered template for an action" do
39
39
  end # that did not render a template, as was expected
40
40
 
41
41
  context "that did not render a template but expected one" do
42
- setup_for_assertion_test { get :text_me }
42
+ hookup_for_assertion_test { get :text_me }
43
43
  assertion_test_fails("with message", %Q{expected template "text_me", not ""}) do
44
44
  topic.asserts_controller.renders_template('text_me')
45
45
  end
46
46
  end # that did not render a template but expected one
47
47
 
48
48
  context "that rendered a template with a partial match on template name" do
49
- setup_for_assertion_test { get :foo_bar }
49
+ hookup_for_assertion_test { get :foo_bar }
50
50
 
51
51
  assertion_test_fails("with message",
52
- %Q{expected template "foo", not "rendered_templates/foo_bar.html.erb"}) do
52
+ %Q{expected template "foo", not "app/views/rendered_templates/foo_bar.html.erb"}) do
53
53
  topic.asserts_controller.renders_template('foo')
54
54
  end
55
55
  end # that rendered a template with a partial match on template name
@@ -7,24 +7,24 @@ end
7
7
  context "Asserting the body of a response" do
8
8
  setup do
9
9
  @situation = Riot::Situation.new
10
- context = Riot::Context.new("renders") {}
10
+ context = RiotRails::RailsContext.new("renders") {}
11
11
  context.controlling(:renders).run(@situation)
12
- context.setup { get :index }.run(@situation)
12
+ context.hookup { get :index }.run(@situation)
13
13
  context
14
14
  end
15
15
 
16
- assertion_test_passes("when body equals expected") { topic.asserts_controller.renders("Yo mama") }
16
+ assertion_test_passes("when body equals expected") { topic.asserts(:response).renders("Yo mama") }
17
17
 
18
18
  assertion_test_fails("when rendered action body does not equal expected",
19
19
  %Q{expected response body "Yo mama" to equal "Yo"}) do
20
- topic.asserts_controller.renders("Yo")
20
+ topic.asserts(:response).renders("Yo")
21
21
  end
22
22
 
23
- assertion_test_passes("when body matches expected") { topic.asserts_controller.renders(/mama/) }
23
+ assertion_test_passes("when body matches expected") { topic.asserts(:response).renders(/mama/) }
24
24
 
25
25
  assertion_test_fails("when rendered action body does not match expected",
26
26
  %Q{expected response body "Yo mama" to match /obama/}) do
27
- topic.asserts_controller.renders(/obama/)
27
+ topic.asserts(:response).renders(/obama/)
28
28
  end
29
29
 
30
30
  end # Asserting the body of a response
@@ -9,48 +9,48 @@ end
9
9
  context "Asserting the response status for an action" do
10
10
  setup do
11
11
  @situation = Riot::Situation.new
12
- context = Riot::Context.new("response status") {}
12
+ context = RiotRails::RailsContext.new("response status") {}
13
13
  context.controlling(:response_codes).run(@situation)
14
14
  context
15
15
  end
16
16
 
17
17
  context "returning OK" do
18
- setup_for_assertion_test { get :ok_go }
18
+ hookup_for_assertion_test { get :ok_go }
19
19
 
20
20
  assertion_test_passes("when asked if :ok", "returns response code 200") do
21
- topic.asserts_controller.response_code(:ok)
21
+ topic.asserts(:response).code(:ok)
22
22
  end
23
23
 
24
24
  assertion_test_passes("when asked if 200", "returns response code 200") do
25
- topic.asserts_controller.response_code(200)
25
+ topic.asserts(:response).code(200)
26
26
  end
27
27
 
28
28
  assertion_test_fails("when CONTINUE returned instead", %Q{expected response code 100, not 200}) do
29
- topic.asserts_controller.response_code(100)
29
+ topic.asserts(:response).code(100)
30
30
  end
31
31
  end # returning OK
32
32
 
33
33
  context "that is redirecting" do
34
- setup_for_assertion_test { get :fffound }
34
+ hookup_for_assertion_test { get :fffound }
35
35
 
36
36
  assertion_test_passes("when asked if :found", "returns response code 302") do
37
- topic.asserts_controller.response_code(:found)
37
+ topic.asserts(:response).code(:found)
38
38
  end
39
39
 
40
40
  assertion_test_passes("when asked if 302", "returns response code 302") do
41
- topic.asserts_controller.response_code(302)
41
+ topic.asserts(:response).code(302)
42
42
  end
43
43
  end # that is redirecting
44
44
 
45
45
  context "that has explicit status" do
46
- setup_for_assertion_test { get :make_me }
46
+ hookup_for_assertion_test { get :make_me }
47
47
 
48
48
  assertion_test_passes("when asked if :created", "returns response code 201") do
49
- topic.asserts_controller.response_code(:created)
49
+ topic.asserts(:response).code(:created)
50
50
  end
51
51
 
52
52
  assertion_test_passes("when asked if 201", "returns response code 201") do
53
- topic.asserts_controller.response_code(201)
53
+ topic.asserts(:response).code(201)
54
54
  end
55
55
  end # that has explicit status
56
56
 
@@ -6,15 +6,15 @@ context "The allow_values_for assertion macro" do
6
6
 
7
7
  should("pass when attribute allows a value") do
8
8
  topic.allows_values_for(:email, "a@b.cd").run(Riot::Situation.new)
9
- end.equals([:pass, nil])
9
+ end.equals([:pass, ""])
10
10
 
11
11
  should("pass when attribute allows multiple values") do
12
12
  topic.allows_values_for(:email, "a@b.cd", "e@f.gh").run(Riot::Situation.new)
13
- end.equals([:pass, nil])
13
+ end.equals([:pass, ""])
14
14
 
15
15
  should("fail when attribute is provided a valid and an invalid value") do
16
16
  topic.allows_values_for(:email, "a", "e@f.gh").run(Riot::Situation.new)
17
- end.equals([:fail, %Q{expected :email to allow value(s) ["a"]}])
17
+ end.equals([:fail, %Q{expected :email to allow values ["a"]}, blah, blah])
18
18
  end # The allow_values_for assertion macro
19
19
 
20
20
  context "The does_not_allow_values_for assertion macro" do
@@ -23,15 +23,15 @@ context "The does_not_allow_values_for assertion macro" do
23
23
 
24
24
  should("pass when attribute does not allow a value") do
25
25
  topic.does_not_allow_values_for(:email, "a").run(Riot::Situation.new)
26
- end.equals([:pass, nil])
26
+ end.equals([:pass, ""])
27
27
 
28
28
  should("pass when attribute does not allow multiple values") do
29
29
  topic.does_not_allow_values_for(:email, "a", "e").run(Riot::Situation.new)
30
- end.equals([:pass, nil])
30
+ end.equals([:pass, ""])
31
31
 
32
32
  should("fail when attribute is provided a valid and an invalid value") do
33
33
  topic.does_not_allow_values_for(:email, "a", "e@f.gh").run(Riot::Situation.new)
34
- end.equals([:fail, %Q{expected :email not to allow value(s) ["e@f.gh"]}])
34
+ end.equals([:fail, %Q{expected :email not to allow values ["e@f.gh"]}, blah, blah])
35
35
  end # The does_not_allow_values_for assertion macro
36
36
 
37
37
  context "The is_invalid_when assertion macro" do
@@ -52,13 +52,13 @@ context "The is_invalid_when assertion macro" do
52
52
 
53
53
  should("fail when attribute is valid") do
54
54
  topic.is_invalid_when(:email, "a@b.cd", "is invalid").run(Riot::Situation.new)
55
- end.equals([:fail, %Q{expected :email to be invalid when value is "a@b.cd"}])
55
+ end.equals([:fail, %Q{expected :email to be invalid when value is "a@b.cd"}, blah, blah])
56
56
 
57
57
  should("fail when exact error message not found") do
58
58
  topic.is_invalid_when(:email, "fake", "can't be blank").run(Riot::Situation.new)
59
- end.equals([:fail, %Q{expected :email to be invalid with error message "can't be blank"}])
59
+ end.equals([:fail, %Q{expected :email to be invalid with error message "can't be blank"}, blah, blah])
60
60
 
61
61
  should("fail when error message not matched to returned errors") do
62
62
  topic.is_invalid_when(:email, "fake", /blank/).run(Riot::Situation.new)
63
- end.equals([:fail, %Q{expected :email to be invalid with error message /blank/}])
63
+ end.equals([:fail, %Q{expected :email to be invalid with error message /blank/}, blah, blah])
64
64
  end # The is_invalid_when assertion macro
@@ -0,0 +1,20 @@
1
+ require 'teststrap'
2
+
3
+ context "The attribute_is_invalid macro" do
4
+ setup_test_context
5
+
6
+ should("fail when attribute is not invalid") do
7
+ assertion = topic.asserts("room") { Room.new(:location => "barn burner") }
8
+ assertion.attribute_is_invalid(:location, "not yet").run(Riot::Situation.new)
9
+ end.equals([:fail, ":location expected to be invalid", blah, blah])
10
+
11
+ should("fail when attribute is invalid, but the message could not be found") do
12
+ assertion = topic.asserts("room") { Room.new }
13
+ assertion.attribute_is_invalid(:location, "child please").run(Riot::Situation.new)
14
+ end.equals([:fail, %Q{:location is invalid, but "child please" is not a valid error message}, blah, blah])
15
+
16
+ should("pass when attribute is invalid and error message is found") do
17
+ assertion = topic.asserts("room") { Room.new }
18
+ assertion.attribute_is_invalid(:location, "can't be blank").run(Riot::Situation.new)
19
+ end.equals([:pass, %Q{:location is invalid}])
20
+ end # The attribute_is_invalid macro
@@ -0,0 +1,22 @@
1
+ require 'teststrap'
2
+
3
+ context "The belongs_to assertion macro" do
4
+ setup_test_context
5
+ setup { topic.asserts("room") { Room.new } }
6
+
7
+ should("pass when record has a belongs_to association defined for attribute") do
8
+ topic.belongs_to(:house).run(Riot::Situation.new)
9
+ end.equals([:pass, ":house is a belongs_to association"])
10
+
11
+ should("fail when record does not have a belongs_to association defined for attribute") do
12
+ topic.belongs_to(:someone_else).run(Riot::Situation.new)
13
+ end.equals([:fail, ":someone_else is not a belongs_to association", blah, blah])
14
+
15
+ should("fail when attribute is not a belongs_to, but is a has_one association") do
16
+ topic.belongs_to(:floor).run(Riot::Situation.new)
17
+ end.equals([:fail, ":floor is not a belongs_to association", blah, blah])
18
+
19
+ should("fail when association options are specified, but they do not match the record") do
20
+ topic.belongs_to(:owner, :class_name => "Person").run(Riot::Situation.new)
21
+ end.equals([:fail, %q[expected belongs_to :owner with {:class_name=>"Person"}], blah, blah])
22
+ end # The has_many assertion macro
@@ -0,0 +1,22 @@
1
+ require 'teststrap'
2
+
3
+ context "The has_and_belongs_to_many assertion macro" do
4
+ setup_test_context
5
+ setup { topic.asserts("room") { Room.new } }
6
+
7
+ should("pass when record has a has_and_belongs_to_many association defined for attribute") do
8
+ topic.has_and_belongs_to_many(:walls).run(Riot::Situation.new)
9
+ end.equals([:pass, ":walls is a has_and_belongs_to_many association"])
10
+
11
+ should("fail when record does not have a has_and_belongs_to_many association defined for attribute") do
12
+ topic.has_and_belongs_to_many(:windows).run(Riot::Situation.new)
13
+ end.equals([:fail, ":windows is not a has_and_belongs_to_many association", blah, blah])
14
+
15
+ should("fail when attribute is not a has_and_belongs_to_many, but is a has_many association") do
16
+ topic.has_and_belongs_to_many(:doors).run(Riot::Situation.new)
17
+ end.equals([:fail, ":doors is not a has_and_belongs_to_many association", blah, blah])
18
+
19
+ should("fail when association options are specified, but they do not match the record") do
20
+ topic.has_and_belongs_to_many(:walls, :join_table => "blueprints").run(Riot::Situation.new)
21
+ end.equals([:fail, %q[expected has_and_belongs_to_many :walls with {:join_table=>"blueprints"}], blah, blah])
22
+ end # The has_and_belongs_to_many assertion macro
@@ -0,0 +1,73 @@
1
+ require 'teststrap'
2
+ require 'ostruct'
3
+
4
+ context "The has_database_index_on macro" do
5
+ setup_test_context
6
+ setup { topic.asserts("room") { Room.new } }
7
+
8
+ hookup do
9
+ MockConnection = Class.new do
10
+ def initialize(index_lookup) @index_lookup = index_lookup; end
11
+ def indexes(table) @index_lookup[table]; end
12
+ end
13
+
14
+ def build_assertion(table, columns, unique=false)
15
+ database_connection = MockConnection.new({table => [ define_index(table, columns, unique) ]})
16
+ # I'll inject your dependency! ;)
17
+ RiotRails::ActiveRecord::HasDatabaseIndexOnMacro.new(database_connection)
18
+ end
19
+
20
+ def define_index(table, columns, unique)
21
+ ActiveRecord::ConnectionAdapters::IndexDefinition.new(table, columns.join(','), unique, columns)
22
+ end
23
+ end
24
+
25
+ should("fail when no index for column") do
26
+ topic.has_database_index_on(:foo).run(Riot::Situation.new)
27
+ end.equals([:fail, %Q{expected index on [:foo]}, blah, blah])
28
+
29
+ should("fail when no index for column set") do
30
+ topic.has_database_index_on(:foo, :bar).run(Riot::Situation.new)
31
+ end.equals([:fail, %Q{expected index on [:foo, :bar]}, blah, blah])
32
+
33
+ should("fail when index found for column, but it's not unique") do
34
+ build_assertion("rooms", ["foo"], false).
35
+ evaluate(Room.new, :foo, :unique => true)
36
+ end.equals([:fail, %Q{expected unique index on [:foo]}, blah, blah])
37
+
38
+ should("fail when index found for column, but it's unique and should not be") do
39
+ build_assertion("rooms", ["foo"], true).
40
+ evaluate(Room.new, :foo, :unique => false)
41
+ end.equals([:fail, %Q{expected index on [:foo]}, blah, blah])
42
+
43
+ should("pass when index found for column") do
44
+ build_assertion("rooms", ["foo"], false).
45
+ evaluate(Room.new, :foo)
46
+ end.equals([:pass, %Q{has index on [:foo]}])
47
+
48
+ should("pass when index found for column set") do
49
+ build_assertion("rooms", ["foo", "bar"], false).
50
+ evaluate(Room.new, :foo, :bar)
51
+ end.equals([:pass, %Q{has index on [:foo, :bar]}])
52
+
53
+ should("pass when unique index found for column") do
54
+ build_assertion("rooms", ["foo"], true).
55
+ evaluate(Room.new, :foo, :unique => true)
56
+ end.equals([:pass, %Q{has unique index on [:foo]}])
57
+
58
+ should("pass when unique index found for column set") do
59
+ build_assertion("rooms", ["foo", "bar"], true).
60
+ evaluate(Room.new, :foo, :bar, :unique => true)
61
+ end.equals([:pass, %Q{has unique index on [:foo, :bar]}])
62
+
63
+ should("pass when non-unique index found for column") do
64
+ build_assertion("rooms", ["foo"], false).
65
+ evaluate(Room.new, :foo, :unique => false)
66
+ end.equals([:pass, %Q{has index on [:foo]}])
67
+
68
+ should("pass when non-unique index found for column set") do
69
+ build_assertion("rooms", ["foo", "bar"], false).
70
+ evaluate(Room.new, :foo, :bar, :unique => false)
71
+ end.equals([:pass, %Q{has index on [:foo, :bar]}])
72
+
73
+ end # The attribute_is_invalid macro
@@ -6,13 +6,17 @@ context "The has_many assertion macro" do
6
6
 
7
7
  should("pass when record has a has_many association defined for attribute") do
8
8
  topic.has_many(:doors).run(Riot::Situation.new)
9
- end.equals([:pass, "has many :doors"])
9
+ end.equals([:pass, ":doors is a has_many association"])
10
10
 
11
11
  should("fail when record does not have a has_many association defined for attribute") do
12
12
  topic.has_many(:windows).run(Riot::Situation.new)
13
- end.equals([:fail, "expected :windows to be a has_many association, but was not"])
13
+ end.equals([:fail, ":windows is not a has_many association", blah, blah])
14
14
 
15
15
  should("fail when attribute is not a has_many, but is a has_one association") do
16
16
  topic.has_many(:floor).run(Riot::Situation.new)
17
- end.equals([:fail, "expected :floor to be a has_many association, but was a has_one instead"])
17
+ end.equals([:fail, ":floor is not a has_many association", blah, blah])
18
+
19
+ should("fail when association options are specified, but they do not match the record") do
20
+ topic.has_many(:doors, :class_name => "Portal").run(Riot::Situation.new)
21
+ end.equals([:fail, %q[expected has_many :doors with {:class_name=>"Portal"}], blah, blah])
18
22
  end # The has_many assertion macro
@@ -0,0 +1,22 @@
1
+ require 'teststrap'
2
+
3
+ context "The has_one assertion macro" do
4
+ setup_test_context
5
+ setup { topic.asserts("room") { Room.new } }
6
+
7
+ should("pass when record has a has_one association defined for attribute") do
8
+ topic.has_one(:floor).run(Riot::Situation.new)
9
+ end.equals([:pass, ":floor is a has_one association"])
10
+
11
+ should("fail when record does not have a has_one association defined for attribute") do
12
+ topic.has_one(:windows).run(Riot::Situation.new)
13
+ end.equals([:fail, ":windows is not a has_one association", blah, blah])
14
+
15
+ should("fail when attribute is not a has_one, but is a has_many association") do
16
+ topic.has_one(:doors).run(Riot::Situation.new)
17
+ end.equals([:fail, ":doors is not a has_one association", blah, blah])
18
+
19
+ should("fail when association options are specified, but they do not match the record") do
20
+ topic.has_one(:floor, :class_name => "Surface").run(Riot::Situation.new)
21
+ end.equals([:fail, %q[expected has_one :floor with {:class_name=>"Surface"}], blah, blah])
22
+ end # The has_one assertion macro
@@ -0,0 +1,31 @@
1
+ require 'teststrap'
2
+
3
+ context "The validates_length_of assertion macro" do
4
+ setup_test_context
5
+ setup { topic.asserts("room") { Room.new } }
6
+
7
+ should("fail when minimum length causes an error") do
8
+ topic.validates_length_of(:name, (4..15)).run(Riot::Situation.new)
9
+ end.equals([:fail, ":name should be able to be 4 characters", blah, blah])
10
+
11
+ should("fail when value less than minimum value does not cause an error") do
12
+ topic.validates_length_of(:name, (6..15)).run(Riot::Situation.new)
13
+ end.equals([:fail, ":name expected to be more than 5 characters", blah, blah])
14
+
15
+ should("fail when maximum length causes an error") do
16
+ topic.validates_length_of(:name, (5..21)).run(Riot::Situation.new)
17
+ end.equals([:fail, ":name should be able to be 21 characters", blah, blah])
18
+
19
+ should("fail when value greater than maximum value does not cause an error") do
20
+ topic.validates_length_of(:name, (5..19)).run(Riot::Situation.new)
21
+ end.equals([:fail, ":name expected to be less than 20 characters", blah, blah])
22
+
23
+ should("pass when only a value can only be within the specific range") do
24
+ topic.validates_length_of(:name, (5..20)).run(Riot::Situation.new)
25
+ end.equals([:pass, "validates length of :name is within 5..20"])
26
+
27
+ should("pass even when minimum value is zero") do
28
+ topic.validates_length_of(:contents, (0..100)).run(Riot::Situation.new)
29
+ end.equals([:pass, "validates length of :contents is within 0..100"])
30
+
31
+ end # The validates_length_of assertion macro
@@ -10,5 +10,5 @@ context "The validates_presence_of assertion macro" do
10
10
 
11
11
  should("fail when attribute does not require presence") do
12
12
  topic.validates_presence_of(:contents).run(Riot::Situation.new)
13
- end.equals([:fail, "expected to validate presence of :contents"])
13
+ end.equals([:fail, "expected to validate presence of :contents", blah, blah])
14
14
  end # The validates_presence_of assertion macro
@@ -5,9 +5,9 @@ context "The validates_uniqueness_of assertion macro" do
5
5
 
6
6
  should("fail without a persisted record") do
7
7
  topic.asserts("room") do
8
- Room.new(:email => "foo@bar.baz", :foo => "what")
8
+ Room.new(:email => "foo@bar.baz")
9
9
  end.validates_uniqueness_of(:email).run(Riot::Situation.new)
10
- end.equals([:fail, "topic is not a new record when testing uniqueness of :email"])
10
+ end.equals([:fail, "must use a persisted record when testing uniqueness of :email", blah, blah])
11
11
 
12
12
  should("pass with a persisted record") do
13
13
  topic.asserts("room") do
@@ -19,5 +19,5 @@ context "The validates_uniqueness_of assertion macro" do
19
19
  topic.asserts("room") do
20
20
  Room.create_with_good_data(:email => "goo@car.caz")
21
21
  end.validates_uniqueness_of(:foo).run(Riot::Situation.new)
22
- end.equals([:fail, "expected to fail because :foo is not unique"])
22
+ end.equals([:fail, "expected to fail because :foo is not unique", blah, blah])
23
23
  end # The validates_uniqueness_of assertion macro