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
@@ -0,0 +1,34 @@
1
+ # JSON Representations
2
+
3
+ This document describes the JSON representations for the ResponseSet and Survey models. The models can be serialized
4
+ by calling the `to_json` method.
5
+
6
+ ## ResponseSet
7
+
8
+ An example of the serialized ResponseSet JSON can be found below. The schema will be coming soon.
9
+
10
+ /* ResponseSet JSON */
11
+ {
12
+ "uuid" : "9af6d142-7fac-4ccb-9bca-58a05308a5a7",
13
+ "survey_id" : "94b3d750-fb63-4540-a1e2-dd7f88be9b4f",
14
+ "created_at" : "1970-02-04T05:15:30Z",
15
+ "completed_at": "1990-03-06T07:21:42Z"
16
+ "responses": [{
17
+ "uuid" : "07d72796-ebb2-4be2-91b9-68f5a30a0054",
18
+ "answer_id" : "9c788711-8373-44d7-b44b-754c31e596a9",
19
+ "question_id" : "376a501b-c32f-49de-b4d7-e28030a2ea94",
20
+ "value" : "Chimpanzee",
21
+ "created_at" : "1970-02-04T05:15:30Z",
22
+ "modified_at" : "1990-03-06T07:21:42Z"
23
+ },{
24
+ "uuid" : "d0467180-e126-44c0-b112-63bb87f0d869",
25
+ "answer_id" : "86a85d44-9f39-4df9-ae90-da7ff5dbaaf5",
26
+ "question_id" : "6146c103-4a8b-4869-836b-415b8666babe",
27
+ "created_at" : "1970-02-04T05:16:30Z",
28
+ "modified_at" : "1990-03-06T07:22:42Z"
29
+ }]
30
+ }
31
+
32
+ ## Survey
33
+
34
+ Example representation and schema coming soon.
@@ -0,0 +1,7 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-03/schema#",
3
+ "description": "Public UUID of a Surveyor entity",
4
+ "maxLength": 36,
5
+ "required": true,
6
+ "type": "string"
7
+ }
@@ -0,0 +1,54 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-03/schema#",
3
+ "description": "Response set",
4
+ "properties": {
5
+ "completed_at": {
6
+ "$ref": "http://download.nubic.northwestern.edu/surveyor/surveyor_timestamp_schema.json#"
7
+ },
8
+ "created_at": {
9
+ "$ref": "http://download.nubic.northwestern.edu/surveyor/surveyor_timestamp_schema.json#"
10
+ },
11
+ "responses": {
12
+ "description": "Responses in the response set",
13
+ "items": {
14
+ "properties": {
15
+ "answer_id": {
16
+ "$ref": "http://download.nubic.northwestern.edu/surveyor/api_id_schema.json#"
17
+ },
18
+ "created_at": {
19
+ "$ref": "http://download.nubic.northwestern.edu/surveyor/surveyor_timestamp_schema.json#"
20
+ },
21
+ "question_id": {
22
+ "$ref": "http://download.nubic.northwestern.edu/surveyor/api_id_schema.json#"
23
+ },
24
+ "response_group": {
25
+ "type": [
26
+ "string",
27
+ "null"
28
+ ]
29
+ },
30
+ "updated_at": {
31
+ "$ref": "http://download.nubic.northwestern.edu/surveyor/surveyor_timestamp_schema.json#"
32
+ },
33
+ "uuid": {
34
+ "$ref": "http://download.nubic.northwestern.edu/surveyor/api_id_schema.json#"
35
+ },
36
+ "value": {
37
+ "type": [
38
+ "string",
39
+ "number",
40
+ "null"
41
+ ]
42
+ }
43
+ }
44
+ },
45
+ "type": "array"
46
+ },
47
+ "survey_id": {
48
+ "$ref": "http://download.nubic.northwestern.edu/surveyor/api_id_schema.json#"
49
+ },
50
+ "uuid": {
51
+ "$ref": "http://download.nubic.northwestern.edu/surveyor/api_id_schema.json#"
52
+ }
53
+ }
54
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-03/schema#",
3
+ "description": "Timestamp on a Surveyor entity",
4
+ "format": "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:Z|[+-]\\d{2}:\\d{2})",
5
+ "type": [
6
+ "string",
7
+ "null"
8
+ ]
9
+ }
@@ -0,0 +1,140 @@
1
+ @javascript
2
+ Feature: AJAX submissions
3
+ As a survey administrator
4
+ I want participants' responses to be saved as soon as possible
5
+
6
+ Scenario: With a simple pick-one question
7
+ Given the question
8
+ """
9
+ q_1 "Was this saved?", :pick => :one
10
+ a_y "Yes"
11
+ a_n "No"
12
+ """
13
+ When I start the survey
14
+ And I choose "Yes"
15
+ Then there should be a response for answer "y"
16
+
17
+ Scenario: With a simple pick-any question
18
+ Given the question
19
+ """
20
+ q_1 "What is the state of the cat?", :pick => :any
21
+ a_d "Dead"
22
+ a_a "Alive"
23
+ a_s "Sleeping"
24
+ """
25
+ When I start the survey
26
+ And I check "Alive"
27
+ And I check "Sleeping"
28
+ Then there should be a response for answer "a"
29
+ And there should be a response for answer "s"
30
+ And there should not be a response for answer "d"
31
+
32
+ Scenario: With a free text question
33
+ Given the question
34
+ """
35
+ q_1 "What is your favorite movie?"
36
+ answer "Title", :string
37
+ """
38
+ When I start the survey
39
+ And I fill in "Title" with "The Shawshank Redemption"
40
+ And I click elsewhere
41
+ Then there should be a string response with value "The Shawshank Redemption"
42
+
43
+ Scenario: With a date question
44
+ Given the question
45
+ """
46
+ q_1 "When do you want to depart?"
47
+ answer "Departure date", :date
48
+ """
49
+ When I start the survey
50
+ And I click "Departure date"
51
+ And I select "Mar" as the datepicker's month
52
+ And I select "2013" as the datepicker's year
53
+ And I follow "9"
54
+ Then there should be a date response with value "2013-03-09"
55
+
56
+ Scenario: With a datetime question
57
+ Given the question
58
+ """
59
+ q_1 "When do you want to depart?"
60
+ answer "Departure date and time", :datetime
61
+ """
62
+ When I start the survey
63
+ And I click "Departure date and time"
64
+ And I select "Apr" as the datepicker's month
65
+ And I select "2013" as the datepicker's year
66
+ And I follow "8"
67
+ Then there should be a date response with value "2013-04-08 00:00:00"
68
+
69
+ # How to move the sliders progammatically?
70
+ @wip
71
+ Scenario: With a time question
72
+ Given the question
73
+ """
74
+ q_1 "When do you want lunch?"
75
+ answer "Meal time", :time
76
+ """
77
+ When I start the survey
78
+ And I click "Meal time"
79
+ And ?
80
+ Then there should be a time response with value "11:45:00"
81
+
82
+ Scenario: With a pick-one plus free text question
83
+ Given the question
84
+ """
85
+ q_1 "Where is Panama City?", :pick => :one
86
+ a_florida "Florida"
87
+ a_panama "Panama"
88
+ a_other :other, :string
89
+ """
90
+ When I start the survey
91
+ And I fill in the string for "other" with "Chicago"
92
+ Then I click elsewhere
93
+ And there should be a string response for answer "other" with value "Chicago"
94
+
95
+ # How to move the slider programmatically?
96
+ @wip
97
+ Scenario: With a slider
98
+ Given the question
99
+ """
100
+ q_1 "How many?", :pick => :one, :display_type => :slider
101
+ a_0 "None"
102
+ a_10 "Some"
103
+ a_100 "Lots"
104
+ """
105
+ When I start the survey
106
+ And ?
107
+ Then there should be a response for answer "100"
108
+
109
+ # Issue #339
110
+ Scenario: With a grid question
111
+ Given the question
112
+ """
113
+ grid "Tell us how often do you cover these each day" do
114
+ a_1 "1"
115
+ a_2 "2"
116
+ a_3 "3"
117
+ q_h "Head", :pick => :one
118
+ q_k "Knees", :pick => :one
119
+ q_t "Toes", :pick => :one
120
+ end
121
+ """
122
+ When I start the survey
123
+ And I choose "3"
124
+ Then there should be a response for answer "3"
125
+
126
+ Scenario: With a repeater
127
+ Given the question
128
+ """
129
+ repeater "List your former addresses" do
130
+ q "Address"
131
+ a_address_line "Line", :string
132
+ end
133
+ """
134
+ When I start the survey
135
+ And I fill in the 1st string for "address_line" with "10 Downing St."
136
+ And I press "+ add row"
137
+ And I fill in the 2nd string for "address_line" with "1600 Penn Ave."
138
+ And I click elsewhere
139
+ Then there should be a string response for answer "address_line" with value "10 Downing St."
140
+ And there should be a string response for answer "address_line" with value "1600 Penn Ave."
@@ -17,14 +17,15 @@ Feature: Survey export
17
17
  answer :other
18
18
 
19
19
  q_2b "Choose the colors you don't like", :pick => :any
20
- a_1 "orange"
21
- a_2 "purple"
22
- a_3 "brown"
20
+ a "orange"
21
+ a "purple"
22
+ a "brown"
23
23
  a :omit
24
24
  end
25
25
  end
26
26
  """
27
- Then the json for "Simple json" should be
27
+ And I visit "/surveys/simple-json.json"
28
+ Then the JSON should be:
28
29
  """
29
30
  {
30
31
  "title": "Simple json",
@@ -39,12 +40,117 @@ Feature: Survey export
39
40
  }]
40
41
  }
41
42
  """
42
-
43
+
44
+ Scenario: Exporting export and reference identifiers
45
+ Given I parse
46
+ """
47
+ survey "Exportable" do
48
+ section "First section" do
49
+ question_1 "What is your favorite color?", :pick => :one, :data_export_identifier => "favorite_color"
50
+ a_red "red"
51
+ a_blue "blue"
52
+
53
+ q_2b "Choose the colors you don't like", :pick => :any
54
+ a_1 "orange", :data_export_identifier => "dont_like_orange"
55
+ a_2 "purple"
56
+ end
57
+ end
58
+ """
59
+ And I visit "/surveys/exportable.json"
60
+ Then the JSON should be:
61
+ """
62
+ {
63
+ "title": "Exportable",
64
+ "uuid": "*",
65
+ "sections": [{
66
+ "title": "First section",
67
+ "display_order":0,
68
+ "questions_and_groups": [
69
+ { "uuid": "*", "reference_identifier": "1", "pick": "one", "text": "What is your favorite color?", "data_export_identifier": "favorite_color", "answers": [{"text": "red", "uuid": "*", "reference_identifier": "red"}, {"text": "blue", "uuid": "*", "reference_identifier": "blue"}]},
70
+ { "uuid": "*", "reference_identifier": "2b", "pick": "any", "text": "Choose the colors you don't like", "answers": [{"text": "orange", "uuid": "*", "reference_identifier": "1", "data_export_identifier": "dont_like_orange"},{"text": "purple", "uuid": "*", "reference_identifier": "2"}]}]
71
+ }]
72
+ }
73
+ """
74
+
75
+ Scenario: Exporting versioned survey questions
76
+ Given I parse
77
+ """
78
+ survey "Simple json" do
79
+ section "Basic questions" do
80
+ label "These questions are examples of the basic supported input types"
81
+
82
+ question_1 "What is your favorite color?", :pick => :one
83
+ answer "red"
84
+ answer "blue"
85
+ answer "green"
86
+ answer :other
87
+
88
+ q_2b "Choose the colors you don't like", :pick => :any
89
+ a "orange"
90
+ a "purple"
91
+ a "brown"
92
+ a :omit
93
+ end
94
+ end
95
+ """
96
+ And I parse
97
+ """
98
+ survey "Simple json" do
99
+ section "Not so basic questions" do
100
+ label "These questions are examples of the basic supported input types"
101
+
102
+ question_1 "What is your favorite color?", :pick => :one
103
+ answer "reddish"
104
+ answer "blueish"
105
+ answer "greenish"
106
+ answer :other
107
+
108
+ q_2b "Choose the colors you don't like", :pick => :any
109
+ a "orange"
110
+ a "purple"
111
+ a "brown"
112
+ a :omit
113
+ end
114
+ end
115
+ """
116
+ And I visit "/surveys/simple-json.json"
117
+ Then the JSON should be:
118
+ """
119
+ {
120
+ "title": "Simple json",
121
+ "uuid": "*",
122
+ "sections": [{
123
+ "title": "Not so basic questions",
124
+ "display_order":0,
125
+ "questions_and_groups": [
126
+ { "uuid": "*", "type": "label", "text": "These questions are examples of the basic supported input types" },
127
+ { "uuid": "*", "reference_identifier": "1", "pick": "one", "text": "What is your favorite color?", "answers": [{"text": "reddish", "uuid": "*"}, {"text": "blueish", "uuid": "*"}, {"text": "greenish", "uuid": "*"}, {"text": "Other", "uuid": "*"}]},
128
+ { "uuid": "*", "reference_identifier": "2b", "pick": "any", "text": "Choose the colors you don't like", "answers": [{"text": "orange", "uuid": "*"},{"text": "purple", "uuid": "*"},{"text": "brown", "uuid": "*"},{"text": "Omit", "exclusive":true, "uuid": "*"}]}]
129
+ }]
130
+ }
131
+ """
132
+ And I visit "/surveys/simple-json.json?survey_version=0"
133
+ Then the JSON should be:
134
+ """
135
+ {
136
+ "title": "Simple json",
137
+ "uuid": "*",
138
+ "sections": [{
139
+ "title": "Basic questions",
140
+ "display_order":0,
141
+ "questions_and_groups": [
142
+ { "uuid": "*", "type": "label", "text": "These questions are examples of the basic supported input types" },
143
+ { "uuid": "*", "reference_identifier": "1", "pick": "one", "text": "What is your favorite color?", "answers": [{"text": "red", "uuid": "*"}, {"text": "blue", "uuid": "*"}, {"text": "green", "uuid": "*"}, {"text": "Other", "uuid": "*"}]},
144
+ { "uuid": "*", "reference_identifier": "2b", "pick": "any", "text": "Choose the colors you don't like", "answers": [{"text": "orange", "uuid": "*"},{"text": "purple", "uuid": "*"},{"text": "brown", "uuid": "*"},{"text": "Omit", "exclusive":true, "uuid": "*"}]}]
145
+ }]
146
+ }
147
+ """
148
+
43
149
  Scenario: Exporting response sets
44
150
  Given I parse
45
151
  """
46
152
  survey "Simple json response sets" do
47
- section "Colors" do
153
+ section "Section 1" do
48
154
 
49
155
  question_1 "What is your favorite color?", :pick => :one
50
156
  answer "red"
@@ -55,42 +161,84 @@ Feature: Survey export
55
161
  q_2b "What color don't you like?"
56
162
  a_1 "color", :string
57
163
  end
58
- section "Other" do
164
+ section "Section 2" do
59
165
  label "no"
60
166
  end
61
167
  end
62
168
  """
63
169
  When I start the "Simple json response sets" survey
64
170
  And I choose "red"
65
- And I press "Other"
66
- And I wait 1 seconds
67
- And I press "Colors"
171
+ And I press "Section 2"
172
+ And I press "Section 1"
68
173
  And I fill in "color" with "orange"
69
- And I press "Other"
174
+ And I press "Section 2"
70
175
  And I press "Click here to finish"
71
176
  Then there should be 1 response set with 2 responses with:
72
177
  | answer |
73
178
  | red |
74
- And the json for the last response set for "Simple json response sets" should be
75
- """
76
- {
77
- "uuid":"*",
78
- "survey_id":"*",
79
- "created_at":"*",
80
- "completed_at":"*",
81
- "responses":[{
82
- "uuid":"*",
83
- "answer_id":"*",
84
- "question_id":"*",
85
- "created_at":"*",
86
- "modified_at":"*"
87
- },{
88
- "uuid":"*",
89
- "answer_id":"*",
90
- "question_id":"*",
91
- "created_at":"*",
92
- "modified_at":"*",
93
- "value":"orange"
94
- }]
95
- }
96
- """
179
+ And I export the response set
180
+ Then the JSON at "responses" should have 2 entries
181
+ Then the JSON should not have "responses/0/value"
182
+ And the JSON response at "responses/0/answer_id" should correspond to an answer with text "red"
183
+ And the JSON response at "responses/1/value" should be "orange"
184
+ And the JSON response at "responses/1/answer_id" should correspond to an answer with text "color"
185
+
186
+ # Issue #294 - ResponseSet#to_json generates unexpected results with zero Responses
187
+ Scenario: Exporting response sets without responses
188
+ Given I parse
189
+ """
190
+ survey "Simple json response sets" do
191
+ section "Colors" do
192
+
193
+ question_1 "What is your favorite color?", :pick => :one
194
+ answer "red"
195
+ answer "blue"
196
+ answer "green"
197
+ answer :other
198
+
199
+ q_2b "What color don't you like?"
200
+ a_1 "color", :string
201
+ end
202
+ section "Other" do
203
+ label "no"
204
+ end
205
+ end
206
+ """
207
+ When I start the "Simple json response sets" survey
208
+ And I export the response set
209
+ Then the JSON at "responses" should be an array
210
+ Then the JSON at "responses" should have 0 entries
211
+
212
+ Scenario: Exporting response sets for versioned surveys
213
+ Given I parse
214
+ """
215
+ survey "Simple json response sets" do
216
+ section "Colors" do
217
+ question "What is your least favorite color?"
218
+ a "least favorite color", :string
219
+ end
220
+ end
221
+ """
222
+ And I start the "Simple json response sets" survey
223
+ And I fill in "color" with "orange"
224
+ And I press "Click here to finish"
225
+ And I export the response set
226
+ Then the JSON at "responses" should have 1 entry
227
+ And the JSON response at "responses/0/value" should be "orange"
228
+ And the JSON response at "responses/0/answer_id" should correspond to an answer with text "least favorite color"
229
+ And I parse
230
+ """
231
+ survey "Simple json response sets" do
232
+ section "Colors" do
233
+ question_1 "What is your most favorite color?"
234
+ a "most favorite color", :string
235
+ end
236
+ end
237
+ """
238
+ And I start the "Simple json response sets" survey
239
+ And I fill in "color" with "blueish"
240
+ And I press "Click here to finish"
241
+ And I export the response set
242
+ Then the JSON at "responses" should have 1 entry
243
+ And the JSON response at "responses/0/value" should be "blueish"
244
+ And the JSON response at "responses/0/answer_id" should correspond to an answer with text "most favorite color"
@@ -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."
@@ -4,7 +4,7 @@ Feature: showing a survey
4
4
  So that I can understand the data
5
5
 
6
6
  Scenario: Take a survey, then look at it
7
- Given the survey
7
+ Given I parse
8
8
  """
9
9
  survey "Favorites" do
10
10
  section "Colors" do
@@ -1,7 +1,25 @@
1
- Given /^I parse$|^the survey$/ do |string|
1
+ Given /^I parse$/ do |string|
2
2
  Surveyor::Parser.parse(string)
3
3
  end
4
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
+
5
23
  Given /^I parse redcap file "([^"]*)"$/ do |name|
6
24
  Surveyor::RedcapParser.parse File.read(File.join(Rails.root, '..', 'features', 'support', name)), name
7
25
  end
@@ -36,6 +54,11 @@ Then /^there should be (\d+) question(?:s?) with:$/ do |x, table|
36
54
  end
37
55
  end
38
56
 
57
+ Then /^there should be (\d+) question(?:s?) with a correct answer$/ do |x|
58
+ Question.count(:conditions => "correct_answer_id NOT NULL").should == x.to_i
59
+ Question.all(:conditions => "correct_answer_id NOT NULL").compact.map(&:correct_answer).compact.size.should == x.to_i
60
+ end
61
+
39
62
  Then /^there should be (\d+) answer(?:s?) with:$/ do |x, table|
40
63
  Answer.count.should == x.to_i
41
64
  table.hashes.each do |hash|
@@ -57,7 +80,7 @@ Then /^there should be (\d+) resolved dependency_condition(?:s?) with:$/ do |x,
57
80
  d = DependencyCondition.find(:first, :conditions => hash)
58
81
  d.should_not be_nil
59
82
  d.question.should_not be_nil
60
- d.answer.should_not be_nil unless d.operator.match(/^count[<>=!]{1,2}\d+/)
83
+ d.answer.should_not be_nil unless d.operator.match(/^count[<>=!]{1,2}\d+/)
61
84
  end
62
85
  end
63
86