jakewendt-surveyor 0.11.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (160) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +285 -0
  3. data/Rakefile +54 -0
  4. data/VERSION +1 -0
  5. data/app/controllers/surveyor_controller.rb +142 -0
  6. data/app/helpers/survey_form_builder.rb +37 -0
  7. data/app/helpers/surveyor_helper.rb +67 -0
  8. data/app/models/answer.rb +23 -0
  9. data/app/models/dependency.rb +50 -0
  10. data/app/models/dependency_condition.rb +47 -0
  11. data/app/models/question.rb +54 -0
  12. data/app/models/question_group.rb +33 -0
  13. data/app/models/response.rb +94 -0
  14. data/app/models/response_set.rb +316 -0
  15. data/app/models/survey.rb +172 -0
  16. data/app/models/survey_section.rb +18 -0
  17. data/app/models/validation.rb +38 -0
  18. data/app/models/validation_condition.rb +47 -0
  19. data/app/views/layouts/surveyor_default.html.erb +13 -0
  20. data/app/views/partials/_answer.html.haml +58 -0
  21. data/app/views/partials/_question.html.haml +80 -0
  22. data/app/views/partials/_question_group.html.haml +39 -0
  23. data/app/views/surveyor/edit.html.haml +38 -0
  24. data/app/views/surveyor/new.html.haml +16 -0
  25. data/app/views/surveyor/show.html.haml +12 -0
  26. data/config/routes.rb +11 -0
  27. data/features/step_definitions/surveyor_steps.rb +7 -0
  28. data/features/step_definitions/web_steps.rb +273 -0
  29. data/features/support/env.rb +57 -0
  30. data/features/support/paths.rb +25 -0
  31. data/features/surveyor.feature +11 -0
  32. data/generators/extend_surveyor/extend_surveyor_generator.rb +22 -0
  33. data/generators/extend_surveyor/templates/EXTENDING_SURVEYOR +17 -0
  34. data/generators/extend_surveyor/templates/extensions/survey_extensions.rb +24 -0
  35. data/generators/extend_surveyor/templates/extensions/surveyor_controller_extensions.rb +28 -0
  36. data/generators/extend_surveyor/templates/extensions/surveyor_custom.html.erb +13 -0
  37. data/generators/extend_surveyor/templates/extensions/surveyor_helper_extensions.rb +17 -0
  38. data/generators/surveyor/surveyor_generator.rb +67 -0
  39. data/generators/surveyor/templates/README +10 -0
  40. data/generators/surveyor/templates/assets/images/222222_11x11_icon_arrows_leftright.gif +0 -0
  41. data/generators/surveyor/templates/assets/images/222222_11x11_icon_arrows_updown.gif +0 -0
  42. data/generators/surveyor/templates/assets/images/222222_11x11_icon_close.gif +0 -0
  43. data/generators/surveyor/templates/assets/images/222222_11x11_icon_doc.gif +0 -0
  44. data/generators/surveyor/templates/assets/images/222222_11x11_icon_folder_closed.gif +0 -0
  45. data/generators/surveyor/templates/assets/images/222222_11x11_icon_folder_open.gif +0 -0
  46. data/generators/surveyor/templates/assets/images/222222_11x11_icon_minus.gif +0 -0
  47. data/generators/surveyor/templates/assets/images/222222_11x11_icon_plus.gif +0 -0
  48. data/generators/surveyor/templates/assets/images/222222_11x11_icon_resize_se.gif +0 -0
  49. data/generators/surveyor/templates/assets/images/222222_35x9_colorpicker_indicator.gif.gif +0 -0
  50. data/generators/surveyor/templates/assets/images/222222_7x7_arrow_down.gif +0 -0
  51. data/generators/surveyor/templates/assets/images/222222_7x7_arrow_left.gif +0 -0
  52. data/generators/surveyor/templates/assets/images/222222_7x7_arrow_right.gif +0 -0
  53. data/generators/surveyor/templates/assets/images/222222_7x7_arrow_up.gif +0 -0
  54. data/generators/surveyor/templates/assets/images/454545_11x11_icon_arrows_leftright.gif +0 -0
  55. data/generators/surveyor/templates/assets/images/454545_11x11_icon_arrows_updown.gif +0 -0
  56. data/generators/surveyor/templates/assets/images/454545_11x11_icon_close.gif +0 -0
  57. data/generators/surveyor/templates/assets/images/454545_11x11_icon_doc.gif +0 -0
  58. data/generators/surveyor/templates/assets/images/454545_11x11_icon_folder_closed.gif +0 -0
  59. data/generators/surveyor/templates/assets/images/454545_11x11_icon_folder_open.gif +0 -0
  60. data/generators/surveyor/templates/assets/images/454545_11x11_icon_minus.gif +0 -0
  61. data/generators/surveyor/templates/assets/images/454545_11x11_icon_plus.gif +0 -0
  62. data/generators/surveyor/templates/assets/images/454545_7x7_arrow_down.gif +0 -0
  63. data/generators/surveyor/templates/assets/images/454545_7x7_arrow_left.gif +0 -0
  64. data/generators/surveyor/templates/assets/images/454545_7x7_arrow_right.gif +0 -0
  65. data/generators/surveyor/templates/assets/images/454545_7x7_arrow_up.gif +0 -0
  66. data/generators/surveyor/templates/assets/images/888888_11x11_icon_arrows_leftright.gif +0 -0
  67. data/generators/surveyor/templates/assets/images/888888_11x11_icon_arrows_updown.gif +0 -0
  68. data/generators/surveyor/templates/assets/images/888888_11x11_icon_close.gif +0 -0
  69. data/generators/surveyor/templates/assets/images/888888_11x11_icon_doc.gif +0 -0
  70. data/generators/surveyor/templates/assets/images/888888_11x11_icon_folder_closed.gif +0 -0
  71. data/generators/surveyor/templates/assets/images/888888_11x11_icon_folder_open.gif +0 -0
  72. data/generators/surveyor/templates/assets/images/888888_11x11_icon_minus.gif +0 -0
  73. data/generators/surveyor/templates/assets/images/888888_11x11_icon_plus.gif +0 -0
  74. data/generators/surveyor/templates/assets/images/888888_7x7_arrow_down.gif +0 -0
  75. data/generators/surveyor/templates/assets/images/888888_7x7_arrow_left.gif +0 -0
  76. data/generators/surveyor/templates/assets/images/888888_7x7_arrow_right.gif +0 -0
  77. data/generators/surveyor/templates/assets/images/888888_7x7_arrow_up.gif +0 -0
  78. data/generators/surveyor/templates/assets/images/dadada_40x100_textures_02_glass_75.png +0 -0
  79. data/generators/surveyor/templates/assets/images/e6e6e6_40x100_textures_02_glass_75.png +0 -0
  80. data/generators/surveyor/templates/assets/images/ffffff_40x100_textures_01_flat_0.png +0 -0
  81. data/generators/surveyor/templates/assets/images/ffffff_40x100_textures_02_glass_65.png +0 -0
  82. data/generators/surveyor/templates/assets/javascripts/accessibleUISlider.jQuery.js +201 -0
  83. data/generators/surveyor/templates/assets/javascripts/jquery-1.2.6.js +3549 -0
  84. data/generators/surveyor/templates/assets/javascripts/jquery-ui-personalized-1.5.3.js +7616 -0
  85. data/generators/surveyor/templates/assets/javascripts/jquery.form.js +637 -0
  86. data/generators/surveyor/templates/assets/javascripts/surveyor.js +47 -0
  87. data/generators/surveyor/templates/assets/stylesheets/jquery-ui-slider-additions.css +71 -0
  88. data/generators/surveyor/templates/assets/stylesheets/reset.css +50 -0
  89. data/generators/surveyor/templates/assets/stylesheets/sass/surveyor.sass +243 -0
  90. data/generators/surveyor/templates/assets/stylesheets/surveyor.css +235 -0
  91. data/generators/surveyor/templates/assets/stylesheets/ui.theme.css +851 -0
  92. data/generators/surveyor/templates/initializers/haml.rb +8 -0
  93. data/generators/surveyor/templates/initializers/surveyor.rb +10 -0
  94. data/generators/surveyor/templates/migrate/add_correct_answer_id_to_questions.rb +9 -0
  95. data/generators/surveyor/templates/migrate/add_display_order_to_surveys.rb +9 -0
  96. data/generators/surveyor/templates/migrate/add_index_to_response_sets.rb +9 -0
  97. data/generators/surveyor/templates/migrate/add_index_to_surveys.rb +9 -0
  98. data/generators/surveyor/templates/migrate/add_manual_numbering.rb +11 -0
  99. data/generators/surveyor/templates/migrate/add_unique_indicies.rb +17 -0
  100. data/generators/surveyor/templates/migrate/create_answers.rb +37 -0
  101. data/generators/surveyor/templates/migrate/create_dependencies.rb +22 -0
  102. data/generators/surveyor/templates/migrate/create_dependency_conditions.rb +29 -0
  103. data/generators/surveyor/templates/migrate/create_question_groups.rb +27 -0
  104. data/generators/surveyor/templates/migrate/create_questions.rb +36 -0
  105. data/generators/surveyor/templates/migrate/create_response_sets.rb +22 -0
  106. data/generators/surveyor/templates/migrate/create_responses.rb +33 -0
  107. data/generators/surveyor/templates/migrate/create_survey_sections.rb +29 -0
  108. data/generators/surveyor/templates/migrate/create_surveys.rb +31 -0
  109. data/generators/surveyor/templates/migrate/create_validation_conditions.rb +32 -0
  110. data/generators/surveyor/templates/migrate/create_validations.rb +20 -0
  111. data/generators/surveyor/templates/surveys/kitchen_sink_survey.rb +218 -0
  112. data/generators/surveyor/templates/tasks/surveyor.rb +4 -0
  113. data/generators/test_surveyor/templates/TESTING_SURVEYOR +0 -0
  114. data/generators/test_surveyor/templates/environments/cucumber.rb +21 -0
  115. data/generators/test_surveyor/test_surveyor_generator.rb +15 -0
  116. data/jakewendt-surveyor.gemspec +212 -0
  117. data/lib/fixtures_extensions.rb +6 -0
  118. data/lib/jakewendt-surveyor.rb +1 -0
  119. data/lib/surveyor.rb +44 -0
  120. data/lib/surveyor/acts_as_response.rb +33 -0
  121. data/lib/surveyor/config.rb +45 -0
  122. data/lib/tasks/surveyor_tasks.rake +33 -0
  123. data/lib/xml_formatter.rb +12 -0
  124. data/rails/init.rb +1 -0
  125. data/script/surveyor/answer.rb +54 -0
  126. data/script/surveyor/base.rb +77 -0
  127. data/script/surveyor/dependency.rb +13 -0
  128. data/script/surveyor/dependency_condition.rb +40 -0
  129. data/script/surveyor/parser.rb +207 -0
  130. data/script/surveyor/question.rb +37 -0
  131. data/script/surveyor/question_group.rb +26 -0
  132. data/script/surveyor/specs/answer_spec.rb +29 -0
  133. data/script/surveyor/specs/question_spec.rb +63 -0
  134. data/script/surveyor/specs/spec_helper.rb +7 -0
  135. data/script/surveyor/specs/survey_section_spec.rb +23 -0
  136. data/script/surveyor/specs/validation_condition_spec.rb +20 -0
  137. data/script/surveyor/specs/validation_spec.rb +20 -0
  138. data/script/surveyor/survey.rb +35 -0
  139. data/script/surveyor/survey_section.rb +21 -0
  140. data/script/surveyor/validation.rb +21 -0
  141. data/script/surveyor/validation_condition.rb +21 -0
  142. data/script/surveyor/whr_dsl.tmproj +244 -0
  143. data/spec/controllers/surveyor_controller_spec.rb +193 -0
  144. data/spec/factories.rb +145 -0
  145. data/spec/lib/surveyor_spec.rb +44 -0
  146. data/spec/models/answer_spec.rb +29 -0
  147. data/spec/models/dependency_condition_spec.rb +321 -0
  148. data/spec/models/dependency_spec.rb +81 -0
  149. data/spec/models/question_group_spec.rb +35 -0
  150. data/spec/models/question_spec.rb +75 -0
  151. data/spec/models/response_set_spec.rb +245 -0
  152. data/spec/models/response_spec.rb +76 -0
  153. data/spec/models/survey_section_spec.rb +32 -0
  154. data/spec/models/survey_spec.rb +71 -0
  155. data/spec/models/validation_condition_spec.rb +105 -0
  156. data/spec/models/validation_spec.rb +59 -0
  157. data/spec/rcov.opts +2 -0
  158. data/spec/spec.opts +4 -0
  159. data/spec/spec_helper.rb +12 -0
  160. metadata +254 -0
@@ -0,0 +1,193 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe SurveyorController do
4
+
5
+ # map.with_options :controller => 'surveyor' do |s|
6
+ # s.available_surveys "#{root}", :conditions => {:method => :get}, :action => "new" # GET survey list
7
+ # s.take_survey "#{root}:survey_code", :conditions => {:method => :post}, :action => "create" # Only POST of survey to create
8
+ # s.view_my_survey "#{root}:survey_code/:response_set_code", :conditions => {:method => :get}, :action => "show" # GET viewable/printable? survey
9
+ # s.edit_my_survey "#{root}:survey_code/:response_set_code/take", :conditions => {:method => :get}, :action => "edit" # GET editable survey
10
+ # s.update_my_survey "#{root}:survey_code/:response_set_code", :conditions => {:method => :put}, :action => "update" # PUT edited survey
11
+ # end
12
+
13
+ describe "available surveys: GET /surveys" do
14
+
15
+ before(:each) do
16
+ @survey = Factory(:survey)
17
+ Survey.stub!(:find).and_return([@survey])
18
+ end
19
+
20
+ def do_get
21
+ get :new
22
+ end
23
+
24
+ it "should render index template" do
25
+ do_get
26
+ response.should be_success
27
+ response.should render_template('new')
28
+ end
29
+ it "should find all surveys" do
30
+ Survey.should_receive(:find).with(:all).and_return([@survey])
31
+ do_get
32
+ end
33
+ it "should assign the found surveys for the view" do
34
+ do_get
35
+ assigns[:surveys].should == [@survey]
36
+ end
37
+ end
38
+
39
+ describe "take survey: POST /surveys/XYZ" do
40
+
41
+ before(:each) do
42
+ @survey = Factory(:survey, :title => "XYZ", :access_code => "XYZ")
43
+ @response_set = Factory(:response_set, :access_code => "PDQ")
44
+ ResponseSet.stub!(:create).and_return(@response_set)
45
+ Survey.stub!(:find_by_access_code).and_return(@survey)
46
+ end
47
+
48
+ describe "with success" do
49
+ def do_post
50
+ post :create, :survey_code => "XYZ"
51
+ end
52
+ it "should look for the survey" do
53
+ Survey.should_receive(:find_by_access_code).with("XYZ").and_return(@survey)
54
+ do_post
55
+ end
56
+ it "should create a new response_set" do
57
+ ResponseSet.should_receive(:create).and_return(@response_set)
58
+ do_post
59
+ end
60
+ it "should redirect to the new response_set" do
61
+ do_post
62
+ response.should redirect_to(edit_my_survey_url(:survey_code => "XYZ", :response_set_code => "PDQ"))
63
+ end
64
+ end
65
+
66
+ describe "with failures" do
67
+ it "should re-redirect to 'new' if ResponseSet failed create" do
68
+ ResponseSet.should_receive(:create).and_return(false)
69
+ post :create, :survey_code => "XYZ"
70
+ response.should redirect_to(available_surveys_url)
71
+ end
72
+ it "should re-redirect to 'new' if Survey failed find" do
73
+ Survey.should_receive(:find_by_access_code).and_return(nil)
74
+ post :create, :survey_code => "XYZ"
75
+ response.should redirect_to(available_surveys_url)
76
+ end
77
+ end
78
+ end
79
+
80
+ describe "view my survey: GET /surveys/XYZ/PDQ" do
81
+
82
+ before(:each) do
83
+ @survey = Factory(:survey, :title => "XYZ", :access_code => "XYZ", :sections => [Factory(:survey_section)])
84
+ @response_set = Factory(:response_set, :access_code => "PDQ", :survey => @survey)
85
+ end
86
+
87
+ def do_get
88
+ get :show, :survey_code => "XYZ", :response_set_code => "PDQ"
89
+ end
90
+
91
+ it "should be successful" do
92
+ do_get
93
+ response.should be_success
94
+ end
95
+ it "should render show template" do
96
+ do_get
97
+ response.should render_template('show')
98
+ end
99
+ it "should find the response_set requested" do
100
+ pending
101
+ ResponseSet.should_receive(:find_by_access_code).with("PDQ").and_return(@response_set)
102
+ do_get
103
+ end
104
+ it "should assign the found response_set and survey for the view" do
105
+ pending
106
+ do_get
107
+ assigns[:response_set].should equal(@response_set)
108
+ assigns[:survey].should equal(@survey)
109
+ end
110
+ it "should redirect if :response_code not found" do
111
+ pending
112
+ get :show, :survey_code => "XYZ", :response_set_code => "DIFFERENT"
113
+ response.should redirect_to(available_surveys_url)
114
+ end
115
+ # I'm not sure this is enterly neccessary since we look up the survey from the response_code in the url -BC
116
+ it "should redirect if :survey_code in url doesn't match response_set.survey.access_code" do
117
+ pending
118
+ get :show, :survey_code => "DIFFERENT", :response_set_code => "PDQ"
119
+ response.should redirect_to(available_surveys_url)
120
+ end
121
+ end
122
+
123
+ describe "edit my survey: GET /surveys/XYZ/PDQ/take" do
124
+
125
+ before(:each) do
126
+ @survey = Factory(:survey, :title => "XYZ", :access_code => "XYZ")
127
+ @section = Factory(:survey_section, :survey => @survey)
128
+ @response_set = Factory(:response_set, :access_code => "PDQ", :survey => @survey)
129
+ end
130
+
131
+ it "should be successful, render edit with the requested survey" do
132
+ ResponseSet.should_receive(:find_by_access_code).and_return(@response_set)
133
+ get :edit, :survey_code => "XYZ", :response_set_code => "PDQ"
134
+ response.should be_success
135
+ response.should render_template('edit')
136
+ assigns[:response_set].should == @response_set
137
+ assigns[:survey].should == @survey
138
+ end
139
+ it "should redirect if :response_code not found" do
140
+ get :edit, :survey_code => "XYZ", :response_set_code => "DIFFERENT"
141
+ response.should redirect_to(available_surveys_url)
142
+ end
143
+
144
+ end
145
+
146
+ describe "update my survey: PUT /surveys/XYZ/PDQ" do
147
+
148
+ before(:each) do
149
+ @survey = Factory(:survey, :title => "XYZ", :access_code => "XYZ")
150
+ @section = Factory(:survey_section, :survey => @survey)
151
+ @response_set = Factory(:response_set, :access_code => "PDQ", :survey => @survey)
152
+ # @response_set.stub!(:update_attributes).and_return(true)
153
+ # @response_set.stub!(:complete!).and_return(Time.now)
154
+ # @response_set.stub!(:save).and_return(true)
155
+ end
156
+
157
+ def do_put
158
+ put :update, :survey_code => "XYZ", :response_set_code => "PDQ"
159
+ end
160
+ def do_put_with_finish
161
+ responses = {
162
+ "6"=>{"question_id"=>"6", "20"=>{"string_value"=>"saf"}}, #string
163
+ "7"=>{"question_id"=>"7", "21"=>{"text_value"=>""}}, #text
164
+ "1"=>{"question_id"=>"1", "answer_id"=>"1", "4"=>{"string_value"=>""}}, #radio+txt
165
+ "2"=>{"answer_id"=>"6"}, #radio
166
+ "3"=>{"answer_id"=>"10"}, #radio
167
+ "4"=>{"question_id"=>"4", "answer_id"=>"15"}, #check
168
+ "5"=>{"question_id"=>"5", "16"=>{"selected"=>"1"}, "19"=>{"string_value"=>""}} #check+txt
169
+ }
170
+ put :update, :survey_code => "XYZ", :response_set_code => "PDQ", :finish => "finish", :responses => responses
171
+ end
172
+
173
+ it "should find the response set requested" do
174
+ ResponseSet.should_receive(:find_by_access_code).and_return(@response_set)
175
+ do_put
176
+ end
177
+ it "should redirect to 'edit' without params" do
178
+ do_put
179
+ response.should redirect_to(:action => :edit)
180
+ flash[:notice].should == "Unable to update survey"
181
+ end
182
+ it "should complete the found response set on finish" do
183
+ do_put_with_finish
184
+ flash[:notice].should == "Completed survey"
185
+ end
186
+ it "should redirect to available surveys if :response_code not found" do
187
+ put :update, :survey_code => "XYZ", :response_set_code => "DIFFERENT"
188
+ response.should redirect_to(available_surveys_url)
189
+ flash[:notice].should == "Unable to find your responses to the survey"
190
+ end
191
+
192
+ end
193
+ end
data/spec/factories.rb ADDED
@@ -0,0 +1,145 @@
1
+ # http://github.com/thoughtbot/factory_girl/tree/master
2
+ require 'rubygems'
3
+ require 'factory_girl'
4
+
5
+ Factory.sequence(:unique_survey_access_code){|n| "simple_survey" << n.to_s }
6
+
7
+ Factory.define :survey do |s|
8
+ s.title {"Simple survey"}
9
+ s.description {"A simple survey for testing"}
10
+ s.access_code {Factory.next :unique_survey_access_code}
11
+ s.active_at {Time.now}
12
+ s.inactive_at {}
13
+ s.css_url {}
14
+ end
15
+
16
+ Factory.sequence(:survey_section_display_order){|n| n }
17
+
18
+ Factory.define :survey_section do |s|
19
+ s.association :survey # s.survey_id {}
20
+ s.title {"Demographics"}
21
+ s.description {"Asking you about your personal data"}
22
+ s.display_order {Factory.next :survey_section_display_order}
23
+ s.reference_identifier {"demographics"}
24
+ s.data_export_identifier {"demographics"}
25
+ end
26
+
27
+ Factory.sequence(:question_display_order){|n| n }
28
+
29
+ Factory.define :question do |q|
30
+ q.association :survey_section # s.survey_section_id {}
31
+ q.question_group_id {}
32
+ q.text {"What is your favorite color?"}
33
+ q.short_text {"favorite_color"}
34
+ q.help_text {"just write it in the box"}
35
+ q.pick {:none}
36
+ q.reference_identifier {|me| "q_#{me.object_id}"}
37
+ q.data_export_identifier {}
38
+ q.common_namespace {}
39
+ q.common_identifier {}
40
+ q.display_order {Factory.next :question_display_order}
41
+ q.display_type {} # nil is default
42
+ q.is_mandatory {false}
43
+ q.display_width {}
44
+ q.correct_answer_id {nil}
45
+ end
46
+
47
+ Factory.define :question_group do |g|
48
+ g.text {"Describe your family"}
49
+ g.help_text {}
50
+ g.reference_identifier {|me| "g_#{me.object_id}"}
51
+ g.data_export_identifier {}
52
+ g.common_namespace {}
53
+ g.common_identifier {}
54
+ g.display_type {}
55
+ g.custom_class {}
56
+ g.custom_renderer {}
57
+ end
58
+
59
+ Factory.sequence(:answer_display_order){|n| n }
60
+
61
+ Factory.define :answer do |a|
62
+ a.association :question # a.question_id {}
63
+ a.text {"My favorite color is clear"}
64
+ a.short_text {"clear"}
65
+ a.help_text {"Clear is the absense of color"}
66
+ a.weight {}
67
+ a.response_class {"String"}
68
+ a.reference_identifier {}
69
+ a.data_export_identifier {}
70
+ a.common_namespace {}
71
+ a.common_identifier {}
72
+ a.display_order {Factory.next :answer_display_order}
73
+ a.is_exclusive {}
74
+ a.hide_label {}
75
+ a.display_length {}
76
+ a.custom_class {}
77
+ a.custom_renderer {}
78
+ end
79
+
80
+ Factory.define :dependency do |d|
81
+ # the dependent question
82
+ d.association :question # d.question_id {}
83
+ d.question_group_id {}
84
+ d.rule {"A"}
85
+ end
86
+
87
+ Factory.define :dependency_condition do |d|
88
+ d.association :dependency # d.dependency_id {}
89
+ d.rule_key {"A"}
90
+ # the conditional question
91
+ d.question_id {}
92
+ d.operator {"=="}
93
+ d.answer_id {}
94
+ d.datetime_value {}
95
+ d.integer_value {}
96
+ d.float_value {}
97
+ d.unit {}
98
+ d.text_value {}
99
+ d.string_value {}
100
+ d.response_other {}
101
+ end
102
+
103
+ Factory.define :response_set do |r|
104
+ r.user_id {}
105
+ r.association :survey # r.survey_id {}
106
+ r.access_code {Surveyor.make_tiny_code}
107
+ r.started_at {Time.now}
108
+ r.completed_at {}
109
+ end
110
+
111
+ Factory.define :response do |r|
112
+ r.association :response_set # r.response_set_id {}
113
+ r.question_id {}
114
+ r.answer_id {}
115
+ r.datetime_value {}
116
+ r.integer_value {}
117
+ r.float_value {}
118
+ r.unit {}
119
+ r.text_value {}
120
+ r.string_value {}
121
+ r.response_other {}
122
+ r.response_group {}
123
+ end
124
+
125
+ Factory.define :validation do |v|
126
+ v.association :answer # v.answer_id {}
127
+ v.rule {"A"}
128
+ v.message {}
129
+ end
130
+
131
+ Factory.define :validation_condition do |v|
132
+ v.association :validation # v.validation_id {}
133
+ v.rule_key {"A"}
134
+ v.question_id {}
135
+ v.operator {"=="}
136
+ v.answer_id {}
137
+ v.datetime_value {}
138
+ v.integer_value {}
139
+ v.float_value {}
140
+ v.unit {}
141
+ v.text_value {}
142
+ v.string_value {}
143
+ v.response_other {}
144
+ v.regexp {}
145
+ end
@@ -0,0 +1,44 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../lib/surveyor')
2
+
3
+ describe Surveyor do
4
+ it "should create a normalized code from the answer text" do
5
+ # The answer object should take the title of the text and convert it to a code that is more appropirate for a database entry
6
+
7
+
8
+
9
+
10
+ # Taking a few answers from the survey for testing
11
+ strings = [ "This? is a in - t3rrible-@nswer of! (question) on",
12
+ "Private insurance/ HMO/ PPO",
13
+ "<bold>VA</bold>",
14
+ "PMS (Premenstrual syndrome)/ PMDD (Premenstrual Dysphoric Disorder)",
15
+ "Have never been employed outside the home",
16
+ "Professional",
17
+ "Not working because of temporary disability, but expect to return to a job",
18
+ "How long has it been since you last visited a doctor for a routine checkup (routine being not for a particular reason)?",
19
+ "Do you take medications as directed?",
20
+ "Do you every leak urine (or) water when you didn't want to?", #checking for () and ' removal
21
+ "Do your biological family members (not adopted) have a \"history\" of any of the following?",
22
+ "Your health:",
23
+ "In general, you would say your health is:" ]
24
+
25
+ # What the results should look like
26
+ codes = [ "this_t3rrible_nswer",
27
+ "private_insurance_hmo_ppo",
28
+ "va",
29
+ "pms_pmdd",
30
+ "never_been_employed_outside_home",
31
+ "professional",
32
+ "temporary_disability_expect_return_job",
33
+ "visited_doctor_for_routine_checkup",
34
+ "you_take_medications_as_directed",
35
+ "urine_water_you_didnt_want",
36
+ "family_members_history_any_following",
37
+ "your_health",
38
+ "you_would_say_your_health" ]
39
+
40
+ strings.each_with_index do |s, i|
41
+ Surveyor.to_normalized_string(s).should == codes[i]
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,29 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Answer, "when creating a new answer" do
4
+ before(:each) do
5
+ @answer = Factory(:answer, :text => "Red")
6
+ end
7
+
8
+ it "should be valid" do
9
+ @answer.should be_valid
10
+ end
11
+
12
+ it "should be invalid without a question_id" do
13
+ @answer.question_id = nil
14
+ @answer.should_not be_valid
15
+ end
16
+
17
+ it "should have 'default' renderer with nil question.pick and response_class" do
18
+ @answer.question = Factory(:question, :pick => nil)
19
+ @answer.response_class = nil
20
+ @answer.renderer.should == :default
21
+ end
22
+
23
+ it "should have a_b renderer for a question.pick and B response_class" do
24
+ @answer.question = Factory(:question, :pick => "a")
25
+ @answer.response_class = "B"
26
+ @answer.renderer.should == :a_b
27
+ end
28
+
29
+ end
@@ -0,0 +1,321 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+
4
+ describe DependencyCondition, "Class methods" do
5
+ it "should have a list of operators" do
6
+ %w(== != < > <= >=).each{|operator| DependencyCondition.operators.include?(operator).should be_true }
7
+ end
8
+ end
9
+
10
+ describe DependencyCondition, "instance" do
11
+ before(:each) do
12
+ @dependency_condition = DependencyCondition.new(:dependency_id => 1, :question_id => 45, :operator => "==", :answer_id => 23, :rule_key => "1")
13
+ end
14
+
15
+ it "should be valid" do
16
+ @dependency_condition.should be_valid
17
+ end
18
+
19
+ it "should be invalid without a parent dependency_id, question_id, answer_id" do
20
+ @dependency_condition.dependency_id = nil
21
+ @dependency_condition.should have(1).errors_on(:dependency_id)
22
+ @dependency_condition.question_id = nil
23
+ @dependency_condition.should have(1).errors_on(:question_id)
24
+ @dependency_condition.answer_id = nil
25
+ @dependency_condition.should have(1).errors_on(:answer_id)
26
+ end
27
+
28
+ it "should be invalid without an operator" do
29
+ @dependency_condition.operator = nil
30
+ @dependency_condition.should have(2).errors_on(:operator)
31
+ end
32
+
33
+ it "should be invalid without a rule_key" do
34
+ @dependency_condition.should be_valid
35
+ @dependency_condition.rule_key = nil
36
+ @dependency_condition.should_not be_valid
37
+ @dependency_condition.should have(1).errors_on(:rule_key)
38
+ end
39
+
40
+ it "should have unique rule_key within the context of a dependency" do
41
+ @dependency_condition.should be_valid
42
+ DependencyCondition.create(:dependency_id => 2, :question_id => 46, :operator => "==", :answer_id => 14, :rule_key => "2")
43
+ @dependency_condition.rule_key = "2" #rule key uniquness is scoped by dependency_id
44
+ @dependency_condition.dependency_id = 2
45
+ @dependency_condition.should_not be_valid
46
+ @dependency_condition.should have(1).errors_on(:rule_key)
47
+ end
48
+
49
+ it "should have an operator in DependencyCondition.operators" do
50
+ DependencyCondition.operators.each do |o|
51
+ @dependency_condition.operator = o
52
+ @dependency_condition.should have(0).errors_on(:operator)
53
+ end
54
+ @dependency_condition.operator = "#"
55
+ @dependency_condition.should have(1).error_on(:operator)
56
+ end
57
+
58
+ it "should evaluate within the context of a response set object" do
59
+ @response = Response.new(:question_id => 45, :response_set_id => 40, :answer_id => 23)
60
+ @response.answer = Answer.new(:question_id => 45, :response_class => "answer")
61
+ @dependency_condition.is_met?(@response).should be_true
62
+ # inversion
63
+ @alt_response = Response.new(:question_id => 45, :response_set_id => 40, :answer_id => 55)
64
+ @alt_response.answer = Answer.new(:question_id => 45, :response_class => "answer")
65
+
66
+ @dependency_condition.is_met?(@alt_response).should be_false
67
+ end
68
+
69
+ it "converts to a hash for evaluation by the depedency object" do
70
+ @response = Response.new(:question_id => 45, :response_set_id => 40, :answer_id => 23)
71
+ @rs = mock(ResponseSet, :responses => [@response])
72
+ @dependency_condition.stub!(:is_met?).and_return(true)
73
+ @dependency_condition.to_hash(@rs)
74
+ end
75
+ end
76
+
77
+ describe DependencyCondition, "evaluting the resonse_set state" do
78
+
79
+ describe "when if given a response object whether the dependency is satisfied using '=='" do
80
+ before(:each) do
81
+ @dep_c = DependencyCondition.new(:answer_id => 2, :operator => "==")
82
+ @select_answer = Answer.new(:question_id => 1, :response_class => "answer")
83
+ @response = Response.new(:question_id => 314, :response_set_id => 159, :answer_id => 2)
84
+ @response.answer = @select_answer
85
+ @dep_c.answer = @select_answer
86
+ @dep_c.as(:answer).should == 2
87
+ @response.as(:answer).should == 2
88
+ @dep_c.as(:answer).should == @response.as(:answer)
89
+ end
90
+
91
+ it "knows checkbox/radio type response" do
92
+ @dep_c.is_met?(@response).should be_true
93
+ @dep_c.answer_id = 12
94
+ @dep_c.is_met?(@response).should be_false
95
+ end
96
+
97
+ it "knows string value response" do
98
+ @select_answer.response_class = "string"
99
+ @response.string_value = "hello123"
100
+ @dep_c.string_value = "hello123"
101
+ @dep_c.is_met?(@response).should be_true
102
+ @response.string_value = "foo_abc"
103
+ @dep_c.is_met?(@response).should be_false
104
+ end
105
+
106
+ it "knows a text value response" do
107
+ @select_answer.response_class = "text"
108
+ @response.text_value = "hello this is some text for comparison"
109
+ @dep_c.text_value = "hello this is some text for comparison"
110
+ @dep_c.is_met?(@response).should be_true
111
+ @response.text_value = "Not the same text"
112
+ @dep_c.is_met?(@response).should be_false
113
+ end
114
+
115
+ it "knows an integer value response" do
116
+ @select_answer.response_class = "integer"
117
+ @response.integer_value = 10045
118
+ @dep_c.integer_value = 10045
119
+ @dep_c.is_met?(@response).should be_true
120
+ @response.integer_value = 421
121
+ @dep_c.is_met?(@response).should be_false
122
+ end
123
+
124
+ it "knows a float value response" do
125
+ @select_answer.response_class = "float"
126
+ @response.float_value = 121.1
127
+ @dep_c.float_value = 121.1
128
+ @dep_c.is_met?(@response).should be_true
129
+ @response.float_value = 130.123
130
+ @dep_c.is_met?(@response).should be_false
131
+ end
132
+
133
+ end
134
+
135
+ describe "when if given a response object whether the dependency is satisfied using '!='" do
136
+ before(:each) do
137
+ @dep_c = DependencyCondition.new(:answer_id => 2, :operator => "!=")
138
+ @select_answer = Answer.new(:question_id => 1, :response_class => "answer")
139
+ @response = Response.new(:question_id => 314, :response_set_id => 159, :answer_id => 2)
140
+ @response.answer = @select_answer
141
+ @dep_c.answer = @select_answer
142
+ @dep_c.as(:answer).should == 2
143
+ @response.as(:answer).should == 2
144
+ @dep_c.as(:answer).should == @response.as(:answer)
145
+ end
146
+
147
+ it "knows checkbox/radio type response" do
148
+ @dep_c.is_met?(@response).should be_false
149
+ @dep_c.answer_id = 12
150
+ @dep_c.is_met?(@response).should be_true
151
+ end
152
+
153
+ it "knows string value response" do
154
+ @select_answer.response_class = "string"
155
+ @response.string_value = "hello123"
156
+ @dep_c.string_value = "hello123"
157
+ @dep_c.is_met?(@response).should be_false
158
+ @response.string_value = "foo_abc"
159
+ @dep_c.is_met?(@response).should be_true
160
+ end
161
+
162
+ it "knows a text value response" do
163
+ @select_answer.response_class = "text"
164
+ @response.text_value = "hello this is some text for comparison"
165
+ @dep_c.text_value = "hello this is some text for comparison"
166
+ @dep_c.is_met?(@response).should be_false
167
+ @response.text_value = "Not the same text"
168
+ @dep_c.is_met?(@response).should be_true
169
+ end
170
+
171
+ it "knows an integer value response" do
172
+ @select_answer.response_class = "integer"
173
+ @response.integer_value = 10045
174
+ @dep_c.integer_value = 10045
175
+ @dep_c.is_met?(@response).should be_false
176
+ @response.integer_value = 421
177
+ @dep_c.is_met?(@response).should be_true
178
+ end
179
+
180
+ it "knows a float value response" do
181
+ @select_answer.response_class = "float"
182
+ @response.float_value = 121.1
183
+ @dep_c.float_value = 121.1
184
+ @dep_c.is_met?(@response).should be_false
185
+ @response.float_value = 130.123
186
+ @dep_c.is_met?(@response).should be_true
187
+ end
188
+
189
+ end
190
+
191
+ describe "when if given a response object whether the dependency is satisfied using '<'" do
192
+ before(:each) do
193
+ @dep_c = DependencyCondition.new(:answer_id => 2, :operator => "<")
194
+ @select_answer = Answer.new(:question_id => 1, :response_class => "answer")
195
+ @response = Response.new(:question_id => 314, :response_set_id => 159, :answer_id => 2)
196
+ @response.answer = @select_answer
197
+ @dep_c.answer = @select_answer
198
+
199
+ end
200
+
201
+ it "knows operator on integer value response" do
202
+ @select_answer.response_class = "integer"
203
+ @response.integer_value = 50
204
+ @dep_c.integer_value = 100
205
+ @dep_c.is_met?(@response).should be_true
206
+ @response.integer_value = 421
207
+ @dep_c.is_met?(@response).should be_false
208
+ end
209
+
210
+ it "knows operator on float value response" do
211
+ @select_answer.response_class = "float"
212
+ @response.float_value = 5.1
213
+ @dep_c.float_value = 121.1
214
+ @dep_c.is_met?(@response).should be_true
215
+ @response.float_value = 130.123
216
+ @dep_c.is_met?(@response).should be_false
217
+ end
218
+
219
+ end
220
+
221
+ describe "when if given a response object whether the dependency is satisfied using '<='" do
222
+ before(:each) do
223
+ @dep_c = DependencyCondition.new(:answer_id => 2, :operator => "<=")
224
+ @select_answer = Answer.new(:question_id => 1, :response_class => "answer")
225
+ @response = Response.new(:question_id => 314, :response_set_id => 159, :answer_id => 2)
226
+ @response.answer = @select_answer
227
+ @dep_c.answer = @select_answer
228
+
229
+ end
230
+
231
+ it "knows operator on integer value response" do
232
+ @select_answer.response_class = "integer"
233
+ @response.integer_value = 50
234
+ @dep_c.integer_value = 100
235
+ @dep_c.is_met?(@response).should be_true
236
+ @response.integer_value = 100
237
+ @dep_c.is_met?(@response).should be_true
238
+ @response.integer_value = 421
239
+ @dep_c.is_met?(@response).should be_false
240
+ end
241
+
242
+ it "knows operator on float value response" do
243
+ @select_answer.response_class = "float"
244
+ @response.float_value = 5.1
245
+ @dep_c.float_value = 121.1
246
+ @dep_c.is_met?(@response).should be_true
247
+ @response.float_value = 121.1
248
+ @dep_c.is_met?(@response).should be_true
249
+ @response.float_value = 130.123
250
+ @dep_c.is_met?(@response).should be_false
251
+ end
252
+
253
+ end
254
+
255
+ describe "when if given a response object whether the dependency is satisfied using '>'" do
256
+ before(:each) do
257
+ @dep_c = DependencyCondition.new(:answer_id => 2, :operator => ">")
258
+ @select_answer = Answer.new(:question_id => 1, :response_class => "answer")
259
+ @response = Response.new(:question_id => 314, :response_set_id => 159, :answer_id => 2)
260
+ @response.answer = @select_answer
261
+ @dep_c.answer = @select_answer
262
+
263
+ end
264
+
265
+ it "knows operator on integer value response" do
266
+ @select_answer.response_class = "integer"
267
+ @response.integer_value = 50
268
+ @dep_c.integer_value = 100
269
+ @dep_c.is_met?(@response).should be_false
270
+ @response.integer_value = 421
271
+ @dep_c.is_met?(@response).should be_true
272
+ end
273
+
274
+ it "knows operator on float value response" do
275
+ @select_answer.response_class = "float"
276
+ @response.float_value = 5.1
277
+ @dep_c.float_value = 121.1
278
+ @dep_c.is_met?(@response).should be_false
279
+ @response.float_value = 130.123
280
+ @dep_c.is_met?(@response).should be_true
281
+ end
282
+
283
+ end
284
+
285
+ describe "when if given a response object whether the dependency is satisfied using '>='" do
286
+ before(:each) do
287
+ @dep_c = DependencyCondition.new(:answer_id => 2, :operator => ">=")
288
+ @select_answer = Answer.new(:question_id => 1, :response_class => "answer")
289
+ @response = Response.new(:question_id => 314, :response_set_id => 159, :answer_id => 2)
290
+ @response.answer = @select_answer
291
+ @dep_c.answer = @select_answer
292
+
293
+ end
294
+
295
+ it "knows operator on integer value response" do
296
+ @select_answer.response_class = "integer"
297
+ @response.integer_value = 50
298
+ @dep_c.integer_value = 100
299
+ @dep_c.is_met?(@response).should be_false
300
+ @response.integer_value = 100
301
+ @dep_c.is_met?(@response).should be_true
302
+ @response.integer_value = 421
303
+ @dep_c.is_met?(@response).should be_true
304
+ end
305
+
306
+ it "knows operator on float value response" do
307
+ @select_answer.response_class = "float"
308
+ @response.float_value = 5.1
309
+ @dep_c.float_value = 121.1
310
+ @dep_c.is_met?(@response).should be_false
311
+ @response.float_value = 121.1
312
+ @dep_c.is_met?(@response).should be_true
313
+ @response.float_value = 130.123
314
+ @dep_c.is_met?(@response).should be_true
315
+ end
316
+ end
317
+
318
+
319
+
320
+ end
321
+