diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml
index b704b898..03edd401 100644
--- a/app/views/admin/users/index.html.haml
+++ b/app/views/admin/users/index.html.haml
@@ -66,7 +66,7 @@
%button{:class=> "btn btn-danger", "data-dismiss"=> "modal", "aria-hidden"=>"true"}
Cancel
= f.action :submit, :as => :button, :button_html => {:value => "Save", :class => "btn btn-primary"}
- =link_to "Modify Roles", "#", "data-toggle" => "modal", "data-target" => "#user-role-selection-#{user.id}"
+ =link_to "Modify Roles", "#", "data-toggle" => "modal", "data-target" => "#user-role-selection-#{user.id}",id: "user-modify-role-#{user.id}"
%td
=link_to "Details", "javascript: void(0)", :class => "user-details-popover", "data-trigger" => "click", "data-placement" => "bottom",
"data-html" => "true",
diff --git a/spec/factories/users.rb b/spec/factories/users.rb
index 5fe55ab8..9b2d1e8c 100644
--- a/spec/factories/users.rb
+++ b/spec/factories/users.rb
@@ -1,8 +1,7 @@
# Read about factories at https://github.com/thoughtbot/factory_girl
-
FactoryGirl.define do
factory :user do
- email 'example@example.com'
+ sequence(:email) { |n| "example#{n}@example.com" }
password 'changeme'
password_confirmation 'changeme'
confirmed_at Time.now
diff --git a/spec/features/user_spec.rb b/spec/features/user_spec.rb
new file mode 100644
index 00000000..d66db690
--- /dev/null
+++ b/spec/features/user_spec.rb
@@ -0,0 +1,39 @@
+require 'spec_helper'
+feature User do
+ # It is necessary to use bang version of let to build roles before user
+ let!(:organizer_role) { create(:organizer_role) }
+ let!(:participant_role) { create(:participant_role) }
+ let!(:admin_role) { create(:admin_role) }
+ let(:admin) { create(:admin) }
+ shared_examples 'admin ability' do |user|
+ scenario 'deletes a user', feature: true, js: true do
+ sign_in(admin)
+ visit admin_users_path
+ expected_count = User.count - 1
+ page.all('btn btn-primary btn-danger') do
+ click_link 'Delete'
+ page.evaluate_script('window.confirm = function() { return true; }')
+ page.click('OK')
+ expect(flash).to eq('User got deleted')
+ expect(User.count).to eq(expected_count)
+ end
+ sign_out
+ end
+ scenario 'can modify roles', feature: true, js: true do
+ @user = create(:user)
+ sign_in(admin)
+ visit admin_users_path
+ find("#user-modify-role-#{@user.id}").click
+ find("#user-role-selection-#{@user.id}").visible?
+ page.find('#user_role_ids').find(:xpath, 'option[2]').select_option do
+ find('#user_submit_action').click
+ expect(flash).to eq("Updated #{@user.email}")
+ expect(@user.role_ids).to match_array([2])
+ end
+ sign_out
+ end
+ end
+ describe 'admin' do
+ it_behaves_like 'admin ability', :admin
+ end
+end
diff --git a/spec/features/volunteers_spec.rb b/spec/features/volunteers_spec.rb
new file mode 100644
index 00000000..d934143e
--- /dev/null
+++ b/spec/features/volunteers_spec.rb
@@ -0,0 +1,123 @@
+require 'spec_helper'
+
+feature Conference do
+ # It is necessary to use bang version of let to build roles before user
+ let!(:organizer_role) { create(:organizer_role) }
+ let!(:participant_role) { create(:participant_role) }
+ let!(:admin_role) { create(:admin_role) }
+ let(:admin) { create(:admin) }
+ let(:conference) { create(:conference) }
+ shared_examples 'volunteer' do |user|
+ scenario 'adds and updates vdays', feature: true, js: true do
+ sign_in(admin)
+ visit admin_conference_volunteers_info_path(
+ conference_id: conference.short_title)
+ check('Enable Volunteering')
+ check('Use vdays')
+ click_link 'Add vday'
+ expect(page.all('div.nested-fields').count == 1).to be true
+ page.
+ find('div.nested-fields:nth-of-type(1) select:nth-of-type(1)').
+ set("#{Date.today.strftime('%Y')}")
+ page.
+ find('div.nested-fields:nth-of-type(1) select:nth-of-type(2)').
+ set("#{Date.today.strftime('%B')}")
+ page.
+ find('div.nested-fields:nth-of-type(1) select:nth-of-type(3)').
+ set("#{Date.today.strftime('%d')}")
+ page.
+ find('div.nested-fields:nth-of-type(1) div:nth-of-type(1) textarea').
+ set('Example Person')
+ click_button 'Update Conference'
+ expect(flash).
+ to eq('Volunteering options were successfully updated.')
+
+ # Validations
+ expect(find('div.nested-fields:nth-of-type(1) select:nth-of-type(1)').
+ value).to eq("#{Date.today.strftime('%Y')}")
+ expect(find('div.nested-fields:nth-of-type(1) select:nth-of-type(2)').
+ value).to eq("#{Date.today.month}")
+ expect(find('div.nested-fields:nth-of-type(1) select:nth-of-type(3)').
+ value).to eq("#{Date.today.strftime('%d')}")
+ expect(
+ find('div.nested-fields:nth-of-type(1) div:nth-of-type(1) textarea').
+ value).to eq('Example Person')
+
+ # Remove vday
+ click_link 'Remove vday'
+ expect(page.all('div.nested-fields').count == 0).to be true
+ click_button 'Update Conference'
+ expect(flash).to eq('Volunteering options were successfully updated.')
+ expect(page.all('div.nested-fields').count == 0).to be true
+ sign_out
+ end
+
+ scenario 'adds and updates vpositions', feature: true, js: true do
+ sign_in(admin)
+ visit admin_conference_volunteers_info_path(
+ conference_id: conference.short_title)
+ # Adding vday
+ check('Enable Volunteering')
+ check('Use vdays')
+ click_link 'Add vday'
+ expect(page.all('div.nested-fields').count == 1).to be true
+ page.
+ find('div.nested-fields:nth-of-type(1) select:nth-of-type(1)').
+ set("#{Date.today.strftime('%Y')}")
+ page.
+ find('div.nested-fields:nth-of-type(1) select:nth-of-type(2)').
+ set("#{Date.today.strftime('%B')}")
+ page.
+ find('div.nested-fields:nth-of-type(1) select:nth-of-type(3)').
+ set("#{Date.today.strftime('%d')}")
+ page.
+ find('div.nested-fields:nth-of-type(1) div:nth-of-type(1) textarea').
+ set('Example Person')
+ click_button 'Update Conference'
+ expect(flash).
+ to eq('Volunteering options were successfully updated.')
+ # Add vposition
+ check('Use vpositions')
+ click_link 'Add vposition'
+ expect(page.all('div.nested-fields').count == 2).to be true
+ page.find('div.vpositions div.nested-fields:nth-of-type(1)'\
+ ' div:nth-of-type(1) input').
+ set('Example Position')
+ page.find('div.vpositions div.nested-fields:nth-of-type(1)'\
+ ' div:nth-of-type(2) textarea').
+ set('Example Description')
+ find(:css, "select[id^='conference_vpositions_attributes_']"\
+ "[id$='_vday_ids']").
+ find(:option, "#{Date.today.strftime}").select_option
+ click_button 'Update Conference'
+ expect(flash).
+ to eq('Volunteering options were successfully updated.')
+
+ # Validations
+ expect(find('div.vpositions div.nested-fields:nth-of-type(1)'\
+ ' div:nth-of-type(1) input').
+ value).to eq('Example Position')
+ expect(find('div.vpositions div.nested-fields:nth-of-type(1)'\
+ ' div:nth-of-type(2) textarea').
+ value).to eq('Example Description')
+ expect(find('div.vpositions div.nested-fields:nth-of-type(1)'\
+ ' div:nth-of-type(3) select:nth-of-type(1)').
+ text).to eq("#{Date.today.strftime}")
+
+ # Remove vposition
+ click_link 'Remove vposition'
+ expect(page.all('div.nested-fields').count == 1).to be true
+ click_button 'Update Conference'
+ expect(flash).to eq('Volunteering options were successfully updated.')
+ click_link 'Remove vday'
+ expect(page.all('div.nested-fields').count == 0).to be true
+ sign_out
+ end
+ end
+ describe 'admin' do
+ it_behaves_like 'volunteer', :admin
+ end
+ describe 'organizer' do
+ it_behaves_like 'volunteer', :organizer
+ end
+end