hssc_surveyor 1.4.1.pre

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 (212) hide show
  1. data/.gitignore +28 -0
  2. data/.rspec +1 -0
  3. data/CHANGELOG.md +198 -0
  4. data/Gemfile +5 -0
  5. data/Gemfile.rails_version +19 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.md +186 -0
  8. data/Rakefile +105 -0
  9. data/app/controllers/surveyor_controller.rb +6 -0
  10. data/app/helpers/results_helper.rb +20 -0
  11. data/app/helpers/survey_form_builder.rb +37 -0
  12. data/app/helpers/surveyor_helper.rb +3 -0
  13. data/app/inputs/quiet_input.rb +5 -0
  14. data/app/inputs/surveyor_check_boxes_input.rb +35 -0
  15. data/app/inputs/surveyor_radio_input.rb +18 -0
  16. data/app/models/answer.rb +4 -0
  17. data/app/models/dependency.rb +4 -0
  18. data/app/models/dependency_condition.rb +4 -0
  19. data/app/models/question.rb +4 -0
  20. data/app/models/question_group.rb +5 -0
  21. data/app/models/response.rb +5 -0
  22. data/app/models/response_set.rb +4 -0
  23. data/app/models/survey.rb +4 -0
  24. data/app/models/survey_section.rb +5 -0
  25. data/app/models/survey_section_sweeper.rb +15 -0
  26. data/app/models/survey_translation.rb +5 -0
  27. data/app/models/validation.rb +4 -0
  28. data/app/models/validation_condition.rb +4 -0
  29. data/app/views/layouts/results.html.erb +13 -0
  30. data/app/views/layouts/surveyor_default.html.erb +12 -0
  31. data/app/views/partials/_answer.html.haml +25 -0
  32. data/app/views/partials/_dependents.html.haml +5 -0
  33. data/app/views/partials/_question.html.haml +41 -0
  34. data/app/views/partials/_question_group.html.haml +44 -0
  35. data/app/views/partials/_section.html.haml +12 -0
  36. data/app/views/partials/_section_menu.html.haml +12 -0
  37. data/app/views/surveyor/edit.html.haml +24 -0
  38. data/app/views/surveyor/export.json.rabl +85 -0
  39. data/app/views/surveyor/new.html.haml +24 -0
  40. data/app/views/surveyor/show.html.haml +74 -0
  41. data/app/views/surveyor/show.json.rabl +15 -0
  42. data/ci-exec.sh +56 -0
  43. data/config/routes.rb +8 -0
  44. data/cucumber.yml +10 -0
  45. data/doc/REPRESENTATIONS.md +34 -0
  46. data/doc/api_id_schema.json +7 -0
  47. data/doc/question types.png +0 -0
  48. data/doc/response_set_schema.json +54 -0
  49. data/doc/surveyor question combinations.png +0 -0
  50. data/doc/surveyor reject or delete decision matrix.png +0 -0
  51. data/doc/surveyor_models.png +0 -0
  52. data/doc/surveyor_models2.png +0 -0
  53. data/doc/surveyor_timestamp_schema.json +9 -0
  54. data/features/ajax_submissions.feature +140 -0
  55. data/features/export_to_json.feature +344 -0
  56. data/features/internationalization.feature +121 -0
  57. data/features/no_duplicates.feature +110 -0
  58. data/features/show_survey.feature +71 -0
  59. data/features/step_definitions/parser_steps.rb +145 -0
  60. data/features/step_definitions/surveyor_steps.rb +325 -0
  61. data/features/step_definitions/ui_steps.rb +25 -0
  62. data/features/step_definitions/web_steps.rb +225 -0
  63. data/features/support/REDCapDemoDatabase_DataDictionary.csv +127 -0
  64. data/features/support/database_cleaner.rb +16 -0
  65. data/features/support/env.rb +56 -0
  66. data/features/support/hooks.rb +4 -0
  67. data/features/support/paths.rb +39 -0
  68. data/features/support/redcap_new_headers.csv +1 -0
  69. data/features/support/redcap_siblings.csv +1 -0
  70. data/features/support/redcap_whitespace.csv +1 -0
  71. data/features/support/selectors.rb +39 -0
  72. data/features/support/simultaneous_ajax.rb +101 -0
  73. data/features/support/single_quit_selenium_driver.rb +23 -0
  74. data/features/support/slow_updates.rb +18 -0
  75. data/features/surveyor.feature +895 -0
  76. data/features/surveyor_dependencies.feature +476 -0
  77. data/features/surveyor_parser.feature +504 -0
  78. data/features/z_redcap_parser.feature +62 -0
  79. data/lib/assets/images/surveyor/next.gif +0 -0
  80. data/lib/assets/images/surveyor/prev.gif +0 -0
  81. data/lib/assets/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  82. data/lib/assets/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  83. data/lib/assets/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  84. data/lib/assets/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  85. data/lib/assets/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  86. data/lib/assets/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  87. data/lib/assets/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  88. data/lib/assets/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  89. data/lib/assets/images/ui-icons_222222_256x240.png +0 -0
  90. data/lib/assets/images/ui-icons_2e83ff_256x240.png +0 -0
  91. data/lib/assets/images/ui-icons_454545_256x240.png +0 -0
  92. data/lib/assets/images/ui-icons_888888_256x240.png +0 -0
  93. data/lib/assets/images/ui-icons_cd0a0a_256x240.png +0 -0
  94. data/lib/assets/javascripts/surveyor/jquery-1.9.0.js +9555 -0
  95. data/lib/assets/javascripts/surveyor/jquery-ui-1.10.0.custom.js +14850 -0
  96. data/lib/assets/javascripts/surveyor/jquery-ui-timepicker-addon.js +1919 -0
  97. data/lib/assets/javascripts/surveyor/jquery.maskedinput.js +338 -0
  98. data/lib/assets/javascripts/surveyor/jquery.selectToUISlider.js +240 -0
  99. data/lib/assets/javascripts/surveyor/jquery.surveyor.js +156 -0
  100. data/lib/assets/stylesheets/surveyor/jquery-ui-1.10.0.custom.css +1174 -0
  101. data/lib/assets/stylesheets/surveyor/jquery-ui-timepicker-addon.css +11 -0
  102. data/lib/assets/stylesheets/surveyor/reset.css +48 -0
  103. data/lib/assets/stylesheets/surveyor/results.css +125 -0
  104. data/lib/assets/stylesheets/surveyor/ui.slider.extras.css +110 -0
  105. data/lib/assets/stylesheets/surveyor.sass +132 -0
  106. data/lib/generators/surveyor/custom_generator.rb +18 -0
  107. data/lib/generators/surveyor/install_generator.rb +102 -0
  108. data/lib/generators/surveyor/templates/app/assets/javascripts/surveyor_all.js +6 -0
  109. data/lib/generators/surveyor/templates/app/assets/stylesheets/surveyor_all.css +9 -0
  110. data/lib/generators/surveyor/templates/app/controllers/surveyor_controller.rb +40 -0
  111. data/lib/generators/surveyor/templates/app/views/layouts/surveyor_custom.html.erb +13 -0
  112. data/lib/generators/surveyor/templates/config/locales/surveyor_en.yml +19 -0
  113. data/lib/generators/surveyor/templates/config/locales/surveyor_es.yml +19 -0
  114. data/lib/generators/surveyor/templates/config/locales/surveyor_he.yml +19 -0
  115. data/lib/generators/surveyor/templates/config/locales/surveyor_ko.yml +19 -0
  116. data/lib/generators/surveyor/templates/db/migrate/add_api_id_to_question_groups.rb +10 -0
  117. data/lib/generators/surveyor/templates/db/migrate/add_api_ids.rb +14 -0
  118. data/lib/generators/surveyor/templates/db/migrate/add_api_ids_to_response_sets_and_responses.rb +12 -0
  119. data/lib/generators/surveyor/templates/db/migrate/add_attachment_to_response.rb +5 -0
  120. data/lib/generators/surveyor/templates/db/migrate/add_correct_answer_id_to_questions.rb +10 -0
  121. data/lib/generators/surveyor/templates/db/migrate/add_default_value_to_answers.rb +10 -0
  122. data/lib/generators/surveyor/templates/db/migrate/add_display_order_to_surveys.rb +10 -0
  123. data/lib/generators/surveyor/templates/db/migrate/add_display_type_to_answers.rb +14 -0
  124. data/lib/generators/surveyor/templates/db/migrate/add_index_to_response_sets.rb +10 -0
  125. data/lib/generators/surveyor/templates/db/migrate/add_index_to_surveys.rb +10 -0
  126. data/lib/generators/surveyor/templates/db/migrate/add_input_mask_attributes_to_answer.rb +12 -0
  127. data/lib/generators/surveyor/templates/db/migrate/add_section_id_to_responses.rb +12 -0
  128. data/lib/generators/surveyor/templates/db/migrate/add_unique_index_on_access_code_and_version_in_surveys.rb +10 -0
  129. data/lib/generators/surveyor/templates/db/migrate/add_unique_indicies.rb +18 -0
  130. data/lib/generators/surveyor/templates/db/migrate/add_version_to_surveys.rb +10 -0
  131. data/lib/generators/surveyor/templates/db/migrate/api_ids_must_be_unique.rb +23 -0
  132. data/lib/generators/surveyor/templates/db/migrate/create_answers.rb +38 -0
  133. data/lib/generators/surveyor/templates/db/migrate/create_dependencies.rb +23 -0
  134. data/lib/generators/surveyor/templates/db/migrate/create_dependency_conditions.rb +30 -0
  135. data/lib/generators/surveyor/templates/db/migrate/create_question_groups.rb +28 -0
  136. data/lib/generators/surveyor/templates/db/migrate/create_questions.rb +37 -0
  137. data/lib/generators/surveyor/templates/db/migrate/create_response_sets.rb +23 -0
  138. data/lib/generators/surveyor/templates/db/migrate/create_responses.rb +34 -0
  139. data/lib/generators/surveyor/templates/db/migrate/create_survey_sections.rb +30 -0
  140. data/lib/generators/surveyor/templates/db/migrate/create_survey_translations.rb +19 -0
  141. data/lib/generators/surveyor/templates/db/migrate/create_surveys.rb +32 -0
  142. data/lib/generators/surveyor/templates/db/migrate/create_validation_conditions.rb +33 -0
  143. data/lib/generators/surveyor/templates/db/migrate/create_validations.rb +21 -0
  144. data/lib/generators/surveyor/templates/db/migrate/drop_unique_index_on_access_code_in_surveys.rb +10 -0
  145. data/lib/generators/surveyor/templates/db/migrate/update_blank_api_ids_on_question_group.rb +22 -0
  146. data/lib/generators/surveyor/templates/db/migrate/update_blank_versions_on_surveys.rb +13 -0
  147. data/lib/generators/surveyor/templates/surveys/EXTENDING_SURVEYOR.md +52 -0
  148. data/lib/generators/surveyor/templates/surveys/MODIFYING_SURVEYOR.md +91 -0
  149. data/lib/generators/surveyor/templates/surveys/date_survey.rb +16 -0
  150. data/lib/generators/surveyor/templates/surveys/kitchen_sink_survey.rb +284 -0
  151. data/lib/generators/surveyor/templates/surveys/languages.rb +14 -0
  152. data/lib/generators/surveyor/templates/surveys/quiz.rb +11 -0
  153. data/lib/generators/surveyor/templates/surveys/translations/languages.es.yml +18 -0
  154. data/lib/generators/surveyor/templates/surveys/translations/languages.he.yml +18 -0
  155. data/lib/generators/surveyor/templates/surveys/translations/languages.ko.yml +18 -0
  156. data/lib/generators/surveyor/templates/vendor/assets/stylesheets/custom.sass +5 -0
  157. data/lib/surveyor/acts_as_response.rb +17 -0
  158. data/lib/surveyor/common.rb +59 -0
  159. data/lib/surveyor/engine.rb +10 -0
  160. data/lib/surveyor/helpers/asset_pipeline.rb +13 -0
  161. data/lib/surveyor/helpers/formtastic_custom_input.rb +13 -0
  162. data/lib/surveyor/helpers/surveyor_helper_methods.rb +103 -0
  163. data/lib/surveyor/models/answer_methods.rb +86 -0
  164. data/lib/surveyor/models/dependency_condition_methods.rb +72 -0
  165. data/lib/surveyor/models/dependency_methods.rb +60 -0
  166. data/lib/surveyor/models/question_group_methods.rb +61 -0
  167. data/lib/surveyor/models/question_methods.rb +115 -0
  168. data/lib/surveyor/models/response_methods.rb +132 -0
  169. data/lib/surveyor/models/response_set_methods.rb +196 -0
  170. data/lib/surveyor/models/survey_methods.rb +103 -0
  171. data/lib/surveyor/models/survey_section_methods.rb +56 -0
  172. data/lib/surveyor/models/survey_translation_methods.rb +33 -0
  173. data/lib/surveyor/models/validation_condition_methods.rb +56 -0
  174. data/lib/surveyor/models/validation_methods.rb +48 -0
  175. data/lib/surveyor/mustache_context.rb +11 -0
  176. data/lib/surveyor/parser.rb +428 -0
  177. data/lib/surveyor/redcap_parser.rb +289 -0
  178. data/lib/surveyor/surveyor_controller_methods.rb +237 -0
  179. data/lib/surveyor/unparser.rb +147 -0
  180. data/lib/surveyor/version.rb +3 -0
  181. data/lib/surveyor.rb +13 -0
  182. data/lib/tasks/surveyor_tasks.rake +88 -0
  183. data/rails/init.rb +1 -0
  184. data/spec/controllers/surveyor_controller_spec.rb +307 -0
  185. data/spec/factories.rb +161 -0
  186. data/spec/helpers/formtastic_custom_input_spec.rb +15 -0
  187. data/spec/helpers/surveyor_helper_spec.rb +118 -0
  188. data/spec/lib/benchmark_spec.rb +22 -0
  189. data/spec/lib/chinese_survey.rb +14 -0
  190. data/spec/lib/common_spec.rb +34 -0
  191. data/spec/lib/parser_spec.rb +204 -0
  192. data/spec/lib/rake_kitchen_sink.rb +40 -0
  193. data/spec/lib/redcap_parser_spec.rb +75 -0
  194. data/spec/lib/tasks_spec.rake +26 -0
  195. data/spec/lib/unparser_spec.rb +126 -0
  196. data/spec/models/answer_spec.rb +175 -0
  197. data/spec/models/dependency_condition_spec.rb +439 -0
  198. data/spec/models/dependency_spec.rb +101 -0
  199. data/spec/models/question_group_spec.rb +93 -0
  200. data/spec/models/question_spec.rb +207 -0
  201. data/spec/models/response_set_spec.rb +477 -0
  202. data/spec/models/response_spec.rb +218 -0
  203. data/spec/models/survey_section_spec.rb +85 -0
  204. data/spec/models/survey_spec.rb +191 -0
  205. data/spec/models/validation_condition_spec.rb +113 -0
  206. data/spec/models/validation_spec.rb +74 -0
  207. data/spec/rcov.opts +2 -0
  208. data/spec/spec.opts +4 -0
  209. data/spec/spec_helper.rb +56 -0
  210. data/stacktests.sh +65 -0
  211. data/surveyor.gemspec +45 -0
  212. metadata +657 -0
@@ -0,0 +1,110 @@
1
+ @javascript @slow_updates @simultaneous_ajax
2
+ Feature: Duplicate response prevention
3
+ As a survey administrator
4
+ I want to get exactly the number of responses entered
5
+ So that my results are analytically valid
6
+
7
+ Scenario: With a simple pick-one question
8
+ Given the question
9
+ """
10
+ q_1 "Was this saved?", :pick => :one
11
+ a_y "Yes"
12
+ a_n "No"
13
+ """
14
+ When I start the survey
15
+ And I choose "Yes"
16
+ And I choose "No"
17
+ And I wait for things to settle out
18
+ Then there should be a response for answer "n"
19
+ And there should not be a response for answer "y"
20
+
21
+ Scenario: With a simple pick-any question
22
+ Given the question
23
+ """
24
+ q_1 "What is the state of the cat?", :pick => :any
25
+ a_d "Dead"
26
+ a_a "Alive"
27
+ a_s "Sleeping"
28
+ """
29
+ When I start the survey
30
+ And I check "Alive"
31
+ And I check "Dead"
32
+ And I uncheck "Dead"
33
+ And I check "Sleeping"
34
+ And I wait for things to settle out
35
+ Then there should be a response for answer "a"
36
+ And there should be a response for answer "s"
37
+ And there should not be a response for answer "d"
38
+
39
+ Scenario: With a free text question
40
+ Given the question
41
+ """
42
+ q_1 "What is your favorite movie?"
43
+ answer "Title", :string
44
+ """
45
+ When I start the survey
46
+ And I fill in "Title" with "The Shawshank Redemption"
47
+ And I click elsewhere
48
+ And I fill in "Title" with "Rear Window"
49
+ And I click elsewhere
50
+ And I wait for things to settle out
51
+ And there should be a string response with value "Rear Window"
52
+ Then there should not be a string response with value "The Shawshank Redemption"
53
+
54
+ Scenario: With a pick-one plus free text question
55
+ Given the question
56
+ """
57
+ q_1 "Where is Panama City?", :pick => :one
58
+ a_florida "Florida"
59
+ a_panama "Panama"
60
+ a_other :other, :string
61
+ """
62
+ When I start the survey
63
+ And I choose "Florida"
64
+ And I choose "Other"
65
+ And I fill in the string for "other" with "Chicago"
66
+ And I click elsewhere
67
+ And I wait for things to settle out
68
+ Then there should be a string response for answer "other" with value "Chicago"
69
+ And there should not be a response for answer "florida"
70
+
71
+ Scenario: With a grid question
72
+ Given the question
73
+ """
74
+ grid "Tell us how often do you cover these each day" do
75
+ a_1 "1"
76
+ a_2 "2"
77
+ a_3 "3"
78
+ q_h "Head", :pick => :one
79
+ q_k "Knees", :pick => :one
80
+ q_t "Toes", :pick => :one
81
+ end
82
+ """
83
+ When I start the survey
84
+ And I choose row 1, column 3 of the grid
85
+ And I choose row 1, column 2 of the grid
86
+ And I choose row 2, column 1 of the grid
87
+ And I wait for things to settle out
88
+ Then there should be a response for answer "2" on question "h"
89
+ And there should not be a response for answer "3" on question "h"
90
+ And there should be a response for answer "1" on question "k"
91
+
92
+ Scenario: With a repeater
93
+ Given the question
94
+ """
95
+ repeater "List your former addresses" do
96
+ q "Address"
97
+ a_address_line "Line", :string
98
+ end
99
+ """
100
+ When I start the survey
101
+ And I fill in the 1st string for "address_line" with "10 Downing St."
102
+ And I press "+ add row"
103
+ And I fill in the 2nd string for "address_line" with "1600 Penn Ave."
104
+ And I click elsewhere
105
+ And I fill in the 2nd string for "address_line" with "1600 Pennsylvania Ave."
106
+ And I click elsewhere
107
+ And I wait for things to settle out longer
108
+ Then there should be a string response for answer "address_line" with value "10 Downing St."
109
+ And there should not be a string response for answer "address_line" with value "1600 Penn Ave."
110
+ And there should be a string response for answer "address_line" with value "1600 Pennsylvania Ave."
@@ -0,0 +1,71 @@
1
+ Feature: showing a survey
2
+ As a survey administrator
3
+ I want to see a survey that a participant has taken
4
+ So that I can understand the data
5
+
6
+ Scenario: Take a survey, then look at it
7
+ Given I parse
8
+ """
9
+ survey "Favorites" do
10
+ section "Colors" do
11
+ label "You with the sad eyes don't be discouraged"
12
+
13
+ question_1 "What is your favorite color?", :pick => :one
14
+ answer "red"
15
+ answer "blue"
16
+ answer "green"
17
+ answer :other
18
+
19
+ q_2b "Choose the colors you don't like", :pick => :any
20
+ a_1 "orange"
21
+ a_2 "purple"
22
+ a_3 "brown"
23
+ a :omit
24
+ end
25
+ end
26
+ """
27
+ When I start the "Favorites" survey
28
+ Then I should see "You with the sad eyes don't be discouraged"
29
+ And I choose "red"
30
+ And I choose "blue"
31
+ And I check "orange"
32
+ And I check "brown"
33
+ And I press "Click here to finish"
34
+ Then there should be 1 response set with 3 responses with:
35
+ | answer |
36
+ | blue |
37
+ | orange |
38
+ | brown |
39
+ When I go to the last response set show page
40
+ Then I should see "You with the sad eyes don't be discouraged"
41
+ Then the "blue" radiobutton should be checked
42
+ And the "orange" checkbox should be checked
43
+ And the "brown" checkbox should be checked
44
+
45
+ Scenario: Take a survey with group questions, then look at it
46
+ Given I parse
47
+ """
48
+ survey "Grid question test", :default_mandatory => false do
49
+ section 'Communication Skills' do
50
+ grid 'Identify communication and interviewing skills' do
51
+ a 'Yes'
52
+ a 'No'
53
+
54
+ q 'Able to articulate job duties and skills', :pick => :one
55
+ end
56
+
57
+ q 'Communication Skills Comments'
58
+ a :text
59
+ end
60
+ end
61
+ """
62
+ When I start the "Grid question test" survey
63
+ Then I should see "Identify communication and interviewing skills"
64
+ And I choose "Yes"
65
+ And I press "Click here to finish"
66
+ Then there should be 1 response set with 1 responses with:
67
+ | answer |
68
+ | Yes |
69
+ When I go to the last response set show page
70
+ Then I should see "Identify communication and interviewing skills"
71
+ Then the "Yes" radiobutton should be checked
@@ -0,0 +1,145 @@
1
+ Given /^I parse$/ do |string|
2
+ Surveyor::Parser.parse(string)
3
+ end
4
+
5
+ Given /^the survey$/ do |string|
6
+ @survey_string = string
7
+ end
8
+
9
+ Then /^the parser should fail with "(.*)"$/ do |error_message|
10
+ lambda { Surveyor::Parser.parse(@survey_string) }.should raise_error(Surveyor::ParserError, /#{error_message}/)
11
+ end
12
+
13
+ Given /^the questions?$/ do |q_string|
14
+ Surveyor::Parser.parse(<<-SURVEY)
15
+ survey "Some questions for you" do
16
+ section "All the questions" do
17
+ #{q_string}
18
+ end
19
+ end
20
+ SURVEY
21
+ end
22
+
23
+ Given /^I parse redcap file "(.*)"$/ do |name|
24
+ Surveyor::RedcapParser.parse File.read(File.join(Rails.root, '..', 'features', 'support', name)), name
25
+ end
26
+
27
+ Then /^there should be (\d+) survey(?:s?) with:$/ do |x, table|
28
+ Survey.count.should == x.to_i
29
+ table.hashes.each do |hash|
30
+ Survey.find(:first, :conditions => hash).should_not be_nil
31
+ end
32
+ end
33
+
34
+ Then /^there should be (\d+) translations with$/ do |x, table|
35
+ SurveyTranslation.count.should == x.to_i
36
+ table.hashes.each do |hash|
37
+ SurveyTranslation.find(:first, :conditions => hash).should_not be_nil
38
+ end
39
+ end
40
+
41
+ Then /^there should be (\d+) section(?:s?) with:$/ do |x, table|
42
+ SurveySection.count.should == x.to_i
43
+ table.hashes.each do |hash|
44
+ SurveySection.find(:first, :conditions => hash).should_not be_nil
45
+ end
46
+ end
47
+
48
+ Then /^there should be (\d+) question groups with:$/ do |x, table|
49
+ QuestionGroup.count.should == x.to_i
50
+ table.hashes.each do |hash|
51
+ QuestionGroup.find(:first, :conditions => hash).should_not be_nil
52
+ end
53
+ end
54
+
55
+ Then /^there should be (\d+) question(?:s?) with:$/ do |x, table|
56
+ Question.count.should == x.to_i
57
+ table.hashes.each do |hash|
58
+ hash["reference_identifier"] = nil if hash["reference_identifier"] == "nil"
59
+ hash["custom_class"] = nil if hash["custom_class"] == "nil"
60
+ if hash.has_key?("is_mandatory")
61
+ hash["is_mandatory"] = (hash["is_mandatory"] == "true" ? true : (hash["is_mandatory"] == "false" ? false : hash["is_mandatory"]))
62
+ end
63
+ result = Question.find(:first, :conditions => hash)
64
+ puts hash if result.nil?
65
+ result.should_not be_nil
66
+ end
67
+ end
68
+
69
+ Then /^there should be (\d+) question(?:s?) with a correct answer$/ do |x|
70
+ Question.count(:conditions => "correct_answer_id NOT NULL").should == x.to_i
71
+ Question.all(:conditions => "correct_answer_id NOT NULL").compact.map(&:correct_answer).compact.size.should == x.to_i
72
+ end
73
+
74
+ Then /^there should be (\d+) answer(?:s?) with:$/ do |x, table|
75
+ Answer.count.should == x.to_i
76
+ table.hashes.each do |hash|
77
+ hash["reference_identifier"] = nil if hash["reference_identifier"] == "nil"
78
+ Answer.find(:first, :conditions => hash).should_not be_nil
79
+ end
80
+ end
81
+
82
+ Then /^there should be (\d+) dependenc(?:y|ies) with:$/ do |x, table|
83
+ Dependency.count.should == x.to_i
84
+ table.hashes.each do |hash|
85
+ Dependency.find(:first, :conditions => hash).should_not be_nil
86
+ end
87
+ end
88
+
89
+ Then /^there should be (\d+) resolved dependency_condition(?:s?) with:$/ do |x, table|
90
+ DependencyCondition.count.should == x.to_i
91
+
92
+ table.hashes.each do |hash|
93
+ if hash.has_key?("question_reference")
94
+ question = Question.find_by_reference_identifier(hash.delete("question_reference"))
95
+ question.should_not be_nil
96
+
97
+ hash.merge!({ :question_id => question.id })
98
+
99
+ if hash.has_key?("answer_reference")
100
+ answer = Answer.find(:first, :conditions => { :question_id => question.id, :reference_identifier => hash.delete("answer_reference") })
101
+ answer.should_not be_nil
102
+
103
+ hash.merge!({ :answer_id => answer.id })
104
+ end
105
+ end
106
+
107
+ d = DependencyCondition.find(:first, :conditions => hash)
108
+ d.should_not be_nil
109
+ d.question.should_not be_nil
110
+ d.answer.should_not be_nil unless d.operator.match(/^count[<>=!]{1,2}\d+/)
111
+ end
112
+ end
113
+
114
+
115
+ Then /^there should be (\d+) validation(?:s?) with:$/ do |x, table|
116
+ Validation.count.should == x.to_i
117
+ table.hashes.each do |hash|
118
+ Validation.find(:first, :conditions => hash).should_not be_nil
119
+ end
120
+ end
121
+
122
+ Then /^there should be (\d+) validation_condition(?:s?) with:$/ do |x, table|
123
+ ValidationCondition.count.should == x.to_i
124
+ table.hashes.each do |hash|
125
+ hash["integer_value"] = nil if hash["integer_value"] == "nil"
126
+ ValidationCondition.find(:first, :conditions => hash).should_not be_nil
127
+ end
128
+ end
129
+
130
+ Then /^question "([^"]*)" should have correct answer "([^"]*)"$/ do |qr, ar|
131
+ (q = Question.find_by_reference_identifier(qr)).should_not be_nil
132
+ q.correct_answer.should == q.answers.find_by_reference_identifier(ar)
133
+ end
134
+
135
+ Then /^(\d+) dependencies should depend on questions$/ do |x|
136
+ arr = Dependency.find_all_by_question_group_id(nil)
137
+ arr.size.should == 2
138
+ arr.each{|d| d.question.should_not be_nil}
139
+ end
140
+
141
+ Then /^(\d+) dependencies should depend on question groups$/ do |x|
142
+ arr = Dependency.find_all_by_question_id(nil)
143
+ arr.size.should == 2
144
+ arr.each{|d| d.question_group.should_not be_nil}
145
+ end
@@ -0,0 +1,325 @@
1
+ When /^I start the "([^"]*)" survey$/ do |name|
2
+ steps %Q{
3
+ When I go to the surveys page
4
+ Then I should see "#{name}\"
5
+ When I press "Take it"
6
+ }
7
+ @survey_code = current_path.split("/")[2] # /surveys/:survey_code/:response_set_code/take
8
+ @response_set_code = current_path.split("/")[3] # /surveys/:survey_code/:response_set_code/take
9
+ end
10
+
11
+ When /^I start the survey$/ do
12
+ steps %Q{
13
+ When I go to the surveys page
14
+ And I press "Take it"
15
+ }
16
+ @survey_code = current_path.split("/")[2] # /surveys/:survey_code/:response_set_code/take
17
+ @response_set_code = current_path.split("/")[3] # /surveys/:survey_code/:response_set_code/take
18
+ end
19
+
20
+ When /^I start the survey in "(.*?)"$/ do |locale|
21
+ step %Q{I go to the surveys page in "#{locale}"}
22
+ # these steps need to be separated so the url param has a chance to set I18n.locale
23
+ step %Q{I press "#{I18n.t 'surveyor.take_it'}"}
24
+ end
25
+
26
+
27
+ # When I fill in the (nth) (string) for "(ref_id)" with "(value to fill)"
28
+ When /^I fill in the (\d+[a-z]{0,2} )?(\w+) for "([^"]+)" with "([^"]+)"$/ do |index, type, answer_reference_id, value|
29
+ answer = Answer.where(:reference_identifier => answer_reference_id).first
30
+ fail "No answer with ref ID #{answer_reference_id.inspect}" unless answer
31
+
32
+ i = index ? index.to_i - 1 : 0
33
+
34
+ answer_input_id = page.all("input[@value='#{answer.id}']").
35
+ select { |x| x['id'] =~ /answer_id/ }[i]['id']
36
+ ordinal = answer_input_id.scan(/r_(\d+)/).first.first
37
+ value_input_id = "r_#{ordinal}_#{type}_value"
38
+ page.fill_in(value_input_id, :with => value)
39
+ end
40
+
41
+ Then /^there should be (\d+) response set with (\d+) responses? with:$/ do |rs_num, r_num, table|
42
+ ResponseSet.count.should == rs_num.to_i
43
+ Response.count.should == r_num.to_i
44
+ table.hashes.each do |hash|
45
+ if hash.keys == ["answer"]
46
+ a = Answer.find_by_text(hash["answer"])
47
+ a.should_not be_nil
48
+ Response.first(:conditions => {:answer_id => a.id}).should_not be_nil
49
+ else
50
+ if !(a = hash.delete("answer")).blank? and !(answer = Answer.find_by_text(a)).blank?
51
+ Response.first(:conditions => hash.merge({:answer_id => answer.id})).should_not be_nil
52
+ elsif
53
+ Response.first(:conditions => hash).should_not be_nil
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ Then /^there should be (\d+) dependenc(?:y|ies)$/ do |x|
60
+ Dependency.count.should == x.to_i
61
+ end
62
+
63
+ Then /^question "([^"]*)" should have a dependency with rule "([^"]*)"$/ do |qr, rule|
64
+ q = Question.find_by_reference_identifier(qr)
65
+ q.should_not be_blank
66
+ q.dependency.should_not be_nil
67
+ q.dependency.rule.should == rule
68
+ end
69
+
70
+ Then /^the element "([^"]*)" should have the class "([^"]*)"$/ do |selector, css_class|
71
+ page.should have_selector(selector, :class => css_class)
72
+ end
73
+
74
+ Then /^the element "([^"]*)" should exist$/ do |selector|
75
+ page.should have_selector(selector)
76
+ end
77
+
78
+ Then /^the survey should be complete$/ do
79
+ ResponseSet.first.should be_complete
80
+ end
81
+
82
+ Then /^a dropdown should exist with the options "([^"]*)"$/ do |options_text|
83
+ page.should have_selector('select')
84
+ options = options_text.split(',').collect(&:strip)
85
+ within "select" do |select|
86
+ options.each do |o|
87
+ select o
88
+ end
89
+ end
90
+ end
91
+
92
+ Then /^there should be (\d+) checkboxes$/ do |count|
93
+ page.should have_selector('input[type=checkbox]', :count => count.to_i)
94
+ end
95
+
96
+ Then /^there should be (\d+) text areas$/ do |count|
97
+ page.should have_selector('textarea', :count => count.to_i)
98
+ end
99
+
100
+ Then /^the question "([^"]*)" should be triggered$/ do |text|
101
+ q = Question.find_by_text(text)
102
+ page.should_not have_css %(fieldset#q_#{q.id}.q_hidden)
103
+ end
104
+
105
+ Then /^the question "(.*?)" should be hidden$/ do |text|
106
+ q = Question.find_by_text(text)
107
+ page.should have_css %(fieldset#q_#{q.id}.q_hidden)
108
+ end
109
+
110
+ Then /^there should be (\d+) response with answer "([^"]*)"$/ do |count, answer_text|
111
+ Response.count.should == count.to_i
112
+ Response.find_by_answer_id(Answer.find_by_text(answer_text)).should_not be_blank
113
+ end
114
+
115
+ When /^I choose row (\d+), column (\d+) of the grid$/ do |row, col|
116
+ find(".g_grid").find("tr:nth-child(#{row.to_i + 1})").find("td:nth-child(#{col.to_i + 1})").find("input").set(true)
117
+ end
118
+
119
+ Then /^there should (not )?be a (\w+ )?response(?: for answer "([^"]+)")?(?: with value "([^"]+)")?(?: on question "([^"]+)")?$/ do |neg, type, answer_reference_id, value, question_reference_id|
120
+ conditions = []
121
+ values = []
122
+ where = {}
123
+ expected_count = neg.blank? ? 1 : 0
124
+ if type
125
+ attribute = case type.strip
126
+ when 'date'
127
+ 'datetime_value'
128
+ when 'time'
129
+ 'datetime_value'
130
+ else
131
+ "#{type.strip}_value"
132
+ end
133
+ if value
134
+ case type.strip
135
+ when 'date' || 'datetime' || 'time'
136
+ where[:datetime_value] = Time.zone.parse(value).utc
137
+ else
138
+ conditions << "#{attribute} = ?"
139
+ values << value
140
+ end
141
+ else
142
+ conditions << "#{attribute} IS NOT NULL"
143
+ end
144
+ end
145
+
146
+ if question_reference_id
147
+ question = Question.where(:reference_identifier => question_reference_id).first
148
+ fail "No question with ref ID #{question_reference_id}" unless question
149
+ conditions << 'question_id = ?'
150
+ values << question
151
+ end
152
+
153
+ if answer_reference_id
154
+ a_conds = { :reference_identifier => answer_reference_id }
155
+ if question
156
+ a_conds[:question_id] = question
157
+ end
158
+ answer = Answer.where(a_conds).first
159
+ fail "No answer with ref ID #{answer_reference_id}" unless answer
160
+ conditions << 'answer_id = ?'
161
+ values << answer
162
+ end
163
+
164
+ Response.where(conditions.join(' AND '), *values).where(where).count.should == expected_count
165
+ end
166
+
167
+ Then /^I should see the image "([^"]*)"$/ do |src|
168
+ page.should have_selector %(img[src^="#{src}"])
169
+ end
170
+
171
+ Then /^I click elsewhere$/ do
172
+ page.find('.survey_title').click
173
+ end
174
+
175
+ Then /^(\d+) responses should exist$/ do |response_count|
176
+ Response.count.should == response_count.to_i
177
+ end
178
+
179
+ ## JSON
180
+
181
+ def last_json
182
+ page.find('body').text
183
+ end
184
+
185
+ When /^I visit "(.*?)"$/ do |path|
186
+ visit path
187
+ end
188
+
189
+ Then /^I export the response set$/ do
190
+ visit "/surveys/#{@survey_code}/#{@response_set_code}.json"
191
+ end
192
+
193
+ Then /^the JSON response at "(.*?)" should correspond to an answer with text "(.*?)"$/ do |path, text|
194
+ last_json.should be_json_eql(JsonSpec.remember("\"#{Answer.find_by_text(text).api_id}\"")).at_path(path)
195
+ end
196
+
197
+ Then /^the JSON representation for "(.*?)" should be:$/ do |title, string|
198
+ Survey.find_by_title(title).as_json.to_json.should be_json_eql(string)
199
+ end
200
+
201
+ Given /^I prefix the titles of exported surveys with "(.*?)"$/ do |prefix|
202
+ PREFIX = prefix
203
+ class Survey < ActiveRecord::Base
204
+ include Surveyor::Models::SurveyMethods
205
+ def filtered_for_json
206
+ dolly = self.clone
207
+ dolly.sections = self.sections
208
+ dolly.title = "#{PREFIX}#{dolly.title}"
209
+ dolly
210
+ end
211
+ end
212
+ end
213
+
214
+ ## Hidden and shown elements
215
+
216
+ Then /the element "([^\"]*)" should be hidden$/ do |selector|
217
+ wait_until do
218
+ its_hidden = page.evaluate_script("$('#{selector}').is(':hidden');")
219
+ its_not_in_dom = page.evaluate_script("$('#{selector}').length == 0;")
220
+ (its_hidden || its_not_in_dom).should be_true
221
+ end
222
+ end
223
+
224
+ Then /the element "([^\"]*)" should not be hidden$/ do |selector|
225
+ wait_until do
226
+ its_not_hidden = page.evaluate_script("$('#{selector}').is(':not(:hidden)');")
227
+ its_in_dom = page.evaluate_script("$('#{selector}').length > 0;")
228
+ (its_not_hidden && its_in_dom).should be_true
229
+ end
230
+ end
231
+
232
+ ## Context and substitution with mustache
233
+
234
+ Given /^I have survey context of "(.*)"$/ do |context|
235
+ class SurveyorController < ApplicationController
236
+ require 'mustache'
237
+ class FakeMustacheContext < ::Mustache
238
+ def name
239
+ "Santa Claus"
240
+ end
241
+ def site
242
+ "Northwestern"
243
+ end
244
+ end
245
+ def render_context
246
+ FakeMustacheContext
247
+ end
248
+ end
249
+ end
250
+
251
+ Given /^I have a simple hash context$/ do
252
+ class SurveyorController < ApplicationController
253
+ def render_context
254
+ {:name => "Moses", :site => "Northwestern"}
255
+ end
256
+ end
257
+ end
258
+
259
+ Given /^I replace question numbers with letters$/ do
260
+ module SurveyorHelper
261
+ include Surveyor::Helpers::SurveyorHelperMethods
262
+ def next_question_number(question)
263
+ @letters ||= ("A".."Z").to_a
264
+ @n ||= 25
265
+ "<span class='qnum'>#{@letters[(@n += 1)%26]}. </span>"
266
+ end
267
+ end
268
+ end
269
+
270
+ ## Various input elements
271
+
272
+ Then /^I should see (\d+) textarea(?:s?) on the page$/ do |i|
273
+ page.has_css?('textarea', :count => i).should == true
274
+ end
275
+
276
+ Then /^I should see (\d+) text input(?:s?) on the page$/ do |i|
277
+ page.has_css?('input[type="text"]', :count => i).should == true
278
+ end
279
+
280
+ Then /^I should see no text input(?:s?) on the page$/ do
281
+ page.has_css?('input[type="text"]').should == false
282
+ end
283
+
284
+ Then /^I should see (\d+) "(.*?)" input(?:s?) on the page$/ do |i, css_class|
285
+ page.has_css?("input.#{css_class}", :count => i).should == true
286
+ end
287
+
288
+ Then /^I should see (\d+) select on the page$/ do |i|
289
+ page.has_css?("select", :count => i)
290
+ end
291
+
292
+ Then /^the checkbox for "(.*?)" should be (dis|en)abled$/ do |text, dis_or_en|
293
+ a = Answer.find_by_text(text)
294
+ a.should_not be_nil
295
+ element = find("input[value='#{a.id}']")
296
+ if dis_or_en == 'dis'
297
+ element['disabled'].should == 'true'
298
+ else
299
+ [nil, 'false'].should include(element['disabled'])
300
+ end
301
+ end
302
+
303
+ # see support/simultaneous_ajax.rb
304
+ Then /^I wait for things to settle out( longer)?$/ do |longer|
305
+ if @simultaneous_ajax
306
+ Capybara.timeout(longer ? 120 : 10, page.driver, "waiting for all AJAX requests timed out") do
307
+ page.evaluate_script("window.surveyorIntegratedTestsRequestsOutstanding <= 0")
308
+ end
309
+ end
310
+ end
311
+
312
+ ## quizzes
313
+
314
+ Then /^the question "(.*?)" should have correct answer "(.*?)"$/ do |q, a|
315
+ Question.find_by_reference_identifier(q).correct_answer.reference_identifier.should == a
316
+ end
317
+
318
+ ## for Rails 3.0
319
+ Then /^I set the asset directory$/ do
320
+ ActionController::Base.helpers.config.assets_dir = "public" unless asset_pipeline_enabled?
321
+ end
322
+
323
+ When(/^I change the locale to "(.*?)"$/) do |locale|
324
+ steps %Q{When I select "#{locale}" from "new_locale"}
325
+ end
@@ -0,0 +1,25 @@
1
+ When /^I select "([^"]+)" as the datepicker's (\w+)$/ do |selection, type|
2
+ page.find(".ui-datepicker-#{type}").select(selection)
3
+ end
4
+
5
+ When /^I click the first date field$/ do
6
+ first(:css, "input.date[type='text']").click
7
+ end
8
+
9
+ Then /^the first date field should contain "(.*?)"$/ do |value|
10
+ field_value = first(:css, "input.date[type='text']").value
11
+ if field_value.respond_to? :should
12
+ field_value.should =~ /#{value}/
13
+ else
14
+ assert_match(/#{value}/, field_value)
15
+ end
16
+ end
17
+
18
+ Then /^the first date field should not contain "(.*?)"$/ do |value|
19
+ field_value = first(:css, "input.date[type='text']").value
20
+ if field_value.respond_to? :should_not
21
+ field_value.should_not =~ /#{value}/
22
+ else
23
+ assert_no_match(/#{value}/, field_value)
24
+ end
25
+ end