From c9b894f736d4cffe8b70ac3a68141091a1f624b4 Mon Sep 17 00:00:00 2001 From: padrta Date: Mon, 12 Sep 2016 22:33:04 +0200 Subject: [PATCH] rails_apps_composer: set up database --- .env.example | 13 ++++++ app/services/create_admin_service.rb | 8 ++++ config/initializers/devise.rb | 2 +- config/secrets.yml | 13 ++++++ db/seeds.rb | 9 ++-- spec/factories/users.rb | 4 +- spec/features/users/sign_in_spec.rb | 49 +++++++++++++++++++ spec/features/users/sign_out_spec.rb | 21 +++++++++ spec/features/users/user_delete_spec.rb | 32 +++++++++++++ spec/features/users/user_edit_spec.rb | 42 +++++++++++++++++ spec/features/users/user_index_spec.rb | 25 ++++++++++ spec/features/users/user_show_spec.rb | 39 ++++++++++++++++ spec/features/visitors/sign_up_spec.rb | 62 +++++++++++++++++++++++++ spec/models/user_spec.rb | 14 ++++-- spec/support/devise.rb | 3 ++ spec/support/helpers.rb | 4 ++ spec/support/helpers/session_helpers.rb | 18 +++++++ 17 files changed, 350 insertions(+), 8 deletions(-) create mode 100644 .env.example create mode 100644 app/services/create_admin_service.rb create mode 100644 spec/features/users/sign_in_spec.rb create mode 100644 spec/features/users/sign_out_spec.rb create mode 100644 spec/features/users/user_delete_spec.rb create mode 100644 spec/features/users/user_edit_spec.rb create mode 100644 spec/features/users/user_index_spec.rb create mode 100644 spec/features/users/user_show_spec.rb create mode 100644 spec/features/visitors/sign_up_spec.rb create mode 100644 spec/support/devise.rb create mode 100644 spec/support/helpers.rb create mode 100644 spec/support/helpers/session_helpers.rb diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..701b5f1 --- /dev/null +++ b/.env.example @@ -0,0 +1,13 @@ +# Add account credentials and API keys here. +# This file should be listed in .gitignore to keep your settings secret! +# Each entry sets a local environment variable. +# For example, setting: +# GMAIL_USERNAME=Your_Gmail_Username +# makes 'Your_Gmail_Username' available as ENV["GMAIL_USERNAME"] + +GMAIL_USERNAME=Your_Username +GMAIL_PASSWORD=Your_Password +DOMAIN_NAME=example.com +ADMIN_NAME=First User +ADMIN_EMAIL=user@example.com +ADMIN_PASSWORD=changeme diff --git a/app/services/create_admin_service.rb b/app/services/create_admin_service.rb new file mode 100644 index 0000000..1f0aecc --- /dev/null +++ b/app/services/create_admin_service.rb @@ -0,0 +1,8 @@ +class CreateAdminService + def call + user = User.find_or_create_by!(email: Rails.application.secrets.admin_email) do |user| + user.password = Rails.application.secrets.admin_password + user.password_confirmation = Rails.application.secrets.admin_password + end + end +end diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 222f8a9..89783a1 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -12,7 +12,7 @@ # Configure the e-mail address which will be shown in Devise::Mailer, # note that it will be overwritten if you use your own mailer class # with default "from" parameter. - config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com' + config.mailer_sender = 'no-reply@' + Rails.application.secrets.domain_name # Configure the class responsible to send e-mails. # config.mailer = 'Devise::Mailer' diff --git a/config/secrets.yml b/config/secrets.yml index 6c07186..20a66b1 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -11,12 +11,25 @@ # if you're sharing your code publicly. development: + admin_name: First User + admin_email: user@example.com + admin_password: changeme + email_provider_username: <%= ENV["GMAIL_USERNAME"] %> + email_provider_password: <%= ENV["GMAIL_PASSWORD"] %> + domain_name: example.com secret_key_base: 8d9ef9e1c0c1c6c83c85fa57e1b0599d925958edcd80b8a75dc5eb52068e5cf672bb6a4178afb0f3d6747b483f9eb555a225c0dd262060e656904f71a2426055 test: + domain_name: example.com secret_key_base: 8e445726b8bd7cce5d3baa2bc801e160f2fc76bdda9f051daedab4b30a5ffda9cae9e6e232eeed589d2f8cbc2f13bf5a26d066bd5182a3f7e4b6d342f849ba76 # Do not keep production secrets in the repository, # instead read values from the environment. production: + admin_name: <%= ENV["ADMIN_NAME"] %> + admin_email: <%= ENV["ADMIN_EMAIL"] %> + admin_password: <%= ENV["ADMIN_PASSWORD"] %> + email_provider_username: <%= ENV["GMAIL_USERNAME"] %> + email_provider_password: <%= ENV["GMAIL_PASSWORD"] %> + domain_name: <%= ENV["DOMAIN_NAME"] %> secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> diff --git a/db/seeds.rb b/db/seeds.rb index 1beea2a..02b6690 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1,7 +1,10 @@ # This file should contain all the record creation needed to seed the database with its default values. -# The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). +# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). # # Examples: # -# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) -# Character.create(name: 'Luke', movie: movies.first) +# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) +# Mayor.create(name: 'Emanuel', city: cities.first) +user = CreateAdminService.new.call +puts 'CREATED ADMIN USER: ' << user.email +# Environment variables (ENV['...']) can be set in the file .env file. diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 96b2b0c..38e3ec9 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -1,5 +1,7 @@ FactoryGirl.define do factory :user do - + name "Test User" + email "test@example.com" + password "please123" end end diff --git a/spec/features/users/sign_in_spec.rb b/spec/features/users/sign_in_spec.rb new file mode 100644 index 0000000..57d4d93 --- /dev/null +++ b/spec/features/users/sign_in_spec.rb @@ -0,0 +1,49 @@ +# Feature: Sign in +# As a user +# I want to sign in +# So I can visit protected areas of the site +feature 'Sign in', :devise do + + # Scenario: User cannot sign in if not registered + # Given I do not exist as a user + # When I sign in with valid credentials + # Then I see an invalid credentials message + scenario 'user cannot sign in if not registered' do + signin('test@example.com', 'please123') + expect(page).to have_content I18n.t 'devise.failure.not_found_in_database', authentication_keys: 'email' + end + + # Scenario: User can sign in with valid credentials + # Given I exist as a user + # And I am not signed in + # When I sign in with valid credentials + # Then I see a success message + scenario 'user can sign in with valid credentials' do + user = FactoryGirl.create(:user) + signin(user.email, user.password) + expect(page).to have_content I18n.t 'devise.sessions.signed_in' + end + + # Scenario: User cannot sign in with wrong email + # Given I exist as a user + # And I am not signed in + # When I sign in with a wrong email + # Then I see an invalid email message + scenario 'user cannot sign in with wrong email' do + user = FactoryGirl.create(:user) + signin('invalid@email.com', user.password) + expect(page).to have_content I18n.t 'devise.failure.not_found_in_database', authentication_keys: 'email' + end + + # Scenario: User cannot sign in with wrong password + # Given I exist as a user + # And I am not signed in + # When I sign in with a wrong password + # Then I see an invalid password message + scenario 'user cannot sign in with wrong password' do + user = FactoryGirl.create(:user) + signin(user.email, 'invalidpass') + expect(page).to have_content I18n.t 'devise.failure.invalid', authentication_keys: 'email' + end + +end diff --git a/spec/features/users/sign_out_spec.rb b/spec/features/users/sign_out_spec.rb new file mode 100644 index 0000000..3f906b9 --- /dev/null +++ b/spec/features/users/sign_out_spec.rb @@ -0,0 +1,21 @@ +# Feature: Sign out +# As a user +# I want to sign out +# So I can protect my account from unauthorized access +feature 'Sign out', :devise do + + # Scenario: User signs out successfully + # Given I am signed in + # When I sign out + # Then I see a signed out message + scenario 'user signs out successfully' do + user = FactoryGirl.create(:user) + signin(user.email, user.password) + expect(page).to have_content I18n.t 'devise.sessions.signed_in' + click_link 'Sign out' + expect(page).to have_content I18n.t 'devise.sessions.signed_out' + end + +end + + diff --git a/spec/features/users/user_delete_spec.rb b/spec/features/users/user_delete_spec.rb new file mode 100644 index 0000000..7cd1c97 --- /dev/null +++ b/spec/features/users/user_delete_spec.rb @@ -0,0 +1,32 @@ +include Warden::Test::Helpers +Warden.test_mode! + +# Feature: User delete +# As a user +# I want to delete my user profile +# So I can close my account +feature 'User delete', :devise, :js do + + after(:each) do + Warden.test_reset! + end + + # Scenario: User can delete own account + # Given I am signed in + # When I delete my account + # Then I should see an account deleted message + scenario 'user can delete own account' do + skip 'skip a slow test' + user = FactoryGirl.create(:user) + login_as(user, :scope => :user) + visit edit_user_registration_path(user) + click_button 'Cancel my account' + page.driver.browser.switch_to.alert.accept + expect(page).to have_content I18n.t 'devise.registrations.destroyed' + end + +end + + + + diff --git a/spec/features/users/user_edit_spec.rb b/spec/features/users/user_edit_spec.rb new file mode 100644 index 0000000..f4acd38 --- /dev/null +++ b/spec/features/users/user_edit_spec.rb @@ -0,0 +1,42 @@ +include Warden::Test::Helpers +Warden.test_mode! + +# Feature: User edit +# As a user +# I want to edit my user profile +# So I can change my email address +feature 'User edit', :devise do + + after(:each) do + Warden.test_reset! + end + + # Scenario: User changes email address + # Given I am signed in + # When I change my email address + # Then I see an account updated message + scenario 'user changes email address' do + user = FactoryGirl.create(:user) + login_as(user, :scope => :user) + visit edit_user_registration_path(user) + fill_in 'Email', :with => 'newemail@example.com' + fill_in 'Current password', :with => user.password + click_button 'Update' + txts = [I18n.t( 'devise.registrations.updated'), I18n.t( 'devise.registrations.update_needs_confirmation')] + expect(page).to have_content(/.*#{txts[0]}.*|.*#{txts[1]}.*/) + end + + # Scenario: User cannot edit another user's profile + # Given I am signed in + # When I try to edit another user's profile + # Then I see my own 'edit profile' page + scenario "user cannot cannot edit another user's profile", :me do + me = FactoryGirl.create(:user) + other = FactoryGirl.create(:user, email: 'other@example.com') + login_as(me, :scope => :user) + visit edit_user_registration_path(other) + expect(page).to have_content 'Edit User' + expect(page).to have_field('Email', with: me.email) + end + +end diff --git a/spec/features/users/user_index_spec.rb b/spec/features/users/user_index_spec.rb new file mode 100644 index 0000000..6570e6f --- /dev/null +++ b/spec/features/users/user_index_spec.rb @@ -0,0 +1,25 @@ +include Warden::Test::Helpers +Warden.test_mode! + +# Feature: User index page +# As a user +# I want to see a list of users +# So I can see who has registered +feature 'User index page', :devise do + + after(:each) do + Warden.test_reset! + end + + # Scenario: User listed on index page + # Given I am signed in + # When I visit the user index page + # Then I see my own email address + scenario 'user sees own email address' do + user = FactoryGirl.create(:user) + login_as(user, scope: :user) + visit users_path + expect(page).to have_content user.email + end + +end diff --git a/spec/features/users/user_show_spec.rb b/spec/features/users/user_show_spec.rb new file mode 100644 index 0000000..aeee7d6 --- /dev/null +++ b/spec/features/users/user_show_spec.rb @@ -0,0 +1,39 @@ +include Warden::Test::Helpers +Warden.test_mode! + +# Feature: User profile page +# As a user +# I want to visit my user profile page +# So I can see my personal account data +feature 'User profile page', :devise do + + after(:each) do + Warden.test_reset! + end + + # Scenario: User sees own profile + # Given I am signed in + # When I visit the user profile page + # Then I see my own email address + scenario 'user sees own profile' do + user = FactoryGirl.create(:user) + login_as(user, :scope => :user) + visit user_path(user) + expect(page).to have_content 'User' + expect(page).to have_content user.email + end + + # Scenario: User cannot see another user's profile + # Given I am signed in + # When I visit another user's profile + # Then I see an 'access denied' message + scenario "user cannot see another user's profile" do + me = FactoryGirl.create(:user) + other = FactoryGirl.create(:user, email: 'other@example.com') + login_as(me, :scope => :user) + Capybara.current_session.driver.header 'Referer', root_path + visit user_path(other) + expect(page).to have_content 'Access denied.' + end + +end diff --git a/spec/features/visitors/sign_up_spec.rb b/spec/features/visitors/sign_up_spec.rb new file mode 100644 index 0000000..fc50163 --- /dev/null +++ b/spec/features/visitors/sign_up_spec.rb @@ -0,0 +1,62 @@ +# Feature: Sign up +# As a visitor +# I want to sign up +# So I can visit protected areas of the site +feature 'Sign Up', :devise do + + # Scenario: Visitor can sign up with valid email address and password + # Given I am not signed in + # When I sign up with a valid email address and password + # Then I see a successful sign up message + scenario 'visitor can sign up with valid email address and password' do + sign_up_with('test@example.com', 'please123', 'please123') + txts = [I18n.t( 'devise.registrations.signed_up'), I18n.t( 'devise.registrations.signed_up_but_unconfirmed')] + expect(page).to have_content(/.*#{txts[0]}.*|.*#{txts[1]}.*/) + end + + # Scenario: Visitor cannot sign up with invalid email address + # Given I am not signed in + # When I sign up with an invalid email address + # Then I see an invalid email message + scenario 'visitor cannot sign up with invalid email address' do + sign_up_with('bogus', 'please123', 'please123') + expect(page).to have_content 'Email is invalid' + end + + # Scenario: Visitor cannot sign up without password + # Given I am not signed in + # When I sign up without a password + # Then I see a missing password message + scenario 'visitor cannot sign up without password' do + sign_up_with('test@example.com', '', '') + expect(page).to have_content "Password can't be blank" + end + + # Scenario: Visitor cannot sign up with a short password + # Given I am not signed in + # When I sign up with a short password + # Then I see a 'too short password' message + scenario 'visitor cannot sign up with a short password' do + sign_up_with('test@example.com', 'please', 'please') + expect(page).to have_content "Password is too short" + end + + # Scenario: Visitor cannot sign up without password confirmation + # Given I am not signed in + # When I sign up without a password confirmation + # Then I see a missing password confirmation message + scenario 'visitor cannot sign up without password confirmation' do + sign_up_with('test@example.com', 'please123', '') + expect(page).to have_content "Password confirmation doesn't match" + end + + # Scenario: Visitor cannot sign up with mismatched password and confirmation + # Given I am not signed in + # When I sign up with a mismatched password confirmation + # Then I should see a mismatched password message + scenario 'visitor cannot sign up with mismatched password and confirmation' do + sign_up_with('test@example.com', 'please123', 'mismatch') + expect(page).to have_content "Password confirmation doesn't match" + end + +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 47a31bb..9b17618 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1,5 +1,13 @@ -require 'rails_helper' +describe User do + + before(:each) { @user = User.new(email: 'user@example.com') } + + subject { @user } + + it { should respond_to(:email) } + + it "#email returns a string" do + expect(@user.email).to match 'user@example.com' + end -RSpec.describe User, type: :model do - pending "add some examples to (or delete) #{__FILE__}" end diff --git a/spec/support/devise.rb b/spec/support/devise.rb new file mode 100644 index 0000000..3552bea --- /dev/null +++ b/spec/support/devise.rb @@ -0,0 +1,3 @@ +RSpec.configure do |config| + config.include Devise::TestHelpers, :type => :controller +end diff --git a/spec/support/helpers.rb b/spec/support/helpers.rb new file mode 100644 index 0000000..5e1beca --- /dev/null +++ b/spec/support/helpers.rb @@ -0,0 +1,4 @@ +require 'support/helpers/session_helpers' +RSpec.configure do |config| + config.include Features::SessionHelpers, type: :feature +end diff --git a/spec/support/helpers/session_helpers.rb b/spec/support/helpers/session_helpers.rb new file mode 100644 index 0000000..cb6b66f --- /dev/null +++ b/spec/support/helpers/session_helpers.rb @@ -0,0 +1,18 @@ +module Features + module SessionHelpers + def sign_up_with(email, password, confirmation) + visit new_user_registration_path + fill_in 'Email', with: email + fill_in 'Password', with: password + fill_in 'Password confirmation', :with => confirmation + click_button 'Sign up' + end + + def signin(email, password) + visit new_user_session_path + fill_in 'Email', with: email + fill_in 'Password', with: password + click_button 'Sign in' + end + end +end