From bcd88dc6fb218c314d2e6bd7a3d98096f4fbe1cb Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 12 Oct 2018 11:52:56 -0600 Subject: [PATCH 01/73] Adds Invitations schema, adds timestamps to Groups and Users. --- .../20181012171319_create_invitations.rb | 12 ++++++++++ ...181012172836_add_time_details_to_groups.rb | 8 +++++++ ...0181012173022_add_time_details_to_users.rb | 5 ++++ ...012174839_change_columns_to_invitations.rb | 6 +++++ db/schema.rb | 24 ++++++++++++++++++- 5 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20181012171319_create_invitations.rb create mode 100644 db/migrate/20181012172836_add_time_details_to_groups.rb create mode 100644 db/migrate/20181012173022_add_time_details_to_users.rb create mode 100644 db/migrate/20181012174839_change_columns_to_invitations.rb diff --git a/db/migrate/20181012171319_create_invitations.rb b/db/migrate/20181012171319_create_invitations.rb new file mode 100644 index 0000000..83f6ac5 --- /dev/null +++ b/db/migrate/20181012171319_create_invitations.rb @@ -0,0 +1,12 @@ +class CreateInvitations < ActiveRecord::Migration[5.2] + def change + create_table :invitations do |t| + t.references :group, foreign_key: true + t.references :receiver_id, foreign_key: {to_table: :users} + t.references :sender_id, foreign_key: {to_table: :users} + t.text :comment + t.boolean :accepted + t.timestamps + end + end +end diff --git a/db/migrate/20181012172836_add_time_details_to_groups.rb b/db/migrate/20181012172836_add_time_details_to_groups.rb new file mode 100644 index 0000000..58f88d0 --- /dev/null +++ b/db/migrate/20181012172836_add_time_details_to_groups.rb @@ -0,0 +1,8 @@ +class AddTimeDetailsToGroups < ActiveRecord::Migration[5.2] + def change + add_column :groups, :gift_due_date, :date + add_column :groups, :year, :date + add_timestamps :groups, null: true + + end +end diff --git a/db/migrate/20181012173022_add_time_details_to_users.rb b/db/migrate/20181012173022_add_time_details_to_users.rb new file mode 100644 index 0000000..d269291 --- /dev/null +++ b/db/migrate/20181012173022_add_time_details_to_users.rb @@ -0,0 +1,5 @@ +class AddTimeDetailsToUsers < ActiveRecord::Migration[5.2] + def change + add_timestamps :users, null: true + end +end diff --git a/db/migrate/20181012174839_change_columns_to_invitations.rb b/db/migrate/20181012174839_change_columns_to_invitations.rb new file mode 100644 index 0000000..a4d7b84 --- /dev/null +++ b/db/migrate/20181012174839_change_columns_to_invitations.rb @@ -0,0 +1,6 @@ +class ChangeColumnsToInvitations < ActiveRecord::Migration[5.2] + def change + rename_column(:invitations, :receiver_id_id, :receiver_id) + rename_column(:invitations, :sender_id_id, :sender_id) + end +end diff --git a/db/schema.rb b/db/schema.rb index 7843209..da459b4 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2018_10_01_004651) do +ActiveRecord::Schema.define(version: 2018_10_12_174839) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -19,9 +19,26 @@ t.text "name" t.string "description" t.bigint "owner_id" + t.date "gift_due_date" + t.date "year" + t.datetime "created_at" + t.datetime "updated_at" t.index ["owner_id"], name: "index_groups_on_owner_id" end + create_table "invitations", force: :cascade do |t| + t.bigint "group_id" + t.bigint "receiver_id" + t.bigint "sender_id" + t.text "comment" + t.boolean "accepted" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["group_id"], name: "index_invitations_on_group_id" + t.index ["receiver_id"], name: "index_invitations_on_receiver_id" + t.index ["sender_id"], name: "index_invitations_on_sender_id" + end + create_table "items", force: :cascade do |t| t.text "name" t.text "description" @@ -51,9 +68,14 @@ t.string "email" t.string "password_digest" t.string "password_confirmation" + t.datetime "created_at" + t.datetime "updated_at" end add_foreign_key "groups", "users", column: "owner_id" + add_foreign_key "invitations", "groups" + add_foreign_key "invitations", "users", column: "receiver_id" + add_foreign_key "invitations", "users", column: "sender_id" add_foreign_key "items", "lists", column: "lists_id" add_foreign_key "lists", "groups" add_foreign_key "lists", "users" From 901eda0335dbc565ff1e4209e9019e6b74399d03 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 12 Oct 2018 11:53:16 -0600 Subject: [PATCH 02/73] Changes profile link on page. --- app/views/lists/show.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/lists/show.html.erb b/app/views/lists/show.html.erb index 3027515..cc55420 100644 --- a/app/views/lists/show.html.erb +++ b/app/views/lists/show.html.erb @@ -1,6 +1,6 @@

<%= "#{@user.first_name} #{@user.last_name}'s wishlist for the #{@group.name} group" %>

-<%= link_to "#{@user.first_name} #{@user.last_name}'s list", user_path(@user) %> +<%= link_to "#{@user.first_name} #{@user.last_name}'s profile", user_path(@user) %>
<% if @authorized_user %> <%= link_to 'Create a new Wish list item', new_group_list_item_path(@group, @list) %> From 910e36fc2615a531ac3acfbded4312d321957f3d Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 12 Oct 2018 17:05:32 -0600 Subject: [PATCH 03/73] Adds invitations to user profiles. Group owners can invite users to a group. --- app/controllers/groups_controller.rb | 2 +- app/controllers/users_controller.rb | 18 ++++++++++++++++++ app/models/group.rb | 1 + app/models/user.rb | 1 + app/views/users/show.html.erb | 6 ++++++ config/routes.rb | 5 ++++- 6 files changed, 31 insertions(+), 2 deletions(-) diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index e361592..6861ec9 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -1,7 +1,7 @@ class GroupsController < ApplicationController before_action :set_group, only: [:show, :edit, :update, :destroy] - def index + def index # Delete for the future? @groups = Group.all end def new diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 053df3a..01f3b75 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -32,6 +32,10 @@ def profile def show @user = User.find(params[:id]) @authorized_user = authorized_user(@user) + if @invitable = invitable?(current_user, @user) + @invitation = Invitation.new + @current_user_owned_groups = Group.where("owner_id = ?", current_user.id) + end end def edit @@ -50,6 +54,20 @@ def update private + + def invitable?(logged_in_user, user_profile) + + # Group.joins(:users).where(id: [25, 28]).where(users: { id: 12 }) + + # byebug + if logged_in_user == user_profile + return false + elsif !Group.joins(:users).where(id: user_profile.groups.ids).where(users: {id: logged_in_user.id}).empty? + return false + end + return true + end + def set_user @user = current_user end diff --git a/app/models/group.rb b/app/models/group.rb index bfe65e7..9bcc24a 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -2,6 +2,7 @@ class Group < ApplicationRecord has_many :user_groups has_many :users, through: :user_groups has_many :lists + has_many :invitations belongs_to :user, foreign_key: :owner_id validates_uniqueness_of :name validates :description, presence: true diff --git a/app/models/user.rb b/app/models/user.rb index 6dfda25..b84cbfc 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -2,6 +2,7 @@ class User < ApplicationRecord has_many :user_groups has_many :groups, through: :user_groups has_many :lists + has_many :invitations has_secure_password validates_uniqueness_of :email validates :first_name, presence: true diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index 6bee869..6ea05b8 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -4,6 +4,12 @@ Name: <%= "#{@user.first_name} #{@user.last_name}" %> Email: <%= @user.email %>
+<% if @invitable %> + + <%= render partial: 'invitations/form' %> + +<% end %> + <% if @authorized_user %> <%= link_to 'Update Your Information', edit_user_path(@user.id) %> <% end %> diff --git a/config/routes.rb b/config/routes.rb index 059b3f9..f94f887 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -14,7 +14,10 @@ get '/login' => 'sessions#new', as: 'login' delete '/logout' => 'sessions#destroy', as: 'logout' - resources :users, only: [:show, :create, :edit, :update] + resources :users, only: [:show, :create, :edit, :update] do + resources :invitations, only: [:show, :create] + end + resources :groups do resources :lists do resources :items From 6255a32aeb6d6fb6d4376e3989634e80b4d0565b Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 12 Oct 2018 17:06:21 -0600 Subject: [PATCH 04/73] Adds invitation controller, models and form on user page. --- app/controllers/invitations_controller.rb | 17 +++++++++++++++++ app/models/invitation.rb | 7 +++++++ app/views/invitations/_form.html.erb | 12 ++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 app/controllers/invitations_controller.rb create mode 100644 app/models/invitation.rb create mode 100644 app/views/invitations/_form.html.erb diff --git a/app/controllers/invitations_controller.rb b/app/controllers/invitations_controller.rb new file mode 100644 index 0000000..798e50f --- /dev/null +++ b/app/controllers/invitations_controller.rb @@ -0,0 +1,17 @@ +class InvitationsController < ApplicationController + def create + @invitation = Invitation.new(invitation_params) + @invitation.sender_id = current_user.id + @invitation.receiver_id = params[:user_id] + @invitation.accepted = false + # byebug + @invitation.save + redirect_to user_path(@invitation.receiver_id) + end + + private + + def invitation_params + params.require(:invitation).permit(:comment, :group_id) + end +end diff --git a/app/models/invitation.rb b/app/models/invitation.rb new file mode 100644 index 0000000..898dbed --- /dev/null +++ b/app/models/invitation.rb @@ -0,0 +1,7 @@ +class Invitation < ApplicationRecord + belongs_to :user, foreign_key: :sender_id + belongs_to :user, foreign_key: :receiver_id + belongs_to :group + validates :comment, presence: true + validates :accepted, :inclusion => {:in => [true, false]} +end diff --git a/app/views/invitations/_form.html.erb b/app/views/invitations/_form.html.erb new file mode 100644 index 0000000..0e086e4 --- /dev/null +++ b/app/views/invitations/_form.html.erb @@ -0,0 +1,12 @@ +<%= form_for [ @user, @invitation ] do |f| %> +

+ <%= f.collection_select(:group_id, @current_user_owned_groups, :id, :name) %> +

+

+ <%= f.label :comment %>
+ <%= f.text_field :comment %> +

+

+ <%= f.submit 'Submit' %> +

+<% end %> From 7430c246b86401cb49b3072fe966b796e5e552ca Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 12 Oct 2018 18:57:23 -0600 Subject: [PATCH 05/73] Adds functionality to add an existing user via a selection menu to groups a user already owns. --- app/controllers/dashboard_controller.rb | 1 + app/controllers/groups_controller.rb | 4 +++- app/controllers/invitations_controller.rb | 29 +++++++++++++++++++++-- app/models/invitation.rb | 2 +- app/views/dashboard/show.html.erb | 16 +++++++++++++ config/routes.rb | 2 ++ 6 files changed, 50 insertions(+), 4 deletions(-) diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index bd85291..2ca349e 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -2,6 +2,7 @@ class DashboardController < ApplicationController def show if current_user @user = current_user + @invitations = Invitation.where("receiver_id = ? AND accepted IS NULL", @user.id) else redirect_to root_path flash[:warning] = 'You must be logged in first.' diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 6861ec9..434a29b 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -10,8 +10,9 @@ def new def create @group = Group.new(group_params) - @group.user_ids = current_user.id # Add user as a user + @group.user_ids << current_user.id # Add user as a user @group.owner_id = current_user.id # Add user as owner + current_user.groups << @group if @group.save create_list redirect_to group_path(@group) @@ -26,6 +27,7 @@ def show { user_id: current_user.id, group_id: @group.id }]) @authorized_user = authorized_user(User.find(@group.owner_id)) @belonging_user = belonging_user(@user_list) + # byebug end def edit diff --git a/app/controllers/invitations_controller.rb b/app/controllers/invitations_controller.rb index 798e50f..d678ae5 100644 --- a/app/controllers/invitations_controller.rb +++ b/app/controllers/invitations_controller.rb @@ -1,17 +1,42 @@ class InvitationsController < ApplicationController def create @invitation = Invitation.new(invitation_params) + # byebug @invitation.sender_id = current_user.id @invitation.receiver_id = params[:user_id] - @invitation.accepted = false - # byebug @invitation.save redirect_to user_path(@invitation.receiver_id) end + def edit # Accept route + # byebug + @user = User.find(params[:user_id]) + @group = Group.find(Invitation.find(params[:id]).group_id) + @invitation = Invitation.find(params[:id]) + @invitation.accepted = true + @invitation.save + @user.groups << @group + create_list + redirect_to dashboard_path + end + + def destroy # Decline route + @invitation = Invitation.find(params[:id]) + @invitation.accepted = false + @invitation.save + redirect_to dashboard_path + end + private def invitation_params params.require(:invitation).permit(:comment, :group_id) end + + def create_list + @list = List.new + @list.user_id = current_user.id + @list.group_id = @group.id + @list.save + end end diff --git a/app/models/invitation.rb b/app/models/invitation.rb index 898dbed..f7311a6 100644 --- a/app/models/invitation.rb +++ b/app/models/invitation.rb @@ -3,5 +3,5 @@ class Invitation < ApplicationRecord belongs_to :user, foreign_key: :receiver_id belongs_to :group validates :comment, presence: true - validates :accepted, :inclusion => {:in => [true, false]} + # validates :accepted, :inclusion => {:in => [true, false]} end diff --git a/app/views/dashboard/show.html.erb b/app/views/dashboard/show.html.erb index 5205f21..e4a8f3e 100644 --- a/app/views/dashboard/show.html.erb +++ b/app/views/dashboard/show.html.erb @@ -3,6 +3,22 @@ <%= link_to 'Profile', profile_path %> <%= link_to 'Sign Out', logout_path, method: :delete %> + <% if @invitations %> +

Invitations

+ <% @invitations.each do |invitation| %> + <% if invitation.accepted.nil? %> +

+ <%= "#{User.find(invitation.sender_id).first_name} has invited you to join #{Group.find(invitation.group_id).name}!" %> +

+

+ <%= invitation.comment %> +

+

+ <%= link_to "Accept", user_accept_path(@user.id, invitation.id)%> <%= link_to "Decline", user_decline_path(@user.id, invitation.id)%> +

+ <% end %> + <% end %> + <% end %>

My Groups

<%= link_to "Create a Group", new_group_path %>
diff --git a/config/routes.rb b/config/routes.rb index f94f887..baae14d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -16,6 +16,8 @@ resources :users, only: [:show, :create, :edit, :update] do resources :invitations, only: [:show, :create] + get '/accept/:id' => 'invitations#edit', as: 'accept' + get '/decline/:id' => 'invitations#destroy', as: 'decline' end resources :groups do From 2287d8c5e784143fc995b3154d5cf8ae7aa8d639 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 12 Oct 2018 18:59:09 -0600 Subject: [PATCH 06/73] Changes link text to profile. --- app/views/items/show.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/items/show.html.erb b/app/views/items/show.html.erb index 60bd91e..d7b0c6c 100644 --- a/app/views/items/show.html.erb +++ b/app/views/items/show.html.erb @@ -1,5 +1,5 @@

Item Information

-<%= link_to "#{@user.first_name} #{@user.last_name}'s item", user_path(@user) %> +<%= link_to "#{@user.first_name} #{@user.last_name}'s profile", user_path(@user) %>
  • Name: <%= "#{@item.name}" %>
  • Description: <%= "#{@item.description}" %>
  • From 66a3c579ff716bd564e1530609f2101724ca6e8f Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Mon, 22 Oct 2018 14:29:32 -0600 Subject: [PATCH 07/73] Due date visible on group show page. Group destroy functionality removes items, lists, invitations and the group when invoked. --- app/controllers/groups_controller.rb | 26 +++++++++++++++++++++----- app/views/groups/_form.html.erb | 4 ++++ app/views/groups/show.html.erb | 13 ++++++++++++- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 434a29b..6d7ee28 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -4,6 +4,7 @@ class GroupsController < ApplicationController def index # Delete for the future? @groups = Group.all end + def new @group = Group.new end @@ -23,11 +24,11 @@ def create end def show - @user_list = @group.lists.where(['user_id = :user_id and group_id = :group_id', - { user_id: current_user.id, group_id: @group.id }]) + @user_list = @group.lists.where( + [ 'user_id = :user_id and group_id = :group_id', + { user_id: current_user.id, group_id: @group.id } ] ) @authorized_user = authorized_user(User.find(@group.owner_id)) @belonging_user = belonging_user(@user_list) - # byebug end def edit @@ -44,7 +45,22 @@ def update end def destroy - # Destroy not working. Delete lists associated with group first. + @lists = List.where("group_id = :group_id", {group_id: @group.id}) + if !@lists.empty? + @lists.each do |list| + items = Item.where("lists_id = :list_id", {list_id: list.id}) + items.each { |item| item.destroy } + list.destroy + end + end + + @invitations = Invitation.where("group_id = :group_id", {group_id: @group.id}) + if !@invitations.empty? + @invitations.each do |invitation| + invitation.destroy + end + end + @group.destroy flash[:notice] = "Group Deleted!" redirect_to dashboard_path @@ -64,7 +80,7 @@ def set_group end def group_params - params.require(:group).permit(:name, :description, :owner_id) + params.require(:group).permit(:name, :description, :owner_id, :gift_due_date) end def belonging_user(user_list) diff --git a/app/views/groups/_form.html.erb b/app/views/groups/_form.html.erb index b9f470d..36cb5ae 100644 --- a/app/views/groups/_form.html.erb +++ b/app/views/groups/_form.html.erb @@ -7,6 +7,10 @@ <%= f.label :description %> <%= f.text_area :description %> +
    + <%= f.label :gift_due_date, 'Gift Due Date (YYYY/MM/DD)' %> + <%= f.text_field :gift_due_date %> +
    <%= f.submit %>
    diff --git a/app/views/groups/show.html.erb b/app/views/groups/show.html.erb index 2834447..1818efd 100644 --- a/app/views/groups/show.html.erb +++ b/app/views/groups/show.html.erb @@ -1,6 +1,12 @@

    <%= @group.name %>

    <%= @group.description %>
    +Created on: <%= @group.created_at %> +
    +Gift Due Date: <%= @group.gift_due_date %> +
    +Gift Exchange Year: <%= @group.gift_due_date.year if @group.gift_due_date %> +

    <% if @authorized_user %> <%= link_to 'Edit Group', edit_group_path %> @@ -20,7 +26,12 @@ Users in this group:
      <% @group.users.each do |user| %> <% wish_list = user.lists.where(['user_id = :user_id and group_id = :group_id', { user_id: user.id, group_id: @group.id }]) %> -
    • <%= "#{user.first_name} #{user.last_name}: " %> <%= link_to 'Profile', user_path(user.id) %> <%= link_to "Wish List", group_list_path(@group.id, wish_list[0].id) unless wish_list.empty? %>
    • +
    • + <%= "#{user.first_name} #{user.last_name}: " %> + <%= link_to 'Profile', user_path(user.id) %> + <%= link_to "Wish List", group_list_path(@group.id, wish_list[0].id) unless wish_list.empty? %> + <%= "(Group Owner)" if @group.owner_id == user.id %> +
    • <% end %>
    From 6ff532b2f73e08e1cdbbb4620617989c2f6d51eb Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Mon, 22 Oct 2018 14:30:22 -0600 Subject: [PATCH 08/73] Adds 'Select Group' as default group selection. --- app/views/invitations/_form.html.erb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/invitations/_form.html.erb b/app/views/invitations/_form.html.erb index 0e086e4..05efc10 100644 --- a/app/views/invitations/_form.html.erb +++ b/app/views/invitations/_form.html.erb @@ -1,6 +1,7 @@ <%= form_for [ @user, @invitation ] do |f| %>

    - <%= f.collection_select(:group_id, @current_user_owned_groups, :id, :name) %> + <%= f.collection_select(:group_id, @current_user_owned_groups, :id, :name, + { prompt: 'Select Group' }) %>

    <%= f.label :comment %>
    From 95864d9d4a5fcddf18b73007b07619ef28930ac0 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Mon, 22 Oct 2018 17:48:04 -0600 Subject: [PATCH 09/73] Validates for gift date, raises a flash message when incorrectly entered. --- app/controllers/groups_controller.rb | 9 +++++---- app/models/group.rb | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 6d7ee28..b003ec9 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -4,7 +4,7 @@ class GroupsController < ApplicationController def index # Delete for the future? @groups = Group.all end - + def new @group = Group.new end @@ -13,12 +13,13 @@ def create @group = Group.new(group_params) @group.user_ids << current_user.id # Add user as a user @group.owner_id = current_user.id # Add user as owner - current_user.groups << @group - if @group.save + if @group.valid? + current_user.groups << @group + @group.save create_list redirect_to group_path(@group) else - flash[:notice] = 'The group name is already taken. Please choose another name.' + flash[:warning] = "The Gift Due Date can't be blank, or the Group Name is already taken." redirect_to new_group_path end end diff --git a/app/models/group.rb b/app/models/group.rb index 9bcc24a..cbb5f70 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -7,4 +7,5 @@ class Group < ApplicationRecord validates_uniqueness_of :name validates :description, presence: true validates :owner_id, presence: true + validates :gift_due_date, presence: true end From 3872404961ad9500b2510cdae1ca228e3c521bb4 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Mon, 22 Oct 2018 18:03:19 -0600 Subject: [PATCH 10/73] Adds group invitation list to a profile which can be added to a group. --- app/controllers/users_controller.rb | 27 ++++++++++++++------------- app/views/users/show.html.erb | 4 +--- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 01f3b75..ce039f0 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -32,9 +32,11 @@ def profile def show @user = User.find(params[:id]) @authorized_user = authorized_user(@user) - if @invitable = invitable?(current_user, @user) + @user_invitable_groups = invitable_groups + @group_invitations = !@user_invitable_groups.empty? && !@authorized_user + # Groups owned by the current user && it is not the current user's profile + if @group_invitations @invitation = Invitation.new - @current_user_owned_groups = Group.where("owner_id = ?", current_user.id) end end @@ -54,18 +56,17 @@ def update private - - def invitable?(logged_in_user, user_profile) - - # Group.joins(:users).where(id: [25, 28]).where(users: { id: 12 }) - - # byebug - if logged_in_user == user_profile - return false - elsif !Group.joins(:users).where(id: user_profile.groups.ids).where(users: {id: logged_in_user.id}).empty? - return false + def invitable_groups + Group.where("owner_id = ?", current_user.id).select do |group| + user_does_not_belong_to_group = !group.users.ids.include?(@user.id) + no_pending_user_invitations = user_invitations("group_id = ? AND receiver_id = ? AND accepted IS NULL", group.id, @user.id) + no_declined_user_invitations = user_invitations("group_id = ? AND receiver_id = ? AND accepted = false", group.id, @user.id) + user_does_not_belong_to_group && no_pending_user_invitations && no_declined_user_invitations end - return true + end + + def user_invitations(accepted_string, group, user) + Invitation.joins(:group).where([accepted_string, group, user,]).empty? end def set_user diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index 6ea05b8..69afa08 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -4,10 +4,8 @@ Name: <%= "#{@user.first_name} #{@user.last_name}" %> Email: <%= @user.email %>
    -<% if @invitable %> - +<% if @group_invitations %> <%= render partial: 'invitations/form' %> - <% end %> <% if @authorized_user %> From 492b12034272e97aea1ff41213befae73c610e6e Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Mon, 22 Oct 2018 18:05:09 -0600 Subject: [PATCH 11/73] Removes unneeded comments. --- app/controllers/invitations_controller.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/controllers/invitations_controller.rb b/app/controllers/invitations_controller.rb index d678ae5..61d7b9d 100644 --- a/app/controllers/invitations_controller.rb +++ b/app/controllers/invitations_controller.rb @@ -1,7 +1,6 @@ class InvitationsController < ApplicationController def create @invitation = Invitation.new(invitation_params) - # byebug @invitation.sender_id = current_user.id @invitation.receiver_id = params[:user_id] @invitation.save @@ -9,7 +8,6 @@ def create end def edit # Accept route - # byebug @user = User.find(params[:user_id]) @group = Group.find(Invitation.find(params[:id]).group_id) @invitation = Invitation.find(params[:id]) From c3a13042af0afe41dc07885e6f9e43078fc29fd3 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Mon, 22 Oct 2018 18:06:48 -0600 Subject: [PATCH 12/73] Adds links to invitation sender's profile and to the group page. --- app/views/dashboard/show.html.erb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/views/dashboard/show.html.erb b/app/views/dashboard/show.html.erb index e4a8f3e..9d929f9 100644 --- a/app/views/dashboard/show.html.erb +++ b/app/views/dashboard/show.html.erb @@ -8,7 +8,8 @@ <% @invitations.each do |invitation| %> <% if invitation.accepted.nil? %>

    - <%= "#{User.find(invitation.sender_id).first_name} has invited you to join #{Group.find(invitation.group_id).name}!" %> + <% user = User.find(invitation.sender_id) %> + <%= link_to "#{user.first_name} #{user.last_name}", user_path(invitation.sender_id) %><%= " has invited you to join the group "%><%= link_to "#{Group.find(invitation.group_id).name}!", group_path(invitation.group_id) %>

    <%= invitation.comment %> @@ -22,6 +23,7 @@

    My Groups

    <%= link_to "Create a Group", new_group_path %>
    +
    <% if !current_user.groups.nil? %> <%= render partial: 'users/groups', collection: current_user.groups %> <% else %> From d00859994a960b7a728f7011826d38dd298cccb4 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Mon, 22 Oct 2018 18:07:15 -0600 Subject: [PATCH 13/73] Adds spacing for readability. --- app/views/invitations/_form.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/invitations/_form.html.erb b/app/views/invitations/_form.html.erb index 05efc10..55352ee 100644 --- a/app/views/invitations/_form.html.erb +++ b/app/views/invitations/_form.html.erb @@ -1,6 +1,6 @@ <%= form_for [ @user, @invitation ] do |f| %>

    - <%= f.collection_select(:group_id, @current_user_owned_groups, :id, :name, + <%= f.collection_select(:group_id, @user_invitable_groups, :id, :name, { prompt: 'Select Group' }) %>

    From fe0469746426fcf73faf99f87061b96ca64c514a Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 24 Oct 2018 12:45:45 -0600 Subject: [PATCH 14/73] Moves invitations# accept, decline and invite to paths which make more sense. --- config/routes.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index baae14d..78b9d6d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -16,11 +16,13 @@ resources :users, only: [:show, :create, :edit, :update] do resources :invitations, only: [:show, :create] - get '/accept/:id' => 'invitations#edit', as: 'accept' - get '/decline/:id' => 'invitations#destroy', as: 'decline' end + get '/accept/:id' => 'invitations#accept', as: 'accept' + get '/decline/:id' => 'invitations#decline', as: 'decline' + resources :groups do + post '/invite' => 'invitations#invite', as: 'invite' resources :lists do resources :items end From 193e14a53f1b63f15e7bdaf6b8506c9483e2f7ce Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 24 Oct 2018 12:49:06 -0600 Subject: [PATCH 15/73] Renames edit and destroy actions. Creates invite action accessed from groups by group owner. --- app/controllers/invitations_controller.rb | 42 ++++++++++++++++++++--- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/app/controllers/invitations_controller.rb b/app/controllers/invitations_controller.rb index 61d7b9d..a48c578 100644 --- a/app/controllers/invitations_controller.rb +++ b/app/controllers/invitations_controller.rb @@ -7,10 +7,10 @@ def create redirect_to user_path(@invitation.receiver_id) end - def edit # Accept route - @user = User.find(params[:user_id]) - @group = Group.find(Invitation.find(params[:id]).group_id) + def accept @invitation = Invitation.find(params[:id]) + @user = User.find(@invitation.receiver_id) + @group = Group.find(@invitation.group_id) @invitation.accepted = true @invitation.save @user.groups << @group @@ -18,15 +18,49 @@ def edit # Accept route redirect_to dashboard_path end - def destroy # Decline route + def decline @invitation = Invitation.find(params[:id]) @invitation.accepted = false @invitation.save redirect_to dashboard_path end + def invite + # sent from the groups page, by the group owner + + # params[:invitation][:receiver_id] is a string for an email + receiver = User.where("email = :email_addr", { email_addr: params[:invitation][:receiver_id]})[0] + group = Group.find(params[:group_id]) + if receiver + no_pending_user_invitations = user_invitations("group_id = ? AND receiver_id = ? AND accepted IS NULL", group.id, receiver.id) + no_declined_user_invitations = user_invitations("group_id = ? AND receiver_id = ? AND accepted = false", group.id, receiver.id) + end + + if no_pending_user_invitations && no_declined_user_invitations + invitation = Invitation.new + invitation.group_id = group.id + invitation.receiver_id = receiver.id + invitation.sender_id = group.owner_id + invitation.comment = params[:invitation][:comment] + if invitation.save + flash[:notice] = 'Invitation sent.' + else + flash[:warning] = 'There was an error sending the invitation, please try again.' + end + else + flash[:notice] = "Invitation sent to user's email." + # Default failure behavior to not give away user's email + # Create a new user with this email address, eventually sending them an invitation email. + end + redirect_to group_path(group.id) + end + private + def user_invitations(accepted_string, group, user) + Invitation.joins(:group).where([accepted_string, group, user,]).empty? + end + def invitation_params params.require(:invitation).permit(:comment, :group_id) end From a01791a93745bf1e46167ca23c968864d4dff8ea Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 24 Oct 2018 12:50:57 -0600 Subject: [PATCH 16/73] Adds first/last name to invite title. --- app/views/users/show.html.erb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index 69afa08..db0059f 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -5,7 +5,8 @@ Email: <%= @user.email %>
    <% if @group_invitations %> - <%= render partial: 'invitations/form' %> +

    Invite <%= "#{@user.first_name} #{@user.last_name}" %> to a Group

    + <%= render partial: 'invitations/form' %> <% end %> <% if @authorized_user %> From 2644eee42375f8278a5c4d80a827fc8e4aca7d5c Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 24 Oct 2018 12:51:52 -0600 Subject: [PATCH 17/73] Modifies link_to paths for invitation accept and decline. --- app/views/dashboard/show.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/dashboard/show.html.erb b/app/views/dashboard/show.html.erb index 9d929f9..57ac1b4 100644 --- a/app/views/dashboard/show.html.erb +++ b/app/views/dashboard/show.html.erb @@ -15,7 +15,7 @@ <%= invitation.comment %>

    - <%= link_to "Accept", user_accept_path(@user.id, invitation.id)%> <%= link_to "Decline", user_decline_path(@user.id, invitation.id)%> + <%= link_to "Accept", accept_path(invitation.id)%> <%= link_to "Decline", decline_path(invitation.id)%>

    <% end %> <% end %> From 7407a8f80593027c85d3c6ce050fa14ecb49af10 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 24 Oct 2018 12:52:45 -0600 Subject: [PATCH 18/73] Adds invitation form for a group owner to send an invite. --- app/views/groups/_invitation_form.html.erb | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 app/views/groups/_invitation_form.html.erb diff --git a/app/views/groups/_invitation_form.html.erb b/app/views/groups/_invitation_form.html.erb new file mode 100644 index 0000000..00c63bc --- /dev/null +++ b/app/views/groups/_invitation_form.html.erb @@ -0,0 +1,13 @@ +<%= form_for :invitation, { url: group_invite_path(@group.id) } do |f| %> +

    + <%= f.label :receiver_id, 'Email' %> + <%= f.text_field :receiver_id %> +

    +

    + <%= f.label :comment, "Message" %>
    + <%= f.text_field :comment %> +

    +

    + <%= f.submit 'Submit' %> +

    +<% end %> From 2063a024dea6679e61c01542d0678c8e54914ee7 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 24 Oct 2018 12:53:20 -0600 Subject: [PATCH 19/73] Renames label to 'Message'. --- app/views/invitations/_form.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/invitations/_form.html.erb b/app/views/invitations/_form.html.erb index 55352ee..1b5e39a 100644 --- a/app/views/invitations/_form.html.erb +++ b/app/views/invitations/_form.html.erb @@ -4,7 +4,7 @@ { prompt: 'Select Group' }) %>

    - <%= f.label :comment %>
    + <%= f.label :comment, "Message" %>
    <%= f.text_field :comment %>

    From 585923e9f75f2cac59154343be94beb4ff3f9bcf Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 24 Oct 2018 12:54:00 -0600 Subject: [PATCH 20/73] Adds invitation form for a group owner to send an invite. --- app/views/groups/show.html.erb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/views/groups/show.html.erb b/app/views/groups/show.html.erb index 1818efd..51668f9 100644 --- a/app/views/groups/show.html.erb +++ b/app/views/groups/show.html.erb @@ -19,6 +19,14 @@ Gift Exchange Year: <%= @group.gift_due_date.year if @group.gift_due_date %> <% elsif @user_list.empty? && @belonging_user %> <%= link_to 'Create a Wish List', group_lists_path(@group), method: :post %> <% end %> +
    +
    + +<% if @group_owner %> +

    Send an invitation

    +<%= render partial: 'groups/invitation_form' %> + +<% end %>

    From 5c387dd0dcafc1f67a69c8fd4e67cf4d73b4d6ee Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 24 Oct 2018 12:56:50 -0600 Subject: [PATCH 21/73] Adds @group_owner to the view to display whether or not a user can send group invites. --- app/controllers/groups_controller.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index b003ec9..5c5201c 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -30,6 +30,9 @@ def show { user_id: current_user.id, group_id: @group.id } ] ) @authorized_user = authorized_user(User.find(@group.owner_id)) @belonging_user = belonging_user(@user_list) + if @group_owner = current_user.id == @group.owner_id + @invitation = Invitation.new + end end def edit From cc4151d3c4568ab53e8c1b4577ce0837cfc6acf1 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 24 Oct 2018 16:27:07 -0600 Subject: [PATCH 22/73] Adds seeds to database. --- Gemfile.lock | 18 ++++++++++-------- db/seeds.rb | 28 ++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index a40ff37..ad32cd1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -51,13 +51,14 @@ GEM msgpack (~> 1.0) builder (3.2.3) byebug (10.0.2) - capybara (3.8.2) + capybara (3.10.0) addressable mini_mime (>= 0.1.3) nokogiri (~> 1.8) rack (>= 1.6.0) rack-test (>= 0.6.3) - xpath (~> 3.1) + regexp_parser (~> 1.2) + xpath (~> 3.2) coffee-rails (4.2.2) coffee-script (>= 2.2.0) railties (>= 4.0.0) @@ -75,7 +76,7 @@ GEM ffi (1.9.25) globalid (0.4.1) activesupport (>= 4.2.0) - i18n (1.1.0) + i18n (1.1.1) concurrent-ruby (~> 1.0) jbuilder (2.7.0) activesupport (>= 4.2.0) @@ -89,7 +90,7 @@ GEM loofah (2.2.2) crass (~> 1.0.2) nokogiri (>= 1.5.9) - mail (2.7.0) + mail (2.7.1) mini_mime (>= 0.1.1) marcel (0.3.3) mimemagic (~> 0.3.2) @@ -101,7 +102,7 @@ GEM msgpack (1.2.4) multi_json (1.13.1) nio4r (2.3.1) - nokogiri (1.8.4) + nokogiri (1.8.5) mini_portile2 (~> 2.3.0) pg (1.1.3) public_suffix (3.0.3) @@ -137,15 +138,16 @@ GEM rb-fsevent (0.10.3) rb-inotify (0.9.10) ffi (>= 0.5.0, < 2) + regexp_parser (1.2.0) rspec-core (3.8.0) rspec-support (~> 3.8.0) - rspec-expectations (3.8.1) + rspec-expectations (3.8.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-mocks (3.8.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) - rspec-rails (3.8.0) + rspec-rails (3.8.1) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) @@ -188,7 +190,7 @@ GEM websocket-driver (0.7.0) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.3) - xpath (3.1.0) + xpath (3.2.0) nokogiri (~> 1.8) PLATFORMS diff --git a/db/seeds.rb b/db/seeds.rb index 0ec7c36..6e1cf22 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -6,8 +6,28 @@ # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) # Character.create(name: 'Luke', movie: movies.first) 10.times do - User.create!(first_name: Faker::LordOfTheRings.character, - last_name: Faker::LordOfTheRings.character, - email: Faker::SiliconValley.email, - password: Faker::LordOfTheRings.location) + first_name = Faker::LordOfTheRings.character + last_name = Faker::Name.last_name + user = User.create!(first_name: first_name, + last_name: last_name, + email: "#{first_name}@#{last_name}.com", + password: 'pass', + password_confirmation: 'pass') + + group = Group.create!(name: Faker::MostInterestingManInTheWorld.unique.quote, + description: Faker::GameOfThrones.quote, + owner_id: user.id, + gift_due_date: "#{Faker::Number.between(2018, 2020)}/#{Faker::Number.between(1, 12)}/#{Faker::Number.between(1, 28)}") + + group.user_ids << user.id + user.groups << group + + list = List.create!(user_id: user.id, group_id: group.id) + 5.times do + item = Item.create!(name: Faker::Fallout.character, + description: Faker::FamousLastWords.last_words, + note: Faker::Myst.quote, + size: Faker::Measurement.weight, + lists_id: list.id) + end end From 4c2350d82f7a31afe0e3b999922c9870033ef471 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 24 Oct 2018 16:27:28 -0600 Subject: [PATCH 23/73] Adds login check for groups#show. --- app/controllers/groups_controller.rb | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 5c5201c..ff11752 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -25,13 +25,18 @@ def create end def show - @user_list = @group.lists.where( - [ 'user_id = :user_id and group_id = :group_id', - { user_id: current_user.id, group_id: @group.id } ] ) - @authorized_user = authorized_user(User.find(@group.owner_id)) - @belonging_user = belonging_user(@user_list) - if @group_owner = current_user.id == @group.owner_id - @invitation = Invitation.new + if !current_user + flash[:warning] = "You need to be logged in first." + redirect_to root_path + else + @user_list = @group.lists.where( + [ 'user_id = :user_id and group_id = :group_id', + { user_id: current_user.id, group_id: @group.id } ] ) + @authorized_user = authorized_user(User.find(@group.owner_id)) + @belonging_user = belonging_user(@user_list) + if @group_owner = current_user.id == @group.owner_id + @invitation = Invitation.new + end end end From 2f0278bb1c9476126419af97d9f4428f56968716 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 24 Oct 2018 17:37:23 -0600 Subject: [PATCH 24/73] Adds database_cleaner gem. --- Gemfile | 4 ++++ Gemfile.lock | 2 ++ 2 files changed, 6 insertions(+) diff --git a/Gemfile b/Gemfile index 83fd199..6d7b72a 100644 --- a/Gemfile +++ b/Gemfile @@ -44,6 +44,10 @@ group :development, :test do gem 'launchy' end +group :test do + gem 'database_cleaner' +end + group :development do # Access an interactive console on exception pages or by calling 'console' anywhere in the code. gem 'web-console', '>= 3.3.0' diff --git a/Gemfile.lock b/Gemfile.lock index ad32cd1..192661b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -68,6 +68,7 @@ GEM coffee-script-source (1.12.2) concurrent-ruby (1.0.5) crass (1.0.4) + database_cleaner (1.7.0) diff-lcs (1.3) erubi (1.7.1) execjs (2.7.0) @@ -202,6 +203,7 @@ DEPENDENCIES byebug capybara coffee-rails (~> 4.2) + database_cleaner faker jbuilder (~> 2.5) launchy From 6738e1c8ff752b425b123e469f78969543b2bfbe Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 24 Oct 2018 18:59:43 -0600 Subject: [PATCH 25/73] Adds Model tests. --- spec/models/group_spec.rb | 53 ++++++++++++++++++++++++++++++++++ spec/models/invitation_spec.rb | 37 ++++++++++++++++++++++++ spec/models/item_spec.rb | 32 ++++++++++++++++++++ spec/models/list_spec.rb | 27 +++++++++++++++++ spec/models/user_group_spec.rb | 15 ++++++++++ spec/models/user_spec.rb | 42 ++++++++++++++++++++------- 6 files changed, 196 insertions(+), 10 deletions(-) create mode 100644 spec/models/group_spec.rb create mode 100644 spec/models/invitation_spec.rb create mode 100644 spec/models/item_spec.rb create mode 100644 spec/models/list_spec.rb create mode 100644 spec/models/user_group_spec.rb diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb new file mode 100644 index 0000000..b168a5b --- /dev/null +++ b/spec/models/group_spec.rb @@ -0,0 +1,53 @@ +require 'rails_helper' + +describe Group do + context 'validations' do + it 'validates description needs to be present' do + g = Group.new(name: 'This one Group', description: '', owner_id: 3, gift_due_date: '2018/12/31') + expect(g.valid?).to eq false + end + + it 'validates owner_id needs to be present' do + g = Group.new(name: 'This one Group', description: 'Here is a description', owner_id: nil, gift_due_date: '2018/12/31') + expect(g.valid?).to eq false + end + + it 'validates gift_due_date needs to be present' do + g = Group.new(name: 'This one Group', description: 'Here is a description', owner_id: 3, gift_due_date: '') + expect(g.valid?).to eq false + end + + it 'validates name is unique' do + Group.create(name: 'This one Group', description: 'Here is a description', owner_id: 3, gift_due_date: '2018/12/31') + g = Group.new(name: 'This one Group', description: 'Here is a description', owner_id: 3, gift_due_date: '2018/12/31') + expect(g.valid?).to eq false + end + end + + context 'associations' do + it 'has many lists' do + assc = Group.reflect_on_association(:lists) + expect(assc.macro).to eq :has_many + end + + it 'has many user_groups' do + assc = Group.reflect_on_association(:user_groups) + expect(assc.macro).to eq :has_many + end + + it 'has many users' do + assc = Group.reflect_on_association(:users) + expect(assc.macro).to eq :has_many + end + + it 'has many invitations' do + assc = Group.reflect_on_association(:invitations) + expect(assc.macro).to eq :has_many + end + + it 'belongs to user' do + assc = Group.reflect_on_association(:user) + expect(assc.macro).to eq :belongs_to + end + end +end diff --git a/spec/models/invitation_spec.rb b/spec/models/invitation_spec.rb new file mode 100644 index 0000000..084f86e --- /dev/null +++ b/spec/models/invitation_spec.rb @@ -0,0 +1,37 @@ +require 'rails_helper' + +describe Invitation do + context 'validations' do + it 'validates group_id needs to be present' do + i = Invitation.new(group_id: nil, sender_id: 7, receiver_id: 5, comment: 'Welcome to the group') + expect(i.valid?).to eq false + end + + it 'validates sender_id needs to be present' do + i = Invitation.new(group_id: 3, sender_id: nil, receiver_id: 5, comment: 'Welcome to the group') + expect(i.valid?).to eq false + end + + it 'validates recevier_id needs to be present' do + i = Invitation.new(group_id: 3, sender_id: 7, receiver_id: nil, comment: 'Welcome to the group') + expect(i.valid?).to eq false + end + + it 'validates comment needs to be present' do + i = Invitation.new(group_id: 3, sender_id: 7, receiver_id: 5, comment: nil) + expect(i.valid?).to eq false + end + end + + context 'associations' do + it 'belongs to user' do + assc = Invitation.reflect_on_association(:user) + expect(assc.macro).to eq :belongs_to + end + + it 'belongs to group' do + assc = Invitation.reflect_on_association(:group) + expect(assc.macro).to eq :belongs_to + end + end +end diff --git a/spec/models/item_spec.rb b/spec/models/item_spec.rb new file mode 100644 index 0000000..7737862 --- /dev/null +++ b/spec/models/item_spec.rb @@ -0,0 +1,32 @@ +require 'rails_helper' + +describe Item do + context 'validations' do + it 'validates name needs to be present' do + i = Item.new(name: nil, description: 'my lovely gift', size: 'Large', note: 'Apples') + expect(i.valid?).to eq false + end + + it 'validates description needs to be present' do + i = Item.new(name: 'Purse', description: nil, size: 'Large', note: 'Apples') + expect(i.valid?).to eq false + end + + it 'validates size is optional' do + i = Item.new(name: 'Purse', description: 'my lovely gift', size: '', note: 'Apples') + expect(i.valid?).to eq true + end + + it 'validates note is optional' do + i = Item.new(name: 'Purse', description: 'my lovely gift', size: 'Window', note: '') + expect(i.valid?).to eq true + end + end + + context 'associations' do + it 'has one list' do + assc = Item.reflect_on_association(:list) + expect(assc.macro).to eq :has_one + end + end +end diff --git a/spec/models/list_spec.rb b/spec/models/list_spec.rb new file mode 100644 index 0000000..02a5e08 --- /dev/null +++ b/spec/models/list_spec.rb @@ -0,0 +1,27 @@ +require 'rails_helper' + +describe List do + context 'validations' do + it 'validates user_id needs to be present' do + l = List.new(user_id: nil, group_id: 4) + expect(l.valid?).to eq false + end + + it 'validates group_id needs to be present' do + l = List.new(user_id: 4, group_id: nil) + expect(l.valid?).to eq false + end + end + + context 'associations' do + it 'belongs to user' do + assc = List.reflect_on_association(:user) + expect(assc.macro).to eq :belongs_to + end + + it 'belongs to group' do + assc = List.reflect_on_association(:group) + expect(assc.macro).to eq :belongs_to + end + end +end diff --git a/spec/models/user_group_spec.rb b/spec/models/user_group_spec.rb new file mode 100644 index 0000000..2ff1402 --- /dev/null +++ b/spec/models/user_group_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +describe UserGroup do + context 'associations' do + it 'belongs to user' do + assc = UserGroup.reflect_on_association(:user) + expect(assc.macro).to eq :belongs_to + end + + it 'belongs to group' do + assc = UserGroup.reflect_on_association(:group) + expect(assc.macro).to eq :belongs_to + end + end +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index e47d62c..149290e 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -8,20 +8,20 @@ expect(u.authenticate('password123')).to eq u end - describe 'validations' do - it 'validates email is present' do - u = User.new(first_name: 'Raz', last_name: 'Z', email: '', password: 'passpass') - expect(u.valid?).to eq false - end - - it 'validates first name is present' do + context 'validations' do + it 'validates first name needs to be present' do u = User.new(first_name: nil, last_name: 'Z', email: 'email@email.email', password: 'passpass') - expect(u.valid?).to be_falsey + expect(u.valid?).to be false end - it 'validates last name is present' do + it 'validates last name needs to be present' do u = User.new(first_name: 'Razz', last_name: nil, email: 'email@email.email', password: 'passpass') - expect(u.valid?).to be_falsey + expect(u.valid?).to be false + end + + it 'validates email needs to be present' do + u = User.new(first_name: 'Raz', last_name: 'Z', email: '', password: 'passpass') + expect(u.valid?).to eq false end it 'validates email is unique' do @@ -30,4 +30,26 @@ expect(v.valid?).to eq false end end + + context 'associations' do + it 'has many lists' do + assc = User.reflect_on_association(:lists) + expect(assc.macro).to eq :has_many + end + + it 'has many groups' do + assc = User.reflect_on_association(:groups) + expect(assc.macro).to eq :has_many + end + + it 'has many invitations' do + assc = User.reflect_on_association(:invitations) + expect(assc.macro).to eq :has_many + end + + it 'has many user_groups' do + assc = User.reflect_on_association(:user_groups) + expect(assc.macro).to eq :has_many + end + end end From afafd601444b2abddc25deb6bb123cebc24356c4 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 24 Oct 2018 19:00:31 -0600 Subject: [PATCH 26/73] Removes comment. --- app/models/invitation.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/models/invitation.rb b/app/models/invitation.rb index f7311a6..5cf9a17 100644 --- a/app/models/invitation.rb +++ b/app/models/invitation.rb @@ -3,5 +3,4 @@ class Invitation < ApplicationRecord belongs_to :user, foreign_key: :receiver_id belongs_to :group validates :comment, presence: true - # validates :accepted, :inclusion => {:in => [true, false]} end From e03e2702dbe90512e4e74b5538aa309c6be7cb43 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 24 Oct 2018 19:01:56 -0600 Subject: [PATCH 27/73] Adds database cleaner and adjusts config files. --- spec/rails_helper.rb | 4 +- spec/spec_helper.rb | 18 ++++---- spec/support/database_cleaner.rb | 71 ++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 11 deletions(-) create mode 100644 spec/support/database_cleaner.rb diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index bbe1ba5..4cc5f36 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -20,7 +20,7 @@ # directory. Alternatively, in the individual `*_spec.rb` files, manually # require only the support files necessary. # -# Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } +Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } # Checks for pending migrations and applies them before tests are run. # If you are not using ActiveRecord, you can remove this line. @@ -33,7 +33,7 @@ # If you're not using ActiveRecord, or you'd prefer not to run each of your # examples within a transaction, remove the following line or assign false # instead of true. - config.use_transactional_fixtures = true + # config.use_transactional_fixtures = true # RSpec Rails can automatically mix in different behaviours to your tests # based on their file location, for example enabling you to call `get` and diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 7591dc7..2faa2d0 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -47,40 +47,40 @@ # The settings below are suggested to provide a good initial experience # with RSpec, but feel free to customize to your heart's content. -=begin +begin # This allows you to limit a spec run to individual examples or groups # you care about by tagging them with `:focus` metadata. When nothing # is tagged with `:focus`, all examples get run. RSpec also provides # aliases for `it`, `describe`, and `context` that include `:focus` # metadata: `fit`, `fdescribe` and `fcontext`, respectively. - config.filter_run_when_matching :focus + # config.filter_run_when_matching :focus # Allows RSpec to persist some state between runs in order to support # the `--only-failures` and `--next-failure` CLI options. We recommend # you configure your source control system to ignore this file. - config.example_status_persistence_file_path = "spec/examples.txt" + # config.example_status_persistence_file_path = "spec/examples.txt" # Limits the available syntax to the non-monkey patched syntax that is # recommended. For more details, see: # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode - config.disable_monkey_patching! + # config.disable_monkey_patching! # Many RSpec users commonly either run the entire suite or an individual # file, and it's useful to allow more verbose output when running an # individual spec file. - if config.files_to_run.one? + # if config.files_to_run.one? # Use the documentation formatter for detailed output, # unless a formatter has already been configured # (e.g. via a command-line flag). - config.default_formatter = "doc" - end + # config.default_formatter = "doc" + # end # Print the 10 slowest examples and example groups at the # end of the spec run, to help surface which specs are running # particularly slow. - config.profile_examples = 10 + # config.profile_examples = 10 # Run specs in random order to surface order dependencies. If you find an # order dependency and want to debug it, you can fix the order by providing @@ -93,5 +93,5 @@ # test failures related to randomization by passing the same `--seed` value # as the one that triggered the failure. Kernel.srand config.seed -=end +end end diff --git a/spec/support/database_cleaner.rb b/spec/support/database_cleaner.rb new file mode 100644 index 0000000..95fb896 --- /dev/null +++ b/spec/support/database_cleaner.rb @@ -0,0 +1,71 @@ +# Installing database_cleaner: + +# 0. Check spec/support dir is auto-required in spec/rails_helper.rb. +# +# 1. Add database_cleaner to Gemfile: +# +# group :test do +# gem 'database_cleaner' +# end + +# 2. IMPORTANT! Delete the "config.use_transactional_fixtures = ..." line +# in spec/rails_helper.rb (we're going to configure it in this file you're +# reading instead). + +# 3. Create a file like this one you're reading in spec/support/database_cleaner.rb: +RSpec.configure do |config| + config.use_transactional_fixtures = false + + config.before(:suite) do + if config.use_transactional_fixtures? + raise(<<-MSG) + Delete line `config.use_transactional_fixtures = true` from rails_helper.rb + (or set it to false) to prevent uncommitted transactions being used in + JavaScript-dependent specs. + During testing, the Ruby app server that the JavaScript browser driver + connects to uses a different database connection to the database connection + used by the spec. + + This Ruby app server database connection would not be able to see data that + has been setup by the spec's database connection inside an uncommitted + transaction. + Disabling the use_transactional_fixtures setting helps avoid uncommitted + transactions in JavaScript-dependent specs, meaning that the Ruby app server + database connection can see any data set up by the specs. + MSG + + end + end + + config.before(:suite) do + DatabaseCleaner.clean_with(:truncation) + end + + config.before(:each) do + DatabaseCleaner.strategy = :transaction + end + + config.before(:each, type: :feature) do + # :rack_test driver's Rack app under test shares database connection + # with the specs, so we can use transaction strategy for speed. + driver_shares_db_connection_with_specs = Capybara.current_driver == :rack_test + + if driver_shares_db_connection_with_specs + DatabaseCleaner.strategy = :transaction + else + # Non-:rack_test driver is probably a driver for a JavaScript browser + # with a Rack app under test that does *not* share a database + # connection with the specs, so we must use truncation strategy. + DatabaseCleaner.strategy = :truncation + end + end + + config.before(:each) do + DatabaseCleaner.start + end + + config.after(:each) do + DatabaseCleaner.clean + end + +end From 2be5ab691faa51b4ed0f7d0571f3f47e0c27aaf2 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 24 Oct 2018 19:02:36 -0600 Subject: [PATCH 28/73] These tests now pass. --- spec/features/groups/group_spec.rb | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/spec/features/groups/group_spec.rb b/spec/features/groups/group_spec.rb index b24457b..cdf8a1f 100644 --- a/spec/features/groups/group_spec.rb +++ b/spec/features/groups/group_spec.rb @@ -1,18 +1,32 @@ require 'rails_helper' -xdescribe 'groups' do +describe 'group creation' do before { @user = User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') } - context 'are created' do + context 'created' do it 'correctly' do - @group_info = { name: 'This sdfis one adwesome grfoup', description: 'What a description' } + @group_info = { name: 'This is one awesome group!', + description: 'What a description', + due_date: '2019-02-28' } allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(@user) visit new_group_path fill_in('group_name', with: @group_info[:name]) fill_in('group_description', with: @group_info[:description]) + fill_in('group_gift_due_date', with: @group_info[:due_date]) click_on 'Create Group' + expect(page).to have_content "#{@group_info[:name]}" expect(page).to have_content "#{@group_info[:description]}" + expect(page).to have_content "#{@group_info[:due_date]}" + end + + it 'incorrectly' do + allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(@user) + visit new_group_path + fill_in('group_name', with: '') + fill_in('group_description', with: '') + click_on 'Create Group' + expect(page).to have_content "The Gift Due Date can't be blank, or the Group Name is already taken." end end end From 96b9af1c38601be3604321683d50fc7f1845d067 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 24 Oct 2018 19:03:38 -0600 Subject: [PATCH 29/73] WIP --- spec/features/items/user_creates_item_spec.rb | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 spec/features/items/user_creates_item_spec.rb diff --git a/spec/features/items/user_creates_item_spec.rb b/spec/features/items/user_creates_item_spec.rb new file mode 100644 index 0000000..e8b4003 --- /dev/null +++ b/spec/features/items/user_creates_item_spec.rb @@ -0,0 +1,7 @@ +require 'rails_helper' + +describe 'item creation' do + + + +end From 6dc04464e8447abc267d47dd06cfd12b557af280 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Thu, 25 Oct 2018 09:51:55 -0600 Subject: [PATCH 30/73] Adds tests, utilizing let. --- spec/features/groups/group_spec.rb | 59 ++++++++++++++++---- spec/features/session/user_can_login_spec.rb | 13 +++-- 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/spec/features/groups/group_spec.rb b/spec/features/groups/group_spec.rb index cdf8a1f..ad0f742 100644 --- a/spec/features/groups/group_spec.rb +++ b/spec/features/groups/group_spec.rb @@ -1,26 +1,25 @@ require 'rails_helper' describe 'group creation' do - before { @user = User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') } + context 'created' do + let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') } + let(:group_info) { Group.create(name: 'This is one awesome group!', description: 'What a description', gift_due_date: '2019-02-28') } it 'correctly' do - @group_info = { name: 'This is one awesome group!', - description: 'What a description', - due_date: '2019-02-28' } - allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(@user) + allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(user) visit new_group_path - fill_in('group_name', with: @group_info[:name]) - fill_in('group_description', with: @group_info[:description]) - fill_in('group_gift_due_date', with: @group_info[:due_date]) + fill_in('group_name', with: group_info.name) + fill_in('group_description', with: group_info.description) + fill_in('group_gift_due_date', with: group_info.gift_due_date) click_on 'Create Group' - expect(page).to have_content "#{@group_info[:name]}" - expect(page).to have_content "#{@group_info[:description]}" - expect(page).to have_content "#{@group_info[:due_date]}" + expect(page).to have_content group_info.name + expect(page).to have_content group_info.description + expect(page).to have_content group_info.gift_due_date end it 'incorrectly' do - allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(@user) + allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(user) visit new_group_path fill_in('group_name', with: '') fill_in('group_description', with: '') @@ -29,4 +28,40 @@ expect(page).to have_content "The Gift Due Date can't be blank, or the Group Name is already taken." end end + + context 'while' do + let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') } + let(:group) { Group.create(name: 'My first group creation', description: 'Whoever wants to join', gift_due_date: '2018/12/31') } + + it 'logged in' do + visit login_path + fill_in 'Email', with: user.email + fill_in 'Password', with: user.password + click_on 'Log In' + + expect(current_path).to eq dashboard_path + expect(page).to have_content 'Welcome, Raa.' + click_on 'Create a Group' + + expect(current_path).to eq new_group_path + fill_in('Name', with: group.name) + fill_in('Description', with: group.description) + fill_in('Gift Due Date', with: group.gift_due_date.to_default_s) + click_on 'Create Group' + + expect(page).to have_content group.name + expect(page).to have_content group.description + expect(page).to have_content group.gift_due_date.to_default_s + expect(page).to have_content 'Edit Group', 'Delete Group' + expect(page).to have_content "#{user.first_name} #{user.last_name}:" + expect(page).to have_content '(Group Owner)' + expect(page).to have_content 'Send an invitation', 'View your Wish List' + end + + it 'logged out' do + visit profile_path + expect(current_path).to eq root_path + expect(page).to have_content 'You must be logged in first.' + end + end end diff --git a/spec/features/session/user_can_login_spec.rb b/spec/features/session/user_can_login_spec.rb index 6254726..6854f5a 100644 --- a/spec/features/session/user_can_login_spec.rb +++ b/spec/features/session/user_can_login_spec.rb @@ -5,27 +5,28 @@ # before { @user = User.create() } # let(:user) { User.create() } # let!(:user) { User.create() } - before { @user = User.create(first_name: 'Test', last_name: 'Ing', email: 'test@ing.com', password: 'password') } + # before { @user = User.create(first_name: 'Test', last_name: 'Ing', email: 'test@ing.com', password: 'password') } + let(:user) { User.create(first_name: 'Test', last_name: 'Ing', email: 'test@ing.com', password: 'password') } context 'with correct login information' do it 'can login' do visit new_session_path - fill_in('email', with: @user.email) - fill_in('password', with: @user.password) + fill_in('email', with: user.email) + fill_in('password', with: user.password) click_on 'Log In' expect(current_path).to eq dashboard_path + expect(page).to have_content 'Welcome, Test.' end end context 'with incorrect login information' do it 'rejects login' do visit new_session_path - fill_in('email', with: @user.email) - fill_in('password', with: @user.first_name) + fill_in('email', with: user.email) + fill_in('password', with: user.first_name) click_on 'Log In' expect(current_path).to eq sessions_path expect(page).to have_content 'Email or password is invalid' - end end end From daaeb2b6672d622acd9593c0fb6eb605cd611dd6 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Thu, 25 Oct 2018 09:52:41 -0600 Subject: [PATCH 31/73] Adds support method to Features module. --- spec/rails_helper.rb | 2 ++ spec/support/features/sign_in.rb | 11 +++++++++++ 2 files changed, 13 insertions(+) create mode 100644 spec/support/features/sign_in.rb diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 4cc5f36..c614c4c 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -54,4 +54,6 @@ config.filter_rails_from_backtrace! # arbitrary gems may also be filtered via: # config.filter_gems_from_backtrace("gem name") + + config.include Features, type: :feature end diff --git a/spec/support/features/sign_in.rb b/spec/support/features/sign_in.rb new file mode 100644 index 0000000..df510f4 --- /dev/null +++ b/spec/support/features/sign_in.rb @@ -0,0 +1,11 @@ +module Features + def sign_in +# before { @user = User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') } + @user = User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') + + visit login_path + fill_in 'Email', with: @user.email + fill_in 'Password', with: 'pass' + click_on 'Log In' + end +end From 3571312f8f19227cf676dfaae2d6b0df06867a2c Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Thu, 25 Oct 2018 10:10:09 -0600 Subject: [PATCH 32/73] Uses #find_by instead of #where. --- app/controllers/invitations_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/invitations_controller.rb b/app/controllers/invitations_controller.rb index a48c578..f021e33 100644 --- a/app/controllers/invitations_controller.rb +++ b/app/controllers/invitations_controller.rb @@ -29,7 +29,7 @@ def invite # sent from the groups page, by the group owner # params[:invitation][:receiver_id] is a string for an email - receiver = User.where("email = :email_addr", { email_addr: params[:invitation][:receiver_id]})[0] + receiver = User.find_by(email: params[:invitation][:receiver_id]) group = Group.find(params[:group_id]) if receiver no_pending_user_invitations = user_invitations("group_id = ? AND receiver_id = ? AND accepted IS NULL", group.id, receiver.id) From 7665c5f6f95a424f0f128aa26dd04b75d34183e9 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Thu, 25 Oct 2018 12:11:00 -0600 Subject: [PATCH 33/73] Adds logging in tests, checking for email case. --- spec/features/session/user_can_login_spec.rb | 9 + spec/features/users/user_can_signup_spec.rb | 240 ++++++++++++++++++- 2 files changed, 239 insertions(+), 10 deletions(-) diff --git a/spec/features/session/user_can_login_spec.rb b/spec/features/session/user_can_login_spec.rb index 6854f5a..8d7df17 100644 --- a/spec/features/session/user_can_login_spec.rb +++ b/spec/features/session/user_can_login_spec.rb @@ -17,6 +17,15 @@ expect(current_path).to eq dashboard_path expect(page).to have_content 'Welcome, Test.' end + it 'but wrong case' do + visit new_session_path + fill_in('email', with: user.email.upcase) + fill_in('password', with: user.password) + click_on 'Log In' + + expect(current_path). to eq dashboard_path + expect(page).to have_content 'Welcome, Test.' + end end context 'with incorrect login information' do it 'rejects login' do diff --git a/spec/features/users/user_can_signup_spec.rb b/spec/features/users/user_can_signup_spec.rb index a848f9f..bee5e1a 100644 --- a/spec/features/users/user_can_signup_spec.rb +++ b/spec/features/users/user_can_signup_spec.rb @@ -1,25 +1,245 @@ require 'rails_helper' describe 'user signup' do - context 'with a new user' do - it 'they can create an account' do + context 'a new user' do + before { @user = {first_name: 'Joey', last_name: 'Ralf', email: 'emati@l.com', password: 'pass', password_confirmation: 'pass' }} + it 'can create an account' do visit root_path click_on 'Sign Up' expect(current_path).to eq signup_path - fill_in('user[first_name]', with: 'Ra') - fill_in('user[last_name]', with: 'Zz') - fill_in('user[email]', with: 'email@email.email') - fill_in('user[password]', with: 'passpass') - fill_in('user[password_confirmation]', with: 'passpass') + fill_in('user[first_name]', with: @user[:first_name]) + fill_in('user[last_name]', with: @user[:last_name]) + fill_in('user[email]', with: @user[:email]); + fill_in('user[password]', with: @user[:password]) + fill_in('user[password_confirmation]', with: @user[:password]) click_on 'Create User' expect(current_path).to eq login_path - fill_in('email', with: 'email@email.email') - fill_in('password', with: 'passpass') + fill_in('Email', with: @user[:email]) + fill_in('Password', with: @user[:password]) click_on 'Log In' expect(current_path).to eq dashboard_path - expect(page).to have_content 'Welcome, Ra.' + expect(page).to have_content "Welcome, #{@user[:first_name]}." + expect(page).to have_link 'Sign Out' + expect(page).to have_link 'Profile' + expect(page).not_to have_link 'Log In' + expect(page).not_to have_link 'Sign Up' + end + end + + context 'with an email' do + let(:user) { User.create(first_name: 'Joey', last_name: 'Ralf', email: 'eMaIl@EmAiL.emaILE', password: 'pass', password_confirmation: 'pass') } + it 'signup uppercase, login mixed-case' do + visit root_path + click_on 'Sign Up' + expect(current_path).to eq signup_path + fill_in('user[first_name]', with: user.first_name) + fill_in('user[last_name]', with: user.last_name) + fill_in('user[email]', with: user.email.upcase) + fill_in('user[password]', with: user.password) + fill_in('user[password_confirmation]', with: user.password) + click_on 'Create User' + + expect(current_path).to eq login_path + fill_in('email', with: user.email) + fill_in('password', with: user.password) + click_on 'Log In' + + expect(current_path).to eq dashboard_path + expect(page).to have_content "Welcome, #{user.first_name}." + expect(page).to have_link 'Sign Out' + expect(page).to have_link 'Profile' + expect(page).not_to have_link 'Log In' + expect(page).not_to have_link 'Sign Up' + end + + it 'signup uppercase, login uppercase' do + visit root_path + click_on 'Sign Up' + expect(current_path).to eq signup_path + fill_in('user[first_name]', with: user.first_name) + fill_in('user[last_name]', with: user.last_name) + fill_in('user[email]', with: user.email.upcase) + fill_in('user[password]', with: user.password) + fill_in('user[password_confirmation]', with: user.password) + click_on 'Create User' + + expect(current_path).to eq login_path + fill_in('email', with: user.email.upcase) + fill_in('password', with: user.password) + click_on 'Log In' + + expect(current_path).to eq dashboard_path + expect(page).to have_content "Welcome, #{user.first_name}." + expect(page).to have_link 'Sign Out' + expect(page).to have_link 'Profile' + expect(page).not_to have_link 'Log In' + expect(page).not_to have_link 'Sign Up' + end + + it 'signup uppercase, login downcase' do + visit root_path + click_on 'Sign Up' + expect(current_path).to eq signup_path + fill_in('user[first_name]', with: user.first_name) + fill_in('user[last_name]', with: user.last_name) + fill_in('user[email]', with: user.email.upcase) + fill_in('user[password]', with: user.password) + fill_in('user[password_confirmation]', with: user.password) + click_on 'Create User' + + expect(current_path).to eq login_path + fill_in('email', with: user.email.downcase) + fill_in('password', with: user.password) + click_on 'Log In' + + expect(current_path).to eq dashboard_path + expect(page).to have_content "Welcome, #{user.first_name}." + expect(page).to have_link 'Sign Out' + expect(page).to have_link 'Profile' + expect(page).not_to have_link 'Log In' + expect(page).not_to have_link 'Sign Up' + end + + it 'signup mixed-case, login mixed-case' do + visit root_path + click_on 'Sign Up' + expect(current_path).to eq signup_path + fill_in('user[first_name]', with: user.first_name) + fill_in('user[last_name]', with: user.last_name) + fill_in('user[email]', with: user.email) + fill_in('user[password]', with: user.password) + fill_in('user[password_confirmation]', with: user.password) + click_on 'Create User' + + expect(current_path).to eq login_path + fill_in('email', with: user.email) + fill_in('password', with: user.password) + click_on 'Log In' + + expect(current_path).to eq dashboard_path + expect(page).to have_content "Welcome, #{user.first_name}." + expect(page).to have_link 'Sign Out' + expect(page).to have_link 'Profile' + expect(page).not_to have_link 'Log In' + expect(page).not_to have_link 'Sign Up' + end + + it 'signup mixed-case, login uppercase' do + visit root_path + click_on 'Sign Up' + expect(current_path).to eq signup_path + fill_in('user[first_name]', with: user.first_name) + fill_in('user[last_name]', with: user.last_name) + fill_in('user[email]', with: user.email) + fill_in('user[password]', with: user.password) + fill_in('user[password_confirmation]', with: user.password) + click_on 'Create User' + + expect(current_path).to eq login_path + fill_in('email', with: user.email.upcase) + fill_in('password', with: user.password) + click_on 'Log In' + + expect(current_path).to eq dashboard_path + expect(page).to have_content "Welcome, #{user.first_name}." + expect(page).to have_link 'Sign Out' + expect(page).to have_link 'Profile' + expect(page).not_to have_link 'Log In' + expect(page).not_to have_link 'Sign Up' + end + + it 'signup mixed-case, login downcase' do + visit root_path + click_on 'Sign Up' + expect(current_path).to eq signup_path + fill_in('user[first_name]', with: user.first_name) + fill_in('user[last_name]', with: user.last_name) + fill_in('user[email]', with: user.email) + fill_in('user[password]', with: user.password) + fill_in('user[password_confirmation]', with: user.password) + click_on 'Create User' + + expect(current_path).to eq login_path + fill_in('email', with: user.email.downcase) + fill_in('password', with: user.password) + click_on 'Log In' + + expect(current_path).to eq dashboard_path + expect(page).to have_content "Welcome, #{user.first_name}." + expect(page).to have_link 'Sign Out' + expect(page).to have_link 'Profile' + expect(page).not_to have_link 'Log In' + expect(page).not_to have_link 'Sign Up' + end + + it 'signup downcase, login mixed-case' do + visit root_path + click_on 'Sign Up' + expect(current_path).to eq signup_path + fill_in('user[first_name]', with: user.first_name) + fill_in('user[last_name]', with: user.last_name) + fill_in('user[email]', with: user.email.downcase) + fill_in('user[password]', with: user.password) + fill_in('user[password_confirmation]', with: user.password) + click_on 'Create User' + + expect(current_path).to eq login_path + fill_in('email', with: user.email) + fill_in('password', with: user.password) + click_on 'Log In' + + expect(current_path).to eq dashboard_path + expect(page).to have_content "Welcome, #{user.first_name}." + expect(page).to have_link 'Sign Out' + expect(page).to have_link 'Profile' + expect(page).not_to have_link 'Log In' + expect(page).not_to have_link 'Sign Up' + end + + it 'signup downcase, login uppercase' do + visit root_path + click_on 'Sign Up' + expect(current_path).to eq signup_path + fill_in('user[first_name]', with: user.first_name) + fill_in('user[last_name]', with: user.last_name) + fill_in('user[email]', with: user.email.downcase) + fill_in('user[password]', with: user.password) + fill_in('user[password_confirmation]', with: user.password) + click_on 'Create User' + + expect(current_path).to eq login_path + fill_in('email', with: user.email.upcase) + fill_in('password', with: user.password) + click_on 'Log In' + + expect(current_path).to eq dashboard_path + expect(page).to have_content "Welcome, #{user.first_name}." + expect(page).to have_link 'Sign Out' + expect(page).to have_link 'Profile' + expect(page).not_to have_link 'Log In' + expect(page).not_to have_link 'Sign Up' + end + + it 'signup downcase, login downcase' do + visit root_path + click_on 'Sign Up' + expect(current_path).to eq signup_path + fill_in('user[first_name]', with: user.first_name) + fill_in('user[last_name]', with: user.last_name) + fill_in('user[email]', with: user.email.downcase) + fill_in('user[password]', with: user.password) + fill_in('user[password_confirmation]', with: user.password) + click_on 'Create User' + + expect(current_path).to eq login_path + fill_in('email', with: user.email.downcase) + fill_in('password', with: user.password) + click_on 'Log In' + + expect(current_path).to eq dashboard_path + expect(page).to have_content "Welcome, #{user.first_name}." expect(page).to have_link 'Sign Out' expect(page).to have_link 'Profile' expect(page).not_to have_link 'Log In' From 066e0022cf17b045e9d0437ee93991957f24e3b1 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Thu, 25 Oct 2018 12:11:47 -0600 Subject: [PATCH 34/73] Adds email downcasing functionality. --- app/controllers/invitations_controller.rb | 10 ++++++++-- app/controllers/sessions_controller.rb | 8 +++++++- app/controllers/users_controller.rb | 9 ++++++++- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/app/controllers/invitations_controller.rb b/app/controllers/invitations_controller.rb index f021e33..6673e67 100644 --- a/app/controllers/invitations_controller.rb +++ b/app/controllers/invitations_controller.rb @@ -29,14 +29,16 @@ def invite # sent from the groups page, by the group owner # params[:invitation][:receiver_id] is a string for an email - receiver = User.find_by(email: params[:invitation][:receiver_id]) + # email = params[:invitation][:receiver_id].downcase + receiver = User.find_by(email: downcase_email_param) group = Group.find(params[:group_id]) if receiver no_pending_user_invitations = user_invitations("group_id = ? AND receiver_id = ? AND accepted IS NULL", group.id, receiver.id) no_declined_user_invitations = user_invitations("group_id = ? AND receiver_id = ? AND accepted = false", group.id, receiver.id) + not_inviting_self = (group.owner_id != receiver.id) end - if no_pending_user_invitations && no_declined_user_invitations + if no_pending_user_invitations && no_declined_user_invitations && not_inviting_self invitation = Invitation.new invitation.group_id = group.id invitation.receiver_id = receiver.id @@ -71,4 +73,8 @@ def create_list @list.group_id = @group.id @list.save end + + def downcase_email_param + params[:invitation][:receiver_id].downcase + end end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 0329bed..d4f80f8 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -3,7 +3,7 @@ def new end def create - user = User.find_by(email: params[:email]) + user = User.find_by(email: downcase_email) if user && user.authenticate(params[:password]) session[:user_id] = user.id redirect_to dashboard_path @@ -18,4 +18,10 @@ def destroy flash[:notice] = "Log out successful." redirect_to root_path end + + private + + def downcase_email + params[:email].downcase + end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index ce039f0..853259f 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -12,10 +12,12 @@ def new def create @user = User.new(user_params) + @user.email.downcase! if @user.save redirect_to login_path else - render 'new' + flash[:warning] = "Please enter valid credentials." + redirect_to signup_path end end @@ -78,6 +80,7 @@ def validate_params(string) when 'Name' return params.require(:user).permit(:first_name, :last_name) when 'Email' + downcase_email_param! return params.require(:user).permit(:email) when 'Password' return params.require(:user).permit(:password, :password_confirmation) @@ -87,4 +90,8 @@ def validate_params(string) def user_params params.require(:user).permit(:email, :first_name, :last_name, :password, :password_confirmation) end + + def downcase_email_param! + params[:user][:email].downcase! + end end From 5e9c067167309548c99f1d9dc95d706ac9fa8d36 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Thu, 25 Oct 2018 12:12:14 -0600 Subject: [PATCH 35/73] Seeds emails to be downcase. --- db/seeds.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/seeds.rb b/db/seeds.rb index 6e1cf22..15b1a55 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -10,7 +10,7 @@ last_name = Faker::Name.last_name user = User.create!(first_name: first_name, last_name: last_name, - email: "#{first_name}@#{last_name}.com", + email: "#{first_name.downcase}@#{last_name.downcase}.com".gsub(' ', ''), password: 'pass', password_confirmation: 'pass') From feb84c66b84d7d17d3fe21bb124a15f734f1eec5 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Thu, 25 Oct 2018 13:04:11 -0600 Subject: [PATCH 36/73] Adds group visibility to one user test. --- spec/features/groups/group_spec.rb | 35 ++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/spec/features/groups/group_spec.rb b/spec/features/groups/group_spec.rb index ad0f742..849a91f 100644 --- a/spec/features/groups/group_spec.rb +++ b/spec/features/groups/group_spec.rb @@ -34,10 +34,7 @@ let(:group) { Group.create(name: 'My first group creation', description: 'Whoever wants to join', gift_due_date: '2018/12/31') } it 'logged in' do - visit login_path - fill_in 'Email', with: user.email - fill_in 'Password', with: user.password - click_on 'Log In' + sign_in_as(user) expect(current_path).to eq dashboard_path expect(page).to have_content 'Welcome, Raa.' @@ -64,4 +61,34 @@ expect(page).to have_content 'You must be logged in first.' end end + + context 'visible only' do + let(:user_one) { User.create(first_name: 'Johnny', last_name: 'Jy', email: 'johanna@test.com', password: 'pass') } + let(:user_two) { User.create(first_name: 'Johanna', last_name: 'Ja', email: 'johnny@test.com', password: 'pass') } + let(:group_one) { Group.create(name: 'My first group creation', description: 'Whoever wants to join', gift_due_date: '2018/12/31') } + let(:group_two) { Group.create(name: 'My second group creation', description: 'Whoever wants to join', gift_due_date: '2019/12/31') } + it 'to one user' do + sign_in_as(user_one) + expect(current_path).to eq dashboard_path + click_on 'Create a Group' + expect(current_path).to eq new_group_path + fill_in('Name', with: group_one.name) + fill_in('Description', with: group_one.description) + fill_in('Gift Due Date', with: group_one.gift_due_date.to_default_s) + click_on 'Create Group' + + sign_in_as(user_two) + expect(current_path).to eq dashboard_path + click_on 'Create a Group' + expect(current_path).to eq new_group_path + fill_in('Name', with: group_two.name) + fill_in('Description', with: group_two.description) + fill_in('Gift Due Date', with: group_two.gift_due_date.to_default_s) + click_on 'Create Group' + + visit dashboard_path + expect(page).to have_content group_two.name, user_two.first_name + expect(page).to have_no_content group_one.name, user_one.first_name + end + end end From a61540de09dfccee15244ed821899a044c4a4cab Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Thu, 25 Oct 2018 13:05:23 -0600 Subject: [PATCH 37/73] Adds helper methods and makes use of them. --- spec/features/users/user_can_signup_spec.rb | 122 +++++--------------- spec/support/features/sign_in.rb | 23 +++- 2 files changed, 48 insertions(+), 97 deletions(-) diff --git a/spec/features/users/user_can_signup_spec.rb b/spec/features/users/user_can_signup_spec.rb index bee5e1a..2dad27a 100644 --- a/spec/features/users/user_can_signup_spec.rb +++ b/spec/features/users/user_can_signup_spec.rb @@ -33,60 +33,44 @@ it 'signup uppercase, login mixed-case' do visit root_path click_on 'Sign Up' + expect(current_path).to eq signup_path - fill_in('user[first_name]', with: user.first_name) - fill_in('user[last_name]', with: user.last_name) - fill_in('user[email]', with: user.email.upcase) - fill_in('user[password]', with: user.password) - fill_in('user[password_confirmation]', with: user.password) + fill_out_user_signup_no_email(user) + fill_in 'user[email]', with: user.email.upcase click_on 'Create User' expect(current_path).to eq login_path - fill_in('email', with: user.email) - fill_in('password', with: user.password) - click_on 'Log In' + sign_in_as(user) expect(current_path).to eq dashboard_path - expect(page).to have_content "Welcome, #{user.first_name}." - expect(page).to have_link 'Sign Out' - expect(page).to have_link 'Profile' - expect(page).not_to have_link 'Log In' - expect(page).not_to have_link 'Sign Up' + dashboard_path_content(user) end it 'signup uppercase, login uppercase' do visit root_path click_on 'Sign Up' + expect(current_path).to eq signup_path - fill_in('user[first_name]', with: user.first_name) - fill_in('user[last_name]', with: user.last_name) - fill_in('user[email]', with: user.email.upcase) - fill_in('user[password]', with: user.password) - fill_in('user[password_confirmation]', with: user.password) + fill_out_user_signup_no_email(user) + fill_in 'user[email]', with: user.email.upcase click_on 'Create User' expect(current_path).to eq login_path - fill_in('email', with: user.email.upcase) - fill_in('password', with: user.password) + fill_in 'email', with: user.email.upcase + fill_in 'password', with: user.password click_on 'Log In' expect(current_path).to eq dashboard_path - expect(page).to have_content "Welcome, #{user.first_name}." - expect(page).to have_link 'Sign Out' - expect(page).to have_link 'Profile' - expect(page).not_to have_link 'Log In' - expect(page).not_to have_link 'Sign Up' + dashboard_path_content(user) end it 'signup uppercase, login downcase' do visit root_path click_on 'Sign Up' + expect(current_path).to eq signup_path - fill_in('user[first_name]', with: user.first_name) - fill_in('user[last_name]', with: user.last_name) + fill_out_user_signup_no_email(user) fill_in('user[email]', with: user.email.upcase) - fill_in('user[password]', with: user.password) - fill_in('user[password_confirmation]', with: user.password) click_on 'Create User' expect(current_path).to eq login_path @@ -95,46 +79,30 @@ click_on 'Log In' expect(current_path).to eq dashboard_path - expect(page).to have_content "Welcome, #{user.first_name}." - expect(page).to have_link 'Sign Out' - expect(page).to have_link 'Profile' - expect(page).not_to have_link 'Log In' - expect(page).not_to have_link 'Sign Up' + dashboard_path_content(user) end it 'signup mixed-case, login mixed-case' do visit root_path click_on 'Sign Up' expect(current_path).to eq signup_path - fill_in('user[first_name]', with: user.first_name) - fill_in('user[last_name]', with: user.last_name) + fill_out_user_signup_no_email(user) fill_in('user[email]', with: user.email) - fill_in('user[password]', with: user.password) - fill_in('user[password_confirmation]', with: user.password) click_on 'Create User' expect(current_path).to eq login_path - fill_in('email', with: user.email) - fill_in('password', with: user.password) - click_on 'Log In' + sign_in_as(user) expect(current_path).to eq dashboard_path - expect(page).to have_content "Welcome, #{user.first_name}." - expect(page).to have_link 'Sign Out' - expect(page).to have_link 'Profile' - expect(page).not_to have_link 'Log In' - expect(page).not_to have_link 'Sign Up' + dashboard_path_content(user) end it 'signup mixed-case, login uppercase' do visit root_path click_on 'Sign Up' expect(current_path).to eq signup_path - fill_in('user[first_name]', with: user.first_name) - fill_in('user[last_name]', with: user.last_name) + fill_out_user_signup_no_email(user) fill_in('user[email]', with: user.email) - fill_in('user[password]', with: user.password) - fill_in('user[password_confirmation]', with: user.password) click_on 'Create User' expect(current_path).to eq login_path @@ -143,22 +111,15 @@ click_on 'Log In' expect(current_path).to eq dashboard_path - expect(page).to have_content "Welcome, #{user.first_name}." - expect(page).to have_link 'Sign Out' - expect(page).to have_link 'Profile' - expect(page).not_to have_link 'Log In' - expect(page).not_to have_link 'Sign Up' + dashboard_path_content(user) end it 'signup mixed-case, login downcase' do visit root_path click_on 'Sign Up' expect(current_path).to eq signup_path - fill_in('user[first_name]', with: user.first_name) - fill_in('user[last_name]', with: user.last_name) + fill_out_user_signup_no_email(user) fill_in('user[email]', with: user.email) - fill_in('user[password]', with: user.password) - fill_in('user[password_confirmation]', with: user.password) click_on 'Create User' expect(current_path).to eq login_path @@ -167,46 +128,30 @@ click_on 'Log In' expect(current_path).to eq dashboard_path - expect(page).to have_content "Welcome, #{user.first_name}." - expect(page).to have_link 'Sign Out' - expect(page).to have_link 'Profile' - expect(page).not_to have_link 'Log In' - expect(page).not_to have_link 'Sign Up' + dashboard_path_content(user) end it 'signup downcase, login mixed-case' do visit root_path click_on 'Sign Up' expect(current_path).to eq signup_path - fill_in('user[first_name]', with: user.first_name) - fill_in('user[last_name]', with: user.last_name) + fill_out_user_signup_no_email(user) fill_in('user[email]', with: user.email.downcase) - fill_in('user[password]', with: user.password) - fill_in('user[password_confirmation]', with: user.password) click_on 'Create User' expect(current_path).to eq login_path - fill_in('email', with: user.email) - fill_in('password', with: user.password) - click_on 'Log In' + sign_in_as(user) expect(current_path).to eq dashboard_path - expect(page).to have_content "Welcome, #{user.first_name}." - expect(page).to have_link 'Sign Out' - expect(page).to have_link 'Profile' - expect(page).not_to have_link 'Log In' - expect(page).not_to have_link 'Sign Up' + dashboard_path_content(user) end it 'signup downcase, login uppercase' do visit root_path click_on 'Sign Up' expect(current_path).to eq signup_path - fill_in('user[first_name]', with: user.first_name) - fill_in('user[last_name]', with: user.last_name) + fill_out_user_signup_no_email(user) fill_in('user[email]', with: user.email.downcase) - fill_in('user[password]', with: user.password) - fill_in('user[password_confirmation]', with: user.password) click_on 'Create User' expect(current_path).to eq login_path @@ -215,22 +160,15 @@ click_on 'Log In' expect(current_path).to eq dashboard_path - expect(page).to have_content "Welcome, #{user.first_name}." - expect(page).to have_link 'Sign Out' - expect(page).to have_link 'Profile' - expect(page).not_to have_link 'Log In' - expect(page).not_to have_link 'Sign Up' + dashboard_path_content(user) end it 'signup downcase, login downcase' do visit root_path click_on 'Sign Up' expect(current_path).to eq signup_path - fill_in('user[first_name]', with: user.first_name) - fill_in('user[last_name]', with: user.last_name) + fill_out_user_signup_no_email(user) fill_in('user[email]', with: user.email.downcase) - fill_in('user[password]', with: user.password) - fill_in('user[password_confirmation]', with: user.password) click_on 'Create User' expect(current_path).to eq login_path @@ -239,11 +177,7 @@ click_on 'Log In' expect(current_path).to eq dashboard_path - expect(page).to have_content "Welcome, #{user.first_name}." - expect(page).to have_link 'Sign Out' - expect(page).to have_link 'Profile' - expect(page).not_to have_link 'Log In' - expect(page).not_to have_link 'Sign Up' + dashboard_path_content(user) end end diff --git a/spec/support/features/sign_in.rb b/spec/support/features/sign_in.rb index df510f4..208ca48 100644 --- a/spec/support/features/sign_in.rb +++ b/spec/support/features/sign_in.rb @@ -1,11 +1,28 @@ module Features def sign_in -# before { @user = User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') } @user = User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') + sign_in_as(@user) + end + def sign_in_as(user) visit login_path - fill_in 'Email', with: @user.email - fill_in 'Password', with: 'pass' + fill_in 'Email', with: user.email + fill_in 'Password', with: user.password click_on 'Log In' end + + def fill_out_user_signup_no_email(user) + fill_in('user[first_name]', with: user.first_name) + fill_in('user[last_name]', with: user.last_name) + fill_in('user[password]', with: user.password) + fill_in('user[password_confirmation]', with: user.password) + end + + def dashboard_path_content(user) + expect(page).to have_content "Welcome, #{user.first_name}." + expect(page).to have_link 'Sign Out' + expect(page).to have_link 'Profile' + expect(page).not_to have_link 'Log In' + expect(page).not_to have_link 'Sign Up' + end end From d4e056eafdf7c02965b05a493edcf78e0a75ccdd Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 10:59:16 -0600 Subject: [PATCH 38/73] Removes 'only' array from before actions, modifies flash warning, fixes redirect link. --- app/controllers/items_controller.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index 1df0bff..1d288f7 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -1,6 +1,6 @@ class ItemsController < ApplicationController - before_action :set_group, only: [:new, :create, :show, :edit, :destroy] - before_action :set_list, only: [:new, :create, :show, :edit, :destroy] + before_action :set_group + before_action :set_list before_action :set_item, only: [:show, :edit, :update, :destroy] before_action :set_user, only: [:create, :show] # check if needed in `show` @@ -14,7 +14,7 @@ def create if @item.save redirect_to group_list_path(@group, @list) else - flash[:warning] = 'Invalid entry.' + flash[:warning] = 'Please enter valid information.' render 'new' end end @@ -28,7 +28,7 @@ def edit def update if @item.update(item_params) - redirect_to group_list_item_path(@item) + redirect_to group_list_item_path(@group, @list, @item) flash[:notice] = "Item, #{@item.name}, updated." else flash[:warning] = 'An error occurred, please try again.' From 843bff08f5e141b243b10484e3a9c84a71ec4c1d Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 11:01:16 -0600 Subject: [PATCH 39/73] Adds feature tests for group creation, editing, and deletion. --- spec/features/groups/creating_group_spec.rb | 63 ++++++++++++++++++ spec/features/groups/deleting_group_spec.rb | 64 +++++++++++++++++++ spec/features/groups/editing_group_spec.rb | 47 ++++++++++++++ .../groups/group_visible_to_one_user_spec.rb | 33 ++++++++++ spec/support/features/group.rb | 7 ++ 5 files changed, 214 insertions(+) create mode 100644 spec/features/groups/creating_group_spec.rb create mode 100644 spec/features/groups/deleting_group_spec.rb create mode 100644 spec/features/groups/editing_group_spec.rb create mode 100644 spec/features/groups/group_visible_to_one_user_spec.rb create mode 100644 spec/support/features/group.rb diff --git a/spec/features/groups/creating_group_spec.rb b/spec/features/groups/creating_group_spec.rb new file mode 100644 index 0000000..85b2130 --- /dev/null +++ b/spec/features/groups/creating_group_spec.rb @@ -0,0 +1,63 @@ +require 'rails_helper' + +describe 'group creation' do + context 'created with' do + let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') } + let(:group_info) { Group.create(name: 'This is one awesome group!', description: 'What a description', gift_due_date: '2019-02-28') } + it 'correct information' do + allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(user) + visit new_group_path + fill_in('group_name', with: group_info.name) + fill_in('group_description', with: group_info.description) + fill_in('group_gift_due_date', with: group_info.gift_due_date) + click_on 'Create Group' + + expect(page).to have_content group_info.name + expect(page).to have_content group_info.description + expect(page).to have_content group_info.gift_due_date + end + + it 'blank information' do + allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(user) + visit new_group_path + fill_in('group_name', with: '') + fill_in('group_description', with: '') + click_on 'Create Group' + + expect(page).to have_content "The Gift Due Date can't be blank, or the Group Name is already taken." + end + end + + context 'while' do + let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') } + let(:group) { Group.create(name: 'My first group creation', description: 'Whoever wants to join', gift_due_date: '2018/12/31') } + + it 'logged in' do + sign_in_as(user) + + expect(current_path).to eq dashboard_path + expect(page).to have_content 'Welcome, Raa.' + click_on 'Create a Group' + + expect(current_path).to eq new_group_path + fill_in('Name', with: group.name) + fill_in('Description', with: group.description) + fill_in('Gift Due Date', with: group.gift_due_date.to_default_s) + click_on 'Create Group' + + expect(page).to have_content group.name + expect(page).to have_content group.description + expect(page).to have_content group.gift_due_date.to_default_s + expect(page).to have_content 'Edit Group', 'Delete Group' + expect(page).to have_content "#{user.first_name} #{user.last_name}:" + expect(page).to have_content '(Group Owner)' + expect(page).to have_content 'Send an invitation', 'View your Wish List' + end + + it 'not logged in' do + visit profile_path + expect(current_path).to eq root_path + expect(page).to have_content 'You must be logged in first.' + end + end +end diff --git a/spec/features/groups/deleting_group_spec.rb b/spec/features/groups/deleting_group_spec.rb new file mode 100644 index 0000000..2faeef0 --- /dev/null +++ b/spec/features/groups/deleting_group_spec.rb @@ -0,0 +1,64 @@ +require 'rails_helper' + +describe 'deleting a group' do + context 'with' do + let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') } + let(:group) { Group.create(name: 'My first group creation', description: 'Whoever wants to join', gift_due_date: '2018/12/31') } + let(:item_one) { Item.create(name: 'Wallet', description: 'So pretty', size: 'XL', note: 'I would like many of these.') } + let(:item_two) { Item.create(name: 'Shoes', description: 'So pretty', size: 'XL', note: 'I would like many of these.') } + + + it 'no user items' do + sign_in_as(user) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + visit dashboard_path + click_on group.name + click_on 'Delete Group' + + expect(page).to have_content 'Group Deleted!' + expect(page).to have_no_content group.name + end + + it 'one user items' do + sign_in_as(user) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + visit dashboard_path + click_on group.name + click_on 'View your Wish List' + click_on 'Create a new Wish list item' + create_item(item_one) + click_on 'Create Item' + click_on 'Back to Group' + + click_on 'Delete Group' + expect(page).to have_content 'Group Deleted!' + expect(page).to have_no_content group.name + end + + it 'many user items' do + sign_in_as(user) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + visit dashboard_path + click_on group.name + + click_on 'View your Wish List' + click_on 'Create a new Wish list item' + create_item(item_one) + click_on 'Create Item' + click_on 'Create a new Wish list item' + create_item(item_two) + click_on 'Create Item' + click_on 'Back to Group' + + click_on 'Delete Group' + expect(page).to have_content 'Group Deleted!' + expect(page).to have_no_content group.name + end + end +end diff --git a/spec/features/groups/editing_group_spec.rb b/spec/features/groups/editing_group_spec.rb new file mode 100644 index 0000000..9125cc8 --- /dev/null +++ b/spec/features/groups/editing_group_spec.rb @@ -0,0 +1,47 @@ +require 'rails_helper' + +describe 'editing a group' do + context 'with' do + let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') } + let(:group) { Group.create(name: 'My first group creation', description: 'Whoever wants to join', gift_due_date: '2018/12/31') } + + it 'correct information' do + sign_in_as(user) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + visit dashboard_path + + expect(page).to have_link group.name + click_on group.name + click_on 'Edit Group' + + fill_in 'Name', with: group.name + '!!' + fill_in 'Description', with: group.description + '!!' + fill_in 'Gift Due Date', with: group.gift_due_date.next.to_default_s + click_on 'Update Group' + + expect(page).to have_content group.name + '!!' + expect(page).to have_content group.description + '!!' + expect(page).to have_content group.gift_due_date.next.to_default_s + + end + + it 'blank information' do + sign_in_as(user) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + visit dashboard_path + click_on group.name + click_on 'Edit Group' + + fill_in 'Name', with: '' + fill_in 'Description', with: '' + fill_in 'Gift Due Date', with: '' + click_on 'Update Group' + + expect(page).to have_content 'Please enter valid information.' + end + end +end diff --git a/spec/features/groups/group_visible_to_one_user_spec.rb b/spec/features/groups/group_visible_to_one_user_spec.rb new file mode 100644 index 0000000..5474368 --- /dev/null +++ b/spec/features/groups/group_visible_to_one_user_spec.rb @@ -0,0 +1,33 @@ +require 'rails_helper' + +describe 'a group is' do + context 'visible only' do + let(:user_one) { User.create(first_name: 'Johnny', last_name: 'Jy', email: 'johanna@test.com', password: 'pass') } + let(:user_two) { User.create(first_name: 'Johanna', last_name: 'Ja', email: 'johnny@test.com', password: 'pass') } + let(:group_one) { Group.create(name: 'My first group creation', description: 'Whoever wants to join', gift_due_date: '2018/12/31') } + let(:group_two) { Group.create(name: 'My second group creation', description: 'Whoever wants to join', gift_due_date: '2019/12/31') } + it 'to one user' do + sign_in_as(user_one) + expect(current_path).to eq dashboard_path + click_on 'Create a Group' + expect(current_path).to eq new_group_path + fill_in('Name', with: group_one.name) + fill_in('Description', with: group_one.description) + fill_in('Gift Due Date', with: group_one.gift_due_date.to_default_s) + click_on 'Create Group' + + sign_in_as(user_two) + expect(current_path).to eq dashboard_path + click_on 'Create a Group' + expect(current_path).to eq new_group_path + fill_in('Name', with: group_two.name) + fill_in('Description', with: group_two.description) + fill_in('Gift Due Date', with: group_two.gift_due_date.to_default_s) + click_on 'Create Group' + + visit dashboard_path + expect(page).to have_content group_two.name, user_two.first_name + expect(page).to have_no_content group_one.name, user_one.first_name + end + end +end diff --git a/spec/support/features/group.rb b/spec/support/features/group.rb new file mode 100644 index 0000000..28403e2 --- /dev/null +++ b/spec/support/features/group.rb @@ -0,0 +1,7 @@ +module Features + def create_group(group) + fill_in('group_name', with: group.name) + fill_in('group_description', with: group.description) + fill_in('group_gift_due_date', with: group.gift_due_date.to_default_s) + end +end From 62f9e64c3915cf5adbf3e3872bd9984fa3506df4 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 11:01:57 -0600 Subject: [PATCH 40/73] Replaces flash warning message. --- app/controllers/groups_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index ff11752..006e836 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -48,7 +48,7 @@ def update flash[:notice] = "Group '#{@group.name}' updated!" redirect_to group_path(@group) else - flash[:warning] = 'An error occurred, please try again.' + flash[:warning] = 'Please enter valid information.' redirect_to edit_group_path(@group) end end From 7c4c99a187b76dbb78467279f1bfe8b5b4f002b2 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 11:04:27 -0600 Subject: [PATCH 41/73] Adds feature tests for item creation, editing and deletion. --- spec/features/items/creating_item_spec.rb | 71 +++++++++++++++++++++ spec/features/items/deleting_item_spec.rb | 29 +++++++++ spec/features/items/editing_item_spec.rb | 75 +++++++++++++++++++++++ spec/support/features/item.rb | 22 +++++++ 4 files changed, 197 insertions(+) create mode 100644 spec/features/items/creating_item_spec.rb create mode 100644 spec/features/items/deleting_item_spec.rb create mode 100644 spec/features/items/editing_item_spec.rb create mode 100644 spec/support/features/item.rb diff --git a/spec/features/items/creating_item_spec.rb b/spec/features/items/creating_item_spec.rb new file mode 100644 index 0000000..633e801 --- /dev/null +++ b/spec/features/items/creating_item_spec.rb @@ -0,0 +1,71 @@ +require 'rails_helper' + +describe 'item creation' do + context 'with' do + let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') } + let(:group) { Group.create(name: 'My first group creation', description: 'Whoever wants to join', gift_due_date: '2018/12/31') } + let(:item_one) { Item.create(name: 'Wallet', description: 'So pretty', size: 'XL', note: 'I would like many of these.') } + let(:item_two) { Item.create(name: 'Shoes', description: 'So pretty!', size: 'L', note: 'I would like many of these please.') } + + it 'correct information' do + sign_in_as(user) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + visit dashboard_path + click_on group.name + click_on 'View your Wish List' + click_on 'Create a new Wish list item' + create_item(item_one) + click_on 'Create Item' + + expect(page).to have_link item_one.name + click_on item_one.name + + expect(page).to have_content item_one.name + expect(page).to have_content item_one.description + expect(page).to have_content item_one.size + expect(page).to have_content item_one.note + end + + it 'blank information' do + sign_in_as(user) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + visit dashboard_path + click_on group.name + click_on 'View your Wish List' + click_on 'Create a new Wish list item' + click_on 'Create Item' + + expect(page).to have_content 'Please enter valid information.' + end + + it 'multiple items' do + sign_in_as(user) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + visit dashboard_path + click_on group.name + click_on 'View your Wish List' + click_on 'Create a new Wish list item' + create_item(item_one) + click_on 'Create Item' + + expect(page).to have_link item_one.name + click_on 'Create a new Wish list item' + create_item(item_two) + click_on 'Create Item' + + expect(page).to have_link item_two.name + click_on item_one.name + item_page_content(item_one) + + click_on 'Back to List' + click_on item_two.name + item_page_content(item_two) + end + end +end diff --git a/spec/features/items/deleting_item_spec.rb b/spec/features/items/deleting_item_spec.rb new file mode 100644 index 0000000..a0fd355 --- /dev/null +++ b/spec/features/items/deleting_item_spec.rb @@ -0,0 +1,29 @@ +require 'rails_helper' + +describe 'deleting' do + let(:user) { User.create(first_name: 'Raaa', last_name: 'Zzzz', email: 'emmaiil@raa.zzz', password: 'passpass') } + let(:group) { Group.create(name: 'The best group there is, that I know', description: 'Whoever wants to join', gift_due_date: '2019/12/31') } + let(:item_one) { Item.create(name: 'Keys', description: 'So many', size: 'S', note: 'I have many of these.') } + + it 'an item' do + sign_in_as(user) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + visit dashboard_path + click_on group.name + click_on 'View your Wish List' + click_on 'Create a new Wish list item' + create_item(item_one) + click_on 'Create Item' + + expect(page).to have_link item_one.name + click_on item_one.name + click_on 'Delete Item' + + expect(page).to have_content "Item, #{item_one.name}, Deleted!" + expect(page).to have_no_content item_one.description + expect(page).to have_no_content item_one.size + expect(page).to have_no_content item_one.note + end +end diff --git a/spec/features/items/editing_item_spec.rb b/spec/features/items/editing_item_spec.rb new file mode 100644 index 0000000..dc442d3 --- /dev/null +++ b/spec/features/items/editing_item_spec.rb @@ -0,0 +1,75 @@ +require 'rails_helper' + +describe 'editing an item' do + context 'with' do + let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'emaiil@raa.zzz', password: 'passpass') } + let(:group) { Group.create(name: 'The best group there is', description: 'Whoever wants to join', gift_due_date: '2018/12/31') } + let(:item_one) { Item.create(name: 'Wallet', description: 'So pretty', size: 'XL', note: 'I would like many of these.') } + let(:item_two) { Item.create(name: 'Shoes', description: 'So pretty!', size: 'L', note: 'I would like many of these please.') } + + it 'correct information' do + sign_in_as(user) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + visit dashboard_path + click_on group.name + click_on 'View your Wish List' + click_on 'Create a new Wish list item' + create_item(item_one) + click_on 'Create Item' + + expect(page).to have_link item_one.name + click_on item_one.name + click_on 'Edit Item' + + edit_item(item_one) + click_on 'Update Item' + + expect(page).to have_content item_one.name + '!!' + expect(page).to have_content item_one.description + '!!' + expect(page).to have_content item_one.size + '!!' + expect(page).to have_content item_one.note + '!!' + end + + it 'blank information' do + sign_in_as(user) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + visit dashboard_path + click_on group.name + click_on 'View your Wish List' + click_on 'Create a new Wish list item' + click_on 'Create Item' + + expect(page).to have_content 'Please enter valid information.' + end + + it 'multiple items' do + sign_in_as(user) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + visit dashboard_path + click_on group.name + click_on 'View your Wish List' + click_on 'Create a new Wish list item' + create_item(item_one) + click_on 'Create Item' + + expect(page).to have_link item_one.name + click_on 'Create a new Wish list item' + create_item(item_two) + click_on 'Create Item' + + expect(page).to have_link item_two.name + click_on item_one.name + item_page_content(item_one) + + click_on 'Back to List' + click_on item_two.name + item_page_content(item_two) + end + end +end diff --git a/spec/support/features/item.rb b/spec/support/features/item.rb new file mode 100644 index 0000000..4f2a972 --- /dev/null +++ b/spec/support/features/item.rb @@ -0,0 +1,22 @@ +module Features + def create_item(item) + fill_in 'Name', with: item.name + fill_in 'Description', with: item.description + fill_in 'Size', with: item.size + fill_in 'Note', with: item.note + end + + def item_page_content(item) + expect(page).to have_content item.name + expect(page).to have_content item.description + expect(page).to have_content item.size + expect(page).to have_content item.note + end + + def edit_item(item) + fill_in 'Name', with: item.name + '!!' + fill_in 'Description', with: item.description + '!!' + fill_in 'Size', with: item.size + '!!' + fill_in 'Note', with: item.note + '!!' + end +end From 779a71b9211de66892945fe74e415ad0c224f1c6 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 11:05:10 -0600 Subject: [PATCH 42/73] Renamed and split tests in other files. --- spec/features/groups/group_spec.rb | 94 ------------------- spec/features/items/user_creates_item_spec.rb | 7 -- 2 files changed, 101 deletions(-) delete mode 100644 spec/features/groups/group_spec.rb delete mode 100644 spec/features/items/user_creates_item_spec.rb diff --git a/spec/features/groups/group_spec.rb b/spec/features/groups/group_spec.rb deleted file mode 100644 index 849a91f..0000000 --- a/spec/features/groups/group_spec.rb +++ /dev/null @@ -1,94 +0,0 @@ -require 'rails_helper' - -describe 'group creation' do - - context 'created' do - let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') } - let(:group_info) { Group.create(name: 'This is one awesome group!', description: 'What a description', gift_due_date: '2019-02-28') } - it 'correctly' do - allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(user) - visit new_group_path - fill_in('group_name', with: group_info.name) - fill_in('group_description', with: group_info.description) - fill_in('group_gift_due_date', with: group_info.gift_due_date) - click_on 'Create Group' - - expect(page).to have_content group_info.name - expect(page).to have_content group_info.description - expect(page).to have_content group_info.gift_due_date - end - - it 'incorrectly' do - allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(user) - visit new_group_path - fill_in('group_name', with: '') - fill_in('group_description', with: '') - click_on 'Create Group' - - expect(page).to have_content "The Gift Due Date can't be blank, or the Group Name is already taken." - end - end - - context 'while' do - let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') } - let(:group) { Group.create(name: 'My first group creation', description: 'Whoever wants to join', gift_due_date: '2018/12/31') } - - it 'logged in' do - sign_in_as(user) - - expect(current_path).to eq dashboard_path - expect(page).to have_content 'Welcome, Raa.' - click_on 'Create a Group' - - expect(current_path).to eq new_group_path - fill_in('Name', with: group.name) - fill_in('Description', with: group.description) - fill_in('Gift Due Date', with: group.gift_due_date.to_default_s) - click_on 'Create Group' - - expect(page).to have_content group.name - expect(page).to have_content group.description - expect(page).to have_content group.gift_due_date.to_default_s - expect(page).to have_content 'Edit Group', 'Delete Group' - expect(page).to have_content "#{user.first_name} #{user.last_name}:" - expect(page).to have_content '(Group Owner)' - expect(page).to have_content 'Send an invitation', 'View your Wish List' - end - - it 'logged out' do - visit profile_path - expect(current_path).to eq root_path - expect(page).to have_content 'You must be logged in first.' - end - end - - context 'visible only' do - let(:user_one) { User.create(first_name: 'Johnny', last_name: 'Jy', email: 'johanna@test.com', password: 'pass') } - let(:user_two) { User.create(first_name: 'Johanna', last_name: 'Ja', email: 'johnny@test.com', password: 'pass') } - let(:group_one) { Group.create(name: 'My first group creation', description: 'Whoever wants to join', gift_due_date: '2018/12/31') } - let(:group_two) { Group.create(name: 'My second group creation', description: 'Whoever wants to join', gift_due_date: '2019/12/31') } - it 'to one user' do - sign_in_as(user_one) - expect(current_path).to eq dashboard_path - click_on 'Create a Group' - expect(current_path).to eq new_group_path - fill_in('Name', with: group_one.name) - fill_in('Description', with: group_one.description) - fill_in('Gift Due Date', with: group_one.gift_due_date.to_default_s) - click_on 'Create Group' - - sign_in_as(user_two) - expect(current_path).to eq dashboard_path - click_on 'Create a Group' - expect(current_path).to eq new_group_path - fill_in('Name', with: group_two.name) - fill_in('Description', with: group_two.description) - fill_in('Gift Due Date', with: group_two.gift_due_date.to_default_s) - click_on 'Create Group' - - visit dashboard_path - expect(page).to have_content group_two.name, user_two.first_name - expect(page).to have_no_content group_one.name, user_one.first_name - end - end -end diff --git a/spec/features/items/user_creates_item_spec.rb b/spec/features/items/user_creates_item_spec.rb deleted file mode 100644 index e8b4003..0000000 --- a/spec/features/items/user_creates_item_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require 'rails_helper' - -describe 'item creation' do - - - -end From 37b2e87fbe3e198a87193368539bc36d5b4fc618 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 11:05:47 -0600 Subject: [PATCH 43/73] Adds blank credential feature test. --- spec/features/users/user_can_signup_spec.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/spec/features/users/user_can_signup_spec.rb b/spec/features/users/user_can_signup_spec.rb index 2dad27a..983dd20 100644 --- a/spec/features/users/user_can_signup_spec.rb +++ b/spec/features/users/user_can_signup_spec.rb @@ -27,6 +27,20 @@ expect(page).not_to have_link 'Sign Up' end end + context 'incorrectly with' do + it 'blank credentials' do + visit root_path + click_on 'Sign Up' + expect(current_path).to eq signup_path + + click_on 'Create User' + + expect(page).to have_content 'Please enter valid credentials.' + expect(current_path).to eq signup_path + end + + it 'invalid email format' + end context 'with an email' do let(:user) { User.create(first_name: 'Joey', last_name: 'Ralf', email: 'eMaIl@EmAiL.emaILE', password: 'pass', password_confirmation: 'pass') } From 1c4e662b80d340ed92de0572bf73deab746f1c93 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 11:06:33 -0600 Subject: [PATCH 44/73] Replaces string quotes, moved comment to private method. --- app/controllers/invitations_controller.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/controllers/invitations_controller.rb b/app/controllers/invitations_controller.rb index 6673e67..dacac63 100644 --- a/app/controllers/invitations_controller.rb +++ b/app/controllers/invitations_controller.rb @@ -28,13 +28,11 @@ def decline def invite # sent from the groups page, by the group owner - # params[:invitation][:receiver_id] is a string for an email - # email = params[:invitation][:receiver_id].downcase receiver = User.find_by(email: downcase_email_param) group = Group.find(params[:group_id]) if receiver - no_pending_user_invitations = user_invitations("group_id = ? AND receiver_id = ? AND accepted IS NULL", group.id, receiver.id) - no_declined_user_invitations = user_invitations("group_id = ? AND receiver_id = ? AND accepted = false", group.id, receiver.id) + no_pending_user_invitations = user_invitations('group_id = ? AND receiver_id = ? AND accepted IS NULL', group.id, receiver.id) + no_declined_user_invitations = user_invitations('group_id = ? AND receiver_id = ? AND accepted = false', group.id, receiver.id) not_inviting_self = (group.owner_id != receiver.id) end @@ -75,6 +73,7 @@ def create_list end def downcase_email_param + # params[:invitation][:receiver_id] is a string for an email params[:invitation][:receiver_id].downcase end end From b907a3d5914b4d0db5a2f45fc548c320bf4fab8d Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 11:07:30 -0600 Subject: [PATCH 45/73] Gemfile update after testing Ruby 2.4.0 --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 192661b..6c8a9b4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -221,4 +221,4 @@ RUBY VERSION ruby 2.3.1p112 BUNDLED WITH - 1.16.3 + 1.16.4 From 1355606a713e5869a8da478def5be02be1e77c6e Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 12:21:26 -0600 Subject: [PATCH 46/73] Adds StrongPassword Gem --- Gemfile | 1 + Gemfile.lock | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Gemfile b/Gemfile index 6d7b72a..b8e36c7 100644 --- a/Gemfile +++ b/Gemfile @@ -24,6 +24,7 @@ gem 'jbuilder', '~> 2.5' # gem 'redis', '~> 4.0' # Use ActiveModel has_secure_password gem 'bcrypt', '~> 3.1.7' +gem 'strong_password', '~> 0.0.6' # Use ActiveStorage variant # gem 'mini_magick', '~> 4.8' diff --git a/Gemfile.lock b/Gemfile.lock index 6c8a9b4..e09ff3d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -176,6 +176,7 @@ GEM actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) + strong_password (0.0.6) thor (0.20.0) thread_safe (0.3.6) tilt (2.0.8) @@ -213,6 +214,7 @@ DEPENDENCIES rails (~> 5.2.0) rspec-rails (~> 3.7) sass-rails (~> 5.0) + strong_password (~> 0.0.6) tzinfo-data uglifier (>= 1.3.0) web-console (>= 3.3.0) From 1a41daa03e6cd28ed279d6bdf0157014484a8b64 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 12:23:21 -0600 Subject: [PATCH 47/73] Adds more secure password to tests. --- spec/features/groups/creating_group_spec.rb | 4 ++-- spec/features/groups/deleting_group_spec.rb | 2 +- spec/features/groups/editing_group_spec.rb | 2 +- .../groups/group_visible_to_one_user_spec.rb | 4 ++-- spec/features/items/creating_item_spec.rb | 2 +- spec/features/items/deleting_item_spec.rb | 2 +- spec/features/items/editing_item_spec.rb | 2 +- spec/features/session/user_can_login_spec.rb | 2 +- spec/models/user_spec.rb | 14 +++++++------- spec/support/features/sign_in.rb | 2 +- 10 files changed, 18 insertions(+), 18 deletions(-) diff --git a/spec/features/groups/creating_group_spec.rb b/spec/features/groups/creating_group_spec.rb index 85b2130..b3544e2 100644 --- a/spec/features/groups/creating_group_spec.rb +++ b/spec/features/groups/creating_group_spec.rb @@ -2,7 +2,7 @@ describe 'group creation' do context 'created with' do - let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') } + let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'pas1203489y132809hspa1203489y132809hss1203489y132809h') } let(:group_info) { Group.create(name: 'This is one awesome group!', description: 'What a description', gift_due_date: '2019-02-28') } it 'correct information' do allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(user) @@ -29,7 +29,7 @@ end context 'while' do - let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') } + let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'pa1203489y132809hsspa1203489y132809hss') } let(:group) { Group.create(name: 'My first group creation', description: 'Whoever wants to join', gift_due_date: '2018/12/31') } it 'logged in' do diff --git a/spec/features/groups/deleting_group_spec.rb b/spec/features/groups/deleting_group_spec.rb index 2faeef0..092103e 100644 --- a/spec/features/groups/deleting_group_spec.rb +++ b/spec/features/groups/deleting_group_spec.rb @@ -2,7 +2,7 @@ describe 'deleting a group' do context 'with' do - let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') } + let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'pa1203489y132809hsspas1203489y132809hs') } let(:group) { Group.create(name: 'My first group creation', description: 'Whoever wants to join', gift_due_date: '2018/12/31') } let(:item_one) { Item.create(name: 'Wallet', description: 'So pretty', size: 'XL', note: 'I would like many of these.') } let(:item_two) { Item.create(name: 'Shoes', description: 'So pretty', size: 'XL', note: 'I would like many of these.') } diff --git a/spec/features/groups/editing_group_spec.rb b/spec/features/groups/editing_group_spec.rb index 9125cc8..1dd3f5b 100644 --- a/spec/features/groups/editing_group_spec.rb +++ b/spec/features/groups/editing_group_spec.rb @@ -2,7 +2,7 @@ describe 'editing a group' do context 'with' do - let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') } + let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'pa1203489y132809hsspa1203489y132809hss') } let(:group) { Group.create(name: 'My first group creation', description: 'Whoever wants to join', gift_due_date: '2018/12/31') } it 'correct information' do diff --git a/spec/features/groups/group_visible_to_one_user_spec.rb b/spec/features/groups/group_visible_to_one_user_spec.rb index 5474368..5fc7f6e 100644 --- a/spec/features/groups/group_visible_to_one_user_spec.rb +++ b/spec/features/groups/group_visible_to_one_user_spec.rb @@ -2,8 +2,8 @@ describe 'a group is' do context 'visible only' do - let(:user_one) { User.create(first_name: 'Johnny', last_name: 'Jy', email: 'johanna@test.com', password: 'pass') } - let(:user_two) { User.create(first_name: 'Johanna', last_name: 'Ja', email: 'johnny@test.com', password: 'pass') } + let(:user_one) { User.create(first_name: 'Johnny', last_name: 'Jy', email: 'johanna@test.com', password: 'p1203489y132809has1203489y132809hs') } + let(:user_two) { User.create(first_name: 'Johanna', last_name: 'Ja', email: 'johnny@test.com', password: 'p1203489y132809ha1203489y132809hss') } let(:group_one) { Group.create(name: 'My first group creation', description: 'Whoever wants to join', gift_due_date: '2018/12/31') } let(:group_two) { Group.create(name: 'My second group creation', description: 'Whoever wants to join', gift_due_date: '2019/12/31') } it 'to one user' do diff --git a/spec/features/items/creating_item_spec.rb b/spec/features/items/creating_item_spec.rb index 633e801..f68435d 100644 --- a/spec/features/items/creating_item_spec.rb +++ b/spec/features/items/creating_item_spec.rb @@ -2,7 +2,7 @@ describe 'item creation' do context 'with' do - let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') } + let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'pas1203489y132809hspas1203489y132809hs') } let(:group) { Group.create(name: 'My first group creation', description: 'Whoever wants to join', gift_due_date: '2018/12/31') } let(:item_one) { Item.create(name: 'Wallet', description: 'So pretty', size: 'XL', note: 'I would like many of these.') } let(:item_two) { Item.create(name: 'Shoes', description: 'So pretty!', size: 'L', note: 'I would like many of these please.') } diff --git a/spec/features/items/deleting_item_spec.rb b/spec/features/items/deleting_item_spec.rb index a0fd355..31632ea 100644 --- a/spec/features/items/deleting_item_spec.rb +++ b/spec/features/items/deleting_item_spec.rb @@ -1,7 +1,7 @@ require 'rails_helper' describe 'deleting' do - let(:user) { User.create(first_name: 'Raaa', last_name: 'Zzzz', email: 'emmaiil@raa.zzz', password: 'passpass') } + let(:user) { User.create(first_name: 'Raaa', last_name: 'Zzzz', email: 'emmaiil@raa.zzz', password: 'pa1203489y132809hsspas1203489y132809hs') } let(:group) { Group.create(name: 'The best group there is, that I know', description: 'Whoever wants to join', gift_due_date: '2019/12/31') } let(:item_one) { Item.create(name: 'Keys', description: 'So many', size: 'S', note: 'I have many of these.') } diff --git a/spec/features/items/editing_item_spec.rb b/spec/features/items/editing_item_spec.rb index dc442d3..3245af7 100644 --- a/spec/features/items/editing_item_spec.rb +++ b/spec/features/items/editing_item_spec.rb @@ -2,7 +2,7 @@ describe 'editing an item' do context 'with' do - let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'emaiil@raa.zzz', password: 'passpass') } + let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'emaiil@raa.zzz', password: 'pass1203489y132809hsfduhpass') } let(:group) { Group.create(name: 'The best group there is', description: 'Whoever wants to join', gift_due_date: '2018/12/31') } let(:item_one) { Item.create(name: 'Wallet', description: 'So pretty', size: 'XL', note: 'I would like many of these.') } let(:item_two) { Item.create(name: 'Shoes', description: 'So pretty!', size: 'L', note: 'I would like many of these please.') } diff --git a/spec/features/session/user_can_login_spec.rb b/spec/features/session/user_can_login_spec.rb index 8d7df17..a580f21 100644 --- a/spec/features/session/user_can_login_spec.rb +++ b/spec/features/session/user_can_login_spec.rb @@ -6,7 +6,7 @@ # let(:user) { User.create() } # let!(:user) { User.create() } # before { @user = User.create(first_name: 'Test', last_name: 'Ing', email: 'test@ing.com', password: 'password') } - let(:user) { User.create(first_name: 'Test', last_name: 'Ing', email: 'test@ing.com', password: 'password') } + let(:user) { User.create(first_name: 'Test', last_name: 'Ing', email: 'test@ing.com', password: 'pas1203489y132809hswo1203489y132809hrd') } context 'with correct login information' do it 'can login' do visit new_session_path diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 149290e..a7fc30a 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -3,30 +3,30 @@ describe User do it 'has a secure password' do # this test is for K's benefit to see an example and some of the basics of what comes with bcrypt + has_secure_password - u = User.create!(first_name: 'Raz', last_name: 'Z', email: '123@mail.com', password: 'password123') + u = User.create!(first_name: 'Raz', last_name: 'Z', email: '123@mail.com', password: 'passw1203489y132809hord123') expect(u.authenticate('notthepassword')).to be_falsey - expect(u.authenticate('password123')).to eq u + expect(u.authenticate('passw1203489y132809hord123')).to eq u end context 'validations' do it 'validates first name needs to be present' do - u = User.new(first_name: nil, last_name: 'Z', email: 'email@email.email', password: 'passpass') + u = User.new(first_name: nil, last_name: 'Z', email: 'email@email.email', password: 'pa1203489y132809hsspa1203489y132809hss') expect(u.valid?).to be false end it 'validates last name needs to be present' do - u = User.new(first_name: 'Razz', last_name: nil, email: 'email@email.email', password: 'passpass') + u = User.new(first_name: 'Razz', last_name: nil, email: 'email@email.email', password: 'pa1203489y132809hsspa1203489y132809hss') expect(u.valid?).to be false end it 'validates email needs to be present' do - u = User.new(first_name: 'Raz', last_name: 'Z', email: '', password: 'passpass') + u = User.new(first_name: 'Raz', last_name: 'Z', email: '', password: 'pa1203489y132809hsspa1203489y132809hss') expect(u.valid?).to eq false end it 'validates email is unique' do - User.create(first_name: 'Raz', last_name: 'Z', email: 'email@email.email', password: 'passpass') - v = User.new(first_name: 'Raz', last_name: 'Z', email: 'email@email.email', password: 'passpass') + User.create(first_name: 'Raz', last_name: 'Z', email: 'email@email.email', password: 'pa1203489y132809hsspa1203489y132809hss') + v = User.new(first_name: 'Raz', last_name: 'Z', email: 'email@email.email', password: 'pa1203489y132809hsspa1203489y132809hss') expect(v.valid?).to eq false end end diff --git a/spec/support/features/sign_in.rb b/spec/support/features/sign_in.rb index 208ca48..d299e30 100644 --- a/spec/support/features/sign_in.rb +++ b/spec/support/features/sign_in.rb @@ -1,6 +1,6 @@ module Features def sign_in - @user = User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') + @user = User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passp1203489y132809hass') sign_in_as(@user) end From d452a20679de87c24216dc0dbf805b4a3e1af5be Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 12:25:00 -0600 Subject: [PATCH 48/73] Adds more secure password to seeds. --- db/seeds.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db/seeds.rb b/db/seeds.rb index 15b1a55..3edbf4f 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -11,8 +11,8 @@ user = User.create!(first_name: first_name, last_name: last_name, email: "#{first_name.downcase}@#{last_name.downcase}.com".gsub(' ', ''), - password: 'pass', - password_confirmation: 'pass') + password: 'asdf;lkjpoiuqwer', + password_confirmation: 'asdf;lkjpoiuqwer') group = Group.create!(name: Faker::MostInterestingManInTheWorld.unique.quote, description: Faker::GameOfThrones.quote, From 8051f72056203081c4fe6537a0d28e9f215fb76d Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 17:01:30 -0600 Subject: [PATCH 49/73] Refactors update action for password change functionality. --- app/controllers/users_controller.rb | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 853259f..82d4259 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -47,7 +47,10 @@ def edit def update segment_string = params[:commit].split(' ')[1] - if @user.update(validate_params(segment_string)) + if password_change(segment_string) && @user.update(user_params) + flash[:notice] = 'Password successfully updated.' + redirect_to profile_path + elsif @user.update(user_params) flash[:notice] = "#{segment_string} successfully updated." redirect_to profile_path else @@ -58,6 +61,10 @@ def update private + def password_change(string) + string == 'Password' && @user.authenticate(params[:current_password]) + end + def invitable_groups Group.where("owner_id = ?", current_user.id).select do |group| user_does_not_belong_to_group = !group.users.ids.include?(@user.id) @@ -75,18 +82,6 @@ def set_user @user = current_user end - def validate_params(string) - case string - when 'Name' - return params.require(:user).permit(:first_name, :last_name) - when 'Email' - downcase_email_param! - return params.require(:user).permit(:email) - when 'Password' - return params.require(:user).permit(:password, :password_confirmation) - end - end - def user_params params.require(:user).permit(:email, :first_name, :last_name, :password, :password_confirmation) end From 3d8234fdcfc44b25181c67d6f98e52ce7ea2bb46 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 17:03:38 -0600 Subject: [PATCH 50/73] Separates edit forms. --- app/views/users/_update_email.html.erb | 13 +++++++ app/views/users/_update_name.html.erb | 17 +++++++++ app/views/users/_update_password.html.erb | 18 +++++++++ app/views/users/edit.html.erb | 45 ++++------------------- 4 files changed, 56 insertions(+), 37 deletions(-) create mode 100644 app/views/users/_update_email.html.erb create mode 100644 app/views/users/_update_name.html.erb create mode 100644 app/views/users/_update_password.html.erb diff --git a/app/views/users/_update_email.html.erb b/app/views/users/_update_email.html.erb new file mode 100644 index 0000000..a1db1ad --- /dev/null +++ b/app/views/users/_update_email.html.erb @@ -0,0 +1,13 @@ +<%= form_for @user, namespace: 'email' do |f| %> +
    + <%= f.label :email %> + <%= f.text_field :email %> +
    +
    + <%= f.label :password, 'Current Password' %> + <%= f.password_field :password %> +
    +
    + <%= f.submit 'Update Email' %> +
    +<% end %> diff --git a/app/views/users/_update_name.html.erb b/app/views/users/_update_name.html.erb new file mode 100644 index 0000000..1d5ecb7 --- /dev/null +++ b/app/views/users/_update_name.html.erb @@ -0,0 +1,17 @@ +<%= form_for @user, namespace: 'name' do |f| %> +
    + <%= f.label :first_name %> + <%= f.text_field :first_name %> +
    +
    + <%= f.label :last_name %> + <%= f.text_field :last_name %> +
    +
    + <%= f.label :password, 'Current Password' %> + <%= f.password_field :password %> +
    +
    + <%= f.submit 'Update Name' %> +
    +<% end %> diff --git a/app/views/users/_update_password.html.erb b/app/views/users/_update_password.html.erb new file mode 100644 index 0000000..0d99530 --- /dev/null +++ b/app/views/users/_update_password.html.erb @@ -0,0 +1,18 @@ +<%= form_for @user, namespace: 'password' do |f| %> +
    + <%= f.label :password, 'New Password' %> + <%= f.password_field :password, { id: 'new' } %> +
    +
    + <%= f.label :password_confirmation, 'New Password Confirmation' %> + <%= f.password_field :password_confirmation, { id: 'new_confirmation' } %> +
    + +
    + <%= label_tag 'current_password' %> + <%= password_field_tag 'current_password' %> +
    +
    + <%= f.submit 'Update Password' %> +
    +<% end %> diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb index 5c9eadf..6b4e04b 100644 --- a/app/views/users/edit.html.erb +++ b/app/views/users/edit.html.erb @@ -1,41 +1,12 @@

    Edit Profile

    -<%= form_for @user do |f| %> -
    - <%= f.label :first_name %> - <%= f.text_field :first_name %> -
    -
    - <%= f.label :last_name %> - <%= f.text_field :last_name %> -
    -
    - <%= f.submit 'Update Name' %> -
    -<% end %> - -<%= form_for @user do |f| %> -
    - <%= f.label :email %> - <%= f.text_field :email %> -
    -
    - <%= f.submit 'Update Email' %> -
    -<% end %> - -<%= form_for @user do |f| %> -
    - <%= f.label :password %> - <%= f.password_field :password %> -
    -
    - <%= f.label :password_confirmation %> - <%= f.password_field :password_confirmation %> -
    -
    - <%= f.submit 'Update Password' %> -
    -<% end %> +<%= render partial: 'users/update_name' %> +
    +
    +<%= render partial: 'users/update_email' %> +
    +
    +<%= render partial: 'users/update_password' %> +

    <%= link_to 'Back to Profile', profile_path %> From 35a052e1bd44f44446540104340a3ef867abe57d Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 17:04:09 -0600 Subject: [PATCH 51/73] Adds strong password validators. --- app/models/user.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index b84cbfc..3b9f422 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,11 +1,15 @@ class User < ApplicationRecord + has_many :user_groups has_many :groups, through: :user_groups has_many :lists has_many :invitations - has_secure_password validates_uniqueness_of :email validates :first_name, presence: true validates :last_name, presence: true validates :email, presence: true + + include ActiveModel::Validations + has_secure_password + validates :password, password_strength: {use_dictionary: true} end From afeccdb23269c31a7eea73f0307fa4a22e5be6fe Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 17:29:42 -0600 Subject: [PATCH 52/73] Adds more secure password. --- spec/features/users/user_can_signup_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/features/users/user_can_signup_spec.rb b/spec/features/users/user_can_signup_spec.rb index 983dd20..d6cad8c 100644 --- a/spec/features/users/user_can_signup_spec.rb +++ b/spec/features/users/user_can_signup_spec.rb @@ -2,7 +2,7 @@ describe 'user signup' do context 'a new user' do - before { @user = {first_name: 'Joey', last_name: 'Ralf', email: 'emati@l.com', password: 'pass', password_confirmation: 'pass' }} + before { @user = {first_name: 'Joey', last_name: 'Ralf', email: 'emati@l.com', password: 'p1203489y132809has1203489y132809hs', password_confirmation: 'p1203489y132809has1203489y132809hs' }} it 'can create an account' do visit root_path click_on 'Sign Up' @@ -43,7 +43,7 @@ end context 'with an email' do - let(:user) { User.create(first_name: 'Joey', last_name: 'Ralf', email: 'eMaIl@EmAiL.emaILE', password: 'pass', password_confirmation: 'pass') } + let(:user) { User.create(first_name: 'Joey', last_name: 'Ralf', email: 'eMaIl@EmAiL.emaILE', password: 'p1203489y132809has1203489y132809hs', password_confirmation: 'p1203489y132809has1203489y132809hs') } it 'signup uppercase, login mixed-case' do visit root_path click_on 'Sign Up' @@ -197,7 +197,7 @@ context 'as an existing, logged in user' do it 'redirects from /signup to dashboard' do - u = User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passpass') + u = User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'pa1203489y132809hssp1203489y132809hass') allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(u) visit signup_path expect(current_path).to eq dashboard_path From c91fe923af75bf24e9358d3ad24693dfee1f2ce1 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 17:30:04 -0600 Subject: [PATCH 53/73] Adds password strength model tests. --- spec/models/user_spec.rb | 49 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index a7fc30a..fbbbec1 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1,11 +1,50 @@ require 'rails_helper' describe User do - it 'has a secure password' do - # this test is for K's benefit to see an example and some of the basics of what comes with bcrypt + has_secure_password - u = User.create!(first_name: 'Raz', last_name: 'Z', email: '123@mail.com', password: 'passw1203489y132809hord123') - expect(u.authenticate('notthepassword')).to be_falsey - expect(u.authenticate('passw1203489y132809hord123')).to eq u + context 'password is' do + let(:user) { User.create(first_name: 'Raz', last_name: 'Z', email: '123@mail.com', password: 'passw1203489y132809hord123') } + it 'secure' do + expect(user.authenticate('notthepassword')).to be_falsey + expect(user.authenticate(user.password)).to eq user + end + + it 'strong' do + u = User.new(first_name: 'Any', last_name: 'Y', email: 'eamail@email.email', password: 'pa1203489y1328sdfadsf09hsspa1a203489y132809hss') + expect(u.valid?).to eq true + end + + it 'weak' do + u = User.new(first_name: 'Any', last_name: 'Y', email: 'eamail@email.email', password: 'pa12aa') + expect(u.valid?).to eq false + end + + context 'common password:' do + it 'qwerty' do + u = User.new(first_name: 'Any', last_name: 'Y', email: 'eamail@email.email', password: 'qwerty') + expect(u.valid?).to eq false + end + + it 'password' do + u = User.new(first_name: 'Any', last_name: 'Y', email: 'eamail@email.email', password: 'password') + expect(u.valid?).to eq false + end + + it 'qwertyuiop' do + u = User.new(first_name: 'Any', last_name: 'Y', email: 'eamail@email.email', password: 'qwertyuiop') + expect(u.valid?).to eq false + end + + it '1234567890' do + u = User.new(first_name: 'Any', last_name: 'Y', email: 'eamail@email.email', password: '1234567890') + expect(u.valid?).to eq false + end + + it 'pass' do + u = User.new(first_name: 'Any', last_name: 'Y', email: 'eamail@email.email', password: 'pass') + expect(u.valid?).to eq false + end + end + end context 'validations' do From 07c3594b90e8355e38235965a2604020eaac135a Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 18:27:22 -0600 Subject: [PATCH 54/73] Refactors updating action logic. --- app/controllers/users_controller.rb | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 82d4259..6fb174e 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -47,10 +47,8 @@ def edit def update segment_string = params[:commit].split(' ')[1] - if password_change(segment_string) && @user.update(user_params) - flash[:notice] = 'Password successfully updated.' - redirect_to profile_path - elsif @user.update(user_params) + current_pass = params[:current_password] || params[:user][:password] + if authenticate_user(current_pass) && @user.update(validate_params(segment_string)) flash[:notice] = "#{segment_string} successfully updated." redirect_to profile_path else @@ -61,8 +59,20 @@ def update private - def password_change(string) - string == 'Password' && @user.authenticate(params[:current_password]) + def authenticate_user(current_pass) + !!@user.authenticate(current_pass) + end + + def validate_params(string) + case string + when 'Name' + return params.require(:user).permit(:first_name, :last_name, :password) + when 'Email' + downcase_email_param! + return params.require(:user).permit(:email, :password) + when 'Password' + return params.require(:user).permit(:password, :password_confirmation) + end end def invitable_groups From 7a0a15977e550bc9e30b303ab1a87dc1a39d5972 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 18:27:59 -0600 Subject: [PATCH 55/73] Adds feature tests for editing a user's profile. --- spec/features/users/editing_user_spec.rb | 167 +++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 spec/features/users/editing_user_spec.rb diff --git a/spec/features/users/editing_user_spec.rb b/spec/features/users/editing_user_spec.rb new file mode 100644 index 0000000..17a2a5d --- /dev/null +++ b/spec/features/users/editing_user_spec.rb @@ -0,0 +1,167 @@ +require 'rails_helper' + +describe 'editing a user' do + context 'with a correct current password and a' do + let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'emmmaiil@raa.zzz', password: '8930nc89fadsfhhdufdasdfshi4sa') } + it 'valid first and last name' do + sign_in_as(user) + click_on 'Profile' + expect(page).to have_link 'Update Your Information' + click_on 'Update Your Information' + + fill_in 'name_user_first_name', with: user.first_name + 't' + fill_in 'name_user_last_name', with: user.last_name + 'a' + # Finds the 'Current Password' field within the name_edit_user form + find("[id^=name_edit_user]").fill_in 'Current Password', with: user.password + click_on 'Update Name' + + expect(page).to have_content 'Name successfully updated.' + expect(page).to have_content "Name: #{user.first_name + 't'} #{user.last_name + 'a'}" + end + + it 'valid email' do + sign_in_as(user) + click_on 'Profile' + expect(page).to have_link 'Update Your Information' + click_on 'Update Your Information' + + fill_in 'Email', with: user.email + 'TTT' + # Finds the 'Current Password' field within the email_edit_user form + find("[id^=email_edit_user]").fill_in 'Current Password', with: user.password + click_on 'Update Email' + + expect(page).to have_content 'Email successfully updated.' + expect(page).to have_content "Email: #{user.email + 'ttt'}" + end + + it 'valid new password and confirmation' do + sign_in_as(user) + click_on 'Profile' + expect(page).to have_link 'Update Your Information' + click_on 'Update Your Information' + + fill_in 'password_new', with: user.password + 't34fa' + fill_in 'password_new_confirmation', with: user.password + 't34fa' + fill_in 'current_password', with: user.password + click_on 'Update Password' + + expect(page).to have_content 'Password successfully updated.' + click_on 'Back to Dashboard' + click_on 'Sign Out' + click_on 'Log In' + fill_in 'Email', with: user.email + fill_in 'Password', with: user.password + 't34fa' + click_on 'Log In' + + expect(page).to have_content "Welcome, #{user.first_name}." + end + end + + context 'with a correct current password and a blank' do + let(:user) { User.create(first_name: 'Ra', last_name: 'Zz', email: 'mmmaiil@raa.zzz', password: '8930nc89fhhdufdshi6hgs') } + it 'first and last name' do + sign_in_as(user) + click_on 'Profile' + expect(page).to have_link 'Update Your Information' + click_on 'Update Your Information' + + fill_in 'First name', with: '' + fill_in 'Last name', with: '' + # Finds the 'Current Password' field within the name_edit_user form + find("[id^=name_edit_user]").fill_in 'Current Password', with: user.password + click_on 'Update Name' + + expect(page).to have_content 'An error occurred, please try again.' + end + + it 'email' do + sign_in_as(user) + click_on 'Profile' + expect(page).to have_link 'Update Your Information' + click_on 'Update Your Information' + + fill_in 'Email', with: '' + # Finds the 'Current Password' field within the email_edit_user form + find("[id^=email_edit_user]").fill_in 'Current Password', with: user.password + click_on 'Update Email' + + expect(page).to have_content 'An error occurred, please try again.' + end + + it 'new password and confirmation' do + sign_in_as(user) + click_on 'Profile' + expect(page).to have_link 'Update Your Information' + click_on 'Update Your Information' + + fill_in 'password_new', with: '' + fill_in 'password_new_confirmation', with: '' + fill_in 'current_password', with: user.password + click_on 'Update Password' + + expect(page).to have_content 'An error occurred, please try again.' + end + end + + context 'with an incorrect current password and a' do + let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'emmmaiil@raa.zzz', password: '8930nc89fhhdufdshi4sa') } + it 'valid first and last name' do + sign_in_as(user) + click_on 'Profile' + expect(page).to have_link 'Update Your Information' + click_on 'Update Your Information' + + fill_in 'First name', with: user.first_name + 't' + fill_in 'Last name', with: user.last_name + 'a' + # Finds the 'Current Password' field within the name_edit_user form + find("[id^=name_edit_user]").fill_in 'Current Password', with: user.password + 'asd;hfio' + click_on 'Update Name' + + expect(page).to have_no_content 'Name successfully updated.' + expect(page).to have_no_content "Name: #{user.first_name + 't'} #{user.last_name + 'a'}" + expect(page).to have_content 'An error occurred, please try again.' + end + + it 'valid email' do + sign_in_as(user) + click_on 'Profile' + expect(page).to have_link 'Update Your Information' + click_on 'Update Your Information' + + fill_in 'Email', with: user.email + 't' + # Finds the 'Current Password' field within the email_edit_user form + find("[id^=email_edit_user]").fill_in 'Current Password', with: user.password + 'ph91h' + click_on 'Update Email' + + expect(page).to have_no_content 'Email successfully updated.' + expect(page).to have_no_content "Email: #{user.email + 't'}" + expect(page).to have_content 'An error occurred, please try again.' + end + + it 'valid new password and confirmation' do + sign_in_as(user) + click_on 'Profile' + expect(page).to have_link 'Update Your Information' + click_on 'Update Your Information' + + fill_in 'password_new', with: user.password + 't34fa' + fill_in 'password_new_confirmation', with: user.password + 't34fa' + fill_in 'current_password', with: user.password + 'asjdhfash' + click_on 'Update Password' + + expect(page).to have_content 'An error occurred, please try again.' + expect(page).to have_no_content 'Password successfully updated.' + + click_on 'Back to Profile' + click_on 'Back to Dashboard' + click_on 'Sign Out' + click_on 'Log In' + fill_in 'Email', with: user.email + fill_in 'Password', with: user.password + click_on 'Log In' + + expect(page).to have_content "Welcome, #{user.first_name}." + + end + end +end From baccefc9918d188a12b7fba164cb2d56c1ae27bf Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 20:59:03 -0600 Subject: [PATCH 56/73] Adds feature tests for inviting and accepting group invitations. --- .../invitations/creating_invitation_spec.rb | 67 +++++++++++++++++++ .../replying_to_invitation_spec.rb | 63 +++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 spec/features/invitations/creating_invitation_spec.rb create mode 100644 spec/features/invitations/replying_to_invitation_spec.rb diff --git a/spec/features/invitations/creating_invitation_spec.rb b/spec/features/invitations/creating_invitation_spec.rb new file mode 100644 index 0000000..dbd25e9 --- /dev/null +++ b/spec/features/invitations/creating_invitation_spec.rb @@ -0,0 +1,67 @@ +require 'rails_helper' + +describe 'creating an invitation' do + let(:group) { Group.create(name: 'Gift giving', description: 'We love gifts', gift_due_date: '2019-01-01') } + let(:owner) { User.create(first_name: 'Ray', last_name: 'Lee', email: 'email@ray.lee', password: 'hspa1203489y132809hss12034pas1203489y13280989y132809h') } + let(:invitee) { User.create!(first_name: 'Lee', last_name: 'Ray', email: 'lee@ray.com', password: 'pas1203489y132809h132809hss1203489y132spa1203489y809h') } + + context 'as a group owner' do + it 'inviting from user profile' do + sign_in_as(owner) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + + visit user_path(invitee.id) + page.select group.name, from: 'invitation[group_id]' + fill_in 'invitation[comment]', with: 'Would you like to join?' + click_on 'Submit' + + expect(page).to have_content 'Invitation sent.' + end + + it 'inviting from group page' do + sign_in_as(owner) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + + fill_in 'email', with: invitee.email + fill_in 'invitation[comment]', with: 'Would you like to join our great group?' + click_on 'Submit' + + expect(page).to have_content 'Invitation sent.' + end + end + + let(:group) { Group.create(name: 'Gift giving', description: 'We love gifts', gift_due_date: '2019-01-01') } + let(:owner) { User.create(first_name: 'Ray', last_name: 'Lee', email: 'email@ray.lee', password: 'hspa1203489y132809hss12034pas1203489y13280989y132809h') } + let(:invitee) { User.create!(first_name: 'Lee', last_name: 'Ray', email: 'lee@ray.com', password: 'pas1203489y132809h132809hss1203489y132spa1203489y809h') } + + context 'not as a group owner' do + it 'from user profile' do + sign_in_as(invitee) + + visit user_path(owner.id) + expect(page).to have_no_content "Invite #{owner.first_name} #{owner.last_name} to a Group", 'Submit' + end + + it 'from group page' do + sign_in_as(owner) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + fill_in 'email', with: invitee.email + fill_in 'invitation[comment]', with: 'Would you like to join our great group?' + click_on 'Submit' + expect(page).to have_content 'Invitation sent.' + visit dashboard_path + click_on 'Sign Out' + + sign_in_as(invitee) + click_on 'Accept' + expect(page).to have_no_content 'Send an invitation', 'Submit' + + end + end +end diff --git a/spec/features/invitations/replying_to_invitation_spec.rb b/spec/features/invitations/replying_to_invitation_spec.rb new file mode 100644 index 0000000..2f9fefb --- /dev/null +++ b/spec/features/invitations/replying_to_invitation_spec.rb @@ -0,0 +1,63 @@ +require 'rails_helper' + +describe 'replaying to an invitation' do + let(:group) { Group.create(name: 'Gift giving', description: 'We love gifts', gift_due_date: '2019-01-01') } + let(:owner) { User.create(first_name: 'Ray', last_name: 'Lee', email: 'email@ray.lee', password: 'hspa1203489y132809hss12034pas1203489y13280989y132809h') } + let(:invitee) { User.create!(first_name: 'Lee', last_name: 'Ray', email: 'lee@ray.com', password: 'pas1203489y132809h132809hss1203489y132spa1203489y809h') } + + it 'by accepting' do + sign_in_as(owner) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + visit user_path(invitee.id) + page.select group.name, from: 'invitation[group_id]' + fill_in 'invitation[comment]', with: 'Would you like to join?' + click_on 'Submit' + expect(page).to have_content 'Invitation sent.' + visit dashboard_path + click_on 'Sign Out' + + visit root_path + sign_in_as(invitee) + expect(current_path).to eq dashboard_path + expect(page).to have_content "#{owner.first_name} #{owner.last_name} has invited you to join the group #{group.name}!" + expect(page).to have_content 'Accept', 'Decline' + click_on 'Accept' + + expect(page).to have_content "Invitation accepted." + expect(page).to have_link group.name + expect(page).to have_content group.description + click_on group.name + + # might change over time: + expect(page).to have_content "#{owner.first_name} #{owner.last_name}: Profile Wish List (Group Owner)" + expect(page).to have_content "#{invitee.first_name} #{invitee.last_name}:" + expect(page).to have_link "View your Wish List" + end + + it 'by declining' do + sign_in_as(owner) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + visit user_path(invitee.id) + page.select group.name, from: 'invitation[group_id]' + fill_in 'invitation[comment]', with: 'Would you like to join?' + click_on 'Submit' + expect(page).to have_content 'Invitation sent.' + visit dashboard_path + click_on 'Sign Out' + + visit root_path + sign_in_as(invitee) + expect(current_path).to eq dashboard_path + expect(page).to have_content "#{owner.first_name} #{owner.last_name} has invited you to join the group #{group.name}!" + expect(page).to have_content 'Accept', 'Decline' + click_on 'Decline' + + expect(page).to have_content "Invitation declined." + expect(page).to have_no_content group.name + end + +end From 2312be8dfa0c78b1dc276f65c303fa7f5a583ec4 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 21:00:41 -0600 Subject: [PATCH 57/73] Inserts a form email_field_tag for the email address of the receiver. --- app/controllers/invitations_controller.rb | 7 ++++--- app/views/groups/_invitation_form.html.erb | 16 ++++++++-------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/app/controllers/invitations_controller.rb b/app/controllers/invitations_controller.rb index dacac63..e1e5977 100644 --- a/app/controllers/invitations_controller.rb +++ b/app/controllers/invitations_controller.rb @@ -4,6 +4,7 @@ def create @invitation.sender_id = current_user.id @invitation.receiver_id = params[:user_id] @invitation.save + flash[:notice] = 'Invitation sent.' redirect_to user_path(@invitation.receiver_id) end @@ -15,6 +16,7 @@ def accept @invitation.save @user.groups << @group create_list + flash[:notice] = 'Invitation accepted.' redirect_to dashboard_path end @@ -22,12 +24,12 @@ def decline @invitation = Invitation.find(params[:id]) @invitation.accepted = false @invitation.save + flash[:notice] = 'Invitation declined.' redirect_to dashboard_path end def invite # sent from the groups page, by the group owner - receiver = User.find_by(email: downcase_email_param) group = Group.find(params[:group_id]) if receiver @@ -73,7 +75,6 @@ def create_list end def downcase_email_param - # params[:invitation][:receiver_id] is a string for an email - params[:invitation][:receiver_id].downcase + params[:email].downcase end end diff --git a/app/views/groups/_invitation_form.html.erb b/app/views/groups/_invitation_form.html.erb index 00c63bc..56851c4 100644 --- a/app/views/groups/_invitation_form.html.erb +++ b/app/views/groups/_invitation_form.html.erb @@ -1,13 +1,13 @@ <%= form_for :invitation, { url: group_invite_path(@group.id) } do |f| %> -

    - <%= f.label :receiver_id, 'Email' %> - <%= f.text_field :receiver_id %> -

    -

    +

    + <%= label_tag 'Email' %> + <%= email_field_tag 'email' %> +
    +
    <%= f.label :comment, "Message" %>
    <%= f.text_field :comment %> -

    -

    +

    +
    <%= f.submit 'Submit' %> -

    +
    <% end %> From e3f407ef0d0933cd41db9de93930fbb548c37251 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 21:35:40 -0600 Subject: [PATCH 58/73] Adds edge case tests. --- .../invitations/creating_invitation_spec.rb | 28 +++++++++- .../replying_to_invitation_spec.rb | 55 +++++++++++++++---- 2 files changed, 70 insertions(+), 13 deletions(-) diff --git a/spec/features/invitations/creating_invitation_spec.rb b/spec/features/invitations/creating_invitation_spec.rb index dbd25e9..f60623b 100644 --- a/spec/features/invitations/creating_invitation_spec.rb +++ b/spec/features/invitations/creating_invitation_spec.rb @@ -20,6 +20,16 @@ expect(page).to have_content 'Invitation sent.' end + it 'inviting from group owner user profile' do + sign_in_as(owner) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + + visit user_path(owner.id) + expect(page).to have_no_content "Invite #{owner.first_name} #{owner.last_name} to a Group", 'Submit' + end + it 'inviting from group page' do sign_in_as(owner) click_on 'Create a Group' @@ -32,6 +42,20 @@ expect(page).to have_content 'Invitation sent.' end + + it 'inviting self from group page' do + sign_in_as(owner) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + + fill_in 'email', with: owner.email + fill_in 'invitation[comment]', with: 'Would you like to join our great group?' + click_on 'Submit' + + expect(page).to have_content "#{owner.first_name} #{owner.last_name}:" + expect(page).to have_content "Invitation sent to user's email." # Failing conditional branch + end end let(:group) { Group.create(name: 'Gift giving', description: 'We love gifts', gift_due_date: '2019-01-01') } @@ -55,13 +79,11 @@ fill_in 'invitation[comment]', with: 'Would you like to join our great group?' click_on 'Submit' expect(page).to have_content 'Invitation sent.' - visit dashboard_path - click_on 'Sign Out' + sign_out sign_in_as(invitee) click_on 'Accept' expect(page).to have_no_content 'Send an invitation', 'Submit' - end end end diff --git a/spec/features/invitations/replying_to_invitation_spec.rb b/spec/features/invitations/replying_to_invitation_spec.rb index 2f9fefb..c49710a 100644 --- a/spec/features/invitations/replying_to_invitation_spec.rb +++ b/spec/features/invitations/replying_to_invitation_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' -describe 'replaying to an invitation' do +describe 'replying to an invitation' do let(:group) { Group.create(name: 'Gift giving', description: 'We love gifts', gift_due_date: '2019-01-01') } let(:owner) { User.create(first_name: 'Ray', last_name: 'Lee', email: 'email@ray.lee', password: 'hspa1203489y132809hss12034pas1203489y13280989y132809h') } let(:invitee) { User.create!(first_name: 'Lee', last_name: 'Ray', email: 'lee@ray.com', password: 'pas1203489y132809h132809hss1203489y132spa1203489y809h') } @@ -15,8 +15,7 @@ fill_in 'invitation[comment]', with: 'Would you like to join?' click_on 'Submit' expect(page).to have_content 'Invitation sent.' - visit dashboard_path - click_on 'Sign Out' + sign_out visit root_path sign_in_as(invitee) @@ -27,7 +26,7 @@ expect(page).to have_content "Invitation accepted." expect(page).to have_link group.name - expect(page).to have_content group.description + expect(page).to have_content group.description click_on group.name # might change over time: @@ -41,15 +40,12 @@ click_on 'Create a Group' create_group(group) click_on 'Create Group' - visit user_path(invitee.id) - page.select group.name, from: 'invitation[group_id]' - fill_in 'invitation[comment]', with: 'Would you like to join?' + fill_in 'email', with: invitee.email + fill_in 'invitation[comment]', with: 'Would you like to join our great group?' click_on 'Submit' expect(page).to have_content 'Invitation sent.' - visit dashboard_path - click_on 'Sign Out' + sign_out - visit root_path sign_in_as(invitee) expect(current_path).to eq dashboard_path expect(page).to have_content "#{owner.first_name} #{owner.last_name} has invited you to join the group #{group.name}!" @@ -59,5 +55,44 @@ expect(page).to have_content "Invitation declined." expect(page).to have_no_content group.name end +end +describe 'replying to an invitation' do + let(:group) { Group.create(name: 'Gift giving', description: 'We love gifts', gift_due_date: '2019-01-01') } + let(:owner) { User.create(first_name: 'Ray', last_name: 'Lee', email: 'email@ray.lee', password: 'hspa1203489y132809hss12034pas1203489y13280989y132809h') } + let(:invitee) { User.create!(first_name: 'Lee', last_name: 'Ray', email: 'lee@ray.com', password: 'pas1203489y132809h132809hss1203489y132spa1203489y809h') } + + context 'by declining' do + it 'and the owner submitting another invitation' do + sign_in_as(owner) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + fill_in 'email', with: invitee.email + fill_in 'invitation[comment]', with: 'Would you like to join our great group?' + click_on 'Submit' + expect(page).to have_content 'Invitation sent.' + sign_out + + sign_in_as(invitee) + expect(current_path).to eq dashboard_path + expect(page).to have_content "#{owner.first_name} #{owner.last_name} has invited you to join the group #{group.name}!" + expect(page).to have_content 'Accept', 'Decline' + click_on 'Decline' + expect(page).to have_content "Invitation declined." + expect(page).to have_no_content group.name + sign_out + + sign_in_as(owner) + click_on group.name + fill_in 'email', with: invitee.email + fill_in 'invitation[comment]', with: 'Would you like to join our great group?' + click_on 'Submit' + expect(page).to have_content "Invitation sent to user's email." # Failing conditional branch + + sign_out + sign_in_as(invitee) + expect(page).to have_no_content group.name + end + end end From 694059c465bc153c1f692ea563028a7897b82b4a Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 21:36:07 -0600 Subject: [PATCH 59/73] Renamed file and added sign_out helper method. --- spec/support/features/navigation_helpers.rb | 33 +++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 spec/support/features/navigation_helpers.rb diff --git a/spec/support/features/navigation_helpers.rb b/spec/support/features/navigation_helpers.rb new file mode 100644 index 0000000..acd623f --- /dev/null +++ b/spec/support/features/navigation_helpers.rb @@ -0,0 +1,33 @@ +module Features + def sign_in + @user = User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passp1203489y132809hass') + sign_in_as(@user) + end + + def sign_in_as(user) + visit login_path + fill_in 'Email', with: user.email + fill_in 'Password', with: user.password + click_on 'Log In' + end + + def fill_out_user_signup_no_email(user) + fill_in('user[first_name]', with: user.first_name) + fill_in('user[last_name]', with: user.last_name) + fill_in('user[password]', with: user.password) + fill_in('user[password_confirmation]', with: user.password) + end + + def dashboard_path_content(user) + expect(page).to have_content "Welcome, #{user.first_name}." + expect(page).to have_link 'Sign Out' + expect(page).to have_link 'Profile' + expect(page).not_to have_link 'Log In' + expect(page).not_to have_link 'Sign Up' + end + + def sign_out + visit dashboard_path + click_on 'Sign Out' + end +end From 7538f09423bd58475f0c4f1d106d5be14a7c60cc Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Fri, 26 Oct 2018 21:37:12 -0600 Subject: [PATCH 60/73] Renamed file. --- spec/support/features/sign_in.rb | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 spec/support/features/sign_in.rb diff --git a/spec/support/features/sign_in.rb b/spec/support/features/sign_in.rb deleted file mode 100644 index d299e30..0000000 --- a/spec/support/features/sign_in.rb +++ /dev/null @@ -1,28 +0,0 @@ -module Features - def sign_in - @user = User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'passp1203489y132809hass') - sign_in_as(@user) - end - - def sign_in_as(user) - visit login_path - fill_in 'Email', with: user.email - fill_in 'Password', with: user.password - click_on 'Log In' - end - - def fill_out_user_signup_no_email(user) - fill_in('user[first_name]', with: user.first_name) - fill_in('user[last_name]', with: user.last_name) - fill_in('user[password]', with: user.password) - fill_in('user[password_confirmation]', with: user.password) - end - - def dashboard_path_content(user) - expect(page).to have_content "Welcome, #{user.first_name}." - expect(page).to have_link 'Sign Out' - expect(page).to have_link 'Profile' - expect(page).not_to have_link 'Log In' - expect(page).not_to have_link 'Sign Up' - end -end From 106611631d35eb624deae5395f838d389b546254 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Mon, 5 Nov 2018 18:33:32 -0700 Subject: [PATCH 61/73] Removes ability to accept or decline invitations for another user. --- app/controllers/application_controller.rb | 2 +- app/controllers/invitations_controller.rb | 53 +++++++++++++++-------- config/routes.rb | 2 +- 3 files changed, 37 insertions(+), 20 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 8269b94..9365558 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -23,7 +23,7 @@ def root_path_if_not_logged_in def unauthorized_user(user) if !authorized_user(user) - flash[:warning] = 'This action is unauthorized.' + flash[:warning] = 'Action is unauthorized.' redirect_to root_path end end diff --git a/app/controllers/invitations_controller.rb b/app/controllers/invitations_controller.rb index e1e5977..47baadc 100644 --- a/app/controllers/invitations_controller.rb +++ b/app/controllers/invitations_controller.rb @@ -9,23 +9,40 @@ def create end def accept - @invitation = Invitation.find(params[:id]) - @user = User.find(@invitation.receiver_id) - @group = Group.find(@invitation.group_id) - @invitation.accepted = true - @invitation.save - @user.groups << @group - create_list - flash[:notice] = 'Invitation accepted.' - redirect_to dashboard_path + invitation = Invitation.find(params[:id]) + user = User.find(invitation.receiver_id) + byebug + if authorized_user(user) + group = Group.find(invitation.group_id) + invitation.accepted = true + invitation.save + if !user.groups.include?(group) + user.groups << group + create_list + flash[:notice] = 'Invitation accepted.' + redirect_to dashboard_path + else + flash[:warning] = 'You already belongs to this group.' + redirect_to dashboard_path + end + else + flash[:warning] = 'Action is unauthorized.' + redirect_to root_path + end end def decline - @invitation = Invitation.find(params[:id]) - @invitation.accepted = false - @invitation.save - flash[:notice] = 'Invitation declined.' - redirect_to dashboard_path + invitation = Invitation.find(params[:id]) + user = User.find(invitation.receiver_id) + if authorized_user(user) + invitation.accepted = false + invitation.save + flash[:notice] = 'Invitation declined.' + redirect_to dashboard_path + else + flash[:warning] = 'Action is unauthorized.' + redirect_to root_path + end end def invite @@ -68,10 +85,10 @@ def invitation_params end def create_list - @list = List.new - @list.user_id = current_user.id - @list.group_id = @group.id - @list.save + list = List.new + list.user_id = current_user.id + list.group_id = @group.id + list.save end def downcase_email_param diff --git a/config/routes.rb b/config/routes.rb index fe0db75..4bbd761 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -15,7 +15,7 @@ delete '/logout' => 'sessions#destroy', as: 'logout' resources :users, only: [:show, :create, :edit, :update] do - resources :invitations, only: [:show, :create] + resources :invitations, only: [:create] end get '/accept/:id' => 'invitations#accept', as: 'accept' get '/decline/:id' => 'invitations#decline', as: 'decline' From 4b465594d28bba37f79c42f4bbf7faef11b9e9ac Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Mon, 5 Nov 2018 18:34:07 -0700 Subject: [PATCH 62/73] Modifies model associations. --- app/models/invitation.rb | 4 ++-- app/models/user.rb | 6 +++--- app/models/user_group.rb | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/models/invitation.rb b/app/models/invitation.rb index 5cf9a17..91bd1ac 100644 --- a/app/models/invitation.rb +++ b/app/models/invitation.rb @@ -1,6 +1,6 @@ class Invitation < ApplicationRecord - belongs_to :user, foreign_key: :sender_id - belongs_to :user, foreign_key: :receiver_id + belongs_to :sender, foreign_key: :sender_id, class_name: 'User' + belongs_to :receiver, foreign_key: :receiver_id, class_name: 'User' belongs_to :group validates :comment, presence: true end diff --git a/app/models/user.rb b/app/models/user.rb index 3b9f422..cb9f51e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,15 +1,15 @@ class User < ApplicationRecord - has_many :user_groups has_many :groups, through: :user_groups has_many :lists - has_many :invitations + has_many :received, foreign_key: :receiver_id, class_name: 'Invitation' + has_many :sent, foreign_key: :sender_id, class_name: 'Invitation' validates_uniqueness_of :email + validates_uniqueness_of :id, scope: [:user_groups, :groups] validates :first_name, presence: true validates :last_name, presence: true validates :email, presence: true - include ActiveModel::Validations has_secure_password validates :password, password_strength: {use_dictionary: true} end diff --git a/app/models/user_group.rb b/app/models/user_group.rb index 99451fc..1d123a5 100644 --- a/app/models/user_group.rb +++ b/app/models/user_group.rb @@ -1,4 +1,5 @@ class UserGroup < ApplicationRecord belongs_to :user belongs_to :group + validates_uniqueness_of :user_id, scope: :group_id, message: 'already belongs to this group.' end From 0b294d914e1385d717abfa3f4286025043c279c5 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Mon, 5 Nov 2018 18:35:05 -0700 Subject: [PATCH 63/73] Removes byebug. --- app/controllers/invitations_controller.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/invitations_controller.rb b/app/controllers/invitations_controller.rb index 47baadc..fb195d3 100644 --- a/app/controllers/invitations_controller.rb +++ b/app/controllers/invitations_controller.rb @@ -11,7 +11,6 @@ def create def accept invitation = Invitation.find(params[:id]) user = User.find(invitation.receiver_id) - byebug if authorized_user(user) group = Group.find(invitation.group_id) invitation.accepted = true From ec779785cc09af2954c1678ddc334545cf25b28c Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Mon, 5 Nov 2018 19:20:25 -0700 Subject: [PATCH 64/73] Passing tests. --- app/controllers/groups_controller.rb | 2 +- app/controllers/invitations_controller.rb | 6 +++--- app/views/groups/show.html.erb | 4 ++-- spec/features/groups/creating_group_spec.rb | 4 ++-- spec/features/groups/deleting_group_spec.rb | 6 +++--- spec/features/items/creating_item_spec.rb | 8 ++++---- spec/features/items/deleting_item_spec.rb | 2 +- spec/features/items/editing_item_spec.rb | 8 ++++---- spec/models/invitation_spec.rb | 9 +++++++-- spec/models/item_spec.rb | 21 ++++++++++++--------- spec/models/user_spec.rb | 9 +++++++-- 11 files changed, 46 insertions(+), 33 deletions(-) diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 07c6878..b6ed021 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -49,7 +49,7 @@ def destroy @lists = List.where("group_id = :group_id", {group_id: @group.id}) if !@lists.empty? @lists.each do |list| - items = Item.where("lists_id = :list_id", {list_id: list.id}) + items = Item.where("list_id = :list_id", {list_id: list.id}) items.each { |item| item.destroy } list.destroy end diff --git a/app/controllers/invitations_controller.rb b/app/controllers/invitations_controller.rb index fb195d3..a3beb40 100644 --- a/app/controllers/invitations_controller.rb +++ b/app/controllers/invitations_controller.rb @@ -12,11 +12,11 @@ def accept invitation = Invitation.find(params[:id]) user = User.find(invitation.receiver_id) if authorized_user(user) - group = Group.find(invitation.group_id) + @group = Group.find(invitation.group_id) invitation.accepted = true invitation.save - if !user.groups.include?(group) - user.groups << group + if !user.groups.include?(@group) + user.groups << @group create_list flash[:notice] = 'Invitation accepted.' redirect_to dashboard_path diff --git a/app/views/groups/show.html.erb b/app/views/groups/show.html.erb index 273e24d..123fc03 100644 --- a/app/views/groups/show.html.erb +++ b/app/views/groups/show.html.erb @@ -20,10 +20,9 @@ Gift Exchange Year: <%= @group.gift_due_date.year if @group.gift_due_date %>

    -<% if @group_owner %> +<% if authorized_user(@group.owner) %>

    Send an invitation

    <%= render partial: 'groups/invitation_form' %> - <% end %>
    @@ -35,6 +34,7 @@ Users in this group: <%= "#{user.first_name} #{user.last_name}: " %> <%= link_to 'Profile', user_path(user.id) %> <%= link_to "Wish List", group_list_path(@group.id, @group.user_wish_list(user).id) %> + <%= "(Group Owner)" if @group.owner.id == user.id %> <% end %>
diff --git a/spec/features/groups/creating_group_spec.rb b/spec/features/groups/creating_group_spec.rb index b3544e2..631c6e6 100644 --- a/spec/features/groups/creating_group_spec.rb +++ b/spec/features/groups/creating_group_spec.rb @@ -24,7 +24,7 @@ fill_in('group_description', with: '') click_on 'Create Group' - expect(page).to have_content "The Gift Due Date can't be blank, or the Group Name is already taken." + expect(page).to have_content "The group name is already taken. Please choose another name." end end @@ -57,7 +57,7 @@ it 'not logged in' do visit profile_path expect(current_path).to eq root_path - expect(page).to have_content 'You must be logged in first.' + expect(page).to have_content 'You need to be logged in first.' end end end diff --git a/spec/features/groups/deleting_group_spec.rb b/spec/features/groups/deleting_group_spec.rb index 092103e..5813187 100644 --- a/spec/features/groups/deleting_group_spec.rb +++ b/spec/features/groups/deleting_group_spec.rb @@ -29,7 +29,7 @@ visit dashboard_path click_on group.name click_on 'View your Wish List' - click_on 'Create a new Wish list item' + click_on 'Add an item to your wish list' create_item(item_one) click_on 'Create Item' click_on 'Back to Group' @@ -48,10 +48,10 @@ click_on group.name click_on 'View your Wish List' - click_on 'Create a new Wish list item' + click_on 'Add an item to your wish list' create_item(item_one) click_on 'Create Item' - click_on 'Create a new Wish list item' + click_on 'Add an item to your wish list' create_item(item_two) click_on 'Create Item' click_on 'Back to Group' diff --git a/spec/features/items/creating_item_spec.rb b/spec/features/items/creating_item_spec.rb index f68435d..2cb0e84 100644 --- a/spec/features/items/creating_item_spec.rb +++ b/spec/features/items/creating_item_spec.rb @@ -15,7 +15,7 @@ visit dashboard_path click_on group.name click_on 'View your Wish List' - click_on 'Create a new Wish list item' + click_on 'Add an item to your wish list' create_item(item_one) click_on 'Create Item' @@ -36,7 +36,7 @@ visit dashboard_path click_on group.name click_on 'View your Wish List' - click_on 'Create a new Wish list item' + click_on 'Add an item to your wish list' click_on 'Create Item' expect(page).to have_content 'Please enter valid information.' @@ -50,12 +50,12 @@ visit dashboard_path click_on group.name click_on 'View your Wish List' - click_on 'Create a new Wish list item' + click_on 'Add an item to your wish list' create_item(item_one) click_on 'Create Item' expect(page).to have_link item_one.name - click_on 'Create a new Wish list item' + click_on 'Add an item to your wish list' create_item(item_two) click_on 'Create Item' diff --git a/spec/features/items/deleting_item_spec.rb b/spec/features/items/deleting_item_spec.rb index 31632ea..3d71256f 100644 --- a/spec/features/items/deleting_item_spec.rb +++ b/spec/features/items/deleting_item_spec.rb @@ -13,7 +13,7 @@ visit dashboard_path click_on group.name click_on 'View your Wish List' - click_on 'Create a new Wish list item' + click_on 'Add an item to your wish list' create_item(item_one) click_on 'Create Item' diff --git a/spec/features/items/editing_item_spec.rb b/spec/features/items/editing_item_spec.rb index 3245af7..0f0de93 100644 --- a/spec/features/items/editing_item_spec.rb +++ b/spec/features/items/editing_item_spec.rb @@ -15,7 +15,7 @@ visit dashboard_path click_on group.name click_on 'View your Wish List' - click_on 'Create a new Wish list item' + click_on 'Add an item to your wish list' create_item(item_one) click_on 'Create Item' @@ -40,7 +40,7 @@ visit dashboard_path click_on group.name click_on 'View your Wish List' - click_on 'Create a new Wish list item' + click_on 'Add an item to your wish list' click_on 'Create Item' expect(page).to have_content 'Please enter valid information.' @@ -54,12 +54,12 @@ visit dashboard_path click_on group.name click_on 'View your Wish List' - click_on 'Create a new Wish list item' + click_on 'Add an item to your wish list' create_item(item_one) click_on 'Create Item' expect(page).to have_link item_one.name - click_on 'Create a new Wish list item' + click_on 'Add an item to your wish list' create_item(item_two) click_on 'Create Item' diff --git a/spec/models/invitation_spec.rb b/spec/models/invitation_spec.rb index 084f86e..6353b7e 100644 --- a/spec/models/invitation_spec.rb +++ b/spec/models/invitation_spec.rb @@ -24,8 +24,13 @@ end context 'associations' do - it 'belongs to user' do - assc = Invitation.reflect_on_association(:user) + it 'belongs to receiver' do + assc = Invitation.reflect_on_association(:receiver) + expect(assc.macro).to eq :belongs_to + end + + it 'belongs to receiver' do + assc = Invitation.reflect_on_association(:sender) expect(assc.macro).to eq :belongs_to end diff --git a/spec/models/item_spec.rb b/spec/models/item_spec.rb index 7737862..b89ec3e 100644 --- a/spec/models/item_spec.rb +++ b/spec/models/item_spec.rb @@ -2,31 +2,34 @@ describe Item do context 'validations' do + let(:owner) { User.create!(first_name: 'Henry', last_name: 'Pgg', email: 'hpgg', password: '10893420yoiudfs', password_confirmation: '10893420yoiudfs') } + let(:group) { Group.create!(name: 'Testing!', description: 'Wow', owner_id: owner.id, gift_due_date: '2018-12-13') } + let(:list) { List.create!(group_id: group.id, user_id: owner.id) } it 'validates name needs to be present' do - i = Item.new(name: nil, description: 'my lovely gift', size: 'Large', note: 'Apples') - expect(i.valid?).to eq false + item = Item.new(name: nil, description: 'my lovely gift', size: 'Large', note: 'Apples', list_id: list.id) + expect(item.valid?).to eq false end it 'validates description needs to be present' do - i = Item.new(name: 'Purse', description: nil, size: 'Large', note: 'Apples') - expect(i.valid?).to eq false + item = Item.new(name: 'Purse', description: nil, size: 'Large', note: 'Apples', list_id: list.id) + expect(item.valid?).to eq false end it 'validates size is optional' do - i = Item.new(name: 'Purse', description: 'my lovely gift', size: '', note: 'Apples') - expect(i.valid?).to eq true + item = Item.new(name: 'Purse', description: 'my lovely gift', size: '', note: 'Apples', list_id: list.id) + expect(item.valid?).to eq true end it 'validates note is optional' do - i = Item.new(name: 'Purse', description: 'my lovely gift', size: 'Window', note: '') - expect(i.valid?).to eq true + item = Item.new(name: 'Purse', description: 'my lovely gift', size: 'Window', note: '', list_id: list.id) + expect(item.valid?).to eq true end end context 'associations' do it 'has one list' do assc = Item.reflect_on_association(:list) - expect(assc.macro).to eq :has_one + expect(assc.macro).to eq :belongs_to end end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index fbbbec1..df0f502 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -81,8 +81,13 @@ expect(assc.macro).to eq :has_many end - it 'has many invitations' do - assc = User.reflect_on_association(:invitations) + it 'has many received invitations' do + assc = User.reflect_on_association(:received) + expect(assc.macro).to eq :has_many + end + + it 'has many sent invitations' do + assc = User.reflect_on_association(:sent) expect(assc.macro).to eq :has_many end From 41b568f526268211b7f41e036ba0446028e3f1a0 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Tue, 6 Nov 2018 09:39:00 -0700 Subject: [PATCH 65/73] Adds shoulda-matchers gem for testing. --- Gemfile | 2 ++ Gemfile.lock | 8 ++++++++ spec/rails_helper.rb | 7 +++++++ 3 files changed, 17 insertions(+) diff --git a/Gemfile b/Gemfile index b8e36c7..60a2c2c 100644 --- a/Gemfile +++ b/Gemfile @@ -47,6 +47,8 @@ end group :test do gem 'database_cleaner' + gem 'shoulda-matchers', '4.0.0.rc1' + gem 'rails-controller-testing' end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index e09ff3d..23f70a0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -124,6 +124,10 @@ GEM bundler (>= 1.3.0) railties (= 5.2.1) sprockets-rails (>= 2.0.0) + rails-controller-testing (1.0.2) + actionpack (~> 5.x, >= 5.0.1) + actionview (~> 5.x, >= 5.0.1) + activesupport (~> 5.x) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) @@ -169,6 +173,8 @@ GEM sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) + shoulda-matchers (4.0.0.rc1) + activesupport (>= 4.2.0) sprockets (3.7.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) @@ -212,8 +218,10 @@ DEPENDENCIES pg (>= 0.18, < 2.0) puma (~> 3.11) rails (~> 5.2.0) + rails-controller-testing rspec-rails (~> 3.7) sass-rails (~> 5.0) + shoulda-matchers (= 4.0.0.rc1) strong_password (~> 0.0.6) tzinfo-data uglifier (>= 1.3.0) diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index c614c4c..6026d60 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -57,3 +57,10 @@ config.include Features, type: :feature end + +Shoulda::Matchers.configure do |config| + config.integrate do |with| + with.test_framework :rspec + with.library :rails + end +end From c50de4af4baab6c434fea8270949b89e43796a00 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Tue, 6 Nov 2018 10:35:01 -0700 Subject: [PATCH 66/73] Adds testing for unauthorized access. --- spec/features/groups/editing_group_spec.rb | 11 +++++ .../invitations/creating_invitation_spec.rb | 25 +++++++++++ .../replying_to_invitation_spec.rb | 42 +++++++++++++++++++ spec/features/items/creating_item_spec.rb | 13 ++++++ spec/features/items/editing_item_spec.rb | 13 ++++++ spec/models/user_group_spec.rb | 9 ++++ 6 files changed, 113 insertions(+) diff --git a/spec/features/groups/editing_group_spec.rb b/spec/features/groups/editing_group_spec.rb index 1dd3f5b..3fbd759 100644 --- a/spec/features/groups/editing_group_spec.rb +++ b/spec/features/groups/editing_group_spec.rb @@ -44,4 +44,15 @@ expect(page).to have_content 'Please enter valid information.' end end + + context 'attempt for' do + let(:user_one) { User.create!(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'pas1203489y132809hspas1203489y132809hs') } + let(:user_two) { User.create!(first_name: 'A', last_name: 'Zzrz', email: 'emaaaail@raa.zzz', password: 'pas1203489y132809hspas1203489y132809hs') } + let(:group) { Group.create!(name: 'My first group creation', description: 'Whoever wants to join', gift_due_date: '2018/12/31', owner_id: user_one.id) } + it 'another user' do + sign_in_as(user_two) + visit "/groups/#{group.id}/edit" + expect(page).to have_content "Action is unauthorized." + end + end end diff --git a/spec/features/invitations/creating_invitation_spec.rb b/spec/features/invitations/creating_invitation_spec.rb index f60623b..0882518 100644 --- a/spec/features/invitations/creating_invitation_spec.rb +++ b/spec/features/invitations/creating_invitation_spec.rb @@ -56,6 +56,31 @@ expect(page).to have_content "#{owner.first_name} #{owner.last_name}:" expect(page).to have_content "Invitation sent to user's email." # Failing conditional branch end + + it 'inviting with a blank comment' do + sign_in_as(owner) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + + fill_in 'email', with: owner.email + click_on 'Submit' + + expect(page).to have_content "Invitation sent to user's email." # Failing conditional branch + end + + it 'inviting with a blank email' do + sign_in_as(owner) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + + # fill_in 'email', with: owner.email + fill_in 'invitation[comment]', with: 'Would you like to join our great group?' + click_on 'Submit' + + expect(page).to have_content "Invitation sent to user's email." # Failing conditional branch + end end let(:group) { Group.create(name: 'Gift giving', description: 'We love gifts', gift_due_date: '2019-01-01') } diff --git a/spec/features/invitations/replying_to_invitation_spec.rb b/spec/features/invitations/replying_to_invitation_spec.rb index c49710a..85df0cd 100644 --- a/spec/features/invitations/replying_to_invitation_spec.rb +++ b/spec/features/invitations/replying_to_invitation_spec.rb @@ -61,6 +61,7 @@ let(:group) { Group.create(name: 'Gift giving', description: 'We love gifts', gift_due_date: '2019-01-01') } let(:owner) { User.create(first_name: 'Ray', last_name: 'Lee', email: 'email@ray.lee', password: 'hspa1203489y132809hss12034pas1203489y13280989y132809h') } let(:invitee) { User.create!(first_name: 'Lee', last_name: 'Ray', email: 'lee@ray.com', password: 'pas1203489y132809h132809hss1203489y132spa1203489y809h') } + let(:user) { User.create!(first_name: 'Lee', last_name: 'Ray', email: 'leasdfe@ray.com', password: 'pas1203489y132809h13280dsfsdsdf9hss1203489y132spa1203489y809h') } context 'by declining' do it 'and the owner submitting another invitation' do @@ -95,4 +96,45 @@ expect(page).to have_no_content group.name end end + + context 'for another user' do + it 'accepting' do + sign_in_as(owner) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + fill_in 'email', with: invitee.email + fill_in 'invitation[comment]', with: 'Would you like to join our great group?' + click_on 'Submit' + expect(page).to have_content 'Invitation sent.' + sign_out + + sign_in_as(user) + expect(current_path).to eq dashboard_path + expect(page).to have_no_content "#{owner.first_name} #{owner.last_name} has invited you to join the group #{group.name}!" + expect(page).to have_no_content 'Accept', 'Decline' + visit "/accept/#{invitee.received.first.id}" + expect(page).to have_content 'Action is unauthorized' + + end + + it 'declining' do + sign_in_as(owner) + click_on 'Create a Group' + create_group(group) + click_on 'Create Group' + fill_in 'email', with: invitee.email + fill_in 'invitation[comment]', with: 'Would you like to join our great group?' + click_on 'Submit' + expect(page).to have_content 'Invitation sent.' + sign_out + + sign_in_as(user) + expect(current_path).to eq dashboard_path + expect(page).to have_no_content "#{owner.first_name} #{owner.last_name} has invited you to join the group #{group.name}!" + expect(page).to have_no_content 'Accept', 'Decline' + visit "/decline/#{invitee.received.first.id}" + expect(page).to have_content 'Action is unauthorized' + end + end end diff --git a/spec/features/items/creating_item_spec.rb b/spec/features/items/creating_item_spec.rb index 2cb0e84..6cbbc3a 100644 --- a/spec/features/items/creating_item_spec.rb +++ b/spec/features/items/creating_item_spec.rb @@ -3,6 +3,7 @@ describe 'item creation' do context 'with' do let(:user) { User.create(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'pas1203489y132809hspas1203489y132809hs') } + let(:user_two) { User.create(first_name: 'A', last_name: 'Zzrz', email: 'emaaaail@raa.zzz', password: 'pas1203489y132809hspas1203489y132809hs') } let(:group) { Group.create(name: 'My first group creation', description: 'Whoever wants to join', gift_due_date: '2018/12/31') } let(:item_one) { Item.create(name: 'Wallet', description: 'So pretty', size: 'XL', note: 'I would like many of these.') } let(:item_two) { Item.create(name: 'Shoes', description: 'So pretty!', size: 'L', note: 'I would like many of these please.') } @@ -68,4 +69,16 @@ item_page_content(item_two) end end + + context 'attempt for' do + let(:user_one) { User.create!(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'pas1203489y132809hspas1203489y132809hs') } + let(:user_two) { User.create!(first_name: 'A', last_name: 'Zzrz', email: 'emaaaail@raa.zzz', password: 'pas1203489y132809hspas1203489y132809hs') } + let(:group) { Group.create!(name: 'My first group creation', description: 'Whoever wants to join', gift_due_date: '2018/12/31', owner_id: user_one.id) } + let(:list) { List.create!(user_id: user_one.id, group_id: group.id) } + it 'another user' do + sign_in_as(user_two) + visit "/groups/#{group.id}/lists/#{list.id}/items/new" + expect(page).to have_content "Action is unauthorized." + end + end end diff --git a/spec/features/items/editing_item_spec.rb b/spec/features/items/editing_item_spec.rb index 0f0de93..8458fbd 100644 --- a/spec/features/items/editing_item_spec.rb +++ b/spec/features/items/editing_item_spec.rb @@ -72,4 +72,17 @@ item_page_content(item_two) end end + + context 'attempt for' do + let(:user_one) { User.create!(first_name: 'Raa', last_name: 'Zzz', email: 'email@raa.zzz', password: 'pas1203489y132809hspas1203489y132809hs') } + let(:user_two) { User.create!(first_name: 'A', last_name: 'Zzrz', email: 'emaaaail@raa.zzz', password: 'pas1203489y132809hspas1203489y132809hs') } + let(:group) { Group.create!(name: 'My first group creation', description: 'Whoever wants to join', gift_due_date: '2018/12/31', owner_id: user_one.id) } + let(:list) { List.create!(user_id: user_one.id, group_id: group.id) } + let(:item) { Item.create!(name: 'Wallet', description: 'So pretty', size: 'XL', note: 'I would like many of these.', list_id: list.id) } + it 'another user' do + sign_in_as(user_two) + visit "/groups/#{group.id}/lists/#{list.id}/items/#{item.id}/edit" + expect(page).to have_content "Action is unauthorized." + end + end end diff --git a/spec/models/user_group_spec.rb b/spec/models/user_group_spec.rb index 2ff1402..2e702a0 100644 --- a/spec/models/user_group_spec.rb +++ b/spec/models/user_group_spec.rb @@ -12,4 +12,13 @@ expect(assc.macro).to eq :belongs_to end end + + context 'validates' do + let(:user) { User.create(first_name: 'Aa', last_name: 'Zzz', email: 'emmail@raa.zzz', password: 'pa1203489y132809hsasdfspas1203489y132809hs') } + let(:group) { Group.create(name: 'My group creation!', description: 'Whoever wants to join it', gift_due_date: '2018/12/31', owner_id: user.id) } + subject { UserGroup.create!(user_id: user.id, group_id: group.id) } + context 'uniqueness of user within groups' do + it { should validate_uniqueness_of(:user_id).scoped_to(:group_id).with_message('already belongs to this group.') } + end + end end From 96342dde2c086f1b99bd2e974ca4a47955644540 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 7 Nov 2018 09:51:39 -0700 Subject: [PATCH 67/73] Moves query to user model. --- app/controllers/dashboard_controller.rb | 5 +---- app/models/user.rb | 5 ++++- app/views/dashboard/show.html.erb | 4 ++-- app/views/layouts/application.html.erb | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 2ca349e..22100ab 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -1,9 +1,6 @@ class DashboardController < ApplicationController def show - if current_user - @user = current_user - @invitations = Invitation.where("receiver_id = ? AND accepted IS NULL", @user.id) - else + if !current_user redirect_to root_path flash[:warning] = 'You must be logged in first.' end diff --git a/app/models/user.rb b/app/models/user.rb index cb9f51e..91fcb51 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -9,7 +9,10 @@ class User < ApplicationRecord validates :first_name, presence: true validates :last_name, presence: true validates :email, presence: true - has_secure_password validates :password, password_strength: {use_dictionary: true} + + def outstanding_invitations + Invitation.where('receiver_id = ? AND accepted IS NULL', id) + end end diff --git a/app/views/dashboard/show.html.erb b/app/views/dashboard/show.html.erb index 3f4ea15..e28cb23 100644 --- a/app/views/dashboard/show.html.erb +++ b/app/views/dashboard/show.html.erb @@ -3,9 +3,9 @@ <%= link_to 'Profile', profile_path %> <%= link_to 'Sign Out', logout_path, method: :delete %> - <% if @invitations %> + <% if !current_user.outstanding_invitations.empty? %>

Invitations

- <% @invitations.each do |invitation| %> + <% current_user.outstanding_invitations.each do |invitation| %> <% if invitation.accepted.nil? %>

<% user = User.find(invitation.sender_id) %> diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 67f5fab..121240d 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,7 +1,7 @@ - SecretSanta + Secret Santa <%= csrf_meta_tags %> <%= csp_meta_tag %> From e02fa50a366797f493ea10ce0fbf2e171100fbc7 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 7 Nov 2018 10:04:56 -0700 Subject: [PATCH 68/73] Refactors destroy action. Removes index action. --- app/controllers/groups_controller.rb | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index b6ed021..225a4d6 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -2,10 +2,6 @@ class GroupsController < ApplicationController before_action :set_group, only: [:show, :edit, :update, :destroy] before_action -> { unauthorized_user(@group.owner) }, only: [:update, :edit, :destroy] - def index # Delete for the future? - @groups = Group.all - end - def new @group = Group.new end @@ -46,18 +42,18 @@ def update end def destroy - @lists = List.where("group_id = :group_id", {group_id: @group.id}) - if !@lists.empty? - @lists.each do |list| - items = Item.where("list_id = :list_id", {list_id: list.id}) + lists = List.where(group_id: @group.id) + if !lists.empty? + lists.each do |list| + items = Item.where(list_id: list.id) items.each { |item| item.destroy } list.destroy end end - @invitations = Invitation.where("group_id = :group_id", {group_id: @group.id}) - if !@invitations.empty? - @invitations.each do |invitation| + invitations = Invitation.where(group_id: @group.id) + if !invitations.empty? + invitations.each do |invitation| invitation.destroy end end From ce60080785e97f158b735e645c440fa3abd402a3 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 7 Nov 2018 11:11:35 -0700 Subject: [PATCH 69/73] Adds date selector to group creation and editing. --- app/views/groups/_form.html.erb | 8 ++++++-- app/views/groups/show.html.erb | 2 +- spec/features/groups/creating_group_spec.rb | 2 +- spec/features/groups/editing_group_spec.rb | 4 ++-- spec/features/groups/group_visible_to_one_user_spec.rb | 4 ++-- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/app/views/groups/_form.html.erb b/app/views/groups/_form.html.erb index 36cb5ae..dfe4481 100644 --- a/app/views/groups/_form.html.erb +++ b/app/views/groups/_form.html.erb @@ -8,8 +8,12 @@ <%= f.text_area :description %>

- <%= f.label :gift_due_date, 'Gift Due Date (YYYY/MM/DD)' %> - <%= f.text_field :gift_due_date %> + <%= f.label 'group', 'Gift Due Date' %> + <% if action_name == 'new' %> + <%= date_field 'group', 'gift_due_date', min: Date.today %> + <% else %> + <%= date_field 'group', 'gift_due_date', min: @group.created_at %> + <% end %>
<%= f.submit %> diff --git a/app/views/groups/show.html.erb b/app/views/groups/show.html.erb index 123fc03..356bdd0 100644 --- a/app/views/groups/show.html.erb +++ b/app/views/groups/show.html.erb @@ -1,7 +1,7 @@

<%= @group.name %>

<%= @group.description %>
-Created on: <%= @group.created_at %> +Created on: <%= @group.created_at %>
Gift Due Date: <%= @group.gift_due_date %>
diff --git a/spec/features/groups/creating_group_spec.rb b/spec/features/groups/creating_group_spec.rb index 631c6e6..8c4cd6d 100644 --- a/spec/features/groups/creating_group_spec.rb +++ b/spec/features/groups/creating_group_spec.rb @@ -42,7 +42,7 @@ expect(current_path).to eq new_group_path fill_in('Name', with: group.name) fill_in('Description', with: group.description) - fill_in('Gift Due Date', with: group.gift_due_date.to_default_s) + fill_in('group_gift_due_date', with: group.gift_due_date.to_default_s) click_on 'Create Group' expect(page).to have_content group.name diff --git a/spec/features/groups/editing_group_spec.rb b/spec/features/groups/editing_group_spec.rb index 3fbd759..2fa60b6 100644 --- a/spec/features/groups/editing_group_spec.rb +++ b/spec/features/groups/editing_group_spec.rb @@ -18,7 +18,7 @@ fill_in 'Name', with: group.name + '!!' fill_in 'Description', with: group.description + '!!' - fill_in 'Gift Due Date', with: group.gift_due_date.next.to_default_s + fill_in 'group_gift_due_date', with: group.gift_due_date.next.to_default_s click_on 'Update Group' expect(page).to have_content group.name + '!!' @@ -38,7 +38,7 @@ fill_in 'Name', with: '' fill_in 'Description', with: '' - fill_in 'Gift Due Date', with: '' + fill_in 'group_gift_due_date', with: '' click_on 'Update Group' expect(page).to have_content 'Please enter valid information.' diff --git a/spec/features/groups/group_visible_to_one_user_spec.rb b/spec/features/groups/group_visible_to_one_user_spec.rb index 5fc7f6e..23fe477 100644 --- a/spec/features/groups/group_visible_to_one_user_spec.rb +++ b/spec/features/groups/group_visible_to_one_user_spec.rb @@ -13,7 +13,7 @@ expect(current_path).to eq new_group_path fill_in('Name', with: group_one.name) fill_in('Description', with: group_one.description) - fill_in('Gift Due Date', with: group_one.gift_due_date.to_default_s) + fill_in('group_gift_due_date', with: group_one.gift_due_date.to_default_s) click_on 'Create Group' sign_in_as(user_two) @@ -22,7 +22,7 @@ expect(current_path).to eq new_group_path fill_in('Name', with: group_two.name) fill_in('Description', with: group_two.description) - fill_in('Gift Due Date', with: group_two.gift_due_date.to_default_s) + fill_in('group_gift_due_date', with: group_two.gift_due_date.to_default_s) click_on 'Create Group' visit dashboard_path From 65b887ba86a21f551d7d4803e87a230a057c6c4e Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 7 Nov 2018 11:16:38 -0700 Subject: [PATCH 70/73] Changes user lookup to utilize AR relations. --- app/controllers/invitations_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/invitations_controller.rb b/app/controllers/invitations_controller.rb index a3beb40..78d8fa7 100644 --- a/app/controllers/invitations_controller.rb +++ b/app/controllers/invitations_controller.rb @@ -10,7 +10,7 @@ def create def accept invitation = Invitation.find(params[:id]) - user = User.find(invitation.receiver_id) + user = invitation.receiver if authorized_user(user) @group = Group.find(invitation.group_id) invitation.accepted = true @@ -32,7 +32,7 @@ def accept def decline invitation = Invitation.find(params[:id]) - user = User.find(invitation.receiver_id) + user = invitation.receiver if authorized_user(user) invitation.accepted = false invitation.save From f0202c03fa00fa791910141a99ae477b9b77c1a4 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 7 Nov 2018 11:19:22 -0700 Subject: [PATCH 71/73] Removes validation duplication. --- app/models/user.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index 91fcb51..81af84d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -5,7 +5,6 @@ class User < ApplicationRecord has_many :received, foreign_key: :receiver_id, class_name: 'Invitation' has_many :sent, foreign_key: :sender_id, class_name: 'Invitation' validates_uniqueness_of :email - validates_uniqueness_of :id, scope: [:user_groups, :groups] validates :first_name, presence: true validates :last_name, presence: true validates :email, presence: true From e8a9de506a70f14089a18be90f91fbb7f86457a9 Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Wed, 7 Nov 2018 11:27:21 -0700 Subject: [PATCH 72/73] Refactors conditional check. --- app/views/groups/_form.html.erb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/views/groups/_form.html.erb b/app/views/groups/_form.html.erb index dfe4481..1e9f02e 100644 --- a/app/views/groups/_form.html.erb +++ b/app/views/groups/_form.html.erb @@ -9,11 +9,7 @@
<%= f.label 'group', 'Gift Due Date' %> - <% if action_name == 'new' %> - <%= date_field 'group', 'gift_due_date', min: Date.today %> - <% else %> - <%= date_field 'group', 'gift_due_date', min: @group.created_at %> - <% end %> + <%= date_field 'group', 'gift_due_date', min: (action_name == 'new' ? Date.today : @group.created_at) %>
<%= f.submit %> From 55087d4f3f78c9a80df8f268fc71eda147b066bf Mon Sep 17 00:00:00 2001 From: Kurt Meyerhofer Date: Mon, 12 Nov 2018 09:03:52 -0700 Subject: [PATCH 73/73] Removes groups#index route. --- config/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index 4bbd761..1952114 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -21,7 +21,7 @@ get '/decline/:id' => 'invitations#decline', as: 'decline' - resources :groups do + resources :groups, except: [:index] do post '/invite' => 'invitations#invite', as: 'invite' resources :lists, only: [:show] do resources :items