surveyor 0.22.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) hide show
  1. data/.gitignore +1 -0
  2. data/.rspec +1 -0
  3. data/CHANGELOG.md +83 -0
  4. data/Gemfile.rails_version +7 -1
  5. data/README.md +114 -16
  6. data/Rakefile +15 -9
  7. data/app/inputs/quiet_input.rb +5 -0
  8. data/app/inputs/surveyor_check_boxes_input.rb +35 -0
  9. data/app/inputs/surveyor_radio_input.rb +18 -0
  10. data/app/views/partials/_answer.html.haml +4 -4
  11. data/app/views/partials/_question.html.haml +7 -7
  12. data/app/views/partials/_question_group.html.haml +9 -8
  13. data/app/views/surveyor/export.json.rabl +28 -25
  14. data/app/views/surveyor/new.html.haml +8 -5
  15. data/app/views/surveyor/show.json.rabl +3 -2
  16. data/ci-exec.sh +13 -7
  17. data/cucumber.yml +3 -3
  18. data/doc/REPRESENTATIONS.md +34 -0
  19. data/doc/api_id_schema.json +7 -0
  20. data/doc/response_set_schema.json +54 -0
  21. data/doc/surveyor question combinations.png +0 -0
  22. data/doc/surveyor_timestamp_schema.json +9 -0
  23. data/features/ajax_submissions.feature +140 -0
  24. data/features/export_to_json.feature +182 -34
  25. data/features/no_duplicates.feature +110 -0
  26. data/features/show_survey.feature +1 -1
  27. data/features/step_definitions/parser_steps.rb +25 -2
  28. data/features/step_definitions/surveyor_steps.rb +145 -20
  29. data/features/step_definitions/ui_steps.rb +3 -0
  30. data/features/support/database_cleaner.rb +16 -0
  31. data/features/support/env.rb +21 -17
  32. data/features/support/simultaneous_ajax.rb +101 -0
  33. data/features/support/single_quit_selenium_driver.rb +23 -0
  34. data/features/support/slow_updates.rb +18 -0
  35. data/features/surveyor.feature +174 -44
  36. data/features/surveyor_dependencies.feature +80 -39
  37. data/features/surveyor_parser.feature +114 -20
  38. data/features/z_redcap_parser.feature +0 -1
  39. data/lib/{generators/surveyor/templates/public → assets}/images/surveyor/next.gif +0 -0
  40. data/lib/{generators/surveyor/templates/public → assets}/images/surveyor/prev.gif +0 -0
  41. data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  42. data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  43. data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-bg_glass_65_ffffff_1x400.png +0 -0
  44. data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  45. data/lib/assets/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  46. data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  47. data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-icons_ef8c08_256x240.png +0 -0
  48. data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-icons_ffffff_256x240.png +0 -0
  49. data/lib/{generators/surveyor/templates/public → assets}/javascripts/surveyor/jquery-ui-timepicker-addon.js +23 -23
  50. data/lib/{generators/surveyor/templates/public → assets}/javascripts/surveyor/jquery-ui.js +125 -125
  51. data/lib/assets/javascripts/surveyor/jquery.selectToUISlider.js +240 -0
  52. data/lib/{generators/surveyor/templates/public → assets}/javascripts/surveyor/jquery.surveyor.js +52 -57
  53. data/lib/{generators/surveyor/templates/public → assets}/javascripts/surveyor/jquery.tools.min.js +7 -7
  54. data/lib/{generators/surveyor/templates/public → assets}/stylesheets/surveyor/dateinput.css +13 -13
  55. data/lib/{generators/surveyor/templates/public → assets}/stylesheets/surveyor/jquery-ui-timepicker-addon.css +0 -0
  56. data/lib/{generators/surveyor/templates/public → assets}/stylesheets/surveyor/jquery-ui.custom.css +17 -17
  57. data/lib/{generators/surveyor/templates/public → assets}/stylesheets/surveyor/reset.css +1 -1
  58. data/lib/{generators/surveyor/templates/public → assets}/stylesheets/surveyor/results.css +0 -0
  59. data/lib/assets/stylesheets/surveyor/ui.slider.extras.css +110 -0
  60. data/lib/{generators/surveyor/templates/public/stylesheets/sass → assets/stylesheets}/surveyor.sass +15 -7
  61. data/lib/generators/surveyor/custom_generator.rb +3 -2
  62. data/lib/generators/surveyor/install_generator.rb +59 -17
  63. data/lib/generators/surveyor/templates/app/assets/javascripts/surveyor_all.js +5 -0
  64. data/lib/generators/surveyor/templates/app/assets/stylesheets/surveyor_all.css +9 -0
  65. data/lib/generators/surveyor/templates/app/controllers/surveyor_controller.rb +2 -1
  66. data/lib/generators/surveyor/templates/app/views/layouts/surveyor_custom.html.erb +1 -0
  67. data/lib/generators/surveyor/templates/config/locales/surveyor_es.yml +1 -0
  68. data/lib/generators/surveyor/templates/config/locales/surveyor_he.yml +1 -0
  69. data/lib/generators/surveyor/templates/db/migrate/add_api_id_to_question_groups.rb +1 -0
  70. data/lib/generators/surveyor/templates/db/migrate/add_api_ids.rb +1 -0
  71. data/lib/generators/surveyor/templates/db/migrate/add_api_ids_to_response_sets_and_responses.rb +1 -0
  72. data/lib/generators/surveyor/templates/db/migrate/add_correct_answer_id_to_questions.rb +1 -0
  73. data/lib/generators/surveyor/templates/db/migrate/add_default_value_to_answers.rb +1 -0
  74. data/lib/generators/surveyor/templates/db/migrate/add_display_order_to_surveys.rb +1 -0
  75. data/lib/generators/surveyor/templates/db/migrate/add_display_type_to_answers.rb +1 -0
  76. data/lib/generators/surveyor/templates/db/migrate/add_index_to_response_sets.rb +1 -0
  77. data/lib/generators/surveyor/templates/db/migrate/add_index_to_surveys.rb +1 -0
  78. data/lib/generators/surveyor/templates/db/migrate/add_section_id_to_responses.rb +1 -0
  79. data/lib/generators/surveyor/templates/db/migrate/add_unique_index_on_access_code_and_version_in_surveys.rb +10 -0
  80. data/lib/generators/surveyor/templates/db/migrate/add_unique_indicies.rb +3 -2
  81. data/lib/generators/surveyor/templates/db/migrate/add_version_to_surveys.rb +10 -0
  82. data/lib/generators/surveyor/templates/db/migrate/api_ids_must_be_unique.rb +23 -0
  83. data/lib/generators/surveyor/templates/db/migrate/create_answers.rb +6 -5
  84. data/lib/generators/surveyor/templates/db/migrate/create_dependencies.rb +2 -1
  85. data/lib/generators/surveyor/templates/db/migrate/create_dependency_conditions.rb +2 -1
  86. data/lib/generators/surveyor/templates/db/migrate/create_question_groups.rb +5 -4
  87. data/lib/generators/surveyor/templates/db/migrate/create_questions.rb +4 -3
  88. data/lib/generators/surveyor/templates/db/migrate/create_response_sets.rb +1 -0
  89. data/lib/generators/surveyor/templates/db/migrate/create_responses.rb +10 -9
  90. data/lib/generators/surveyor/templates/db/migrate/create_survey_sections.rb +5 -4
  91. data/lib/generators/surveyor/templates/db/migrate/create_surveys.rb +4 -3
  92. data/lib/generators/surveyor/templates/db/migrate/create_validation_conditions.rb +5 -4
  93. data/lib/generators/surveyor/templates/db/migrate/create_validations.rb +3 -2
  94. data/lib/generators/surveyor/templates/db/migrate/drop_unique_index_on_access_code_in_surveys.rb +10 -0
  95. data/lib/generators/surveyor/templates/db/migrate/update_blank_api_ids_on_question_group.rb +22 -0
  96. data/lib/generators/surveyor/templates/db/migrate/update_blank_versions_on_surveys.rb +13 -0
  97. data/lib/generators/surveyor/templates/surveys/date_survey.rb +1 -0
  98. data/lib/generators/surveyor/templates/surveys/kitchen_sink_survey.rb +54 -24
  99. data/lib/generators/surveyor/templates/surveys/quiz.rb +1 -0
  100. data/lib/generators/surveyor/templates/{public/stylesheets/sass → vendor/assets/stylesheets}/custom.sass +1 -1
  101. data/lib/surveyor/common.rb +16 -31
  102. data/lib/surveyor/engine.rb +2 -4
  103. data/lib/surveyor/helpers/asset_pipeline.rb +13 -0
  104. data/lib/surveyor/helpers/formtastic_custom_input.rb +17 -0
  105. data/lib/surveyor/helpers/surveyor_helper_methods.rb +10 -8
  106. data/lib/surveyor/models/answer_methods.rb +3 -0
  107. data/lib/surveyor/models/dependency_condition_methods.rb +27 -28
  108. data/lib/surveyor/models/dependency_methods.rb +3 -0
  109. data/lib/surveyor/models/question_group_methods.rb +3 -0
  110. data/lib/surveyor/models/question_methods.rb +10 -7
  111. data/lib/surveyor/models/response_methods.rb +16 -0
  112. data/lib/surveyor/models/response_set_methods.rb +71 -64
  113. data/lib/surveyor/models/survey_methods.rb +19 -28
  114. data/lib/surveyor/models/survey_section_methods.rb +3 -0
  115. data/lib/surveyor/models/validation_condition_methods.rb +4 -2
  116. data/lib/surveyor/models/validation_methods.rb +3 -0
  117. data/lib/surveyor/parser.rb +198 -148
  118. data/lib/surveyor/redcap_parser.rb +120 -80
  119. data/lib/surveyor/surveyor_controller_methods.rb +86 -37
  120. data/lib/surveyor/version.rb +2 -2
  121. data/lib/surveyor.rb +5 -6
  122. data/lib/tasks/surveyor_tasks.rake +19 -7
  123. data/spec/controllers/surveyor_controller_spec.rb +166 -92
  124. data/spec/factories.rb +33 -32
  125. data/spec/helpers/formtastic_custom_input_spec.rb +16 -0
  126. data/spec/lib/common_spec.rb +0 -39
  127. data/spec/lib/redcap_parser_spec.rb +24 -24
  128. data/spec/models/answer_spec.rb +12 -0
  129. data/spec/models/dependency_condition_spec.rb +279 -323
  130. data/spec/models/dependency_spec.rb +10 -0
  131. data/spec/models/question_group_spec.rb +12 -0
  132. data/spec/models/question_spec.rb +12 -0
  133. data/spec/models/response_set_spec.rb +189 -139
  134. data/spec/models/response_spec.rb +60 -0
  135. data/spec/models/survey_section_spec.rb +9 -0
  136. data/spec/models/survey_spec.rb +72 -9
  137. data/spec/models/validation_condition_spec.rb +9 -1
  138. data/spec/models/validation_spec.rb +10 -0
  139. data/spec/spec_helper.rb +25 -6
  140. data/surveyor.gemspec +5 -4
  141. metadata +332 -291
  142. data/features/step_definitions/common_steps.rb +0 -3
  143. data/lib/formtastic/surveyor_builder.rb +0 -82
  144. data/lib/generators/surveyor/templates/public/javascripts/surveyor/jquery.blockUI.js +0 -499
@@ -12,7 +12,7 @@ describe DependencyCondition do
12
12
  before(:each) do
13
13
  @dependency_condition = DependencyCondition.new(
14
14
  :dependency_id => 1, :question_id => 45, :operator => "==",
15
- :answer_id => 23, :rule_key => "1")
15
+ :answer_id => 23, :rule_key => "A")
16
16
  end
17
17
 
18
18
  it "should be valid" do
@@ -43,8 +43,8 @@ describe DependencyCondition do
43
43
  @dependency_condition.should be_valid
44
44
  DependencyCondition.create(
45
45
  :dependency_id => 2, :question_id => 46, :operator => "==",
46
- :answer_id => 14, :rule_key => "2")
47
- @dependency_condition.rule_key = "2" # rule key uniquness is scoped by dependency_id
46
+ :answer_id => 14, :rule_key => "B")
47
+ @dependency_condition.rule_key = "B" # rule key uniquness is scoped by dependency_id
48
48
  @dependency_condition.dependency_id = 2
49
49
  @dependency_condition.should_not be_valid
50
50
  @dependency_condition.should have(1).errors_on(:rule_key)
@@ -59,378 +59,334 @@ describe DependencyCondition do
59
59
  @dependency_condition.should have(1).error_on(:operator)
60
60
  end
61
61
 
62
- it "should evaluate within the context of a response set object" do
63
- @response = Response.new(:question_id => 45, :response_set_id => 40, :answer_id => 23)
64
- @response.answer = Answer.new(:question_id => 45, :response_class => "answer").
65
- tap { |a| a.id = 23 }
66
- @dependency_condition.is_met?([@response]).should be_true
67
- # inversion
68
- @alt_response = Response.new(:question_id => 45, :response_set_id => 40)
69
- @alt_response.answer = Answer.new(:question_id => 45, :response_class => "answer").
70
- tap { |a| a.id = 55 }
71
-
72
- @dependency_condition.is_met?([@alt_response]).should be_false
62
+ it "should protect timestamps" do
63
+ saved_attrs = @dependency_condition.attributes
64
+ if defined? ActiveModel::MassAssignmentSecurity::Error
65
+ lambda {@dependency_condition.update_attributes(:created_at => 3.days.ago, :updated_at => 3.hours.ago)}.should raise_error(ActiveModel::MassAssignmentSecurity::Error)
66
+ else
67
+ @dependency_condition.attributes = {:created_at => 3.days.ago, :updated_at => 3.hours.ago} # automatically protected by Rails
68
+ end
69
+ @dependency_condition.attributes.should == saved_attrs
73
70
  end
74
71
 
75
- it "converts to a hash for evaluation by the dependency object" do
76
- @response = Response.new(:question_id => 45, :response_set_id => 40, :answer_id => 23)
77
- @rs = mock(ResponseSet, :responses => [@response])
78
- @dependency_condition.stub!(:is_met?).and_return(true)
79
- @dependency_condition.to_hash(@rs)
80
- end
81
72
  end
82
73
 
83
- describe "to_hash" do
84
- before do
85
- @question = Factory(:question)
86
- @answer = Factory(:answer, :question => @question)
87
- @dependency_condition =
88
- Factory(:dependency_condition, :rule_key => "A", :question => @question)
89
- @rs = Factory(:response_set)
90
- @response =
91
- Factory(:response, :question => @question, :answer => @answer, :response_set => @rs)
92
- @rs.responses << @response
93
- @rs.save!
94
- end
95
-
96
- it "converts unmet condition to {:A => false}" do
97
- @dependency_condition.stub!(:is_met?).and_return(false)
98
- @dependency_condition.to_hash(@rs).should == {:A => false}
99
- end
100
-
101
- it "converts met condition to {:A => true}" do
102
- @dependency_condition.stub!(:is_met?).and_return(true)
103
- @dependency_condition.to_hash(@rs).should == {:A => true}
104
- end
105
-
106
- it "converts unanswered condition to {:A => false}" do
107
- question = Factory(:question)
108
- dependency_condition =
109
- Factory(:dependency_condition, :rule_key => "A", :question => @question)
110
- rs = Factory(:response_set)
111
- dependency_condition.to_hash(rs).should == {:A => false}
112
- end
74
+ it "returns true for != with no responses" do
75
+ question = Factory(:question)
76
+ dependency_condition = Factory(:dependency_condition, :rule_key => "C", :question => question)
77
+ rs = Factory(:response_set)
78
+ dependency_condition.to_hash(rs).should == {:C => false}
113
79
  end
114
80
 
115
- describe "when if given a response object whether the dependency is satisfied using '=='" do
81
+ describe "evaluate '==' operator" do
116
82
  before(:each) do
117
- @select_answer = Answer.new(:question_id => 1, :response_class => "answer").
118
- tap { |a| a.id = 2 }
119
- @dep_c = DependencyCondition.new(:operator => "==", :answer_id => @select_answer.id)
120
- @response = Response.new(:question_id => 314, :response_set_id => 159, :answer_id => @select_answer.id)
121
- @response.answer = @select_answer
122
- @dep_c.answer = @select_answer
123
- @dep_c.as(:answer).should == 2
124
- @response.as(:answer).should == 2
125
- @dep_c.as(:answer).should == @response.as(:answer)
126
- end
127
-
128
- it "knows checkbox/radio type response" do
129
- @dep_c.is_met?([@response]).should be_true
130
- @dep_c.answer_id = 12
131
- @dep_c.is_met?([@response]).should be_false
132
- end
133
-
134
- it "knows string value response" do
135
- @select_answer.response_class = "string"
136
- @response.string_value = "hello123"
137
- @dep_c.string_value = "hello123"
138
- @dep_c.is_met?([@response]).should be_true
139
- @response.string_value = "foo_abc"
140
- @dep_c.is_met?([@response]).should be_false
141
- end
142
-
143
- it "knows a text value response" do
144
- @select_answer.response_class = "text"
145
- @response.text_value = "hello this is some text for comparison"
146
- @dep_c.text_value = "hello this is some text for comparison"
147
- @dep_c.is_met?([@response]).should be_true
148
- @response.text_value = "Not the same text"
149
- @dep_c.is_met?([@response]).should be_false
150
- end
151
-
152
- it "knows an integer value response" do
153
- @select_answer.response_class = "integer"
154
- @response.integer_value = 10045
155
- @dep_c.integer_value = 10045
156
- @dep_c.is_met?([@response]).should be_true
157
- @response.integer_value = 421
158
- @dep_c.is_met?([@response]).should be_false
159
- end
160
-
161
- it "knows a float value response" do
162
- @select_answer.response_class = "float"
163
- @response.float_value = 121.1
164
- @dep_c.float_value = 121.1
165
- @dep_c.is_met?([@response]).should be_true
166
- @response.float_value = 130.123
167
- @dep_c.is_met?([@response]).should be_false
83
+ @a = Factory(:answer)
84
+ @b = Factory(:answer, :question => @a.question)
85
+ @r = Factory(:response, :question => @a.question, :answer => @a)
86
+ @rs = @r.response_set
87
+ @dc = Factory(:dependency_condition, :question => @a.question, :answer => @a, :operator => "==", :rule_key => "D")
88
+ @dc.as(:answer).should == @r.as(:answer)
89
+ end
90
+
91
+ it "with checkbox/radio type response" do
92
+ @dc.to_hash(@rs).should == {:D => true}
93
+ @dc.answer = @b
94
+ @dc.to_hash(@rs).should == {:D => false}
95
+ end
96
+
97
+ it "with string value response" do
98
+ @a.update_attributes(:response_class => "string")
99
+ @r.update_attributes(:string_value => "hello123")
100
+ @dc.string_value = "hello123"
101
+ @dc.to_hash(@rs).should == {:D => true}
102
+ @r.update_attributes(:string_value => "foo_abc")
103
+ @dc.to_hash(@rs).should == {:D => false}
104
+ end
105
+
106
+ it "with a text value response" do
107
+ @a.update_attributes(:response_class => "text")
108
+ @r.update_attributes(:text_value => "hello this is some text for comparison")
109
+ @dc.text_value = "hello this is some text for comparison"
110
+ @dc.to_hash(@rs).should == {:D => true}
111
+ @r.update_attributes(:text_value => "Not the same text")
112
+ @dc.to_hash(@rs).should == {:D => false}
113
+ end
114
+
115
+ it "with an integer value response" do
116
+ @a.update_attributes(:response_class => "integer")
117
+ @r.update_attributes(:integer_value => 10045)
118
+ @dc.integer_value = 10045
119
+ @dc.to_hash(@rs).should == {:D => true}
120
+ @r.update_attributes(:integer_value => 421)
121
+ @dc.to_hash(@rs).should == {:D => false}
122
+ end
123
+
124
+ it "with a float value response" do
125
+ @a.update_attributes(:response_class => "float")
126
+ @r.update_attributes(:float_value => 121.1)
127
+ @dc.float_value = 121.1
128
+ @dc.to_hash(@rs).should == {:D => true}
129
+ @r.update_attributes(:float_value => 130.123)
130
+ @dc.to_hash(@rs).should == {:D => false}
168
131
  end
169
132
  end
170
133
 
171
- describe "when if given a response object whether the dependency is satisfied using '!='" do
134
+ describe "evaluate '!=' operator" do
172
135
  before(:each) do
173
- @select_answer = Answer.new(:question_id => 1, :response_class => "answer").
174
- tap { |a| a.id = 2 }
175
- @response = Response.new(:question_id => 314, :response_set_id => 159, :answer_id => @select_answer.id)
176
- @dep_c = DependencyCondition.new(:operator => "!=", :answer_id => @select_answer.id)
177
- @response.answer = @select_answer
178
- @dep_c.answer = @select_answer
179
- @dep_c.as(:answer).should == 2
180
- @response.as(:answer).should == 2
181
- @dep_c.as(:answer).should == @response.as(:answer)
182
- end
183
-
184
- it "knows checkbox/radio type response" do
185
- @dep_c.is_met?([@response]).should be_false
186
- @dep_c.answer_id = 12
187
- @dep_c.is_met?([@response]).should be_true
188
- end
189
-
190
- it "knows string value response" do
191
- @select_answer.response_class = "string"
192
- @response.string_value = "hello123"
193
- @dep_c.string_value = "hello123"
194
- @dep_c.is_met?([@response]).should be_false
195
- @response.string_value = "foo_abc"
196
- @dep_c.is_met?([@response]).should be_true
197
- end
198
-
199
- it "knows a text value response" do
200
- @select_answer.response_class = "text"
201
- @response.text_value = "hello this is some text for comparison"
202
- @dep_c.text_value = "hello this is some text for comparison"
203
- @dep_c.is_met?([@response]).should be_false
204
- @response.text_value = "Not the same text"
205
- @dep_c.is_met?([@response]).should be_true
206
- end
207
-
208
- it "knows an integer value response" do
209
- @select_answer.response_class = "integer"
210
- @response.integer_value = 10045
211
- @dep_c.integer_value = 10045
212
- @dep_c.is_met?([@response]).should be_false
213
- @response.integer_value = 421
214
- @dep_c.is_met?([@response]).should be_true
215
- end
216
-
217
- it "knows a float value response" do
218
- @select_answer.response_class = "float"
219
- @response.float_value = 121.1
220
- @dep_c.float_value = 121.1
221
- @dep_c.is_met?([@response]).should be_false
222
- @response.float_value = 130.123
223
- @dep_c.is_met?([@response]).should be_true
136
+ @a = Factory(:answer)
137
+ @b = Factory(:answer, :question => @a.question)
138
+ @r = Factory(:response, :question => @a.question, :answer => @a)
139
+ @rs = @r.response_set
140
+ @dc = Factory(:dependency_condition, :question => @a.question, :answer => @a, :operator => "!=", :rule_key => "E")
141
+ @dc.as(:answer).should == @r.as(:answer)
142
+ end
143
+
144
+ it "with checkbox/radio type response" do
145
+ @dc.to_hash(@rs).should == {:E => false}
146
+ @dc.answer_id = @a.id.to_i+1
147
+ @dc.to_hash(@rs).should == {:E => true}
148
+ end
149
+
150
+ it "with string value response" do
151
+ @a.update_attributes(:response_class => "string")
152
+ @r.update_attributes(:string_value => "hello123")
153
+ @dc.string_value = "hello123"
154
+ @dc.to_hash(@rs).should == {:E => false}
155
+ @r.update_attributes(:string_value => "foo_abc")
156
+ @dc.to_hash(@rs).should == {:E => true}
157
+ end
158
+
159
+ it "with a text value response" do
160
+ @a.update_attributes(:response_class => "text")
161
+ @r.update_attributes(:text_value => "hello this is some text for comparison")
162
+ @dc.text_value = "hello this is some text for comparison"
163
+ @dc.to_hash(@rs).should == {:E => false}
164
+ @r.update_attributes(:text_value => "Not the same text")
165
+ @dc.to_hash(@rs).should == {:E => true}
166
+ end
167
+
168
+ it "with an integer value response" do
169
+ @a.update_attributes(:response_class => "integer")
170
+ @r.update_attributes(:integer_value => 10045)
171
+ @dc.integer_value = 10045
172
+ @dc.to_hash(@rs).should == {:E => false}
173
+ @r.update_attributes(:integer_value => 421)
174
+ @dc.to_hash(@rs).should == {:E => true}
175
+ end
176
+
177
+ it "with a float value response" do
178
+ @a.update_attributes(:response_class => "float")
179
+ @r.update_attributes(:float_value => 121.1)
180
+ @dc.float_value = 121.1
181
+ @dc.to_hash(@rs).should == {:E => false}
182
+ @r.update_attributes(:float_value => 130.123)
183
+ @dc.to_hash(@rs).should == {:E => true}
224
184
  end
225
185
  end
226
186
 
227
- describe "when if given a response object whether the dependency is satisfied using '<'" do
187
+ describe "evaluate the '<' operator" do
228
188
  before(:each) do
229
- @dep_c = DependencyCondition.new(:answer_id => 2, :operator => "<")
230
- @select_answer = Answer.new(:question_id => 1, :response_class => "answer")
231
- @response = Response.new(:question_id => 314, :response_set_id => 159, :answer_id => 2)
232
- @response.answer = @select_answer
233
- @dep_c.answer = @select_answer
234
- end
235
-
236
- it "knows operator on integer value response" do
237
- @select_answer.response_class = "integer"
238
- @response.integer_value = 50
239
- @dep_c.integer_value = 100
240
- @dep_c.is_met?([@response]).should be_true
241
- @response.integer_value = 421
242
- @dep_c.is_met?([@response]).should be_false
243
- end
244
-
245
- it "knows operator on float value response" do
246
- @select_answer.response_class = "float"
247
- @response.float_value = 5.1
248
- @dep_c.float_value = 121.1
249
- @dep_c.is_met?([@response]).should be_true
250
- @response.float_value = 130.123
251
- @dep_c.is_met?([@response]).should be_false
189
+ @a = Factory(:answer)
190
+ @b = Factory(:answer, :question => @a.question)
191
+ @r = Factory(:response, :question => @a.question, :answer => @a)
192
+ @rs = @r.response_set
193
+ @dc = Factory(:dependency_condition, :question => @a.question, :answer => @a, :operator => "<", :rule_key => "F")
194
+ @dc.as(:answer).should == @r.as(:answer)
195
+ end
196
+
197
+ it "with an integer value response" do
198
+ @a.update_attributes(:response_class => "integer")
199
+ @r.update_attributes(:integer_value => 50)
200
+ @dc.integer_value = 100
201
+ @dc.to_hash(@rs).should == {:F => true}
202
+ @r.update_attributes(:integer_value => 421)
203
+ @dc.to_hash(@rs).should == {:F => false}
204
+ end
205
+
206
+ it "with a float value response" do
207
+ @a.update_attributes(:response_class => "float")
208
+ @r.update_attributes(:float_value => 5.1)
209
+ @dc.float_value = 121.1
210
+ @dc.to_hash(@rs).should == {:F => true}
211
+ @r.update_attributes(:float_value => 130.123)
212
+ @dc.to_hash(@rs).should == {:F => false}
252
213
  end
253
214
  end
254
215
 
255
- describe "when if given a response object whether the dependency is satisfied using '<='" do
216
+ describe "evaluate the '<=' operator" do
256
217
  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
- end
263
-
264
- it "knows operator on integer value response" do
265
- @select_answer.response_class = "integer"
266
- @response.integer_value = 50
267
- @dep_c.integer_value = 100
268
- @dep_c.is_met?([@response]).should be_true
269
- @response.integer_value = 100
270
- @dep_c.is_met?([@response]).should be_true
271
- @response.integer_value = 421
272
- @dep_c.is_met?([@response]).should be_false
273
- end
274
-
275
- it "knows operator on float value response" do
276
- @select_answer.response_class = "float"
277
- @response.float_value = 5.1
278
- @dep_c.float_value = 121.1
279
- @dep_c.is_met?([@response]).should be_true
280
- @response.float_value = 121.1
281
- @dep_c.is_met?([@response]).should be_true
282
- @response.float_value = 130.123
283
- @dep_c.is_met?([@response]).should be_false
218
+ @a = Factory(:answer)
219
+ @b = Factory(:answer, :question => @a.question)
220
+ @r = Factory(:response, :question => @a.question, :answer => @a)
221
+ @rs = @r.response_set
222
+ @dc = Factory(:dependency_condition, :question => @a.question, :answer => @a, :operator => "<=", :rule_key => "G")
223
+ @dc.as(:answer).should == @r.as(:answer)
224
+ end
225
+
226
+ it "with an integer value response" do
227
+ @a.update_attributes(:response_class => "integer")
228
+ @r.update_attributes(:integer_value => 50)
229
+ @dc.integer_value = 100
230
+ @dc.to_hash(@rs).should == {:G => true}
231
+ @r.update_attributes(:integer_value => 100)
232
+ @dc.to_hash(@rs).should == {:G => true}
233
+ @r.update_attributes(:integer_value => 421)
234
+ @dc.to_hash(@rs).should == {:G => false}
235
+ end
236
+
237
+ it "with a float value response" do
238
+ @a.update_attributes(:response_class => "float")
239
+ @r.update_attributes(:float_value => 5.1)
240
+ @dc.float_value = 121.1
241
+ @dc.to_hash(@rs).should == {:G => true}
242
+ @r.update_attributes(:float_value => 121.1)
243
+ @dc.to_hash(@rs).should == {:G => true}
244
+ @r.update_attributes(:float_value => 130.123)
245
+ @dc.to_hash(@rs).should == {:G => false}
284
246
  end
285
247
 
286
248
  end
287
249
 
288
- describe "when if given a response object whether the dependency is satisfied using '>'" do
250
+ describe "evaluate the '>' operator" do
289
251
  before(:each) do
290
- @dep_c = DependencyCondition.new(:answer_id => 2, :operator => ">")
291
- @select_answer = Answer.new(:question_id => 1, :response_class => "answer")
292
- @response = Response.new(:question_id => 314, :response_set_id => 159, :answer_id => 2)
293
- @response.answer = @select_answer
294
- @dep_c.answer = @select_answer
295
- end
296
-
297
- it "knows operator on integer value response" do
298
- @select_answer.response_class = "integer"
299
- @response.integer_value = 50
300
- @dep_c.integer_value = 100
301
- @dep_c.is_met?([@response]).should be_false
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 = 130.123
312
- @dep_c.is_met?([@response]).should be_true
252
+ @a = Factory(:answer)
253
+ @b = Factory(:answer, :question => @a.question)
254
+ @r = Factory(:response, :question => @a.question, :answer => @a)
255
+ @rs = @r.response_set
256
+ @dc = Factory(:dependency_condition, :question => @a.question, :answer => @a, :operator => ">", :rule_key => "H")
257
+ @dc.as(:answer).should == @r.as(:answer)
258
+ end
259
+
260
+ it "with an integer value response" do
261
+ @a.update_attributes(:response_class => "integer")
262
+ @r.update_attributes(:integer_value => 50)
263
+ @dc.integer_value = 100
264
+ @dc.to_hash(@rs).should == {:H => false}
265
+ @r.update_attributes(:integer_value => 421)
266
+ @dc.to_hash(@rs).should == {:H => true}
267
+ end
268
+
269
+ it "with a float value response" do
270
+ @a.update_attributes(:response_class => "float")
271
+ @r.update_attributes(:float_value => 5.1)
272
+ @dc.float_value = 121.1
273
+ @dc.to_hash(@rs).should == {:H => false}
274
+ @r.update_attributes(:float_value => 130.123)
275
+ @dc.to_hash(@rs).should == {:H => true}
313
276
  end
314
277
  end
315
278
 
316
- describe "when if given a response object whether the dependency is satisfied using '>='" do
279
+ describe "evaluate the '>=' operator" do
317
280
  before(:each) do
318
- @dep_c = DependencyCondition.new(:answer_id => 2, :operator => ">=")
319
- @select_answer = Answer.new(:question_id => 1, :response_class => "answer")
320
- @response = Response.new(:question_id => 314, :response_set_id => 159, :answer_id => 2)
321
- @response.answer = @select_answer
322
- @dep_c.answer = @select_answer
323
- end
324
-
325
- it "knows operator on integer value response" do
326
- @select_answer.response_class = "integer"
327
- @response.integer_value = 50
328
- @dep_c.integer_value = 100
329
- @dep_c.is_met?([@response]).should be_false
330
- @response.integer_value = 100
331
- @dep_c.is_met?([@response]).should be_true
332
- @response.integer_value = 421
333
- @dep_c.is_met?([@response]).should be_true
334
- end
335
-
336
- it "knows operator on float value response" do
337
- @select_answer.response_class = "float"
338
- @response.float_value = 5.1
339
- @dep_c.float_value = 121.1
340
- @dep_c.is_met?([@response]).should be_false
341
- @response.float_value = 121.1
342
- @dep_c.is_met?([@response]).should be_true
343
- @response.float_value = 130.123
344
- @dep_c.is_met?([@response]).should be_true
281
+ @a = Factory(:answer)
282
+ @b = Factory(:answer, :question => @a.question)
283
+ @r = Factory(:response, :question => @a.question, :answer => @a)
284
+ @rs = @r.response_set
285
+ @dc = Factory(:dependency_condition, :question => @a.question, :answer => @a, :operator => ">=", :rule_key => "I")
286
+ @dc.as(:answer).should == @r.as(:answer)
287
+ end
288
+
289
+ it "with an integer value response" do
290
+ @a.update_attributes(:response_class => "integer")
291
+ @r.update_attributes(:integer_value => 50)
292
+ @dc.integer_value = 100
293
+ @dc.to_hash(@rs).should == {:I => false}
294
+ @r.update_attributes(:integer_value => 100)
295
+ @dc.to_hash(@rs).should == {:I => true}
296
+ @r.update_attributes(:integer_value => 421)
297
+ @dc.to_hash(@rs).should == {:I => true}
298
+ end
299
+
300
+ it "with a float value response" do
301
+ @a.update_attributes(:response_class => "float")
302
+ @r.update_attributes(:float_value => 5.1)
303
+ @dc.float_value = 121.1
304
+ @dc.to_hash(@rs).should == {:I => false}
305
+ @r.update_attributes(:float_value => 121.1)
306
+ @dc.to_hash(@rs).should == {:I => true}
307
+ @r.update_attributes(:float_value => 130.123)
308
+ @dc.to_hash(@rs).should == {:I => true}
345
309
  end
346
310
  end
347
311
 
348
- describe "when evaluating a pick one/many with response_class e.g. string" do
312
+ describe "evaluating with response_class string" do
349
313
  it "should compare answer ids when the string_value is nil" do
350
- a = Factory(:answer, :response_class => "string")
351
- dc = Factory(:dependency_condition,
352
- :question_id => a.question.id, :answer_id => a.id, :operator => "==")
353
- r = Factory(:response, :question_id => a.question.id, :answer_id => a.id, :string_value => "")
354
- r.should_receive(:as).with("answer").and_return(a.id)
355
- dc.is_met?([r]).should be_true
314
+ @a = Factory(:answer, :response_class => "string")
315
+ @b = Factory(:answer, :question => @a.question)
316
+ @r = Factory(:response, :question => @a.question, :answer => @a, :string_value => "")
317
+ @rs = @r.response_set
318
+ @dc = Factory(:dependency_condition, :question => @a.question, :answer => @a, :operator => "==", :rule_key => "J")
319
+ @dc.to_hash(@rs).should == {:J => true}
356
320
  end
357
321
 
358
322
  it "should compare strings when the string_value is not nil, even if it is blank" do
359
- a = Factory(:answer, :response_class => "string")
360
- dc = Factory(:dependency_condition,
361
- :question_id => a.question.id, :answer_id => a.id,
362
- :operator => "==", :string_value => "foo")
363
- r = Factory(:response,
364
- :question_id => a.question.id, :answer_id => a.id, :string_value => "foo")
365
- r.should_receive(:as).with("string").and_return("foo")
366
- dc.is_met?([r]).should be_true
367
-
368
- dc2 = Factory(:dependency_condition,
369
- :question_id => a.question.id, :answer_id => a.id, :operator => "==", :string_value => "")
370
- r2 = Factory(:response,
371
- :question_id => a.question.id, :answer_id => a.id, :string_value => "")
372
- r2.should_receive(:as).with("string").and_return("")
373
- dc2.is_met?([r2]).should be_true
323
+ @a = Factory(:answer, :response_class => "string")
324
+ @b = Factory(:answer, :question => @a.question)
325
+ @r = Factory(:response, :question => @a.question, :answer => @a, :string_value => "foo")
326
+ @rs = @r.response_set
327
+ @dc = Factory(:dependency_condition, :question => @a.question, :answer => @a, :operator => "==", :rule_key => "K", :string_value => "foo")
328
+ @dc.to_hash(@rs).should == {:K => true}
329
+
330
+ @r.update_attributes(:string_value => "")
331
+ @dc.string_value = ""
332
+ @dc.to_hash(@rs).should == {:K => true}
374
333
  end
375
334
  end
376
335
 
377
- describe "when given responses whether the dependency is satisfied using 'count'" do
336
+ describe "evaluate 'count' operator" do
378
337
  before(:each) do
379
- @dep_c = DependencyCondition.new(:answer_id => nil,
380
- :operator => "count>2")
381
- @question = Question.new
382
- @select_answers = []
338
+ @q = Factory(:question)
339
+ @dc = DependencyCondition.new(:operator => "count>2", :rule_key => "M", :question => @q)
340
+ @as = []
383
341
  3.times do
384
- @select_answers << Answer.new(:question => @question,
385
- :response_class => "answer")
342
+ @as << Factory(:answer, :question => @q, :response_class => "answer")
386
343
  end
387
- @responses = []
388
- @select_answers.slice(0,2).each do |a|
389
- @responses << Response.new(:question => @question, :answer => a,
390
- :response_set_id => 159)
344
+ @rs = Factory(:response_set)
345
+ @as.slice(0,2).each do |a|
346
+ Factory(:response, :question => @q, :answer => a, :response_set => @rs)
391
347
  end
348
+ @rs.save
392
349
  end
393
350
 
394
- it "knows operator with >" do
395
- @dep_c.is_met?(@responses).should be_false
396
- @responses << Response.new(:question => @question,
397
- :answer => @select_answers.last,
398
- :response_set_id => 159)
399
- @dep_c.is_met?(@responses).should be_true
351
+ it "with operator with >" do
352
+ @dc.to_hash(@rs).should == {:M => false}
353
+ Factory(:response, :question => @q, :answer => @as.last, :response_set => @rs)
354
+ @rs.reload.responses.count.should == 3
355
+ @dc.to_hash(@rs.reload).should == {:M => true}
400
356
  end
401
357
 
402
- it "knows operator with <" do
403
- @dep_c.operator = "count<2"
404
- @dep_c.is_met?(@responses).should be_false
405
- @dep_c.operator = "count<3"
406
- @dep_c.is_met?(@responses).should be_true
358
+ it "with operator with <" do
359
+ @dc.operator = "count<2"
360
+ @dc.to_hash(@rs).should == {:M => false}
361
+ @dc.operator = "count<3"
362
+ @dc.to_hash(@rs).should == {:M => true}
407
363
  end
408
364
 
409
- it "knows operator with <=" do
410
- @dep_c.operator = "count<=1"
411
- @dep_c.is_met?(@responses).should be_false
412
- @dep_c.operator = "count<=2"
413
- @dep_c.is_met?(@responses).should be_true
414
- @dep_c.operator = "count<=3"
415
- @dep_c.is_met?(@responses).should be_true
365
+ it "with operator with <=" do
366
+ @dc.operator = "count<=1"
367
+ @dc.to_hash(@rs).should == {:M => false}
368
+ @dc.operator = "count<=2"
369
+ @dc.to_hash(@rs).should == {:M => true}
370
+ @dc.operator = "count<=3"
371
+ @dc.to_hash(@rs).should == {:M => true}
416
372
  end
417
373
 
418
- it "knows operator with >=" do
419
- @dep_c.operator = "count>=1"
420
- @dep_c.is_met?(@responses).should be_true
421
- @dep_c.operator = "count>=2"
422
- @dep_c.is_met?(@responses).should be_true
423
- @dep_c.operator = "count>=3"
424
- @dep_c.is_met?(@responses).should be_false
374
+ it "with operator with >=" do
375
+ @dc.operator = "count>=1"
376
+ @dc.to_hash(@rs).should == {:M => true}
377
+ @dc.operator = "count>=2"
378
+ @dc.to_hash(@rs).should == {:M => true}
379
+ @dc.operator = "count>=3"
380
+ @dc.to_hash(@rs).should == {:M => false}
425
381
  end
426
382
 
427
- it "knows operator with !=" do
428
- @dep_c.operator = "count!=1"
429
- @dep_c.is_met?(@responses).should be_true
430
- @dep_c.operator = "count!=2"
431
- @dep_c.is_met?(@responses).should be_false
432
- @dep_c.operator = "count!=3"
433
- @dep_c.is_met?(@responses).should be_true
383
+ it "with operator with !=" do
384
+ @dc.operator = "count!=1"
385
+ @dc.to_hash(@rs).should == {:M => true}
386
+ @dc.operator = "count!=2"
387
+ @dc.to_hash(@rs).should == {:M => false}
388
+ @dc.operator = "count!=3"
389
+ @dc.to_hash(@rs).should == {:M => true}
434
390
  end
435
391
  end
436
392
  end