From 657c760737e87e442eff7dff3ccb297f3d100db0 Mon Sep 17 00:00:00 2001 From: Petko Bordjukov Date: Sun, 11 Nov 2018 00:07:00 +0200 Subject: [PATCH] Introduce first feature specs --- Gemfile | 5 +- Gemfile.lock | 4 + app/controllers/application_controller.rb | 3 + app/models/event_type.rb | 1 + app/uploaders/picture_uploader.rb | 4 +- db/seeds.rb | 7 +- spec/features/call_for_papers_spec.rb | 129 ++++++++++++++++++++++ spec/features/landing_page_spec.rb | 16 +++ spec/support/capybara.rb | 2 + spec/support/delorean.rb | 5 + spec/support/feature_helpers.rb | 120 ++++++++++++++++++++ 11 files changed, 292 insertions(+), 4 deletions(-) create mode 100644 spec/features/call_for_papers_spec.rb create mode 100644 spec/features/landing_page_spec.rb create mode 100644 spec/support/delorean.rb create mode 100644 spec/support/feature_helpers.rb diff --git a/Gemfile b/Gemfile index 252b068..e401cf6 100644 --- a/Gemfile +++ b/Gemfile @@ -26,7 +26,8 @@ gem 'phony_rails' # Picture uploads gem 'carrierwave' -gem 'rmagick' +#gem 'rmagick' +gem "mini_magick" gem "refile", require: ['refile/rails', 'refile/simple_form'] gem "refile-mini_magick" @@ -85,6 +86,8 @@ group :development, :test do gem 'byebug' gem 'simplecov' gem 'i18n-tasks' + + gem 'delorean' end group :test do diff --git a/Gemfile.lock b/Gemfile.lock index ed8b912..f921a91 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -93,6 +93,7 @@ GEM childprocess (0.9.0) ffi (~> 1.0, >= 1.0.11) choice (0.2.0) + chronic (0.10.2) chunky_png (1.3.8) coderay (1.1.1) coffee-rails (4.2.1) @@ -108,6 +109,8 @@ GEM crass (1.0.4) database_cleaner (1.7.0) debug_inspector (0.0.2) + delorean (2.1.0) + chronic devise (4.2.0) bcrypt (~> 3.0) orm_adapter (~> 0.1) @@ -413,6 +416,7 @@ DEPENDENCIES coffee-rails copy_carrierwave_file database_cleaner + delorean devise devise-i18n factory_girl_rails diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index a431ae1..5d5e932 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -32,6 +32,9 @@ class ApplicationController < ActionController::Base def set_view_paths # TODO: make this get the domain from the database prepend_view_path 'lib/initfest/views' if request.host =~ /openfest/ + prepend_view_path 'lib/initfest/views' if request.host =~ /example/ + prepend_view_path 'lib/initfest/views' if request.host =~ /127\.0\.0/ + end protected diff --git a/app/models/event_type.rb b/app/models/event_type.rb index 839d604..d477b9c 100644 --- a/app/models/event_type.rb +++ b/app/models/event_type.rb @@ -6,4 +6,5 @@ class EventType < ActiveRecord::Base validates :name, presence: true, uniqueness: {scope: :conference, message: :must_be_unique_for_the_conference} validates :description, presence: true + validates :minimum_length, :maximum_length, presence: true end diff --git a/app/uploaders/picture_uploader.rb b/app/uploaders/picture_uploader.rb index 3dc3914..55deef0 100644 --- a/app/uploaders/picture_uploader.rb +++ b/app/uploaders/picture_uploader.rb @@ -1,8 +1,8 @@ class PictureUploader < CarrierWave::Uploader::Base # Include RMagick or MiniMagick support: - include CarrierWave::RMagick - # include CarrierWave::MiniMagick + #include CarrierWave::RMagick + include CarrierWave::MiniMagick # Choose what kind of storage to use for this uploader: storage :file diff --git a/db/seeds.rb b/db/seeds.rb index 4edb1e8..36330fd 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -4,4 +4,9 @@ # Examples: # # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) -# Mayor.create(name: 'Emanuel', city: cities.first) +# Mayor.create(name: 'Emanuel', city: cities.first +User.create(email: 'foo@example.com', + password: '123qweASD', + password_confirmation: '123qweASD', + confirmed_at: Time.current, + admin: true) diff --git a/spec/features/call_for_papers_spec.rb b/spec/features/call_for_papers_spec.rb new file mode 100644 index 0000000..8dc9709 --- /dev/null +++ b/spec/features/call_for_papers_spec.rb @@ -0,0 +1,129 @@ +require "rails_helper" + +feature 'Call for papers' do + before do + Rails.application.load_seed + end + + scenario "A new user submits an event proposition" do + sign_in_as_admin + create_new_conference + sign_out + + visit root_path + click_on I18n.t('views.welcome.submit_event', event_type: Conference.first.event_types.first.name.try(:mb_chars).try(:downcase)) + click_on I18n.t(:registration) + + register_a_new_user(false) + + submit_an_event_proposition + + expect(page).to have_content I18n.t('views.events.event_successfully_created', event_type: Event.last.event_type.name.mb_chars.downcase) + expect(page).to have_content I18n.t(:please_fill_in_your_speaker_profile) + + fill_in_personal_profile + + expect(page).to have_content I18n.t('views.personal_profiles.successfully_created') + + click_on I18n.t('views.navigation.my_submissions') + + expect(page).to have_content(Event.last.event_type.name + ' "This is just a sample title of an event"') + + sign_out + + verify_the_event_is_submitted + end + + scenario "A returning user submits an event proposition" do + time_travel_to(2.years.ago) do + sign_in_as_admin + create_new_conference + sign_out + + visit root_path + click_on I18n.t('views.welcome.submit_event', event_type: Conference.first.event_types.first.name.try(:mb_chars).try(:downcase)) + click_on I18n.t(:registration) + + register_a_new_user(false) + + submit_an_event_proposition + + fill_in_personal_profile + sign_out + end + + sign_in_as_admin + create_new_conference + sign_out + + visit root_path + click_on I18n.t('views.welcome.submit_event', event_type: Conference.first.event_types.first.name.try(:mb_chars).try(:downcase)) + + sign_in_as_an_existing_user(false) + + submit_an_event_proposition(false) + expect(page).to have_content I18n.t(:please_fill_in_your_speaker_profile) + click_on I18n.t('helpers.submit.create', model: PersonalProfile.model_name.human) + + expect(page).to have_content I18n.t('views.personal_profiles.successfully_created') + + click_on I18n.t('views.navigation.my_submissions') + + expect(page).to have_content(Event.last.event_type.name + ' "This is just a sample title of an event"') + + sign_out + + verify_the_event_is_submitted + end + + + scenario "A returning user resets their password and submits an event proposition" do + time_travel_to(2.years.ago) do + sign_in_as_admin + create_new_conference + sign_out + + visit root_path + click_on I18n.t('views.welcome.submit_event', event_type: Conference.first.event_types.first.name.try(:mb_chars).try(:downcase)) + click_on I18n.t(:registration) + + register_a_new_user(false) + + submit_an_event_proposition + + fill_in_personal_profile + sign_out + end + + sign_in_as_admin + create_new_conference + sign_out + + visit root_path + click_on I18n.t('views.welcome.submit_event', event_type: Conference.first.event_types.first.name.try(:mb_chars).try(:downcase)) + + click_on I18n.t('lostpass') + fill_in User.human_attribute_name(:email), with: 'bar@example.com' + click_on I18n.t(:send_lostpass_instructions) + expect(page).to have_content I18n.t('devise.passwords.send_instructions') + visit ActionMailer::Base.deliveries.last.body.raw_source.match(/https?:\/\/.*?(\/.*\w)/)[1] + + fill_in User.human_attribute_name(:password), with: 'foobarbaz' + fill_in User.human_attribute_name(:password_confirmation), with: 'foobarbaz' + click_on I18n.t(:change_pass) + + submit_an_event_proposition(false) + expect(page).to have_content I18n.t(:please_fill_in_your_speaker_profile) + click_on I18n.t('helpers.submit.create', model: PersonalProfile.model_name.human) + + expect(page).to have_content I18n.t('views.personal_profiles.successfully_created') + + click_on I18n.t('views.navigation.my_submissions') + + expect(page).to have_content(Event.last.event_type.name + ' "This is just a sample title of an event"') + + sign_out + + verify_the_event_is_submitted + end +end diff --git a/spec/features/landing_page_spec.rb b/spec/features/landing_page_spec.rb new file mode 100644 index 0000000..195cb33 --- /dev/null +++ b/spec/features/landing_page_spec.rb @@ -0,0 +1,16 @@ +require "rails_helper" + +feature 'Landing page' do + before do + Rails.application.load_seed + sign_in_as_admin + create_new_conference + sign_out + end + + it 'displays information about the conference' do + visit root_path + expect(page).to have_content I18n.t(:home_title, conference: "FooConf #{1.year.from_now.year}") + end +end + diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb index d81f8ee..3c0cb09 100644 --- a/spec/support/capybara.rb +++ b/spec/support/capybara.rb @@ -10,6 +10,8 @@ RSpec.configure do |config| end RSpec.configure do |config| + config.include FeatureHelpers, type: :feature + config.alias_example_group_to :feature, capybara_feature: true, type: :feature config.alias_example_group_to :xfeature, capybara_feature: true, type: :feature, skip: "Temporarily disabled with xfeature" config.alias_example_group_to :ffeature, capybara_feature: true, type: :feature, focus: true diff --git a/spec/support/delorean.rb b/spec/support/delorean.rb new file mode 100644 index 0000000..8d2da91 --- /dev/null +++ b/spec/support/delorean.rb @@ -0,0 +1,5 @@ +# TODO: Remove once upgrade to Rails 5+ is done + +RSpec.configure do |config| + config.include Delorean +end diff --git a/spec/support/feature_helpers.rb b/spec/support/feature_helpers.rb new file mode 100644 index 0000000..ef37d58 --- /dev/null +++ b/spec/support/feature_helpers.rb @@ -0,0 +1,120 @@ +module FeatureHelpers + def sign_in_as_admin + visit management_root_path + within 'section.content' do + fill_in User.human_attribute_name(:email), with: 'foo@example.com' + fill_in User.human_attribute_name(:password), with: '123qweASD' + click_on I18n.t(:login) + end + end + + def create_new_conference(title = "FooConf #{1.year.from_now.year}", + host_name: 'www.example.com', + planned_cfp_end_date: 1.year.from_now, + start_date: 1.year.from_now + 1.day, + end_date: 1.year.from_now + 2.days) + click_on I18n.t('actions.create.button', model: Conference.model_name.human) + fill_in Conference.human_attribute_name(:title), with: title + fill_in Conference.human_attribute_name(:email), with: 'foo@example.com' + fill_in Conference.human_attribute_name(:host_name), with: host_name + select planned_cfp_end_date.year, from: 'conference[planned_cfp_end_date(1i)]' + select I18n.t('date.month_names')[planned_cfp_end_date.month], from: 'conference[planned_cfp_end_date(2i)]' + select planned_cfp_end_date.day, from: 'conference[planned_cfp_end_date(3i)]' + + select start_date.year, from: 'conference[start_date(1i)]' + select I18n.t('date.month_names')[start_date.month], from: 'conference[start_date(2i)]' + select start_date.day, from: 'conference[start_date(3i)]' + + select end_date.year, from: 'conference[end_date(1i)]' + select I18n.t('date.month_names')[end_date.month], from: 'conference[end_date(2i)]' + select end_date.day, from: 'conference[end_date(3i)]' + + within '.form-group.conference_description' do + fill_in Conference.human_attribute_name(:description), with: 'Lorem' + end + + within '#event_types' do + fill_in EventType.human_attribute_name(:description), with: 'Lorem' + fill_in EventType.human_attribute_name(:minimum_length), with: '45' + fill_in EventType.human_attribute_name(:maximum_length), with: '45' + + end + + within '#tracks' do + fill_in Track.human_attribute_name(:description), with: 'Lorem' + end + + within '#volunteer_teams' do + fill_in VolunteerTeam.human_attribute_name(:description), with: 'Lorem' + end + + page.find('.btn.btn-primary').click + + click_on I18n.t('management.conferences.show.cfp_status') + end + + def sign_out + click_on I18n.t('sessions.sign_out') + end + + def register_a_new_user(visit_registration_path = true) + if visit_registration_path + click_on I18n.t('sessions.sign_in') + end + + fill_in User.human_attribute_name(:email), with: 'bar@example.com' + fill_in User.human_attribute_name(:password), with: '123qweASD' + fill_in User.human_attribute_name(:password_confirmation), with: '123qweASD' + + within '.form-actions' do + page.find('.btn').click + end + visit(user_confirmation_path + "?confirmation_token=" + User.order(created_at: :desc).first.confirmation_token) + end + + def sign_in_as_an_existing_user(visit_sign_in_path = true) + if visit_sign_in_path + click_on I18n.t('sessions.sign_in') + end + + within 'section.content' do + fill_in User.human_attribute_name(:email), with: 'bar@example.com' + fill_in User.human_attribute_name(:password), with: '123qweASD' + click_on I18n.t(:login) + end + end + + + def submit_an_event_proposition(visit_event_submission_path = true) + if visit_event_submission_path + visit root_path + click_on I18n.t('views.welcome.submit_event', event_type: Conference.first.event_types.first.name.try(:mb_chars).try(:downcase)) + end + + fill_in Event.human_attribute_name(:title), with: 'This is just a sample title of an event' + select Conference.first.tracks.first.name, from: Event.human_attribute_name(:track) + fill_in Event.human_attribute_name(:length), with: '45' + fill_in Event.human_attribute_name(:abstract), with: 'Lorem' + fill_in Event.human_attribute_name(:description), with: 'Ipsum' + check Event.human_attribute_name(:agreement) + + click_on I18n.t('helpers.submit.event.create') + end + + def fill_in_personal_profile + attach_file PersonalProfile.human_attribute_name(:picture), Rails.root.join('spec', 'support', 'picture.jpg') + fill_in PersonalProfile.human_attribute_name(:first_name), with: 'Foo' + fill_in PersonalProfile.human_attribute_name(:last_name), with: 'Bar' + fill_in PersonalProfile.human_attribute_name(:mobile_phone), with: '+359666666' + fill_in PersonalProfile.human_attribute_name(:biography), with: 'Lorem' + + click_on I18n.t('helpers.submit.create', model: PersonalProfile.model_name.human) + end + + def verify_the_event_is_submitted + sign_in_as_admin + click_on I18n.t('actions.view.button', model: Conference.model_name.human), match: :first + click_on Event.model_name.human(count: 2).mb_chars.capitalize + expect(page).to have_content 'This is just a sample title of an event' + end +end