surveyor 0.6.1

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 (137) hide show
  1. data/.gitignore +6 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +104 -0
  4. data/Rakefile +50 -0
  5. data/VERSION +1 -0
  6. data/app/controllers/surveyor_controller.rb +117 -0
  7. data/app/helpers/survey_form_builder.rb +37 -0
  8. data/app/helpers/surveyor_helper.rb +66 -0
  9. data/app/models/answer.rb +21 -0
  10. data/app/models/dependency.rb +46 -0
  11. data/app/models/dependency_condition.rb +79 -0
  12. data/app/models/question.rb +54 -0
  13. data/app/models/question_group.rb +18 -0
  14. data/app/models/response.rb +47 -0
  15. data/app/models/response_set.rb +185 -0
  16. data/app/models/survey.rb +57 -0
  17. data/app/models/survey_section.rb +15 -0
  18. data/app/views/layouts/surveyor_default.html.erb +13 -0
  19. data/app/views/partials/_answer.html.haml +49 -0
  20. data/app/views/partials/_question.html.haml +73 -0
  21. data/app/views/partials/_question_group.html.haml +41 -0
  22. data/app/views/surveyor/edit.html.haml +32 -0
  23. data/app/views/surveyor/new.html.haml +17 -0
  24. data/app/views/surveyor/show.html.haml +12 -0
  25. data/config/routes.rb +10 -0
  26. data/generators/surveyor/EXTENDING_SURVEYOR +12 -0
  27. data/generators/surveyor/extend_surveyor_generator.rb +22 -0
  28. data/generators/surveyor/surveyor_generator.rb +60 -0
  29. data/generators/surveyor/templates/README +10 -0
  30. data/generators/surveyor/templates/assets/images/222222_11x11_icon_arrows_leftright.gif +0 -0
  31. data/generators/surveyor/templates/assets/images/222222_11x11_icon_arrows_updown.gif +0 -0
  32. data/generators/surveyor/templates/assets/images/222222_11x11_icon_close.gif +0 -0
  33. data/generators/surveyor/templates/assets/images/222222_11x11_icon_doc.gif +0 -0
  34. data/generators/surveyor/templates/assets/images/222222_11x11_icon_folder_closed.gif +0 -0
  35. data/generators/surveyor/templates/assets/images/222222_11x11_icon_folder_open.gif +0 -0
  36. data/generators/surveyor/templates/assets/images/222222_11x11_icon_minus.gif +0 -0
  37. data/generators/surveyor/templates/assets/images/222222_11x11_icon_plus.gif +0 -0
  38. data/generators/surveyor/templates/assets/images/222222_11x11_icon_resize_se.gif +0 -0
  39. data/generators/surveyor/templates/assets/images/222222_35x9_colorpicker_indicator.gif.gif +0 -0
  40. data/generators/surveyor/templates/assets/images/222222_7x7_arrow_down.gif +0 -0
  41. data/generators/surveyor/templates/assets/images/222222_7x7_arrow_left.gif +0 -0
  42. data/generators/surveyor/templates/assets/images/222222_7x7_arrow_right.gif +0 -0
  43. data/generators/surveyor/templates/assets/images/222222_7x7_arrow_up.gif +0 -0
  44. data/generators/surveyor/templates/assets/images/454545_11x11_icon_arrows_leftright.gif +0 -0
  45. data/generators/surveyor/templates/assets/images/454545_11x11_icon_arrows_updown.gif +0 -0
  46. data/generators/surveyor/templates/assets/images/454545_11x11_icon_close.gif +0 -0
  47. data/generators/surveyor/templates/assets/images/454545_11x11_icon_doc.gif +0 -0
  48. data/generators/surveyor/templates/assets/images/454545_11x11_icon_folder_closed.gif +0 -0
  49. data/generators/surveyor/templates/assets/images/454545_11x11_icon_folder_open.gif +0 -0
  50. data/generators/surveyor/templates/assets/images/454545_11x11_icon_minus.gif +0 -0
  51. data/generators/surveyor/templates/assets/images/454545_11x11_icon_plus.gif +0 -0
  52. data/generators/surveyor/templates/assets/images/454545_7x7_arrow_down.gif +0 -0
  53. data/generators/surveyor/templates/assets/images/454545_7x7_arrow_left.gif +0 -0
  54. data/generators/surveyor/templates/assets/images/454545_7x7_arrow_right.gif +0 -0
  55. data/generators/surveyor/templates/assets/images/454545_7x7_arrow_up.gif +0 -0
  56. data/generators/surveyor/templates/assets/images/888888_11x11_icon_arrows_leftright.gif +0 -0
  57. data/generators/surveyor/templates/assets/images/888888_11x11_icon_arrows_updown.gif +0 -0
  58. data/generators/surveyor/templates/assets/images/888888_11x11_icon_close.gif +0 -0
  59. data/generators/surveyor/templates/assets/images/888888_11x11_icon_doc.gif +0 -0
  60. data/generators/surveyor/templates/assets/images/888888_11x11_icon_folder_closed.gif +0 -0
  61. data/generators/surveyor/templates/assets/images/888888_11x11_icon_folder_open.gif +0 -0
  62. data/generators/surveyor/templates/assets/images/888888_11x11_icon_minus.gif +0 -0
  63. data/generators/surveyor/templates/assets/images/888888_11x11_icon_plus.gif +0 -0
  64. data/generators/surveyor/templates/assets/images/888888_7x7_arrow_down.gif +0 -0
  65. data/generators/surveyor/templates/assets/images/888888_7x7_arrow_left.gif +0 -0
  66. data/generators/surveyor/templates/assets/images/888888_7x7_arrow_right.gif +0 -0
  67. data/generators/surveyor/templates/assets/images/888888_7x7_arrow_up.gif +0 -0
  68. data/generators/surveyor/templates/assets/images/dadada_40x100_textures_02_glass_75.png +0 -0
  69. data/generators/surveyor/templates/assets/images/e6e6e6_40x100_textures_02_glass_75.png +0 -0
  70. data/generators/surveyor/templates/assets/images/ffffff_40x100_textures_01_flat_0.png +0 -0
  71. data/generators/surveyor/templates/assets/images/ffffff_40x100_textures_02_glass_65.png +0 -0
  72. data/generators/surveyor/templates/assets/javascripts/accessibleUISlider.jQuery.js +201 -0
  73. data/generators/surveyor/templates/assets/javascripts/jquery-1.2.6.js +3549 -0
  74. data/generators/surveyor/templates/assets/javascripts/jquery-ui-personalized-1.5.3.js +7616 -0
  75. data/generators/surveyor/templates/assets/javascripts/jquery.form.js +637 -0
  76. data/generators/surveyor/templates/assets/javascripts/surveyor.js +28 -0
  77. data/generators/surveyor/templates/assets/stylesheets/jquery-ui-slider-additions.css +71 -0
  78. data/generators/surveyor/templates/assets/stylesheets/reset.css +46 -0
  79. data/generators/surveyor/templates/assets/stylesheets/sass/surveyor.sass +245 -0
  80. data/generators/surveyor/templates/assets/stylesheets/surveyor.css +231 -0
  81. data/generators/surveyor/templates/assets/stylesheets/ui.theme.css +851 -0
  82. data/generators/surveyor/templates/extensions/survey_extensions.rb +18 -0
  83. data/generators/surveyor/templates/extensions/surveyor_controller_extensions.rb +28 -0
  84. data/generators/surveyor/templates/extensions/surveyor_custom.html.erb +13 -0
  85. data/generators/surveyor/templates/extensions/surveyor_helper_extensions.rb +18 -0
  86. data/generators/surveyor/templates/initializers/haml.rb +8 -0
  87. data/generators/surveyor/templates/initializers/surveyor.rb +11 -0
  88. data/generators/surveyor/templates/migrate/create_answers.rb +45 -0
  89. data/generators/surveyor/templates/migrate/create_dependencies.rb +21 -0
  90. data/generators/surveyor/templates/migrate/create_dependency_conditions.rb +29 -0
  91. data/generators/surveyor/templates/migrate/create_question_groups.rb +18 -0
  92. data/generators/surveyor/templates/migrate/create_questions.rb +33 -0
  93. data/generators/surveyor/templates/migrate/create_response_sets.rb +22 -0
  94. data/generators/surveyor/templates/migrate/create_responses.rb +33 -0
  95. data/generators/surveyor/templates/migrate/create_survey_sections.rb +25 -0
  96. data/generators/surveyor/templates/migrate/create_surveys.rb +25 -0
  97. data/generators/surveyor/templates/surveys/kitchen_sink_survey.rb +201 -0
  98. data/generators/surveyor/templates/tasks/surveyor.rb +4 -0
  99. data/init.rb +1 -0
  100. data/install.rb +1 -0
  101. data/lib/surveyor.rb +7 -0
  102. data/lib/surveyor/config.rb +45 -0
  103. data/lib/tasks/surveyor_tasks.rake +33 -0
  104. data/lib/tiny_code.rb +58 -0
  105. data/lib/xml_formatter.rb +12 -0
  106. data/script/surveyor/answer.rb +84 -0
  107. data/script/surveyor/columnizer.rb +36 -0
  108. data/script/surveyor/dependency.rb +43 -0
  109. data/script/surveyor/dependency_condition.rb +74 -0
  110. data/script/surveyor/question.rb +76 -0
  111. data/script/surveyor/question_group.rb +33 -0
  112. data/script/surveyor/specs/answer_spec.rb +66 -0
  113. data/script/surveyor/specs/question_dependency_spec.rb +46 -0
  114. data/script/surveyor/specs/question_group_spec.rb +9 -0
  115. data/script/surveyor/specs/question_spec.rb +111 -0
  116. data/script/surveyor/specs/section_spec.rb +58 -0
  117. data/script/surveyor/survey.rb +108 -0
  118. data/script/surveyor/survey_parser.rb +64 -0
  119. data/script/surveyor/survey_section.rb +153 -0
  120. data/script/surveyor/whr_dsl.tmproj +244 -0
  121. data/spec/controllers/surveyor_controller_spec.rb +328 -0
  122. data/spec/factories.rb +107 -0
  123. data/spec/models/answer_spec.rb +29 -0
  124. data/spec/models/dependency_condition_spec.rb +338 -0
  125. data/spec/models/dependency_spec.rb +82 -0
  126. data/spec/models/question_group_spec.rb +11 -0
  127. data/spec/models/question_spec.rb +75 -0
  128. data/spec/models/response_set_spec.rb +153 -0
  129. data/spec/models/response_spec.rb +94 -0
  130. data/spec/models/survey_section_spec.rb +34 -0
  131. data/spec/models/survey_spec.rb +72 -0
  132. data/spec/rcov.opts +2 -0
  133. data/spec/spec.opts +4 -0
  134. data/spec/spec_helper.rb +14 -0
  135. data/surveyor.gemspec +187 -0
  136. data/uninstall.rb +1 -0
  137. metadata +211 -0
@@ -0,0 +1,82 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Dependency do
4
+ before(:each) do
5
+ @dependency = Dependency.new(:rule => "1 and 2 or 3", :question_id => 23)
6
+ end
7
+
8
+ it "should be valid" do
9
+ @dependency.should be_valid
10
+ end
11
+
12
+ it "should be invalid without a rule" do
13
+ @dependency.rule = nil
14
+ @dependency.should have(2).errors_on(:rule)
15
+ @dependency.rule = " "
16
+ @dependency.should have(1).errors_on(:rule)
17
+ end
18
+
19
+ it "should be invalid without a question_id" do
20
+ @dependency.question_id = nil
21
+ @dependency.should have(1).error_on(:question_id)
22
+ end
23
+
24
+ it "should alias question_id as dependent_question_id" do
25
+ @dependency.question_id = 19
26
+ @dependency.dependent_question_id.should == 19
27
+ @dependency.dependent_question_id = 14
28
+ @dependency.question_id.should == 14
29
+ end
30
+
31
+ it "should be invalid unless rule composed of only references and operators" do
32
+ @dependency.rule = "foo"
33
+ @dependency.should have(1).error_on(:rule)
34
+ @dependency.rule = "1 to 2"
35
+ @dependency.should have(1).error_on(:rule)
36
+ @dependency.rule = "a and b"
37
+ @dependency.should have(1).error_on(:rule)
38
+ end
39
+
40
+ end
41
+
42
+ describe Dependency, "when evaluating dependency conditions of a question in a response set" do
43
+
44
+ before(:each) do
45
+ @dep = Dependency.new(:rule => "A", :question_id => 1)
46
+ @dep2 = Dependency.new(:rule => "A and B", :question_id => 1)
47
+ @dep3 = Dependency.new(:rule => "A or B", :question_id => 1)
48
+ @dep4 = Dependency.new(:rule => "!(A and B) and C", :question_id => 1)
49
+
50
+ @dep_c = mock_model(DependencyCondition, :id => 1, :rule_key => "A", :to_evaluation_hash => {:A => true})
51
+ @dep_c2 = mock_model(DependencyCondition, :id => 2, :rule_key => "B", :to_evaluation_hash => {:B => false})
52
+ @dep_c3 = mock_model(DependencyCondition, :id => 3, :rule_key => "C", :to_evaluation_hash => {:C => true})
53
+
54
+ @dep.stub!(:dependency_conditions).and_return([@dep_c])
55
+ @dep2.stub!(:dependency_conditions).and_return([@dep_c, @dep_c2])
56
+ @dep3.stub!(:dependency_conditions).and_return([@dep_c, @dep_c2])
57
+ @dep4.stub!(:dependency_conditions).and_return([@dep_c, @dep_c2, @dep_c3])
58
+ end
59
+
60
+ it "knows if the dependencies are met" do
61
+ @dep.met?(@response_set).should be_true
62
+ @dep2.met?(@response_set).should be_false
63
+ @dep3.met?(@response_set).should be_true
64
+ @dep4.met?(@response_set).should be_true
65
+ end
66
+
67
+ it "returns the proper keyed pairs from the dependency conditions" do
68
+ @dep.keyed_conditions(@response_set).should == {:A => true}
69
+ @dep2.keyed_conditions(@response_set).should == {:A => true, :B => false}
70
+ @dep3.keyed_conditions(@response_set).should == {:A => true, :B => false}
71
+ @dep4.keyed_conditions(@response_set).should == {:A => true, :B => false, :C => true}
72
+ end
73
+
74
+ it "evaluates the rule from the keyed pairs and return a boolean value" do
75
+ @dep.rule_evaluation(@dep.keyed_conditions(@response_set)).should be_true
76
+ @dep2.rule_evaluation(@dep2.keyed_conditions(@response_set)).should be_false
77
+ @dep3.rule_evaluation(@dep3.keyed_conditions(@response_set)).should be_true
78
+ @dep4.rule_evaluation(@dep4.keyed_conditions(@response_set)).should be_true
79
+ end
80
+
81
+
82
+ end
@@ -0,0 +1,11 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe QuestionGroup do
4
+ before(:each) do
5
+ @question_group = QuestionGroup.new
6
+ end
7
+
8
+ it "should be valid" do
9
+ @question_group.should be_valid
10
+ end
11
+ end
@@ -0,0 +1,75 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Question, "when creating a new question" do
4
+ before(:each) do
5
+ @ss = mock_model(SurveySection)
6
+ @question = Question.new(:text => "What is your favorite color?", :survey_section => @ss, :is_mandatory => true, :display_order => 1)
7
+ end
8
+
9
+ it "should be valid" do
10
+ @question.should be_valid
11
+ end
12
+
13
+ it "should be invalid without text" do
14
+ @question.text = nil
15
+ @question.should have(1).error_on(:text)
16
+ end
17
+
18
+ it "should have a parent survey section" do
19
+ @question.survey_section = nil
20
+ @question.should have(1).error_on(:survey_section_id)
21
+ end
22
+
23
+ it "should be mandatory by default" do
24
+ @question.mandatory?.should be_true
25
+ end
26
+
27
+ end
28
+
29
+ describe Question, "that has answers" do
30
+ before(:each) do
31
+ @question = Factory(:question, :text => "What is your favorite color?")
32
+ Factory(:answer, :question => @question, :display_order => 3, :text => "blue")
33
+ Factory(:answer, :question => @question, :display_order => 1, :text => "red")
34
+ Factory(:answer, :question => @question, :display_order => 2, :text => "green")
35
+ end
36
+
37
+ it "should have answers" do
38
+ @question.answers.should have(3).answers
39
+ end
40
+
41
+ it "should retrieve those answers in display_order" do
42
+ @question.answers.map(&:display_order).should == [1,2,3]
43
+ end
44
+
45
+ end
46
+
47
+ describe Question, "when interacting with an instance" do
48
+
49
+ before(:each) do
50
+ @ss = mock_model(SurveySection)
51
+ @question = Question.new(:text => "What is your favorite color?", :survey_section => @ss)
52
+ end
53
+
54
+ it "should return 'default' for nil display type" do
55
+ @question.display_type = nil
56
+ @question.display_type.should == "default"
57
+ end
58
+
59
+ end
60
+
61
+ describe Question, "with dependencies" do
62
+ before(:each) do
63
+ @ss = mock_model(SurveySection)
64
+ @rs = mock_model(ResponseSet)
65
+ @question = Question.new(:text => "Which island?", :survey_section => @ss)
66
+ end
67
+
68
+ it "should check its dependency" do
69
+ @dependency = mock_model(Dependency)
70
+ @dependency.stub!(:met?).with(@rs).and_return(true)
71
+ @question.stub!(:dependency).and_return(@dependency)
72
+ @question.dependency_is_satisfied?(@rs).should == true
73
+ end
74
+
75
+ end
@@ -0,0 +1,153 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe ResponseSet, "class methods" do
4
+ before(:each) do
5
+ @response_set = Factory(:response_set, :access_code => "PDQ")
6
+ end
7
+ it "should find a response set by response_set.access_code or return false" do
8
+ ResponseSet.find_by_access_code("PDQ").should == @response_set
9
+ ResponseSet.find_by_access_code("Different").should be_nil
10
+ end
11
+ end
12
+ describe ResponseSet, "with responses" do
13
+ before(:each) do
14
+ @response_set = Factory(:response_set)
15
+ end
16
+
17
+ it "can tell you its responses" do
18
+ 3.times{ |x| @response_set.responses.build }
19
+ @response_set.responses.should have(3).items
20
+ end
21
+
22
+ it "is completable" do
23
+ @response_set.completed_at.should be_nil
24
+ @response_set.complete!
25
+ @response_set.completed_at.should_not be_nil
26
+ @response_set.completed_at.is_a?(Time).should be_true
27
+ end
28
+
29
+ it "does not allow completion through mass assignment" do
30
+ @response_set.completed_at.should be_nil
31
+ @response_set.update_attributes(:completed_at => Time.now)
32
+ @response_set.completed_at.should be_nil
33
+ end
34
+
35
+ end
36
+ describe ResponseSet, "Creating new set for user" do
37
+ before(:each) do
38
+ @response_set = Factory(:response_set)
39
+ end
40
+ it "should have a unique code with length 10 that identifies the survey" do
41
+ @response_set.access_code.should_not be_nil
42
+ @response_set.access_code.length.should == 10
43
+ end
44
+ end
45
+ describe ResponseSet, "Updating the response set" do
46
+ before(:each) do
47
+ @response_set = Factory(:response_set)
48
+ # {"responses"=>{
49
+ # "6"=>{"question_id"=>"6", "20"=>{"string_value"=>""}},
50
+ # "7"=>{"question_id"=>"7", "21"=>{"text_value"=>"Brian is tired"}},
51
+ # "1"=>{"question_id"=>"1", "answer_id"=>"1", "4"=>{"string_value"=>"XXL"}},
52
+ # "2"=>{"question_id"=>"2", "answer_id"=>"6"},
53
+ # "3"=>{"question_id"=>"3"},
54
+ # "4"=>{"question_id"=>"4"},
55
+ # "5"=>{"question_id"=>"5", "19"=>{"string_value"=>""}}},
56
+ # "survey_code"=>"test_survey",
57
+ # "commit"=>"Next Section (Utensiles and you!) >>",
58
+ # "authenticity_token"=>"d03bc1b52fa9669e1ed87c313b939836e7b93e34",
59
+ # "_method"=>"put",
60
+ # "action"=>"update",
61
+ # "controller"=>"app",
62
+ # "response_set_code"=>"cIFn0DnxlU",
63
+ # "section"=>"2"}
64
+
65
+ #TODO test views to produce these params. e.g., blank responses should still have a hash with question_id
66
+ @radio_response_attributes = HashWithIndifferentAccess.new({
67
+ "1"=>{"question_id"=>"1", "answer_id"=>"1", "4"=>{"string_value"=>"XXL"}},
68
+ "2"=>{"question_id"=>"2", "answer_id"=>"6"},
69
+ "3"=>{"question_id"=>"3"}
70
+ })
71
+ @other_response_attributes = HashWithIndifferentAccess.new({
72
+ "6"=>{"question_id"=>"6", "20"=>{"string_value"=>""}},
73
+ "7"=>{"question_id"=>"7", "21"=>{"text_value"=>"Brian is tired"}},
74
+ "5"=>{"question_id"=>"5", "19"=>{"string_value"=>""}}
75
+ })
76
+ end
77
+
78
+ it "should delete existing responses corresponding to every question key that comes in" do
79
+ Response.should_receive(:delete_all).exactly(3).times
80
+ @response_set.update_attributes(:response_attributes => @radio_response_attributes)
81
+ end
82
+ it "should save new responses from radio buttons, ignoring blanks" do
83
+ @response_set.update_attributes(:response_attributes => @radio_response_attributes)
84
+ @response_set.responses.should have(2).items
85
+ @response_set.responses.detect{|r| r.question_id == 2}.answer_id.should == 6
86
+ end
87
+ it "should save new responses from other types, ignoring blanks" do
88
+ @response_set.update_attributes(:response_attributes => @other_response_attributes)
89
+ @response_set.responses.should have(1).items
90
+ @response_set.responses.detect{|r| r.question_id == 7}.text_value.should == "Brian is tired"
91
+ end
92
+ it "should ignore data if corresponding radio button is not selected" do
93
+ @response_set.update_attributes(:response_attributes => @radio_response_attributes)
94
+ @response_set.responses.select{|r| r.question_id == 2}.should have(1).item
95
+ @response_set.responses.detect{|r| r.question_id == 2}.string_value.should == nil
96
+ end
97
+ it "should preserve data in checkboxes regardless of selection" do
98
+ pending
99
+ end
100
+
101
+ it "should give convenient access to responses through response_for" do
102
+ @response_set.save #need to save for the associated models to build/save
103
+ @response_set.attributes = {:response_attributes => @radio_response_attributes}
104
+ @response_set.save.should be_true
105
+ @response_set.responses.should have(2).items
106
+
107
+ pending
108
+ end
109
+ end
110
+
111
+ describe ResponseSet, "knowing internal status" do
112
+ before(:each) do
113
+ @response_set = Factory(:response_set)
114
+ end
115
+ it "knows when it is empty" do
116
+ @response_set.empty?.should be_true
117
+ end
118
+
119
+ it "knows when it is not empty" do
120
+ @response_set.responses.build({:question_id => 1, :answer_id => 8})
121
+ @response_set.empty?.should be_false
122
+ end
123
+ end
124
+ describe ResponseSet, "with dependencies" do
125
+ before(:each) do
126
+ # Questions
127
+ @do_you_like_pie = Factory(:question, :text => "Do you like pie?")
128
+ @what_flavor = Factory(:question, :text => "What flavor?")
129
+ @what_bakery = Factory(:question, :text => "What bakery?")
130
+ # Answers
131
+ @do_you_like_pie.answers << Factory(:answer, :text => "yes", :question_id => @do_you_like_pie.id)
132
+ @do_you_like_pie.answers << Factory(:answer, :text => "no", :question_id => @do_you_like_pie.id)
133
+ @what_flavor.answers << Factory(:answer, :response_class => :string, :question_id => @what_flavor.id)
134
+ @what_bakery.answers << Factory(:answer, :response_class => :string, :question_id => @what_bakery.id)
135
+ # Dependency
136
+ @what_flavor_dep = Factory(:dependency, :rule => "1", :question_id => @what_flavor.id)
137
+ @what_flavor_dep.dependency_conditions << Factory(:dependency_condition, :rule_key => "1", :question_id => @do_you_like_pie.id, :operator => "==", :answer_id => @do_you_like_pie.answers.first.id, :dependency_id => @what_flavor_dep.id)
138
+ @what_bakery_dep = Factory(:dependency, :rule => "2", :question_id => @what_bakery.id)
139
+ @what_bakery_dep.dependency_conditions << Factory(:dependency_condition, :rule_key => "2", :question_id => @do_you_like_pie.id, :operator => "==", :answer_id => @do_you_like_pie.answers.first.id, :dependency_id => @what_bakery_dep.id)
140
+ # Responses
141
+ @response_set = Factory(:response_set)
142
+ @response_set.responses << Factory(:response, :question_id => @do_you_like_pie.id, :answer_id => @do_you_like_pie.answers.first.id, :response_set_id => @response_set.id)
143
+ @response_set.responses << Factory(:response, :string_value => "pecan pie", :question_id => @what_flavor.id, :answer_id => @what_flavor.answers.first.id, :response_set_id => @response_set.id)
144
+ end
145
+
146
+ it "should list unanswered dependencies to show at the top of the next page (javascript turned off)" do
147
+ @response_set.unanswered_dependencies.should == [@what_bakery]
148
+ end
149
+ it "should list answered and unanswered dependencies to show inline (javascript turned on)" do
150
+ @response_set.all_dependencies[:show].should == [@what_flavor, @what_bakery]
151
+ end
152
+
153
+ end
@@ -0,0 +1,94 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Response, "when saving a response" do
4
+ before(:each) do
5
+ @response = Response.new(:question_id => 314, :response_set_id => 159, :answer_id => 1)
6
+ end
7
+
8
+ it "should be valid" do
9
+ @response.should be_valid
10
+ end
11
+
12
+ it "should be invalid without a parent response set and question" do
13
+ @response.response_set_id = nil
14
+ @response.should have(1).error_on(:response_set_id)
15
+
16
+ @response.question_id = nil
17
+ @response.should have(1).error_on(:question_id)
18
+ end
19
+
20
+ describe "returns the response as the type requested" do
21
+
22
+ it "returns 'string'" do
23
+ @response.string_value = "blah"
24
+ @response.as("string").should == "blah"
25
+ @response.as(:string).should == "blah"
26
+ end
27
+
28
+ it "returns 'integer'" do
29
+ @response.integer_value = 1001
30
+ @response.as(:integer).should == 1001
31
+ end
32
+
33
+ it "returns 'float'"do
34
+ @response.float_value = 3.14
35
+ @response.as(:float).should == 3.14
36
+ end
37
+
38
+ it "returns 'answer'" do
39
+ @response.answer_id = 14
40
+ @response.as(:answer).should == 14
41
+ end
42
+
43
+ it "default returns answer type if not specified" do
44
+ @response.answer_id =18
45
+ @response.as(:stuff).should == 18
46
+ end
47
+
48
+ it "returns empty elements if the response is cast as a type that is not present" do
49
+ resp = Response.new(:question_id => 314, :response_set_id => 156)
50
+ resp.as(:string).should == nil
51
+ resp.as(:integer).should == nil
52
+ resp.as(:float).should == nil
53
+ resp.as(:answer).should == nil
54
+ resp.as(:stuff).should == nil
55
+ end
56
+
57
+ end
58
+
59
+ describe "model validation defined in the answer class attributes" do
60
+
61
+ before(:each) do
62
+ # faking out all the basic validations on the model
63
+ @response = Response.new(:question_id => 123, :response_set_id => 421, :answer_id => 213)
64
+ end
65
+
66
+ describe "Integer response_type validations" do
67
+
68
+ before(:each) do
69
+ @response.stub!(:answer).and_return(mock(Answer, {:response_class => :integer}))
70
+ end
71
+
72
+ it "validates an upper limit on responses" do
73
+ @response.answer.stub!(:max_value).and_return(10)
74
+ @response.integer_value = 100
75
+ @response.save.should be_false
76
+ @response.should have(1).error_on(:integer_value)
77
+ end
78
+
79
+ end
80
+
81
+ describe "Float response_type validations" do
82
+
83
+ before(:each) do
84
+ @response.stub!(:answer).and_return(mock(Answer, {:response_class => :float}))
85
+ end
86
+
87
+ it "validates an upper limit on responses" do
88
+ pending
89
+ end
90
+
91
+ end
92
+
93
+ end
94
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe SurveySection, "when saving a survey_section" do
4
+ before(:each) do
5
+ @valid_attributes={:title => "foo", :survey_id => 2, :display_order => 4}
6
+ @survey_section = SurveySection.new(@valid_attributes)
7
+ end
8
+
9
+ it "should be invalid without title" do
10
+ @survey_section.title = nil
11
+ @survey_section.should have(1).error_on(:title)
12
+ end
13
+
14
+ it "should have a parent survey" do
15
+ @survey_section.survey_id = nil
16
+ @survey_section.should have(1).error_on(:survey)
17
+ end
18
+ end
19
+
20
+ describe SurveySection, "with questions" do
21
+ before(:each) do
22
+ @survey = mock_model(Survey)
23
+ @valid_attributes={:title => "Rhymes", :survey => @survey, :display_order => 4}
24
+ @survey_section = SurveySection.create(@valid_attributes)
25
+ @q1 = @survey_section.questions.create(:text => "Peep", :display_order => 3)
26
+ @q2 = @survey_section.questions.create(:text => "Little", :display_order => 1)
27
+ @q3 = @survey_section.questions.create(:text => "Bo", :display_order => 2)
28
+ end
29
+
30
+ it "should return questions sorted in display order" do
31
+ @survey_section.questions.should have(3).questions
32
+ @survey_section.questions.should == [@q2,@q3,@q1]
33
+ end
34
+ end