surveyor 0.22.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/CHANGELOG.md +83 -0
- data/Gemfile.rails_version +7 -1
- data/README.md +114 -16
- data/Rakefile +15 -9
- data/app/inputs/quiet_input.rb +5 -0
- data/app/inputs/surveyor_check_boxes_input.rb +35 -0
- data/app/inputs/surveyor_radio_input.rb +18 -0
- data/app/views/partials/_answer.html.haml +4 -4
- data/app/views/partials/_question.html.haml +7 -7
- data/app/views/partials/_question_group.html.haml +9 -8
- data/app/views/surveyor/export.json.rabl +28 -25
- data/app/views/surveyor/new.html.haml +8 -5
- data/app/views/surveyor/show.json.rabl +3 -2
- data/ci-exec.sh +13 -7
- data/cucumber.yml +3 -3
- data/doc/REPRESENTATIONS.md +34 -0
- data/doc/api_id_schema.json +7 -0
- data/doc/response_set_schema.json +54 -0
- data/doc/surveyor question combinations.png +0 -0
- data/doc/surveyor_timestamp_schema.json +9 -0
- data/features/ajax_submissions.feature +140 -0
- data/features/export_to_json.feature +182 -34
- data/features/no_duplicates.feature +110 -0
- data/features/show_survey.feature +1 -1
- data/features/step_definitions/parser_steps.rb +25 -2
- data/features/step_definitions/surveyor_steps.rb +145 -20
- data/features/step_definitions/ui_steps.rb +3 -0
- data/features/support/database_cleaner.rb +16 -0
- data/features/support/env.rb +21 -17
- data/features/support/simultaneous_ajax.rb +101 -0
- data/features/support/single_quit_selenium_driver.rb +23 -0
- data/features/support/slow_updates.rb +18 -0
- data/features/surveyor.feature +174 -44
- data/features/surveyor_dependencies.feature +80 -39
- data/features/surveyor_parser.feature +114 -20
- data/features/z_redcap_parser.feature +0 -1
- data/lib/{generators/surveyor/templates/public → assets}/images/surveyor/next.gif +0 -0
- data/lib/{generators/surveyor/templates/public → assets}/images/surveyor/prev.gif +0 -0
- data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/lib/assets/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-icons_ef8c08_256x240.png +0 -0
- data/lib/{generators/surveyor/templates/public/stylesheets/surveyor → assets/images}/ui-icons_ffffff_256x240.png +0 -0
- data/lib/{generators/surveyor/templates/public → assets}/javascripts/surveyor/jquery-ui-timepicker-addon.js +23 -23
- data/lib/{generators/surveyor/templates/public → assets}/javascripts/surveyor/jquery-ui.js +125 -125
- data/lib/assets/javascripts/surveyor/jquery.selectToUISlider.js +240 -0
- data/lib/{generators/surveyor/templates/public → assets}/javascripts/surveyor/jquery.surveyor.js +52 -57
- data/lib/{generators/surveyor/templates/public → assets}/javascripts/surveyor/jquery.tools.min.js +7 -7
- data/lib/{generators/surveyor/templates/public → assets}/stylesheets/surveyor/dateinput.css +13 -13
- data/lib/{generators/surveyor/templates/public → assets}/stylesheets/surveyor/jquery-ui-timepicker-addon.css +0 -0
- data/lib/{generators/surveyor/templates/public → assets}/stylesheets/surveyor/jquery-ui.custom.css +17 -17
- data/lib/{generators/surveyor/templates/public → assets}/stylesheets/surveyor/reset.css +1 -1
- data/lib/{generators/surveyor/templates/public → assets}/stylesheets/surveyor/results.css +0 -0
- data/lib/assets/stylesheets/surveyor/ui.slider.extras.css +110 -0
- data/lib/{generators/surveyor/templates/public/stylesheets/sass → assets/stylesheets}/surveyor.sass +15 -7
- data/lib/generators/surveyor/custom_generator.rb +3 -2
- data/lib/generators/surveyor/install_generator.rb +59 -17
- data/lib/generators/surveyor/templates/app/assets/javascripts/surveyor_all.js +5 -0
- data/lib/generators/surveyor/templates/app/assets/stylesheets/surveyor_all.css +9 -0
- data/lib/generators/surveyor/templates/app/controllers/surveyor_controller.rb +2 -1
- data/lib/generators/surveyor/templates/app/views/layouts/surveyor_custom.html.erb +1 -0
- data/lib/generators/surveyor/templates/config/locales/surveyor_es.yml +1 -0
- data/lib/generators/surveyor/templates/config/locales/surveyor_he.yml +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_api_id_to_question_groups.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_api_ids.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_api_ids_to_response_sets_and_responses.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_correct_answer_id_to_questions.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_default_value_to_answers.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_display_order_to_surveys.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_display_type_to_answers.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_index_to_response_sets.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_index_to_surveys.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_section_id_to_responses.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/add_unique_index_on_access_code_and_version_in_surveys.rb +10 -0
- data/lib/generators/surveyor/templates/db/migrate/add_unique_indicies.rb +3 -2
- data/lib/generators/surveyor/templates/db/migrate/add_version_to_surveys.rb +10 -0
- data/lib/generators/surveyor/templates/db/migrate/api_ids_must_be_unique.rb +23 -0
- data/lib/generators/surveyor/templates/db/migrate/create_answers.rb +6 -5
- data/lib/generators/surveyor/templates/db/migrate/create_dependencies.rb +2 -1
- data/lib/generators/surveyor/templates/db/migrate/create_dependency_conditions.rb +2 -1
- data/lib/generators/surveyor/templates/db/migrate/create_question_groups.rb +5 -4
- data/lib/generators/surveyor/templates/db/migrate/create_questions.rb +4 -3
- data/lib/generators/surveyor/templates/db/migrate/create_response_sets.rb +1 -0
- data/lib/generators/surveyor/templates/db/migrate/create_responses.rb +10 -9
- data/lib/generators/surveyor/templates/db/migrate/create_survey_sections.rb +5 -4
- data/lib/generators/surveyor/templates/db/migrate/create_surveys.rb +4 -3
- data/lib/generators/surveyor/templates/db/migrate/create_validation_conditions.rb +5 -4
- data/lib/generators/surveyor/templates/db/migrate/create_validations.rb +3 -2
- data/lib/generators/surveyor/templates/db/migrate/drop_unique_index_on_access_code_in_surveys.rb +10 -0
- data/lib/generators/surveyor/templates/db/migrate/update_blank_api_ids_on_question_group.rb +22 -0
- data/lib/generators/surveyor/templates/db/migrate/update_blank_versions_on_surveys.rb +13 -0
- data/lib/generators/surveyor/templates/surveys/date_survey.rb +1 -0
- data/lib/generators/surveyor/templates/surveys/kitchen_sink_survey.rb +54 -24
- data/lib/generators/surveyor/templates/surveys/quiz.rb +1 -0
- data/lib/generators/surveyor/templates/{public/stylesheets/sass → vendor/assets/stylesheets}/custom.sass +1 -1
- data/lib/surveyor/common.rb +16 -31
- data/lib/surveyor/engine.rb +2 -4
- data/lib/surveyor/helpers/asset_pipeline.rb +13 -0
- data/lib/surveyor/helpers/formtastic_custom_input.rb +17 -0
- data/lib/surveyor/helpers/surveyor_helper_methods.rb +10 -8
- data/lib/surveyor/models/answer_methods.rb +3 -0
- data/lib/surveyor/models/dependency_condition_methods.rb +27 -28
- data/lib/surveyor/models/dependency_methods.rb +3 -0
- data/lib/surveyor/models/question_group_methods.rb +3 -0
- data/lib/surveyor/models/question_methods.rb +10 -7
- data/lib/surveyor/models/response_methods.rb +16 -0
- data/lib/surveyor/models/response_set_methods.rb +71 -64
- data/lib/surveyor/models/survey_methods.rb +19 -28
- data/lib/surveyor/models/survey_section_methods.rb +3 -0
- data/lib/surveyor/models/validation_condition_methods.rb +4 -2
- data/lib/surveyor/models/validation_methods.rb +3 -0
- data/lib/surveyor/parser.rb +198 -148
- data/lib/surveyor/redcap_parser.rb +120 -80
- data/lib/surveyor/surveyor_controller_methods.rb +86 -37
- data/lib/surveyor/version.rb +2 -2
- data/lib/surveyor.rb +5 -6
- data/lib/tasks/surveyor_tasks.rake +19 -7
- data/spec/controllers/surveyor_controller_spec.rb +166 -92
- data/spec/factories.rb +33 -32
- data/spec/helpers/formtastic_custom_input_spec.rb +16 -0
- data/spec/lib/common_spec.rb +0 -39
- data/spec/lib/redcap_parser_spec.rb +24 -24
- data/spec/models/answer_spec.rb +12 -0
- data/spec/models/dependency_condition_spec.rb +279 -323
- data/spec/models/dependency_spec.rb +10 -0
- data/spec/models/question_group_spec.rb +12 -0
- data/spec/models/question_spec.rb +12 -0
- data/spec/models/response_set_spec.rb +189 -139
- data/spec/models/response_spec.rb +60 -0
- data/spec/models/survey_section_spec.rb +9 -0
- data/spec/models/survey_spec.rb +72 -9
- data/spec/models/validation_condition_spec.rb +9 -1
- data/spec/models/validation_spec.rb +10 -0
- data/spec/spec_helper.rb +25 -6
- data/surveyor.gemspec +5 -4
- metadata +332 -291
- data/features/step_definitions/common_steps.rb +0 -3
- data/lib/formtastic/surveyor_builder.rb +0 -82
- data/lib/generators/surveyor/templates/public/javascripts/surveyor/jquery.blockUI.js +0 -499
data/.gitignore
CHANGED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color -fn
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
History for Surveyor
|
2
|
+
====================
|
3
|
+
|
4
|
+
1.0.0
|
5
|
+
------
|
6
|
+
|
7
|
+
### Features
|
8
|
+
|
9
|
+
- Official support for Rails 3.2, including declaring of all mass-assignable
|
10
|
+
attributes with `attr_accessible`.
|
11
|
+
|
12
|
+
- Breaking change: Surveys are now explicitly versioned. If you loaded a survey
|
13
|
+
when another survey with the same title/access code had already been loaded,
|
14
|
+
Surveyor would previously have appended a serial number to the title. As of
|
15
|
+
this version, Surveyor keeps the serial number in a separate `survey_version`
|
16
|
+
field. (#262)
|
17
|
+
|
18
|
+
- Add encoding comments for generated files. (#329)
|
19
|
+
|
20
|
+
- Asset pipeline support for Rails 3.1+. Rails 3.0 is still supported.
|
21
|
+
(#307, #314, #315)
|
22
|
+
|
23
|
+
- Upgrade to Formtastic 2.1. (#227)
|
24
|
+
|
25
|
+
- `:pick => :one` and `:pick => :any` questions may now have date, time,
|
26
|
+
datetime, integer, or float values, in addition to the already-supported
|
27
|
+
string values. (#207)
|
28
|
+
|
29
|
+
- Added Survey#as_json, ResponseSet#as_json. (#291)
|
30
|
+
|
31
|
+
- Changed defaults for and interpretation of for Survey#active_at and
|
32
|
+
Survey#inactive_at. (#258)
|
33
|
+
|
34
|
+
- JSON export representation of DateTimes is 2010-04-08T10:30+00:00 and Dates is
|
35
|
+
2010-04-08 and Times is 10:30. (#355)
|
36
|
+
|
37
|
+
- JSON representation of Response includes response_group. (#349)
|
38
|
+
|
39
|
+
- Use Object#extend to inject SuryeyorParser and SurveyorRedcapParser methods into
|
40
|
+
instances of models instead of reopening classes. Move responsibility for keeping
|
41
|
+
track of and reporting duplicate and bad references from the models to the parsers.
|
42
|
+
Upgrade SurveyorRedcapParser to trace only when rake --trace is specified. (#341)
|
43
|
+
|
44
|
+
- export Question#data_export_identifier, Answer#data_export_identifier,
|
45
|
+
Answer#reference_identifier in survey JSON export. (#368)
|
46
|
+
|
47
|
+
### Fixes
|
48
|
+
|
49
|
+
- Ensure response set is available to `render_context` (#320)
|
50
|
+
|
51
|
+
- Hide dependent rows of grids. (#343)
|
52
|
+
|
53
|
+
- Dependency condition with '!=' now returns true if there is no response. (#337)
|
54
|
+
|
55
|
+
- Properly handle multiple "exclusive" checkboxes in a single question. (#336)
|
56
|
+
|
57
|
+
- Correct storing of "correct" answers when parsing a survey. (#326)
|
58
|
+
|
59
|
+
- Restore "slider" renderer. (#230)
|
60
|
+
|
61
|
+
- Ensure that duplicate responses cannot be created by parallel AJAX requests.
|
62
|
+
(#328)
|
63
|
+
|
64
|
+
- Create default identifiers in before_create, not in the initializer. (#369)
|
65
|
+
|
66
|
+
- Eliminate unnecessary (and incorrect) access code uniqueness checks.
|
67
|
+
Use SecureRandom for generating access codes. (#370)
|
68
|
+
|
69
|
+
- Use json_spec for testing JSON responses, instead of
|
70
|
+
Surveyor::Common#deep_compare_excluding_wildcards. (#350)
|
71
|
+
|
72
|
+
- Parser now sets Question#correct_answer_id correctly. The association is changed from
|
73
|
+
Question :has_one correct_answer => Question :belongs_to correct_answer. (#365)
|
74
|
+
|
75
|
+
### Infrastructure
|
76
|
+
|
77
|
+
- Enabled Selenium-backed cucumber features in CI. (#333)
|
78
|
+
|
79
|
+
- Added `testbed:surveys` task to load all sample surveys in the testbed.
|
80
|
+
|
81
|
+
- Begin formal changelog.
|
82
|
+
|
83
|
+
- Change test infra so that tx behavior can be tested. (#360)
|
data/Gemfile.rails_version
CHANGED
@@ -4,9 +4,15 @@
|
|
4
4
|
if ENV['RAILS_VERSION']
|
5
5
|
case ENV['RAILS_VERSION']
|
6
6
|
when /3.0$/
|
7
|
-
gem 'rails', '~> 3.0.
|
7
|
+
gem 'rails', '~> 3.0.15'
|
8
8
|
when /3.1$/
|
9
9
|
gem 'rails', '~> 3.1.0'
|
10
|
+
# A JS runtime is required for Rails 3.1+
|
11
|
+
gem 'therubyracer'
|
12
|
+
when /3.2$/
|
13
|
+
gem 'rails', '~> 3.2.0'
|
14
|
+
# A JS runtime is required for Rails 3.1+
|
15
|
+
gem 'therubyracer'
|
10
16
|
else
|
11
17
|
fail "Unknown Rails version #{ENV['RAILS_VERSION']}"
|
12
18
|
end
|
data/README.md
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# Surveys On Rails
|
2
2
|
|
3
|
-
Surveyor is a
|
3
|
+
Surveyor is a developer tool that brings surveys into Rails
|
4
|
+
applications. Surveys are written in the Surveyor DSL (Domain Specific
|
5
|
+
Language). Internally, Surveyor is a Rails engine distributed as a
|
6
|
+
ruby gem, meaning it is straightforward to override or extend its
|
7
|
+
behaviors in your Rails app without maintaining a fork.
|
4
8
|
|
5
9
|
## Why you might want to use Surveyor
|
6
10
|
|
@@ -55,7 +59,7 @@ The first question is "pick one" (radio buttons) with "other". The second questi
|
|
55
59
|
|
56
60
|
# Installation
|
57
61
|
|
58
|
-
|
62
|
+
Add surveyor to your Gemfile:
|
59
63
|
|
60
64
|
gem "surveyor"
|
61
65
|
|
@@ -63,16 +67,16 @@ Then run:
|
|
63
67
|
|
64
68
|
bundle install
|
65
69
|
|
66
|
-
|
70
|
+
Generate assets, run migrations:
|
67
71
|
|
68
72
|
script/rails generate surveyor:install
|
69
|
-
rake db:migrate
|
73
|
+
bundle exec rake db:migrate
|
70
74
|
|
71
|
-
|
75
|
+
Try out the "kitchen sink" survey. The rake task above generates surveys from our custom survey DSL (a good format for end users and stakeholders).
|
72
76
|
|
73
|
-
rake surveyor FILE=surveys/kitchen_sink_survey.rb
|
77
|
+
bundle exec rake surveyor FILE=surveys/kitchen_sink_survey.rb
|
74
78
|
|
75
|
-
|
79
|
+
Start up your app and visit http://localhost:3000/surveys
|
76
80
|
|
77
81
|
Try taking the survey and compare it to the contents of the DSL file kitchen\_sink\_survey.rb. See how the DSL maps to what you see.
|
78
82
|
|
@@ -82,14 +86,71 @@ There are two other useful rake tasks:
|
|
82
86
|
* `rake surveyor:unparse` exports a survey from the application into a
|
83
87
|
file in the surveyor DSL.
|
84
88
|
|
89
|
+
# Upgrading
|
90
|
+
|
91
|
+
When you are ready to update to the latest version of Surveyor, just do
|
92
|
+
|
93
|
+
bundle update surveyor
|
94
|
+
|
95
|
+
and you'll get the latest version that bundler thinks you can use based on the
|
96
|
+
constraints in your Gemfile.
|
97
|
+
|
98
|
+
After you've installed a new version, you should always re-run the surveyor
|
99
|
+
generator:
|
100
|
+
|
101
|
+
script/rails generate surveyor:install
|
102
|
+
|
103
|
+
This will copy over any new or updated assets and new migrations. Use your VCS'
|
104
|
+
utilities to review what's changed, then commit the new versions.
|
105
|
+
|
106
|
+
git status
|
107
|
+
git diff
|
108
|
+
[...]
|
109
|
+
git add -A
|
110
|
+
git commit
|
111
|
+
|
112
|
+
If there were new migrations, you'll want to be sure to run them before the next
|
113
|
+
time you start your app:
|
114
|
+
|
115
|
+
bundle exec rake db:migrate
|
116
|
+
|
117
|
+
Finally, review the [changelog][] entries corresponding to the versions between
|
118
|
+
your original version and the version you've updated to. There may be changes
|
119
|
+
which will affect your customizations. There should be hints in the changelog
|
120
|
+
or the referenced issues for what to update when necessary.
|
121
|
+
|
122
|
+
[changelog]: https://github.com/NUBIC/surveyor/blob/master/CHANGELOG.md
|
123
|
+
|
124
|
+
## Following master
|
125
|
+
|
126
|
+
If you are following along with pre-release versions of Surveyor using a `:git`
|
127
|
+
source in your Gemfile, be particularly careful about reviewing migrations after
|
128
|
+
updating Surveyor and re-running the generator. We will never change a migration
|
129
|
+
between two released versions of Surveyor. However, we may on rare occasions
|
130
|
+
change a migration which has been merged into master. When this happens, you'll
|
131
|
+
need to assess the differences and decide on an appropriate course of action for
|
132
|
+
your app.
|
133
|
+
|
134
|
+
If you aren't sure what this means, we do not recommend that you deploy an app
|
135
|
+
that's locked to surveyor master into production.
|
136
|
+
|
85
137
|
# Customizing surveyor
|
86
138
|
|
87
139
|
Surveyor's controller, models, and views may be customized via classes in your app/models, app/helpers and app/controllers directories. To generate a sample custom controller and layout, run:
|
88
140
|
|
89
|
-
|
141
|
+
script/rails generate surveyor:custom
|
90
142
|
|
91
143
|
and read surveys/EXTENDING\_SURVEYOR
|
92
144
|
|
145
|
+
# The asset pipeline
|
146
|
+
|
147
|
+
Surveyor is now aware of the Rails asset pipeline (http://guides.rubyonrails.org/asset_pipeline.html). With the asset pipeline enabled `Rails.application.config.assets.enabled == true`, then the `surveyor:install` generator will generate `app/assets/stylesheets/surveyor_all.css` and `app/assets/javascripts/surveyor_all.js` manifest files and link them from the surveyor\_default layout. Assets remain in the gem and are picked up for inclusion and pre-compilation from there if `config/environments/production.rb` is set to include surveyor assets.
|
148
|
+
|
149
|
+
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
|
150
|
+
config.assets.precompile += %w( surveyor_all.js surveyor_all.css )
|
151
|
+
|
152
|
+
The previous copy-to-application behavior still exists in the case where the asset pipeline is missing or disabled.
|
153
|
+
|
93
154
|
# PDF support
|
94
155
|
|
95
156
|
* Add the following lines to your Gemfile:
|
@@ -120,17 +181,33 @@ or on OSX:
|
|
120
181
|
|
121
182
|
# Requirements
|
122
183
|
|
123
|
-
Surveyor
|
184
|
+
Surveyor works with:
|
185
|
+
|
186
|
+
* Ruby 1.8.7, 1.9.2, and 1.9.3
|
187
|
+
* Rails 3.0-3.2
|
188
|
+
|
189
|
+
Some key library dependencies are:
|
124
190
|
|
125
|
-
* Ruby (1.8.7 - 1.9.2)
|
126
|
-
* Rails 3.0-3.1
|
127
191
|
* HAML
|
128
|
-
*
|
129
|
-
*
|
130
|
-
|
131
|
-
|
192
|
+
* Sass
|
193
|
+
* Formtastic
|
194
|
+
|
195
|
+
A more exhaustive list can be found in the gemspec.
|
196
|
+
|
197
|
+
# Support
|
198
|
+
|
199
|
+
For general discussion (e.g., "how do I do this?"), please send a message to the
|
200
|
+
[surveyor-dev][] group. This group is moderated to keep out spam; don't be
|
201
|
+
surprised if your message isn't posted immediately.
|
132
202
|
|
133
|
-
|
203
|
+
For reproducible bugs, please file an issue on the [GitHub issue
|
204
|
+
tracker][issues]. Please include a minimal test case (a detailed description of
|
205
|
+
how to trigger the bug in a clean rails application). If you aren't sure how to
|
206
|
+
isolate the bug, send a message to [surveyor-dev][] with what you know and we'll
|
207
|
+
try to help.
|
208
|
+
|
209
|
+
[surveyor-dev]: https://groups.google.com/group/surveyor-dev
|
210
|
+
[issues]: https://github.com/NUBIC/surveyor/issues
|
134
211
|
|
135
212
|
# Contributing, testing
|
136
213
|
|
@@ -155,4 +232,25 @@ to run the features and start writing tests!
|
|
155
232
|
|
156
233
|
[bundler]: http://gembundler.com/
|
157
234
|
|
235
|
+
## Selenium
|
236
|
+
|
237
|
+
Some of Surveyor's integration tests use Selenium WebDriver and Capybara. The
|
238
|
+
WebDriver-based tests default to running in Chrome due to an unfortunate
|
239
|
+
[Firefox bug][FF566671]. For them to run, you'll either need:
|
240
|
+
|
241
|
+
* Chrome and [chromedriver][] installed, or
|
242
|
+
* to switch to use Firefox instead
|
243
|
+
|
244
|
+
To use Firefox instead of Chrome, invoke one or more features with
|
245
|
+
`SELENIUM_BROWSER` set in the environment:
|
246
|
+
|
247
|
+
$ SELENIUM_BROWSER=firefox bundle exec rake cucumber
|
248
|
+
$ SELENIUM_BROWSER=firefox bundle exec cucumber features/ajax_submissions.feature
|
249
|
+
|
250
|
+
Note that when running features in Firefox, you must allow the WebDriver-driven
|
251
|
+
Firefox to retain focus, otherwise some tests will fail.
|
252
|
+
|
253
|
+
[FF566671]: https://bugzilla.mozilla.org/show_bug.cgi?id=566671
|
254
|
+
[chromedriver]: http://code.google.com/p/selenium/wiki/ChromeDriver
|
255
|
+
|
158
256
|
Copyright (c) 2008-2011 Brian Chamberlain and Mark Yoon, released under the MIT license
|
data/Rakefile
CHANGED
@@ -40,18 +40,14 @@ task :testbed => 'testbed:rebuild'
|
|
40
40
|
namespace :testbed do
|
41
41
|
desc 'Generate a minimal surveyor-using rails app'
|
42
42
|
task :generate do
|
43
|
-
sh 'bundle exec rails new testbed'
|
43
|
+
sh 'bundle exec rails new testbed --skip-bundle' # don't run bundle install until the Gemfile modifications
|
44
44
|
chdir('testbed') do
|
45
|
-
File.
|
46
|
-
|
47
|
-
|
48
|
-
f.puts %q{eval(File.read File.join(plugin_root, 'Gemfile.rails_version'))}
|
49
|
-
f.puts %q{gem 'sqlite3'}
|
50
|
-
f.puts %q{gem 'surveyor', :path => plugin_root}
|
51
|
-
end
|
45
|
+
gem_file_contents = File.read('Gemfile')
|
46
|
+
gem_file_contents.sub!(/^(gem 'rails'.*)$/, %Q{# \\1\nplugin_root = File.expand_path('../..', __FILE__)\neval(File.read File.join(plugin_root, 'Gemfile.rails_version'))\ngem 'surveyor', :path => plugin_root})
|
47
|
+
File.open('Gemfile', 'w'){|f| f.write(gem_file_contents) }
|
52
48
|
|
53
49
|
Bundler.with_clean_env do
|
54
|
-
sh 'bundle
|
50
|
+
sh 'bundle install' # run bundle install after Gemfile modifications
|
55
51
|
end
|
56
52
|
end
|
57
53
|
end
|
@@ -72,6 +68,16 @@ namespace :testbed do
|
|
72
68
|
end
|
73
69
|
|
74
70
|
task :rebuild => [:remove, :generate, :migrate]
|
71
|
+
|
72
|
+
desc 'Load all the sample surveys into the testbed instance'
|
73
|
+
task :surveys do
|
74
|
+
cd('testbed') do
|
75
|
+
Dir[File.join('surveys', '*.rb')].each do |fn|
|
76
|
+
puts "Installing #{fn} into the testbed"
|
77
|
+
system("rake surveyor FILE='#{fn}'")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
75
81
|
end
|
76
82
|
|
77
83
|
###### CI
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class SurveyorCheckBoxesInput < Formtastic::Inputs::CheckBoxesInput
|
2
|
+
include Surveyor::Helpers::FormtasticCustomInput
|
3
|
+
def to_html
|
4
|
+
super
|
5
|
+
end
|
6
|
+
def choice_html(choice)
|
7
|
+
output = ""
|
8
|
+
output << template.content_tag(:label,
|
9
|
+
hidden_fields? ?
|
10
|
+
check_box_with_hidden_input(choice) :
|
11
|
+
check_box_without_hidden_input(choice) <<
|
12
|
+
choice_label(choice),
|
13
|
+
label_html_options.merge(:for => choice_input_dom_id(choice), :class => nil)
|
14
|
+
)
|
15
|
+
output << builder.text_field(:response_other, input_html_options_with(choice, :response_other)) if options[:response_class] == "other_and_string"
|
16
|
+
output << builder.text_field(response_class_to_method(options[:response_class]), input_html_options_with(choice, options[:response_class])) if %w(date datetime time float integer string other_and_string).include? options[:response_class]
|
17
|
+
output << builder.text_area(:text_value, input_html_options_with(choice, :text_value)) if options[:response_class] == "text"
|
18
|
+
output.html_safe
|
19
|
+
end
|
20
|
+
def checked?(value)
|
21
|
+
selected_values.include?(value.to_s)
|
22
|
+
end
|
23
|
+
def disabled?(value)
|
24
|
+
disabled_values.include?(value) || input_html_options[:disabled] == true
|
25
|
+
end
|
26
|
+
def make_selected_values
|
27
|
+
if object.respond_to?(method)
|
28
|
+
selected_items = [object.send(method)].compact.flatten.map(&:to_s)
|
29
|
+
|
30
|
+
[*selected_items.map { |o| send_or_call_or_object(value_method, o) }].compact
|
31
|
+
else
|
32
|
+
[]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class SurveyorRadioInput < Formtastic::Inputs::RadioInput
|
2
|
+
include Surveyor::Helpers::FormtasticCustomInput
|
3
|
+
def to_html
|
4
|
+
super
|
5
|
+
end
|
6
|
+
def choice_html(choice)
|
7
|
+
output = ""
|
8
|
+
output << template.content_tag(:label,
|
9
|
+
builder.radio_button(input_name, choice_value(choice), input_html_options.merge(choice_html_options(choice)).merge(:required => false)) <<
|
10
|
+
choice_label(choice),
|
11
|
+
label_html_options.merge(:for => choice_input_dom_id(choice), :class => nil)
|
12
|
+
)
|
13
|
+
output << builder.text_field(:response_other, input_html_options_with(choice, :response_other)) if options[:response_class] == "other_and_string"
|
14
|
+
output << builder.text_field(response_class_to_method(options[:response_class]), input_html_options_with(choice, options[:response_class])) if %w(date datetime time float integer string other_and_string).include? options[:response_class]
|
15
|
+
output << builder.text_area(:text_value, input_html_options_with(choice, :text_value)) if options[:response_class] == "text"
|
16
|
+
output.html_safe
|
17
|
+
end
|
18
|
+
end
|
@@ -4,9 +4,9 @@
|
|
4
4
|
- i = response_idx(q.pick != "one") # argument will be false (don't increment i) if we're on radio buttons
|
5
5
|
- disabled = defined?(disableFlag) ? disableFlag : false
|
6
6
|
= f.semantic_fields_for i, r do |ff|
|
7
|
-
= ff.
|
8
|
-
= ff.
|
9
|
-
= ff.
|
7
|
+
= ff.input :question_id, :as => :quiet unless q.pick == "one" # don't repeat question_id if we're on radio buttons
|
8
|
+
= ff.input :api_id, :as => :quiet unless q.pick == "one"
|
9
|
+
= ff.input :response_group, :value => rg, :as => :quiet if q.pick != "one" && g && g.display_type == "repeater"
|
10
10
|
- case q.pick
|
11
11
|
- when "one"
|
12
12
|
= ff.input :answer_id, :as => :surveyor_radio, :collection => [[a_text(a, nil, @render_context), a.id]], :label => false, :input_html => {:class => a.css_class, :disabled => disabled}, :response_class => a.response_class
|
@@ -14,7 +14,7 @@
|
|
14
14
|
= ff.input :answer_id, :as => :surveyor_check_boxes, :collection => [[a_text(a, nil, @render_context), a.id]], :label => false, :input_html => {:class => a.css_class, :disabled => disabled}, :response_class => a.response_class
|
15
15
|
- when "none"
|
16
16
|
- if %w(date datetime time float integer string text).include? a.response_class
|
17
|
-
= ff.
|
17
|
+
= ff.input :answer_id, :as => :quiet, :input_html => {:class => a.css_class, :value => a.id}
|
18
18
|
= ff.input rc_to_attr(a.response_class), :as => rc_to_as(a.response_class), :label => a_text(a, :pre, @render_context).blank? ? false : a_text(a, :pre, @render_context), :hint => a_text(a, :post, @render_context), :input_html => generate_pick_none_input_html(r.as(a.response_class), a.default_value, a.css_class, a.response_class, disabled)
|
19
19
|
- else
|
20
20
|
= a_text(a, nil, @render_context)
|
@@ -10,18 +10,18 @@
|
|
10
10
|
- r = response_for(@response_set, q, nil, rg)
|
11
11
|
- i = response_idx
|
12
12
|
= f.semantic_fields_for i, r do |ff|
|
13
|
-
= ff.
|
14
|
-
= ff.
|
15
|
-
= ff.
|
16
|
-
= ff.input :answer_id, :as => :select, :collection => q.answers.map{|a| [a.text, a.id]}, :label => q.text, :input_html => { :disabled => disabled }
|
13
|
+
= ff.input :question_id, :as => :quiet
|
14
|
+
= ff.input :response_group, :as => :quiet, :value => rg if g && g.display_type == "repeater"
|
15
|
+
= ff.input :api_id, :as => :quiet
|
16
|
+
= ff.input :answer_id, :as => :select, :collection => q.answers.map{|a| [a.text, a.id]}, :include_blank => (renderer != :slider), :label => q.text, :input_html => { :disabled => disabled }
|
17
17
|
- else # :default, :inline, :inline_default
|
18
18
|
- if q.pick == "one"
|
19
19
|
- r = response_for(@response_set, q, nil, rg)
|
20
20
|
- i = response_idx # increment the response index since the answer partial skips for q.pick == one
|
21
21
|
= f.semantic_fields_for i, r do |ff|
|
22
|
-
= ff.
|
23
|
-
= ff.
|
24
|
-
= ff.
|
22
|
+
= ff.input :question_id, :as => :quiet
|
23
|
+
= ff.input :response_group, :as => :quiet, :value => rg if g && g.display_type == "repeater"
|
24
|
+
= ff.input :api_id, :as => :quiet
|
25
25
|
- q.answers.each do |a|
|
26
26
|
- next if (q.pick == "one" or q.pick == "any") and disabled and @response_set.responses.where( :question_id => q.id, :answer_id => a.id).empty?
|
27
27
|
= render a.custom_renderer || '/partials/answer', :q => q, :a => a, :f => f, :rg => rg, :g => g, :disableFlag => disabled
|
@@ -6,7 +6,7 @@
|
|
6
6
|
%li
|
7
7
|
%table
|
8
8
|
%col.pre
|
9
|
-
- qs.first.answers.each do |a|
|
9
|
+
- qs.first.answers.each do |a|
|
10
10
|
%col{:class => cycle("odd", "even")}
|
11
11
|
%col.post
|
12
12
|
%tbody
|
@@ -18,13 +18,14 @@
|
|
18
18
|
%th
|
19
19
|
- ten_questions.each_with_index do |q, i|
|
20
20
|
%tr{:id => "q_#{q.id}", :class => "q_#{renderer} #{q.css_class(@response_set)}"}
|
21
|
-
|
22
|
-
|
23
|
-
-
|
24
|
-
|
25
|
-
=
|
26
|
-
=
|
27
|
-
|
21
|
+
%th
|
22
|
+
= q.split_text(:pre)
|
23
|
+
- if q.pick == "one"
|
24
|
+
- r = response_for(@response_set, q, nil, g)
|
25
|
+
- i = response_idx # increment the response index since the answer partial skips for q.pick == one
|
26
|
+
= f.semantic_fields_for i, r do |ff|
|
27
|
+
= ff.input :question_id, :as => :quiet
|
28
|
+
= ff.input :api_id, :as => :quiet
|
28
29
|
- q.answers.each do |a|
|
29
30
|
%td= render a.custom_renderer || '/partials/answer', :g => g, :q => q, :a => a, :f => f
|
30
31
|
%th= q.split_text(:post)
|
@@ -1,36 +1,39 @@
|
|
1
1
|
object @survey
|
2
2
|
attribute :title
|
3
|
-
attribute :api_id
|
4
|
-
node(:description,
|
5
|
-
node(:reference_identifier,
|
3
|
+
attribute :api_id => :uuid
|
4
|
+
node(:description, :if => lambda {|s| !s.description.blank? }){|s| s.description }
|
5
|
+
node(:reference_identifier, :if => lambda {|s| !s.reference_identifier.blank? }){|s| s.reference_identifier }
|
6
6
|
|
7
7
|
child :sections => :sections do
|
8
8
|
attributes :title, :display_order
|
9
|
-
node(:description,
|
10
|
-
node(:reference_identifier,
|
11
|
-
|
9
|
+
node(:description, :if => lambda {|s| !s.description.blank? }){|s| s.description }
|
10
|
+
node(:reference_identifier, :if => lambda {|s| !s.reference_identifier.blank? }){|s| s.reference_identifier }
|
11
|
+
|
12
12
|
child :questions_and_groups => :questions_and_groups do
|
13
13
|
# both questions and question_groups have uuid, text, help_text, reference_identifier, and type
|
14
|
-
attribute :api_id
|
15
|
-
node(:text,
|
16
|
-
node(:text,
|
17
|
-
node(:help_text,
|
18
|
-
node(:reference_identifier,
|
19
|
-
node(:
|
20
|
-
|
14
|
+
attribute :api_id => :uuid
|
15
|
+
node(:text, :if => lambda { |q| q.is_a?(Question)}){ |q| q.split_text(:pre) }
|
16
|
+
node(:text, :if => lambda { |q| q.is_a?(QuestionGroup)}){ |q| q.text }
|
17
|
+
node(:help_text, :if => lambda { |q| !q.help_text.blank? }){ |q| q.help_text }
|
18
|
+
node(:reference_identifier, :if => lambda { |q| !q.reference_identifier.blank? }){ |q| q.reference_identifier }
|
19
|
+
node(:data_export_identifier, :if => lambda { |q| !q.data_export_identifier.blank? }){ |q| q.data_export_identifier }
|
20
|
+
node(:type, :if => lambda { |q| q.display_type != "default" }){ |q| q.display_type }
|
21
|
+
|
21
22
|
# only questions
|
22
|
-
node(:pick,
|
23
|
-
node(:post_text,
|
24
|
-
|
23
|
+
node(:pick, :if => lambda { |q| q.is_a?(Question) && q.pick != "none" }){ |q| q.pick }
|
24
|
+
node(:post_text, :if => lambda { |q| q.is_a?(Question) && !q.split_text(:post).blank? }){ |q| q.split_text(:post) }
|
25
|
+
|
25
26
|
child :answers, :if => lambda { |q| q.is_a?(Question) && !q.answers.blank? } do
|
26
|
-
attribute :api_id
|
27
|
-
node(:help_text,
|
28
|
-
node(:exclusive,
|
27
|
+
attribute :api_id => :uuid
|
28
|
+
node(:help_text, :if => lambda { |a| !a.help_text.blank? }){ |a| a.help_text }
|
29
|
+
node(:exclusive, :if => lambda { |a| a.is_exclusive }){ |a| a.is_exclusive }
|
29
30
|
node(:text){ |a| a.split_or_hidden_text(:pre) }
|
30
|
-
node(:post_text,
|
31
|
-
node(:type,
|
31
|
+
node(:post_text, :if => lambda { |a| !a.split_or_hidden_text(:post).blank? }){ |a| a.split_or_hidden_text(:post) }
|
32
|
+
node(:type, :if => lambda { |a| a.response_class != "answer" }){ |a| a.response_class }
|
33
|
+
node(:reference_identifier, :if => lambda { |a| !a.reference_identifier.blank? }){ |a| a.reference_identifier }
|
34
|
+
node(:data_export_identifier, :if => lambda { |a| !a.data_export_identifier.blank? }){ |a| a.data_export_identifier }
|
32
35
|
end
|
33
|
-
|
36
|
+
|
34
37
|
# both questions and question_groups have dependencies
|
35
38
|
child :dependency, :if => lambda { |q| q.dependency } do
|
36
39
|
attributes :rule
|
@@ -41,7 +44,7 @@ child :sections => :sections do
|
|
41
44
|
node(:value, :if => lambda { |d| d.answer && d.answer.response_class != "answer" && d.as(d.answer.response_class) }){ |d| d.as(d.answer.response_class)}
|
42
45
|
end
|
43
46
|
end
|
44
|
-
|
47
|
+
|
45
48
|
child(:questions, :if => lambda{|x| x.is_a?(QuestionGroup)}) do
|
46
49
|
attributes :api_id => :uuid
|
47
50
|
node(:text){ |q| q.split_text(:pre) }
|
@@ -50,7 +53,7 @@ child :sections => :sections do
|
|
50
53
|
node(:reference_identifier, :if => lambda { |q| !q.reference_identifier.blank? }){ |q| q.reference_identifier }
|
51
54
|
node(:type, :if => lambda { |q| q.display_type != "default" }){ |q| q.display_type }
|
52
55
|
node(:pick, :if => lambda { |q| q.pick != "none" }){ |q| q.pick }
|
53
|
-
|
56
|
+
|
54
57
|
child :answers, :if => lambda { |q| !q.answers.blank? } do
|
55
58
|
attributes :api_id => :uuid
|
56
59
|
node(:help_text, :if => lambda { |a| !a.help_text.blank? }){ |a| a.help_text }
|
@@ -59,7 +62,7 @@ child :sections => :sections do
|
|
59
62
|
node(:post_text, :if => lambda { |a| !a.split_or_hidden_text(:post).blank? }){ |a| a.split_or_hidden_text(:post) }
|
60
63
|
node(:type, :if => lambda { |a| a.response_class != "answer" }){ |a| a.response_class }
|
61
64
|
end
|
62
|
-
|
65
|
+
|
63
66
|
child :dependency, :if => lambda { |q| q.dependency } do
|
64
67
|
attributes :rule
|
65
68
|
child :dependency_conditions => :conditions do
|
@@ -7,13 +7,16 @@
|
|
7
7
|
%br
|
8
8
|
#survey_list
|
9
9
|
%ul
|
10
|
-
- unless @
|
11
|
-
- @
|
10
|
+
- unless @codes.empty?
|
11
|
+
- @codes.each do |access_code, values|
|
12
12
|
%li
|
13
|
-
= form_tag
|
13
|
+
= form_tag take_survey_path(:survey_code => access_code) do
|
14
14
|
= hidden_field_tag :surveyor_javascript_enabled, false
|
15
|
-
|
16
|
-
=
|
15
|
+
|
16
|
+
= values[:title]
|
17
|
+
|
18
|
+
= label_tag :survey_version, 'version:'
|
19
|
+
= select_tag(:survey_version, options_for_select([["-- Current version --", ""]] + values[:survey_versions]))
|
17
20
|
|
18
21
|
= submit_tag( t('surveyor.take_it') )
|
19
22
|
- else
|
@@ -4,11 +4,12 @@ attribute :created_at
|
|
4
4
|
attribute :completed_at
|
5
5
|
node(:survey_id){|rs| rs.survey.api_id }
|
6
6
|
|
7
|
-
child :responses do
|
7
|
+
child (@response_set.responses || []) => :responses do
|
8
8
|
attribute :api_id => :uuid
|
9
9
|
attribute :created_at
|
10
10
|
attribute :updated_at => :modified_at
|
11
|
+
attribute :response_group
|
11
12
|
node(:answer_id){|r| r.answer.api_id }
|
12
13
|
node(:question_id){|r| r.question.api_id }
|
13
|
-
node(:value, :if => lambda{|r| r.answer.response_class != "answer"}){|r| r.
|
14
|
+
node(:value, :if => lambda{|r| r.answer.response_class != "answer"}){|r| r.json_value }
|
14
15
|
end
|
data/ci-exec.sh
CHANGED
@@ -1,19 +1,25 @@
|
|
1
1
|
#!/bin/bash -xe
|
2
2
|
|
3
|
-
BUNDLER_VERSION=1.1.
|
3
|
+
BUNDLER_VERSION=1.1.5
|
4
4
|
GEMSET=surveyor
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
if [ -z $CI_RUBY ]; then
|
7
|
+
echo "CI_RUBY must be set"
|
8
|
+
exit 1
|
9
|
+
fi
|
10
|
+
|
11
|
+
# TMPDIR under the workspace causes gconfd-2 to stop responding and eat all
|
12
|
+
# memory when Firefox is running for the Selenium tests. TMPDIR in user home
|
13
|
+
# seems to work fine.
|
14
|
+
export TMPDIR="${HOME}/tmp/surveyor-ci-${CI_RUBY}"
|
8
15
|
|
9
16
|
if [ -n "${RAILS_VERSION}" ]; then
|
10
17
|
GEMSET="${GEMSET}-${RAILS_VERSION}"
|
18
|
+
TMPDIR="${TMPDIR}-${RAILS_VERSION}"
|
11
19
|
fi
|
12
20
|
|
13
|
-
|
14
|
-
|
15
|
-
exit 1
|
16
|
-
fi
|
21
|
+
rm -rf "${TMPDIR}"
|
22
|
+
mkdir -p "${TMPDIR}"
|
17
23
|
|
18
24
|
set +xe
|
19
25
|
echo "Initializing RVM"
|
data/cucumber.yml
CHANGED
@@ -4,7 +4,7 @@ rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'pr
|
|
4
4
|
std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} --strict --tags ~@wip"
|
5
5
|
%>
|
6
6
|
default: <%= std_opts %> features
|
7
|
-
wip: --tags @wip
|
7
|
+
wip: --tags @wip --wip features
|
8
8
|
rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip
|
9
|
-
ci: --tags ~@wip --
|
10
|
-
ci_wip: --wip --tags @wip --
|
9
|
+
ci: --tags ~@wip --format html --out reports/cucumber.html --format junit --out reports/cucumber-xml --format pretty --strict features
|
10
|
+
ci_wip: --wip --tags @wip --format html --out reports/cucumber_wip.html --format pretty features
|