From 0a07442317dd7dee93844529c64374c3f57e59d0 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 10 Jul 2019 11:36:03 +1200 Subject: [PATCH 001/151] Remove badge override --- app/assets/stylesheets/overrides.scss | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/assets/stylesheets/overrides.scss b/app/assets/stylesheets/overrides.scss index 11bac4567..79db1fb4a 100755 --- a/app/assets/stylesheets/overrides.scss +++ b/app/assets/stylesheets/overrides.scss @@ -28,14 +28,6 @@ a:hover { color: $blue; } -span.badge { - background-color: $brown; - - a { - color: $white; - } -} - .list-inline > li.first { padding-left: 0; } From ac3679fa18b4c90dedfd08eb447458bb10fa3f0d Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 10 Jul 2019 11:37:41 +1200 Subject: [PATCH 002/151] Remove duplicate and empty css definitions --- app/assets/stylesheets/_plantings.scss | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/assets/stylesheets/_plantings.scss b/app/assets/stylesheets/_plantings.scss index 8d5d3cbe0..fadfb35a6 100755 --- a/app/assets/stylesheets/_plantings.scss +++ b/app/assets/stylesheets/_plantings.scss @@ -89,14 +89,6 @@ display: block; } - h3 { - // padding-top: 1em; - } - - span { - display: block; - } - img { height: 50%; } From a6e9ef2d92dbb345e774ea78fa8e9824b9a781e7 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jul 2019 11:33:46 +1200 Subject: [PATCH 003/151] Notifications responsiveness --- app/views/members/_follow_buttons.haml | 6 +++ app/views/members/show.html.haml | 8 +-- app/views/notifications/_form.html.haml | 44 ++++++++-------- .../notifications/_notification.html.haml | 2 +- app/views/notifications/index.html.haml | 52 ++++++++----------- app/views/notifications/reply.html.haml | 4 +- app/views/notifications/show.html.haml | 14 +++-- 7 files changed, 66 insertions(+), 64 deletions(-) create mode 100644 app/views/members/_follow_buttons.haml diff --git a/app/views/members/_follow_buttons.haml b/app/views/members/_follow_buttons.haml new file mode 100644 index 000000000..82a2b7d88 --- /dev/null +++ b/app/views/members/_follow_buttons.haml @@ -0,0 +1,6 @@ +- if current_member && current_member != member # must be logged in, can't follow yourself + - follow = current_member.get_follow(member) + - if !follow && can?(:create, Follow) # not already following + = link_to 'Follow', follows_path(followed: member), method: :post, class: 'btn btn-block' + - if follow && can?(:destroy, follow) # already following + = link_to 'Unfollow', follow_path(follow), method: :delete, class: 'btn btn-block' \ No newline at end of file diff --git a/app/views/members/show.html.haml b/app/views/members/show.html.haml index 536b0c688..8031e151a 100644 --- a/app/views/members/show.html.haml +++ b/app/views/members/show.html.haml @@ -43,12 +43,8 @@ = icon('fas', 'envelope') Send message - - if current_member && current_member != @member # must be logged in, can't follow yourself - - follow = current_member.get_follow(@member) - - if !follow && can?(:create, Follow) # not already following - = link_to 'Follow', follows_path(followed: @member), method: :post, class: 'btn btn-block' - - if follow && can?(:destroy, follow) # already following - = link_to 'Unfollow', follow_path(follow), method: :delete, class: 'btn btn-block' + = render 'members/follow_buttons', member: @member + = render "stats", member: @member .card-footer = render "contact", member: @member, twitter_auth: @twitter_auth, diff --git a/app/views/notifications/_form.html.haml b/app/views/notifications/_form.html.haml index 23c844813..5f5880a93 100644 --- a/app/views/notifications/_form.html.haml +++ b/app/views/notifications/_form.html.haml @@ -1,24 +1,26 @@ -= form_for @notification do |f| - - if @notification.errors.any? - #error_explanation - %h2 - = pluralize(@post.errors.size, "error") - prohibited this message from being sent: - %ul - - @notification.errors.full_messages.each do |msg| - %li= msg += bootstrap_form_for @notification do |f| + .card + .card-body + - if @notification.errors.any? + #error_explanation + %h2 + = pluralize(@post.errors.size, "error") + prohibited this message from being sent: + %ul + - @notification.errors.full_messages.each do |msg| + %li= msg - .field - = f.hidden_field :recipient_id, value: @recipient.id + .field + = f.hidden_field :recipient_id, value: @recipient.id - %p - To: - = link_to @recipient, @recipient - = label_tag :notification, "Subject:" - = f.text_field :subject, value: @subject, class: 'form-control', maxlength: 255 - = label_tag :body, "Type your message here:" - = f.text_area :body, rows: 12, class: 'form-control' - %span.help-block - = render partial: "shared/markdown_help" + %p + To + = link_to @recipient, @recipient + = render 'members/tiny', member: @recipient + = f.text_field :subject, value: @subject, class: 'form-control', maxlength: 255 + = f.text_area :body, rows: 12, label: "Type your message here" + %span.help-block= render partial: "shared/markdown_help" + .card-footer - = f.submit "Send", class: 'btn btn-primary' + = link_to 'cancel', notifications_path, class: 'btn' + .float-right= f.submit "Send", class: 'btn btn-primary' diff --git a/app/views/notifications/_notification.html.haml b/app/views/notifications/_notification.html.haml index 898bfe736..881b93c50 100644 --- a/app/views/notifications/_notification.html.haml +++ b/app/views/notifications/_notification.html.haml @@ -1,4 +1,4 @@ -%p +%p.text-muted From = link_to notification.sender, notification.sender on diff --git a/app/views/notifications/index.html.haml b/app/views/notifications/index.html.haml index 8dc28b27b..39a7ccea6 100644 --- a/app/views/notifications/index.html.haml +++ b/app/views/notifications/index.html.haml @@ -4,35 +4,27 @@ .alert.alert-success{role: "alert"} You have no messages. - else = paginate @notifications, theme: 'twitter-bootstrap-3' - %table.table.table-striped - %thead - %tr - %th From - %th Subject - %th Date - %th + .index-cards - @notifications.each do |n| - - if can? :read, n - %tr - %td - - if n.sender.present? - - if n.read - = link_to n.sender, member_path(n.sender) - - else - %strong= link_to n.sender, member_path(n.sender) - - else - *deleted member* - %td - - if n.read - = link_to n.subject, notification_path(n) - - else - %strong= link_to n.subject, notification_path(n) - %td - - if n.read - = n.created_at - - else - %strong= n.created_at - %td - = link_to 'Delete', n, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default background-danger btn-xs' - = paginate @notifications, theme: 'twitter-bootstrap-3' + .card.message + .card-body + .row + .col-6 + %p= link_to n.subject, notification_path(n) + %p + - if n.read + = n.created_at + - else + %strong= n.created_at + .col-6 + = render 'members/tiny', member: n.sender + = n.sender + = render 'members/follow_buttons', member: n.sender + .card-footer + = link_to 'Read', n, class: 'btn btn-primary' + = link_to 'Reply', reply_link(n), class: 'btn btn-secondary' + = link_to n, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger btn-xs' do + = delete_icon + = t('buttons.delete') + = paginate @notifications \ No newline at end of file diff --git a/app/views/notifications/reply.html.haml b/app/views/notifications/reply.html.haml index a363fe8bc..5cd3b8478 100644 --- a/app/views/notifications/reply.html.haml +++ b/app/views/notifications/reply.html.haml @@ -1,6 +1,6 @@ = content_for :title, "Send a message to #{@recipient}" -= render @sender_notification - +.card + .card-body= render @sender_notification = render 'form' diff --git a/app/views/notifications/show.html.haml b/app/views/notifications/show.html.haml index e506f3bac..fd4241eae 100644 --- a/app/views/notifications/show.html.haml +++ b/app/views/notifications/show.html.haml @@ -1,7 +1,13 @@ = content_for :title, @notification.subject -= render @notification +.card + .card-header + .card-title= @notification.subject + .card-body + = render @notification -%p - = link_to 'Delete', @notification, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default' - = link_to 'Reply', @reply_link, class: 'btn btn-primary' + .card-footer + = link_to 'Reply', @reply_link, class: 'btn btn-primary' + = link_to @notification, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger' do + = delete_icon + = t('buttons.delete') From f444196b5c18d529efcae312c32896e8c970b2e3 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jul 2019 11:48:10 +1200 Subject: [PATCH 004/151] Update notification spec to count messages, not rows --- spec/features/notifications_spec.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spec/features/notifications_spec.rb b/spec/features/notifications_spec.rb index d925d785f..77ac4ce38 100644 --- a/spec/features/notifications_spec.rb +++ b/spec/features/notifications_spec.rb @@ -22,6 +22,7 @@ describe "Notifications", :js do it "Replying to the notification" do click_link "Reply" expect(page).to have_content "Notification body" + Percy.snapshot(page, name: 'Replying to notification') fill_in 'notification_body', with: "Response body" Percy.snapshot(page, name: "notifications#new") @@ -44,12 +45,12 @@ describe "Notifications", :js do end it 'paginates at 30 notifications per page' do - expect(page).to have_selector 'tr', count: 31 + expect(page).to have_selector '.message', count: 30 end it 'navigates pages' do first('a[rel="next"]').click - expect(page).to have_selector 'tr', count: 5 + expect(page).to have_selector '.message', count: 4 end end end From 67af0698041aee3522b38c1c311c43468dedf914 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jul 2019 12:08:15 +1200 Subject: [PATCH 005/151] more percy specs --- spec/features/admin/admin_spec.rb | 16 ++++++++++++++++ .../comments/commenting_a_comment_spec.rb | 1 + spec/features/crops/alternate_name_spec.rb | 2 ++ spec/features/members/deletion_spec.rb | 1 + spec/features/notifications_spec.rb | 3 +++ spec/features/percy/percy_spec.rb | 5 ----- spec/features/photos/new_photo_spec.rb | 1 + spec/features/photos/show_photo_spec.rb | 1 + spec/features/places/searching_a_place_spec.rb | 1 + 9 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 spec/features/admin/admin_spec.rb diff --git a/spec/features/admin/admin_spec.rb b/spec/features/admin/admin_spec.rb new file mode 100644 index 000000000..6ee586ee7 --- /dev/null +++ b/spec/features/admin/admin_spec.rb @@ -0,0 +1,16 @@ +require 'rails_helper' + +describe "forums", js: true do + context "as an admin user" do + let(:member) { create :admin_member } + + before do + login_as member + end + + it "navigating to forum admin with js" do + visit admin_path + Percy.snapshot(page, name: 'Admin page') + end + end +end diff --git a/spec/features/comments/commenting_a_comment_spec.rb b/spec/features/comments/commenting_a_comment_spec.rb index 2ab3fa615..f2136e98e 100644 --- a/spec/features/comments/commenting_a_comment_spec.rb +++ b/spec/features/comments/commenting_a_comment_spec.rb @@ -14,6 +14,7 @@ describe 'Commenting on a post' do click_button "Post comment" expect(page).to have_content "comment was successfully created." expect(page).to have_content "Posted by" + Percy.snapshot(page, name: 'Posting a comment') end context "editing a comment" do diff --git a/spec/features/crops/alternate_name_spec.rb b/spec/features/crops/alternate_name_spec.rb index cfb4bf3e3..903b6d3a7 100644 --- a/spec/features/crops/alternate_name_spec.rb +++ b/spec/features/crops/alternate_name_spec.rb @@ -34,6 +34,7 @@ describe "Alternate names", js: true do # expect(page.status_code).to equal 200 expect(page).to have_css "option[value='#{crop.id}'][selected=selected]" fill_in 'Name', with: "alternative aubergine" + Percy.snapshot(page, name: 'Crop wrangler adding alternate name') click_on "Save" # expect(page.status_code).to equal 200 expect(page).to have_content "alternative aubergine" @@ -77,6 +78,7 @@ describe "Alternate names", js: true do it "Displays crop rejection message" do visit alternate_name_path(pending_alt_name) expect(page).to have_content "This crop was rejected for the following reason: Totally fake" + Percy.snapshot(page, name: 'Rejecting crops') end end end diff --git a/spec/features/members/deletion_spec.rb b/spec/features/members/deletion_spec.rb index 7d5ac5972..5feb7014b 100644 --- a/spec/features/members/deletion_spec.rb +++ b/spec/features/members/deletion_spec.rb @@ -70,6 +70,7 @@ describe "member deletion" do visit member_path(member) click_link 'Edit profile' click_link 'Delete Account' + Percy.snapshot(page, name: 'Account deletion') fill_in "current_pw_for_delete", with: "password1", match: :prefer_exact click_button "Delete" logout diff --git a/spec/features/notifications_spec.rb b/spec/features/notifications_spec.rb index d925d785f..ee660f42a 100644 --- a/spec/features/notifications_spec.rb +++ b/spec/features/notifications_spec.rb @@ -36,6 +36,9 @@ describe "Notifications", :js do FactoryBot.create_list :notification, 34, recipient: recipient login_as recipient visit notifications_path + end + + it do Percy.snapshot(page, name: "notifications#index") end diff --git a/spec/features/percy/percy_spec.rb b/spec/features/percy/percy_spec.rb index 9bd59dd78..7b614d169 100644 --- a/spec/features/percy/percy_spec.rb +++ b/spec/features/percy/percy_spec.rb @@ -256,11 +256,6 @@ rest of the garden. end describe '#new' do - it 'plantings#new' do - visit new_planting_path - Percy.snapshot(page, name: "#{prefix}/plantings#new") - end - it 'crops#new' do visit new_crop_path Percy.snapshot(page, name: "#{prefix}/crops#new") diff --git a/spec/features/photos/new_photo_spec.rb b/spec/features/photos/new_photo_spec.rb index 8bf89fc7e..de0ae5664 100644 --- a/spec/features/photos/new_photo_spec.rb +++ b/spec/features/photos/new_photo_spec.rb @@ -18,6 +18,7 @@ describe "new photo page" do click_link('Add photo') end expect(page).to have_text planting.crop.name + Percy.snapshot(page, name: 'Add photo to planting') end end diff --git a/spec/features/photos/show_photo_spec.rb b/spec/features/photos/show_photo_spec.rb index a8d2ff802..2c027d57d 100644 --- a/spec/features/photos/show_photo_spec.rb +++ b/spec/features/photos/show_photo_spec.rb @@ -47,6 +47,7 @@ describe "show photo page" do before do garden.photos << photo visit photo_path(photo) + Percy.snapshot(page, name: 'Show photo of a garden') end it { expect(page).to have_link "garden named \"#{garden.name}\" by #{garden.owner}", href: garden_path(garden) } diff --git a/spec/features/places/searching_a_place_spec.rb b/spec/features/places/searching_a_place_spec.rb index 2db703c0a..fa64ea568 100644 --- a/spec/features/places/searching_a_place_spec.rb +++ b/spec/features/places/searching_a_place_spec.rb @@ -36,6 +36,7 @@ describe "User searches" do expect(page).to have_content "Nearby members" expect(page).to have_content "Seeds available for trade near Philippines" expect(page).to have_content "Recent plantings near Philippines" + Percy.snapshot(page, name: 'places map') end it "goes to members' index page" do From de80a8450244675c5aefacccdadcda4bf2a79731 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jul 2019 12:12:05 +1200 Subject: [PATCH 006/151] update notification view spec, not a table anymore --- spec/views/notifications/index.html.haml_spec.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/spec/views/notifications/index.html.haml_spec.rb b/spec/views/notifications/index.html.haml_spec.rb index d02e43038..c4ec0280c 100644 --- a/spec/views/notifications/index.html.haml_spec.rb +++ b/spec/views/notifications/index.html.haml_spec.rb @@ -15,9 +15,8 @@ describe "notifications/index" do end it "renders a list of notifications" do - assert_select "table" - assert_select "tr>td", text: @notification.sender.to_s, count: 2 - assert_select "tr>td", text: @notification.subject, count: 2 + has_content @notification.sender.to_s, count: 2 + has_content @notification.subject, count: 2 end it "links to sender's profile" do From 2cc307f09b2122f75b46b7b7daba2791f11e943b Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jul 2019 12:14:54 +1200 Subject: [PATCH 007/151] fixes percy error, running same snapshot more than once --- spec/features/members/deletion_spec.rb | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/spec/features/members/deletion_spec.rb b/spec/features/members/deletion_spec.rb index 5feb7014b..7a5ccf273 100644 --- a/spec/features/members/deletion_spec.rb +++ b/spec/features/members/deletion_spec.rb @@ -63,6 +63,17 @@ describe "member deletion" do expect(page).to have_text "The page you were looking for doesn't exist." end + describe 'percy spec' do + it do + logout + login_as(member) + visit member_path(member) + click_link 'Edit profile' + click_link 'Delete Account' + Percy.snapshot(page, name: 'Account deletion') + end + end + context "deletes and" do before do logout @@ -70,7 +81,6 @@ describe "member deletion" do visit member_path(member) click_link 'Edit profile' click_link 'Delete Account' - Percy.snapshot(page, name: 'Account deletion') fill_in "current_pw_for_delete", with: "password1", match: :prefer_exact click_button "Delete" logout From 1250fa388f5c144272b39f1b19166e6fc3bc2d44 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jul 2019 12:41:02 +1200 Subject: [PATCH 008/151] Fix spec for notifications#index --- spec/views/notifications/index.html.haml_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/views/notifications/index.html.haml_spec.rb b/spec/views/notifications/index.html.haml_spec.rb index c4ec0280c..eece9f23e 100644 --- a/spec/views/notifications/index.html.haml_spec.rb +++ b/spec/views/notifications/index.html.haml_spec.rb @@ -15,8 +15,8 @@ describe "notifications/index" do end it "renders a list of notifications" do - has_content @notification.sender.to_s, count: 2 - has_content @notification.subject, count: 2 + expect(rendered).to have_content @notification.sender.to_s, count: 2 + expect(rendered).to have_content @notification.subject, count: 2 end it "links to sender's profile" do From 4d1b45317b3a709ee3a9d35f9cfc5b55c4373b53 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jul 2019 13:06:02 +1200 Subject: [PATCH 009/151] tidy up larger screen display of inbox --- app/assets/stylesheets/application.scss | 21 +++++----- app/assets/stylesheets/notifications.scss | 3 ++ app/views/notifications/index.html.haml | 47 ++++++++++++----------- 3 files changed, 39 insertions(+), 32 deletions(-) create mode 100644 app/assets/stylesheets/notifications.scss diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index fc958cd69..03c66c680 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -8,16 +8,6 @@ @import 'leaflet'; @import 'leaflet.markercluster'; -@import 'predictions'; -@import 'plantings'; -@import 'members'; -@import 'harvests'; -@import 'seeds'; -@import 'posts'; -@import 'crops'; - -@import 'homepage'; -@import 'photos'; // Font Awesome @import 'font-awesome-sprockets'; @@ -26,3 +16,14 @@ @import 'rails_bootstrap_forms'; @import 'overrides'; +@import 'crops'; +@import 'harvests'; +@import 'members'; +@import 'notifications'; +@import 'plantings'; +@import 'posts'; +@import 'predictions'; +@import 'seeds'; + +@import 'homepage'; +@import 'photos'; diff --git a/app/assets/stylesheets/notifications.scss b/app/assets/stylesheets/notifications.scss new file mode 100644 index 000000000..fde249d0a --- /dev/null +++ b/app/assets/stylesheets/notifications.scss @@ -0,0 +1,3 @@ +.message { + width: 100%; +} diff --git a/app/views/notifications/index.html.haml b/app/views/notifications/index.html.haml index 39a7ccea6..d275b7161 100644 --- a/app/views/notifications/index.html.haml +++ b/app/views/notifications/index.html.haml @@ -5,26 +5,29 @@ - else = paginate @notifications, theme: 'twitter-bootstrap-3' - .index-cards - - @notifications.each do |n| - .card.message - .card-body - .row - .col-6 - %p= link_to n.subject, notification_path(n) - %p - - if n.read - = n.created_at - - else - %strong= n.created_at - .col-6 - = render 'members/tiny', member: n.sender - = n.sender - = render 'members/follow_buttons', member: n.sender - .card-footer - = link_to 'Read', n, class: 'btn btn-primary' - = link_to 'Reply', reply_link(n), class: 'btn btn-secondary' - = link_to n, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger btn-xs' do - = delete_icon - = t('buttons.delete') + - @notifications.each do |n| + .card.message + .card-body + .row + .col-6.col-md-9 + %h3= link_to n.subject, notification_path(n) + %p + - if n.read + = icon 'far', 'envelope-open' + - else + = icon 'far', 'envelope' + %strong unread + = n.created_at + .col-6.col-md-3.text-right + = link_to n.sender do + %h3 + = render 'members/tiny', member: n.sender + = n.sender + = render 'members/follow_buttons', member: n.sender + .card-footer + = link_to 'Read', n, class: 'btn btn-primary' + = link_to 'Reply', reply_link(n), class: 'btn btn-secondary' + = link_to n, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger btn-xs' do + = delete_icon + = t('buttons.delete') = paginate @notifications \ No newline at end of file From 97ffc0d1bf7e069eb17e140034690a04851360b4 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jul 2019 13:13:11 +1200 Subject: [PATCH 010/151] adding breadcrumbs --- app/views/notifications/index.html.haml | 2 ++ app/views/notifications/new.html.haml | 2 ++ app/views/notifications/reply.html.haml | 2 ++ app/views/notifications/show.html.haml | 7 +++++++ 4 files changed, 13 insertions(+) diff --git a/app/views/notifications/index.html.haml b/app/views/notifications/index.html.haml index d275b7161..6568fef89 100644 --- a/app/views/notifications/index.html.haml +++ b/app/views/notifications/index.html.haml @@ -1,4 +1,6 @@ - content_for :title, "Inbox" +- content_for :breadcrumbs do + %li.breadcrumb-item.active= link_to 'Messages', notifications_path - if @notifications.empty? .alert.alert-success{role: "alert"} You have no messages. diff --git a/app/views/notifications/new.html.haml b/app/views/notifications/new.html.haml index 633e26193..721dcca7d 100644 --- a/app/views/notifications/new.html.haml +++ b/app/views/notifications/new.html.haml @@ -1,4 +1,6 @@ = content_for :title, "Send a message to #{@recipient}" +- content_for :breadcrumbs do + %li.breadcrumb-item= link_to 'Messages', notifications_path = render 'form' diff --git a/app/views/notifications/reply.html.haml b/app/views/notifications/reply.html.haml index 5cd3b8478..54230dff4 100644 --- a/app/views/notifications/reply.html.haml +++ b/app/views/notifications/reply.html.haml @@ -1,4 +1,6 @@ = content_for :title, "Send a message to #{@recipient}" +- content_for :breadcrumbs do + %li.breadcrumb-item= link_to 'Messages', notifications_path .card .card-body= render @sender_notification diff --git a/app/views/notifications/show.html.haml b/app/views/notifications/show.html.haml index fd4241eae..2303c9ea5 100644 --- a/app/views/notifications/show.html.haml +++ b/app/views/notifications/show.html.haml @@ -1,8 +1,15 @@ = content_for :title, @notification.subject +- content_for :breadcrumbs do + %li.breadcrumb-item= link_to 'Messages', notifications_path + .card .card-header .card-title= @notification.subject + .float-right + = link_to @notification.sender do + = @notification.sender + = render 'members/tiny', member: @notification.sender .card-body = render @notification From 29e606a8701d9af4ba2025bdce18fc69746b5933 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jul 2019 13:17:31 +1200 Subject: [PATCH 011/151] use badges for unread message count --- app/views/layouts/_header.html.haml | 10 ++++++---- config/locales/en.yml | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/views/layouts/_header.html.haml b/app/views/layouts/_header.html.haml index 780789096..8093caccb 100644 --- a/app/views/layouts/_header.html.haml +++ b/app/views/layouts/_header.html.haml @@ -29,7 +29,8 @@ %li.nav-item.dropdown %a.nav-link.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", href: "#", role: "button"} - if current_member.notifications.unread_count.positive? - = t('.your_stuff', unread_count: current_member.notifications.unread_count) + = t('.your_stuff') + %span.badge.badge-info= current_member.notifications.unread_count - else = t('.current_memberlogin_name', current_memberlogin_name: current_member.login_name) .dropdown-menu{"aria-labelledby" => "navbarDropdown"} @@ -47,9 +48,10 @@ - if current_member.notifications.unread_count.positive? .dropdown-divider - %strong= link_to(t('.inbox_unread', - unread_count: current_member.notifications.unread_count), - notifications_path, class: 'dropdown-item') + %strong + = link_to(notifications_path, class: 'dropdown-item') do + = t('.inbox') + %span.badge.badge-info= current_member.notifications.unread_count - else = link_to t('.inbox'), notifications_path, class: 'dropdown-item' diff --git a/config/locales/en.yml b/config/locales/en.yml index 627762143..3c6a765e2 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -236,7 +236,7 @@ en: skip: Skip navigation menu support_growstuff: Support Growstuff toggle_navigation: Toggle Navigation - your_stuff: Your Stuff (%{unread_count}) + your_stuff: Your Stuff links: my_gardens: My gardens members: From da8d67c7e7fd55ce605e95370be595ae3f71ce46 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jul 2019 13:20:40 +1200 Subject: [PATCH 012/151] Add the unread inbox menu display to percy --- spec/features/notifications_spec.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spec/features/notifications_spec.rb b/spec/features/notifications_spec.rb index 4b2140d3f..dc149c7d9 100644 --- a/spec/features/notifications_spec.rb +++ b/spec/features/notifications_spec.rb @@ -15,6 +15,9 @@ describe "Notifications", :js do before do login_as recipient + visit root_path + click_link 'Your Stuff' + Percy.snapshot(page, name: "notification menu") visit notification_path(notification) Percy.snapshot(page, name: "notifications#show") end From e355c83c156fbee791af5d29b4831da24501c2b2 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jul 2019 17:26:40 +1200 Subject: [PATCH 013/151] Put newest messages at the top of the page --- app/controllers/notifications_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index 0b145b04b..a340bd6f7 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -6,7 +6,7 @@ class NotificationsController < ApplicationController # GET /notifications def index - @notifications = Notification.by_recipient(current_member).order(:created_at).paginate(page: params[:page], per_page: 30) + @notifications = Notification.by_recipient(current_member).order(created_at: desc).paginate(page: params[:page], per_page: 30) end # GET /notifications/1 From cafad7a0099636951dc4a1d18f3b397732a3f272 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jul 2019 19:53:45 +1200 Subject: [PATCH 014/151] Fix sorting --- app/controllers/notifications_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index a340bd6f7..9b93b7324 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -6,7 +6,7 @@ class NotificationsController < ApplicationController # GET /notifications def index - @notifications = Notification.by_recipient(current_member).order(created_at: desc).paginate(page: params[:page], per_page: 30) + @notifications = Notification.by_recipient(current_member).order(created_at: :desc).paginate(page: params[:page], per_page: 30) end # GET /notifications/1 From e97608b5ffce986f1349f9d537c9ff2657b84e5e Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jul 2019 20:11:28 +1200 Subject: [PATCH 015/151] Update inbox link in spec --- spec/views/layouts/_header_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/views/layouts/_header_spec.rb b/spec/views/layouts/_header_spec.rb index f4521ee88..184825051 100644 --- a/spec/views/layouts/_header_spec.rb +++ b/spec/views/layouts/_header_spec.rb @@ -82,7 +82,7 @@ describe 'layouts/_header.html.haml', type: "view" do it 'shows inbox link' do rendered.should have_content 'Inbox' - rendered.should_not match(/Inbox \(\d+\)/) + rendered.should_not match(/Inbox \d+/) end context 'has notifications' do From d2c5d8e9ceb5beb7ba3ec98511af46e422492a79 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jul 2019 20:11:49 +1200 Subject: [PATCH 016/151] Update inbox link in spec --- spec/views/layouts/_header_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/views/layouts/_header_spec.rb b/spec/views/layouts/_header_spec.rb index f4521ee88..184825051 100644 --- a/spec/views/layouts/_header_spec.rb +++ b/spec/views/layouts/_header_spec.rb @@ -82,7 +82,7 @@ describe 'layouts/_header.html.haml', type: "view" do it 'shows inbox link' do rendered.should have_content 'Inbox' - rendered.should_not match(/Inbox \(\d+\)/) + rendered.should_not match(/Inbox \d+/) end context 'has notifications' do From 063c745aca4d5d466111ce9c471a0929c817f011 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jul 2019 20:13:10 +1200 Subject: [PATCH 017/151] Add missing translation --- config/locales/en.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/config/locales/en.yml b/config/locales/en.yml index 3c6a765e2..11dd0a781 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -89,6 +89,7 @@ en: plant_something_here: Plant something here record_harvest: Record Harvest save_seeds: Save seeds + timeline: Timeline write_blog_post: Write blog post crops: search: Search crops From c91fdf47442d5dc005ae9548387b53723150e54f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jul 2019 22:01:03 +1200 Subject: [PATCH 018/151] Update inbox link in spec --- spec/views/layouts/_header_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/views/layouts/_header_spec.rb b/spec/views/layouts/_header_spec.rb index 184825051..4a39e99b3 100644 --- a/spec/views/layouts/_header_spec.rb +++ b/spec/views/layouts/_header_spec.rb @@ -89,7 +89,7 @@ describe 'layouts/_header.html.haml', type: "view" do it 'shows inbox count' do FactoryBot.create(:notification, recipient: @member) render - rendered.should have_content 'Inbox (1)' + rendered.should have_content 'Inbox 1' end end end From d2b310b9eb3de803f60f2bbfd9a3a84091b03abf Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jul 2019 22:06:55 +1200 Subject: [PATCH 019/151] Remove unnecesary theme param from pagination --- app/views/notifications/index.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/notifications/index.html.haml b/app/views/notifications/index.html.haml index 6568fef89..484fe6c10 100644 --- a/app/views/notifications/index.html.haml +++ b/app/views/notifications/index.html.haml @@ -5,7 +5,7 @@ - if @notifications.empty? .alert.alert-success{role: "alert"} You have no messages. - else - = paginate @notifications, theme: 'twitter-bootstrap-3' + = paginate @notifications - @notifications.each do |n| .card.message From c50556221c6d3e4370c0f8eaec18a6a99f295080 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jul 2019 22:28:51 +1200 Subject: [PATCH 020/151] TRying to get mailboxxer working --- Gemfile | 3 + Gemfile.lock | 8 ++ app/controllers/conversations_controller.rb | 92 +++++++++++++++++++ app/controllers/messages_controller.rb | 79 ++++++++++++++++ app/controllers/notifications_controller.rb | 19 ++-- app/models/member.rb | 5 + app/views/conversations/index.haml | 35 +++++++ .../message_mailer/new_message_email.html.erb | 20 ++++ .../message_mailer/new_message_email.text.erb | 10 ++ .../reply_message_email.html.erb | 20 ++++ .../reply_message_email.text.erb | 10 ++ .../new_notification_email.html.erb | 20 ++++ .../new_notification_email.text.erb | 10 ++ config/initializers/mailboxer.rb | 21 +++++ config/routes.rb | 2 + ...43651_create_mailboxer.mailboxer_engine.rb | 65 +++++++++++++ ...dd_conversation_optout.mailboxer_engine.rb | 15 +++ ...53_add_missing_indices.mailboxer_engine.rb | 20 ++++ ..._to_mailboxer_receipts.mailboxer_engine.rb | 8 ++ db/schema.rb | 90 +++++++++++++++++- 20 files changed, 544 insertions(+), 8 deletions(-) create mode 100644 app/controllers/conversations_controller.rb create mode 100644 app/controllers/messages_controller.rb create mode 100644 app/views/conversations/index.haml create mode 100644 app/views/mailboxer/message_mailer/new_message_email.html.erb create mode 100644 app/views/mailboxer/message_mailer/new_message_email.text.erb create mode 100644 app/views/mailboxer/message_mailer/reply_message_email.html.erb create mode 100644 app/views/mailboxer/message_mailer/reply_message_email.text.erb create mode 100644 app/views/mailboxer/notification_mailer/new_notification_email.html.erb create mode 100644 app/views/mailboxer/notification_mailer/new_notification_email.text.erb create mode 100644 config/initializers/mailboxer.rb create mode 100644 db/migrate/20190711043651_create_mailboxer.mailboxer_engine.rb create mode 100644 db/migrate/20190711043652_add_conversation_optout.mailboxer_engine.rb create mode 100644 db/migrate/20190711043653_add_missing_indices.mailboxer_engine.rb create mode 100644 db/migrate/20190711043654_add_delivery_tracking_info_to_mailboxer_receipts.mailboxer_engine.rb diff --git a/Gemfile b/Gemfile index c16f8fcf9..c151aa424 100644 --- a/Gemfile +++ b/Gemfile @@ -115,6 +115,9 @@ gem 'puma' gem 'loofah', '>= 2.2.1' gem 'rack-protection', '>= 2.0.1' +# Member to member messaging system +gem 'mailboxer' + group :production do gem 'bonsai-elasticsearch-rails' # Integration with Bonsa-Elasticsearch on heroku gem 'dalli' diff --git a/Gemfile.lock b/Gemfile.lock index 0fd7810ab..b4afcdd92 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -100,6 +100,10 @@ GEM capybara-screenshot (1.0.23) capybara (>= 1.0, < 4) launchy + carrierwave (1.3.1) + activemodel (>= 4.0.0) + activesupport (>= 4.0.0) + mime-types (>= 1.16) chartkick (3.2.0) childprocess (1.0.1) rake (< 13.0) @@ -283,6 +287,9 @@ GEM nokogiri (>= 1.5.9) mail (2.7.1) mini_mime (>= 0.1.1) + mailboxer (0.15.1) + carrierwave (>= 0.5.8) + rails (>= 5.0.0) marcel (0.3.3) mimemagic (~> 0.3.2) material-sass (4.1.1) @@ -584,6 +591,7 @@ DEPENDENCIES letter_opener listen loofah (>= 2.2.1) + mailboxer material-sass (= 4.1.1) material_icons memcachier diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb new file mode 100644 index 000000000..6c69e4893 --- /dev/null +++ b/app/controllers/conversations_controller.rb @@ -0,0 +1,92 @@ +class ConversationsController < ApplicationController + before_action :authenticate_member! + before_action :get_mailbox, :get_box # , :get_actor + # before_action :check_current_subject_in_conversation, :only => [:show, :update, :destroy] + + def index + @conversations = if @box.eql? "inbox" + @mailbox.inbox.paginate(page: params[:page]) + elsif @box.eql? "sentbox" + @mailbox.sentbox.paginate(page: params[:page]) + else + @mailbox.trash.paginate(page: params[:page]) + end + + respond_to do |format| + format.html { render @conversations if request.xhr? } + end + end + + def show + @receipts = if @box.eql? 'trash' + @mailbox.receipts_for(@conversation).trash + else + @mailbox.receipts_for(@conversation).not_trash + end + render action: :show + @receipts.mark_as_read + end + + def update + @conversation.untrash(@actor) if params[:untrash].present? + + if params[:reply_all].present? + last_receipt = @mailbox.receipts_for(@conversation).last + @receipt = @actor.reply_to_all(last_receipt, params[:body]) + end + + @receipts = if @box.eql? 'trash' + @mailbox.receipts_for(@conversation).trash + else + @mailbox.receipts_for(@conversation).not_trash + end + redirect_to action: :show + @receipts.mark_as_read + end + + def destroy + @conversation.move_to_trash(@actor) + + respond_to do |format| + format.html do + if params[:location].present? && (params[:location] == 'conversation') + redirect_to conversations_path(box: :trash) + else + redirect_to conversations_path(box: @box, page: params[:page]) + end + end + format.js do + if params[:location].present? && (params[:location] == 'conversation') + render js: "window.location = '#{conversations_path(box: @box, page: params[:page])}';" + else + render 'conversations/destroy' + end + end + end + end + + private + + def get_mailbox + @mailbox = current_member.mailbox + end + + def get_actor + @actor = Actor.normalize(current_subject) + end + + def get_box + params[:box] = 'inbox' if params[:box].blank? || !%w(inbox sentbox trash).include?(params[:box]) + + @box = params[:box] + end + + def check_current_subject_in_conversation + @conversation = Conversation.find_by(id: params[:id]) + + if @conversation.nil? || !@conversation.is_participant?(@actor) + redirect_to conversations_path(box: @box) + return + end + end +end diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb new file mode 100644 index 000000000..ec9b98702 --- /dev/null +++ b/app/controllers/messages_controller.rb @@ -0,0 +1,79 @@ +class MessagesController < ApplicationController + before_action :authenticate_user! + before_action :get_mailbox, :get_box, :get_actor + def index + redirect_to conversations_path(box: @box) + end + + # GET /messages/1 + # GET /messages/1.xml + def show + if (@message = Message.find_by(id: params[:id])) && (@conversation = @message.conversation) + if @conversation.is_participant?(@actor) + redirect_to conversation_path(@conversation, box: @box, anchor: "message_" + @message.id.to_s) + return + end + end + redirect_to conversations_path(box: @box) + end + + # GET /messages/new + # GET /messages/new.xml + def new + if params[:receiver].present? + @recipient = Actor.find_by(slug: params[:receiver]) + return if @recipient.nil? + + @recipient = nil if Actor.normalize(@recipient) == Actor.normalize(current_subject) + end + end + + # GET /messages/1/edit + def edit; end + + # POST /messages + # POST /messages.xml + def create + @recipients = + if params[:_recipients].present? + @recipients = params[:_recipients].split(',').map { |r| Actor.find(r) } + else + [] + end + + @receipt = @actor.send_message(@recipients, params[:body], params[:subject]) + if @receipt.errors.blank? + @conversation = @receipt.conversation + flash[:success] = t('mailboxer.sent') + redirect_to conversation_path(@conversation, box: :sentbox) + else + render action: :new + end + end + + # PUT /messages/1 + # PUT /messages/1.xml + def update; end + + # DELETE /messages/1 + # DELETE /messages/1.xml + def destroy; end + + private + + def get_mailbox + @mailbox = current_subject.mailbox + end + + def get_actor + @actor = Actor.normalize(current_subject) + end + + def get_box + if params[:box].blank? || !%w(inbox sentbox trash).include?(params[:box]) + @box = "inbox" + return + end + @box = params[:box] + end +end diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index 9b93b7324..9e2475d9d 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -46,15 +46,20 @@ class NotificationsController < ApplicationController # POST /notifications def create - params[:notification][:sender_id] = current_member.id - @notification = Notification.new(notification_params) - @recipient = Member.find_by(id: params[:notification][:recipient_id]) + # params[:notification][:sender_id] = current_member.id + # @notification = Notification.new(notification_params) + @recipient = Member.find_by(id: notification_params[:recipient_id]) + @body = notification_params[:body] + @subject = notification_params[:subject] - if @notification.save + byebug + current_member.send_message(@recipient, @body, @subject) + + # if @notification.save redirect_to notifications_path, notice: 'Message was successfully sent.' - else - render action: "new" - end + # else + # render action: "new" + # end end private diff --git a/app/models/member.rb b/app/models/member.rb index 175ee4a6c..a8416ef2b 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -1,5 +1,6 @@ class Member < ApplicationRecord acts_as_paranoid # implements soft deletion + acts_as_messageable # messages can be sent to this model before_destroy :newsletter_unsubscribe include Geocodable extend FriendlyId @@ -110,6 +111,10 @@ class Member < ApplicationRecord slug end + def name + login_name + end + def role?(role_sym) roles.any? { |r| r.name.gsub(/\s+/, "_").underscore.to_sym == role_sym } end diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml new file mode 100644 index 000000000..8be9c5833 --- /dev/null +++ b/app/views/conversations/index.haml @@ -0,0 +1,35 @@ +- content_for :title, "Inbox" +- content_for :breadcrumbs do + %li.breadcrumb-item.active= link_to 'Messages', notifications_path + +- if @conversations.empty? + .alert.alert-success{role: "alert"} You have no messages. +- else + = paginate @conversations, theme: 'twitter-bootstrap-3' + +-# - @conversations.each do |n| +-# .card.message +-# .card-body +-# .row +-# .col-6.col-md-9 +-# %h3= link_to n.subject, notification_path(n) +-# %p +-# - if n.read +-# = icon 'far', 'envelope-open' +-# - else +-# = icon 'far', 'envelope' +-# %strong unread +-# = n.created_at +-# .col-6.col-md-3.text-right +-# = link_to n.sender do +-# %h3 +-# = render 'members/tiny', member: n.sender +-# = n.sender +-# = render 'members/follow_buttons', member: n.sender +-# .card-footer +-# = link_to 'Read', n, class: 'btn btn-primary' +-# = link_to 'Reply', reply_link(n), class: 'btn btn-secondary' +-# = link_to n, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger btn-xs' do +-# = delete_icon +-# = t('buttons.delete') +-# = paginate @conversations \ No newline at end of file diff --git a/app/views/mailboxer/message_mailer/new_message_email.html.erb b/app/views/mailboxer/message_mailer/new_message_email.html.erb new file mode 100644 index 000000000..c779e8881 --- /dev/null +++ b/app/views/mailboxer/message_mailer/new_message_email.html.erb @@ -0,0 +1,20 @@ + + + + + + +

You have a new message: <%= @subject %>

+

+ You have received a new message: +

+
+

+ <%= raw @message.body %> +

+
+

+ Visit <%= link_to root_url, root_url %> and go to your inbox for more info. +

+ + diff --git a/app/views/mailboxer/message_mailer/new_message_email.text.erb b/app/views/mailboxer/message_mailer/new_message_email.text.erb new file mode 100644 index 000000000..228ca58a4 --- /dev/null +++ b/app/views/mailboxer/message_mailer/new_message_email.text.erb @@ -0,0 +1,10 @@ +You have a new message: <%= @subject %> +=============================================== + +You have received a new message: + +----------------------------------------------- +<%= @message.body.html_safe? ? @message.body : strip_tags(@message.body) %> +----------------------------------------------- + +Visit <%= root_url %> and go to your inbox for more info. diff --git a/app/views/mailboxer/message_mailer/reply_message_email.html.erb b/app/views/mailboxer/message_mailer/reply_message_email.html.erb new file mode 100644 index 000000000..fd1286c5f --- /dev/null +++ b/app/views/mailboxer/message_mailer/reply_message_email.html.erb @@ -0,0 +1,20 @@ + + + + + + +

You have a new reply: <%= @subject %>

+

+ You have received a new reply: +

+
+

+ <%= raw @message.body %> +

+
+

+ Visit <%= link_to root_url, root_url %> and go to your inbox for more info. +

+ + diff --git a/app/views/mailboxer/message_mailer/reply_message_email.text.erb b/app/views/mailboxer/message_mailer/reply_message_email.text.erb new file mode 100644 index 000000000..c56bfb5e0 --- /dev/null +++ b/app/views/mailboxer/message_mailer/reply_message_email.text.erb @@ -0,0 +1,10 @@ +You have a new reply: <%= @subject %> +=============================================== + +You have received a new reply: + +----------------------------------------------- +<%= @message.body.html_safe? ? @message.body : strip_tags(@message.body) %> +----------------------------------------------- + +Visit <%= root_url %> and go to your inbox for more info. diff --git a/app/views/mailboxer/notification_mailer/new_notification_email.html.erb b/app/views/mailboxer/notification_mailer/new_notification_email.html.erb new file mode 100644 index 000000000..5502d7fc4 --- /dev/null +++ b/app/views/mailboxer/notification_mailer/new_notification_email.html.erb @@ -0,0 +1,20 @@ + + + + + + +

You have a new notification: <%= @notification.subject.html_safe? ? @notification.subject : strip_tags(@notification.subject) %>

+

+ You have received a new notification: +

+
+

+ <%= raw @notification.body %> +

+
+

+ Visit <%= link_to root_url,root_url %> and go to your notifications for more info. +

+ + \ No newline at end of file diff --git a/app/views/mailboxer/notification_mailer/new_notification_email.text.erb b/app/views/mailboxer/notification_mailer/new_notification_email.text.erb new file mode 100644 index 000000000..8ae17d32a --- /dev/null +++ b/app/views/mailboxer/notification_mailer/new_notification_email.text.erb @@ -0,0 +1,10 @@ +You have a new notification: <%= @notification.subject.html_safe? ? @notification.subject : strip_tags(@notification.subject) %> +=============================================== + +You have received a new notification: + +----------------------------------------------- +<%= @notification.body.html_safe? ? @notification.body : strip_tags(@notification.body) %> +----------------------------------------------- + +Visit <%= root_url %> and go to your notifications for more info. diff --git a/config/initializers/mailboxer.rb b/config/initializers/mailboxer.rb new file mode 100644 index 000000000..cfa647e6d --- /dev/null +++ b/config/initializers/mailboxer.rb @@ -0,0 +1,21 @@ +Mailboxer.setup do |config| + # Configures if your application uses or not email sending for Notifications and Messages + config.uses_emails = true + + # Configures the default from for emails sent for Messages and Notifications + config.default_from = "no-reply@mailboxer.com" + + # Configures the methods needed by mailboxer + config.email_method = :email + config.name_method = :login_name + config.notify_method = :notify + + # Configures if you use or not a search engine and which one you are using + # Supported engines: [:solr,:sphinx,:pg_search] + config.search_enabled = false + config.search_engine = :solr + + # Configures maximum length of the message subject and body + config.subject_max_length = 255 + config.body_max_length = 32_000 +end diff --git a/config/routes.rb b/config/routes.rb index aa93d3c5d..04a1220fc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -100,6 +100,8 @@ Rails.application.routes.draw do resources :notifications do get 'reply' end + resources :messages + resources :conversations resources :places, only: %i(index show), param: :place do get 'search', on: :collection diff --git a/db/migrate/20190711043651_create_mailboxer.mailboxer_engine.rb b/db/migrate/20190711043651_create_mailboxer.mailboxer_engine.rb new file mode 100644 index 000000000..3b9acbddb --- /dev/null +++ b/db/migrate/20190711043651_create_mailboxer.mailboxer_engine.rb @@ -0,0 +1,65 @@ +# This migration comes from mailboxer_engine (originally 20110511145103) +class CreateMailboxer < ActiveRecord::Migration[4.2] + def self.up + # Tables + # Conversations + create_table :mailboxer_conversations do |t| + t.column :subject, :string, default: "" + t.column :created_at, :datetime, null: false + t.column :updated_at, :datetime, null: false + end + # Receipts + create_table :mailboxer_receipts do |t| + t.references :receiver, polymorphic: true + t.column :notification_id, :integer, null: false + t.column :is_read, :boolean, default: false + t.column :trashed, :boolean, default: false + t.column :deleted, :boolean, default: false + t.column :mailbox_type, :string, limit: 25 + t.column :created_at, :datetime, null: false + t.column :updated_at, :datetime, null: false + end + # Notifications and Messages + create_table :mailboxer_notifications do |t| + t.column :type, :string + t.column :body, :text + t.column :subject, :string, default: "" + t.references :sender, polymorphic: true + t.column :conversation_id, :integer + t.column :draft, :boolean, default: false + t.string :notification_code, default: nil + t.references :notified_object, polymorphic: true, index: { name: 'mailboxer_notifications_notified_object' } + t.column :attachment, :string + t.column :updated_at, :datetime, null: false + t.column :created_at, :datetime, null: false + t.boolean :global, default: false + t.datetime :expires + end + + # Indexes + # Conversations + # Receipts + add_index "mailboxer_receipts", "notification_id" + + # Messages + add_index "mailboxer_notifications", "conversation_id" + + # Foreign keys + # Conversations + # Receipts + add_foreign_key "mailboxer_receipts", "mailboxer_notifications", name: "receipts_on_notification_id", column: "notification_id" + # Messages + add_foreign_key "mailboxer_notifications", "mailboxer_conversations", name: "notifications_on_conversation_id", column: "conversation_id" + end + + def self.down + # Tables + remove_foreign_key "mailboxer_receipts", name: "receipts_on_notification_id" + remove_foreign_key "mailboxer_notifications", name: "notifications_on_conversation_id" + + # Indexes + drop_table :mailboxer_receipts + drop_table :mailboxer_conversations + drop_table :mailboxer_notifications + end +end diff --git a/db/migrate/20190711043652_add_conversation_optout.mailboxer_engine.rb b/db/migrate/20190711043652_add_conversation_optout.mailboxer_engine.rb new file mode 100644 index 000000000..a8aa6bbed --- /dev/null +++ b/db/migrate/20190711043652_add_conversation_optout.mailboxer_engine.rb @@ -0,0 +1,15 @@ +# This migration comes from mailboxer_engine (originally 20131206080416) +class AddConversationOptout < ActiveRecord::Migration[4.2] + def self.up + create_table :mailboxer_conversation_opt_outs do |t| + t.references :unsubscriber, polymorphic: true + t.references :conversation + end + add_foreign_key "mailboxer_conversation_opt_outs", "mailboxer_conversations", name: "mb_opt_outs_on_conversations_id", column: "conversation_id" + end + + def self.down + remove_foreign_key "mailboxer_conversation_opt_outs", name: "mb_opt_outs_on_conversations_id" + drop_table :mailboxer_conversation_opt_outs + end +end diff --git a/db/migrate/20190711043653_add_missing_indices.mailboxer_engine.rb b/db/migrate/20190711043653_add_missing_indices.mailboxer_engine.rb new file mode 100644 index 000000000..b079f4a3d --- /dev/null +++ b/db/migrate/20190711043653_add_missing_indices.mailboxer_engine.rb @@ -0,0 +1,20 @@ +# This migration comes from mailboxer_engine (originally 20131206080417) +class AddMissingIndices < ActiveRecord::Migration[4.2] + def change + # We'll explicitly specify its name, as the auto-generated name is too long and exceeds 63 + # characters limitation. + add_index :mailboxer_conversation_opt_outs, %i(unsubscriber_id unsubscriber_type), + name: 'index_mailboxer_conversation_opt_outs_on_unsubscriber_id_type' + add_index :mailboxer_conversation_opt_outs, :conversation_id + + add_index :mailboxer_notifications, :type + add_index :mailboxer_notifications, %i(sender_id sender_type) + + # We'll explicitly specify its name, as the auto-generated name is too long and exceeds 63 + # characters limitation. + add_index :mailboxer_notifications, %i(notified_object_id notified_object_type), + name: 'index_mailboxer_notifications_on_notified_object_id_and_type' + + add_index :mailboxer_receipts, %i(receiver_id receiver_type) + end +end diff --git a/db/migrate/20190711043654_add_delivery_tracking_info_to_mailboxer_receipts.mailboxer_engine.rb b/db/migrate/20190711043654_add_delivery_tracking_info_to_mailboxer_receipts.mailboxer_engine.rb new file mode 100644 index 000000000..498d152d9 --- /dev/null +++ b/db/migrate/20190711043654_add_delivery_tracking_info_to_mailboxer_receipts.mailboxer_engine.rb @@ -0,0 +1,8 @@ +# This migration comes from mailboxer_engine (originally 20151103080417) +class AddDeliveryTrackingInfoToMailboxerReceipts < ActiveRecord::Migration[4.2] + def change + add_column :mailboxer_receipts, :is_delivered, :boolean, default: false + add_column :mailboxer_receipts, :delivery_method, :string + add_column :mailboxer_receipts, :message_id, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index d6cb3cbf4..71f21ede5 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: 2019_03_26_224347) do +ActiveRecord::Schema.define(version: 2019_07_11_043654) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -221,6 +221,7 @@ ActiveRecord::Schema.define(version: 2019_03_26_224347) do t.decimal "area" t.string "area_unit" t.integer "garden_type_id" + t.jsonb "layout" t.index ["garden_type_id"], name: "index_gardens_on_garden_type_id" t.index ["owner_id"], name: "index_gardens_on_owner_id" t.index ["slug"], name: "index_gardens_on_slug", unique: true @@ -268,6 +269,60 @@ ActiveRecord::Schema.define(version: 2019_03_26_224347) do t.index ["member_id"], name: "index_likes_on_member_id" end + create_table "mailboxer_conversation_opt_outs", id: :serial, force: :cascade do |t| + t.string "unsubscriber_type" + t.integer "unsubscriber_id" + t.integer "conversation_id" + t.index ["conversation_id"], name: "index_mailboxer_conversation_opt_outs_on_conversation_id" + t.index ["unsubscriber_id", "unsubscriber_type"], name: "index_mailboxer_conversation_opt_outs_on_unsubscriber_id_type" + end + + create_table "mailboxer_conversations", id: :serial, force: :cascade do |t| + t.string "subject", default: "" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "mailboxer_notifications", id: :serial, force: :cascade do |t| + t.string "type" + t.text "body" + t.string "subject", default: "" + t.string "sender_type" + t.integer "sender_id" + t.integer "conversation_id" + t.boolean "draft", default: false + t.string "notification_code" + t.string "notified_object_type" + t.integer "notified_object_id" + t.string "attachment" + t.datetime "updated_at", null: false + t.datetime "created_at", null: false + t.boolean "global", default: false + t.datetime "expires" + t.index ["conversation_id"], name: "index_mailboxer_notifications_on_conversation_id" + t.index ["notified_object_id", "notified_object_type"], name: "index_mailboxer_notifications_on_notified_object_id_and_type" + t.index ["notified_object_type", "notified_object_id"], name: "mailboxer_notifications_notified_object" + t.index ["sender_id", "sender_type"], name: "index_mailboxer_notifications_on_sender_id_and_sender_type" + t.index ["type"], name: "index_mailboxer_notifications_on_type" + end + + create_table "mailboxer_receipts", id: :serial, force: :cascade do |t| + t.string "receiver_type" + t.integer "receiver_id" + t.integer "notification_id", null: false + t.boolean "is_read", default: false + t.boolean "trashed", default: false + t.boolean "deleted", default: false + t.string "mailbox_type", limit: 25 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.boolean "is_delivered", default: false + t.string "delivery_method" + t.string "message_id" + t.index ["notification_id"], name: "index_mailboxer_receipts_on_notification_id" + t.index ["receiver_id", "receiver_type"], name: "index_mailboxer_receipts_on_receiver_id_and_receiver_type" + end + create_table "median_functions", id: :serial, force: :cascade do |t| end @@ -433,6 +488,16 @@ ActiveRecord::Schema.define(version: 2019_03_26_224347) do t.integer "creator_id" end + create_table "seed_trades", force: :cascade do |t| + t.bigint "seed_id" + t.bigint "member_id" + t.boolean "accepted" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["member_id"], name: "index_seed_trades_on_member_id" + t.index ["seed_id"], name: "index_seed_trades_on_seed_id" + end + create_table "seeds", id: :serial, force: :cascade do |t| t.integer "owner_id", null: false t.integer "crop_id", null: false @@ -454,9 +519,32 @@ ActiveRecord::Schema.define(version: 2019_03_26_224347) do t.index ["slug"], name: "index_seeds_on_slug", unique: true end + create_table "trades", force: :cascade do |t| + t.bigint "seed_id" + t.bigint "responded_seed_id" + t.bigint "requested_by_id" + t.boolean "accepted" + t.text "message" + t.text "address_for_delivery" + t.text "rejection_reason" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["requested_by_id"], name: "index_trades_on_requested_by_id" + t.index ["responded_seed_id"], name: "index_trades_on_responded_seed_id" + t.index ["seed_id"], name: "index_trades_on_seed_id" + end + add_foreign_key "harvests", "plantings" + add_foreign_key "mailboxer_conversation_opt_outs", "mailboxer_conversations", column: "conversation_id", name: "mb_opt_outs_on_conversations_id" + add_foreign_key "mailboxer_notifications", "mailboxer_conversations", column: "conversation_id", name: "notifications_on_conversation_id" + add_foreign_key "mailboxer_receipts", "mailboxer_notifications", column: "notification_id", name: "receipts_on_notification_id" add_foreign_key "photographings", "crops" add_foreign_key "photographings", "photos" add_foreign_key "plantings", "seeds", column: "parent_seed_id", name: "parent_seed", on_delete: :nullify + add_foreign_key "seed_trades", "members" + add_foreign_key "seed_trades", "seeds" add_foreign_key "seeds", "plantings", column: "parent_planting_id", name: "parent_planting", on_delete: :nullify + add_foreign_key "trades", "members", column: "requested_by_id" + add_foreign_key "trades", "seeds" + add_foreign_key "trades", "seeds", column: "responded_seed_id" end From 097555ec06664a681bf8e63b11c0c320fb217722 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 20 Jul 2019 13:20:24 +1200 Subject: [PATCH 021/151] View for messages --- app/views/messages/_form.haml | 26 ++++++++++++++++++++++++++ app/views/messages/new.html.haml | 6 ++++++ 2 files changed, 32 insertions(+) create mode 100644 app/views/messages/_form.haml create mode 100644 app/views/messages/new.html.haml diff --git a/app/views/messages/_form.haml b/app/views/messages/_form.haml new file mode 100644 index 000000000..5d277b384 --- /dev/null +++ b/app/views/messages/_form.haml @@ -0,0 +1,26 @@ += bootstrap_form_for @message do |f| + .card + .card-body + -# - if @notification.errors.any? + -# #error_explanation + -# %h2 + -# = pluralize(@notification.errors.size, "error") + -# prohibited this message from being sent: + -# %ul + -# - @notification.errors.full_messages.each do |msg| + -# %li= msg + + .field + = f.hidden_field :recipient_id, value: @recipient.id + + %p + To + = link_to @recipient, @recipient + = render 'members/tiny', member: @recipient + = f.text_field :subject, value: @subject, class: 'form-control', maxlength: 255 + = f.text_area :body, rows: 12, label: "Type your message here" + %span.help-block= render partial: "shared/markdown_help" + .card-footer + + = link_to 'cancel', notifications_path, class: 'btn' + .float-right= f.submit "Send", class: 'btn btn-primary' diff --git a/app/views/messages/new.html.haml b/app/views/messages/new.html.haml new file mode 100644 index 000000000..721dcca7d --- /dev/null +++ b/app/views/messages/new.html.haml @@ -0,0 +1,6 @@ += content_for :title, "Send a message to #{@recipient}" +- content_for :breadcrumbs do + %li.breadcrumb-item= link_to 'Messages', notifications_path + += render 'form' + From 339b3fd57e656161117249c540c6b8ee2e00e552 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 20 Jul 2019 13:21:05 +1200 Subject: [PATCH 022/151] Moving to conversations and messages instead of notifications --- app/controllers/conversations_controller.rb | 25 +++----- app/controllers/messages_controller.rb | 20 ++++--- app/controllers/notifications_controller.rb | 37 ++++++++---- app/models/notification.rb | 10 ++-- app/views/conversations/index.haml | 66 +++++++++++---------- app/views/conversations/show.html.haml | 39 ++++++++++++ app/views/layouts/_header.html.haml | 4 +- app/views/members/show.html.haml | 2 +- app/views/notifications/_form.html.haml | 2 +- 9 files changed, 132 insertions(+), 73 deletions(-) create mode 100644 app/views/conversations/show.html.haml diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index 6c69e4893..6064ee76f 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -1,7 +1,7 @@ class ConversationsController < ApplicationController before_action :authenticate_member! before_action :get_mailbox, :get_box # , :get_actor - # before_action :check_current_subject_in_conversation, :only => [:show, :update, :destroy] + before_action :check_current_subject_in_conversation, :only => [:show, :update, :destroy] def index @conversations = if @box.eql? "inbox" @@ -18,13 +18,10 @@ class ConversationsController < ApplicationController end def show - @receipts = if @box.eql? 'trash' - @mailbox.receipts_for(@conversation).trash - else - @mailbox.receipts_for(@conversation).not_trash - end - render action: :show - @receipts.mark_as_read + # byebug + # @receipts = @mailbox.receipts_for(@conversation) + # @receipts.mark_as_read + # render action: :show end def update @@ -36,7 +33,7 @@ class ConversationsController < ApplicationController end @receipts = if @box.eql? 'trash' - @mailbox.receipts_for(@conversation).trash + @mailbox.receipts_for(@conversation).trash else @mailbox.receipts_for(@conversation).not_trash end @@ -71,20 +68,14 @@ class ConversationsController < ApplicationController @mailbox = current_member.mailbox end - def get_actor - @actor = Actor.normalize(current_subject) - end - def get_box params[:box] = 'inbox' if params[:box].blank? || !%w(inbox sentbox trash).include?(params[:box]) - @box = params[:box] end def check_current_subject_in_conversation - @conversation = Conversation.find_by(id: params[:id]) - - if @conversation.nil? || !@conversation.is_participant?(@actor) + @conversation = Mailboxer::Conversation.find_by(id: params[:id]) + if @conversation.nil? || !@conversation.is_participant?(current_member) redirect_to conversations_path(box: @box) return end diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index ec9b98702..d19c4645b 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -1,6 +1,6 @@ class MessagesController < ApplicationController - before_action :authenticate_user! - before_action :get_mailbox, :get_box, :get_actor + before_action :authenticate_member! + before_action :get_mailbox #, :get_box, :get_actor def index redirect_to conversations_path(box: @box) end @@ -17,14 +17,13 @@ class MessagesController < ApplicationController redirect_to conversations_path(box: @box) end - # GET /messages/new - # GET /messages/new.xml def new - if params[:receiver].present? - @recipient = Actor.find_by(slug: params[:receiver]) + @message = Mailboxer::Message.new + if params[:recipient_id].present? + @recipient = Member.find_by(id: params[:recipient_id]) return if @recipient.nil? - @recipient = nil if Actor.normalize(@recipient) == Actor.normalize(current_subject) + # @recipient = nil if Member.normalize(@recipient) == Actor.normalize(current_subject) end end @@ -76,4 +75,11 @@ class MessagesController < ApplicationController end @box = params[:box] end + + def current_subject + @current_subject ||= + # current_subject_from_params || + # current_subject_from_session || + current_member + end end diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index 9e2475d9d..a82c674f2 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -6,7 +6,7 @@ class NotificationsController < ApplicationController # GET /notifications def index - @notifications = Notification.by_recipient(current_member).order(created_at: :desc).paginate(page: params[:page], per_page: 30) + # @notifications = Notification.by_recipient(current_member).order(created_at: :desc).paginate(page: params[:page], per_page: 30) end # GET /notifications/1 @@ -47,19 +47,18 @@ class NotificationsController < ApplicationController # POST /notifications def create # params[:notification][:sender_id] = current_member.id - # @notification = Notification.new(notification_params) - @recipient = Member.find_by(id: notification_params[:recipient_id]) + @notification = Notification.new(notification_params) + @notification.sender = current_member + @notification.recipient = Member.find_by(id: notification_params[:recipient_id]) @body = notification_params[:body] @subject = notification_params[:subject] - byebug - current_member.send_message(@recipient, @body, @subject) - - # if @notification.save + if @notification.save + @notification.sender.send_message(@notification.recipient, @notification.body, @notification.subject) redirect_to notifications_path, notice: 'Message was successfully sent.' - # else - # render action: "new" - # end + else + render action: "new" + end end private @@ -67,4 +66,22 @@ class NotificationsController < ApplicationController def notification_params params.require(:notification).permit(:sender_id, :recipient_id, :subject, :body, :post_id, :read) end + + def conversation_params(*keys) + fetch_params(:conversation, *keys) + end + + def message_params(*keys) + fetch_params(:message, *keys) + end + + def fetch_params(key, *subkeys) + params[key].instance_eval do + case subkeys.size + when 0 then self + when 1 then self[subkeys.first] + else subkeys.map{|k| self[k] } + end + end + end end diff --git a/app/models/notification.rb b/app/models/notification.rb index d4e8db676..4a8137d55 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -9,7 +9,7 @@ class Notification < ApplicationRecord scope :by_recipient, ->(recipient) { where(recipient_id: recipient) } before_create :replace_blank_subject - after_create :send_email + # after_create :create_mailboxer_message def self.unread_count unread.size @@ -19,7 +19,9 @@ class Notification < ApplicationRecord self.subject = "(no subject)" if subject.nil? || subject =~ /^\s*$/ end - def send_email - Notifier.notify(self).deliver_now! if recipient.send_notification_email - end + # def create_mailboxer_message + # byebug + # sender.send_message(recipient, body, subject) + # Notifier.notify(self).deliver_now! if recipient.send_notification_email + # end end diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index 8be9c5833..065149712 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -1,35 +1,39 @@ - content_for :title, "Inbox" - content_for :breadcrumbs do - %li.breadcrumb-item.active= link_to 'Messages', notifications_path + %li.breadcrumb-item.active= link_to 'Conversations', conversations_path -- if @conversations.empty? - .alert.alert-success{role: "alert"} You have no messages. -- else - = paginate @conversations, theme: 'twitter-bootstrap-3' +- unless @conversations.empty? + = paginate @conversations --# - @conversations.each do |n| --# .card.message --# .card-body --# .row --# .col-6.col-md-9 --# %h3= link_to n.subject, notification_path(n) --# %p --# - if n.read --# = icon 'far', 'envelope-open' --# - else --# = icon 'far', 'envelope' --# %strong unread --# = n.created_at --# .col-6.col-md-3.text-right --# = link_to n.sender do --# %h3 --# = render 'members/tiny', member: n.sender --# = n.sender --# = render 'members/follow_buttons', member: n.sender --# .card-footer --# = link_to 'Read', n, class: 'btn btn-primary' --# = link_to 'Reply', reply_link(n), class: 'btn btn-secondary' --# = link_to n, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger btn-xs' do --# = delete_icon --# = t('buttons.delete') --# = paginate @conversations \ No newline at end of file + +%ul.nav.grey.lighten-4.py-4 + - %W[inbox sentbox trash].each do |box| + %li.nav-item= link_to box, conversations_path(box: box), class: 'nav-link' + +- @conversations.each do |conversation| + .card.message + .card-body + .row + .col-6.col-md-9 + %h3= link_to conversation.subject, conversation_path(conversation) + -# %p + -# - if n.read + -# = icon 'far', 'envelope-open' + -# - else + -# = icon 'far', 'envelope' + -# %strong unread + -# = n.created_at + -# .col-6.col-md-3.text-right + -# = link_to n.sender do + -# %h3 + -# = render 'members/tiny', member: n.sender + -# = n.sender + -# = render 'members/follow_buttons', member: n.sender + .card-footer + = link_to 'Read', conversation_path(conversation), class: 'btn btn-primary' + -#= link_to 'Reply', reply_link(conversation), class: 'btn btn-secondary' + = link_to conversation_path(conversation), method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger btn-xs' do + = delete_icon + = t('buttons.delete') +- unless @conversations.empty? + = paginate @conversations \ No newline at end of file diff --git a/app/views/conversations/show.html.haml b/app/views/conversations/show.html.haml new file mode 100644 index 000000000..6a79642f7 --- /dev/null +++ b/app/views/conversations/show.html.haml @@ -0,0 +1,39 @@ +- content_for :breadcrumbs do + %li.breadcrumb-item= link_to 'Conversations', conversations_path + %li.breadcrumb-item.active= link_to @conversation.subject, conversation_path(@conversation) + + +.row + .col-2.card + .card-header + %h6 Participants + .card-body + - @conversation.recipients.each do |r| + %li + = render 'members/tiny', member: r + = link_to r, r + .col-10 + %h1= @conversation.subject + - @conversation.messages.each do |message| + .card + .card-body + .card-title= message.subject + .float-right + = link_to message.sender do + = message.sender + = render 'members/tiny', member: message.sender + %p.text-muted + From + = link_to message.sender, message.sender + on + = message.created_at + .well + :growstuff_markdown + #{ strip_tags(message.body) } + + + .card-footer + -# = link_to 'Reply', @reply_link, class: 'btn btn-primary' + -# = link_to message, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger' do + -# = delete_icon + -# = t('buttons.delete') diff --git a/app/views/layouts/_header.html.haml b/app/views/layouts/_header.html.haml index 8093caccb..5fbeab4c5 100644 --- a/app/views/layouts/_header.html.haml +++ b/app/views/layouts/_header.html.haml @@ -49,11 +49,11 @@ - if current_member.notifications.unread_count.positive? .dropdown-divider %strong - = link_to(notifications_path, class: 'dropdown-item') do + = link_to(conversations_path, class: 'dropdown-item') do = t('.inbox') %span.badge.badge-info= current_member.notifications.unread_count - else - = link_to t('.inbox'), notifications_path, class: 'dropdown-item' + = link_to t('.inbox'), conversations_path, class: 'dropdown-item' - if current_member.role?(:crop_wrangler) || current_member.role?(:admin) %li.nav-item.dropdown diff --git a/app/views/members/show.html.haml b/app/views/members/show.html.haml index 8031e151a..8661126fb 100644 --- a/app/views/members/show.html.haml +++ b/app/views/members/show.html.haml @@ -39,7 +39,7 @@ = t('members.edit_profile') - if can?(:create, Notification) && current_member != @member - = link_to new_notification_path(recipient_id: @member.id), class: 'btn btn-block' do + = link_to new_message_path(recipient_id: @member.id), class: 'btn btn-block' do = icon('fas', 'envelope') Send message diff --git a/app/views/notifications/_form.html.haml b/app/views/notifications/_form.html.haml index 5f5880a93..d613007a1 100644 --- a/app/views/notifications/_form.html.haml +++ b/app/views/notifications/_form.html.haml @@ -4,7 +4,7 @@ - if @notification.errors.any? #error_explanation %h2 - = pluralize(@post.errors.size, "error") + = pluralize(@notification.errors.size, "error") prohibited this message from being sent: %ul - @notification.errors.full_messages.each do |msg| From 26839acf01200f7ac1bb3fbff5344a4a12d1ce65 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 20 Jul 2019 13:21:26 +1200 Subject: [PATCH 023/151] Turn off message sending until errors are fixed --- config/initializers/mailboxer.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/initializers/mailboxer.rb b/config/initializers/mailboxer.rb index cfa647e6d..1a62934cb 100644 --- a/config/initializers/mailboxer.rb +++ b/config/initializers/mailboxer.rb @@ -1,9 +1,9 @@ Mailboxer.setup do |config| # Configures if your application uses or not email sending for Notifications and Messages - config.uses_emails = true + config.uses_emails = false # Configures the default from for emails sent for Messages and Notifications - config.default_from = "no-reply@mailboxer.com" + config.default_from = "no-reply@growstuff.org" # Configures the methods needed by mailboxer config.email_method = :email From d91a5bf55f75e8fb3cf3d692ddd1d3ea2c1ebd28 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 20 Jul 2019 19:43:29 +1200 Subject: [PATCH 024/151] Rewriting messages functionality to use mail boxer --- app/controllers/conversations_controller.rb | 67 +++++++---------- app/controllers/messages_controller.rb | 57 ++++----------- app/models/notification.rb | 10 ++- app/views/conversations/index.haml | 72 +++++++++++-------- app/views/conversations/show.html.haml | 52 +++++++------- app/views/members/_tiny.haml | 2 +- app/views/messages/_form.haml | 28 +++++--- app/views/messages/new.html.haml | 2 +- config/initializers/mailboxer.rb | 4 +- config/routes.rb | 3 - ...190720000625_notifications_to_mailboxer.rb | 5 ++ 11 files changed, 138 insertions(+), 164 deletions(-) diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index 6064ee76f..6f6ef8515 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -1,82 +1,67 @@ class ConversationsController < ApplicationController + respond_to :html before_action :authenticate_member! - before_action :get_mailbox, :get_box # , :get_actor + # before_action :get_mailbox, :get_box before_action :check_current_subject_in_conversation, :only => [:show, :update, :destroy] def index - @conversations = if @box.eql? "inbox" - @mailbox.inbox.paginate(page: params[:page]) - elsif @box.eql? "sentbox" - @mailbox.sentbox.paginate(page: params[:page]) + @conversations = if box.eql? "inbox" + mailbox.inbox.paginate(page: params[:page]) + elsif box.eql? "sentbox" + mailbox.sentbox.paginate(page: params[:page]) else - @mailbox.trash.paginate(page: params[:page]) + mailbox.trash.paginate(page: params[:page]) end - respond_to do |format| - format.html { render @conversations if request.xhr? } - end + respond_with @conversations end def show - # byebug - # @receipts = @mailbox.receipts_for(@conversation) - # @receipts.mark_as_read - # render action: :show + @receipts = mailbox.receipts_for(@conversation) + @receipts.mark_as_read end def update @conversation.untrash(@actor) if params[:untrash].present? if params[:reply_all].present? - last_receipt = @mailbox.receipts_for(@conversation).last + last_receipt = mailbox.receipts_for(@conversation).last @receipt = @actor.reply_to_all(last_receipt, params[:body]) end - @receipts = if @box.eql? 'trash' - @mailbox.receipts_for(@conversation).trash + @receipts = if box.eql? 'trash' + mailbox.receipts_for(@conversation).trash else - @mailbox.receipts_for(@conversation).not_trash + mailbox.receipts_for(@conversation).not_trash end redirect_to action: :show @receipts.mark_as_read end def destroy - @conversation.move_to_trash(@actor) - - respond_to do |format| - format.html do - if params[:location].present? && (params[:location] == 'conversation') - redirect_to conversations_path(box: :trash) - else - redirect_to conversations_path(box: @box, page: params[:page]) - end - end - format.js do - if params[:location].present? && (params[:location] == 'conversation') - render js: "window.location = '#{conversations_path(box: @box, page: params[:page])}';" - else - render 'conversations/destroy' - end - end - end + @conversation = Mailboxer::Conversation.find params[:id] + current_member.mark_as_deleted @conversation + redirect_to conversations_path end private - def get_mailbox - @mailbox = current_member.mailbox + def mailbox + current_member.mailbox end - def get_box - params[:box] = 'inbox' if params[:box].blank? || !%w(inbox sentbox trash).include?(params[:box]) - @box = params[:box] + def box + if params[:box].blank? || !%w(inbox sentbox trash).include?(params[:box]) + 'inbox' + else + params[:box] + end end def check_current_subject_in_conversation @conversation = Mailboxer::Conversation.find_by(id: params[:id]) if @conversation.nil? || !@conversation.is_participant?(current_member) - redirect_to conversations_path(box: @box) + redirect_to conversations_path(box: box) return end end diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index d19c4645b..c29144223 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -1,15 +1,13 @@ class MessagesController < ApplicationController + respond_to :html, :json before_action :authenticate_member! - before_action :get_mailbox #, :get_box, :get_actor def index redirect_to conversations_path(box: @box) end - # GET /messages/1 - # GET /messages/1.xml def show if (@message = Message.find_by(id: params[:id])) && (@conversation = @message.conversation) - if @conversation.is_participant?(@actor) + if @conversation.is_participant?(current_member) redirect_to conversation_path(@conversation, box: @box, anchor: "message_" + @message.id.to_s) return end @@ -18,64 +16,33 @@ class MessagesController < ApplicationController end def new - @message = Mailboxer::Message.new if params[:recipient_id].present? @recipient = Member.find_by(id: params[:recipient_id]) return if @recipient.nil? - - # @recipient = nil if Member.normalize(@recipient) == Actor.normalize(current_subject) end end - # GET /messages/1/edit - def edit; end - - # POST /messages - # POST /messages.xml def create - @recipients = - if params[:_recipients].present? - @recipients = params[:_recipients].split(',').map { |r| Actor.find(r) } - else - [] - end - - @receipt = @actor.send_message(@recipients, params[:body], params[:subject]) - if @receipt.errors.blank? - @conversation = @receipt.conversation - flash[:success] = t('mailboxer.sent') - redirect_to conversation_path(@conversation, box: :sentbox) + if params[:conversation_id].present? + @conversation = Mailboxer::Conversation.find(params[:conversation_id]) + # receipts = conversation.receipts_for alfa + current_member.reply_to_conversation(@conversation, params[:body]) + redirect_to conversation_path(@conversation) else - render action: :new + recipient = Member.find(params[:recipient_id]) + body = params[:body] + subject = params[:subject] + @conversation = current_member.send_message(recipient, body, subject) + redirect_to conversations_path(box: 'sentbox') end end - # PUT /messages/1 - # PUT /messages/1.xml def update; end - # DELETE /messages/1 - # DELETE /messages/1.xml def destroy; end private - def get_mailbox - @mailbox = current_subject.mailbox - end - - def get_actor - @actor = Actor.normalize(current_subject) - end - - def get_box - if params[:box].blank? || !%w(inbox sentbox trash).include?(params[:box]) - @box = "inbox" - return - end - @box = params[:box] - end - def current_subject @current_subject ||= # current_subject_from_params || diff --git a/app/models/notification.rb b/app/models/notification.rb index 4a8137d55..de9d01d8d 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -9,7 +9,7 @@ class Notification < ApplicationRecord scope :by_recipient, ->(recipient) { where(recipient_id: recipient) } before_create :replace_blank_subject - # after_create :create_mailboxer_message + after_create :create_mailboxer_message def self.unread_count unread.size @@ -19,9 +19,7 @@ class Notification < ApplicationRecord self.subject = "(no subject)" if subject.nil? || subject =~ /^\s*$/ end - # def create_mailboxer_message - # byebug - # sender.send_message(recipient, body, subject) - # Notifier.notify(self).deliver_now! if recipient.send_notification_email - # end + def create_mailboxer_message + sender.send_message(recipient, body, subject) + end end diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index 065149712..2cb9ba5f3 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -5,35 +5,45 @@ - unless @conversations.empty? = paginate @conversations +.row + .col-2 + %ul + - %W[inbox sentbox trash].each do |box| + %li.nav-item + = link_to conversations_path(box: box), class: 'nav-link' do + = box + = icon 'fas', box + .col-10 + %table.table + %thead.black.white-text + %tr + %th{scope: "col"} Sender + %th{scope: "col"} Subject + %th{scope: "col"} Sent at + %th{scope: "col"} + %tbody + - @conversations.each do |conversation| -%ul.nav.grey.lighten-4.py-4 - - %W[inbox sentbox trash].each do |box| - %li.nav-item= link_to box, conversations_path(box: box), class: 'nav-link' - -- @conversations.each do |conversation| - .card.message - .card-body - .row - .col-6.col-md-9 - %h3= link_to conversation.subject, conversation_path(conversation) - -# %p - -# - if n.read - -# = icon 'far', 'envelope-open' - -# - else - -# = icon 'far', 'envelope' - -# %strong unread - -# = n.created_at - -# .col-6.col-md-3.text-right - -# = link_to n.sender do - -# %h3 - -# = render 'members/tiny', member: n.sender - -# = n.sender - -# = render 'members/follow_buttons', member: n.sender - .card-footer - = link_to 'Read', conversation_path(conversation), class: 'btn btn-primary' - -#= link_to 'Reply', reply_link(conversation), class: 'btn btn-secondary' - = link_to conversation_path(conversation), method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger btn-xs' do - = delete_icon - = t('buttons.delete') -- unless @conversations.empty? - = paginate @conversations \ No newline at end of file + %tr{class: conversation.receipts_for(current_member).last.is_unread? ? 'active': ''} + %td + -# - conversation.recipients.each do |member| + -# - unless member == current_member + -# .float-left= render 'members/tiny', member: member + -# = link_to member.login_name, member + %td + %h3.h3-responsive + = link_to conversation_path(conversation) do + - if conversation.receipts_for(current_member).last.is_unread? + = icon 'far', 'envelope' + - else + = icon 'far', 'envelope-open' + =conversation.subject + %td + =conversation.updated_at + .text-muted (#{time_ago_in_words conversation.updated_at} ago) + %td + = link_to conversation_path(conversation), method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger btn-xs' do + = delete_icon + = t('buttons.delete') + - unless @conversations.empty? + = paginate @conversations \ No newline at end of file diff --git a/app/views/conversations/show.html.haml b/app/views/conversations/show.html.haml index 6a79642f7..19a470144 100644 --- a/app/views/conversations/show.html.haml +++ b/app/views/conversations/show.html.haml @@ -8,32 +8,34 @@ .card-header %h6 Participants .card-body - - @conversation.recipients.each do |r| - %li - = render 'members/tiny', member: r - = link_to r, r + -# - @conversation.recipients.each do |r| + -# %li + -# = render 'members/tiny', member: r + -# = link_to r, r .col-10 %h1= @conversation.subject - - @conversation.messages.each do |message| - .card + .card + - @conversation.messages.order(:created_at).each do |message| + - message .card-body - .card-title= message.subject - .float-right - = link_to message.sender do - = message.sender - = render 'members/tiny', member: message.sender - %p.text-muted - From - = link_to message.sender, message.sender - on - = message.created_at - .well - :growstuff_markdown - #{ strip_tags(message.body) } + .col + .float-left + = link_to message.sender do + = message.sender + = render 'members/tiny', member: message.sender + .col + %p.text-muted + From + = link_to message.sender, message.sender + on + = message.created_at + .well + :growstuff_markdown + #{ strip_tags(message.body) } + -# .card-footer + -# = link_to 'Reply', @reply_link, class: 'btn btn-primary' + -# = link_to message, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger' do + -# = delete_icon + -# = t('buttons.delete') - - .card-footer - -# = link_to 'Reply', @reply_link, class: 'btn btn-primary' - -# = link_to message, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger' do - -# = delete_icon - -# = t('buttons.delete') + = render 'messages/form', conversation: @conversation \ No newline at end of file diff --git a/app/views/members/_tiny.haml b/app/views/members/_tiny.haml index f8c534b3d..17733daa5 100644 --- a/app/views/members/_tiny.haml +++ b/app/views/members/_tiny.haml @@ -1 +1 @@ -= image_tag(avatar_uri(member, 50), alt: '', class: 'img img-fluid avatar', height: 50) \ No newline at end of file += image_tag(avatar_uri(member, 50), alt: '', class: 'img img-fluid avatar', height: 50, width: 50) \ No newline at end of file diff --git a/app/views/messages/_form.haml b/app/views/messages/_form.haml index 5d277b384..e32c879b0 100644 --- a/app/views/messages/_form.haml +++ b/app/views/messages/_form.haml @@ -1,4 +1,4 @@ -= bootstrap_form_for @message do |f| += bootstrap_form_tag url: '/messages' do |f| .card .card-body -# - if @notification.errors.any? @@ -11,16 +11,26 @@ -# %li= msg .field - = f.hidden_field :recipient_id, value: @recipient.id - %p - To - = link_to @recipient, @recipient - = render 'members/tiny', member: @recipient - = f.text_field :subject, value: @subject, class: 'form-control', maxlength: 255 + - if @conversation.present? + = f.hidden_field :conversation_id, value: @conversation.id + -# To + -# - @conversation.recipients.each do |recipient| + -# - unless recipient == current_member + -# = link_to recipient, recipient + -# = render 'members/tiny', member: recipient + - elsif @recipient.present? + %p + To + = link_to @recipient, @recipient + = render 'members/tiny', member: @recipient + = f.hidden_field :recipient_id, value: @recipient.id + = f.text_field :subject, value: @subject, class: 'form-control', maxlength: 255 + - else + TODO - add recipient field + = f.text_area :body, rows: 12, label: "Type your message here" %span.help-block= render partial: "shared/markdown_help" .card-footer - - = link_to 'cancel', notifications_path, class: 'btn' + = link_to 'cancel', conversations_path, class: 'btn' .float-right= f.submit "Send", class: 'btn btn-primary' diff --git a/app/views/messages/new.html.haml b/app/views/messages/new.html.haml index 721dcca7d..0f7477430 100644 --- a/app/views/messages/new.html.haml +++ b/app/views/messages/new.html.haml @@ -1,6 +1,6 @@ = content_for :title, "Send a message to #{@recipient}" - content_for :breadcrumbs do - %li.breadcrumb-item= link_to 'Messages', notifications_path + %li.breadcrumb-item= link_to 'Messages', conversations_path = render 'form' diff --git a/config/initializers/mailboxer.rb b/config/initializers/mailboxer.rb index 1a62934cb..194e5261e 100644 --- a/config/initializers/mailboxer.rb +++ b/config/initializers/mailboxer.rb @@ -12,8 +12,8 @@ Mailboxer.setup do |config| # Configures if you use or not a search engine and which one you are using # Supported engines: [:solr,:sphinx,:pg_search] - config.search_enabled = false - config.search_engine = :solr + # config.search_enabled = false + # config.search_engine = :solr # Configures maximum length of the message subject and body config.subject_max_length = 255 diff --git a/config/routes.rb b/config/routes.rb index 401bc3c7f..0bc39d728 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -97,9 +97,6 @@ Rails.application.routes.draw do get 'followers' => 'follows#followers' end - resources :notifications do - get 'reply' - end resources :messages resources :conversations diff --git a/db/migrate/20190720000625_notifications_to_mailboxer.rb b/db/migrate/20190720000625_notifications_to_mailboxer.rb index 235d3a000..6f9f5ef21 100644 --- a/db/migrate/20190720000625_notifications_to_mailboxer.rb +++ b/db/migrate/20190720000625_notifications_to_mailboxer.rb @@ -1,4 +1,9 @@ class NotificationsToMailboxer < ActiveRecord::Migration[5.2] def change + Notification.all.each do |n| + recipient = Member.with_deleted.find(n.recipient_id) + sender = Member.with_deleted.find(n.sender_id) + sender.send_message(recipient, n.body, n.subject) + end end end From a4e0ed0d8dc6b6e8ee6a98966debe4ef0427922f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 11:25:37 +1200 Subject: [PATCH 025/151] Fixed deleted imports --- app/assets/stylesheets/application.scss | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index cdd758685..15c7d43c2 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -16,6 +16,15 @@ @import 'rails_bootstrap_forms'; @import 'overrides'; +@import 'crops'; +@import 'harvests'; +@import 'likes'; +@import 'members'; +@import 'notifications'; +@import 'plantings'; +@import 'posts'; +@import 'predictions'; +@import 'seeds'; @import 'homepage'; @import 'photos'; From 1e7eb7326f7cf147f888ddf3509df99c031f9e37 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 14:22:32 +1200 Subject: [PATCH 026/151] rubocop linter --- ...00555_create_mailboxer.mailboxer_engine.rb | 76 +++++++++---------- ...dd_conversation_optout.mailboxer_engine.rb | 6 +- ...57_add_missing_indices.mailboxer_engine.rb | 8 +- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/db/migrate/20190720000555_create_mailboxer.mailboxer_engine.rb b/db/migrate/20190720000555_create_mailboxer.mailboxer_engine.rb index d42e89f9a..3b9acbddb 100644 --- a/db/migrate/20190720000555_create_mailboxer.mailboxer_engine.rb +++ b/db/migrate/20190720000555_create_mailboxer.mailboxer_engine.rb @@ -1,63 +1,63 @@ # This migration comes from mailboxer_engine (originally 20110511145103) class CreateMailboxer < ActiveRecord::Migration[4.2] def self.up - #Tables - #Conversations + # Tables + # Conversations create_table :mailboxer_conversations do |t| - t.column :subject, :string, :default => "" - t.column :created_at, :datetime, :null => false - t.column :updated_at, :datetime, :null => false + t.column :subject, :string, default: "" + t.column :created_at, :datetime, null: false + t.column :updated_at, :datetime, null: false end - #Receipts + # Receipts create_table :mailboxer_receipts do |t| - t.references :receiver, :polymorphic => true - t.column :notification_id, :integer, :null => false - t.column :is_read, :boolean, :default => false - t.column :trashed, :boolean, :default => false - t.column :deleted, :boolean, :default => false - t.column :mailbox_type, :string, :limit => 25 - t.column :created_at, :datetime, :null => false - t.column :updated_at, :datetime, :null => false + t.references :receiver, polymorphic: true + t.column :notification_id, :integer, null: false + t.column :is_read, :boolean, default: false + t.column :trashed, :boolean, default: false + t.column :deleted, :boolean, default: false + t.column :mailbox_type, :string, limit: 25 + t.column :created_at, :datetime, null: false + t.column :updated_at, :datetime, null: false end - #Notifications and Messages + # Notifications and Messages create_table :mailboxer_notifications do |t| t.column :type, :string t.column :body, :text - t.column :subject, :string, :default => "" - t.references :sender, :polymorphic => true + t.column :subject, :string, default: "" + t.references :sender, polymorphic: true t.column :conversation_id, :integer - t.column :draft, :boolean, :default => false - t.string :notification_code, :default => nil - t.references :notified_object, :polymorphic => true, index: { name: 'mailboxer_notifications_notified_object' } + t.column :draft, :boolean, default: false + t.string :notification_code, default: nil + t.references :notified_object, polymorphic: true, index: { name: 'mailboxer_notifications_notified_object' } t.column :attachment, :string - t.column :updated_at, :datetime, :null => false - t.column :created_at, :datetime, :null => false + t.column :updated_at, :datetime, null: false + t.column :created_at, :datetime, null: false t.boolean :global, default: false t.datetime :expires end - #Indexes - #Conversations - #Receipts - add_index "mailboxer_receipts","notification_id" + # Indexes + # Conversations + # Receipts + add_index "mailboxer_receipts", "notification_id" - #Messages - add_index "mailboxer_notifications","conversation_id" + # Messages + add_index "mailboxer_notifications", "conversation_id" - #Foreign keys - #Conversations - #Receipts - add_foreign_key "mailboxer_receipts", "mailboxer_notifications", :name => "receipts_on_notification_id", :column => "notification_id" - #Messages - add_foreign_key "mailboxer_notifications", "mailboxer_conversations", :name => "notifications_on_conversation_id", :column => "conversation_id" + # Foreign keys + # Conversations + # Receipts + add_foreign_key "mailboxer_receipts", "mailboxer_notifications", name: "receipts_on_notification_id", column: "notification_id" + # Messages + add_foreign_key "mailboxer_notifications", "mailboxer_conversations", name: "notifications_on_conversation_id", column: "conversation_id" end def self.down - #Tables - remove_foreign_key "mailboxer_receipts", :name => "receipts_on_notification_id" - remove_foreign_key "mailboxer_notifications", :name => "notifications_on_conversation_id" + # Tables + remove_foreign_key "mailboxer_receipts", name: "receipts_on_notification_id" + remove_foreign_key "mailboxer_notifications", name: "notifications_on_conversation_id" - #Indexes + # Indexes drop_table :mailboxer_receipts drop_table :mailboxer_conversations drop_table :mailboxer_notifications diff --git a/db/migrate/20190720000556_add_conversation_optout.mailboxer_engine.rb b/db/migrate/20190720000556_add_conversation_optout.mailboxer_engine.rb index a9860bdcb..a8aa6bbed 100644 --- a/db/migrate/20190720000556_add_conversation_optout.mailboxer_engine.rb +++ b/db/migrate/20190720000556_add_conversation_optout.mailboxer_engine.rb @@ -2,14 +2,14 @@ class AddConversationOptout < ActiveRecord::Migration[4.2] def self.up create_table :mailboxer_conversation_opt_outs do |t| - t.references :unsubscriber, :polymorphic => true + t.references :unsubscriber, polymorphic: true t.references :conversation end - add_foreign_key "mailboxer_conversation_opt_outs", "mailboxer_conversations", :name => "mb_opt_outs_on_conversations_id", :column => "conversation_id" + add_foreign_key "mailboxer_conversation_opt_outs", "mailboxer_conversations", name: "mb_opt_outs_on_conversations_id", column: "conversation_id" end def self.down - remove_foreign_key "mailboxer_conversation_opt_outs", :name => "mb_opt_outs_on_conversations_id" + remove_foreign_key "mailboxer_conversation_opt_outs", name: "mb_opt_outs_on_conversations_id" drop_table :mailboxer_conversation_opt_outs end end diff --git a/db/migrate/20190720000557_add_missing_indices.mailboxer_engine.rb b/db/migrate/20190720000557_add_missing_indices.mailboxer_engine.rb index 608d7f620..b079f4a3d 100644 --- a/db/migrate/20190720000557_add_missing_indices.mailboxer_engine.rb +++ b/db/migrate/20190720000557_add_missing_indices.mailboxer_engine.rb @@ -3,18 +3,18 @@ class AddMissingIndices < ActiveRecord::Migration[4.2] def change # We'll explicitly specify its name, as the auto-generated name is too long and exceeds 63 # characters limitation. - add_index :mailboxer_conversation_opt_outs, [:unsubscriber_id, :unsubscriber_type], + add_index :mailboxer_conversation_opt_outs, %i(unsubscriber_id unsubscriber_type), name: 'index_mailboxer_conversation_opt_outs_on_unsubscriber_id_type' add_index :mailboxer_conversation_opt_outs, :conversation_id add_index :mailboxer_notifications, :type - add_index :mailboxer_notifications, [:sender_id, :sender_type] + add_index :mailboxer_notifications, %i(sender_id sender_type) # We'll explicitly specify its name, as the auto-generated name is too long and exceeds 63 # characters limitation. - add_index :mailboxer_notifications, [:notified_object_id, :notified_object_type], + add_index :mailboxer_notifications, %i(notified_object_id notified_object_type), name: 'index_mailboxer_notifications_on_notified_object_id_and_type' - add_index :mailboxer_receipts, [:receiver_id, :receiver_type] + add_index :mailboxer_receipts, %i(receiver_id receiver_type) end end From ecb8ad9dfd2ad0610d432fea765b18a80323a4b8 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 14:24:02 +1200 Subject: [PATCH 027/151] removing unused code --- app/controllers/conversations_controller.rb | 5 ++--- app/controllers/messages_controller.rb | 3 +-- app/controllers/notifications_controller.rb | 18 ------------------ 3 files changed, 3 insertions(+), 23 deletions(-) diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index 6f6ef8515..615df01fb 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -1,8 +1,7 @@ class ConversationsController < ApplicationController respond_to :html before_action :authenticate_member! - # before_action :get_mailbox, :get_box - before_action :check_current_subject_in_conversation, :only => [:show, :update, :destroy] + before_action :check_current_subject_in_conversation, only: %i(show update destroy) def index @conversations = if box.eql? "inbox" @@ -30,7 +29,7 @@ class ConversationsController < ApplicationController end @receipts = if box.eql? 'trash' - mailbox.receipts_for(@conversation).trash + mailbox.receipts_for(@conversation).trash else mailbox.receipts_for(@conversation).not_trash end diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index c29144223..cf1acf321 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -25,7 +25,6 @@ class MessagesController < ApplicationController def create if params[:conversation_id].present? @conversation = Mailboxer::Conversation.find(params[:conversation_id]) - # receipts = conversation.receipts_for alfa current_member.reply_to_conversation(@conversation, params[:body]) redirect_to conversation_path(@conversation) else @@ -47,6 +46,6 @@ class MessagesController < ApplicationController @current_subject ||= # current_subject_from_params || # current_subject_from_session || - current_member + current_member end end diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index a82c674f2..ce4edc5cb 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -66,22 +66,4 @@ class NotificationsController < ApplicationController def notification_params params.require(:notification).permit(:sender_id, :recipient_id, :subject, :body, :post_id, :read) end - - def conversation_params(*keys) - fetch_params(:conversation, *keys) - end - - def message_params(*keys) - fetch_params(:message, *keys) - end - - def fetch_params(key, *subkeys) - params[key].instance_eval do - case subkeys.size - when 0 then self - when 1 then self[subkeys.first] - else subkeys.map{|k| self[k] } - end - end - end end From dab9a96486076a925521e339c08d0c364d344072 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 14:47:32 +1200 Subject: [PATCH 028/151] better handling of deleted members --- app/controllers/conversations_controller.rb | 38 +++++++++++---------- app/views/conversations/index.haml | 14 ++++++-- app/views/conversations/show.html.haml | 35 +++++++++---------- app/views/members/_tiny.haml | 5 ++- 4 files changed, 51 insertions(+), 41 deletions(-) diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index 615df01fb..e7e7150f7 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -1,12 +1,13 @@ class ConversationsController < ApplicationController respond_to :html before_action :authenticate_member! + before_action :set_box before_action :check_current_subject_in_conversation, only: %i(show update destroy) def index - @conversations = if box.eql? "inbox" + @conversations = if @box.eql? "inbox" mailbox.inbox.paginate(page: params[:page]) - elsif box.eql? "sentbox" + elsif @box.eql? "sent" mailbox.sentbox.paginate(page: params[:page]) else mailbox.trash.paginate(page: params[:page]) @@ -21,25 +22,25 @@ class ConversationsController < ApplicationController end def update - @conversation.untrash(@actor) if params[:untrash].present? + # @conversation.untrash(@actor) if params[:untrash].present? - if params[:reply_all].present? - last_receipt = mailbox.receipts_for(@conversation).last - @receipt = @actor.reply_to_all(last_receipt, params[:body]) - end + # if params[:reply_all].present? + # last_receipt = mailbox.receipts_for(@conversation).last + # @receipt = @actor.reply_to_all(last_receipt, params[:body]) + # end - @receipts = if box.eql? 'trash' - mailbox.receipts_for(@conversation).trash - else - mailbox.receipts_for(@conversation).not_trash - end - redirect_to action: :show - @receipts.mark_as_read + # @receipts = if box.eql? 'trash' + # mailbox.receipts_for(@conversation).trash + # else + # mailbox.receipts_for(@conversation).not_trash + # end + # redirect_to action: :show + # @receipts.mark_as_read end def destroy - @conversation = Mailboxer::Conversation.find params[:id] - current_member.mark_as_deleted @conversation + @conversation = Mailboxer::Conversation.find(params[:id]) + @conversation.move_to_trash(current_member) redirect_to conversations_path end @@ -49,8 +50,9 @@ class ConversationsController < ApplicationController current_member.mailbox end - def box - if params[:box].blank? || !%w(inbox sentbox trash).include?(params[:box]) + def set_box + @boxes = %W[inbox sent trash] + @box = if params[:box].blank? || !@boxes.include?(params[:box]) 'inbox' else params[:box] diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index 2cb9ba5f3..4917fea56 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -5,19 +5,21 @@ - unless @conversations.empty? = paginate @conversations + .row .col-2 %ul - - %W[inbox sentbox trash].each do |box| + - @boxes.each do |box| %li.nav-item = link_to conversations_path(box: box), class: 'nav-link' do = box = icon 'fas', box .col-10 + %h1= @box %table.table %thead.black.white-text %tr - %th{scope: "col"} Sender + %th{scope: "col"} Participants %th{scope: "col"} Subject %th{scope: "col"} Sent at %th{scope: "col"} @@ -26,7 +28,13 @@ %tr{class: conversation.receipts_for(current_member).last.is_unread? ? 'active': ''} %td - -# - conversation.recipients.each do |member| + - conversation.receipts.each do |r| + = render 'members/tiny', member: r.receiver + - if r.receiver.nil? + deleted member + - else + = link_to r.receiver, r.receiver + -# - unless member == current_member -# .float-left= render 'members/tiny', member: member -# = link_to member.login_name, member diff --git a/app/views/conversations/show.html.haml b/app/views/conversations/show.html.haml index 19a470144..57bcc59d0 100644 --- a/app/views/conversations/show.html.haml +++ b/app/views/conversations/show.html.haml @@ -8,30 +8,27 @@ .card-header %h6 Participants .card-body - -# - @conversation.recipients.each do |r| - -# %li - -# = render 'members/tiny', member: r - -# = link_to r, r + - @conversation.receipts.each do |r| + %li + = render 'members/tiny', member: r.receiver + - if r.receiver.nil? + deleted member + - else + = link_to r.receiver, r.receiver + .col-10 %h1= @conversation.subject .card - @conversation.messages.order(:created_at).each do |message| - - message .card-body - .col - .float-left - = link_to message.sender do - = message.sender - = render 'members/tiny', member: message.sender - .col - %p.text-muted - From - = link_to message.sender, message.sender - on - = message.created_at - .well - :growstuff_markdown - #{ strip_tags(message.body) } + %p.text-muted + From + = link_to message.sender, message.sender + on + = message.created_at + .well + :growstuff_markdown + #{ strip_tags(message.body) } -# .card-footer -# = link_to 'Reply', @reply_link, class: 'btn btn-primary' -# = link_to message, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger' do diff --git a/app/views/members/_tiny.haml b/app/views/members/_tiny.haml index 17733daa5..fa06f0d34 100644 --- a/app/views/members/_tiny.haml +++ b/app/views/members/_tiny.haml @@ -1 +1,4 @@ -= image_tag(avatar_uri(member, 50), alt: '', class: 'img img-fluid avatar', height: 50, width: 50) \ No newline at end of file +- if member.nil? + = icon 'fas', 'user-times' +- else + = image_tag(avatar_uri(member, 50), alt: '', class: 'img img-fluid avatar', height: 50, width: 50) \ No newline at end of file From 1df84beb6d79e007789535171e2841184a31b382 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 15:29:39 +1200 Subject: [PATCH 029/151] introduce pretty chips for members --- app/assets/stylesheets/_members.scss | 19 +++++++++++++++++++ app/views/members/_tiny.haml | 14 ++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/_members.scss b/app/assets/stylesheets/_members.scss index aef8571ed..f71d7697e 100644 --- a/app/assets/stylesheets/_members.scss +++ b/app/assets/stylesheets/_members.scss @@ -15,3 +15,22 @@ padding-left: 1em; width: 15em; } + + +.member-chip { + display: inline-block; + padding: 0 25px; + height: 50px; + font-size: 16px; + line-height: 50px; + border-radius: 25px; + background-color: #f1f1f1; +} + +.member-chip img { + float: left; + margin: 0 10px 0 -25px; + height: 50px; + width: 50px; + border-radius: 50%; +} \ No newline at end of file diff --git a/app/views/members/_tiny.haml b/app/views/members/_tiny.haml index fa06f0d34..1479f69da 100644 --- a/app/views/members/_tiny.haml +++ b/app/views/members/_tiny.haml @@ -1,4 +1,10 @@ -- if member.nil? - = icon 'fas', 'user-times' -- else - = image_tag(avatar_uri(member, 50), alt: '', class: 'img img-fluid avatar', height: 50, width: 50) \ No newline at end of file +.member-chip + - if member.nil? + = icon 'fas', 'user-times' + deleted + - else + = link_to member do + = image_tag(avatar_uri(member, 100), alt: '', height: 50, width: 50) + = member + + From 7f16fdfe5326f62d2f4ca5518ae9a7922a339912 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 15:29:54 +1200 Subject: [PATCH 030/151] working on display of messages in conversations --- app/controllers/conversations_controller.rb | 9 +++-- app/views/conversations/index.haml | 27 ++++++++------- app/views/conversations/show.html.haml | 37 +++++++++------------ 3 files changed, 36 insertions(+), 37 deletions(-) diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index e7e7150f7..a0ec258c0 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -19,6 +19,7 @@ class ConversationsController < ApplicationController def show @receipts = mailbox.receipts_for(@conversation) @receipts.mark_as_read + @participants = @conversation.participants end def update @@ -51,8 +52,12 @@ class ConversationsController < ApplicationController end def set_box - @boxes = %W[inbox sent trash] - @box = if params[:box].blank? || !@boxes.include?(params[:box]) + @boxes = { + 'inbox'=> mailbox.inbox.size, + 'sent'=> mailbox.sentbox.size, + 'trash'=> mailbox.trash.size + } + @box = if params[:box].blank? || !@boxes.keys.include?(params[:box]) 'inbox' else params[:box] diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index 4917fea56..949ca8bba 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -5,17 +5,21 @@ - unless @conversations.empty? = paginate @conversations - .row .col-2 - %ul - - @boxes.each do |box| - %li.nav-item - = link_to conversations_path(box: box), class: 'nav-link' do - = box - = icon 'fas', box .col-10 %h1= @box +.row + .col-2 + %ul.list-group + - @boxes.each do |box_name, item_count| + %li.list-group-item.d-flex.justify-content-between{class: box_name == @box ? 'active' : ''} + = link_to conversations_path(box: box_name), class: 'nav-link' do + = icon 'fas', box_name + = box_name + %span.badge.badge-primary.badge-pill= item_count + + .col-10 %table.table %thead.black.white-text %tr @@ -28,13 +32,8 @@ %tr{class: conversation.receipts_for(current_member).last.is_unread? ? 'active': ''} %td - - conversation.receipts.each do |r| - = render 'members/tiny', member: r.receiver - - if r.receiver.nil? - deleted member - - else - = link_to r.receiver, r.receiver - + -# - conversation.participants.each do |member| + -# = render 'members/tiny', member: member -# - unless member == current_member -# .float-left= render 'members/tiny', member: member -# = link_to member.login_name, member diff --git a/app/views/conversations/show.html.haml b/app/views/conversations/show.html.haml index 57bcc59d0..5b3e9c854 100644 --- a/app/views/conversations/show.html.haml +++ b/app/views/conversations/show.html.haml @@ -4,31 +4,26 @@ .row - .col-2.card - .card-header - %h6 Participants - .card-body - - @conversation.receipts.each do |r| - %li - = render 'members/tiny', member: r.receiver - - if r.receiver.nil? - deleted member - - else - = link_to r.receiver, r.receiver - + .col-2 + .card + .card-header + %h6 Participants + %ul.list-group.list-group-flush + - @participants.each do |member| + %li.list-group-item= render 'members/tiny', member: member .col-10 %h1= @conversation.subject .card - @conversation.messages.order(:created_at).each do |message| - .card-body - %p.text-muted - From - = link_to message.sender, message.sender - on - = message.created_at - .well - :growstuff_markdown - #{ strip_tags(message.body) } + %ul.list-group.list-group-flush + %li.list-group-item + .text-muted.float-right + = comment_icon + on #{message.created_at} + = render 'members/tiny', member: message.sender + %p.mb-2.well + :growstuff_markdown + #{ strip_tags(message.body) } -# .card-footer -# = link_to 'Reply', @reply_link, class: 'btn btn-primary' -# = link_to message, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger' do From 67ce5265b4f906b83466fb8471964a951f0aa6c1 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 16:58:57 +1200 Subject: [PATCH 031/151] Migrate from paranoia to discard closes #1995 --- Gemfile | 2 +- Gemfile.lock | 6 +++--- app/controllers/members_controller.rb | 4 ++-- app/models/comment.rb | 2 +- app/models/concerns/ownable.rb | 2 ++ app/models/garden.rb | 1 - app/models/harvest.rb | 1 - app/models/member.rb | 13 +++++++++++-- app/models/photo.rb | 1 - app/models/planting.rb | 1 - app/models/post.rb | 2 +- app/models/seed.rb | 2 +- app/views/layouts/_header.html.haml | 2 +- db/migrate/20171105011017_set_prediction_data.rb | 2 +- db/migrate/20190317023129_finished_boolean.rb | 4 ++-- db/migrate/20190326224347_add_harvests_count.rb | 2 +- .../20190720000625_notifications_to_mailboxer.rb | 4 +--- db/migrate/20190721042146_paranoia_to_discard.rb | 5 +++++ db/schema.rb | 6 +++--- 19 files changed, 36 insertions(+), 26 deletions(-) create mode 100644 db/migrate/20190721042146_paranoia_to_discard.rb diff --git a/Gemfile b/Gemfile index c151aa424..510b993f5 100644 --- a/Gemfile +++ b/Gemfile @@ -106,7 +106,7 @@ gem 'rake', '>= 10.0.0' gem "responders" # allows soft delete. Used for members. -gem "paranoia", "~> 2.2" +gem 'discard', '~> 1.0' gem 'xmlrpc' # fixes rake error - can be removed if not needed later diff --git a/Gemfile.lock b/Gemfile.lock index c62dbb628..026689bd5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -150,6 +150,8 @@ GEM responders warden (~> 1.2.3) diff-lcs (1.3) + discard (1.1.0) + activerecord (>= 4.2, < 7) docile (1.1.5) elasticsearch (6.8.0) elasticsearch-api (= 6.8.0) @@ -342,8 +344,6 @@ GEM rack orm_adapter (0.5.0) parallel (1.17.0) - paranoia (2.4.2) - activerecord (>= 4.0, < 6.1) parser (2.6.3.0) ast (~> 2.4.0) percy-capybara (4.0.1) @@ -566,6 +566,7 @@ DEPENDENCIES dalli database_cleaner devise + discard (~> 1.0) elasticsearch (< 7.0.0) factory_bot_rails faker @@ -601,7 +602,6 @@ DEPENDENCIES omniauth-facebook omniauth-flickr (>= 0.0.15) omniauth-twitter - paranoia (~> 2.2) percy-capybara (~> 4.0.0) pg (< 1.0.0) platform-api diff --git a/app/controllers/members_controller.rb b/app/controllers/members_controller.rb index d044836ed..552a71bd0 100644 --- a/app/controllers/members_controller.rb +++ b/app/controllers/members_controller.rb @@ -13,7 +13,7 @@ class MembersController < ApplicationController end def show - @member = Member.confirmed.find_by!(slug: params[:slug]) + @member = Member.confirmed.kept.find_by!(slug: params[:slug]) @twitter_auth = @member.auth('twitter') @flickr_auth = @member.auth('flickr') @facebook_auth = @member.auth('facebook') @@ -89,6 +89,6 @@ class MembersController < ApplicationController Member.recently_joined else Member.order(:login_name) - end.confirmed.paginate(page: params[:page]) + end.kept.confirmed.paginate(page: params[:page]) end end diff --git a/app/models/comment.rb b/app/models/comment.rb index 3ff8eef4f..9b0882350 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,5 +1,5 @@ class Comment < ApplicationRecord - belongs_to :author, -> { with_deleted }, class_name: 'Member', inverse_of: :comments + belongs_to :author, class_name: 'Member', inverse_of: :comments belongs_to :post scope :post_order, -> { reorder("created_at ASC") } # for display on post page diff --git a/app/models/concerns/ownable.rb b/app/models/concerns/ownable.rb index eea4c9ac7..9328743fd 100644 --- a/app/models/concerns/ownable.rb +++ b/app/models/concerns/ownable.rb @@ -4,5 +4,7 @@ module Ownable included do belongs_to :owner, class_name: 'Member', # rubocop:disable Rails/InverseOf foreign_key: 'owner_id', counter_cache: true + + default_scope { joins(:owner).merge(Member.kept) } # Ensures the owner still exists end end diff --git a/app/models/garden.rb b/app/models/garden.rb index 8eb27cc78..c16dc396c 100644 --- a/app/models/garden.rb +++ b/app/models/garden.rb @@ -16,7 +16,6 @@ class Garden < ApplicationRecord after_validation :empty_unwanted_geocodes after_save :mark_inactive_garden_plantings_as_finished - default_scope { joins(:owner) } # Ensures owner exists scope :active, -> { where(active: true) } scope :inactive, -> { where(active: false) } scope :order_by_name, -> { order(Arel.sql("lower(name) asc")) } diff --git a/app/models/harvest.rb b/app/models/harvest.rb index 6dffbca6a..8a78ad4fc 100644 --- a/app/models/harvest.rb +++ b/app/models/harvest.rb @@ -39,7 +39,6 @@ class Harvest < ApplicationRecord ## ## Scopes - default_scope { joins(:owner) } # Ensures owner exists scope :interesting, -> { has_photos.one_per_owner } scope :recent, -> { order(created_at: :desc) } scope :one_per_owner, lambda { diff --git a/app/models/member.rb b/app/models/member.rb index a8416ef2b..da510e8dd 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -1,5 +1,5 @@ class Member < ApplicationRecord - acts_as_paranoid # implements soft deletion + include Discard::Model acts_as_messageable # messages can be sent to this model before_destroy :newsletter_unsubscribe include Geocodable @@ -58,6 +58,11 @@ class Member < ApplicationRecord :recoverable, :rememberable, :trackable, :validatable, :confirmable, :lockable, :timeoutable, :omniauthable + # discarded (deleted) member cannot log in + def active_for_authentication? + super && !discarded? + end + # set up geocoding geocoded_by :location @@ -104,7 +109,11 @@ class Member < ApplicationRecord end def to_s - login_name + if discarded? + 'deleted' + else + login_name + end end def to_param diff --git a/app/models/photo.rb b/app/models/photo.rb index de44ebbbd..8ed9c2f57 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -15,7 +15,6 @@ class Photo < ApplicationRecord source_type: type end - default_scope { joins(:owner) } # Ensures the owner still exists scope :by_crop, ->(crop) { joins(:photo_associations).where(photo_associations: { crop: crop }) } scope :by_model, lambda { |model_name| joins(:photo_associations).where(photo_associations: { photographable_type: model_name.to_s }) diff --git a/app/models/planting.rb b/app/models/planting.rb index 67bdd281d..2379c06db 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -32,7 +32,6 @@ class Planting < ApplicationRecord ## ## Scopes - default_scope { joins(:owner) } # Ensures the owner still exists scope :active, -> { where('finished <> true').where('finished_at IS NULL OR finished_at < ?', Time.zone.now) } scope :interesting, -> { has_photos.one_per_owner.order(planted_at: :desc) } scope :recent, -> { order(created_at: :desc) } diff --git a/app/models/post.rb b/app/models/post.rb index 0427ada70..685ffee19 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -19,7 +19,7 @@ class Post < ApplicationRecord after_save :update_crops_posts_association after_create :send_notification - default_scope { joins(:author) } # Ensures the owner still exists + default_scope { joins(:author).merge(Member.kept) } # Ensures the owner still exists # # Validations diff --git a/app/models/seed.rb b/app/models/seed.rb index b335127c0..8e0544b52 100644 --- a/app/models/seed.rb +++ b/app/models/seed.rb @@ -48,7 +48,7 @@ class Seed < ApplicationRecord # # Scopes - default_scope { joins(:owner) } # Ensure owner exists + default_scope { joins(:owner).merge(Member.kept) } # Ensure owner exists scope :tradable, -> { where.not(tradable_to: 'nowhere') } scope :interesting, -> { tradable.has_location } scope :has_location, -> { joins(:owner).where.not("members.location": nil) } diff --git a/app/views/layouts/_header.html.haml b/app/views/layouts/_header.html.haml index 5fbeab4c5..60ae199b5 100644 --- a/app/views/layouts/_header.html.haml +++ b/app/views/layouts/_header.html.haml @@ -32,7 +32,7 @@ = t('.your_stuff') %span.badge.badge-info= current_member.notifications.unread_count - else - = t('.current_memberlogin_name', current_memberlogin_name: current_member.login_name) + = t('.current_memberlogin_name', current_memberlogin_name: current_member) .dropdown-menu{"aria-labelledby" => "navbarDropdown"} = link_to member_path(current_member), class: 'dropdown-item' do = t('.profile') diff --git a/db/migrate/20171105011017_set_prediction_data.rb b/db/migrate/20171105011017_set_prediction_data.rb index c1931b2b6..8dfd91b4f 100644 --- a/db/migrate/20171105011017_set_prediction_data.rb +++ b/db/migrate/20171105011017_set_prediction_data.rb @@ -1,7 +1,7 @@ class SetPredictionData < ActiveRecord::Migration[4.2] def up say "Updating all plantings time to first harvest" - Planting.all.each(&:update_harvest_days!) + Planting.unscoped.all.each(&:update_harvest_days!) say "Updating crop median time to first harvest, and lifespan" Crop.all.each do |crop| crop.update_lifespan_medians diff --git a/db/migrate/20190317023129_finished_boolean.rb b/db/migrate/20190317023129_finished_boolean.rb index 5f8601fca..ac6524316 100644 --- a/db/migrate/20190317023129_finished_boolean.rb +++ b/db/migrate/20190317023129_finished_boolean.rb @@ -1,7 +1,7 @@ class FinishedBoolean < ActiveRecord::Migration[5.2] def change - Planting.where('finished_at < now()').update_all(finished: true) - Planting.where(finished: nil).update_all(finished: false) + Planting.unscoped.where('finished_at < now()').update_all(finished: true) + Planting.unscoped.where(finished: nil).update_all(finished: false) change_column_null :plantings, :finished, false change_column_default :plantings, :finished, from: nil, to: false end diff --git a/db/migrate/20190326224347_add_harvests_count.rb b/db/migrate/20190326224347_add_harvests_count.rb index 8b2396713..9557ffdae 100644 --- a/db/migrate/20190326224347_add_harvests_count.rb +++ b/db/migrate/20190326224347_add_harvests_count.rb @@ -2,7 +2,7 @@ class AddHarvestsCount < ActiveRecord::Migration[5.2] def change add_column :plantings, :harvests_count, :integer, default: 0 Planting.reset_column_information - Planting.pluck(:id).each do |planting_id| + Planting.unscoped.pluck(:id).each do |planting_id| Planting.reset_counters(planting_id, :harvests) end end diff --git a/db/migrate/20190720000625_notifications_to_mailboxer.rb b/db/migrate/20190720000625_notifications_to_mailboxer.rb index 6f9f5ef21..9ea60b7d1 100644 --- a/db/migrate/20190720000625_notifications_to_mailboxer.rb +++ b/db/migrate/20190720000625_notifications_to_mailboxer.rb @@ -1,9 +1,7 @@ class NotificationsToMailboxer < ActiveRecord::Migration[5.2] def change Notification.all.each do |n| - recipient = Member.with_deleted.find(n.recipient_id) - sender = Member.with_deleted.find(n.sender_id) - sender.send_message(recipient, n.body, n.subject) + n.sender.send_message(n.recipient, n.body, n.subject) end end end diff --git a/db/migrate/20190721042146_paranoia_to_discard.rb b/db/migrate/20190721042146_paranoia_to_discard.rb new file mode 100644 index 000000000..4b8803360 --- /dev/null +++ b/db/migrate/20190721042146_paranoia_to_discard.rb @@ -0,0 +1,5 @@ +class ParanoiaToDiscard < ActiveRecord::Migration[5.2] + def change + rename_column :members, :deleted_at, :discarded_at + end +end diff --git a/db/schema.rb b/db/schema.rb index a7cf22479..f9ac74a45 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: 2019_07_20_000625) do +ActiveRecord::Schema.define(version: 2019_07_21_042146) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -361,11 +361,11 @@ ActiveRecord::Schema.define(version: 2019_07_20_000625) do t.integer "gardens_count" t.integer "harvests_count" t.integer "seeds_count" - t.datetime "deleted_at" + t.datetime "discarded_at" t.integer "photos_count" t.integer "forums_count" t.index ["confirmation_token"], name: "index_members_on_confirmation_token", unique: true - t.index ["deleted_at"], name: "index_members_on_deleted_at" + t.index ["discarded_at"], name: "index_members_on_discarded_at" t.index ["email"], name: "index_members_on_email", unique: true t.index ["reset_password_token"], name: "index_members_on_reset_password_token", unique: true t.index ["slug"], name: "index_members_on_slug", unique: true From e77e806efc08b2e746bce37e995f695f2684396a Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 16:59:26 +1200 Subject: [PATCH 032/151] turn members/tiny into a "chip" --- app/views/conversations/index.haml | 7 ++----- app/views/members/_tiny.haml | 4 ++-- app/views/plantings/_card.html.haml | 1 - 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index 949ca8bba..4419f5b07 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -32,11 +32,8 @@ %tr{class: conversation.receipts_for(current_member).last.is_unread? ? 'active': ''} %td - -# - conversation.participants.each do |member| - -# = render 'members/tiny', member: member - -# - unless member == current_member - -# .float-left= render 'members/tiny', member: member - -# = link_to member.login_name, member + - conversation.participants.each do |member| + = render 'members/tiny', member: member %td %h3.h3-responsive = link_to conversation_path(conversation) do diff --git a/app/views/members/_tiny.haml b/app/views/members/_tiny.haml index 1479f69da..dcd4e9987 100644 --- a/app/views/members/_tiny.haml +++ b/app/views/members/_tiny.haml @@ -1,7 +1,7 @@ .member-chip - - if member.nil? + - if member.discarded? = icon 'fas', 'user-times' - deleted + = member - else = link_to member do = image_tag(avatar_uri(member, 100), alt: '', height: 50, width: 50) diff --git a/app/views/plantings/_card.html.haml b/app/views/plantings/_card.html.haml index 23cee3cec..c6695f3e0 100644 --- a/app/views/plantings/_card.html.haml +++ b/app/views/plantings/_card.html.haml @@ -21,5 +21,4 @@ .card-body.text-center %h4.card-title= link_to planting.crop, planting .text-center= render 'plantings/badges', planting: planting - .card-footer = render 'plantings/progress', planting: planting \ No newline at end of file From f9f1846bce0b6d00c23cce8c8c96c3e02aee7940 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 16:59:59 +1200 Subject: [PATCH 033/151] Using chip on plantings cards (made room by shrinking the date) --- app/views/plantings/_progress.html.haml | 4 +--- app/views/seeds/_card.html.haml | 15 ++++++++------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/app/views/plantings/_progress.html.haml b/app/views/plantings/_progress.html.haml index 6577f2403..f5527410b 100644 --- a/app/views/plantings/_progress.html.haml +++ b/app/views/plantings/_progress.html.haml @@ -1,5 +1,3 @@ -- if planting.planted_at.present? - planted #{planting.planted_at} - if planting.percentage_grown.present? .progress .progress-bar.bg-success{"aria-valuemax" => "100", "aria-valuemin" => "0", "aria-valuenow" => planting.percentage_grown, :role => "progressbar", :style => "width: #{planting.percentage_grown}%; height: 25px"} @@ -7,4 +5,4 @@ .float-left #{sprintf '%.0f', planting.percentage_grown}% - unless planting.finish_predicted_at.blank? - .float-right= planting.finish_predicted_at + .float-right= planting.finish_predicted_at.strftime(Date::DATE_FORMATS[:ymd]) diff --git a/app/views/seeds/_card.html.haml b/app/views/seeds/_card.html.haml index e46e5da8b..cd7db9099 100644 --- a/app/views/seeds/_card.html.haml +++ b/app/views/seeds/_card.html.haml @@ -2,11 +2,12 @@ = link_to seed do = image_tag(seed_image_path(seed, full_size: true), alt: seed, class: 'img-card') .card-body - %h5= link_to seed, seed + .card-title= link_to seed.crop, seed + .card-footer + = render 'members/tiny', member: seed.owner - if seed.tradable? - %span.badge.badge-pill.badge-secondary Will trade #{seed.tradable_to} - = link_to seed.owner do - .card-footer - %span.badge.badge-pill.badge-secondary - = truncate(seed.owner.location, length: 20, separator: ' ', omission: '... ') - = render 'members/tiny', member: seed.owner \ No newline at end of file + %span.badge.badge-pill.badge-info + = icon 'fas', 'map' + Will trade #{seed.tradable_to} + %span.badge.badge-pill.badge-secondary + = truncate(seed.owner.location, length: 30, separator: ' ', omission: '... ') \ No newline at end of file From 39dc878ea73fe8b37d8843e1907441573fcc9bc0 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 17:15:21 +1200 Subject: [PATCH 034/151] Tidy up styling of conversations#index --- app/views/conversations/index.haml | 65 ++++++++++++++++-------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index 4419f5b07..1c9eb1c3c 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -20,34 +20,37 @@ %span.badge.badge-primary.badge-pill= item_count .col-10 - %table.table - %thead.black.white-text - %tr - %th{scope: "col"} Participants - %th{scope: "col"} Subject - %th{scope: "col"} Sent at - %th{scope: "col"} - %tbody - - @conversations.each do |conversation| - - %tr{class: conversation.receipts_for(current_member).last.is_unread? ? 'active': ''} - %td - - conversation.participants.each do |member| - = render 'members/tiny', member: member - %td - %h3.h3-responsive - = link_to conversation_path(conversation) do - - if conversation.receipts_for(current_member).last.is_unread? - = icon 'far', 'envelope' - - else - = icon 'far', 'envelope-open' - =conversation.subject - %td - =conversation.updated_at - .text-muted (#{time_ago_in_words conversation.updated_at} ago) - %td - = link_to conversation_path(conversation), method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger btn-xs' do - = delete_icon - = t('buttons.delete') - - unless @conversations.empty? - = paginate @conversations \ No newline at end of file + - unless @conversations.empty? + = paginate @conversations + .table-responsive.text-nowrap + %table.table.table-hover + %thead.black.white-text + %tr + %th{scope: "col"} Participants + %th{scope: "col"} Subject + %th{scope: "col"} Sent at + %th{scope: "col"} + %tbody + - @conversations.each do |conversation| + %tr{class: conversation.receipts_for(current_member).last.is_unread? ? 'active': ''} + %td + - conversation.participants.each do |member| + = render 'members/tiny', member: member + %td + %h3.h3-responsive + = link_to conversation_path(conversation) do + - if conversation.receipts_for(current_member).last.is_unread? + = icon 'far', 'envelope' + - else + = icon 'far', 'envelope-open' + =conversation.subject + %td + =conversation.updated_at + .text-muted (#{time_ago_in_words conversation.updated_at} ago) + %td + = link_to conversation_path(conversation), method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger btn-xs' do + = delete_icon + .sr-only= t('buttons.delete') + - unless @conversations.empty? + = paginate @conversations + \ No newline at end of file From c4806fddf33e298a7d13c4fb66c634c8ef11b22f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 17:21:36 +1200 Subject: [PATCH 035/151] re-coloured the memberships to green --- app/assets/stylesheets/_members.scss | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/app/assets/stylesheets/_members.scss b/app/assets/stylesheets/_members.scss index f71d7697e..ca42759d9 100644 --- a/app/assets/stylesheets/_members.scss +++ b/app/assets/stylesheets/_members.scss @@ -24,13 +24,15 @@ font-size: 16px; line-height: 50px; border-radius: 25px; - background-color: #f1f1f1; -} - -.member-chip img { - float: left; - margin: 0 10px 0 -25px; - height: 50px; - width: 50px; - border-radius: 50%; + background-color: lighten($green, 30%); + a { + color: $black; + } + img { + float: left; + margin: 0 10px 0 -25px; + height: 50px; + width: 50px; + border-radius: 50%; + } } \ No newline at end of file From eda36397085a932d2d315766072024d6c8caaba8 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 17:23:28 +1200 Subject: [PATCH 036/151] Discard members on ban --- app/controllers/admin/members_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/admin/members_controller.rb b/app/controllers/admin/members_controller.rb index ca35129b3..11b3c0d9b 100644 --- a/app/controllers/admin/members_controller.rb +++ b/app/controllers/admin/members_controller.rb @@ -8,7 +8,7 @@ module Admin def destroy @member = Member.find_by!(slug: params[:slug]) - @member.destroy + @member.discard redirect_to admin_members_path end From 6144a7c06573f1f89c8a805bf1f34f03ab8bc7fb Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 17:26:45 +1200 Subject: [PATCH 037/151] tidy display of discard member on admin page --- app/views/admin/members/index.html.haml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/views/admin/members/index.html.haml b/app/views/admin/members/index.html.haml index 522c659c6..7bf1e7764 100644 --- a/app/views/admin/members/index.html.haml +++ b/app/views/admin/members/index.html.haml @@ -11,10 +11,12 @@ - @members.each do |member| %tr %td= render 'members/tiny', member: member - %td - = link_to member, member + %td= member.login_name %td= member.email %td = link_to admin_member_path(member), method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-light text-danger' do = icon 'fas', 'ban' Ban member +.pagination + = page_entries_info @members + = will_paginate @members From d382f84f9b2ff4ae0212148ecf4076835d4a85a1 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 17:28:04 +1200 Subject: [PATCH 038/151] Remove notifications code --- app/controllers/notifications_controller.rb | 69 ------------------- app/views/notifications/_form.html.haml | 26 ------- .../notifications/_notification.html.haml | 13 ---- app/views/notifications/index.html.haml | 38 ---------- app/views/notifications/new.html.haml | 6 -- app/views/notifications/reply.html.haml | 8 --- app/views/notifications/show.html.haml | 24 ------- .../notifications/index.html.haml_spec.rb | 46 ------------- .../views/notifications/new.html.haml_spec.rb | 50 -------------- .../notifications/show.html.haml_spec.rb | 25 ------- 10 files changed, 305 deletions(-) delete mode 100644 app/controllers/notifications_controller.rb delete mode 100644 app/views/notifications/_form.html.haml delete mode 100644 app/views/notifications/_notification.html.haml delete mode 100644 app/views/notifications/index.html.haml delete mode 100644 app/views/notifications/new.html.haml delete mode 100644 app/views/notifications/reply.html.haml delete mode 100644 app/views/notifications/show.html.haml delete mode 100644 spec/views/notifications/index.html.haml_spec.rb delete mode 100644 spec/views/notifications/new.html.haml_spec.rb delete mode 100644 spec/views/notifications/show.html.haml_spec.rb diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb deleted file mode 100644 index ce4edc5cb..000000000 --- a/app/controllers/notifications_controller.rb +++ /dev/null @@ -1,69 +0,0 @@ -class NotificationsController < ApplicationController - include NotificationsHelper - before_action :authenticate_member! - load_and_authorize_resource - respond_to :html - - # GET /notifications - def index - # @notifications = Notification.by_recipient(current_member).order(created_at: :desc).paginate(page: params[:page], per_page: 30) - end - - # GET /notifications/1 - def show - @notification.read = true - @notification.save - @reply_link = reply_link(@notification) - end - - # GET /notifications/new - - def new - @notification = Notification.new - @recipient = Member.find_by(id: params[:recipient_id]) - @subject = params[:subject] || "" - end - - # GET /notifications/1/reply - def reply - @notification = Notification.new - @sender_notification = Notification.find_by!(id: params[:notification_id], recipient: current_member) - @sender_notification.read = true - @sender_notification.save - @recipient = @sender_notification.sender - @subject = if @sender_notification.subject.start_with? 'Re: ' - @sender_notification.subject - else - "Re: #{@sender_notification.subject}" - end - end - - # DELETE /notifications/1 - def destroy - @notification.destroy - redirect_to notifications_url - end - - # POST /notifications - def create - # params[:notification][:sender_id] = current_member.id - @notification = Notification.new(notification_params) - @notification.sender = current_member - @notification.recipient = Member.find_by(id: notification_params[:recipient_id]) - @body = notification_params[:body] - @subject = notification_params[:subject] - - if @notification.save - @notification.sender.send_message(@notification.recipient, @notification.body, @notification.subject) - redirect_to notifications_path, notice: 'Message was successfully sent.' - else - render action: "new" - end - end - - private - - def notification_params - params.require(:notification).permit(:sender_id, :recipient_id, :subject, :body, :post_id, :read) - end -end diff --git a/app/views/notifications/_form.html.haml b/app/views/notifications/_form.html.haml deleted file mode 100644 index d613007a1..000000000 --- a/app/views/notifications/_form.html.haml +++ /dev/null @@ -1,26 +0,0 @@ -= bootstrap_form_for @notification do |f| - .card - .card-body - - if @notification.errors.any? - #error_explanation - %h2 - = pluralize(@notification.errors.size, "error") - prohibited this message from being sent: - %ul - - @notification.errors.full_messages.each do |msg| - %li= msg - - .field - = f.hidden_field :recipient_id, value: @recipient.id - - %p - To - = link_to @recipient, @recipient - = render 'members/tiny', member: @recipient - = f.text_field :subject, value: @subject, class: 'form-control', maxlength: 255 - = f.text_area :body, rows: 12, label: "Type your message here" - %span.help-block= render partial: "shared/markdown_help" - .card-footer - - = link_to 'cancel', notifications_path, class: 'btn' - .float-right= f.submit "Send", class: 'btn btn-primary' diff --git a/app/views/notifications/_notification.html.haml b/app/views/notifications/_notification.html.haml deleted file mode 100644 index 881b93c50..000000000 --- a/app/views/notifications/_notification.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -%p.text-muted - From - = link_to notification.sender, notification.sender - on - = notification.created_at - - - if notification.post_id - in response to: - = link_to notification.post.subject, notification.post - -.well - :growstuff_markdown - #{ strip_tags(notification.body) } diff --git a/app/views/notifications/index.html.haml b/app/views/notifications/index.html.haml deleted file mode 100644 index d6ac4b5b3..000000000 --- a/app/views/notifications/index.html.haml +++ /dev/null @@ -1,38 +0,0 @@ -- content_for :title, "Inbox" -- content_for :breadcrumbs do - %li.breadcrumb-item.active= link_to 'Messages', notifications_path - -- if @notifications.empty? - .alert.alert-success{role: "alert"} You have no messages. -- else - = paginate @notifications - - - @notifications.each do |n| - .card.message - .card-body - .row - .col-6.col-md-9 - %h3= link_to n.subject, notification_path(n) - %p - - if n.read - = icon 'far', 'envelope-open' - - else - = icon 'far', 'envelope' - %strong unread - = n.created_at - .col-6.col-md-3.text-right - - if n.sender.present? - = link_to n.sender do - %h3 - = render 'members/tiny', member: n.sender - = n.sender - = render 'members/follow_buttons', member: n.sender - - else - Member deleted - .card-footer - = link_to 'Read', n, class: 'btn btn-primary' - = link_to 'Reply', reply_link(n), class: 'btn btn-secondary' - = link_to n, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger btn-xs' do - = delete_icon - = t('buttons.delete') - = paginate @notifications \ No newline at end of file diff --git a/app/views/notifications/new.html.haml b/app/views/notifications/new.html.haml deleted file mode 100644 index 721dcca7d..000000000 --- a/app/views/notifications/new.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -= content_for :title, "Send a message to #{@recipient}" -- content_for :breadcrumbs do - %li.breadcrumb-item= link_to 'Messages', notifications_path - -= render 'form' - diff --git a/app/views/notifications/reply.html.haml b/app/views/notifications/reply.html.haml deleted file mode 100644 index 54230dff4..000000000 --- a/app/views/notifications/reply.html.haml +++ /dev/null @@ -1,8 +0,0 @@ -= content_for :title, "Send a message to #{@recipient}" -- content_for :breadcrumbs do - %li.breadcrumb-item= link_to 'Messages', notifications_path - -.card - .card-body= render @sender_notification -= render 'form' - diff --git a/app/views/notifications/show.html.haml b/app/views/notifications/show.html.haml deleted file mode 100644 index 84a8a29f2..000000000 --- a/app/views/notifications/show.html.haml +++ /dev/null @@ -1,24 +0,0 @@ -= content_for :title, @notification.subject - -- content_for :breadcrumbs do - %li.breadcrumb-item= link_to 'Messages', notifications_path - -.card - .card-header - .card-title= @notification.subject - .float-right - - if @notification.sender.present? - = link_to @notification.sender do - = @notification.sender - = render 'members/tiny', member: @notification.sender - - else - Member deleted - - .card-body - = render @notification - - .card-footer - = link_to 'Reply', @reply_link, class: 'btn btn-primary' - = link_to @notification, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger' do - = delete_icon - = t('buttons.delete') diff --git a/spec/views/notifications/index.html.haml_spec.rb b/spec/views/notifications/index.html.haml_spec.rb deleted file mode 100644 index eece9f23e..000000000 --- a/spec/views/notifications/index.html.haml_spec.rb +++ /dev/null @@ -1,46 +0,0 @@ -require 'rails_helper' - -describe "notifications/index" do - before do - @member = FactoryBot.create(:member) - controller.stub(:current_user) { @member } - end - - context "ordinary notifications" do - before do - @notification = FactoryBot.create(:notification, sender: @member, - recipient: @member) - assign(:notifications, Kaminari.paginate_array([@notification, @notification]).page(1)) - render - end - - it "renders a list of notifications" do - expect(rendered).to have_content @notification.sender.to_s, count: 2 - expect(rendered).to have_content @notification.subject, count: 2 - end - - it "links to sender's profile" do - assert_select "a", href: member_path(@notification.sender) - end - end - - context "no subject" do - it "shows (no subject)" do - @notification = FactoryBot.create(:notification, - sender: @member, recipient: @member, subject: nil) - assign(:notifications, Kaminari.paginate_array([@notification]).page(1)) - render - rendered.should have_content "(no subject)" - end - end - - context "whitespace-only subject" do - it "shows (no subject)" do - @notification = FactoryBot.create(:notification, - sender: @member, recipient: @member, subject: " ") - assign(:notifications, Kaminari.paginate_array([@notification]).page(1)) - render - rendered.should have_content "(no subject)" - end - end -end diff --git a/spec/views/notifications/new.html.haml_spec.rb b/spec/views/notifications/new.html.haml_spec.rb deleted file mode 100644 index 242f433e3..000000000 --- a/spec/views/notifications/new.html.haml_spec.rb +++ /dev/null @@ -1,50 +0,0 @@ -require 'rails_helper' - -describe "notifications/new" do - before do - @recipient = FactoryBot.create(:member) - @sender = FactoryBot.create(:member) - assign(:notification, FactoryBot.create(:notification, recipient_id: @recipient.id, sender_id: @sender.id)) - sign_in @sender - controller.stub(:current_user) { @sender } - end - - it "renders new message form" do - render - assert_select "form", action: notifications_path, method: "notification" do - assert_select "input#notification_subject", name: "notification[subject]" - assert_select "textarea#notification_body", name: "notification[body]" - end - end - - it "tells you who the recipient is" do - render - rendered.should have_content @recipient.login_name - end - - it "puts the recipient in a hidden field" do - render - assert_select "input#notification_recipient_id[type=hidden]", name: "notification[recipient_id]" - end - - it "fills in the subject if provided" do - assign(:subject, 'Foo') - render - assert_select "input#notification_subject", value: "Foo" - end - - it "leaves the subject empty if not provided" do - render - assert_select "input#notification_subject", value: "" - end - - it "Tells you to write your message here" do - render - rendered.should have_content "Type your message here" - end - - it 'shows markdown help' do - render - rendered.should have_content 'Markdown' - end -end diff --git a/spec/views/notifications/show.html.haml_spec.rb b/spec/views/notifications/show.html.haml_spec.rb deleted file mode 100644 index 9f5087f41..000000000 --- a/spec/views/notifications/show.html.haml_spec.rb +++ /dev/null @@ -1,25 +0,0 @@ -require 'rails_helper' - -describe "notifications/show" do - before do - @member = FactoryBot.create(:member) - @notification = FactoryBot.create(:notification, recipient: @member) - assign(:notification, @notification) - @reply_link = assign(:reply_link, new_notification_path) - controller.stub(:current_user) { @member } - render - end - - it "renders attributes" do - rendered.should have_content @notification.sender.to_s - rendered.should have_content @notification.body.to_s - end - - it "includes a delete button" do - assert_select "a", "Delete" - end - - it "includes a reply button" do - assert_select "a", { href: @reply_link }, "Reply" - end -end From 754da0777a109388841cf8fe9cf50ca13215b78a Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 19:13:51 +1200 Subject: [PATCH 039/151] preserve which box we're looking at while deleting messages --- app/controllers/conversations_controller.rb | 2 +- app/views/conversations/index.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index a0ec258c0..3b998c1dc 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -42,7 +42,7 @@ class ConversationsController < ApplicationController def destroy @conversation = Mailboxer::Conversation.find(params[:id]) @conversation.move_to_trash(current_member) - redirect_to conversations_path + redirect_to conversations_path(box: params[:box]) end private diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index 1c9eb1c3c..7eec431b6 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -48,7 +48,7 @@ =conversation.updated_at .text-muted (#{time_ago_in_words conversation.updated_at} ago) %td - = link_to conversation_path(conversation), method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger btn-xs' do + = link_to conversation_path(conversation, box: @box), method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger btn-xs' do = delete_icon .sr-only= t('buttons.delete') - unless @conversations.empty? From bcd95aab4a3172dd96d5dfeba7286d4883ccf5a8 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 19:14:02 +1200 Subject: [PATCH 040/151] removed unused partial --- app/views/members/_actions.html.haml | 15 --------------- app/views/members/show.html.haml | 3 --- 2 files changed, 18 deletions(-) delete mode 100644 app/views/members/_actions.html.haml diff --git a/app/views/members/_actions.html.haml b/app/views/members/_actions.html.haml deleted file mode 100644 index 9e69566d0..000000000 --- a/app/views/members/_actions.html.haml +++ /dev/null @@ -1,15 +0,0 @@ --# %p.btn-group --# - if can? :update, @member --# = link_to edit_member_registration_path, class: 'btn btn-default text-right' do --# = edit_icon --# = t('members.edit_profile') - --# - if can?(:create, Notification) && current_member != @member --# = link_to 'Send message', new_notification_path(recipient_id: @member.id), class: 'btn btn-default' - --# - if current_member && current_member != @member # must be logged in, can't follow yourself --# - follow = current_member.get_follow(@member) --# - if !follow && can?(:create, Follow) # not already following --# = link_to 'Follow', follows_path(followed: @member), method: :post, class: 'btn btn-default text-right' --# - if follow && can?(:destroy, follow) # already following --# = link_to 'Unfollow', follow_path(follow), method: :delete, class: 'btn btn-default text-right' diff --git a/app/views/members/show.html.haml b/app/views/members/show.html.haml index 772b95dbd..5e1192c31 100644 --- a/app/views/members/show.html.haml +++ b/app/views/members/show.html.haml @@ -7,9 +7,6 @@ = tag("meta", property: "og:url", content: request.original_url) = tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME']) - -= render 'members/actions', member: @member - - content_for :member_rss_login_name, @member.login_name - content_for :member_rss_slug, @member.slug From 36c4c1e97121c219738e398b0f3354bfc9113fce Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 19:14:22 +1200 Subject: [PATCH 041/151] use message path instead of notifications --- app/views/seeds/show.html.haml | 2 +- spec/features/members/profile_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/seeds/show.html.haml b/app/views/seeds/show.html.haml index 4e833f02b..07aec7b53 100644 --- a/app/views/seeds/show.html.haml +++ b/app/views/seeds/show.html.haml @@ -68,7 +68,7 @@ - if current_member - if @seed.tradable? && current_member != @seed.owner %p= link_to "Request seeds", - new_notification_path(recipient_id: @seed.owner.id, + new_message_path(recipient_id: @seed.owner.id, subject: "Interested in your #{@seed.crop} seeds"), class: 'btn btn-primary' - else diff --git a/spec/features/members/profile_spec.rb b/spec/features/members/profile_spec.rb index 6b6ab0f94..f6f96ce30 100644 --- a/spec/features/members/profile_spec.rb +++ b/spec/features/members/profile_spec.rb @@ -179,7 +179,7 @@ describe "member profile", js: true do before { visit member_path(other_member) } it "has a private message button" do - expect(page).to have_link "Send message", href: new_notification_path(recipient_id: other_member.id) + expect(page).to have_link "Send message", href: new_message_path(recipient_id: other_member.id) end it { expect(page).not_to have_link "Edit profile", href: edit_member_registration_path } end From 6485bde8e74bae101e9f311915a96e518a831355 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 19:15:45 +1200 Subject: [PATCH 042/151] show harvest owner --- app/views/harvests/show.html.haml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/views/harvests/show.html.haml b/app/views/harvests/show.html.haml index 5909f1d55..86efb8bba 100644 --- a/app/views/harvests/show.html.haml +++ b/app/views/harvests/show.html.haml @@ -37,7 +37,11 @@ = display_quantity(@harvest) - .col-md-4= render @harvest.crop + .col-md-4 + .card + .card-body= render 'harvests/owner', harvest: @harvest + + = render @harvest.crop - if @harvest.description.present? %h2 Notes From e309548d20608e653f0fe227da8a73cba3d71db1 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 19:16:07 +1200 Subject: [PATCH 043/151] mark required fields on a message --- app/views/messages/_form.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/messages/_form.haml b/app/views/messages/_form.haml index e32c879b0..bb6d05f4d 100644 --- a/app/views/messages/_form.haml +++ b/app/views/messages/_form.haml @@ -25,11 +25,11 @@ = link_to @recipient, @recipient = render 'members/tiny', member: @recipient = f.hidden_field :recipient_id, value: @recipient.id - = f.text_field :subject, value: @subject, class: 'form-control', maxlength: 255 + = f.text_field :subject, value: @subject, class: 'form-control', maxlength: 255, required: true - else TODO - add recipient field - = f.text_area :body, rows: 12, label: "Type your message here" + = f.text_area :body, rows: 12, label: "Type your message here", required: true %span.help-block= render partial: "shared/markdown_help" .card-footer = link_to 'cancel', conversations_path, class: 'btn' From 3f84f5abe1b00a14d068f434850569448da7eb4d Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 19:16:22 +1200 Subject: [PATCH 044/151] harvest owner info --- app/views/harvests/_owner.html.haml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 app/views/harvests/_owner.html.haml diff --git a/app/views/harvests/_owner.html.haml b/app/views/harvests/_owner.html.haml new file mode 100644 index 000000000..f51da33f8 --- /dev/null +++ b/app/views/harvests/_owner.html.haml @@ -0,0 +1,18 @@ +.well + .row + .col-md-6 + %h4 + Harvested by + = link_to harvest.owner, harvest.owner + = link_to "view all #{harvest.owner}'s harvests", member_gardens_path(harvest.owner) + + - if harvest.planting.present? + %p + Harvested from + = link_to harvest.planting, harvest.planting + - if harvest.owner.location + %p + %small + View other harvests, members and more near + = link_to harvest.owner.location, place_path(harvest.owner.location, anchor: "harvests") + .col-md-6= render "members/avatar", member: harvest.owner \ No newline at end of file From 965c9af15aa314a3b0a1437eb63052105cbd2a8b Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 19:18:13 +1200 Subject: [PATCH 045/151] Sort scss lines --- app/assets/stylesheets/_members.scss | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/assets/stylesheets/_members.scss b/app/assets/stylesheets/_members.scss index ca42759d9..b0fa67fae 100644 --- a/app/assets/stylesheets/_members.scss +++ b/app/assets/stylesheets/_members.scss @@ -18,21 +18,21 @@ .member-chip { - display: inline-block; - padding: 0 25px; - height: 50px; - font-size: 16px; - line-height: 50px; - border-radius: 25px; background-color: lighten($green, 30%); + border-radius: 25px; + display: inline-block; + font-size: 16px; + height: 50px; + line-height: 50px; + padding: 0 25px; a { color: $black; } img { - float: left; - margin: 0 10px 0 -25px; - height: 50px; - width: 50px; border-radius: 50%; + float: left; + height: 50px; + margin: 0 10px 0 -25px; + width: 50px; } } \ No newline at end of file From 733a8642dd2b5e9105c25786abeae2f4d6132cb7 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 19:19:14 +1200 Subject: [PATCH 046/151] rubocop lint --- app/controllers/conversations_controller.rb | 36 ++++++++++----------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index 3b998c1dc..d3d6d43f5 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -23,20 +23,20 @@ class ConversationsController < ApplicationController end def update - # @conversation.untrash(@actor) if params[:untrash].present? + # @conversation.untrash(@actor) if params[:untrash].present? - # if params[:reply_all].present? - # last_receipt = mailbox.receipts_for(@conversation).last - # @receipt = @actor.reply_to_all(last_receipt, params[:body]) - # end + # if params[:reply_all].present? + # last_receipt = mailbox.receipts_for(@conversation).last + # @receipt = @actor.reply_to_all(last_receipt, params[:body]) + # end - # @receipts = if box.eql? 'trash' - # mailbox.receipts_for(@conversation).trash - # else - # mailbox.receipts_for(@conversation).not_trash - # end - # redirect_to action: :show - # @receipts.mark_as_read + # @receipts = if box.eql? 'trash' + # mailbox.receipts_for(@conversation).trash + # else + # mailbox.receipts_for(@conversation).not_trash + # end + # redirect_to action: :show + # @receipts.mark_as_read end def destroy @@ -53,14 +53,14 @@ class ConversationsController < ApplicationController def set_box @boxes = { - 'inbox'=> mailbox.inbox.size, - 'sent'=> mailbox.sentbox.size, - 'trash'=> mailbox.trash.size + 'inbox' => mailbox.inbox.size, + 'sent' => mailbox.sentbox.size, + 'trash' => mailbox.trash.size } @box = if params[:box].blank? || !@boxes.keys.include?(params[:box]) - 'inbox' - else - params[:box] + 'inbox' + else + params[:box] end end From 2b9538c407008ee9e73382b84ab571ddb934a08d Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 19:21:13 +1200 Subject: [PATCH 047/151] Use a guard clause --- app/controllers/messages_controller.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index cf1acf321..fb69545ad 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -16,10 +16,9 @@ class MessagesController < ApplicationController end def new - if params[:recipient_id].present? - @recipient = Member.find_by(id: params[:recipient_id]) - return if @recipient.nil? - end + return unless params[:recipient_id].present? + @recipient = Member.find_by(id: params[:recipient_id]) + return if @recipient.nil? end def create From 6f2e27952cda62d3f8fa225ae49850442fa45bc6 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 19:21:34 +1200 Subject: [PATCH 048/151] Remove unused methods --- app/controllers/messages_controller.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index fb69545ad..fb7475f05 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -35,10 +35,6 @@ class MessagesController < ApplicationController end end - def update; end - - def destroy; end - private def current_subject From 0ac243e129e350a20efd92e5dac37c5bb380dea1 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 19:21:55 +1200 Subject: [PATCH 049/151] Remove unused methods --- app/controllers/messages_controller.rb | 9 --------- 1 file changed, 9 deletions(-) diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index fb7475f05..0cd78db2e 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -34,13 +34,4 @@ class MessagesController < ApplicationController redirect_to conversations_path(box: 'sentbox') end end - - private - - def current_subject - @current_subject ||= - # current_subject_from_params || - # current_subject_from_session || - current_member - end end From 6b501f13eebe368e081e8f5a33c6985b7848190f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 19:22:25 +1200 Subject: [PATCH 050/151] Fixed double negative --- app/controllers/messages_controller.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index 0cd78db2e..21bb4d0b2 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -16,7 +16,8 @@ class MessagesController < ApplicationController end def new - return unless params[:recipient_id].present? + return if params[:recipient_id].blank? + @recipient = Member.find_by(id: params[:recipient_id]) return if @recipient.nil? end From a9b8003ff30a192b305330dadb157b338ef68d89 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 19:23:33 +1200 Subject: [PATCH 051/151] DRY --- app/controllers/conversations_controller.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index d3d6d43f5..43d989ca6 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -6,12 +6,12 @@ class ConversationsController < ApplicationController def index @conversations = if @box.eql? "inbox" - mailbox.inbox.paginate(page: params[:page]) + mailbox.inbox elsif @box.eql? "sent" - mailbox.sentbox.paginate(page: params[:page]) + mailbox.sentbox else - mailbox.trash.paginate(page: params[:page]) - end + mailbox.trash + end.paginate(page: params[:page]) respond_with @conversations end From bcbb020fde2f74197644a298e9ee6cb12386450e Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 19:27:53 +1200 Subject: [PATCH 052/151] newline at end of file --- app/assets/stylesheets/_members.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/_members.scss b/app/assets/stylesheets/_members.scss index b0fa67fae..9db058fac 100644 --- a/app/assets/stylesheets/_members.scss +++ b/app/assets/stylesheets/_members.scss @@ -35,4 +35,4 @@ margin: 0 10px 0 -25px; width: 50px; } -} \ No newline at end of file +} From 3db63aeabf547b84d8b5dedbedd2a77bce801793 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 20:05:06 +1200 Subject: [PATCH 053/151] untrash a message --- app/controllers/conversations_controller.rb | 16 ++-------------- app/views/conversations/index.haml | 11 ++++++++--- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index 43d989ca6..4744a2abc 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -23,20 +23,8 @@ class ConversationsController < ApplicationController end def update - # @conversation.untrash(@actor) if params[:untrash].present? - - # if params[:reply_all].present? - # last_receipt = mailbox.receipts_for(@conversation).last - # @receipt = @actor.reply_to_all(last_receipt, params[:body]) - # end - - # @receipts = if box.eql? 'trash' - # mailbox.receipts_for(@conversation).trash - # else - # mailbox.receipts_for(@conversation).not_trash - # end - # redirect_to action: :show - # @receipts.mark_as_read + @conversation.untrash(current_member) + redirect_to conversations_path(box: params[:box]) end def destroy diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index 7eec431b6..97f83c6d6 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -48,9 +48,14 @@ =conversation.updated_at .text-muted (#{time_ago_in_words conversation.updated_at} ago) %td - = link_to conversation_path(conversation, box: @box), method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger btn-xs' do - = delete_icon - .sr-only= t('buttons.delete') + - if @box == 'trash' + = link_to conversation_path(conversation, box: @box), method: :put, class: 'btn btn-default btn-info btn-xs' do + = icon 'fas', 'trash-restore' + .sr-only= t('buttons.restore') + - else + = link_to conversation_path(conversation, box: @box), method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger btn-xs' do + = delete_icon + .sr-only= t('buttons.delete') - unless @conversations.empty? = paginate @conversations \ No newline at end of file From e90d719436109568b12881ca82975d84dabc0723 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 20:24:30 +1200 Subject: [PATCH 054/151] fixed unread count on headers --- app/models/member.rb | 4 ++++ app/views/conversations/index.haml | 16 +++++++--------- app/views/layouts/_header.html.haml | 8 ++++---- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/app/models/member.rb b/app/models/member.rb index da510e8dd..0183ab840 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -132,6 +132,10 @@ class Member < ApplicationRecord authentications.find_by(provider: provider) end + def unread_count + receipts.where(is_read: false).count + end + # Authenticates against Flickr and returns an object we can use for subsequent api calls def flickr if @flickr.nil? diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index 97f83c6d6..c8562aa80 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -2,13 +2,13 @@ - content_for :breadcrumbs do %li.breadcrumb-item.active= link_to 'Conversations', conversations_path -- unless @conversations.empty? - = paginate @conversations .row .col-2 .col-10 %h1= @box + - unless @conversations.empty? + = will_paginate @conversations .row .col-2 %ul.list-group @@ -20,8 +20,6 @@ %span.badge.badge-primary.badge-pill= item_count .col-10 - - unless @conversations.empty? - = paginate @conversations .table-responsive.text-nowrap %table.table.table-hover %thead.black.white-text @@ -37,12 +35,12 @@ - conversation.participants.each do |member| = render 'members/tiny', member: member %td - %h3.h3-responsive + %h2 = link_to conversation_path(conversation) do - if conversation.receipts_for(current_member).last.is_unread? - = icon 'far', 'envelope' + .badge.badge-pill.badge-info= icon 'far', 'envelope' - else - = icon 'far', 'envelope-open' + .badge.badge-pill.badge-success= icon 'far', 'envelope-open' =conversation.subject %td =conversation.updated_at @@ -56,6 +54,6 @@ = link_to conversation_path(conversation, box: @box), method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger btn-xs' do = delete_icon .sr-only= t('buttons.delete') - - unless @conversations.empty? - = paginate @conversations + - unless @conversations.empty? + = will_paginate @conversations \ No newline at end of file diff --git a/app/views/layouts/_header.html.haml b/app/views/layouts/_header.html.haml index 60ae199b5..9376d9a02 100644 --- a/app/views/layouts/_header.html.haml +++ b/app/views/layouts/_header.html.haml @@ -28,9 +28,9 @@ - if member_signed_in? %li.nav-item.dropdown %a.nav-link.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", href: "#", role: "button"} - - if current_member.notifications.unread_count.positive? + - if current_member.unread_count.positive? = t('.your_stuff') - %span.badge.badge-info= current_member.notifications.unread_count + %span.badge.badge-info= current_member.unread_count - else = t('.current_memberlogin_name', current_memberlogin_name: current_member) .dropdown-menu{"aria-labelledby" => "navbarDropdown"} @@ -46,12 +46,12 @@ = t('.seeds') = link_to t('.posts'), member_posts_path(current_member), class: 'dropdown-item' - - if current_member.notifications.unread_count.positive? + - if current_member.unread_count.positive? .dropdown-divider %strong = link_to(conversations_path, class: 'dropdown-item') do = t('.inbox') - %span.badge.badge-info= current_member.notifications.unread_count + %span.badge.badge-info= current_member.unread_count - else = link_to t('.inbox'), conversations_path, class: 'dropdown-item' From 783e4ae046ebf261b69958c05f4cca24c1c72eb3 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 20:24:39 +1200 Subject: [PATCH 055/151] fixed up comments by deleted members --- app/views/comments/_single.html.haml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/views/comments/_single.html.haml b/app/views/comments/_single.html.haml index b29502adf..30db5ad15 100644 --- a/app/views/comments/_single.html.haml +++ b/app/views/comments/_single.html.haml @@ -1,10 +1,11 @@ .card.comment .card-body .row - .col-md-1= render "members/tiny", member: comment.author - .col-md-11.border-left + .col + = render "members/tiny", member: comment.author - if can?(:edit, comment) || can?(:destroy, comment) - .dropdown.float-right + %hr/ + .dropdown %button#comment-edit-button.btn.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", type: "button"} Actions .dropdown-menu.dropdown-menu-xs{"aria-labelledby" => "comment-edit-button"} - if can? :edit, comment @@ -16,9 +17,10 @@ data: { confirm: 'Are you sure?' }, class: 'dropdown-item text-danger' do = delete_icon Delete + .col-md-9.border-left .comment-meta.text-muted Posted by - - if comment.author.deleted? + - if comment.author.discarded? Member Deleted - else = link_to comment.author.login_name, member_path(comment.author) From 50560b01eb61a5b4f43581aab43bbe31bb018635 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 20:24:56 +1200 Subject: [PATCH 056/151] line up boxes --- app/views/conversations/show.html.haml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/views/conversations/show.html.haml b/app/views/conversations/show.html.haml index 5b3e9c854..ca4ee8a20 100644 --- a/app/views/conversations/show.html.haml +++ b/app/views/conversations/show.html.haml @@ -2,7 +2,10 @@ %li.breadcrumb-item= link_to 'Conversations', conversations_path %li.breadcrumb-item.active= link_to @conversation.subject, conversation_path(@conversation) - +.row + .col-2 + .col-10 + %h1= @conversation.subject .row .col-2 .card @@ -12,7 +15,6 @@ - @participants.each do |member| %li.list-group-item= render 'members/tiny', member: member .col-10 - %h1= @conversation.subject .card - @conversation.messages.order(:created_at).each do |message| %ul.list-group.list-group-flush From 57ca80f0eb98a40a929a3dba7e4973868d6316c7 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jul 2019 20:26:04 +1200 Subject: [PATCH 057/151] line up display of posts --- app/views/posts/show.html.haml | 35 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/app/views/posts/show.html.haml b/app/views/posts/show.html.haml index b91bbb8ad..f88612496 100644 --- a/app/views/posts/show.html.haml +++ b/app/views/posts/show.html.haml @@ -32,25 +32,24 @@ .row .col-md-8.col-12 - %section.blog-post - .card.post{ id: "post-#{@post.id}" } - .card-header - %h2.display-3.float-left - = @post.subject - = render 'posts/actions', post: @post - .card-body - .post-content= render 'posts/single', post: @post - .index-cards - - @post.photos.each do |photo| - = render 'photos/thumbnail', photo: photo + .card.post{ id: "post-#{@post.id}" } + .card-header + %h2.display-3.float-left + = @post.subject + = render 'posts/actions', post: @post + .card-body + .post-content= render 'posts/single', post: @post + .index-cards + - @post.photos.each do |photo| + = render 'photos/thumbnail', photo: photo - .card-footer - = render 'posts/likes', post: @post - .float-right - - if can? :create, Comment - = link_to new_comment_path(post_id: @post.id), class: 'btn' do - = icon 'fas', 'comment' - Comment + .card-footer + = render 'posts/likes', post: @post + .float-right + - if can? :create, Comment + = link_to new_comment_path(post_id: @post.id), class: 'btn' do + = icon 'fas', 'comment' + Comment %secion.comments= render "comments", post: @post From 01b53a0e69a96a0bb2e9f25a7c4ff946a0035b97 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 23 Jul 2019 09:37:57 +1200 Subject: [PATCH 058/151] continuing to replace notifications with conversations --- app/assets/stylesheets/_members.scss | 10 ++-- app/helpers/notifications_helper.rb | 11 ----- app/views/conversations/index.haml | 19 ++++---- app/views/conversations/show.html.haml | 26 +++++------ app/views/messages/_form.haml | 63 +++++++++++++------------- 5 files changed, 57 insertions(+), 72 deletions(-) delete mode 100644 app/helpers/notifications_helper.rb diff --git a/app/assets/stylesheets/_members.scss b/app/assets/stylesheets/_members.scss index 9db058fac..cfa145c1d 100644 --- a/app/assets/stylesheets/_members.scss +++ b/app/assets/stylesheets/_members.scss @@ -21,9 +21,9 @@ background-color: lighten($green, 30%); border-radius: 25px; display: inline-block; - font-size: 16px; - height: 50px; - line-height: 50px; + font-size: 1em; + height: 30px; + line-height: 30px; padding: 0 25px; a { color: $black; @@ -31,8 +31,8 @@ img { border-radius: 50%; float: left; - height: 50px; + height: 30px; margin: 0 10px 0 -25px; - width: 50px; + width: 30px; } } diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb deleted file mode 100644 index 2e551b3cb..000000000 --- a/app/helpers/notifications_helper.rb +++ /dev/null @@ -1,11 +0,0 @@ -module NotificationsHelper - def reply_link(notification) - if notification.post - # comment on the post in question - new_comment_url(post_id: notification.post.id) - else - # by default, reply link sends a PM in return - notification_reply_url(notification) - end - end -end diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index c8562aa80..677325e09 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -32,16 +32,17 @@ - @conversations.each do |conversation| %tr{class: conversation.receipts_for(current_member).last.is_unread? ? 'active': ''} %td - - conversation.participants.each do |member| - = render 'members/tiny', member: member + .d-flex.w-100.justify-content-between + - if conversation.receipts_for(current_member).last.is_unread? + %span.badge.badge-pill.badge-info= icon 'far', 'envelope' + - else + %span.badge.badge-pill.badge-success= icon 'far', 'envelope-open' + - conversation.participants.each do |member| + - if member != current_member + = render 'members/tiny', member: member %td - %h2 - = link_to conversation_path(conversation) do - - if conversation.receipts_for(current_member).last.is_unread? - .badge.badge-pill.badge-info= icon 'far', 'envelope' - - else - .badge.badge-pill.badge-success= icon 'far', 'envelope-open' - =conversation.subject + = link_to conversation_path(conversation) do + %strong= conversation.subject %td =conversation.updated_at .text-muted (#{time_ago_in_words conversation.updated_at} ago) diff --git a/app/views/conversations/show.html.haml b/app/views/conversations/show.html.haml index ca4ee8a20..7dc5fc1c7 100644 --- a/app/views/conversations/show.html.haml +++ b/app/views/conversations/show.html.haml @@ -3,33 +3,29 @@ %li.breadcrumb-item.active= link_to @conversation.subject, conversation_path(@conversation) .row - .col-2 - .col-10 + .col-md-4 + .col-md-8 %h1= @conversation.subject .row - .col-2 + .col-md-4 .card .card-header %h6 Participants %ul.list-group.list-group-flush - @participants.each do |member| %li.list-group-item= render 'members/tiny', member: member - .col-10 + .col-md-8 .card - - @conversation.messages.order(:created_at).each do |message| - %ul.list-group.list-group-flush + %ul.list-group.list-group-flush + - @conversation.messages.order(:created_at).each do |message| %li.list-group-item .text-muted.float-right = comment_icon on #{message.created_at} - = render 'members/tiny', member: message.sender - %p.mb-2.well + = render 'members/tiny', member: message.sender + %p.text-justify :growstuff_markdown #{ strip_tags(message.body) } - -# .card-footer - -# = link_to 'Reply', @reply_link, class: 'btn btn-primary' - -# = link_to message, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger' do - -# = delete_icon - -# = t('buttons.delete') - - = render 'messages/form', conversation: @conversation \ No newline at end of file + %li.list-group-item + = icon 'fas', 'reply' + = render 'messages/form', conversation: @conversation diff --git a/app/views/messages/_form.haml b/app/views/messages/_form.haml index bb6d05f4d..a7bb3d42c 100644 --- a/app/views/messages/_form.haml +++ b/app/views/messages/_form.haml @@ -1,36 +1,35 @@ = bootstrap_form_tag url: '/messages' do |f| - .card - .card-body - -# - if @notification.errors.any? - -# #error_explanation - -# %h2 - -# = pluralize(@notification.errors.size, "error") - -# prohibited this message from being sent: - -# %ul - -# - @notification.errors.full_messages.each do |msg| - -# %li= msg + -# - if @notification.errors.any? + -# #error_explanation + -# %h2 + -# = pluralize(@notification.errors.size, "error") + -# prohibited this message from being sent: + -# %ul + -# - @notification.errors.full_messages.each do |msg| + -# %li= msg - .field + .field - - if @conversation.present? - = f.hidden_field :conversation_id, value: @conversation.id - -# To - -# - @conversation.recipients.each do |recipient| - -# - unless recipient == current_member - -# = link_to recipient, recipient - -# = render 'members/tiny', member: recipient - - elsif @recipient.present? - %p - To - = link_to @recipient, @recipient - = render 'members/tiny', member: @recipient - = f.hidden_field :recipient_id, value: @recipient.id - = f.text_field :subject, value: @subject, class: 'form-control', maxlength: 255, required: true - - else - TODO - add recipient field + - if @conversation.present? + = f.hidden_field :conversation_id, value: @conversation.id + -# To + -# - @conversation.recipients.each do |recipient| + -# - unless recipient == current_member + -# = link_to recipient, recipient + -# = render 'members/tiny', member: recipient + - elsif @recipient.present? + %p + To + = link_to @recipient, @recipient + = render 'members/tiny', member: @recipient + = f.hidden_field :recipient_id, value: @recipient.id + = f.text_field :subject, value: @subject, class: 'form-control', maxlength: 255, required: true + - else + TODO - add recipient field - = f.text_area :body, rows: 12, label: "Type your message here", required: true - %span.help-block= render partial: "shared/markdown_help" - .card-footer - = link_to 'cancel', conversations_path, class: 'btn' - .float-right= f.submit "Send", class: 'btn btn-primary' + = f.text_area :body, rows: 12, label: "Type your message here", required: true + %span.help-block= render partial: "shared/markdown_help" + + .card-footer + = link_to 'cancel', conversations_path, class: 'btn' + .float-right= f.submit "Send", class: 'btn btn-primary' From e24c0ee3e861a35a2a16d9f5e6d29491922c3af1 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 23 Jul 2019 09:38:22 +1200 Subject: [PATCH 059/151] Removing commented out code --- app/views/messages/_form.haml | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/app/views/messages/_form.haml b/app/views/messages/_form.haml index a7bb3d42c..205c85aee 100644 --- a/app/views/messages/_form.haml +++ b/app/views/messages/_form.haml @@ -1,22 +1,6 @@ = bootstrap_form_tag url: '/messages' do |f| - -# - if @notification.errors.any? - -# #error_explanation - -# %h2 - -# = pluralize(@notification.errors.size, "error") - -# prohibited this message from being sent: - -# %ul - -# - @notification.errors.full_messages.each do |msg| - -# %li= msg - - .field - - if @conversation.present? = f.hidden_field :conversation_id, value: @conversation.id - -# To - -# - @conversation.recipients.each do |recipient| - -# - unless recipient == current_member - -# = link_to recipient, recipient - -# = render 'members/tiny', member: recipient - elsif @recipient.present? %p To From 01cb0ca9751a1d76569e85da839caf654ed28e96 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 23 Jul 2019 09:38:30 +1200 Subject: [PATCH 060/151] Removed todo --- app/views/messages/_form.haml | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/views/messages/_form.haml b/app/views/messages/_form.haml index 205c85aee..c7c6e7a84 100644 --- a/app/views/messages/_form.haml +++ b/app/views/messages/_form.haml @@ -8,8 +8,6 @@ = render 'members/tiny', member: @recipient = f.hidden_field :recipient_id, value: @recipient.id = f.text_field :subject, value: @subject, class: 'form-control', maxlength: 255, required: true - - else - TODO - add recipient field = f.text_area :body, rows: 12, label: "Type your message here", required: true %span.help-block= render partial: "shared/markdown_help" From fab222f581a4851378f32df47dddaaf095dbb5c7 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 23 Jul 2019 09:38:59 +1200 Subject: [PATCH 061/151] Removing rubocop.yml --- app/views/conversations/index.haml | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index 677325e09..2df257204 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -2,7 +2,6 @@ - content_for :breadcrumbs do %li.breadcrumb-item.active= link_to 'Conversations', conversations_path - .row .col-2 .col-10 @@ -57,4 +56,3 @@ .sr-only= t('buttons.delete') - unless @conversations.empty? = will_paginate @conversations - \ No newline at end of file From 8ca0eef53cb5e0f0a3daa2fbf644bbecf2189603 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 23 Jul 2019 09:41:18 +1200 Subject: [PATCH 062/151] Removing notifications controller specs --- .../notifications_controller_spec.rb | 75 ------------------- 1 file changed, 75 deletions(-) delete mode 100644 spec/controllers/notifications_controller_spec.rb diff --git a/spec/controllers/notifications_controller_spec.rb b/spec/controllers/notifications_controller_spec.rb deleted file mode 100644 index c606d9fe9..000000000 --- a/spec/controllers/notifications_controller_spec.rb +++ /dev/null @@ -1,75 +0,0 @@ -require 'rails_helper' - -describe NotificationsController do - login_member - - def valid_attributes - { - "recipient_id" => subject.current_member.id, - "sender_id" => FactoryBot.create(:member).id, - "subject" => 'test' - } - end - - describe "GET index" do - it "assigns all notifications as @notifications" do - notification = FactoryBot.create(:notification, recipient_id: subject.current_member.id) - get :index, params: {} - assigns(:notifications).should eq([notification]) - end - end - - describe "GET show" do - it "assigns the requested notification as @notification" do - notification = FactoryBot.create(:notification, recipient_id: subject.current_member.id) - get :show, params: { id: notification.to_param } - assigns(:notification).should eq(notification) - end - - it "assigns the reply link for a post comment" do - notification = FactoryBot.create(:notification, recipient_id: subject.current_member.id) - - get :show, params: { id: notification.to_param } - assigns(:reply_link).should_not be_nil - assigns(:reply_link).should eq new_comment_url( - post_id: notification.post.id - ) - end - - it "marks notifications as read" do - notification = FactoryBot.create(:notification, recipient_id: subject.current_member.id) - get :show, params: { id: notification.to_param } - # we need to fetch it from the db again, can't test against the old one - n = Notification.find(notification.id) - n.read.should eq true - end - end - - describe "GET reply" do - it "marks notifications as read" do - notification = FactoryBot.create(:notification, recipient_id: subject.current_member.id) - get :reply, params: { notification_id: notification.to_param } - # we need to fetch it from the db again, can't test against the old one - n = Notification.find(notification.id) - n.read.should eq true - end - end - - describe "GET new" do - it "assigns a recipient" do - @recipient = FactoryBot.create(:member) - get :new, params: { recipient_id: @recipient.id } - expect(assigns(:recipient)).to be_an_instance_of(Member) - end - end - - describe "POST create" do - describe "with valid params" do - it "redirects to the recipient's profile" do - @recipient = FactoryBot.create(:member) - post :create, params: { notification: { recipient_id: @recipient.id, subject: 'foo' } } - response.should redirect_to(notifications_path) - end - end - end -end From 8cb21ec79bc92edaf2b792e5c403a2babce1c00d Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 23 Jul 2019 09:41:18 +1200 Subject: [PATCH 063/151] Removing notifications specs --- .../notifications_controller_spec.rb | 75 ------------------- spec/routing/notifications_routing_spec.rb | 33 -------- 2 files changed, 108 deletions(-) delete mode 100644 spec/controllers/notifications_controller_spec.rb delete mode 100644 spec/routing/notifications_routing_spec.rb diff --git a/spec/controllers/notifications_controller_spec.rb b/spec/controllers/notifications_controller_spec.rb deleted file mode 100644 index c606d9fe9..000000000 --- a/spec/controllers/notifications_controller_spec.rb +++ /dev/null @@ -1,75 +0,0 @@ -require 'rails_helper' - -describe NotificationsController do - login_member - - def valid_attributes - { - "recipient_id" => subject.current_member.id, - "sender_id" => FactoryBot.create(:member).id, - "subject" => 'test' - } - end - - describe "GET index" do - it "assigns all notifications as @notifications" do - notification = FactoryBot.create(:notification, recipient_id: subject.current_member.id) - get :index, params: {} - assigns(:notifications).should eq([notification]) - end - end - - describe "GET show" do - it "assigns the requested notification as @notification" do - notification = FactoryBot.create(:notification, recipient_id: subject.current_member.id) - get :show, params: { id: notification.to_param } - assigns(:notification).should eq(notification) - end - - it "assigns the reply link for a post comment" do - notification = FactoryBot.create(:notification, recipient_id: subject.current_member.id) - - get :show, params: { id: notification.to_param } - assigns(:reply_link).should_not be_nil - assigns(:reply_link).should eq new_comment_url( - post_id: notification.post.id - ) - end - - it "marks notifications as read" do - notification = FactoryBot.create(:notification, recipient_id: subject.current_member.id) - get :show, params: { id: notification.to_param } - # we need to fetch it from the db again, can't test against the old one - n = Notification.find(notification.id) - n.read.should eq true - end - end - - describe "GET reply" do - it "marks notifications as read" do - notification = FactoryBot.create(:notification, recipient_id: subject.current_member.id) - get :reply, params: { notification_id: notification.to_param } - # we need to fetch it from the db again, can't test against the old one - n = Notification.find(notification.id) - n.read.should eq true - end - end - - describe "GET new" do - it "assigns a recipient" do - @recipient = FactoryBot.create(:member) - get :new, params: { recipient_id: @recipient.id } - expect(assigns(:recipient)).to be_an_instance_of(Member) - end - end - - describe "POST create" do - describe "with valid params" do - it "redirects to the recipient's profile" do - @recipient = FactoryBot.create(:member) - post :create, params: { notification: { recipient_id: @recipient.id, subject: 'foo' } } - response.should redirect_to(notifications_path) - end - end - end -end diff --git a/spec/routing/notifications_routing_spec.rb b/spec/routing/notifications_routing_spec.rb deleted file mode 100644 index bb7335e1b..000000000 --- a/spec/routing/notifications_routing_spec.rb +++ /dev/null @@ -1,33 +0,0 @@ -require "rails_helper" - -describe NotificationsController do - describe "routing" do - it "routes to #index" do - get("/notifications").should route_to("notifications#index") - end - - it "routes to #new" do - get("/notifications/new").should route_to("notifications#new") - end - - it "routes to #show" do - get("/notifications/1").should route_to("notifications#show", id: "1") - end - - it "routes to #edit" do - get("/notifications/1/edit").should route_to("notifications#edit", id: "1") - end - - it "routes to #create" do - post("/notifications").should route_to("notifications#create") - end - - it "routes to #update" do - put("/notifications/1").should route_to("notifications#update", id: "1") - end - - it "routes to #destroy" do - delete("/notifications/1").should route_to("notifications#destroy", id: "1") - end - end -end From 66223194667170781c77d04450c8b4793a2741c6 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 23 Jul 2019 09:47:16 +1200 Subject: [PATCH 064/151] Removed chekcing subject in converation --- app/controllers/conversations_controller.rb | 9 --------- 1 file changed, 9 deletions(-) diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index 4744a2abc..d52021244 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -2,7 +2,6 @@ class ConversationsController < ApplicationController respond_to :html before_action :authenticate_member! before_action :set_box - before_action :check_current_subject_in_conversation, only: %i(show update destroy) def index @conversations = if @box.eql? "inbox" @@ -51,12 +50,4 @@ class ConversationsController < ApplicationController params[:box] end end - - def check_current_subject_in_conversation - @conversation = Mailboxer::Conversation.find_by(id: params[:id]) - if @conversation.nil? || !@conversation.is_participant?(current_member) - redirect_to conversations_path(box: box) - return - end - end end From 4a8f737bace75cbf77eb4f86f9e6507501a292e9 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 23 Jul 2019 09:50:37 +1200 Subject: [PATCH 065/151] Revert "Removed chekcing subject in converation" This reverts commit 66223194667170781c77d04450c8b4793a2741c6. --- app/controllers/conversations_controller.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index d52021244..4744a2abc 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -2,6 +2,7 @@ class ConversationsController < ApplicationController respond_to :html before_action :authenticate_member! before_action :set_box + before_action :check_current_subject_in_conversation, only: %i(show update destroy) def index @conversations = if @box.eql? "inbox" @@ -50,4 +51,12 @@ class ConversationsController < ApplicationController params[:box] end end + + def check_current_subject_in_conversation + @conversation = Mailboxer::Conversation.find_by(id: params[:id]) + if @conversation.nil? || !@conversation.is_participant?(current_member) + redirect_to conversations_path(box: box) + return + end + end end From 17e3998261c7bf277c0b40edcf99fa6985569dec Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 23 Jul 2019 11:27:53 +1200 Subject: [PATCH 066/151] Move from tables to lists --- app/models/planting.rb | 2 +- app/views/conversations/index.haml | 69 +++++++++++++----------------- 2 files changed, 31 insertions(+), 40 deletions(-) diff --git a/app/models/planting.rb b/app/models/planting.rb index 2379c06db..0df0dcdd7 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -43,7 +43,7 @@ class Planting < ApplicationRecord ## ## Delegations - delegate :name, :en_wikipedia_url, :default_scientific_name, :plantings_count, + delegate :name, :en_wikipedia_url, :annual?, :default_scientific_name, :plantings_count, to: :crop, prefix: true ## diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index 2df257204..69431066b 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -3,13 +3,13 @@ %li.breadcrumb-item.active= link_to 'Conversations', conversations_path .row - .col-2 - .col-10 + .col-md-2 + .col-md-10 %h1= @box - unless @conversations.empty? = will_paginate @conversations .row - .col-2 + .col-md-2 %ul.list-group - @boxes.each do |box_name, item_count| %li.list-group-item.d-flex.justify-content-between{class: box_name == @box ? 'active' : ''} @@ -17,42 +17,33 @@ = icon 'fas', box_name = box_name %span.badge.badge-primary.badge-pill= item_count + %hr/ + .col-md-10 + %ul.list-group + - @conversations.each do |conversation| + %li.list-group-item + .float-right + - if @box == 'trash' + = link_to conversation_path(conversation, box: @box), method: :put, class: 'btn btn-default text-info btn-xs' do + = icon 'fas', 'trash-restore' + .sr-only= t('buttons.restore') + - else + = link_to conversation_path(conversation, box: @box), method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default text-danger btn-xs' do + = delete_icon + .sr-only= t('buttons.delete') + + = link_to conversation_path(conversation), class: 'list-group-item-action flex-column align-items-start' do + %h3 + - if conversation.receipts_for(current_member).last.is_unread? + %span.badge.badge-pill.badge-info= icon 'far', 'envelope' + - else + %span.badge.badge-pill.badge-success= icon 'far', 'envelope-open' + = conversation.subject + %p + = truncate(strip_tags(conversation.messages.last.body), length: 100, separator: ' ', omission: '... ') + - conversation.participants.each do |member| + - if member != current_member + = render 'members/tiny', member: member - .col-10 - .table-responsive.text-nowrap - %table.table.table-hover - %thead.black.white-text - %tr - %th{scope: "col"} Participants - %th{scope: "col"} Subject - %th{scope: "col"} Sent at - %th{scope: "col"} - %tbody - - @conversations.each do |conversation| - %tr{class: conversation.receipts_for(current_member).last.is_unread? ? 'active': ''} - %td - .d-flex.w-100.justify-content-between - - if conversation.receipts_for(current_member).last.is_unread? - %span.badge.badge-pill.badge-info= icon 'far', 'envelope' - - else - %span.badge.badge-pill.badge-success= icon 'far', 'envelope-open' - - conversation.participants.each do |member| - - if member != current_member - = render 'members/tiny', member: member - %td - = link_to conversation_path(conversation) do - %strong= conversation.subject - %td - =conversation.updated_at - .text-muted (#{time_ago_in_words conversation.updated_at} ago) - %td - - if @box == 'trash' - = link_to conversation_path(conversation, box: @box), method: :put, class: 'btn btn-default btn-info btn-xs' do - = icon 'fas', 'trash-restore' - .sr-only= t('buttons.restore') - - else - = link_to conversation_path(conversation, box: @box), method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-danger btn-xs' do - = delete_icon - .sr-only= t('buttons.delete') - unless @conversations.empty? = will_paginate @conversations From bf77f317770d74c011ff32477e99f68dcd957a37 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 28 Jul 2019 14:28:08 +1200 Subject: [PATCH 067/151] don't show progress bars on annuals --- app/models/planting.rb | 3 ++- app/views/members/_member.haml | 4 ++-- app/views/plantings/_progress.html.haml | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/models/planting.rb b/app/models/planting.rb index 0df0dcdd7..0555e4ac5 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -43,9 +43,10 @@ class Planting < ApplicationRecord ## ## Delegations - delegate :name, :en_wikipedia_url, :annual?, :default_scientific_name, :plantings_count, + delegate :name, :en_wikipedia_url, :default_scientific_name, :plantings_count, to: :crop, prefix: true + delegate :annual?, to: :crop ## ## Validations validates :garden, presence: true diff --git a/app/views/members/_member.haml b/app/views/members/_member.haml index 3f0746362..2274a8e5c 100644 --- a/app/views/members/_member.haml +++ b/app/views/members/_member.haml @@ -19,10 +19,10 @@ %ul.nav.nav-justified.small %li.nav-item.border-right = link_to member_plantings_path(member) do - = localize_plural(member.plantings.active, Planting) + = localize_plural(member.plantings, Planting) %li.nav-item.border-right = link_to member_harvests_path(member) do = localize_plural(member.harvests, Harvest) %li.nav-item = link_to member_seeds_path(member) do - = localize_plural(member.seeds.active, Seed) + = localize_plural(member.seeds, Seed) diff --git a/app/views/plantings/_progress.html.haml b/app/views/plantings/_progress.html.haml index f5527410b..16fb5686f 100644 --- a/app/views/plantings/_progress.html.haml +++ b/app/views/plantings/_progress.html.haml @@ -1,4 +1,4 @@ -- if planting.percentage_grown.present? +- if planting.annual? && planting.percentage_grown.present? .progress .progress-bar.bg-success{"aria-valuemax" => "100", "aria-valuemin" => "0", "aria-valuenow" => planting.percentage_grown, :role => "progressbar", :style => "width: #{planting.percentage_grown}%; height: 25px"} From 51577932020fdc76c2f42115a31d55446a0477d0 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 4 Aug 2019 15:37:15 +1200 Subject: [PATCH 068/151] wrap long line --- .../20190720000555_create_mailboxer.mailboxer_engine.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/db/migrate/20190720000555_create_mailboxer.mailboxer_engine.rb b/db/migrate/20190720000555_create_mailboxer.mailboxer_engine.rb index 3b9acbddb..c932d9041 100644 --- a/db/migrate/20190720000555_create_mailboxer.mailboxer_engine.rb +++ b/db/migrate/20190720000555_create_mailboxer.mailboxer_engine.rb @@ -47,9 +47,11 @@ class CreateMailboxer < ActiveRecord::Migration[4.2] # Foreign keys # Conversations # Receipts - add_foreign_key "mailboxer_receipts", "mailboxer_notifications", name: "receipts_on_notification_id", column: "notification_id" + add_foreign_key "mailboxer_receipts", "mailboxer_notifications", + name: "receipts_on_notification_id", column: "notification_id" # Messages - add_foreign_key "mailboxer_notifications", "mailboxer_conversations", name: "notifications_on_conversation_id", column: "conversation_id" + add_foreign_key "mailboxer_notifications", "mailboxer_conversations", + name: "notifications_on_conversation_id", column: "conversation_id" end def self.down From 00fbfc77e7968598a4f165b6ecddfe1bff49c20f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 4 Aug 2019 16:04:23 +1200 Subject: [PATCH 069/151] tidy up inbox view --- app/views/conversations/index.haml | 51 ++++++++++++------------------ 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index 69431066b..e5e38d5e2 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -1,6 +1,7 @@ - content_for :title, "Inbox" - content_for :breadcrumbs do - %li.breadcrumb-item.active= link_to 'Conversations', conversations_path + %li.breadcrumb-item= link_to 'Conversations', conversations_path + %li.breadcrumb-item.active= link_to @box, conversations_path(box: @box) .row .col-md-2 @@ -9,41 +10,29 @@ - unless @conversations.empty? = will_paginate @conversations .row - .col-md-2 - %ul.list-group - - @boxes.each do |box_name, item_count| - %li.list-group-item.d-flex.justify-content-between{class: box_name == @box ? 'active' : ''} - = link_to conversations_path(box: box_name), class: 'nav-link' do - = icon 'fas', box_name - = box_name + .col-md-2.list-group + - @boxes.each do |box_name, item_count| + = link_to conversations_path(box: box_name), class: 'nav-link' do + .list-group-item.d-flex.justify-content-between{class: "#{box_name == @box ? 'active' : ''} #{box_name}"} + = icon 'fas', box_name + = box_name %span.badge.badge-primary.badge-pill= item_count - %hr/ + .col-md-10 - %ul.list-group + .list-group - @conversations.each do |conversation| - %li.list-group-item - .float-right - - if @box == 'trash' - = link_to conversation_path(conversation, box: @box), method: :put, class: 'btn btn-default text-info btn-xs' do - = icon 'fas', 'trash-restore' - .sr-only= t('buttons.restore') - - else - = link_to conversation_path(conversation, box: @box), method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default text-danger btn-xs' do - = delete_icon - .sr-only= t('buttons.delete') - - = link_to conversation_path(conversation), class: 'list-group-item-action flex-column align-items-start' do - %h3 + %a.list-group-item.list-group-item-action.flex-column.align-items-start{href: conversation_path(conversation)} + .d-flex.w-100.justify-content-between + %h5.mb-2.h5 - if conversation.receipts_for(current_member).last.is_unread? - %span.badge.badge-pill.badge-info= icon 'far', 'envelope' + %i.far.fa-envelope.mr-4.pr-3 - else - %span.badge.badge-pill.badge-success= icon 'far', 'envelope-open' - = conversation.subject - %p - = truncate(strip_tags(conversation.messages.last.body), length: 100, separator: ' ', omission: '... ') - - conversation.participants.each do |member| - - if member != current_member - = render 'members/tiny', member: member + %i.far.fa-envelope-open.mr-4.pr-3 + %strong= conversation.subject + %small= time_ago_in_words conversation.messages.last.created_at + %p.mb-2 + = truncate(strip_tags(conversation.messages.last.body), length: 100, separator: ' ', omission: '... ') + Donec id elit non mi porta. - unless @conversations.empty? = will_paginate @conversations From 17da3bdd966019fe32eaef6d3f335633f5ec073a Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 4 Aug 2019 17:41:43 +1200 Subject: [PATCH 070/151] conversations view changes --- app/views/conversations/index.haml | 20 ++++++++++++++------ app/views/conversations/show.html.haml | 8 ++++---- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index e5e38d5e2..a0f3d7fc2 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -12,11 +12,10 @@ .row .col-md-2.list-group - @boxes.each do |box_name, item_count| - = link_to conversations_path(box: box_name), class: 'nav-link' do - .list-group-item.d-flex.justify-content-between{class: "#{box_name == @box ? 'active' : ''} #{box_name}"} - = icon 'fas', box_name - = box_name - %span.badge.badge-primary.badge-pill= item_count + = link_to conversations_path(box: box_name), class: "nav-link list-group-item d-flex justify-content-between #{box_name == @box ? 'active' : ''} #{box_name}" do + = icon 'fas', box_name + = box_name + %span.badge.badge-primary.badge-pill= item_count .col-md-10 .list-group @@ -29,7 +28,16 @@ - else %i.far.fa-envelope-open.mr-4.pr-3 %strong= conversation.subject - %small= time_ago_in_words conversation.messages.last.created_at + %small + #{time_ago_in_words conversation.messages.last.created_at} ago + %span.text-muted= conversation.messages.last.created_at + + %ul.list-group + - conversation.recipients.each do |member| + - if member != current_member + %li.member-chip + = image_tag(avatar_uri(member, 100), alt: '', height: 50, width: 50) + = member %p.mb-2 = truncate(strip_tags(conversation.messages.last.body), length: 100, separator: ' ', omission: '... ') diff --git a/app/views/conversations/show.html.haml b/app/views/conversations/show.html.haml index 7dc5fc1c7..791f72b96 100644 --- a/app/views/conversations/show.html.haml +++ b/app/views/conversations/show.html.haml @@ -3,18 +3,18 @@ %li.breadcrumb-item.active= link_to @conversation.subject, conversation_path(@conversation) .row - .col-md-4 - .col-md-8 + .col-md-2 + .col-md-10 %h1= @conversation.subject .row - .col-md-4 + .col-md-2 .card .card-header %h6 Participants %ul.list-group.list-group-flush - @participants.each do |member| %li.list-group-item= render 'members/tiny', member: member - .col-md-8 + .col-md-10 .card %ul.list-group.list-group-flush - @conversation.messages.order(:created_at).each do |message| From 493a49bb3e6fc0445cbfd2d9022817c368d0b5a8 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 5 Aug 2019 18:57:54 +1200 Subject: [PATCH 071/151] Nicer display when there are not gardens --- app/views/gardens/index.html.haml | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/app/views/gardens/index.html.haml b/app/views/gardens/index.html.haml index 444b9c4dc..50a922678 100644 --- a/app/views/gardens/index.html.haml +++ b/app/views/gardens/index.html.haml @@ -13,18 +13,20 @@ - else %li.breadcrumb-item.active= link_to 'Gardens', gardens_path -= link_to gardens_active_tickbox_path(@owner, @show_all) do - = check_box_tag 'active', 'all', @show_all - include in-active - -.pagination - = page_entries_info @gardens - = will_paginate @gardens - +%section.border-top + = link_to gardens_active_tickbox_path(@owner, @show_all) do + = check_box_tag 'active', 'all', @show_all + include in-active - if @gardens.empty? %p There are no gardens to display. + - if can?(:create, Garden) && @owner == current_member + = link_to 'Add a garden', new_garden_path, class: 'btn btn-primary' + - else + .row + .col-12= page_entries_info @gardens + .col-12= will_paginate @gardens - @gardens.each do |garden| %section.border-top .row @@ -43,6 +45,6 @@ .col-6.col-md-4.col-lg-3= render 'plantings/card', planting: planting -.pagination - = page_entries_info @gardens - = will_paginate @gardens + .row + .col-12= page_entries_info @gardens + .col-12= will_paginate @gardens From 0c8e993006f05dbcf22ec029ef8c00ce56b399bd Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 7 Aug 2019 16:18:59 +1200 Subject: [PATCH 072/151] gardens show all as a button --- app/views/gardens/index.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/gardens/index.html.haml b/app/views/gardens/index.html.haml index 50a922678..0515ad7ef 100644 --- a/app/views/gardens/index.html.haml +++ b/app/views/gardens/index.html.haml @@ -14,7 +14,7 @@ %li.breadcrumb-item.active= link_to 'Gardens', gardens_path %section.border-top - = link_to gardens_active_tickbox_path(@owner, @show_all) do + = link_to gardens_active_tickbox_path(@owner, @show_all), class: 'btn' do = check_box_tag 'active', 'all', @show_all include in-active From 6af95fa722370f39fbe625e7b40cb0954432308d Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 7 Aug 2019 16:19:11 +1200 Subject: [PATCH 073/151] Help percy find the correct link --- spec/features/percy/percy_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/percy/percy_spec.rb b/spec/features/percy/percy_spec.rb index 7b614d169..13f3f22db 100644 --- a/spec/features/percy/percy_spec.rb +++ b/spec/features/percy/percy_spec.rb @@ -330,7 +330,7 @@ rest of the garden. Percy.snapshot(page, name: "#{prefix}/crops-menu") click_on 'Community' Percy.snapshot(page, name: "#{prefix}/community-menu") - click_on 'percy' + click_on 'percy', class: 'nav-link' Percy.snapshot(page, name: "#{prefix}/member-menu") end end From 4c045374ff5b2bcf1edfa554097db1ae212a16a9 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 7 Aug 2019 16:19:37 +1200 Subject: [PATCH 074/151] tidy up plantings view --- app/views/plantings/index.html.haml | 35 ++++++++++++++++------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/app/views/plantings/index.html.haml b/app/views/plantings/index.html.haml index f905e12d2..f0c60a53e 100644 --- a/app/views/plantings/index.html.haml +++ b/app/views/plantings/index.html.haml @@ -13,25 +13,28 @@ - else %li.breadcrumb-item.active= link_to 'Plantings', plantings_path -= link_to plantings_active_tickbox_path(@owner, @show_all) do - = check_box_tag 'active', 'all', @show_all - include in-active +%section.border-top + .btn-group + = link_to plantings_active_tickbox_path(@owner, @show_all), class: 'btn' do + = check_box_tag 'active', 'all', @show_all + include in-active -- if @owner - = link_to t('.view_owners_profile', owner: @owner), member_path(@owner) + - if @owner + = link_to t('.view_owners_profile', owner: @owner), member_path(@owner), class: 'btn' -.pagination - = page_entries_info @plantings - = render 'layouts/pagination', collection: @plantings +.row + .col-12= page_entries_info @plantings + .col-12= render 'layouts/pagination', collection: @plantings .index-cards= render @plantings, full: true -.pagination - = page_entries_info @plantings - = render 'layouts/pagination', collection: @plantings +.row + .col-12= page_entries_info @plantings + .col-12= render 'layouts/pagination', collection: @plantings - %ul.list-inline - %li= t('.the_data_on_this_page_is_available_in_the_following_formats') - - ['csv', 'json', 'rss'].each do |format| - %li= link_to format.upcase, - (@owner ? member_plantings_path(@owner, format: format) : plantings_path(format: format)) +%p= t('.the_data_on_this_page_is_available_in_the_following_formats') +%ul.list-group.list-group-horizontal + - ['csv', 'json', 'rss'].each do |format| + %li.list-group-item + = icon 'fas', format + = link_to format.upcase, (@owner ? member_plantings_path(@owner, format: format) : plantings_path(format: format)) From 149f92536dc5599b147078e8e79037ce4c1f8be1 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 7 Aug 2019 16:19:43 +1200 Subject: [PATCH 075/151] conversations view matching the index (avatar photos on the right) --- app/views/conversations/show.html.haml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/app/views/conversations/show.html.haml b/app/views/conversations/show.html.haml index 791f72b96..308686a71 100644 --- a/app/views/conversations/show.html.haml +++ b/app/views/conversations/show.html.haml @@ -19,13 +19,15 @@ %ul.list-group.list-group-flush - @conversation.messages.order(:created_at).each do |message| %li.list-group-item - .text-muted.float-right + .col-md-8.text-muted = comment_icon on #{message.created_at} - = render 'members/tiny', member: message.sender - %p.text-justify - :growstuff_markdown - #{ strip_tags(message.body) } + .col-md-4.text-right.float-right + = render 'members/tiny', member: message.sender + .col-12 + %p.text-justify + :growstuff_markdown + #{ strip_tags(message.body) } %li.list-group-item = icon 'fas', 'reply' = render 'messages/form', conversation: @conversation From ba1c3a71593b7c4ef72ad79bcab7d41def8014f1 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 7 Aug 2019 16:20:10 +1200 Subject: [PATCH 076/151] add the notifications helper back --- app/helpers/notifications_helper.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 app/helpers/notifications_helper.rb diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb new file mode 100644 index 000000000..2e551b3cb --- /dev/null +++ b/app/helpers/notifications_helper.rb @@ -0,0 +1,11 @@ +module NotificationsHelper + def reply_link(notification) + if notification.post + # comment on the post in question + new_comment_url(post_id: notification.post.id) + else + # by default, reply link sends a PM in return + notification_reply_url(notification) + end + end +end From 9651bc6db5be3e97b2e19f26e7aab4596f1baa46 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 7 Aug 2019 16:51:46 +1200 Subject: [PATCH 077/151] Changed notifications spec to conversations spec --- spec/features/conversations/index_spec.rb | 37 +++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 spec/features/conversations/index_spec.rb diff --git a/spec/features/conversations/index_spec.rb b/spec/features/conversations/index_spec.rb new file mode 100644 index 000000000..72a75d13f --- /dev/null +++ b/spec/features/conversations/index_spec.rb @@ -0,0 +1,37 @@ +require 'rails_helper' + +describe "Notifications", :js do + let(:sender) { create :member } + let(:recipient) { create :member, login_name: 'beyonce' } + + before do + sender.send_message(recipient, "this is the body", "something i want to say") + login_as recipient + end + + describe "Read conversations list" do + before do + visit root_path + click_link 'Your Stuff' + click_link 'Inbox' + end + it { expect(page).to have_content 'something i want to say' } + it { Percy.snapshot(page, name: 'conversations#index') } + + describe 'view conversation thread' do + before { click_link 'something i want to say' } + + it { expect(page).to have_content 'this is the body' } + it { expect(page).to have_link sender.login_name } + it { Percy.snapshot(page, name: 'conversations#show') } + + describe 'Replying to the conversation' do + before do + fill_in :body, with: 'i like this too' + click_button 'Send' + end + it { expect(page).to have_content "i like this too" } + end + end + end +end From 60671af6abffc384ae2db3eb4dafac4962fec2f5 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 7 Aug 2019 21:49:27 +1200 Subject: [PATCH 078/151] Conversations spec --- app/views/conversations/index.haml | 41 +++++++-------- spec/features/conversations/index_spec.rb | 15 +----- spec/features/conversations/show_spec.rb | 32 ++++++++++++ spec/features/notifications_spec.rb | 62 ----------------------- 4 files changed, 52 insertions(+), 98 deletions(-) create mode 100644 spec/features/conversations/show_spec.rb delete mode 100644 spec/features/notifications_spec.rb diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index a0f3d7fc2..d6a2e5885 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -20,27 +20,24 @@ .col-md-10 .list-group - @conversations.each do |conversation| - %a.list-group-item.list-group-item-action.flex-column.align-items-start{href: conversation_path(conversation)} - .d-flex.w-100.justify-content-between - %h5.mb-2.h5 - - if conversation.receipts_for(current_member).last.is_unread? - %i.far.fa-envelope.mr-4.pr-3 - - else - %i.far.fa-envelope-open.mr-4.pr-3 - %strong= conversation.subject - %small - #{time_ago_in_words conversation.messages.last.created_at} ago - %span.text-muted= conversation.messages.last.created_at - - %ul.list-group - - conversation.recipients.each do |member| - - if member != current_member - %li.member-chip - = image_tag(avatar_uri(member, 100), alt: '', height: 50, width: 50) - = member - - %p.mb-2 - = truncate(strip_tags(conversation.messages.last.body), length: 100, separator: ' ', omission: '... ') - Donec id elit non mi porta. + %a.list-group-item.list-group-item-action{href: conversation_path(conversation)} + .text-right.float-right + - conversation.recipients.each do |member| + - if member != current_member + .member-chip + = image_tag(avatar_uri(member, 100), alt: '', height: 50, width: 50) + = member + %h5.mb-2.h5 + - if conversation.receipts_for(current_member).last.is_unread? + = icon 'far', 'envelope' + - else + = icon 'far', 'envelope-open' + %strong= conversation.subject + %small + #{time_ago_in_words conversation.messages.last.created_at} ago + %span.text-muted= conversation.messages.last.created_at + %small= truncate(strip_tags(conversation.messages.last.body), length: 500, separator: ' ', omission: '... ') + .col-md-1 + = link_to delete_icon, conversation_path(conversation), class: 'btn text-danger' - unless @conversations.empty? = will_paginate @conversations diff --git a/spec/features/conversations/index_spec.rb b/spec/features/conversations/index_spec.rb index 72a75d13f..35f1107de 100644 --- a/spec/features/conversations/index_spec.rb +++ b/spec/features/conversations/index_spec.rb @@ -18,20 +18,7 @@ describe "Notifications", :js do it { expect(page).to have_content 'something i want to say' } it { Percy.snapshot(page, name: 'conversations#index') } - describe 'view conversation thread' do - before { click_link 'something i want to say' } - - it { expect(page).to have_content 'this is the body' } - it { expect(page).to have_link sender.login_name } - it { Percy.snapshot(page, name: 'conversations#show') } - - describe 'Replying to the conversation' do - before do - fill_in :body, with: 'i like this too' - click_button 'Send' - end - it { expect(page).to have_content "i like this too" } - end + describe 'deleting' do end end end diff --git a/spec/features/conversations/show_spec.rb b/spec/features/conversations/show_spec.rb new file mode 100644 index 000000000..8be150c0c --- /dev/null +++ b/spec/features/conversations/show_spec.rb @@ -0,0 +1,32 @@ +require 'rails_helper' + +describe "Notifications", :js do + let(:sender) { create :member } + let(:recipient) { create :member, login_name: 'beyonce' } + + before do + sender.send_message(recipient, "this is the body", "something i want to say") + login_as recipient + end + + describe 'view conversation thread' do + before do + visit root_path + click_link 'Your Stuff' + click_link 'Inbox' + click_link 'something i want to say' + end + + it { expect(page).to have_content 'this is the body' } + it { expect(page).to have_link sender.login_name } + it { Percy.snapshot(page, name: 'conversations#show') } + + describe 'Replying to the conversation' do + before do + fill_in :body, with: 'i like this too' + click_button 'Send' + end + it { expect(page).to have_content "i like this too" } + end + end +end diff --git a/spec/features/notifications_spec.rb b/spec/features/notifications_spec.rb deleted file mode 100644 index dc149c7d9..000000000 --- a/spec/features/notifications_spec.rb +++ /dev/null @@ -1,62 +0,0 @@ -require 'rails_helper' - -describe "Notifications", :js do - let(:sender) { create :member } - let(:recipient) { create :member, login_name: 'beyonce' } - - context "On existing notification" do - let!(:notification) do - create :notification, - sender: sender, - recipient: recipient, - body: "Notification body", - post_id: nil - end - - before do - login_as recipient - visit root_path - click_link 'Your Stuff' - Percy.snapshot(page, name: "notification menu") - visit notification_path(notification) - Percy.snapshot(page, name: "notifications#show") - end - - it "Replying to the notification" do - click_link "Reply" - expect(page).to have_content "Notification body" - Percy.snapshot(page, name: 'Replying to notification') - - fill_in 'notification_body', with: "Response body" - Percy.snapshot(page, name: "notifications#new") - click_button "Send" - - expect(page).to have_content "Message was successfully sent" - end - end - - describe 'pagination' do - before do - FactoryBot.create_list :notification, 34, recipient: recipient - login_as recipient - visit notifications_path - end - - it do - Percy.snapshot(page, name: "notifications#index") - end - - it 'has page navigation' do - expect(page).to have_selector 'a[rel="next"]' - end - - it 'paginates at 30 notifications per page' do - expect(page).to have_selector '.message', count: 30 - end - - it 'navigates pages' do - first('a[rel="next"]').click - expect(page).to have_selector '.message', count: 4 - end - end -end From cafbfb349fdd5865dac98e0f1ad01b2624606c4d Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 7 Aug 2019 22:18:24 +1200 Subject: [PATCH 079/151] Delete and restore buttons --- app/controllers/conversations_controller.rb | 6 +-- app/views/conversations/index.haml | 50 ++++++++++++--------- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index 4744a2abc..8da180b54 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -41,9 +41,9 @@ class ConversationsController < ApplicationController def set_box @boxes = { - 'inbox' => mailbox.inbox.size, - 'sent' => mailbox.sentbox.size, - 'trash' => mailbox.trash.size + 'inbox' => { 'total' => mailbox.inbox.size, 'unread' => 0}, + 'sent' => { 'total' => mailbox.sentbox.size, 'unread' => 0}, + 'trash' => { 'total' => mailbox.trash.size, 'unread' => 0} } @box = if params[:box].blank? || !@boxes.keys.include?(params[:box]) 'inbox' diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index d6a2e5885..e2e79dbe2 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -11,33 +11,41 @@ = will_paginate @conversations .row .col-md-2.list-group - - @boxes.each do |box_name, item_count| + - @boxes.each do |box_name, counts| = link_to conversations_path(box: box_name), class: "nav-link list-group-item d-flex justify-content-between #{box_name == @box ? 'active' : ''} #{box_name}" do = icon 'fas', box_name = box_name - %span.badge.badge-primary.badge-pill= item_count + - if counts['unread'].positive? + %span.badge.badge-primary.badge-pill=counts['unread'] .col-md-10 .list-group - @conversations.each do |conversation| - %a.list-group-item.list-group-item-action{href: conversation_path(conversation)} - .text-right.float-right - - conversation.recipients.each do |member| - - if member != current_member - .member-chip - = image_tag(avatar_uri(member, 100), alt: '', height: 50, width: 50) - = member - %h5.mb-2.h5 - - if conversation.receipts_for(current_member).last.is_unread? - = icon 'far', 'envelope' - - else - = icon 'far', 'envelope-open' - %strong= conversation.subject - %small - #{time_ago_in_words conversation.messages.last.created_at} ago - %span.text-muted= conversation.messages.last.created_at - %small= truncate(strip_tags(conversation.messages.last.body), length: 500, separator: ' ', omission: '... ') - .col-md-1 - = link_to delete_icon, conversation_path(conversation), class: 'btn text-danger' + .list-group-item + .row + .col-md-1 + - if @box == 'trash' + = link_to conversation_path(conversation, box: @box), method: :put do + = icon 'fas', 'trash-restore' + - else + = link_to delete_icon, conversation_path(conversation, box: @box), method: :delete, class: 'text-danger' + .col-md-11 + .text-right.float-right + - conversation.recipients.each do |member| + - if member != current_member + .member-chip + = image_tag(avatar_uri(member, 100), alt: '', height: 50, width: 50) + = member + %h5.mb-2.h5 + %a{href: conversation_path(conversation)} + - if conversation.receipts_for(current_member).last.is_unread? + = icon 'far', 'envelope' + - else + = icon 'far', 'envelope-open' + %strong= conversation.subject + %small + #{time_ago_in_words conversation.messages.last.created_at} ago + %span.text-muted= conversation.messages.last.created_at + %small= truncate(strip_tags(conversation.messages.last.body), length: 150, separator: ' ', omission: '... ') - unless @conversations.empty? = will_paginate @conversations From dc59b487ca23296ab0b8aaae8768e09aad021f6f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 7 Aug 2019 22:27:01 +1200 Subject: [PATCH 080/151] tests for restoring conversations --- app/views/conversations/index.haml | 4 ++-- spec/features/conversations/index_spec.rb | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index e2e79dbe2..19f4fe172 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -25,10 +25,10 @@ .row .col-md-1 - if @box == 'trash' - = link_to conversation_path(conversation, box: @box), method: :put do + = link_to conversation_path(conversation, box: @box), method: :put, class: 'restore' do = icon 'fas', 'trash-restore' - else - = link_to delete_icon, conversation_path(conversation, box: @box), method: :delete, class: 'text-danger' + = link_to delete_icon, conversation_path(conversation, box: @box), method: :delete, class: 'delete text-danger' .col-md-11 .text-right.float-right - conversation.recipients.each do |member| diff --git a/spec/features/conversations/index_spec.rb b/spec/features/conversations/index_spec.rb index 35f1107de..a4af6e257 100644 --- a/spec/features/conversations/index_spec.rb +++ b/spec/features/conversations/index_spec.rb @@ -19,6 +19,24 @@ describe "Notifications", :js do it { Percy.snapshot(page, name: 'conversations#index') } describe 'deleting' do + before do + # delete button + click_link class: 'delete' + end + + describe 'view trash' do + before { click_link 'trash' } + it { expect(page).to have_content 'something i want to say' } + describe 'restore conversation' do + before { click_link class: 'restore' } + it { expect(page).not_to have_content 'something i want to say' } + + describe 'conversation was restored' do + before { click_link 'inbox' } + it { expect(page).to have_content 'something i want to say' } + end + end + end end end end From 78852e14c9c5382f7c12a2cd3491912f2568431c Mon Sep 17 00:00:00 2001 From: codefactor-io Date: Wed, 7 Aug 2019 10:32:24 +0000 Subject: [PATCH 081/151] [CodeFactor] Apply fixes --- app/controllers/conversations_controller.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index 8da180b54..ae6dee1a0 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -41,9 +41,9 @@ class ConversationsController < ApplicationController def set_box @boxes = { - 'inbox' => { 'total' => mailbox.inbox.size, 'unread' => 0}, - 'sent' => { 'total' => mailbox.sentbox.size, 'unread' => 0}, - 'trash' => { 'total' => mailbox.trash.size, 'unread' => 0} + 'inbox' => { 'total' => mailbox.inbox.size, 'unread' => 0 }, + 'sent' => { 'total' => mailbox.sentbox.size, 'unread' => 0 }, + 'trash' => { 'total' => mailbox.trash.size, 'unread' => 0 } } @box = if params[:box].blank? || !@boxes.keys.include?(params[:box]) 'inbox' From 83322becb2fbec917692373102843d70c2614f6f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 7 Aug 2019 22:33:01 +1200 Subject: [PATCH 082/151] Use guard clause --- app/controllers/conversations_controller.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index 8da180b54..3ff476b6b 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -54,9 +54,8 @@ class ConversationsController < ApplicationController def check_current_subject_in_conversation @conversation = Mailboxer::Conversation.find_by(id: params[:id]) - if @conversation.nil? || !@conversation.is_participant?(current_member) - redirect_to conversations_path(box: box) - return - end + return unless @conversation.nil? || !@conversation.is_participant?(current_member) + redirect_to conversations_path(box: box) + return end end From 2f0e3876462c7e57593bc5a28bb7f80fb5bf7490 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 7 Aug 2019 22:33:39 +1200 Subject: [PATCH 083/151] rubocop lint --- app/controllers/conversations_controller.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index 3ff476b6b..9d0e23386 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -41,9 +41,9 @@ class ConversationsController < ApplicationController def set_box @boxes = { - 'inbox' => { 'total' => mailbox.inbox.size, 'unread' => 0}, - 'sent' => { 'total' => mailbox.sentbox.size, 'unread' => 0}, - 'trash' => { 'total' => mailbox.trash.size, 'unread' => 0} + 'inbox' => { 'total' => mailbox.inbox.size, 'unread' => 0 }, + 'sent' => { 'total' => mailbox.sentbox.size, 'unread' => 0 }, + 'trash' => { 'total' => mailbox.trash.size, 'unread' => 0 } } @box = if params[:box].blank? || !@boxes.keys.include?(params[:box]) 'inbox' @@ -55,7 +55,8 @@ class ConversationsController < ApplicationController def check_current_subject_in_conversation @conversation = Mailboxer::Conversation.find_by(id: params[:id]) return unless @conversation.nil? || !@conversation.is_participant?(current_member) + redirect_to conversations_path(box: box) - return + nil end end From 2f5f8985e728a29bca8b999e3d6baf7ddcffa420 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 7 Aug 2019 22:34:41 +1200 Subject: [PATCH 084/151] lint --- app/assets/stylesheets/_members.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/_members.scss b/app/assets/stylesheets/_members.scss index cfa145c1d..41dcef6b0 100644 --- a/app/assets/stylesheets/_members.scss +++ b/app/assets/stylesheets/_members.scss @@ -21,7 +21,7 @@ background-color: lighten($green, 30%); border-radius: 25px; display: inline-block; - font-size: 1em; + font-size: 1em; height: 30px; line-height: 30px; padding: 0 25px; From 909d9b34ef96fe6dfe51dd009c59b62e8ce0ab2a Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 7 Aug 2019 22:34:53 +1200 Subject: [PATCH 085/151] lint --- app/assets/stylesheets/_members.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/assets/stylesheets/_members.scss b/app/assets/stylesheets/_members.scss index 41dcef6b0..758aff496 100644 --- a/app/assets/stylesheets/_members.scss +++ b/app/assets/stylesheets/_members.scss @@ -25,9 +25,11 @@ height: 30px; line-height: 30px; padding: 0 25px; + a { color: $black; } + img { border-radius: 50%; float: left; From 21b63d9b620ed5dbe200279eef8fc5516b00efc6 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 7 Aug 2019 22:36:43 +1200 Subject: [PATCH 086/151] lint --- app/controllers/conversations_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index 9d0e23386..82a24a2b9 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -49,7 +49,7 @@ class ConversationsController < ApplicationController 'inbox' else params[:box] - end + end end def check_current_subject_in_conversation From 12c1002dc662daba64d1ffd0042461671d0b81ef Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 8 Aug 2019 09:31:53 +1200 Subject: [PATCH 087/151] Removing unused notifications code --- app/helpers/notifications_helper.rb | 11 ----- app/mailers/notifier.rb | 56 ----------------------- spec/helpers/notifications_helper_spec.rb | 24 ---------- 3 files changed, 91 deletions(-) delete mode 100644 app/helpers/notifications_helper.rb delete mode 100644 app/mailers/notifier.rb delete mode 100644 spec/helpers/notifications_helper_spec.rb diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb deleted file mode 100644 index 2e551b3cb..000000000 --- a/app/helpers/notifications_helper.rb +++ /dev/null @@ -1,11 +0,0 @@ -module NotificationsHelper - def reply_link(notification) - if notification.post - # comment on the post in question - new_comment_url(post_id: notification.post.id) - else - # by default, reply link sends a PM in return - notification_reply_url(notification) - end - end -end diff --git a/app/mailers/notifier.rb b/app/mailers/notifier.rb deleted file mode 100644 index 0386450f1..000000000 --- a/app/mailers/notifier.rb +++ /dev/null @@ -1,56 +0,0 @@ -class Notifier < ApplicationMailer - include NotificationsHelper - default from: "Growstuff <#{ENV['GROWSTUFF_EMAIL']}>" - - def verifier - unless ENV['RAILS_SECRET_TOKEN'] - raise "RAILS_SECRET_TOKEN environment variable"\ - "not set - have you created config/application.yml?" - end - - ActiveSupport::MessageVerifier.new(ENV['RAILS_SECRET_TOKEN']) - end - - def notify(notification) - @notification = notification - @reply_link = reply_link(@notification) - - # Encrypting - message = { member_id: @notification.recipient.id, type: :send_notification_email } - @signed_message = verifier.generate(message) - - mail(to: @notification.recipient.email, - subject: @notification.subject) - end - - def planting_reminder(member) - @member = member - - @plantings = @member.plantings.order(planted_at: :desc).first(5) - @harvests = @member.harvests.order(harvested_at: :desc).first(5) - - # Encrypting - message = { member_id: @member.id, type: :send_planting_reminder } - @signed_message = verifier.generate(message) - - mail(to: @member.email, subject: "What have you planted lately?") if @member.send_planting_reminder - end - - def new_crop_request(member, request) - @member = member - @request = request - mail(to: @member.email, subject: "#{@request.requester.login_name} has requested #{@request.name} as a new crop") - end - - def crop_request_approved(member, crop) - @member = member - @crop = crop - mail(to: @member.email, subject: "#{crop.name.capitalize} has been approved") - end - - def crop_request_rejected(member, crop) - @member = member - @crop = crop - mail(to: @member.email, subject: "#{crop.name.capitalize} has been rejected") - end -end diff --git a/spec/helpers/notifications_helper_spec.rb b/spec/helpers/notifications_helper_spec.rb deleted file mode 100644 index 68262fb9e..000000000 --- a/spec/helpers/notifications_helper_spec.rb +++ /dev/null @@ -1,24 +0,0 @@ -require 'rails_helper' - -describe NotificationsHelper do - describe "reply_link" do - let(:member) { FactoryBot.create(:member) } - - it "replies to PMs with PMs" do - notification = FactoryBot.create(:notification, recipient_id: member.id, post_id: nil) - link = helper.reply_link(notification) - link.should_not be_nil - link.should eq notification_reply_url(notification) - end - - it "replies to post comments with post comments" do - notification = FactoryBot.create(:notification, recipient_id: member.id) - - link = helper.reply_link(notification) - link.should_not be_nil - link.should eq new_comment_url( - post_id: notification.post.id - ) - end - end -end From 548bc1581abac6f4314cc5078f08069496e53990 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 8 Aug 2019 10:21:39 +1200 Subject: [PATCH 088/151] Removing notification mailer spec --- spec/mailers/notifier_spec.rb | 121 ---------------------------------- 1 file changed, 121 deletions(-) delete mode 100644 spec/mailers/notifier_spec.rb diff --git a/spec/mailers/notifier_spec.rb b/spec/mailers/notifier_spec.rb deleted file mode 100644 index 791137c59..000000000 --- a/spec/mailers/notifier_spec.rb +++ /dev/null @@ -1,121 +0,0 @@ -require "rails_helper" - -describe Notifier do - describe "notifications" do - let(:notification) { FactoryBot.create(:notification) } - let(:mail) { Notifier.notify(notification) } - - it 'sets the subject correctly' do - mail.subject.should == notification.subject - end - - it 'comes from noreply@test.growstuff.org' do - mail.from.should == ['noreply@test.growstuff.org'] - end - - it 'sends the mail to the recipient of the notification' do - mail.to.should == [notification.recipient.email] - end - end - - describe "planting reminders" do - let(:member) { FactoryBot.create(:member) } - let(:mail) { Notifier.planting_reminder(member) } - - it 'sets the subject correctly' do - mail.subject.should == "What have you planted lately?" - end - - it 'comes from noreply@test.growstuff.org' do - mail.from.should == ['noreply@test.growstuff.org'] - end - - it 'sends the mail to the recipient of the notification' do - mail.to.should == [member.email] - end - - it 'includes the new planting URL' do - mail.body.encoded.should match new_planting_path - end - - it 'includes the new harvest URL' do - mail.body.encoded.should match new_harvest_path - end - end - - describe "new crop request" do - let(:member) { FactoryBot.create(:crop_wrangling_member) } - let(:crop) { FactoryBot.create(:crop_request) } - let(:mail) { Notifier.new_crop_request(member, crop) } - - it 'sets the subject correctly' do - mail.subject.should == "#{crop.requester.login_name} has requested Ultra berry as a new crop" - end - - it 'comes from noreply@test.growstuff.org' do - mail.from.should == ['noreply@test.growstuff.org'] - end - - it 'sends the mail to the recipient of the notification' do - mail.to.should == [member.email] - end - - it 'includes the requested crop URL' do - mail.body.encoded.should match crop_url(crop) - end - end - - describe "crop approved" do - let(:member) { FactoryBot.create(:member) } - let(:crop) { FactoryBot.create(:crop) } - let(:mail) { Notifier.crop_request_approved(member, crop) } - - it 'sets the subject correctly' do - expect(mail.subject).to eq "Magic bean has been approved" - end - - it 'comes from noreply@test.growstuff.org' do - expect(mail.from).to eq ['noreply@test.growstuff.org'] - end - - it 'sends the mail to the recipient of the notification' do - expect(mail.to).to eq [member.email] - end - - it 'includes the approved crop URL' do - expect(mail.body.encoded).to match crop_url(crop) - end - - it 'includes links to plant, harvest and stash seeds for the new crop' do - expect(mail.body.encoded).to match "#{new_planting_url}\\?crop_id=#{crop.id}" - expect(mail.body.encoded).to match "#{new_harvest_url}\\?crop_id=#{crop.id}" - expect(mail.body.encoded).to match "#{new_seed_url}\\?crop_id=#{crop.id}" - end - end - - describe "crop rejected" do - let(:member) { FactoryBot.create(:member) } - let(:crop) { FactoryBot.create(:rejected_crop) } - let(:mail) { Notifier.crop_request_rejected(member, crop) } - - it 'sets the subject correctly' do - expect(mail.subject).to eq "Fail bean has been rejected" - end - - it 'comes from noreply@test.growstuff.org' do - expect(mail.from).to eq ['noreply@test.growstuff.org'] - end - - it 'sends the mail to the recipient of the notification' do - expect(mail.to).to eq [member.email] - end - - it 'includes the rejected crop URL' do - expect(mail.body.encoded).to match crop_url(crop) - end - - it 'includes the reason for rejection' do - expect(mail.body.encoded).to match "Totally fake" - end - end -end From 1dfbecfac00b2eeaa740c3534bab9242cce91278 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Fri, 9 Aug 2019 22:32:36 +1200 Subject: [PATCH 089/151] Don't re-look up planting --- app/controllers/plantings_controller.rb | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app/controllers/plantings_controller.rb b/app/controllers/plantings_controller.rb index d6d3a164e..1bbbefc93 100644 --- a/app/controllers/plantings_controller.rb +++ b/app/controllers/plantings_controller.rb @@ -31,12 +31,7 @@ class PlantingsController < ApplicationController end def show - @planting = Planting.includes(:owner, :crop, :garden, :photos) - .friendly - .find(params[:id]) - @photos = @planting.photos - .includes(:owner) - .order(date_taken: :desc) + @photos = @planting.photos.includes(:owner).order(date_taken: :desc) respond_with @planting end From c29f0c15ee2178bb33211a8c9d1024146436713c Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 10 Aug 2019 10:39:40 +1200 Subject: [PATCH 090/151] don't join to owners when fetching gardens discard isn't the same --- app/controllers/gardens_controller.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/gardens_controller.rb b/app/controllers/gardens_controller.rb index 791c6d7b4..f9037923a 100644 --- a/app/controllers/gardens_controller.rb +++ b/app/controllers/gardens_controller.rb @@ -14,7 +14,6 @@ class GardensController < ApplicationController @gardens = @gardens.active unless @show_all @gardens = @gardens.where(owner: @owner) if @owner.present? @gardens = @gardens.joins(:owner).order(:name).paginate(page: params[:page]) - @gardens = @gardens.includes(:owner, plantings: [:owner, crop: :parent]) respond_with(@gardens) end From c137d5e285ac4dcd264aa6e9c85c6a6f30cb8347 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 10 Aug 2019 10:48:48 +1200 Subject: [PATCH 091/151] update signin spec to use messages and converations --- spec/features/signin_spec.rb | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/spec/features/signin_spec.rb b/spec/features/signin_spec.rb index 4be647588..dd7526549 100644 --- a/spec/features/signin_spec.rb +++ b/spec/features/signin_spec.rb @@ -33,9 +33,12 @@ describe "signin", js: true do expect(current_path).to eq root_path end - it "redirect to signin page for if not authenticated to view notification" do - visit notification_path(notification) - expect(current_path).to eq new_member_session_path + describe "redirect to signin page for if not authenticated to view conversations" do + before do + conversation = member.send_message(recipient, 'hey there', 'kiaora') + visit conversation_path(conversation) + end + it { expect(current_path).to eq new_member_session_path } end shared_examples "redirects to what you were trying to do" do @@ -55,11 +58,11 @@ describe "signin", js: true do end end - it "after signin, redirect to new notifications page" do - visit new_notification_path(recipient_id: recipient.id) + it "after signin, redirect to new message page" do + visit new_message_path(recipient_id: recipient.id) expect(current_path).to eq new_member_session_path login - expect(current_path).to eq new_notification_path + expect(current_path).to eq new_message_path end it "after crop wrangler signs in and crops await wrangling, show alert" do From 0a919d8599ba8ffa3e654e6f3db374dc68144ba8 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 10 Aug 2019 10:50:57 +1200 Subject: [PATCH 092/151] Remove notifications spec --- spec/requests/notifications_spec.rb | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 spec/requests/notifications_spec.rb diff --git a/spec/requests/notifications_spec.rb b/spec/requests/notifications_spec.rb deleted file mode 100644 index 85afbdd9f..000000000 --- a/spec/requests/notifications_spec.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'rails_helper' - -describe "Notifications" do - describe "GET /notifications" do - it "works! (now write some real specs)" do - get notifications_path - # can't see notifications because not logged in - # therefore redirect to homepage - response.status.should be(302) - end - end -end From 86540c3352dae59256718e84aff0cc9e069e1309 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 10 Aug 2019 10:52:49 +1200 Subject: [PATCH 093/151] Removed feature plantings code and spec because it's not used --- app/models/garden.rb | 16 ---------------- spec/models/garden_spec.rb | 38 -------------------------------------- 2 files changed, 54 deletions(-) diff --git a/app/models/garden.rb b/app/models/garden.rb index c16dc396c..0131242f9 100644 --- a/app/models/garden.rb +++ b/app/models/garden.rb @@ -58,22 +58,6 @@ class Garden < ApplicationRecord "#{owner.login_name}-#{name}".downcase.tr(' ', '-') end - # featured plantings returns the most recent 4 plantings for a garden, - # choosing them so that no crop is repeated. - def featured_plantings - unique_plantings = [] - seen_crops = [] - - plantings.includes(:garden, :crop, :owner, :harvests).order(created_at: :desc).each do |p| - unless seen_crops.include?(p.crop) - unique_plantings.push(p) - seen_crops.push(p.crop) - end - end - - unique_plantings[0..3] - end - def to_s name end diff --git a/spec/models/garden_spec.rb b/spec/models/garden_spec.rb index c709794a3..522a9bfc1 100644 --- a/spec/models/garden_spec.rb +++ b/spec/models/garden_spec.rb @@ -56,44 +56,6 @@ describe Garden do garden.to_s.should == garden.name end - context "featured plantings" do - let(:tomato) { FactoryBot.create(:tomato) } - let(:maize) { FactoryBot.create(:maize) } - let(:chard) { FactoryBot.create(:chard) } - let(:apple) { FactoryBot.create(:apple) } - let(:pear) { FactoryBot.create(:pear) } - let(:walnut) { FactoryBot.create(:walnut) } - - it "fetches < 4 featured plantings if insufficient exist" do - @p1 = FactoryBot.create(:planting, crop: tomato, garden: garden, owner: garden.owner) - @p2 = FactoryBot.create(:planting, crop: maize, garden: garden, owner: garden.owner) - - expect(garden.featured_plantings).to eq [@p2, @p1] - end - - it "fetches most recent 4 featured plantings" do - @p1 = FactoryBot.create(:planting, crop: tomato, garden: garden, owner: garden.owner) - @p2 = FactoryBot.create(:planting, crop: maize, garden: garden, owner: garden.owner) - @p3 = FactoryBot.create(:planting, crop: chard, garden: garden, owner: garden.owner) - @p4 = FactoryBot.create(:planting, crop: apple, garden: garden, owner: garden.owner) - @p5 = FactoryBot.create(:planting, crop: walnut, garden: garden, owner: garden.owner) - - expect(garden.featured_plantings).to eq [@p5, @p4, @p3, @p2] - end - - it "skips repeated plantings" do - @p1 = FactoryBot.create(:planting, crop: tomato, garden: garden, owner: garden.owner) - @p2 = FactoryBot.create(:planting, crop: maize, garden: garden, owner: garden.owner) - @p3 = FactoryBot.create(:planting, crop: chard, garden: garden, owner: garden.owner) - @p4 = FactoryBot.create(:planting, crop: apple, garden: garden, owner: garden.owner) - @p5 = FactoryBot.create(:planting, crop: walnut, garden: garden, owner: garden.owner) - @p6 = FactoryBot.create(:planting, crop: apple, garden: garden, owner: garden.owner) - @p7 = FactoryBot.create(:planting, crop: pear, garden: garden, owner: garden.owner) - - expect(garden.featured_plantings).to eq [@p7, @p6, @p5, @p3] - end - end - it "destroys plantings when deleted" do garden = FactoryBot.create(:garden, owner: owner) @planting1 = FactoryBot.create(:planting, garden: garden, owner: garden.owner) From 843e15a107d7dcbe514e77e18a9ce7cc3fd08367 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 10 Aug 2019 10:53:20 +1200 Subject: [PATCH 094/151] Removed notification view spec --- spec/views/notifier/notify.html.haml_spec.rb | 35 -------------------- 1 file changed, 35 deletions(-) delete mode 100644 spec/views/notifier/notify.html.haml_spec.rb diff --git a/spec/views/notifier/notify.html.haml_spec.rb b/spec/views/notifier/notify.html.haml_spec.rb deleted file mode 100644 index 39b52e603..000000000 --- a/spec/views/notifier/notify.html.haml_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -require 'rails_helper' - -describe 'notifier/notify.html.haml', type: "view" do - before do - @notification = FactoryBot.create(:notification) - @reply_link = "http://example.com" - @signed_message = "EncryptedMessage" - assign(:reply_link, @reply_link) - render - end - - it 'says that you have a message' do - rendered.should have_content 'You have received a message' - end - - it 'includes notification metadata' do - rendered.should have_content @notification.sender.login_name - rendered.should have_content @notification.post.subject - end - - it 'includes a reply link' do - assert_select "a[href='#{@reply_link}']", text: /Reply/ - end - - it 'contains a link to your inbox' do - assert_select "a[href*='notifications']" - end - - it 'has fully qualified URLs' do - # lots of lovely fully qualified URLs - assert_select "a[href^='http']", minimum: 4 - # no relative URLs starting with / - assert_select "a[href^='/']", count: 0 - end -end From 5226eadfd8e7c19f3c6211659ad1770e4707366e Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 10 Aug 2019 11:07:12 +1200 Subject: [PATCH 095/151] fix crop join to members --- app/models/crop.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index 12eb01975..c8a9227a3 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -17,7 +17,7 @@ class Crop < ApplicationRecord has_many :harvests, dependent: :destroy has_many :photo_associations, dependent: :destroy has_many :photos, through: :photo_associations - has_many :plant_parts, -> { distinct.order("plant_parts.name") }, through: :harvests + has_many :plant_parts, -> { joins("INNER JOIN members ON members.id = owner_id").distinct.order("plant_parts.name") }, through: :harvests belongs_to :creator, class_name: 'Member', optional: true, inverse_of: :created_crops belongs_to :requester, class_name: 'Member', optional: true, inverse_of: :requested_crops belongs_to :parent, class_name: 'Crop', optional: true, inverse_of: :varieties From d4644ccdf8f54c7cad041de5ac74b86c5e57cbfc Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 10 Aug 2019 11:37:52 +1200 Subject: [PATCH 096/151] Added join to members to fix error caused by discard gem --- app/models/crop.rb | 3 ++- app/models/plant_part.rb | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index c8a9227a3..36ec4e832 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -17,7 +17,7 @@ class Crop < ApplicationRecord has_many :harvests, dependent: :destroy has_many :photo_associations, dependent: :destroy has_many :photos, through: :photo_associations - has_many :plant_parts, -> { joins("INNER JOIN members ON members.id = owner_id").distinct.order("plant_parts.name") }, through: :harvests + has_many :plant_parts, -> { joins_members.distinct.order("plant_parts.name") }, through: :harvests belongs_to :creator, class_name: 'Member', optional: true, inverse_of: :created_crops belongs_to :requester, class_name: 'Member', optional: true, inverse_of: :requested_crops belongs_to :parent, class_name: 'Crop', optional: true, inverse_of: :varieties @@ -34,6 +34,7 @@ class Crop < ApplicationRecord scope :rejected, -> { where(approval_status: "rejected") } scope :interesting, -> { approved.has_photos } scope :has_photos, -> { includes(:photos).where.not(photos: { id: nil }) } + scope :joins_members, -> { joins("INNER JOIN members ON members.id = harvests.owner_id") } # Special scope to control if it's in the search index scope :search_import, -> { approved } diff --git a/app/models/plant_part.rb b/app/models/plant_part.rb index 7af288706..34d39eb06 100644 --- a/app/models/plant_part.rb +++ b/app/models/plant_part.rb @@ -3,10 +3,12 @@ class PlantPart < ApplicationRecord friendly_id :name, use: %i(slugged finders) has_many :harvests, dependent: :destroy - has_many :crops, -> { distinct }, through: :harvests + has_many :crops, -> { joins_members.distinct }, through: :harvests validates :name, presence: true, uniqueness: true + scope :joins_members, -> { joins("INNER JOIN members ON members.id = harvests.owner_id") } + def to_s name end From b3807100d11d6961b4a5cf943332f8088a8c2447 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 10 Aug 2019 11:47:45 +1200 Subject: [PATCH 097/151] fixes email sending --- app/models/member.rb | 8 ++++++++ app/models/notification.rb | 4 ++-- config/initializers/mailboxer.rb | 6 +++--- spec/models/notification_spec.rb | 4 ++-- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/app/models/member.rb b/app/models/member.rb index 0183ab840..2b988a3e7 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -124,6 +124,14 @@ class Member < ApplicationRecord login_name end + def mailboxer_email(messageable) + if send_notification_email + email + else + false + end + end + def role?(role_sym) roles.any? { |r| r.name.gsub(/\s+/, "_").underscore.to_sym == role_sym } end diff --git a/app/models/notification.rb b/app/models/notification.rb index de9d01d8d..096a0fefa 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -9,7 +9,7 @@ class Notification < ApplicationRecord scope :by_recipient, ->(recipient) { where(recipient_id: recipient) } before_create :replace_blank_subject - after_create :create_mailboxer_message + after_create :send_message def self.unread_count unread.size @@ -19,7 +19,7 @@ class Notification < ApplicationRecord self.subject = "(no subject)" if subject.nil? || subject =~ /^\s*$/ end - def create_mailboxer_message + def send_message sender.send_message(recipient, body, subject) end end diff --git a/config/initializers/mailboxer.rb b/config/initializers/mailboxer.rb index 194e5261e..4392f70c2 100644 --- a/config/initializers/mailboxer.rb +++ b/config/initializers/mailboxer.rb @@ -1,13 +1,13 @@ Mailboxer.setup do |config| # Configures if your application uses or not email sending for Notifications and Messages - config.uses_emails = false + config.uses_emails = true # Configures the default from for emails sent for Messages and Notifications config.default_from = "no-reply@growstuff.org" # Configures the methods needed by mailboxer - config.email_method = :email - config.name_method = :login_name + # config.email_method = :email + # config.name_method = :login_name config.notify_method = :notify # Configures if you use or not a search engine and which one you are using diff --git a/spec/models/notification_spec.rb b/spec/models/notification_spec.rb index 330a97003..5c9dc4883 100644 --- a/spec/models/notification_spec.rb +++ b/spec/models/notification_spec.rb @@ -32,12 +32,12 @@ describe Notification do it "sends email if asked" do @notification2 = FactoryBot.create(:notification) - @notification2.send_email + @notification2.send_message expect(ActionMailer::Base.deliveries.last&.to).to eq [@notification2.recipient.email] end it "doesn't send email to people who don't want it" do - FactoryBot.create(:no_email_notification).send_email + FactoryBot.create(:no_email_notification).send_message expect(ActionMailer::Base.deliveries.last&.to).not_to eq [notification.recipient.email] end From 1872bff3465634dcebefa005ba72f69c97c9ca43 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 10 Aug 2019 12:09:23 +1200 Subject: [PATCH 098/151] Restore notifier not hooked up to mailboxer yet --- app/mailers/notifier.rb | 56 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 app/mailers/notifier.rb diff --git a/app/mailers/notifier.rb b/app/mailers/notifier.rb new file mode 100644 index 000000000..e39ced825 --- /dev/null +++ b/app/mailers/notifier.rb @@ -0,0 +1,56 @@ +class Notifier < ApplicationMailer + # include NotificationsHelper + default from: "Growstuff <#{ENV['GROWSTUFF_EMAIL']}>" + + def verifier + unless ENV['RAILS_SECRET_TOKEN'] + raise "RAILS_SECRET_TOKEN environment variable"\ + "not set - have you created config/application.yml?" + end + + ActiveSupport::MessageVerifier.new(ENV['RAILS_SECRET_TOKEN']) + end + + def notify(notification) + @notification = notification + @reply_link = reply_link(@notification) + + # Encrypting + message = { member_id: @notification.recipient.id, type: :send_notification_email } + @signed_message = verifier.generate(message) + + mail(to: @notification.recipient.email, + subject: @notification.subject) + end + + def planting_reminder(member) + @member = member + + @plantings = @member.plantings.order(planted_at: :desc).first(5) + @harvests = @member.harvests.order(harvested_at: :desc).first(5) + + # Encrypting + message = { member_id: @member.id, type: :send_planting_reminder } + @signed_message = verifier.generate(message) + + mail(to: @member.email, subject: "What have you planted lately?") if @member.send_planting_reminder + end + + def new_crop_request(member, request) + @member = member + @request = request + mail(to: @member.email, subject: "#{@request.requester.login_name} has requested #{@request.name} as a new crop") + end + + def crop_request_approved(member, crop) + @member = member + @crop = crop + mail(to: @member.email, subject: "#{crop.name.capitalize} has been approved") + end + + def crop_request_rejected(member, crop) + @member = member + @crop = crop + mail(to: @member.email, subject: "#{crop.name.capitalize} has been rejected") + end +end From 82a3cc35a4a83a2bc611fca167e65f7f10f7499f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 10 Aug 2019 15:39:07 +1200 Subject: [PATCH 099/151] Fix member discarding to match specs --- app/controllers/registrations_controller.rb | 4 +++- spec/features/members/deletion_spec.rb | 11 +++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index b9ed73dfe..24a8ee8e8 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -37,9 +37,11 @@ class RegistrationsController < Devise::RegistrationsController end def destroy - if @member.destroy_with_password(params.require(:member)[:current_password]) + if @member.valid_password?(params.require(:member)[:current_password]) + @member.discard redirect_to root_path else + @member.errors.add(:current_password, 'Incorrect password') render "edit" end end diff --git a/spec/features/members/deletion_spec.rb b/spec/features/members/deletion_spec.rb index 7a5ccf273..35326a0c9 100644 --- a/spec/features/members/deletion_spec.rb +++ b/spec/features/members/deletion_spec.rb @@ -41,7 +41,7 @@ describe "member deletion" do click_link 'Edit profile' click_link 'Delete Account' click_button "Delete" - expect(page).to have_content "Current password can't be blank" + expect(page).to have_content "Incorrect password" end it "password must be correct" do @@ -50,7 +50,7 @@ describe "member deletion" do click_link 'Delete Account' fill_in "current_pw_for_delete", with: "wrongpassword" click_button "Delete" - expect(page).to have_content "Current password is invalid" + expect(page).to have_content "Incorrect password" end it "deletes and removes bio" do @@ -87,7 +87,10 @@ describe "member deletion" do end describe 'member exists but is marked deleted' do - it { expect(Member.with_deleted.find(member.id)).to eq member } + subject { Member.all.find(member.id) } + it { expect(subject).to eq member } + it { expect(subject.discarded?).to eq true } + it { expect(Member.kept).not_to include(member) } end it "removes plantings" do @@ -144,7 +147,7 @@ describe "member deletion" do fill_in 'Login', with: member.login_name fill_in 'Password', with: member.password click_button 'Sign in' - expect(page).to have_content 'Invalid Login or password' + expect(page).to have_content 'Your account is not activated' end end end From f676054cd6556d72f539fe3bfdf2e38363846e8b Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 10 Aug 2019 16:09:57 +1200 Subject: [PATCH 100/151] switch to member.discard --- spec/models/member_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 16ad228fb..10ca3f5e6 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -359,7 +359,7 @@ describe 'member' do context "deleted admin member" do let(:member) { FactoryBot.create(:admin_member) } - before { member.destroy } + before { member.discard } context 'crop creator' do let!(:crop) { FactoryBot.create(:crop, creator: member) } From 083d7c09e654ffe70e97abb225e30991df3b473e Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 10 Aug 2019 17:30:24 +1200 Subject: [PATCH 101/151] Migration of notifications to mailboxer, without sending new emails --- app/models/notification.rb | 2 ++ ...190720000625_notifications_to_mailboxer.rb | 24 +++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/app/models/notification.rb b/app/models/notification.rb index 096a0fefa..8a786c8fa 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -4,6 +4,8 @@ class Notification < ApplicationRecord belongs_to :post, optional: true validates :subject, length: { maximum: 255 } + validates :subject, presence: true + validates :body, presence: true scope :unread, -> { where(read: false) } scope :by_recipient, ->(recipient) { where(recipient_id: recipient) } diff --git a/db/migrate/20190720000625_notifications_to_mailboxer.rb b/db/migrate/20190720000625_notifications_to_mailboxer.rb index 9ea60b7d1..513ae1db2 100644 --- a/db/migrate/20190720000625_notifications_to_mailboxer.rb +++ b/db/migrate/20190720000625_notifications_to_mailboxer.rb @@ -1,7 +1,27 @@ class NotificationsToMailboxer < ActiveRecord::Migration[5.2] - def change + def up Notification.all.each do |n| - n.sender.send_message(n.recipient, n.body, n.subject) + next unless n.valid? + + conversation = Mailboxer::ConversationBuilder.new( + subject: n.subject, + created_at: n.created_at, + updated_at: n.updated_at + ).build + + message = Mailboxer::MessageBuilder.new( + sender: n.sender, + conversation: conversation, + recipients: [n.recipient], + body: n.body, + subject: n.subject, + # attachment: attachment, + created_at: n.created_at, + updated_at: n.updated_at + ).build + + conversation.save! + message.save! end end end From 5d7ef7e86162d94880c702e720eb5108ae8324f7 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 10 Aug 2019 17:30:41 +1200 Subject: [PATCH 102/151] rubocop lint --- app/models/crop.rb | 2 +- app/models/member.rb | 2 +- app/models/plant_part.rb | 2 +- config.rb | 4 ++-- spec/views/gardens/show.html.haml_spec.rb | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index 36ec4e832..e0166744d 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -34,7 +34,7 @@ class Crop < ApplicationRecord scope :rejected, -> { where(approval_status: "rejected") } scope :interesting, -> { approved.has_photos } scope :has_photos, -> { includes(:photos).where.not(photos: { id: nil }) } - scope :joins_members, -> { joins("INNER JOIN members ON members.id = harvests.owner_id") } + scope :joins_members, -> { joins("INNER JOIN members ON members.id = harvests.owner_id") } # Special scope to control if it's in the search index scope :search_import, -> { approved } diff --git a/app/models/member.rb b/app/models/member.rb index 2b988a3e7..9891d4e64 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -124,7 +124,7 @@ class Member < ApplicationRecord login_name end - def mailboxer_email(messageable) + def mailboxer_email(_messageable) if send_notification_email email else diff --git a/app/models/plant_part.rb b/app/models/plant_part.rb index 34d39eb06..6fd57bff5 100644 --- a/app/models/plant_part.rb +++ b/app/models/plant_part.rb @@ -7,7 +7,7 @@ class PlantPart < ApplicationRecord validates :name, presence: true, uniqueness: true - scope :joins_members, -> { joins("INNER JOIN members ON members.id = harvests.owner_id") } + scope :joins_members, -> { joins("INNER JOIN members ON members.id = harvests.owner_id") } def to_s name diff --git a/config.rb b/config.rb index acd8ec0eb..e63707f3f 100644 --- a/config.rb +++ b/config.rb @@ -2,8 +2,8 @@ # rubocop:disable Lint/UselessAssignment # Set this to the root of your project when deployed: http_path = "/" -css_dir = "app/assets/stylesheets" -sass_dir = "app/assets/stylesheets" +css_dir = "app/assets/stylesheets" +sass_dir = "app/assets/stylesheets" javascripts_dir = "app/assets/javascripts" images_dir = "app/assets/images" diff --git a/spec/views/gardens/show.html.haml_spec.rb b/spec/views/gardens/show.html.haml_spec.rb index 5fee8fc4e..29841111f 100644 --- a/spec/views/gardens/show.html.haml_spec.rb +++ b/spec/views/gardens/show.html.haml_spec.rb @@ -4,7 +4,7 @@ describe "gardens/show" do before do @owner = FactoryBot.create(:member) controller.stub(:current_user) { @owner } - @garden = FactoryBot.create(:garden, owner: @owner) + @garden = FactoryBot.create(:garden, owner: @owner) @planting = FactoryBot.create(:planting, garden: @garden, owner: @garden.owner) assign(:garden, @garden) assign(:current_plantings, [@planting]) From 2a3563f9fdbf06f660db3f035ff40540350ab212 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 11 Aug 2019 13:37:56 +1200 Subject: [PATCH 103/151] Migration from notifications to mailboxer --- app/models/notification.rb | 31 +++++++++++++++++++ ...190720000625_notifications_to_mailboxer.rb | 27 +++------------- spec/models/notification_spec.rb | 21 +++++++++++++ 3 files changed, 57 insertions(+), 22 deletions(-) diff --git a/app/models/notification.rb b/app/models/notification.rb index 8a786c8fa..65ccb84b8 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -24,4 +24,35 @@ class Notification < ApplicationRecord def send_message sender.send_message(recipient, body, subject) end + + def migrate_to_mailboxer! + conversation = Mailboxer::ConversationBuilder.new( + subject: subject, + created_at: created_at, + updated_at: updated_at + ).build + + message = Mailboxer::MessageBuilder.new( + sender: sender, + conversation: conversation, + recipients: [recipient], + body: body, + subject: subject, + # attachment: attachment, + created_at: created_at, + updated_at: updated_at + ).build + + notification = Mailboxer::NotificationBuilder.new( + recipients: [recipient], + subject: subject, + body: body, + sender: sender + ).build + + conversation.save! + message.save! + notification.save! + notification.deliver(false, false) + end end diff --git a/db/migrate/20190720000625_notifications_to_mailboxer.rb b/db/migrate/20190720000625_notifications_to_mailboxer.rb index 513ae1db2..6e003c44a 100644 --- a/db/migrate/20190720000625_notifications_to_mailboxer.rb +++ b/db/migrate/20190720000625_notifications_to_mailboxer.rb @@ -1,27 +1,10 @@ class NotificationsToMailboxer < ActiveRecord::Migration[5.2] def up - Notification.all.each do |n| - next unless n.valid? - - conversation = Mailboxer::ConversationBuilder.new( - subject: n.subject, - created_at: n.created_at, - updated_at: n.updated_at - ).build - - message = Mailboxer::MessageBuilder.new( - sender: n.sender, - conversation: conversation, - recipients: [n.recipient], - body: n.body, - subject: n.subject, - # attachment: attachment, - created_at: n.created_at, - updated_at: n.updated_at - ).build - - conversation.save! - message.save! + Notification.find_in_batches do |group| + group.each do |n| + next unless n.valid? + n.migrate_to_mailboxer! + end end end end diff --git a/spec/models/notification_spec.rb b/spec/models/notification_spec.rb index 5c9dc4883..745a2fb7d 100644 --- a/spec/models/notification_spec.rb +++ b/spec/models/notification_spec.rb @@ -3,6 +3,27 @@ require 'rails_helper' describe Notification do let(:notification) { FactoryBot.create(:notification) } + describe 'migration to mailboxer' do + let(:body) do + "Hellos + how are you today? + I am fine + + -- me + " + end + let(:sender) { FactoryBot.create :member } + let(:recipient) { FactoryBot.create :member } + let(:notification) do + FactoryBot.create :notification, + subject: 'hello', body: body, + sender: sender, + recipient: recipient + end + before { notification.migrate_to_mailboxer! } + it { expect(recipient.mailbox.inbox.count).to eq 1 } + it { expect(recipient.mailbox.inbox.first.subject).to eq 'hello' } + end it "belongs to a post" do expect(notification.post).to be_an_instance_of Post end From 0d370603b73edc8c1bded46d3eb5e2b2bb06b9bd Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 11 Aug 2019 13:39:00 +1200 Subject: [PATCH 104/151] Rename spec from Notifications to Conversations --- spec/features/conversations/index_spec.rb | 2 +- spec/features/conversations/show_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/features/conversations/index_spec.rb b/spec/features/conversations/index_spec.rb index a4af6e257..850e42236 100644 --- a/spec/features/conversations/index_spec.rb +++ b/spec/features/conversations/index_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' -describe "Notifications", :js do +describe "Conversations", :js do let(:sender) { create :member } let(:recipient) { create :member, login_name: 'beyonce' } diff --git a/spec/features/conversations/show_spec.rb b/spec/features/conversations/show_spec.rb index 8be150c0c..ccf92fb8f 100644 --- a/spec/features/conversations/show_spec.rb +++ b/spec/features/conversations/show_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' -describe "Notifications", :js do +describe "Conversations", :js do let(:sender) { create :member } let(:recipient) { create :member, login_name: 'beyonce' } From 4f74b20565b39dfdff3c5123ef473d6ededdcc92 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 11 Aug 2019 14:17:30 +1200 Subject: [PATCH 105/151] Migrate from notifications to conversations without sending emails --- app/models/notification.rb | 31 ------------------- ...190720000625_notifications_to_mailboxer.rb | 10 ++++-- spec/models/notification_spec.rb | 21 ------------- 3 files changed, 7 insertions(+), 55 deletions(-) diff --git a/app/models/notification.rb b/app/models/notification.rb index 65ccb84b8..8a786c8fa 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -24,35 +24,4 @@ class Notification < ApplicationRecord def send_message sender.send_message(recipient, body, subject) end - - def migrate_to_mailboxer! - conversation = Mailboxer::ConversationBuilder.new( - subject: subject, - created_at: created_at, - updated_at: updated_at - ).build - - message = Mailboxer::MessageBuilder.new( - sender: sender, - conversation: conversation, - recipients: [recipient], - body: body, - subject: subject, - # attachment: attachment, - created_at: created_at, - updated_at: updated_at - ).build - - notification = Mailboxer::NotificationBuilder.new( - recipients: [recipient], - subject: subject, - body: body, - sender: sender - ).build - - conversation.save! - message.save! - notification.save! - notification.deliver(false, false) - end end diff --git a/db/migrate/20190720000625_notifications_to_mailboxer.rb b/db/migrate/20190720000625_notifications_to_mailboxer.rb index 6e003c44a..1a5d281b6 100644 --- a/db/migrate/20190720000625_notifications_to_mailboxer.rb +++ b/db/migrate/20190720000625_notifications_to_mailboxer.rb @@ -1,9 +1,13 @@ class NotificationsToMailboxer < ActiveRecord::Migration[5.2] def up - Notification.find_in_batches do |group| + Mailboxer.setup do |config| + # turn off emails + config.uses_emails = false + end + Notification.find_in_batches.each do |group| group.each do |n| - next unless n.valid? - n.migrate_to_mailboxer! + n.body = 'message has no body' if n.body.blank? + n.send_message end end end diff --git a/spec/models/notification_spec.rb b/spec/models/notification_spec.rb index 745a2fb7d..5c9dc4883 100644 --- a/spec/models/notification_spec.rb +++ b/spec/models/notification_spec.rb @@ -3,27 +3,6 @@ require 'rails_helper' describe Notification do let(:notification) { FactoryBot.create(:notification) } - describe 'migration to mailboxer' do - let(:body) do - "Hellos - how are you today? - I am fine - - -- me - " - end - let(:sender) { FactoryBot.create :member } - let(:recipient) { FactoryBot.create :member } - let(:notification) do - FactoryBot.create :notification, - subject: 'hello', body: body, - sender: sender, - recipient: recipient - end - before { notification.migrate_to_mailboxer! } - it { expect(recipient.mailbox.inbox.count).to eq 1 } - it { expect(recipient.mailbox.inbox.first.subject).to eq 'hello' } - end it "belongs to a post" do expect(notification.post).to be_an_instance_of Post end From 105c2639e4fbb86968c3965d0b9847feada8a8f1 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 11 Aug 2019 14:23:27 +1200 Subject: [PATCH 106/151] Adding timestamps to tables --- .../20190720000555_create_mailboxer.mailboxer_engine.rb | 9 +++------ ...720000556_add_conversation_optout.mailboxer_engine.rb | 1 + db/schema.rb | 4 +++- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/db/migrate/20190720000555_create_mailboxer.mailboxer_engine.rb b/db/migrate/20190720000555_create_mailboxer.mailboxer_engine.rb index c932d9041..ff7eaea51 100644 --- a/db/migrate/20190720000555_create_mailboxer.mailboxer_engine.rb +++ b/db/migrate/20190720000555_create_mailboxer.mailboxer_engine.rb @@ -5,8 +5,7 @@ class CreateMailboxer < ActiveRecord::Migration[4.2] # Conversations create_table :mailboxer_conversations do |t| t.column :subject, :string, default: "" - t.column :created_at, :datetime, null: false - t.column :updated_at, :datetime, null: false + t.timestamps null: false end # Receipts create_table :mailboxer_receipts do |t| @@ -16,8 +15,7 @@ class CreateMailboxer < ActiveRecord::Migration[4.2] t.column :trashed, :boolean, default: false t.column :deleted, :boolean, default: false t.column :mailbox_type, :string, limit: 25 - t.column :created_at, :datetime, null: false - t.column :updated_at, :datetime, null: false + t.timestamps null: false end # Notifications and Messages create_table :mailboxer_notifications do |t| @@ -30,8 +28,7 @@ class CreateMailboxer < ActiveRecord::Migration[4.2] t.string :notification_code, default: nil t.references :notified_object, polymorphic: true, index: { name: 'mailboxer_notifications_notified_object' } t.column :attachment, :string - t.column :updated_at, :datetime, null: false - t.column :created_at, :datetime, null: false + t.timestamps null: false t.boolean :global, default: false t.datetime :expires end diff --git a/db/migrate/20190720000556_add_conversation_optout.mailboxer_engine.rb b/db/migrate/20190720000556_add_conversation_optout.mailboxer_engine.rb index a8aa6bbed..55676db21 100644 --- a/db/migrate/20190720000556_add_conversation_optout.mailboxer_engine.rb +++ b/db/migrate/20190720000556_add_conversation_optout.mailboxer_engine.rb @@ -4,6 +4,7 @@ class AddConversationOptout < ActiveRecord::Migration[4.2] create_table :mailboxer_conversation_opt_outs do |t| t.references :unsubscriber, polymorphic: true t.references :conversation + t.timestamps null: false end add_foreign_key "mailboxer_conversation_opt_outs", "mailboxer_conversations", name: "mb_opt_outs_on_conversations_id", column: "conversation_id" end diff --git a/db/schema.rb b/db/schema.rb index f9ac74a45..1ce9e5deb 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -272,6 +272,8 @@ ActiveRecord::Schema.define(version: 2019_07_21_042146) do t.string "unsubscriber_type" t.integer "unsubscriber_id" t.integer "conversation_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.index ["conversation_id"], name: "index_mailboxer_conversation_opt_outs_on_conversation_id" t.index ["unsubscriber_id", "unsubscriber_type"], name: "index_mailboxer_conversation_opt_outs_on_unsubscriber_id_type" end @@ -294,8 +296,8 @@ ActiveRecord::Schema.define(version: 2019_07_21_042146) do t.string "notified_object_type" t.integer "notified_object_id" t.string "attachment" - t.datetime "updated_at", null: false t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.boolean "global", default: false t.datetime "expires" t.index ["conversation_id"], name: "index_mailboxer_notifications_on_conversation_id" From 3976d1a982a2b78a0d4c1dd08c8ad545086aa4a8 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 11 Aug 2019 14:24:17 +1200 Subject: [PATCH 107/151] Shorten method --- app/models/member.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/models/member.rb b/app/models/member.rb index 9891d4e64..3181a8396 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -109,11 +109,7 @@ class Member < ApplicationRecord end def to_s - if discarded? - 'deleted' - else - login_name - end + discarded? ? 'deleted' : login_name end def to_param From 031734bb7f1e6d2136ed205b06814460477e324d Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 11 Aug 2019 14:24:43 +1200 Subject: [PATCH 108/151] shorten method --- app/models/member.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/models/member.rb b/app/models/member.rb index 3181a8396..667c8040e 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -121,11 +121,7 @@ class Member < ApplicationRecord end def mailboxer_email(_messageable) - if send_notification_email - email - else - false - end + send_notification_email ? email : false end def role?(role_sym) From c4b33db4950a57a405442384e4d8b301a44bebc2 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 11 Aug 2019 15:50:36 +1200 Subject: [PATCH 109/151] Mark read notifications as read after migrating to conversations --- config/initializers/mailboxer.rb | 2 +- db/migrate/20190720000625_notifications_to_mailboxer.rb | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/config/initializers/mailboxer.rb b/config/initializers/mailboxer.rb index 4392f70c2..6f1b0fa7c 100644 --- a/config/initializers/mailboxer.rb +++ b/config/initializers/mailboxer.rb @@ -7,7 +7,7 @@ Mailboxer.setup do |config| # Configures the methods needed by mailboxer # config.email_method = :email - # config.name_method = :login_name + config.name_method = :login_name config.notify_method = :notify # Configures if you use or not a search engine and which one you are using diff --git a/db/migrate/20190720000625_notifications_to_mailboxer.rb b/db/migrate/20190720000625_notifications_to_mailboxer.rb index 1a5d281b6..e0aaff0b5 100644 --- a/db/migrate/20190720000625_notifications_to_mailboxer.rb +++ b/db/migrate/20190720000625_notifications_to_mailboxer.rb @@ -7,7 +7,10 @@ class NotificationsToMailboxer < ActiveRecord::Migration[5.2] Notification.find_in_batches.each do |group| group.each do |n| n.body = 'message has no body' if n.body.blank? - n.send_message + receipt = n.send_message + next unless n.read + + receipt.conversation.receipts.each(&:mark_as_read) end end end From 3c073a950ad6ce6a10573b4d1e8cec649fd52c62 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 11 Aug 2019 15:50:48 +1200 Subject: [PATCH 110/151] Reducing size of member model --- app/models/member.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/models/member.rb b/app/models/member.rb index 667c8040e..ad6a8cba8 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -116,10 +116,6 @@ class Member < ApplicationRecord slug end - def name - login_name - end - def mailboxer_email(_messageable) send_notification_email ? email : false end From e01b53fd9b45352997acadcb6eb33ce4cca097ab Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 11 Aug 2019 15:52:11 +1200 Subject: [PATCH 111/151] Remove extra validators on notification We are migrating away from here --- app/models/notification.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/models/notification.rb b/app/models/notification.rb index 8a786c8fa..f15734325 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -4,8 +4,6 @@ class Notification < ApplicationRecord belongs_to :post, optional: true validates :subject, length: { maximum: 255 } - validates :subject, presence: true - validates :body, presence: true scope :unread, -> { where(read: false) } scope :by_recipient, ->(recipient) { where(recipient_id: recipient) } @@ -13,10 +11,6 @@ class Notification < ApplicationRecord before_create :replace_blank_subject after_create :send_message - def self.unread_count - unread.size - end - def replace_blank_subject self.subject = "(no subject)" if subject.nil? || subject =~ /^\s*$/ end From 11ef0fb694f096785ce8e2bc75f517d1c17dc95c Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 11 Aug 2019 16:31:51 +1200 Subject: [PATCH 112/151] Removed test for unused method --- spec/models/notification_spec.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/spec/models/notification_spec.rb b/spec/models/notification_spec.rb index 5c9dc4883..2a4c7e86a 100644 --- a/spec/models/notification_spec.rb +++ b/spec/models/notification_spec.rb @@ -24,12 +24,6 @@ describe Notification do expect(Notification.unread).to include notification end - it "counts unread" do - @who = notification.recipient - @n2 = FactoryBot.create(:notification, recipient: @who, read: false) - expect(@who.notifications.unread_count).to eq 2 - end - it "sends email if asked" do @notification2 = FactoryBot.create(:notification) @notification2.send_message From 44d8cd0f63b5fbdf5e4810480953de8b3be46f10 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 11 Aug 2019 16:55:15 +1200 Subject: [PATCH 113/151] Copy timestamps from Notifications to Conversations --- db/migrate/20190720000625_notifications_to_mailboxer.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/db/migrate/20190720000625_notifications_to_mailboxer.rb b/db/migrate/20190720000625_notifications_to_mailboxer.rb index e0aaff0b5..cd92baca6 100644 --- a/db/migrate/20190720000625_notifications_to_mailboxer.rb +++ b/db/migrate/20190720000625_notifications_to_mailboxer.rb @@ -8,9 +8,12 @@ class NotificationsToMailboxer < ActiveRecord::Migration[5.2] group.each do |n| n.body = 'message has no body' if n.body.blank? receipt = n.send_message - next unless n.read - - receipt.conversation.receipts.each(&:mark_as_read) + # Copy over which messages are read + receipt.conversation.receipts.each(&:mark_as_read) if n.read + # copy over timestamps + receipt.conversation.messages.each do |msg| + msg.update!(created_at: n.created_at, updated_at: n.updated_at) + end end end end From c189e4ed3d0b15c4b2d9b03d66d791a039092176 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 11 Aug 2019 16:55:32 +1200 Subject: [PATCH 114/151] Bigger envelope icons on conversations#index --- app/views/conversations/index.haml | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index 19f4fe172..f968302d0 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -24,12 +24,13 @@ .list-group-item .row .col-md-1 - - if @box == 'trash' - = link_to conversation_path(conversation, box: @box), method: :put, class: 'restore' do - = icon 'fas', 'trash-restore' - - else - = link_to delete_icon, conversation_path(conversation, box: @box), method: :delete, class: 'delete text-danger' - .col-md-11 + + %h1 + - if conversation.receipts_for(current_member).last.is_unread? + = icon 'far', 'envelope' + - else + .text-muted= icon 'far', 'envelope-open' + .col-md-10 .text-right.float-right - conversation.recipients.each do |member| - if member != current_member @@ -39,13 +40,18 @@ %h5.mb-2.h5 %a{href: conversation_path(conversation)} - if conversation.receipts_for(current_member).last.is_unread? - = icon 'far', 'envelope' + %strong= conversation.subject - else - = icon 'far', 'envelope-open' - %strong= conversation.subject + = conversation.subject %small #{time_ago_in_words conversation.messages.last.created_at} ago %span.text-muted= conversation.messages.last.created_at - %small= truncate(strip_tags(conversation.messages.last.body), length: 150, separator: ' ', omission: '... ') + = truncate(strip_tags(conversation.messages.last.body), length: 150, separator: ' ', omission: '... ') + .col-md-1 + - if @box == 'trash' + = link_to conversation_path(conversation, box: @box), method: :put, class: 'restore' do + = icon 'fas', 'trash-restore' + - else + = link_to delete_icon, conversation_path(conversation, box: @box), method: :delete, class: 'delete text-danger' - unless @conversations.empty? = will_paginate @conversations From 109f9af0b9271c91f094c63ef7d8132275091deb Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 11 Aug 2019 17:04:52 +1200 Subject: [PATCH 115/151] Unread counts --- app/controllers/conversations_controller.rb | 2 +- app/views/conversations/index.haml | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index 82a24a2b9..67cf92211 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -41,7 +41,7 @@ class ConversationsController < ApplicationController def set_box @boxes = { - 'inbox' => { 'total' => mailbox.inbox.size, 'unread' => 0 }, + 'inbox' => { 'total' => mailbox.inbox.size, 'unread' => current_member.receipts.where(is_read: false).count }, 'sent' => { 'total' => mailbox.sentbox.size, 'unread' => 0 }, 'trash' => { 'total' => mailbox.trash.size, 'unread' => 0 } } diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index f968302d0..279967647 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -13,10 +13,13 @@ .col-md-2.list-group - @boxes.each do |box_name, counts| = link_to conversations_path(box: box_name), class: "nav-link list-group-item d-flex justify-content-between #{box_name == @box ? 'active' : ''} #{box_name}" do - = icon 'fas', box_name - = box_name - if counts['unread'].positive? - %span.badge.badge-primary.badge-pill=counts['unread'] + %span.badge.badge-info=counts['unread'] + - else + %span + %span + = icon 'fas', box_name + = box_name .col-md-10 .list-group From 222400d4e188d1b2e25030f98718a175ad590a0f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 11 Aug 2019 20:55:20 +1200 Subject: [PATCH 116/151] links to member from conversations#index --- app/views/conversations/index.haml | 35 ++++++++++++++---------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/app/views/conversations/index.haml b/app/views/conversations/index.haml index 279967647..81f38c125 100644 --- a/app/views/conversations/index.haml +++ b/app/views/conversations/index.haml @@ -27,29 +27,26 @@ .list-group-item .row .col-md-1 - - %h1 - - if conversation.receipts_for(current_member).last.is_unread? - = icon 'far', 'envelope' - - else - .text-muted= icon 'far', 'envelope-open' + - if conversation.receipts_for(current_member).last.is_unread? + %h1= icon 'far', 'envelope' + - else + %h1.text-muted= icon 'far', 'envelope-open' .col-md-10 .text-right.float-right - conversation.recipients.each do |member| - if member != current_member - .member-chip - = image_tag(avatar_uri(member, 100), alt: '', height: 50, width: 50) - = member - %h5.mb-2.h5 - %a{href: conversation_path(conversation)} - - if conversation.receipts_for(current_member).last.is_unread? - %strong= conversation.subject - - else - = conversation.subject - %small - #{time_ago_in_words conversation.messages.last.created_at} ago - %span.text-muted= conversation.messages.last.created_at - = truncate(strip_tags(conversation.messages.last.body), length: 150, separator: ' ', omission: '... ') + = render 'members/tiny', member: member + = link_to conversation_path(conversation) do + .conversation + %h5.mb-2.h5 + - if conversation.receipts_for(current_member).last.is_unread? + %strong= conversation.subject + - else + = conversation.subject + %small + #{time_ago_in_words conversation.messages.last.created_at} ago + %span.text-muted= conversation.messages.last.created_at + = truncate(strip_tags(conversation.messages.last.body), length: 150, separator: ' ', omission: '... ') .col-md-1 - if @box == 'trash' = link_to conversation_path(conversation, box: @box), method: :put, class: 'restore' do From df87a79ab64a41019312d4cc9a342b6ee4d47ac4 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 12 Aug 2019 09:40:53 +1200 Subject: [PATCH 117/151] Only send email if user wants them --- app/models/notification.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/notification.rb b/app/models/notification.rb index f15734325..397f8806e 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -16,6 +16,6 @@ class Notification < ApplicationRecord end def send_message - sender.send_message(recipient, body, subject) + sender.send_message(recipient, body, subject) if recipient.send_notification_email end end From c77742ababc3b7de232168c4977ef1297349a018 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 12 Aug 2019 09:51:00 +1200 Subject: [PATCH 118/151] Wrapped long line --- .../20190720000556_add_conversation_optout.mailboxer_engine.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/db/migrate/20190720000556_add_conversation_optout.mailboxer_engine.rb b/db/migrate/20190720000556_add_conversation_optout.mailboxer_engine.rb index 55676db21..19190febd 100644 --- a/db/migrate/20190720000556_add_conversation_optout.mailboxer_engine.rb +++ b/db/migrate/20190720000556_add_conversation_optout.mailboxer_engine.rb @@ -6,7 +6,8 @@ class AddConversationOptout < ActiveRecord::Migration[4.2] t.references :conversation t.timestamps null: false end - add_foreign_key "mailboxer_conversation_opt_outs", "mailboxer_conversations", name: "mb_opt_outs_on_conversations_id", column: "conversation_id" + add_foreign_key "mailboxer_conversation_opt_outs", "mailboxer_conversations", + name: "mb_opt_outs_on_conversations_id", column: "conversation_id" end def self.down From c173d359d8b5889c6c4f49b14c6513b48b254d64 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 12 Aug 2019 10:00:21 +1200 Subject: [PATCH 119/151] Split up giant member model --- app/models/concerns/member_flickr.rb | 51 ++++++++++++++ app/models/concerns/member_newsletter.rb | 46 ++++++++++++ app/models/member.rb | 89 +----------------------- app/models/notification.rb | 10 +-- 4 files changed, 106 insertions(+), 90 deletions(-) create mode 100644 app/models/concerns/member_flickr.rb create mode 100644 app/models/concerns/member_newsletter.rb diff --git a/app/models/concerns/member_flickr.rb b/app/models/concerns/member_flickr.rb new file mode 100644 index 000000000..2f1e22eec --- /dev/null +++ b/app/models/concerns/member_flickr.rb @@ -0,0 +1,51 @@ +module MemberFlickr + extend ActiveSupport::Concern + + included do # rubocop:disable Metrics/BlockLength + # Authenticates against Flickr and returns an object we can use for subsequent api calls + def flickr + if @flickr.nil? + flickr_auth = auth('flickr') + if flickr_auth + FlickRaw.api_key = ENV['GROWSTUFF_FLICKR_KEY'] + FlickRaw.shared_secret = ENV['GROWSTUFF_FLICKR_SECRET'] + @flickr = FlickRaw::Flickr.new + @flickr.access_token = flickr_auth.token + @flickr.access_secret = flickr_auth.secret + end + end + @flickr + end + + # Fetches a collection of photos from Flickr + # Returns a [[page of photos], total] pair. + # Total is needed for pagination. + def flickr_photos(page_num = 1, set = nil) + result = if set + flickr.photosets.getPhotos( + photoset_id: set, + page: page_num, + per_page: 30 + ) + else + flickr.people.getPhotos( + user_id: 'me', + page: page_num, + per_page: 30 + ) + end + return [result.photo, result.total] if result + + [[], 0] + end + + # Returns a hash of Flickr photosets' ids and titles + def flickr_sets + sets = {} + flickr.photosets.getList.each do |p| + sets[p.title] = p.id + end + sets + end + end +end diff --git a/app/models/concerns/member_newsletter.rb b/app/models/concerns/member_newsletter.rb new file mode 100644 index 000000000..938ba2237 --- /dev/null +++ b/app/models/concerns/member_newsletter.rb @@ -0,0 +1,46 @@ +module MemberNewsletter + extend ActiveSupport::Concern + + included do # rubocop:disable Metrics/BlockLength + after_save :update_newsletter_subscription + before_destroy :newsletter_unsubscribe + + scope :wants_newsletter, -> { where(newsletter: true) } + + def update_newsletter_subscription + return unless will_save_change_to_attribute?(:confirmed) || will_save_change_to_attribute?(:newsletter) + + if newsletter + newsletter_subscribe if confirmed_just_now? || requested_newsletter_just_now? + elsif confirmed_at + newsletter_unsubscribe + end + end + + def confirmed_just_now? + will_save_change_to_attribute?(:confirmed_at) + end + + def requested_newsletter_just_now? + confirmed_at && will_save_change_to_attribute?(:newsletter) + end + + def newsletter_subscribe(gibbon = Gibbon::API.new, testing = false) + return true if Rails.env.test? && !testing + + gibbon.lists.subscribe( + id: Rails.application.config.newsletter_list_id, + email: { email: email }, + merge_vars: { login_name: login_name }, + double_optin: false # they already confirmed their email with us + ) + end + + def newsletter_unsubscribe(gibbon = Gibbon::API.new, testing = false) + return true if Rails.env.test? && !testing + + gibbon.lists.unsubscribe(id: Rails.application.config.newsletter_list_id, + email: { email: email }) + end + end +end diff --git a/app/models/member.rb b/app/models/member.rb index ad6a8cba8..e809c5370 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -1,10 +1,11 @@ class Member < ApplicationRecord include Discard::Model acts_as_messageable # messages can be sent to this model - before_destroy :newsletter_unsubscribe include Geocodable - extend FriendlyId + include MemberFlickr + include MemberNewsletter + extend FriendlyId friendly_id :login_name, use: %i(slugged finders) # @@ -47,7 +48,6 @@ class Member < ApplicationRecord scope :located, -> { where.not(location: '').where.not(latitude: nil).where.not(longitude: nil) } scope :recently_signed_in, -> { reorder(updated_at: :desc) } scope :recently_joined, -> { reorder(confirmed_at: :desc) } - scope :wants_newsletter, -> { where(newsletter: true) } scope :interesting, -> { confirmed.located.recently_signed_in.has_plantings } scope :has_plantings, -> { joins(:plantings).group("members.id") } @@ -92,7 +92,6 @@ class Member < ApplicationRecord # Triggers after_validation :geocode after_validation :empty_unwanted_geocodes - after_save :update_newsletter_subscription # Give each new member a default garden # we use find_or_create to avoid accidentally creating a second one, @@ -132,52 +131,6 @@ class Member < ApplicationRecord receipts.where(is_read: false).count end - # Authenticates against Flickr and returns an object we can use for subsequent api calls - def flickr - if @flickr.nil? - flickr_auth = auth('flickr') - if flickr_auth - FlickRaw.api_key = ENV['GROWSTUFF_FLICKR_KEY'] - FlickRaw.shared_secret = ENV['GROWSTUFF_FLICKR_SECRET'] - @flickr = FlickRaw::Flickr.new - @flickr.access_token = flickr_auth.token - @flickr.access_secret = flickr_auth.secret - end - end - @flickr - end - - # Fetches a collection of photos from Flickr - # Returns a [[page of photos], total] pair. - # Total is needed for pagination. - def flickr_photos(page_num = 1, set = nil) - result = if set - flickr.photosets.getPhotos( - photoset_id: set, - page: page_num, - per_page: 30 - ) - else - flickr.people.getPhotos( - user_id: 'me', - page: page_num, - per_page: 30 - ) - end - return [result.photo, result.total] if result - - [[], 0] - end - - # Returns a hash of Flickr photosets' ids and titles - def flickr_sets - sets = {} - flickr.photosets.getList.each do |p| - sets[p.title] = p.id - end - sets - end - def self.login_name_or_email(login) where(["lower(login_name) = :value OR lower(email) = :value", { value: login.downcase }]) end @@ -195,42 +148,6 @@ class Member < ApplicationRecord nearby_members end - def update_newsletter_subscription - return unless will_save_change_to_attribute?(:confirmed) || will_save_change_to_attribute?(:newsletter) - - if newsletter - newsletter_subscribe if confirmed_just_now? || requested_newsletter_just_now? - elsif confirmed_at - newsletter_unsubscribe - end - end - - def confirmed_just_now? - will_save_change_to_attribute?(:confirmed_at) - end - - def requested_newsletter_just_now? - confirmed_at && will_save_change_to_attribute?(:newsletter) - end - - def newsletter_subscribe(gibbon = Gibbon::API.new, testing = false) - return true if Rails.env.test? && !testing - - gibbon.lists.subscribe( - id: Rails.application.config.newsletter_list_id, - email: { email: email }, - merge_vars: { login_name: login_name }, - double_optin: false # they already confirmed their email with us - ) - end - - def newsletter_unsubscribe(gibbon = Gibbon::API.new, testing = false) - return true if Rails.env.test? && !testing - - gibbon.lists.unsubscribe(id: Rails.application.config.newsletter_list_id, - email: { email: email }) - end - def already_following?(member) follows.exists?(followed_id: member.id) end diff --git a/app/models/notification.rb b/app/models/notification.rb index 397f8806e..466fe73be 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -11,11 +11,13 @@ class Notification < ApplicationRecord before_create :replace_blank_subject after_create :send_message - def replace_blank_subject - self.subject = "(no subject)" if subject.nil? || subject =~ /^\s*$/ - end - def send_message sender.send_message(recipient, body, subject) if recipient.send_notification_email end + + private + + def replace_blank_subject + self.subject = "(no subject)" if subject.nil? || subject =~ /^\s*$/ + end end From e27cf02d961f871d0f3b4beff78bacce065ed2cd Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Fri, 16 Aug 2019 13:49:31 +1200 Subject: [PATCH 120/151] Shared context for signing in/out on feature specs --- spec/support/feature_helpers.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spec/support/feature_helpers.rb b/spec/support/feature_helpers.rb index 857e6b250..1f3fc1902 100644 --- a/spec/support/feature_helpers.rb +++ b/spec/support/feature_helpers.rb @@ -9,6 +9,11 @@ module FeatureHelpers selector = %{ul.ui-autocomplete li.ui-menu-item a:contains("#{select}")} page.execute_script " $('#{selector}').mouseenter().click() " end + + shared_context 'signed in' do + before { sign_in user } + after { sign_out user } + end end RSpec.configure do |config| From 893693325188736d6ae6fe877aba2bced4c98124 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 17 Aug 2019 14:10:48 +1200 Subject: [PATCH 121/151] Shared context for signing in (and then out) in feature specs --- spec/features/admin/admin_spec.rb | 8 +- spec/features/admin/forums_spec.rb | 85 ++-- spec/features/cms_spec.rb | 24 +- .../comments/commenting_a_comment_spec.rb | 47 +- spec/features/crops/alternate_name_spec.rb | 7 +- spec/features/crops/browse_crops_spec.rb | 10 +- spec/features/crops/crop_detail_page_spec.rb | 29 +- spec/features/crops/crop_photos_spec.rb | 33 +- spec/features/crops/crop_wranglers_spec.rb | 129 +++-- .../crops/crop_wrangling_button_spec.rb | 30 +- spec/features/crops/delete_crop_spec.rb | 31 +- spec/features/crops/request_new_crop_spec.rb | 58 +-- spec/features/crops/requested_crops_spec.rb | 14 +- spec/features/crops/scientific_name_spec.rb | 114 ++--- spec/features/gardens/actions_spec.rb | 107 ++-- spec/features/gardens/adding_gardens_spec.rb | 53 +- spec/features/gardens/gardens_spec.rb | 218 ++++---- spec/features/gardens/index_spec.rb | 104 ++-- .../features/harvests/browse_harvests_spec.rb | 35 +- .../harvests/harvesting_a_crop_spec.rb | 212 ++++---- spec/features/home/home_spec.rb | 18 +- spec/features/likeable_spec.rb | 4 +- spec/features/members/ban_spec.rb | 21 +- spec/features/members/following_spec.rb | 99 ++-- spec/features/members/profile_spec.rb | 28 +- spec/features/notifications_spec.rb | 95 ++-- spec/features/percy/percy_spec.rb | 254 ++++----- spec/features/photos/new_photo_spec.rb | 74 +-- spec/features/photos/show_photo_spec.rb | 94 ++-- .../features/places/searching_a_place_spec.rb | 45 +- .../plantings/planting_a_crop_spec.rb | 481 +++++++++--------- spec/features/posts/posting_a_post_spec.rb | 45 +- spec/features/seeds/adding_seeds_spec.rb | 116 +++-- spec/features/seeds/misc_seeds_spec.rb | 124 ++--- spec/features/seeds/seed_photos.rb | 65 ++- spec/support/devise.rb | 1 + spec/support/feature_helpers.rb | 19 +- 37 files changed, 1443 insertions(+), 1488 deletions(-) diff --git a/spec/features/admin/admin_spec.rb b/spec/features/admin/admin_spec.rb index 6ee586ee7..57c8953b1 100644 --- a/spec/features/admin/admin_spec.rb +++ b/spec/features/admin/admin_spec.rb @@ -1,13 +1,7 @@ require 'rails_helper' describe "forums", js: true do - context "as an admin user" do - let(:member) { create :admin_member } - - before do - login_as member - end - + include_context 'signed in admin' do it "navigating to forum admin with js" do visit admin_path Percy.snapshot(page, name: 'Admin page') diff --git a/spec/features/admin/forums_spec.rb b/spec/features/admin/forums_spec.rb index d13cc13fb..d22ace435 100644 --- a/spec/features/admin/forums_spec.rb +++ b/spec/features/admin/forums_spec.rb @@ -1,52 +1,55 @@ require 'rails_helper' describe "forums", js: true do - context "as an admin user" do - let(:member) { create :admin_member } - let(:forum) { create :forum } + include_context 'signed in admin' do + let(:forum) { create :forum } - before do - login_as member - end - - it "navigating to forum admin with js" do - visit admin_path - within 'ul#site_admin' do - click_link "Forums" + describe "navigating to forum admin with js" do + before do + visit admin_path + within 'ul#site_admin' do + click_link "Forums" + end end - expect(current_path).to eq forums_path - expect(page).to have_link "New forum" + it { expect(current_path).to eq forums_path } + it { expect(page).to have_link "New forum" } end - it "adding a forum" do - visit forums_path - click_link "New forum" - expect(current_path).to eq new_forum_path - fill_in 'Name', with: 'Discussion' - fill_in 'Description', with: "this is a new forum" - click_button 'Save' - expect(current_path).to eq forum_path(Forum.last) - expect(page).to have_content 'Forum was successfully created' - end - - it 'editing forum' do - visit forum_path forum - click_link 'Edit' - fill_in 'Name', with: 'Something else' - click_button 'Save' - forum.reload - expect(current_path).to eq forum_path(forum) - expect(page).to have_content 'Forum was successfully updated' - expect(page).to have_content 'Something else' - end - - it 'deleting forum' do - visit forum_path forum - accept_confirm do - click_link 'Delete' + describe "adding a forum" do + before do + visit forums_path + click_link "New forum" + expect(current_path).to eq new_forum_path + fill_in 'Name', with: 'Discussion' + fill_in 'Description', with: "this is a new forum" + click_button 'Save' end - expect(current_path).to eq forums_path - expect(page).to have_content 'Forum was successfully deleted' + it { expect(current_path).to eq forum_path(Forum.last) } + it { expect(page).to have_content 'Forum was successfully created' } + end + + describe 'editing forum' do + before do + visit forum_path forum + click_link 'Edit' + fill_in 'Name', with: 'Something else' + click_button 'Save' + forum.reload + end + it { expect(current_path).to eq forum_path(forum) } + it { expect(page).to have_content 'Forum was successfully updated' } + it { expect(page).to have_content 'Something else' } + end + + describe 'deleting forum' do + before do + visit forum_path forum + accept_confirm do + click_link 'Delete' + end + end + it { expect(current_path).to eq forums_path } + it { expect(page).to have_content 'Forum was successfully deleted' } end end end diff --git a/spec/features/cms_spec.rb b/spec/features/cms_spec.rb index 4abe7d6d4..d07f3c935 100644 --- a/spec/features/cms_spec.rb +++ b/spec/features/cms_spec.rb @@ -1,26 +1,24 @@ require 'rails_helper' describe "cms admin" do - let(:member) { create :member } - let(:admin_member) { create :admin_member } - it "can't view CMS admin if not signed in" do visit comfy_admin_cms_path expect(current_path).to eq root_path expect(page).to have_content "Please sign in as an admin user" end - it "can't view CMS admin if not an admin member" do - # sign in as an ordinary member - login_as member - visit comfy_admin_cms_path - expect(current_path).to eq root_path - expect(page).to have_content "Please sign in as an admin user" + include_context 'signed in member' do + it "can't view CMS admin if not an admin member" do + visit comfy_admin_cms_path + expect(current_path).to eq root_path + expect(page).to have_content "Please sign in as an admin user" + end end - it "admin members can view CMS admin area" do - login_as admin_member - visit comfy_admin_cms_path - expect(current_path).to match(/#{comfy_admin_cms_path}/) # match any CMS admin page + include_context 'signed in admin' do + it "admin members can view CMS admin area" do + visit comfy_admin_cms_path + expect(current_path).to match(/#{comfy_admin_cms_path}/) # match any CMS admin page + end end end diff --git a/spec/features/comments/commenting_a_comment_spec.rb b/spec/features/comments/commenting_a_comment_spec.rb index f2136e98e..34907080b 100644 --- a/spec/features/comments/commenting_a_comment_spec.rb +++ b/spec/features/comments/commenting_a_comment_spec.rb @@ -1,34 +1,33 @@ require 'rails_helper' describe 'Commenting on a post' do - let(:member) { create :member } - let(:post) { create :post, author: member } + include_context 'signed in member' do + let(:member) { create :member } + let(:post) { create :post, author: member } - before do - login_as member - visit new_comment_path post_id: post.id - end + before { visit new_comment_path post_id: post.id } - it "creating a comment" do - fill_in "comment_body", with: "This is a sample test for comment" - click_button "Post comment" - expect(page).to have_content "comment was successfully created." - expect(page).to have_content "Posted by" - Percy.snapshot(page, name: 'Posting a comment') - end - - context "editing a comment" do - let(:existing_comment) { create :comment, post: post, author: member } - - before do - visit edit_comment_path existing_comment + it "creating a comment" do + fill_in "comment_body", with: "This is a sample test for comment" + click_button "Post comment" + expect(page).to have_content "comment was successfully created." + expect(page).to have_content "Posted by" + Percy.snapshot(page, name: 'Posting a comment') end - it "saving edit" do - fill_in "comment_body", with: "Testing edit for comment" - click_button "Post comment" - expect(page).to have_content "comment was successfully updated." - expect(page).to have_content "edited at" + context "editing a comment" do + let(:existing_comment) { create :comment, post: post, author: member } + + before do + visit edit_comment_path existing_comment + end + + it "saving edit" do + fill_in "comment_body", with: "Testing edit for comment" + click_button "Post comment" + expect(page).to have_content "comment was successfully updated." + expect(page).to have_content "edited at" + end end end end diff --git a/spec/features/crops/alternate_name_spec.rb b/spec/features/crops/alternate_name_spec.rb index 903b6d3a7..acd79bb36 100644 --- a/spec/features/crops/alternate_name_spec.rb +++ b/spec/features/crops/alternate_name_spec.rb @@ -15,13 +15,8 @@ describe "Alternate names", js: true do expect(page).to have_content alternate_eggplant.name end - context "User is a crop wrangler" do + include_context 'signed in crop wrangler' do let!(:crop_wranglers) { create_list :crop_wrangling_member, 3 } - let(:member) { crop_wranglers.first } - - before do - login_as member - end it "Crop wranglers can edit alternate names" do visit crop_path(crop) diff --git a/spec/features/crops/browse_crops_spec.rb b/spec/features/crops/browse_crops_spec.rb index 821ae01c4..9979cfb8e 100644 --- a/spec/features/crops/browse_crops_spec.rb +++ b/spec/features/crops/browse_crops_spec.rb @@ -12,9 +12,8 @@ describe "browse crops" do end it "shows a list of crops" do - crop1 = tomato visit crops_path - expect(page).to have_content crop1.name + expect(page).to have_content tomato.name end it "pending crops are not listed" do @@ -27,11 +26,8 @@ describe "browse crops" do expect(page).not_to have_content rejected_crop.name end - context "logged in and crop wrangler" do - before do - login_as FactoryBot.create(:crop_wrangling_member) - visit crops_path - end + include_context 'signed in crop wrangler' do + before { visit crops_path } it "shows a new crop link" do expect(page).to have_link "Add New Crop" diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index 2e1fec723..3da5f8828 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -20,13 +20,7 @@ describe "crop detail page", js: true do end end - context "signed in member" do - let(:member) { create :member } - - before do - login_as(member) - end - + include_context "signed in member" do context "action buttons" do before { subject } @@ -86,17 +80,16 @@ describe "crop detail page", js: true do expect(page).not_to have_content "You have 20 seeds" end - it "User signed in" do - login_as(member) - visit crop_path(seed.crop) - expect(page).to have_link "You have 20 seeds of this crop." - end - - it "click link to your owned seeds" do - login_as(member) - visit crop_path(seed.crop) - click_link "You have 20 seeds of this crop." - expect(current_path).to eq member_seeds_path(member_slug: member.slug) + include_context 'signed in member' do + it "User signed in" do + visit crop_path(seed.crop) + expect(page).to have_link "You have 20 seeds of this crop." + end + it "click link to your owned seeds" do + visit crop_path(seed.crop) + click_link "You have 20 seeds of this crop." + expect(current_path).to eq member_seeds_path(member_slug: member.slug) + end end end diff --git a/spec/features/crops/crop_photos_spec.rb b/spec/features/crops/crop_photos_spec.rb index e66d645d3..39654a6bd 100644 --- a/spec/features/crops/crop_photos_spec.rb +++ b/spec/features/crops/crop_photos_spec.rb @@ -3,20 +3,20 @@ require 'rails_helper' describe "crop detail page", js: true do subject { page } - let!(:member) { FactoryBot.create :member } + let!(:owner_member) { FactoryBot.create :member } let!(:crop) { FactoryBot.create :crop } - let!(:planting) { FactoryBot.create :planting, crop: crop, owner: member } - let!(:harvest) { FactoryBot.create :harvest, crop: crop, owner: member } - let!(:seed) { FactoryBot.create :seed, crop: crop, owner: member } + let!(:planting) { FactoryBot.create :planting, crop: crop, owner: owner_member } + let!(:harvest) { FactoryBot.create :harvest, crop: crop, owner: owner_member } + let!(:seed) { FactoryBot.create :seed, crop: crop, owner: owner_member } - let!(:photo1) { FactoryBot.create(:photo, owner: member) } - let!(:photo2) { FactoryBot.create(:photo, owner: member) } - let!(:photo3) { FactoryBot.create(:photo, owner: member) } - let!(:photo4) { FactoryBot.create(:photo, owner: member) } - let!(:photo5) { FactoryBot.create(:photo, owner: member) } - let!(:photo6) { FactoryBot.create(:photo, owner: member) } + let!(:photo1) { FactoryBot.create(:photo, owner: owner_member) } + let!(:photo2) { FactoryBot.create(:photo, owner: owner_member) } + let!(:photo3) { FactoryBot.create(:photo, owner: owner_member) } + let!(:photo4) { FactoryBot.create(:photo, owner: owner_member) } + let!(:photo5) { FactoryBot.create(:photo, owner: owner_member) } + let!(:photo6) { FactoryBot.create(:photo, owner: owner_member) } before do planting.photos << photo1 @@ -50,15 +50,16 @@ describe "crop detail page", js: true do end context "when signed in" do - before { login_as(FactoryBot.create(:member)) } - - include_examples "shows photos" + include_context 'signed in member' do + include_examples "shows photos" + end end context "when signed in as photos owner" do - before { login_as(member) } - - include_examples "shows photos" + include_context 'signed in member' do + let(:member) { owner_member } + include_examples "shows photos" + end end context "when not signed in " do diff --git a/spec/features/crops/crop_wranglers_spec.rb b/spec/features/crops/crop_wranglers_spec.rb index 77571c0d4..3f52757ce 100644 --- a/spec/features/crops/crop_wranglers_spec.rb +++ b/spec/features/crops/crop_wranglers_spec.rb @@ -2,87 +2,86 @@ require 'rails_helper' describe "crop wranglers", js: true do context "signed in wrangler" do - let!(:crop_wranglers) { create_list :crop_wrangling_member, 3 } - let(:wrangler) { crop_wranglers.first } - let!(:crops) { create_list :crop, 2 } - let!(:requested_crop) { create :crop_request } - let!(:rejected_crop) { create :rejected_crop } + include_context 'signed in crop wrangler' do + let!(:crop_wranglers) { create_list :crop_wrangling_member, 3 } + let!(:crops) { create_list :crop, 2 } + let!(:requested_crop) { create :crop_request } + let!(:rejected_crop) { create :rejected_crop } - before { login_as wrangler } + it "sees crop wranglers listed on the crop wrangler page" do + visit root_path + click_link 'Admin' + click_link 'Crop Wrangling' - it "sees crop wranglers listed on the crop wrangler page" do - visit root_path - click_link 'Admin' - click_link 'Crop Wrangling' - - within '.crop_wranglers' do - expect(page).to have_content 'Crop Wranglers:' - crop_wranglers.each do |crop_wrangler| - expect(page).to have_link crop_wrangler.login_name, href: member_path(crop_wrangler) + within '.crop_wranglers' do + expect(page).to have_content 'Crop Wranglers:' + crop_wranglers.each do |crop_wrangler| + expect(page).to have_link crop_wrangler.login_name, href: member_path(crop_wrangler) + end end end - end - it "can see list of crops with extra detail of who created a crop" do - visit root_path - click_link 'Admin' - click_link 'Crop Wrangling' - within '#recently-added-crops' do - expect(page).to have_content crops.first.creator.login_name.to_s - end - end - - describe "visiting a crop can see wrangler links" do - before do - visit crop_path(crops.first) - click_link 'Actions' + it "can see list of crops with extra detail of who created a crop" do + visit root_path + click_link 'Admin' + click_link 'Crop Wrangling' + within '#recently-added-crops' do + expect(page).to have_content crops.first.creator.login_name.to_s + end end - it { expect(page).to have_content 'You are a CROP WRANGLER' } - it { expect(page).to have_link 'Edit' } - it { expect(page).to have_link 'Delete' } - end + describe "visiting a crop can see wrangler links" do + before do + visit crop_path(crops.first) + click_link 'Actions' + end - it "can create a new crop" do - visit root_path - click_link 'Admin' - click_link 'Crop Wrangling' - click_link 'Add Crop' - fill_in 'Name', with: "aubergine" - fill_in 'en_wikipedia_url', with: "http://en.wikipedia.org/wiki/Maize" - fill_in 'sci_name[1]', with: "planticus maximus" - click_on 'Save' - expect(page).to have_content 'crop was successfully created.' - expect(page).to have_content 'planticus maximus' - end + it { expect(page).to have_content 'You are a CROP WRANGLER' } + it { expect(page).to have_link 'Edit' } + it { expect(page).to have_link 'Delete' } + end - it "View pending crops" do - visit crop_path(requested_crop) - expect(page).to have_content "This crop is currently pending approval." - expect(page).to have_content "Please approve this even though it's fake." - end + it "can create a new crop" do + visit root_path + click_link 'Admin' + click_link 'Crop Wrangling' + click_link 'Add Crop' + fill_in 'Name', with: "aubergine" + fill_in 'en_wikipedia_url', with: "http://en.wikipedia.org/wiki/Maize" + fill_in 'sci_name[1]', with: "planticus maximus" + click_on 'Save' + expect(page).to have_content 'crop was successfully created.' + expect(page).to have_content 'planticus maximus' + end - it "View rejected crops" do - visit crop_path(rejected_crop) - expect(page).to have_content "This crop was rejected for the following reason: Totally fake" + it "View pending crops" do + visit crop_path(requested_crop) + expect(page).to have_content "This crop is currently pending approval." + expect(page).to have_content "Please approve this even though it's fake." + end + + it "View rejected crops" do + visit crop_path(rejected_crop) + expect(page).to have_content "This crop was rejected for the following reason: Totally fake" + end end end context "signed in non-wrangler" do - let!(:crop_wranglers) { create_list :crop_wrangling_member, 3 } - let(:member) { create :member } + include_context 'signed in member' do + let!(:crop_wranglers) { create_list :crop_wrangling_member, 3 } + let(:member) { create :member } - before { login_as member } + it "can't see wrangling page without js", js: false do + visit root_path + expect(page).not_to have_link "Crop Wrangling" + end - it "can't see wrangling page without js", js: false do - visit root_path - expect(page).not_to have_link "Crop Wrangling" - end - - it "can't see wrangling page with js" do - visit root_path - click_link member.login_name - expect(page).not_to have_link "Crop Wrangling" + it "can't see wrangling page with js" do + visit root_path + click_link member.login_name + expect(page).not_to have_link "Crop Wrangling" + end end end end diff --git a/spec/features/crops/crop_wrangling_button_spec.rb b/spec/features/crops/crop_wrangling_button_spec.rb index 7e9c3d8d1..2dfdcda6d 100644 --- a/spec/features/crops/crop_wrangling_button_spec.rb +++ b/spec/features/crops/crop_wrangling_button_spec.rb @@ -1,28 +1,22 @@ require 'rails_helper' describe "crop wrangling button" do - let(:crop_wrangler) { create :crop_wrangling_member } - let(:member) { create :member } + context 'not signed in' do + before { visit crops_path } + it { expect(page).to have_no_link "Wrangle Crops", href: wrangle_crops_path } + end - context "crop wrangling button" do - before do - login_as crop_wrangler - visit crops_path - end - - it "has a link to crop wrangling page" do - expect(page).to have_link "Wrangle Crops", href: wrangle_crops_path + context "signed in, but not a crop wrangler" do + include_context 'signed in member' do + before { visit crops_path } + it { expect(page).to have_no_link "Wrangle Crops", href: wrangle_crops_path } end end - context "crop wrangling button" do - before do - login_as member - visit crops_path - end - - it "has no link to crop wrangling page" do - expect(page).to have_no_link "Wrangle Crops", href: wrangle_crops_path + context "signed in crop wrangler" do + include_context 'signed in crop wrangler' do + before { visit crops_path } + it { expect(page).to have_link "Wrangle Crops", href: wrangle_crops_path } end end end diff --git a/spec/features/crops/delete_crop_spec.rb b/spec/features/crops/delete_crop_spec.rb index b3c108ef9..00a8e7cec 100644 --- a/spec/features/crops/delete_crop_spec.rb +++ b/spec/features/crops/delete_crop_spec.rb @@ -2,28 +2,27 @@ require 'rails_helper' describe "Delete crop spec" do context "As a crop wrangler" do - let(:wrangler) { FactoryBot.create :crop_wrangling_member } let!(:pending_crop) { FactoryBot.create :crop_request } let!(:approved_crop) { FactoryBot.create :crop } - before { login_as wrangler } - - it "Delete approved crop" do - visit crop_path(approved_crop) - click_link 'Actions' - accept_confirm do - click_link 'Delete' + include_context 'signed in crop wrangler' do + it "deletes approved crop" do + visit crop_path(approved_crop) + click_link 'Actions' + accept_confirm do + click_link 'Delete' + end + expect(page).to have_content "crop was successfully destroyed" end - expect(page).to have_content "crop was successfully destroyed" - end - it "Delete pending crop" do - visit crop_path(pending_crop) - click_link 'Actions' - accept_confirm do - click_link 'Delete' + it "deletes pending crop" do + visit crop_path(pending_crop) + click_link 'Actions' + accept_confirm do + click_link 'Delete' + end + expect(page).to have_content "crop was successfully destroyed" end - expect(page).to have_content "crop was successfully destroyed" end end end diff --git a/spec/features/crops/request_new_crop_spec.rb b/spec/features/crops/request_new_crop_spec.rb index cd5cfb984..a35480b66 100644 --- a/spec/features/crops/request_new_crop_spec.rb +++ b/spec/features/crops/request_new_crop_spec.rb @@ -2,46 +2,40 @@ require 'rails_helper' describe "Requesting a new crop" do context "As a regular member" do - let(:member) { create :member } - let!(:wrangler) { create :crop_wrangling_member } - - before do - login_as member - end - - it "Submit request" do - visit new_crop_path - fill_in "Name", with: "Couch potato" - fill_in "request_notes", with: "Couch potatoes are real for real." - click_button "Save" - expect(page).to have_content 'crop was successfully created.' - expect(page).to have_content "This crop is currently pending approval." + include_context 'signed in member' do + it "Submit request" do + visit new_crop_path + fill_in "Name", with: "Couch potato" + fill_in "request_notes", with: "Couch potatoes are real for real." + click_button "Save" + expect(page).to have_content 'crop was successfully created.' + expect(page).to have_content "This crop is currently pending approval." + end end end context "As a crop wrangler" do - let(:wrangler) { create :crop_wrangling_member } let!(:crop) { create :crop_request } let!(:already_approved) { create :crop } - before { login_as wrangler } + include_context 'signed in crop wrangler' do + it "Approve a request" do + visit edit_crop_path(crop) + select "approved", from: "Approval status" + click_button "Save" + expect(page).to have_content "En wikipedia url is not a valid English Wikipedia URL" + fill_in "en_wikipedia_url", with: "http://en.wikipedia.org/wiki/Aung_San_Suu_Kyi" + click_button "Save" + expect(page).to have_content "crop was successfully updated." + end - it "Approve a request" do - visit edit_crop_path(crop) - select "approved", from: "Approval status" - click_button "Save" - expect(page).to have_content "En wikipedia url is not a valid English Wikipedia URL" - fill_in "en_wikipedia_url", with: "http://en.wikipedia.org/wiki/Aung_San_Suu_Kyi" - click_button "Save" - expect(page).to have_content "crop was successfully updated." - end - - it "Rejecting a crop" do - visit edit_crop_path(crop) - select "rejected", from: "Approval status" - select "not edible", from: "Reason for rejection" - click_button "Save" - expect(page).to have_content "crop was successfully updated." + it "Rejecting a crop" do + visit edit_crop_path(crop) + select "rejected", from: "Approval status" + select "not edible", from: "Reason for rejection" + click_button "Save" + expect(page).to have_content "crop was successfully updated." + end end end end diff --git a/spec/features/crops/requested_crops_spec.rb b/spec/features/crops/requested_crops_spec.rb index a4e406b63..5692e71fc 100644 --- a/spec/features/crops/requested_crops_spec.rb +++ b/spec/features/crops/requested_crops_spec.rb @@ -1,15 +1,13 @@ require 'rails_helper' -describe "Crop - " do - let(:member) { create :member } +describe "Requesting Crops" do let!(:requested_crop) { create :crop, requester: member, approval_status: 'pending', name: 'puha for dinner' } - before do - login_as member - visit requested_crops_path - end + include_context 'signed in member' do + before { visit requested_crops_path } - it "creating a crop with multiple scientific and alternate name", :js do - expect(page).to have_content "puha for dinner" + it "creating a crop with multiple scientific and alternate name", :js do + expect(page).to have_content "puha for dinner" + end end end diff --git a/spec/features/crops/scientific_name_spec.rb b/spec/features/crops/scientific_name_spec.rb index be428f7b0..3b525c5c3 100644 --- a/spec/features/crops/scientific_name_spec.rb +++ b/spec/features/crops/scientific_name_spec.rb @@ -20,69 +20,67 @@ describe "Scientific names", js: true do let!(:crop_wranglers) { create_list :crop_wrangling_member, 3 } let(:member) { crop_wranglers.first } - before do - login_as(member) - end - - it "Crop wranglers can edit scientific names" do - visit crop_path(crop) - # expect(page.status_code).to equal 200 - expect(page).to have_content "CROP WRANGLER" - expect(page).to have_content zea_mays.name - click_link zea_mays.name - expect(page).to have_link "Edit", href: edit_scientific_name_path(zea_mays) - within('.scientific_names') { click_on "Edit" } - # expect(page.status_code).to equal 200 - expect(page).to have_css "option[value='#{crop.id}'][selected=selected]" - fill_in 'Name', with: "Zea mirabila" - click_on "Save" - expect(page).to have_content "Zea mirabila" - expect(page).to have_content 'crop was successfully updated' - end - - it "Crop wranglers can delete scientific names" do - visit crop_path(zea_mays.crop) - click_link zea_mays.name - expect(page).to have_link "Delete", - href: scientific_name_path(zea_mays) - within('.scientific_names') do - accept_confirm do - click_link 'Delete' - end + include_context 'signed in crop wrangler' do + it "Crop wranglers can edit scientific names" do + visit crop_path(crop) + # expect(page.status_code).to equal 200 + expect(page).to have_content "CROP WRANGLER" + expect(page).to have_content zea_mays.name + click_link zea_mays.name + expect(page).to have_link "Edit", href: edit_scientific_name_path(zea_mays) + within('.scientific_names') { click_on "Edit" } + # expect(page.status_code).to equal 200 + expect(page).to have_css "option[value='#{crop.id}'][selected=selected]" + fill_in 'Name', with: "Zea mirabila" + click_on "Save" + expect(page).to have_content "Zea mirabila" + expect(page).to have_content 'crop was successfully updated' end - # expect(page.status_code).to equal 200 - expect(page).not_to have_content zea_mays.name - expect(page).to have_content 'Scientific name was successfully deleted.' - end - it "Crop wranglers can add scientific names" do - visit crop_path(crop) - expect(page).to have_link "Add", - href: new_scientific_name_path(crop_id: crop.id) - within('.scientific_names') { click_on "Add" } - # expect(page.status_code).to equal 200 - expect(page).to have_css "option[value='#{crop.id}'][selected=selected]" - fill_in 'Name', with: "Zea mirabila" - click_on "Save" - # expect(page.status_code).to equal 200 - expect(page).to have_content "Zea mirabila" - expect(page).to have_content 'crop was successfully created.' - end + it "Crop wranglers can delete scientific names" do + visit crop_path(zea_mays.crop) + click_link zea_mays.name + expect(page).to have_link "Delete", + href: scientific_name_path(zea_mays) + within('.scientific_names') do + accept_confirm do + click_link 'Delete' + end + end + # expect(page.status_code).to equal 200 + expect(page).not_to have_content zea_mays.name + expect(page).to have_content 'Scientific name was successfully deleted.' + end - it "The show-scientific-name page works" do - visit scientific_name_path(zea_mays) - # expect(page.status_code).to equal 200 - expect(page).to have_link zea_mays.crop.name, - href: crop_path(zea_mays.crop) - end + it "Crop wranglers can add scientific names" do + visit crop_path(crop) + expect(page).to have_link "Add", + href: new_scientific_name_path(crop_id: crop.id) + within('.scientific_names') { click_on "Add" } + # expect(page.status_code).to equal 200 + expect(page).to have_css "option[value='#{crop.id}'][selected=selected]" + fill_in 'Name', with: "Zea mirabila" + click_on "Save" + # expect(page.status_code).to equal 200 + expect(page).to have_content "Zea mirabila" + expect(page).to have_content 'crop was successfully created.' + end - context "When scientific name is pending" do - let(:pending_crop) { create :crop_request } - let(:pending_sci_name) { create :scientific_name, crop: pending_crop } + it "The show-scientific-name page works" do + visit scientific_name_path(zea_mays) + # expect(page.status_code).to equal 200 + expect(page).to have_link zea_mays.crop.name, + href: crop_path(zea_mays.crop) + end - it "Displays crop pending message" do - visit scientific_name_path(pending_sci_name) - expect(page).to have_content "This crop is currently pending approval" + context "When scientific name is pending" do + let(:pending_crop) { create :crop_request } + let(:pending_sci_name) { create :scientific_name, crop: pending_crop } + + it "Displays crop pending message" do + visit scientific_name_path(pending_sci_name) + expect(page).to have_content "This crop is currently pending approval" + end end end end diff --git a/spec/features/gardens/actions_spec.rb b/spec/features/gardens/actions_spec.rb index 0e53e178b..98f37adcd 100644 --- a/spec/features/gardens/actions_spec.rb +++ b/spec/features/gardens/actions_spec.rb @@ -5,73 +5,72 @@ describe "Gardens" do context 'logged in' do subject { page } - let(:member) { FactoryBot.create :member } - before { login_as member } + include_context 'signed in member' do + let(:garden) { member.gardens.first } + let(:other_member_garden) { FactoryBot.create :garden } - let(:garden) { member.gardens.first } - let(:other_member_garden) { FactoryBot.create :garden } + describe '#index' do + shared_examples "has buttons bar at top" do + it "has buttons bar at top" do + within '.layout-actions' do + expect(subject).to have_link 'Add a garden' + expect(subject).to have_link 'My gardens' + expect(subject).to have_link "Everyone's gardens" + end + end + end - describe '#index' do - shared_examples "has buttons bar at top" do - it "has buttons bar at top" do - within '.layout-actions' do - expect(subject).to have_link 'Add a garden' - expect(subject).to have_link 'My gardens' - expect(subject).to have_link "Everyone's gardens" + context 'my gardens' do + before { visit gardens_path(member_slug: member.slug) } + + include_examples "has buttons bar at top" + + context 'with actions menu expanded' do + before { click_link 'Actions' } + it "has actions on garden" do + expect(subject).to have_link 'Plant something here' + expect(subject).to have_link 'Mark as inactive' + expect(subject).to have_link 'Edit' + expect(subject).to have_link 'Add photo' + expect(subject).to have_link 'Delete' + end + end + end + + context 'all gardens' do + before { visit gardens_path } + + include_examples "has buttons bar at top" + end + + context "other member's garden" do + before { visit gardens_path(member_slug: FactoryBot.create(:member).slug) } + + include_examples "has buttons bar at top" + describe 'does not show actions on other member garden' do + it { is_expected.not_to have_link 'Actions' } end end end - context 'my gardens' do - before { visit gardens_path(member_slug: member.slug) } + describe '#show' do + describe 'my garden' do + before { visit garden_path(garden) } - include_examples "has buttons bar at top" - - context 'with actions menu expanded' do - before { click_link 'Actions' } - it "has actions on garden" do - expect(subject).to have_link 'Plant something here' - expect(subject).to have_link 'Mark as inactive' - expect(subject).to have_link 'Edit' - expect(subject).to have_link 'Add photo' - expect(subject).to have_link 'Delete' + context 'with actions menu expanded' do + before { click_link 'Actions' } + it { is_expected.to have_link 'Edit' } + it { is_expected.to have_link 'Delete' } + it { is_expected.to have_content "Plant something here" } + it { is_expected.to have_content "Add photo" } end end - end - context 'all gardens' do - before { visit gardens_path } - - include_examples "has buttons bar at top" - end - - context "other member's garden" do - before { visit gardens_path(member_slug: FactoryBot.create(:member).slug) } - - include_examples "has buttons bar at top" - describe 'does not show actions on other member garden' do + describe "someone else's garden" do + before { visit garden_path(other_member_garden) } it { is_expected.not_to have_link 'Actions' } end end end - - describe '#show' do - describe 'my garden' do - before { visit garden_path(garden) } - - context 'with actions menu expanded' do - before { click_link 'Actions' } - it { is_expected.to have_link 'Edit' } - it { is_expected.to have_link 'Delete' } - it { is_expected.to have_content "Plant something here" } - it { is_expected.to have_content "Add photo" } - end - end - - describe "someone else's garden" do - before { visit garden_path(other_member_garden) } - it { is_expected.not_to have_link 'Actions' } - end - end end end diff --git a/spec/features/gardens/adding_gardens_spec.rb b/spec/features/gardens/adding_gardens_spec.rb index bb161e4fd..47f521fd1 100644 --- a/spec/features/gardens/adding_gardens_spec.rb +++ b/spec/features/gardens/adding_gardens_spec.rb @@ -2,37 +2,34 @@ require 'rails_helper' require 'custom_matchers' describe "Gardens", :js do - let(:member) { FactoryBot.create :member } + include_context 'signed in member' do + before { visit new_garden_path } - before do - login_as member - visit new_garden_path - end + it "has the required fields help text" do + expect(page).to have_content "* denotes a required field" + end - it "has the required fields help text" do - expect(page).to have_content "* denotes a required field" - end + it "displays required and optional fields properly" do + expect(page).to have_selector ".required", text: "Name" + expect(page).to have_selector 'textarea#garden_description' + expect(page).to have_selector 'input#garden_location' + expect(page).to have_selector 'input#garden_area' + end - it "displays required and optional fields properly" do - expect(page).to have_selector ".required", text: "Name" - expect(page).to have_selector 'textarea#garden_description' - expect(page).to have_selector 'input#garden_location' - expect(page).to have_selector 'input#garden_area' - end + it "Create new garden" do + fill_in "Name", with: "New garden" + click_button "Save" + expect(page).to have_content "Garden was successfully created" + expect(page).to have_content "New garden" + end - it "Create new garden" do - fill_in "Name", with: "New garden" - click_button "Save" - expect(page).to have_content "Garden was successfully created" - expect(page).to have_content "New garden" - end - - it "Refuse to create new garden with negative area" do - visit new_garden_path - fill_in "Name", with: "Negative Garden" - fill_in "Area", with: -5 - click_button "Save" - expect(page).not_to have_content "Garden was successfully created" - expect(page).to have_content "Area must be greater than or equal to 0" + it "Refuse to create new garden with negative area" do + visit new_garden_path + fill_in "Name", with: "Negative Garden" + fill_in "Area", with: -5 + click_button "Save" + expect(page).not_to have_content "Garden was successfully created" + expect(page).to have_content "Area must be greater than or equal to 0" + end end end diff --git a/spec/features/gardens/gardens_spec.rb b/spec/features/gardens/gardens_spec.rb index f39c210f6..fdb517b08 100644 --- a/spec/features/gardens/gardens_spec.rb +++ b/spec/features/gardens/gardens_spec.rb @@ -1,121 +1,119 @@ require 'rails_helper' describe "Planting a crop", js: true do - # name is aaa to ensure it is ordered first - let!(:garden) { create :garden, name: 'aaa' } - let!(:planting) { create :planting, garden: garden, owner: garden.owner, planted_at: Date.parse("2013-3-10") } - let!(:tomato) { create :tomato } - let!(:finished_planting) { create :finished_planting, owner: garden.owner, garden: garden, crop: tomato } + include_context 'signed in member' do + # name is aaa to ensure it is ordered first + let!(:garden) { create :garden, name: 'aaa', owner: member } + let!(:planting) { create :planting, garden: garden, owner: garden.owner, planted_at: Date.parse("2013-3-10") } + let!(:tomato) { create :tomato } + let!(:finished_planting) { create :finished_planting, owner: garden.owner, garden: garden, crop: tomato } - before do - login_as garden.owner - end - - it "View gardens" do - visit gardens_path - expect(page).to have_content "Everyone's gardens" - within '.layout-actions' do - click_link "My gardens" - end - expect(page).to have_content "#{garden.owner.login_name}'s gardens" - within '.layout-actions' do - click_link "Everyone's gardens" - end - expect(page).to have_content "Everyone's gardens" - end - - it "Marking a garden as inactive" do - visit garden_path(garden) - click_link 'Actions' - accept_confirm do - click_link "Mark as inactive" - end - expect(page).to have_content "Garden was successfully updated" - expect(page).to have_content "This garden is inactive" - - click_link 'Actions' - expect(page).to have_content "Mark as active" - expect(page).not_to have_content "Mark as inactive" - end - - it "List only active gardens" do - visit garden_path(garden) - click_link 'Actions' - accept_confirm do - click_link "Mark as inactive" - end - visit gardens_path - expect(page).not_to have_link garden_path(garden) - end - - it "Create new garden" do - visit new_garden_path - fill_in "Name", with: "New garden" - click_button "Save" - expect(page).to have_content "Garden was successfully created" - expect(page).to have_content "New garden" - end - - it "Refuse to create new garden with negative area" do - visit new_garden_path - fill_in "Name", with: "Negative Garden" - fill_in "Area", with: -5 - click_button "Save" - expect(page).not_to have_content "Garden was successfully created" - expect(page).to have_content "Area must be greater than or equal to 0" - end - - context "Clicking edit from the index page" do - before do + it "View gardens" do visit gardens_path + expect(page).to have_content "Everyone's gardens" + within '.layout-actions' do + click_link "My gardens" + end + expect(page).to have_content "#{garden.owner.login_name}'s gardens" + within '.layout-actions' do + click_link "Everyone's gardens" + end + expect(page).to have_content "Everyone's gardens" end - it "button on index to edit garden" do - first('a#garden-actions-button').click - click_link href: edit_garden_path(garden) - expect(page).to have_content 'Edit garden' - end - end - - it "Edit garden" do - visit new_garden_path - fill_in "Name", with: "New garden" - click_button "Save" - click_link 'Actions' - within '.garden-actions' do - click_link 'Edit' - end - fill_in "Name", with: "Different name" - click_button "Save" - expect(page).to have_content "Garden was successfully updated" - expect(page).to have_content "Different name" - end - - it "Delete garden" do - visit new_garden_path - fill_in "Name", with: "New garden" - click_button "Save" - visit garden_path(Garden.last) - click_link 'Actions' - accept_confirm do - click_link 'Delete' - end - expect(page).to have_content "Garden was successfully deleted" - expect(page).to have_content "#{garden.owner}'s gardens" - end - - describe "Making a planting inactive from garden show" do - it do + it "Marking a garden as inactive" do visit garden_path(garden) - click_link(class: 'planting-menu') - click_link "Mark as finished" - find(".datepicker-days td.day", text: "21").click - expect(page).to have_content 'Finished' - end - end + click_link 'Actions' + accept_confirm do + click_link "Mark as inactive" + end + expect(page).to have_content "Garden was successfully updated" + expect(page).to have_content "This garden is inactive" - it "List only active plantings on a garden" do - visit gardens_path - expect(page).not_to have_content finished_planting.crop_name + click_link 'Actions' + expect(page).to have_content "Mark as active" + expect(page).not_to have_content "Mark as inactive" + end + + it "List only active gardens" do + visit garden_path(garden) + click_link 'Actions' + accept_confirm do + click_link "Mark as inactive" + end + visit gardens_path + expect(page).not_to have_link garden_path(garden) + end + + it "Create new garden" do + visit new_garden_path + fill_in "Name", with: "New garden" + click_button "Save" + expect(page).to have_content "Garden was successfully created" + expect(page).to have_content "New garden" + end + + it "Refuse to create new garden with negative area" do + visit new_garden_path + fill_in "Name", with: "Negative Garden" + fill_in "Area", with: -5 + click_button "Save" + expect(page).not_to have_content "Garden was successfully created" + expect(page).to have_content "Area must be greater than or equal to 0" + end + + context "Clicking edit from the index page" do + before do + visit gardens_path + end + + it "button on index to edit garden" do + first('a#garden-actions-button').click + click_link href: edit_garden_path(garden) + expect(page).to have_content 'Edit garden' + end + end + + it "Edit garden" do + visit new_garden_path + fill_in "Name", with: "New garden" + click_button "Save" + click_link 'Actions' + within '.garden-actions' do + click_link 'Edit' + end + fill_in "Name", with: "Different name" + click_button "Save" + expect(page).to have_content "Garden was successfully updated" + expect(page).to have_content "Different name" + end + + it "Delete garden" do + visit new_garden_path + fill_in "Name", with: "New garden" + click_button "Save" + visit garden_path(Garden.last) + click_link 'Actions' + accept_confirm do + click_link 'Delete' + end + expect(page).to have_content "Garden was successfully deleted" + expect(page).to have_content "#{garden.owner}'s gardens" + end + + describe "Making a planting inactive from garden show" do + it do + visit garden_path(garden) + click_link(class: 'planting-menu') + click_link "Mark as finished" + find(".datepicker-days td.day", text: "21").click + expect(page).to have_content 'Finished' + end + end + + it "List only active plantings on a garden" do + visit gardens_path + expect(page).not_to have_content finished_planting.crop_name + end end end diff --git a/spec/features/gardens/index_spec.rb b/spec/features/gardens/index_spec.rb index e14bbbc5d..39b422d25 100644 --- a/spec/features/gardens/index_spec.rb +++ b/spec/features/gardens/index_spec.rb @@ -3,68 +3,68 @@ require 'custom_matchers' describe "Gardens#index", :js do context "Logged in as member" do - let(:member) { FactoryBot.create :member, login_name: 'shadow' } + include_context 'signed in member' do + let(:member) { FactoryBot.create :member, login_name: 'shadow' } - before { login_as member } + context "with 10 gardens" do + before do + FactoryBot.create_list :garden, 10, owner: member + visit member_gardens_path(member_slug: member.slug) + end - context "with 10 gardens" do - before do - FactoryBot.create_list :garden, 10, owner: member - visit member_gardens_path(member_slug: member.slug) - end - - it "displays each of the gardens" do - member.gardens.each do |garden| - expect(page).to have_text garden.name + it "displays each of the gardens" do + member.gardens.each do |garden| + expect(page).to have_text garden.name + end + end + it "links to each garden" do + member.gardens.each do |garden| + expect(page).to have_link(garden.name, href: garden_path(garden)) + end end end - it "links to each garden" do - member.gardens.each do |garden| - expect(page).to have_link(garden.name, href: garden_path(garden)) + + context "with inactive gardens" do + let!(:active_garden) { FactoryBot.create :garden, name: "My active garden", owner: member } + let!(:inactive_garden) { FactoryBot.create :inactive_garden, name: "retired garden", owner: member } + + before { visit member_gardens_path(member_slug: member.slug) } + + it "show active garden" do + expect(page).to have_text active_garden.name + end + it "does not show inactive garden" do + expect(page).not_to have_text inactive_garden.name + end + it "links to active garden" do + expect(page).to have_link(active_garden.name, href: garden_path(active_garden)) + end + it "does not link to inactive gardens" do + expect(page).not_to have_link(inactive_garden.name, href: garden_path(inactive_garden)) end end - end - context "with inactive gardens" do - let!(:active_garden) { FactoryBot.create :garden, name: "My active garden", owner: member } - let!(:inactive_garden) { FactoryBot.create :inactive_garden, name: "retired garden", owner: member } + context 'with plantings' do + let(:maize) { FactoryBot.create(:maize) } + let(:tomato) { FactoryBot.create(:tomato) } - before { visit member_gardens_path(member_slug: member.slug) } + let!(:planting) do + FactoryBot.create :planting, owner: member, crop: maize, garden: member.gardens.first + end + let!(:finished_planting) do + FactoryBot.create :finished_planting, owner: member, crop: tomato, garden: member.gardens.first + end - it "show active garden" do - expect(page).to have_text active_garden.name - end - it "does not show inactive garden" do - expect(page).not_to have_text inactive_garden.name - end - it "links to active garden" do - expect(page).to have_link(active_garden.name, href: garden_path(active_garden)) - end - it "does not link to inactive gardens" do - expect(page).not_to have_link(inactive_garden.name, href: garden_path(inactive_garden)) - end - end + before do + visit member_gardens_path(member_slug: member.slug) + end - context 'with plantings' do - let(:maize) { FactoryBot.create(:maize) } - let(:tomato) { FactoryBot.create(:tomato) } - - let!(:planting) do - FactoryBot.create :planting, owner: member, crop: maize, garden: member.gardens.first - end - let!(:finished_planting) do - FactoryBot.create :finished_planting, owner: member, crop: tomato, garden: member.gardens.first - end - - before do - visit member_gardens_path(member_slug: member.slug) - end - - it "shows planting in garden" do - expect(page).to have_link(planting.crop.name, href: planting_path(planting)) - end - it "does not show finished planting" do - expect(page).not_to have_text(finished_planting.crop.name) + it "shows planting in garden" do + expect(page).to have_link(planting.crop.name, href: planting_path(planting)) + end + it "does not show finished planting" do + expect(page).not_to have_text(finished_planting.crop.name) + end end end end diff --git a/spec/features/harvests/browse_harvests_spec.rb b/spec/features/harvests/browse_harvests_spec.rb index 67dc75e55..bc6b29078 100644 --- a/spec/features/harvests/browse_harvests_spec.rb +++ b/spec/features/harvests/browse_harvests_spec.rb @@ -3,30 +3,29 @@ require 'rails_helper' describe "browse harvests" do subject { page } - let!(:member) { create :member } let!(:harvest) { create :harvest, owner: member } - before { login_as member } + include_context 'signed in member' do + describe 'blank optional fields' do + let!(:harvest) { create :harvest, :no_description } - describe 'blank optional fields' do - let!(:harvest) { create :harvest, :no_description } + before { visit harvests_path } - before { visit harvests_path } - - it 'read more' do - expect(subject).not_to have_link "Read more" - end - end - - describe "filled in optional fields" do - let!(:harvest) { create :harvest, :long_description } - - before do - visit harvests_path + it 'read more' do + expect(subject).not_to have_link "Read more" + end end - it 'links to #show' do - expect(subject).to have_link harvest.crop.name, href: harvest_path(harvest) + describe "filled in optional fields" do + let!(:harvest) { create :harvest, :long_description } + + before do + visit harvests_path + end + + it 'links to #show' do + expect(subject).to have_link harvest.crop.name, href: harvest_path(harvest) + end end end end diff --git a/spec/features/harvests/harvesting_a_crop_spec.rb b/spec/features/harvests/harvesting_a_crop_spec.rb index c425dfa4f..d3ded52e1 100644 --- a/spec/features/harvests/harvesting_a_crop_spec.rb +++ b/spec/features/harvests/harvesting_a_crop_spec.rb @@ -2,128 +2,126 @@ require 'rails_helper' require 'custom_matchers' describe "Harvesting a crop", :js, :elasticsearch do - let(:member) { create :member } - let!(:maize) { create :maize } - let!(:plant_part) { create :plant_part } - let(:planting) { create :planting, crop: maize, owner: member } + include_context 'signed in member' do + let!(:maize) { create :maize } + let!(:plant_part) { create :plant_part } + let(:planting) { create :planting, crop: maize, owner: member } - before do - login_as member - visit new_harvest_path - end + before { visit new_harvest_path } - it_behaves_like "crop suggest", "harvest", "crop" + it_behaves_like "crop suggest", "harvest", "crop" - it "has the required fields help text" do - expect(page).to have_content "* denotes a required field" - end - - describe "displays required and optional fields properly" do - it { expect(page).to have_selector ".required", text: "What did you harvest?" } - it { expect(page).to have_selector 'input#harvest_quantity' } - it { expect(page).to have_selector 'input#harvest_weight_quantity' } - it { expect(page).to have_selector 'textarea#harvest_description' } - end - - it "Creating a new harvest", :js do - fill_autocomplete "crop", with: "mai" - select_from_autocomplete "maize" - - within "form#new_harvest" do - choose plant_part.name - fill_in "When?", with: "2014-06-15" - fill_in "How many?", with: 42 - fill_in "Weighing (in total)", with: 42 - fill_in "Notes", with: "It's killer." - click_button "Save" + it "has the required fields help text" do + expect(page).to have_content "* denotes a required field" end - expect(page).to have_content "harvest was successfully created." - end + describe "displays required and optional fields properly" do + it { expect(page).to have_selector ".required", text: "What did you harvest?" } + it { expect(page).to have_selector 'input#harvest_quantity' } + it { expect(page).to have_selector 'input#harvest_weight_quantity' } + it { expect(page).to have_selector 'textarea#harvest_description' } + end - it "Clicking link to owner's profile" do - visit member_harvests_path(member) - click_link "View #{member}'s profile >>" - expect(current_path).to eq member_path member - end + it "Creating a new harvest", :js do + fill_autocomplete "crop", with: "mai" + select_from_autocomplete "maize" - describe "Harvesting from crop page" do - before do - visit crop_path(maize) - within '.crop-actions' do - click_link "Harvest #{maize.name}" - end within "form#new_harvest" do choose plant_part.name - expect(page).to have_selector "input[value='maize']" + fill_in "When?", with: "2014-06-15" + fill_in "How many?", with: 42 + fill_in "Weighing (in total)", with: 42 + fill_in "Notes", with: "It's killer." click_button "Save" end + + expect(page).to have_content "harvest was successfully created." + end + + it "Clicking link to owner's profile" do + visit member_harvests_path(member) + click_link "View #{member}'s profile >>" + expect(current_path).to eq member_path member + end + + describe "Harvesting from crop page" do + before do + visit crop_path(maize) + within '.crop-actions' do + click_link "Harvest #{maize.name}" + end + within "form#new_harvest" do + choose plant_part.name + expect(page).to have_selector "input[value='maize']" + click_button "Save" + end + end + + it { expect(page).to have_content "harvest was successfully created." } + it { expect(page).to have_content "maize" } + end + + describe "Harvesting from planting page" do + let!(:planting) { create :planting, crop: maize, owner: member, garden: member.gardens.first } + before do + visit planting_path(planting) + click_link "Record Harvest" + + choose plant_part.name + click_button "Save" + end + + it { expect(page).to have_content "harvest was successfully created." } + it { expect(page).to have_content planting.garden.name } + it { expect(page).to have_content "maize" } + end + + context "Editing a harvest" do + let(:existing_harvest) { create :harvest, crop: maize, owner: member } + let!(:other_plant_part) { create :plant_part, name: 'chocolate' } + + before do + visit harvest_path(existing_harvest) + click_link 'Actions' + click_link "Edit" + end + + it "Saving without edits" do + # Check that the autosuggest helper properly fills inputs with + # existing resource's data + click_button "Save" + expect(page).to have_content "harvest was successfully updated." + expect(page).to have_content "maize" + end + + it "change plant part" do + choose other_plant_part.name + click_button "Save" + expect(page).to have_content "harvest was successfully updated." + expect(page).to have_content other_plant_part.name + end end - it { expect(page).to have_content "harvest was successfully created." } - it { expect(page).to have_content "maize" } - end + context "Viewing a harvest" do + let(:existing_harvest) do + create :harvest, crop: maize, owner: member, + harvested_at: Time.zone.today + end + let!(:existing_planting) do + create :planting, crop: maize, owner: member, + planted_at: Time.zone.yesterday + end - describe "Harvesting from planting page" do - let!(:planting) { create :planting, crop: maize, owner: member, garden: member.gardens.first } - before do - visit planting_path(planting) - click_link "Record Harvest" + before do + visit harvest_path(existing_harvest) + end - choose plant_part.name - click_button "Save" - end - - it { expect(page).to have_content "harvest was successfully created." } - it { expect(page).to have_content planting.garden.name } - it { expect(page).to have_content "maize" } - end - - context "Editing a harvest" do - let(:existing_harvest) { create :harvest, crop: maize, owner: member } - let!(:other_plant_part) { create :plant_part, name: 'chocolate' } - - before do - visit harvest_path(existing_harvest) - click_link 'Actions' - click_link "Edit" - end - - it "Saving without edits" do - # Check that the autosuggest helper properly fills inputs with - # existing resource's data - click_button "Save" - expect(page).to have_content "harvest was successfully updated." - expect(page).to have_content "maize" - end - - it "change plant part" do - choose other_plant_part.name - click_button "Save" - expect(page).to have_content "harvest was successfully updated." - expect(page).to have_content other_plant_part.name - end - end - - context "Viewing a harvest" do - let(:existing_harvest) do - create :harvest, crop: maize, owner: member, - harvested_at: Time.zone.today - end - let!(:existing_planting) do - create :planting, crop: maize, owner: member, - planted_at: Time.zone.yesterday - end - - before do - visit harvest_path(existing_harvest) - end - - it "linking to a planting" do - expect(page).to have_content existing_planting.to_s - choose("harvest_planting_id_#{existing_planting.id}") - click_button "save" - expect(page).to have_link(href: planting_path(existing_planting)) + it "linking to a planting" do + expect(page).to have_content existing_planting.to_s + choose("harvest_planting_id_#{existing_planting.id}") + click_button "save" + expect(page).to have_link(href: planting_path(existing_planting)) + end end end end diff --git a/spec/features/home/home_spec.rb b/spec/features/home/home_spec.rb index 89dbacdc5..42d354f14 100644 --- a/spec/features/home/home_spec.rb +++ b/spec/features/home/home_spec.rb @@ -79,17 +79,17 @@ describe "home page" do end context "when signed in" do - before { login_as member } + include_context 'signed in member' do + include_examples 'show crops' + include_examples 'show plantings' + include_examples 'show harvests' + include_examples 'shows seeds' - include_examples 'show crops' - include_examples 'show plantings' - include_examples 'show harvests' - include_examples 'shows seeds' + describe 'should say welcome' do + before { visit root_path } - describe 'should say welcome' do - before { visit root_path } - - it { expect(page).to have_content "Welcome to #{ENV['GROWSTUFF_SITE_NAME']}, #{member.login_name}" } + it { expect(page).to have_content "Welcome to #{ENV['GROWSTUFF_SITE_NAME']}, #{member.login_name}" } + end end end end diff --git a/spec/features/likeable_spec.rb b/spec/features/likeable_spec.rb index 42aa03c6b..068fcba77 100644 --- a/spec/features/likeable_spec.rb +++ b/spec/features/likeable_spec.rb @@ -6,9 +6,7 @@ describe 'Likeable', js: true do let!(:post) { FactoryBot.create(:post, author: member) } let!(:photo) { FactoryBot.create(:photo, owner: member) } - context 'logged in member' do - before { login_as member } - + include_context 'signed in member' do describe 'photos' do let(:like_count_class) { "#photo-#{photo.id} .like-count" } diff --git a/spec/features/members/ban_spec.rb b/spec/features/members/ban_spec.rb index 8eb2888e7..256083a3e 100644 --- a/spec/features/members/ban_spec.rb +++ b/spec/features/members/ban_spec.rb @@ -4,18 +4,17 @@ describe "members list" do let!(:spammer) { FactoryBot.create :member } let!(:admin) { FactoryBot.create :admin_member } - context 'logged in as admin' do - before do - login_as admin - visit member_path(spammer) - end - it { expect(page).to have_link "Ban member" } - describe 'bans the user' do - before do - accept_confirm { click_link 'Ban member' } + context 'logged in as admin' do + include_context 'signed in admin' do + before { visit member_path(spammer) } + it { expect(page).to have_link "Ban member" } + describe 'bans the user' do + before do + accept_confirm { click_link 'Ban member' } + end + it { expect(page).to have_link admin.login_name } + it { expect(page).not_to have_link spammer.login_name } end - it { expect(page).to have_link admin.login_name } - it { expect(page).not_to have_link spammer.login_name } end end end diff --git a/spec/features/members/following_spec.rb b/spec/features/members/following_spec.rb index 762320671..fea8b5a7f 100644 --- a/spec/features/members/following_spec.rb +++ b/spec/features/members/following_spec.rb @@ -12,65 +12,62 @@ describe "follows", :js do end context "when signed in" do - let(:member) { create :member } - let(:other_member) { create :member } + include_context 'signed in member' do + let(:other_member) { create :member } - before do - login_as(member) - end - - it "your profile doesn't have a follow button" do - visit member_path(member) - expect(page).not_to have_link "Follow" - expect(page).not_to have_link "Unfollow" - end - - context "following another member" do - before { visit member_path(other_member) } - - it "has a follow button" do - expect(page).to have_link "Follow", href: follows_path(followed: other_member.slug) + it "your profile doesn't have a follow button" do + visit member_path(member) + expect(page).not_to have_link "Follow" + expect(page).not_to have_link "Unfollow" end - it "has correct message and unfollow button" do - click_link 'Follow' - expect(page).to have_content "Followed #{other_member.login_name}" - expect(page).to have_link "Unfollow", href: follow_path(member.get_follow(other_member)) - end + context "following another member" do + before { visit member_path(other_member) } - it "has a followed member listed in the following page" do - click_link 'Follow' - visit member_follows_path(member) - expect(page).to have_content other_member.login_name - end + it "has a follow button" do + expect(page).to have_link "Follow", href: follows_path(followed: other_member.slug) + end - it "has correct message and follow button after unfollow" do - click_link 'Follow' - click_link 'Unfollow' - expect(page).to have_content "Unfollowed #{other_member.login_name}" - visit member_path(other_member) # unfollowing redirects to root - expect(page).to have_link "Follow", href: follows_path(followed: other_member.slug) - end + it "has correct message and unfollow button" do + click_link 'Follow' + expect(page).to have_content "Followed #{other_member.login_name}" + expect(page).to have_link "Unfollow", href: follow_path(member.get_follow(other_member)) + end - it "has member in following list" do - click_link 'Follow' - visit member_follows_path(member) - expect(page).to have_content other_member.login_name - end + it "has a followed member listed in the following page" do + click_link 'Follow' + visit member_follows_path(member) + expect(page).to have_content other_member.login_name + end - it "appears in in followed member's followers list" do - click_link 'Follow' - visit member_followers_path(other_member) - expect(page).to have_content member.login_name - end + it "has correct message and follow button after unfollow" do + click_link 'Follow' + click_link 'Unfollow' + expect(page).to have_content "Unfollowed #{other_member.login_name}" + visit member_path(other_member) # unfollowing redirects to root + expect(page).to have_link "Follow", href: follows_path(followed: other_member.slug) + end - it "removes members from following and followers lists after unfollow" do - click_link 'Follow' - click_link 'Unfollow' - visit member_follows_path(member) - expect(page).not_to have_content other_member.login_name - visit member_followers_path(other_member) - expect(page).to have_content member.login_name + it "has member in following list" do + click_link 'Follow' + visit member_follows_path(member) + expect(page).to have_content other_member.login_name + end + + it "appears in in followed member's followers list" do + click_link 'Follow' + visit member_followers_path(other_member) + expect(page).to have_content member.login_name + end + + it "removes members from following and followers lists after unfollow" do + click_link 'Follow' + click_link 'Unfollow' + visit member_follows_path(member) + expect(page).not_to have_content other_member.login_name + visit member_followers_path(other_member) + expect(page).to have_content member.login_name + end end end end diff --git a/spec/features/members/profile_spec.rb b/spec/features/members/profile_spec.rb index 6b6ab0f94..a2296b247 100644 --- a/spec/features/members/profile_spec.rb +++ b/spec/features/members/profile_spec.rb @@ -162,26 +162,26 @@ describe "member profile", js: true do end context "signed in member" do - before { login_as(member) } + include_context 'signed in member' do + include_examples 'member details' + include_examples 'member activity' - include_examples 'member details' - include_examples 'member activity' + context "your own profile page" do + before { visit member_path(member) } - context "your own profile page" do - before { visit member_path(member) } - - it "has a button to edit profile" do - expect(page).to have_link "Edit profile", href: edit_member_registration_path + it "has a button to edit profile" do + expect(page).to have_link "Edit profile", href: edit_member_registration_path + end end - end - context "someone else's profile page" do - before { visit member_path(other_member) } + context "someone else's profile page" do + before { visit member_path(other_member) } - it "has a private message button" do - expect(page).to have_link "Send message", href: new_notification_path(recipient_id: other_member.id) + it "has a private message button" do + expect(page).to have_link "Send message", href: new_notification_path(recipient_id: other_member.id) + end + it { expect(page).not_to have_link "Edit profile", href: edit_member_registration_path } end - it { expect(page).not_to have_link "Edit profile", href: edit_member_registration_path } end end end diff --git a/spec/features/notifications_spec.rb b/spec/features/notifications_spec.rb index dc149c7d9..1ab31dc30 100644 --- a/spec/features/notifications_spec.rb +++ b/spec/features/notifications_spec.rb @@ -4,59 +4,60 @@ describe "Notifications", :js do let(:sender) { create :member } let(:recipient) { create :member, login_name: 'beyonce' } - context "On existing notification" do - let!(:notification) do - create :notification, - sender: sender, - recipient: recipient, - body: "Notification body", - post_id: nil + include_context 'signed in member' do + let(:member) { recipient } + + context "On existing notification" do + let!(:notification) do + create :notification, + sender: sender, + recipient: recipient, + body: "Notification body", + post_id: nil + end + before do + visit root_path + click_link 'Your Stuff' + Percy.snapshot(page, name: "notification menu") + visit notification_path(notification) + Percy.snapshot(page, name: "notifications#show") + end + + it "Replying to the notification" do + click_link "Reply" + expect(page).to have_content "Notification body" + Percy.snapshot(page, name: 'Replying to notification') + + fill_in 'notification_body', with: "Response body" + Percy.snapshot(page, name: "notifications#new") + click_button "Send" + + expect(page).to have_content "Message was successfully sent" + end end - before do - login_as recipient - visit root_path - click_link 'Your Stuff' - Percy.snapshot(page, name: "notification menu") - visit notification_path(notification) - Percy.snapshot(page, name: "notifications#show") - end + describe 'pagination' do + before do + FactoryBot.create_list :notification, 34, recipient: recipient + visit notifications_path + end - it "Replying to the notification" do - click_link "Reply" - expect(page).to have_content "Notification body" - Percy.snapshot(page, name: 'Replying to notification') + it do + Percy.snapshot(page, name: "notifications#index") + end - fill_in 'notification_body', with: "Response body" - Percy.snapshot(page, name: "notifications#new") - click_button "Send" + it 'has page navigation' do + expect(page).to have_selector 'a[rel="next"]' + end - expect(page).to have_content "Message was successfully sent" - end - end + it 'paginates at 30 notifications per page' do + expect(page).to have_selector '.message', count: 30 + end - describe 'pagination' do - before do - FactoryBot.create_list :notification, 34, recipient: recipient - login_as recipient - visit notifications_path - end - - it do - Percy.snapshot(page, name: "notifications#index") - end - - it 'has page navigation' do - expect(page).to have_selector 'a[rel="next"]' - end - - it 'paginates at 30 notifications per page' do - expect(page).to have_selector '.message', count: 30 - end - - it 'navigates pages' do - first('a[rel="next"]').click - expect(page).to have_selector '.message', count: 4 + it 'navigates pages' do + first('a[rel="next"]').click + expect(page).to have_selector '.message', count: 4 + end end end end diff --git a/spec/features/percy/percy_spec.rb b/spec/features/percy/percy_spec.rb index 7b614d169..a5968742f 100644 --- a/spec/features/percy/percy_spec.rb +++ b/spec/features/percy/percy_spec.rb @@ -235,152 +235,154 @@ rest of the garden. context 'when signed in' do let(:prefix) { 'signed-in' } - before { login_as member } - include_examples 'visit pages' + include_context 'signed in member' do + include_examples 'visit pages' - it 'load my plantings#show' do - planting = FactoryBot.create :planting, crop: tomato, owner: member, garden: member.gardens.first - visit planting_path(planting) - Percy.snapshot(page, name: "#{prefix}/self/plantings#show") - end - - it 'load my members#show' do - visit member_path(member) - Percy.snapshot(page, name: "#{prefix}/self/members#show") - end - - it 'load my gardens#show' do - garden = FactoryBot.create :garden, name: 'paradise', owner: member - visit garden_path(garden) - Percy.snapshot(page, name: "#{prefix}/self/gardens#show") - end - - describe '#new' do - it 'crops#new' do - visit new_crop_path - Percy.snapshot(page, name: "#{prefix}/crops#new") + it 'load my plantings#show' do + planting = FactoryBot.create :planting, crop: tomato, owner: member, garden: member.gardens.first + visit planting_path(planting) + Percy.snapshot(page, name: "#{prefix}/self/plantings#show") end - it 'gardens#new' do - visit new_garden_path - Percy.snapshot(page, name: "#{prefix}/gardens#new") + it 'load my members#show' do + visit member_path(member) + Percy.snapshot(page, name: "#{prefix}/self/members#show") end - it 'harvests#new' do - visit new_harvest_path - Percy.snapshot(page, name: "#{prefix}/harvests#new") - fill_in(id: 'crop', with: 'tom') - Percy.snapshot(page, name: "#{prefix}/harvests#new-autosuggest") + it 'load my gardens#show' do + garden = FactoryBot.create :garden, name: 'paradise', owner: member + visit garden_path(garden) + Percy.snapshot(page, name: "#{prefix}/self/gardens#show") end - it 'plantings#new' do - visit new_planting_path - Percy.snapshot(page, name: "#{prefix}/plantings#new") - fill_in(id: 'crop', with: 'tom') - Percy.snapshot(page, name: "#{prefix}/plantings#new-autosuggest") + describe '#new' do + it 'crops#new' do + visit new_crop_path + Percy.snapshot(page, name: "#{prefix}/crops#new") + end + + it 'gardens#new' do + visit new_garden_path + Percy.snapshot(page, name: "#{prefix}/gardens#new") + end + + it 'harvests#new' do + visit new_harvest_path + Percy.snapshot(page, name: "#{prefix}/harvests#new") + fill_in(id: 'crop', with: 'tom') + Percy.snapshot(page, name: "#{prefix}/harvests#new-autosuggest") + end + + it 'plantings#new' do + visit new_planting_path + Percy.snapshot(page, name: "#{prefix}/plantings#new") + fill_in(id: 'crop', with: 'tom') + Percy.snapshot(page, name: "#{prefix}/plantings#new-autosuggest") + end + + it 'seeds#new' do + visit new_seed_path + Percy.snapshot(page, name: "#{prefix}/seeds#new") + fill_in(id: 'crop', with: 'tom') + Percy.snapshot(page, name: "#{prefix}/seeds#new-autosuggest") + end + + it 'posts#new' do + visit new_post_path + Percy.snapshot(page, name: "#{prefix}/posts#new") + end end - it 'seeds#new' do - visit new_seed_path - Percy.snapshot(page, name: "#{prefix}/seeds#new") - fill_in(id: 'crop', with: 'tom') - Percy.snapshot(page, name: "#{prefix}/seeds#new-autosuggest") + describe '#edit' do + it 'loads gardens#edit' do + garden = FactoryBot.create :garden, owner: member + visit edit_garden_path(garden) + Percy.snapshot(page, name: "#{prefix}/gardens#edit") + end + + it 'loads harvests#edit' do + harvest = FactoryBot.create :harvest, owner: member + visit edit_harvest_path(harvest) + Percy.snapshot(page, name: "#{prefix}/harvests#edit") + end + + it 'loads planting#edit' do + planting = FactoryBot.create :planting, owner: member + visit edit_planting_path(planting) + Percy.snapshot(page, name: "#{prefix}/plantings#edit") + end + + it 'loads posts#edit' do + visit edit_post_path(post) + Percy.snapshot(page, name: "#{prefix}/posts#edit") + end + + it 'comments#new' do + visit new_comment_path(post_id: post.id) + Percy.snapshot(page, name: "comments#new") + end end - it 'posts#new' do - visit new_post_path - Percy.snapshot(page, name: "#{prefix}/posts#new") - end - end - - describe '#edit' do - it 'loads gardens#edit' do - garden = FactoryBot.create :garden, owner: member - visit edit_garden_path(garden) - Percy.snapshot(page, name: "#{prefix}/gardens#edit") - end - - it 'loads harvests#edit' do - harvest = FactoryBot.create :harvest, owner: member - visit edit_harvest_path(harvest) - Percy.snapshot(page, name: "#{prefix}/harvests#edit") - end - - it 'loads planting#edit' do - planting = FactoryBot.create :planting, owner: member - visit edit_planting_path(planting) - Percy.snapshot(page, name: "#{prefix}/plantings#edit") - end - - it 'loads posts#edit' do - visit edit_post_path(post) - Percy.snapshot(page, name: "#{prefix}/posts#edit") - end - - it 'comments#new' do - visit new_comment_path(post_id: post.id) - Percy.snapshot(page, name: "comments#new") - end - end - - describe 'expand menus' do - it 'expands crop menu' do - visit root_path - click_on 'Crops' - Percy.snapshot(page, name: "#{prefix}/crops-menu") - click_on 'Community' - Percy.snapshot(page, name: "#{prefix}/community-menu") - click_on 'percy' - Percy.snapshot(page, name: "#{prefix}/member-menu") + describe 'expand menus' do + it 'expands crop menu' do + visit root_path + click_on 'Crops' + Percy.snapshot(page, name: "#{prefix}/crops-menu") + click_on 'Community' + Percy.snapshot(page, name: "#{prefix}/community-menu") + click_on 'percy' + Percy.snapshot(page, name: "#{prefix}/member-menu") + end end end end context 'wrangling crops' do - let(:prefix) { 'crop-wrangler' } - before { login_as crop_wrangler } - let!(:candy) { FactoryBot.create :crop_request, name: 'candy' } + include_context 'signed in crop wrangler' do + let(:prefix) { 'crop-wrangler' } + let!(:candy) { FactoryBot.create :crop_request, name: 'candy' } - it 'crop wrangling page' do - visit wrangle_crops_path - Percy.snapshot(page, name: 'crops wrangle') - click_link 'Pending approval' - Percy.snapshot(page, name: 'crops pending approval') - click_link 'candy' - Percy.snapshot(page, name: 'editing pending crop') + it 'crop wrangling page' do + visit wrangle_crops_path + Percy.snapshot(page, name: 'crops wrangle') + click_link 'Pending approval' + Percy.snapshot(page, name: 'crops pending approval') + click_link 'candy' + Percy.snapshot(page, name: 'editing pending crop') + end end end + context 'admin' do - before do - login_as admin_user - visit admin_path - end - it 'admin page' do - Percy.snapshot(page, name: 'Admin') - end - it 'Roles' do - click_link 'Roles' - Percy.snapshot(page, name: 'Admin Roles') - end - it 'CMS' do - click_link 'CMS' - Percy.snapshot(page, name: 'CMS') - end - it 'Garden Types' do - click_link 'Garden Types' - Percy.snapshot(page, name: 'Admin Garden type') - end - it 'Alternate names' do - click_link 'Alternate names' - Percy.snapshot(page, name: 'Admin Alternate names') - end - it 'Scientific names' do - click_link 'Scientific names' - Percy.snapshot(page, name: 'Admin Scientific names') - end - it 'Members' do - click_link 'Members' - Percy.snapshot(page, name: 'Admin Members') + include_context 'signed in admin' do + before { visit admin_path } + it 'admin page' do + Percy.snapshot(page, name: 'Admin') + end + it 'Roles' do + click_link 'Roles' + Percy.snapshot(page, name: 'Admin Roles') + end + it 'CMS' do + click_link 'CMS' + Percy.snapshot(page, name: 'CMS') + end + it 'Garden Types' do + click_link 'Garden Types' + Percy.snapshot(page, name: 'Admin Garden type') + end + it 'Alternate names' do + click_link 'Alternate names' + Percy.snapshot(page, name: 'Admin Alternate names') + end + it 'Scientific names' do + click_link 'Scientific names' + Percy.snapshot(page, name: 'Admin Scientific names') + end + it 'Members' do + click_link 'Members' + Percy.snapshot(page, name: 'Admin Members') + end end end end diff --git a/spec/features/photos/new_photo_spec.rb b/spec/features/photos/new_photo_spec.rb index de0ae5664..4bf64065e 100644 --- a/spec/features/photos/new_photo_spec.rb +++ b/spec/features/photos/new_photo_spec.rb @@ -6,56 +6,56 @@ describe "new photo page" do context "signed in member" do let(:member) { FactoryBot.create :member } - before { login_as member } + include_context 'signed in member' do + context "viewing a planting" do + let(:planting) { FactoryBot.create :planting, owner: member } - context "viewing a planting" do - let(:planting) { FactoryBot.create :planting, owner: member } - - it "add photo" do - visit planting_path(planting) - click_link 'Actions' - within '.planting-actions' do - click_link('Add photo') + it "add photo" do + visit planting_path(planting) + click_link 'Actions' + within '.planting-actions' do + click_link('Add photo') + end + expect(page).to have_text planting.crop.name + Percy.snapshot(page, name: 'Add photo to planting') end - expect(page).to have_text planting.crop.name - Percy.snapshot(page, name: 'Add photo to planting') end - end - context "viewing a harvest" do - let(:harvest) { FactoryBot.create :harvest, owner: member } + context "viewing a harvest" do + let(:harvest) { FactoryBot.create :harvest, owner: member } - it "add photo" do - visit harvest_path(harvest) - click_link 'Actions' - within '.harvest-actions' do - click_link "Add photo" + it "add photo" do + visit harvest_path(harvest) + click_link 'Actions' + within '.harvest-actions' do + click_link "Add photo" + end + expect(page).to have_text harvest.crop.name end - expect(page).to have_text harvest.crop.name end - end - context "viewing a garden" do - let(:garden) { FactoryBot.create :garden, owner: member } + context "viewing a garden" do + let(:garden) { FactoryBot.create :garden, owner: member } - it "add photo" do - visit garden_path(garden) - click_link 'Actions' - within '.garden-actions' do - click_link "Add photo" + it "add photo" do + visit garden_path(garden) + click_link 'Actions' + within '.garden-actions' do + click_link "Add photo" + end + expect(page).to have_text garden.name end - expect(page).to have_text garden.name end - end - describe "viewing a seed" do - let(:seed) { FactoryBot.create :seed, owner: member } + describe "viewing a seed" do + let(:seed) { FactoryBot.create :seed, owner: member } - it "add photo" do - visit seed_path(seed) - click_link 'Actions' - first('.seed-actions').click_link('Add photo') - expect(page).to have_text seed.to_s + it "add photo" do + visit seed_path(seed) + click_link 'Actions' + first('.seed-actions').click_link('Add photo') + expect(page).to have_text seed.to_s + end end end end diff --git a/spec/features/photos/show_photo_spec.rb b/spec/features/photos/show_photo_spec.rb index 2c027d57d..664b24aee 100644 --- a/spec/features/photos/show_photo_spec.rb +++ b/spec/features/photos/show_photo_spec.rb @@ -4,68 +4,68 @@ describe "show photo page" do context "signed in member" do let(:member) { create :member } - before { login_as member } + include_context 'signed in member' do + context "linked to planting" do + let(:planting) { create :planting } + let(:photo) { create :photo, owner: planting.owner } - context "linked to planting" do - let(:planting) { create :planting } - let(:photo) { create :photo, owner: planting.owner } + context "shows linkback to planting" do + before do + planting.photos << photo + visit photo_path(photo) + end - context "shows linkback to planting" do - before do - planting.photos << photo - visit photo_path(photo) + it { + expect(page).to have_link "#{planting.crop.name} planting in #{planting.garden.name} by #{planting.owner}", + href: planting_path(planting) + } + it { expect(page).to have_link planting.crop.name } end - - it { - expect(page).to have_link "#{planting.crop.name} planting in #{planting.garden.name} by #{planting.owner}", - href: planting_path(planting) - } - it { expect(page).to have_link planting.crop.name } end - end - context "linked to harvest" do - let(:photo) { create :photo, owner: harvest.owner } - let(:harvest) { create :harvest } + context "linked to harvest" do + let(:photo) { create :photo, owner: harvest.owner } + let(:harvest) { create :harvest } - context "shows linkback to harvest" do - before do - harvest.photos << photo - visit photo_path(photo) + context "shows linkback to harvest" do + before do + harvest.photos << photo + visit photo_path(photo) + end + + it { expect(page).to have_link "#{harvest.crop.name} harvest by #{harvest.owner}", href: harvest_path(harvest) } + it { expect(page).to have_link harvest.crop.name } end - - it { expect(page).to have_link "#{harvest.crop.name} harvest by #{harvest.owner}", href: harvest_path(harvest) } - it { expect(page).to have_link harvest.crop.name } end - end - context "linked to garden" do - let(:photo) { create :photo, owner: garden.owner } - let(:garden) { create :garden } + context "linked to garden" do + let(:photo) { create :photo, owner: garden.owner } + let(:garden) { create :garden } - context "shows linkback to garden" do - before do - garden.photos << photo - visit photo_path(photo) - Percy.snapshot(page, name: 'Show photo of a garden') + context "shows linkback to garden" do + before do + garden.photos << photo + visit photo_path(photo) + Percy.snapshot(page, name: 'Show photo of a garden') + end + + it { expect(page).to have_link "garden named \"#{garden.name}\" by #{garden.owner}", href: garden_path(garden) } end - - it { expect(page).to have_link "garden named \"#{garden.name}\" by #{garden.owner}", href: garden_path(garden) } end - end - context "linked to seed" do - let(:photo) { create :photo, owner: seed.owner } - let(:seed) { create :seed } + context "linked to seed" do + let(:photo) { create :photo, owner: seed.owner } + let(:seed) { create :seed } - context "shows linkback to seed" do - before do - seed.photos << photo - visit photo_path(photo) + context "shows linkback to seed" do + before do + seed.photos << photo + visit photo_path(photo) + end + + it { expect(page).to have_link "#{seed.crop.name} seeds belonging to #{seed.owner}", href: seed_path(seed) } + it { expect(page).to have_link seed.crop.name } end - - it { expect(page).to have_link "#{seed.crop.name} seeds belonging to #{seed.owner}", href: seed_path(seed) } - it { expect(page).to have_link seed.crop.name } end end end diff --git a/spec/features/places/searching_a_place_spec.rb b/spec/features/places/searching_a_place_spec.rb index fa64ea568..0a5ba110a 100644 --- a/spec/features/places/searching_a_place_spec.rb +++ b/spec/features/places/searching_a_place_spec.rb @@ -26,32 +26,33 @@ describe "User searches" do end describe "Nearby plantings, seed, and members" do - before do - login_as member - visit places_path - search_with "Philippines" - end + include_context 'signed in member' do + before do + visit places_path + search_with "Philippines" + end - it "shows that there are nearby seeds, plantings, and members" do - expect(page).to have_content "Nearby members" - expect(page).to have_content "Seeds available for trade near Philippines" - expect(page).to have_content "Recent plantings near Philippines" - Percy.snapshot(page, name: 'places map') - end + it "shows that there are nearby seeds, plantings, and members" do + expect(page).to have_content "Nearby members" + expect(page).to have_content "Seeds available for trade near Philippines" + expect(page).to have_content "Recent plantings near Philippines" + Percy.snapshot(page, name: 'places map') + end - it "goes to members' index page" do - click_link 'View all members >>' - expect(current_path).to eq members_path - end + it "goes to members' index page" do + click_link 'View all members >>' + expect(current_path).to eq members_path + end - it "goes to plantings' index page" do - click_link 'View all plantings >>' - expect(current_path).to eq plantings_path - end + it "goes to plantings' index page" do + click_link 'View all plantings >>' + expect(current_path).to eq plantings_path + end - it "goes to seeds' index page" do - click_link 'View all seeds >>' - expect(current_path).to eq seeds_path + it "goes to seeds' index page" do + click_link 'View all seeds >>' + expect(current_path).to eq seeds_path + end end end diff --git a/spec/features/plantings/planting_a_crop_spec.rb b/spec/features/plantings/planting_a_crop_spec.rb index 24925b073..8ff4b2d96 100644 --- a/spec/features/plantings/planting_a_crop_spec.rb +++ b/spec/features/plantings/planting_a_crop_spec.rb @@ -8,273 +8,270 @@ describe "Planting a crop", :js, :elasticsearch do let!(:planting) do FactoryBot.create :planting, garden: garden, owner: member, planted_at: Date.parse("2013-03-10") end + include_context 'signed in member' do + before { visit new_planting_path } - before do - login_as member - visit new_planting_path - end + it_behaves_like "crop suggest", "planting" - it_behaves_like "crop suggest", "planting" + it "has the required fields help text" do + expect(page).to have_content "* denotes a required field" + end - it "has the required fields help text" do - expect(page).to have_content "* denotes a required field" - end + describe "displays required and optional fields properly" do + it { expect(page).to have_selector ".required", text: "What did you plant?" } + it { expect(page).to have_selector ".required", text: "Where did you plant it?" } + it { expect(page).to have_selector 'input#planting_planted_at' } + it { expect(page).to have_selector 'input#planting_quantity' } + it { expect(page).to have_selector 'select#planting_planted_from' } + it { expect(page).to have_selector 'select#planting_sunniness' } + it { expect(page).to have_selector 'textarea#planting_description' } + it { expect(page).to have_selector 'input#planting_finished_at' } + end - describe "displays required and optional fields properly" do - it { expect(page).to have_selector ".required", text: "What did you plant?" } - it { expect(page).to have_selector ".required", text: "Where did you plant it?" } - it { expect(page).to have_selector 'input#planting_planted_at' } - it { expect(page).to have_selector 'input#planting_quantity' } - it { expect(page).to have_selector 'select#planting_planted_from' } - it { expect(page).to have_selector 'select#planting_sunniness' } - it { expect(page).to have_selector 'textarea#planting_description' } - it { expect(page).to have_selector 'input#planting_finished_at' } - end + describe "Creating a new planting" do + before do + fill_autocomplete "crop", with: "mai" + select_from_autocomplete "maize" + within "form#new_planting" do + fill_in "How many?", with: 42 + select "cutting", from: "Planted from" + select "semi-shade", from: "Sun or shade?" + fill_in "Tell us more about it", with: "It's rad." + choose 'Garden' + fill_in "When", with: "2014-06-15" + click_button "Save" + end + end - describe "Creating a new planting" do - before do - fill_autocomplete "crop", with: "mai" - select_from_autocomplete "maize" - within "form#new_planting" do - fill_in "How many?", with: 42 - select "cutting", from: "Planted from" - select "semi-shade", from: "Sun or shade?" - fill_in "Tell us more about it", with: "It's rad." - choose 'Garden' - fill_in "When", with: "2014-06-15" - click_button "Save" + it { expect(page).to have_content "planting was successfully created" } + end + + describe "Clicking link to owner's profile" do + before do + visit member_plantings_path(member) + click_link "View #{member}'s profile >>" + end + it { expect(current_path).to eq member_path(member) } + end + + describe "Progress bar status on planting creation" do + before do + visit new_planting_path + + @a_past_date = 15.days.ago.strftime("%Y-%m-%d") + @right_now = Time.zone.today.strftime("%Y-%m-%d") + @a_future_date = 1.year.from_now.strftime("%Y-%m-%d") + end + + it "shows that it is not planted yet" do + fill_autocomplete "crop", with: "mai" + select_from_autocomplete "maize" + within "form#new_planting" do + choose 'Garden' + fill_in "When", with: @a_future_date + fill_in "How many?", with: 42 + select "cutting", from: "Planted from" + select "semi-shade", from: "Sun or shade?" + fill_in "Tell us more about it", with: "It's rad." + click_button "Save" + end + + expect(page).to have_content "planting was successfully created" + expect(page).to have_content "0%" + end + + it "shows that days before maturity is unknown" do + fill_autocomplete "crop", with: "mai" + select_from_autocomplete "maize" + within "form#new_planting" do + choose 'Garden' + fill_in "When", with: @a_past_date + fill_in "How many?", with: 42 + select "cutting", from: "Planted from" + select "semi-shade", from: "Sun or shade?" + fill_in "Tell us more about it", with: "It's rad." + click_button "Save" + end + + expect(page).to have_content "planting was successfully created" + expect(page).not_to have_content "Finished" + expect(page).not_to have_content "Finishes" + end + + it "shows that planting is in progress" do + fill_autocomplete "crop", with: "mai" + select_from_autocomplete "maize" + within "form#new_planting" do + choose 'Garden' + fill_in "When", with: @right_now + fill_in "How many?", with: 42 + select "cutting", from: "Planted from" + select "semi-shade", from: "Sun or shade?" + fill_in "When?", with: '2013-03-10' + fill_in "Tell us more about it", with: "It's rad." + fill_in "Finished date", with: @a_future_date + click_button "Save" + end + + expect(page).to have_content "planting was successfully created" + expect(page).not_to have_content "0%" + expect(page).not_to have_content "Finished" + expect(page).not_to have_content "Finishes" + end + + it "shows that planting is 100% complete (no date specified)" do + fill_autocomplete "crop", with: "mai" + select_from_autocomplete "maize" + within "form#new_planting" do + choose 'Garden' + fill_in "When", with: @right_now + fill_in "How many?", with: 42 + select "cutting", from: "Planted from" + select "semi-shade", from: "Sun or shade?" + fill_in "Tell us more about it", with: "It's rad." + check "Mark as finished" + click_button "Save" + end + + expect(page).to have_content "planting was successfully created" + expect(page).to have_content "Finished" + end + + it "shows that planting is 100% complete (date specified)" do + fill_autocomplete "crop", with: "mai" + select_from_autocomplete "maize" + within "form#new_planting" do + choose 'Garden' + fill_in "When", with: @a_past_date + fill_in "How many?", with: 42 + select "cutting", from: "Planted from" + select "semi-shade", from: "Sun or shade?" + choose 'Garden' + fill_in "Tell us more about it", with: "It's rad." + fill_in "Finished date", with: @right_now + click_button "Save" + end + + expect(page).to have_content "planting was successfully created" + expect(page).to have_content "Finished" end end - it { expect(page).to have_content "planting was successfully created" } - end - - describe "Clicking link to owner's profile" do - before do - visit member_plantings_path(member) - click_link "View #{member}'s profile >>" - end - it { expect(current_path).to eq member_path(member) } - end - - describe "Progress bar status on planting creation" do - before do - login_as member - visit new_planting_path - - @a_past_date = 15.days.ago.strftime("%Y-%m-%d") - @right_now = Time.zone.today.strftime("%Y-%m-%d") - @a_future_date = 1.year.from_now.strftime("%Y-%m-%d") - end - - it "shows that it is not planted yet" do - fill_autocomplete "crop", with: "mai" - select_from_autocomplete "maize" + it "Planting from crop page" do + visit crop_path(maize) + within '.crop-actions' do + click_link "Plant maize" + end within "form#new_planting" do - choose 'Garden' - fill_in "When", with: @a_future_date - fill_in "How many?", with: 42 - select "cutting", from: "Planted from" - select "semi-shade", from: "Sun or shade?" - fill_in "Tell us more about it", with: "It's rad." - click_button "Save" + expect(page).to have_selector "input[value='maize']" end - expect(page).to have_content "planting was successfully created" - expect(page).to have_content "0%" - end - - it "shows that days before maturity is unknown" do - fill_autocomplete "crop", with: "mai" - select_from_autocomplete "maize" - within "form#new_planting" do - choose 'Garden' - fill_in "When", with: @a_past_date - fill_in "How many?", with: 42 - select "cutting", from: "Planted from" - select "semi-shade", from: "Sun or shade?" - fill_in "Tell us more about it", with: "It's rad." - click_button "Save" - end - - expect(page).to have_content "planting was successfully created" - expect(page).not_to have_content "Finished" - expect(page).not_to have_content "Finishes" - end - - it "shows that planting is in progress" do - fill_autocomplete "crop", with: "mai" - select_from_autocomplete "maize" - within "form#new_planting" do - choose 'Garden' - fill_in "When", with: @right_now - fill_in "How many?", with: 42 - select "cutting", from: "Planted from" - select "semi-shade", from: "Sun or shade?" - fill_in "When?", with: '2013-03-10' - fill_in "Tell us more about it", with: "It's rad." - fill_in "Finished date", with: @a_future_date - click_button "Save" - end - - expect(page).to have_content "planting was successfully created" - expect(page).not_to have_content "0%" - expect(page).not_to have_content "Finished" - expect(page).not_to have_content "Finishes" - end - - it "shows that planting is 100% complete (no date specified)" do - fill_autocomplete "crop", with: "mai" - select_from_autocomplete "maize" - within "form#new_planting" do - choose 'Garden' - fill_in "When", with: @right_now - fill_in "How many?", with: 42 - select "cutting", from: "Planted from" - select "semi-shade", from: "Sun or shade?" - fill_in "Tell us more about it", with: "It's rad." - check "Mark as finished" - click_button "Save" - end - - expect(page).to have_content "planting was successfully created" - expect(page).to have_content "Finished" - end - - it "shows that planting is 100% complete (date specified)" do - fill_autocomplete "crop", with: "mai" - select_from_autocomplete "maize" - within "form#new_planting" do - choose 'Garden' - fill_in "When", with: @a_past_date - fill_in "How many?", with: 42 - select "cutting", from: "Planted from" - select "semi-shade", from: "Sun or shade?" - choose 'Garden' - fill_in "Tell us more about it", with: "It's rad." - fill_in "Finished date", with: @right_now - click_button "Save" - end - - expect(page).to have_content "planting was successfully created" - expect(page).to have_content "Finished" - end - end - - it "Planting from crop page" do - visit crop_path(maize) - within '.crop-actions' do - click_link "Plant maize" - end - within "form#new_planting" do - expect(page).to have_selector "input[value='maize']" - end - - choose(member.gardens.first.name) - click_button "Save" - - expect(page).to have_content "planting was successfully created" - expect(page).to have_content "maize" - end - - it "Editing a planting to add details" do - visit planting_path(planting) - click_link 'Actions' - click_link "Edit" - fill_in "Tell us more about it", with: "Some extra notes" - click_button "Save" - expect(page).to have_content "planting was successfully updated" - end - - it "Editing a planting to fill in the finished date" do - visit planting_path(planting) - expect(page).not_to have_content "Finishes" - # click_link(id: 'planting-actions-button') - click_link 'Actions' - click_link "Edit" - check "finished" - fill_in "Finished date", with: "2015-06-25" - click_button "Save" - expect(page).to have_content "planting was successfully updated" - expect(page).to have_content "Finished" - end - - it "Marking a planting as finished" do - fill_autocomplete "crop", with: "mai" - select_from_autocomplete "maize" - choose(member.gardens.first.name) - within "form#new_planting" do - fill_in "When?", with: "2014-07-01" - check "Mark as finished" - fill_in "Finished date", with: "2014-08-30" - uncheck 'Mark as finished' - end - - # Javascript removes the finished at date when the - # planting is marked unfinished. - expect(find("#planting_finished_at").value).to eq("") - - within "form#new_planting" do - check 'Mark as finished' - end - - # The finished at date was cached in Javascript in - # case the user clicks unfinished accidentally. - expect(find("#planting_finished_at").value).to eq("2014-08-30") - - within "form#new_planting" do + choose(member.gardens.first.name) click_button "Save" + + expect(page).to have_content "planting was successfully created" + expect(page).to have_content "maize" end - expect(page).to have_content "planting was successfully created" - expect(page).to have_content "Finished" - expect(page).to have_content "30 Aug" - # shouldn't be on the page - visit plantings_path - expect(page).not_to have_content "maize" + it "Editing a planting to add details" do + visit planting_path(planting) + click_link 'Actions' + click_link "Edit" + fill_in "Tell us more about it", with: "Some extra notes" + click_button "Save" + expect(page).to have_content "planting was successfully updated" + end - # show all plantings to see this finished planting - visit plantings_path(all: 1) - expect(page).to have_content "maize" - end + it "Editing a planting to fill in the finished date" do + visit planting_path(planting) + expect(page).not_to have_content "Finishes" + # click_link(id: 'planting-actions-button') + click_link 'Actions' + click_link "Edit" + check "finished" + fill_in "Finished date", with: "2015-06-25" + click_button "Save" + expect(page).to have_content "planting was successfully updated" + expect(page).to have_content "Finished" + end - describe "Marking a planting as finished without a date" do - before do + it "Marking a planting as finished" do fill_autocomplete "crop", with: "mai" select_from_autocomplete "maize" + choose(member.gardens.first.name) within "form#new_planting" do - choose member.gardens.first.name + fill_in "When?", with: "2014-07-01" check "Mark as finished" + fill_in "Finished date", with: "2014-08-30" + uncheck 'Mark as finished' + end + + # Javascript removes the finished at date when the + # planting is marked unfinished. + expect(find("#planting_finished_at").value).to eq("") + + within "form#new_planting" do + check 'Mark as finished' + end + + # The finished at date was cached in Javascript in + # case the user clicks unfinished accidentally. + expect(find("#planting_finished_at").value).to eq("2014-08-30") + + within "form#new_planting" do click_button "Save" end + expect(page).to have_content "planting was successfully created" + expect(page).to have_content "Finished" + expect(page).to have_content "30 Aug" + + # shouldn't be on the page + visit plantings_path + expect(page).not_to have_content "maize" + + # show all plantings to see this finished planting + visit plantings_path(all: 1) + expect(page).to have_content "maize" + end + + describe "Marking a planting as finished without a date" do + before do + fill_autocomplete "crop", with: "mai" + select_from_autocomplete "maize" + within "form#new_planting" do + choose member.gardens.first.name + check "Mark as finished" + click_button "Save" + end + end + + it { expect(page).to have_content "planting was successfully created" } + it { expect(page).to have_content "Finished" } + end + + describe "Planting sunniness" do + before "shows the a sunny image" do + fill_autocomplete "crop", with: "mai" + select_from_autocomplete "maize" + within "form#new_planting" do + fill_in "When", with: "2015-10-15" + fill_in "How many?", with: 42 + select "cutting", from: "Planted from" + select "sun", from: "Sun or shade?" + fill_in "Tell us more about it", with: "It's rad." + check "Mark as finished" + click_button "Save" + end + + it { expect(page).to have_css("img[alt='sun']") } + end end - it { expect(page).to have_content "planting was successfully created" } - it { expect(page).to have_content "Finished" } - end + describe "Marking a planting as finished from the show page" do + let(:path) { planting_path(planting) } + let(:link_text) { "Mark as finished" } - describe "Planting sunniness" do - before "shows the a sunny image" do - fill_autocomplete "crop", with: "mai" - select_from_autocomplete "maize" - within "form#new_planting" do - fill_in "When", with: "2015-10-15" - fill_in "How many?", with: 42 - select "cutting", from: "Planted from" - select "sun", from: "Sun or shade?" - fill_in "Tell us more about it", with: "It's rad." - check "Mark as finished" - click_button "Save" - end - - it { expect(page).to have_css("img[alt='sun']") } + it_behaves_like "append date" end end - - describe "Marking a planting as finished from the show page" do - let(:path) { planting_path(planting) } - let(:link_text) { "Mark as finished" } - - it_behaves_like "append date" - end end diff --git a/spec/features/posts/posting_a_post_spec.rb b/spec/features/posts/posting_a_post_spec.rb index 7467517c5..cde48b467 100644 --- a/spec/features/posts/posting_a_post_spec.rb +++ b/spec/features/posts/posting_a_post_spec.rb @@ -1,33 +1,30 @@ require 'rails_helper' describe 'Post a post' do - let(:member) { create :member } + include_context 'signed in member' do + before { visit new_post_path } - before do - login_as member - visit new_post_path - end - - it "creating a post" do - fill_in "post_subject", with: "Testing" - fill_in "post_body", with: "This is a sample test" - click_button "Post" - expect(page).to have_content "Post was successfully created" - expect(page).to have_content "Posted by" - end - - context "editing a post" do - let(:existing_post) { create :post, author: member } - - before do - visit edit_post_path(existing_post) + it "creating a post" do + fill_in "post_subject", with: "Testing" + fill_in "post_body", with: "This is a sample test" + click_button "Post" + expect(page).to have_content "Post was successfully created" + expect(page).to have_content "Posted by" end - it "saving edit" do - fill_in "post_subject", with: "Testing Edit" - click_button "Post" - expect(page).to have_content "Post was successfully updated" - expect(page).to have_content "edited at" + context "editing a post" do + let(:existing_post) { create :post, author: member } + + before do + visit edit_post_path(existing_post) + end + + it "saving edit" do + fill_in "post_subject", with: "Testing Edit" + click_button "Post" + expect(page).to have_content "Post was successfully updated" + expect(page).to have_content "edited at" + end end end end diff --git a/spec/features/seeds/adding_seeds_spec.rb b/spec/features/seeds/adding_seeds_spec.rb index ce5ab31b4..cc29ef027 100644 --- a/spec/features/seeds/adding_seeds_spec.rb +++ b/spec/features/seeds/adding_seeds_spec.rb @@ -2,71 +2,69 @@ require 'rails_helper' require 'custom_matchers' describe "Seeds", :js, :elasticsearch do - let(:member) { create :member } - let!(:maize) { create :maize } + include_context 'signed in member' do + let!(:maize) { create :maize } - before do - login_as member - visit new_seed_path - end + before { visit new_seed_path } - it_behaves_like "crop suggest", "seed", "crop" + it_behaves_like "crop suggest", "seed", "crop" - it "has the required fields help text" do - expect(page).to have_content "* denotes a required field" - end - - describe "displays required and optional fields properly" do - it { expect(page).to have_selector ".form-group.required", text: "Crop" } - it { expect(page).to have_selector 'input#seed_quantity' } - it { expect(page).to have_selector 'input#seed_plant_before' } - it { expect(page).to have_selector 'input#seed_days_until_maturity_min' } - it { expect(page).to have_selector 'input#seed_days_until_maturity_max' } - it { expect(page).to have_selector '.form-group.required', text: 'Organic?' } - it { expect(page).to have_selector '.form-group.required', text: 'GMO?' } - it { expect(page).to have_selector '.form-group.required', text: 'Heirloom?' } - it { expect(page).to have_selector 'textarea#seed_description' } - it { expect(page).to have_selector '.form-group.required', text: 'Will trade' } - end - - describe "Adding a new seed", js: true do - before do - fill_autocomplete "crop", with: "mai" - select_from_autocomplete "maize" - within "form#new_seed" do - fill_in "Quantity", with: 42 - fill_in "Plant before", with: "2014-06-15" - fill_in "min", with: 999 - fill_in "max", with: 1999 - select "certified organic", from: "Organic?" - select "non-certified GMO-free", from: "GMO?" - select "heirloom", from: "Heirloom?" - fill_in "Description", with: "It's killer." - select "internationally", from: "Will trade" - click_button "Save" - end + it "has the required fields help text" do + expect(page).to have_content "* denotes a required field" end - it { expect(page).to have_content "Successfully added maize seed to your stash" } - it { expect(page).to have_content "Quantity: 42" } - it { expect(page).to have_content "Days until maturity: 999–1999" } - it { expect(page).to have_content "certified organic" } - it { expect(page).to have_content "non-certified GMO-free" } - it { expect(page).to have_content "Heirloom? heirloom" } - it { expect(page).to have_content "It's killer." } - end - - describe "Adding a seed from crop page" do - before do - visit crop_path(maize) - click_link "Add maize seeds to stash" - within "form#new_seed" do - expect(page).to have_selector "input[value='maize']" - click_button "Save" - end + describe "displays required and optional fields properly" do + it { expect(page).to have_selector ".form-group.required", text: "Crop" } + it { expect(page).to have_selector 'input#seed_quantity' } + it { expect(page).to have_selector 'input#seed_plant_before' } + it { expect(page).to have_selector 'input#seed_days_until_maturity_min' } + it { expect(page).to have_selector 'input#seed_days_until_maturity_max' } + it { expect(page).to have_selector '.form-group.required', text: 'Organic?' } + it { expect(page).to have_selector '.form-group.required', text: 'GMO?' } + it { expect(page).to have_selector '.form-group.required', text: 'Heirloom?' } + it { expect(page).to have_selector 'textarea#seed_description' } + it { expect(page).to have_selector '.form-group.required', text: 'Will trade' } end - it { expect(page).to have_content "Successfully added maize seed to your stash" } - it { expect(page).to have_content "maize" } + describe "Adding a new seed", js: true do + before do + fill_autocomplete "crop", with: "mai" + select_from_autocomplete "maize" + within "form#new_seed" do + fill_in "Quantity", with: 42 + fill_in "Plant before", with: "2014-06-15" + fill_in "min", with: 999 + fill_in "max", with: 1999 + select "certified organic", from: "Organic?" + select "non-certified GMO-free", from: "GMO?" + select "heirloom", from: "Heirloom?" + fill_in "Description", with: "It's killer." + select "internationally", from: "Will trade" + click_button "Save" + end + end + + it { expect(page).to have_content "Successfully added maize seed to your stash" } + it { expect(page).to have_content "Quantity: 42" } + it { expect(page).to have_content "Days until maturity: 999–1999" } + it { expect(page).to have_content "certified organic" } + it { expect(page).to have_content "non-certified GMO-free" } + it { expect(page).to have_content "Heirloom? heirloom" } + it { expect(page).to have_content "It's killer." } + end + + describe "Adding a seed from crop page" do + before do + visit crop_path(maize) + click_link "Add maize seeds to stash" + within "form#new_seed" do + expect(page).to have_selector "input[value='maize']" + click_button "Save" + end + end + + it { expect(page).to have_content "Successfully added maize seed to your stash" } + it { expect(page).to have_content "maize" } + end end end diff --git a/spec/features/seeds/misc_seeds_spec.rb b/spec/features/seeds/misc_seeds_spec.rb index 620a07823..467c1acb3 100644 --- a/spec/features/seeds/misc_seeds_spec.rb +++ b/spec/features/seeds/misc_seeds_spec.rb @@ -6,92 +6,92 @@ describe "seeds", js: true do context "signed in user" do let(:crop) { create :crop } - before { login_as member } + include_context 'signed in member' do + xit "button on index to edit seed" do + let!(:seed) { create :seed, owner: member } - xit "button on index to edit seed" do - let!(:seed) { create :seed, owner: member } + before do + visit seeds_path + click_link 'Actions' + click_link "Edit" + end - before do - visit seeds_path - click_link 'Actions' - click_link "Edit" + it { expect(current_path).to eq edit_seed_path(seed) } + it { expect(page).to have_content 'Editing seeds' } end - it { expect(current_path).to eq edit_seed_path(seed) } - it { expect(page).to have_content 'Editing seeds' } - end + describe "button on front page to add seeds" do + before do + visit root_path + click_link(href: new_seed_path) + end - describe "button on front page to add seeds" do - before do - visit root_path - click_link(href: new_seed_path) + it { expect(current_path).to eq new_seed_path } + it { expect(page).to have_content 'Save seeds' } end - it { expect(current_path).to eq new_seed_path } - it { expect(page).to have_content 'Save seeds' } - end + describe "Clicking link to owner's profile" do + before do + visit member_seeds_path(member) + click_link "View #{member}'s profile >>" + end - describe "Clicking link to owner's profile" do - before do - visit member_seeds_path(member) - click_link "View #{member}'s profile >>" + it { expect(current_path).to eq member_path(member) } end - it { expect(current_path).to eq member_path(member) } - end + # actually adding seeds is in spec/features/seeds_new_spec.rb - # actually adding seeds is in spec/features/seeds_new_spec.rb - - it "edit seeds" do - seed = create :seed, owner: member - visit seed_path(seed) - click_link 'Actions' - click_link 'Edit' - expect(current_path).to eq edit_seed_path(seed) - fill_in 'Quantity', with: seed.quantity * 2 - click_button 'Save' - expect(current_path).to eq seed_path(seed) - end - - describe "delete seeds" do - let(:seed) { FactoryBot.create :seed, owner: member } - - before do + it "edit seeds" do + seed = create :seed, owner: member visit seed_path(seed) click_link 'Actions' - accept_confirm do - click_link 'Delete' + click_link 'Edit' + expect(current_path).to eq edit_seed_path(seed) + fill_in 'Quantity', with: seed.quantity * 2 + click_button 'Save' + expect(current_path).to eq seed_path(seed) + end + + describe "delete seeds" do + let(:seed) { FactoryBot.create :seed, owner: member } + + before do + visit seed_path(seed) + click_link 'Actions' + accept_confirm do + click_link 'Delete' + end end + + it { expect(current_path).to eq seeds_path } end - it { expect(current_path).to eq seeds_path } - end + describe '#show' do + before { visit seed_path(seed) } - describe '#show' do - before { visit seed_path(seed) } + describe "view seeds with max and min days until maturity" do + let(:seed) { FactoryBot.create :seed, days_until_maturity_min: 5, days_until_maturity_max: 7 } - describe "view seeds with max and min days until maturity" do - let(:seed) { FactoryBot.create :seed, days_until_maturity_min: 5, days_until_maturity_max: 7 } + it { expect(page).to have_content "Days until maturity: 5–7" } + end - it { expect(page).to have_content "Days until maturity: 5–7" } - end + describe "view seeds with only max days until maturity" do + let(:seed) { FactoryBot.create :seed, days_until_maturity_max: 7 } - describe "view seeds with only max days until maturity" do - let(:seed) { FactoryBot.create :seed, days_until_maturity_max: 7 } + it { expect(page).to have_content "Days until maturity: 7" } + end - it { expect(page).to have_content "Days until maturity: 7" } - end + describe "view seeds with only min days until maturity" do + let(:seed) { FactoryBot.create :seed, days_until_maturity_min: 5 } - describe "view seeds with only min days until maturity" do - let(:seed) { FactoryBot.create :seed, days_until_maturity_min: 5 } + it { expect(page).to have_content "Days until maturity: 5" } + end - it { expect(page).to have_content "Days until maturity: 5" } - end + describe "view seeds with neither max nor min days until maturity" do + let(:seed) { FactoryBot.create :seed } - describe "view seeds with neither max nor min days until maturity" do - let(:seed) { FactoryBot.create :seed } - - it { expect(page).to have_content "Days until maturity: unknown" } + it { expect(page).to have_content "Days until maturity: unknown" } + end end end end diff --git a/spec/features/seeds/seed_photos.rb b/spec/features/seeds/seed_photos.rb index d1eacdd7f..b787e2b87 100644 --- a/spec/features/seeds/seed_photos.rb +++ b/spec/features/seeds/seed_photos.rb @@ -2,45 +2,44 @@ require 'rails_helper' require 'custom_matchers' describe "Seeds", :js do - subject do - login_as member - visit seed_path(seed) - page - end + include_context 'signed in member' do + before { visit seed_path(seed) } + subject { page } - let(:member) { FactoryBot.create :member } - let!(:seed) { FactoryBot.create :seed, owner: member } + let(:member) { FactoryBot.create :member } + let!(:seed) { FactoryBot.create :seed, owner: member } - it { is_expected.to have_content 'Add photo' } + it { is_expected.to have_content 'Add photo' } - # context 'no photos' do - # it { is_expected.to have_content 'no photos' } - # end - context 'has one photo' do - before { seed.photos = [photo] } + # context 'no photos' do + # it { is_expected.to have_content 'no photos' } + # end + context 'has one photo' do + before { seed.photos = [photo] } - let!(:photo) { FactoryBot.create :photo, title: 'hello photo' } + let!(:photo) { FactoryBot.create :photo, title: 'hello photo' } - it { is_expected.to have_xpath("//img[contains(@src,'#{photo.thumbnail_url}')]") } - it { is_expected.to have_xpath("//a[contains(@href,'#{photo_path(photo)}')]") } - end - - context 'has 50 photos' do - before { seed.photos = photos } - - let!(:photos) { FactoryBot.create_list :photo, 50 } - - it "shows newest photo" do - expect(subject).to have_xpath("//img[contains(@src,'#{photos.last.thumbnail_url}')]") + it { is_expected.to have_xpath("//img[contains(@src,'#{photo.thumbnail_url}')]") } + it { is_expected.to have_xpath("//a[contains(@href,'#{photo_path(photo)}')]") } end - it "links to newest photo" do - expect(subject).to have_xpath("//a[contains(@href,'#{photo_path(photos.last)}')]") - end - it "does not show oldest photo" do - expect(subject).not_to have_xpath("//img[contains(@src,'#{photos.first.thumbnail_url}')]") - end - it "does not link to oldest photo" do - expect(subject).not_to have_xpath("//a[contains(@href,'#{photo_path(photos.first)}')]") + + context 'has 50 photos' do + before { seed.photos = photos } + + let!(:photos) { FactoryBot.create_list :photo, 50 } + + it "shows newest photo" do + expect(subject).to have_xpath("//img[contains(@src,'#{photos.last.thumbnail_url}')]") + end + it "links to newest photo" do + expect(subject).to have_xpath("//a[contains(@href,'#{photo_path(photos.last)}')]") + end + it "does not show oldest photo" do + expect(subject).not_to have_xpath("//img[contains(@src,'#{photos.first.thumbnail_url}')]") + end + it "does not link to oldest photo" do + expect(subject).not_to have_xpath("//a[contains(@href,'#{photo_path(photos.first)}')]") + end end end end diff --git a/spec/support/devise.rb b/spec/support/devise.rb index 0cf56ea83..090ffc6a8 100644 --- a/spec/support/devise.rb +++ b/spec/support/devise.rb @@ -1,4 +1,5 @@ RSpec.configure do |config| config.include Devise::Test::ControllerHelpers, type: :controller config.include Devise::Test::ControllerHelpers, type: :view + config.include Devise::Test::IntegrationHelpers, type: :feature end diff --git a/spec/support/feature_helpers.rb b/spec/support/feature_helpers.rb index 1f3fc1902..0b85fe72a 100644 --- a/spec/support/feature_helpers.rb +++ b/spec/support/feature_helpers.rb @@ -10,9 +10,22 @@ module FeatureHelpers page.execute_script " $('#{selector}').mouseenter().click() " end - shared_context 'signed in' do - before { sign_in user } - after { sign_out user } + shared_context 'signed in member' do + let(:member) { FactoryBot.create :member } + include_examples 'sign in' + end + shared_context 'signed in crop wrangler' do + let(:member) { FactoryBot.create :crop_wrangling_member } + include_examples 'sign in' + end + shared_context 'signed in admin' do + let(:member) { FactoryBot.create :admin_member } + include_examples 'sign in' + end + + shared_examples 'sign in' do + before { sign_in member } + after { sign_out member } end end From b49b7b563cc9a41cdbebc8867e5f225b0c4309b7 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 17 Aug 2019 14:14:58 +1200 Subject: [PATCH 122/151] Added logout after like spec --- spec/features/likeable_spec.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/features/likeable_spec.rb b/spec/features/likeable_spec.rb index 068fcba77..767bffa07 100644 --- a/spec/features/likeable_spec.rb +++ b/spec/features/likeable_spec.rb @@ -40,6 +40,7 @@ describe 'Likeable', js: true do expect(page).to have_css(like_count_class, text: "1") click_link '1', class: 'like-btn' expect(page).to have_css(like_count_class, text: "2") + logout(another_member) end end describe 'photos#index' do @@ -89,6 +90,7 @@ describe 'Likeable', js: true do expect(page).to have_link 'Like' click_link 'Like', class: 'like-btn' expect(page).to have_css(like_count_class, text: "2") + logout(another_member) end end end From aa17f8e332cd3f5a7d76798e2f8c719f965b268d Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 17 Aug 2019 14:17:05 +1200 Subject: [PATCH 123/151] Removed unused let() --- spec/features/crops/crop_wranglers_spec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/features/crops/crop_wranglers_spec.rb b/spec/features/crops/crop_wranglers_spec.rb index 3f52757ce..c758fc047 100644 --- a/spec/features/crops/crop_wranglers_spec.rb +++ b/spec/features/crops/crop_wranglers_spec.rb @@ -70,7 +70,6 @@ describe "crop wranglers", js: true do context "signed in non-wrangler" do include_context 'signed in member' do let!(:crop_wranglers) { create_list :crop_wrangling_member, 3 } - let(:member) { create :member } it "can't see wrangling page without js", js: false do visit root_path From c1deed70adf7b11b39ca2fc394271a558aa85149 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 17 Aug 2019 14:32:18 +1200 Subject: [PATCH 124/151] Keep username consistent in specs --- spec/features/percy/percy_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/features/percy/percy_spec.rb b/spec/features/percy/percy_spec.rb index a5968742f..6a0d22937 100644 --- a/spec/features/percy/percy_spec.rb +++ b/spec/features/percy/percy_spec.rb @@ -325,6 +325,7 @@ rest of the garden. describe 'expand menus' do it 'expands crop menu' do + member.update! login_name: 'percy' visit root_path click_on 'Crops' Percy.snapshot(page, name: "#{prefix}/crops-menu") From a36d1491257f10c349bdd9322aee900a1bf5f3f1 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 17 Aug 2019 14:35:39 +1200 Subject: [PATCH 125/151] sign in as member with location --- spec/features/places/searching_a_place_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/places/searching_a_place_spec.rb b/spec/features/places/searching_a_place_spec.rb index 0a5ba110a..565515464 100644 --- a/spec/features/places/searching_a_place_spec.rb +++ b/spec/features/places/searching_a_place_spec.rb @@ -1,7 +1,6 @@ require "rails_helper" describe "User searches" do - let(:member) { create :member, location: "Philippines" } let!(:maize) { create :maize } let(:garden) { create :garden, owner: member } let!(:seed1) { create :seed, owner: member } @@ -27,6 +26,7 @@ describe "User searches" do describe "Nearby plantings, seed, and members" do include_context 'signed in member' do + let(:member) { create :member, location: "Philippines" } before do visit places_path search_with "Philippines" From 1cb009678846996017cf2efac3b217e51a49e0b2 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 17 Aug 2019 14:38:43 +1200 Subject: [PATCH 126/151] fixed specs --- spec/features/crops/crop_detail_page_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index 3da5f8828..e9a297cad 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -72,8 +72,7 @@ describe "crop detail page", js: true do end context "seed quantity for a crop" do - let(:member) { create :member } - let(:seed) { create :seed, crop: crop, quantity: 20, owner: member } + let(:seed) { create :seed, crop: crop, quantity: 20 } it "User not signed in" do visit crop_path(seed.crop) @@ -86,6 +85,7 @@ describe "crop detail page", js: true do expect(page).to have_link "You have 20 seeds of this crop." end it "click link to your owned seeds" do + seed.update! owner: member visit crop_path(seed.crop) click_link "You have 20 seeds of this crop." expect(current_path).to eq member_seeds_path(member_slug: member.slug) From b2d8818ae158e86147b9627efbe50b4eb0738f87 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 17 Aug 2019 14:43:32 +1200 Subject: [PATCH 127/151] don't notify wranglers if there are none --- app/controllers/crops_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/crops_controller.rb b/app/controllers/crops_controller.rb index 89e45a163..8a02e195c 100644 --- a/app/controllers/crops_controller.rb +++ b/app/controllers/crops_controller.rb @@ -139,7 +139,7 @@ class CropsController < ApplicationController def notify_wranglers return if current_member.role? :crop_wrangler - Role.crop_wranglers.each do |w| + Role.crop_wranglers&.each do |w| Notifier.new_crop_request(w, @crop).deliver_now! end end From a993eadea9dc7fdd48125ea5ee16bd06322008fd Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 17 Aug 2019 14:43:39 +1200 Subject: [PATCH 128/151] fix spec --- spec/features/crops/request_new_crop_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/features/crops/request_new_crop_spec.rb b/spec/features/crops/request_new_crop_spec.rb index a35480b66..d2f07a53d 100644 --- a/spec/features/crops/request_new_crop_spec.rb +++ b/spec/features/crops/request_new_crop_spec.rb @@ -15,10 +15,10 @@ describe "Requesting a new crop" do end context "As a crop wrangler" do - let!(:crop) { create :crop_request } - let!(:already_approved) { create :crop } - include_context 'signed in crop wrangler' do + let!(:crop) { create :crop_request } + let!(:already_approved) { create :crop } + it "Approve a request" do visit edit_crop_path(crop) select "approved", from: "Approval status" From 27d4ebda5180bc18c1420e735d7e75974bcb1d18 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 17 Aug 2019 15:01:34 +1200 Subject: [PATCH 129/151] make sure there's a member to find in specs --- spec/features/places/searching_a_place_spec.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/spec/features/places/searching_a_place_spec.rb b/spec/features/places/searching_a_place_spec.rb index 565515464..bf830116a 100644 --- a/spec/features/places/searching_a_place_spec.rb +++ b/spec/features/places/searching_a_place_spec.rb @@ -1,10 +1,11 @@ require "rails_helper" describe "User searches" do + let!(:located_member) { create :member, location: "Philippines" } let!(:maize) { create :maize } - let(:garden) { create :garden, owner: member } - let!(:seed1) { create :seed, owner: member } - let!(:planting) { create :planting, garden: garden, owner: member, planted_at: Date.parse("2013-3-10") } + let(:garden) { create :garden, owner: located_member } + let!(:seed1) { create :seed, owner: located_member } + let!(:planting) { create :planting, garden: garden, owner: located_member, planted_at: Date.parse("2013-3-10") } describe "with a valid place" do before do @@ -26,7 +27,7 @@ describe "User searches" do describe "Nearby plantings, seed, and members" do include_context 'signed in member' do - let(:member) { create :member, location: "Philippines" } + let(:member) { located_member } before do visit places_path search_with "Philippines" From 7a21ec31d9db0805d1db90bd4598d9d8e07dc179 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 17 Aug 2019 15:08:02 +1200 Subject: [PATCH 130/151] wrap context in spec --- spec/features/cms_spec.rb | 23 ++-- spec/features/crops/crop_detail_page_spec.rb | 102 +++++++++--------- .../features/places/searching_a_place_spec.rb | 2 +- 3 files changed, 67 insertions(+), 60 deletions(-) diff --git a/spec/features/cms_spec.rb b/spec/features/cms_spec.rb index d07f3c935..15e4fd521 100644 --- a/spec/features/cms_spec.rb +++ b/spec/features/cms_spec.rb @@ -7,18 +7,21 @@ describe "cms admin" do expect(page).to have_content "Please sign in as an admin user" end - include_context 'signed in member' do - it "can't view CMS admin if not an admin member" do - visit comfy_admin_cms_path - expect(current_path).to eq root_path - expect(page).to have_content "Please sign in as an admin user" + context 'signed in' do + include_context 'signed in member' do + it "can't view CMS admin if not an admin member" do + visit comfy_admin_cms_path + expect(current_path).to eq root_path + expect(page).to have_content "Please sign in as an admin user" + end end end - - include_context 'signed in admin' do - it "admin members can view CMS admin area" do - visit comfy_admin_cms_path - expect(current_path).to match(/#{comfy_admin_cms_path}/) # match any CMS admin page + context 'admin' do + include_context 'signed in admin' do + it "admin members can view CMS admin area" do + visit comfy_admin_cms_path + expect(current_path).to match(/#{comfy_admin_cms_path}/) # match any CMS admin page + end end end end diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index e9a297cad..51e73f9f6 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -20,53 +20,55 @@ describe "crop detail page", js: true do end end - include_context "signed in member" do - context "action buttons" do - before { subject } + context 'signed in' do + include_context "signed in member" do + context "action buttons" do + before { subject } - it "has a link to plant the crop" do - expect(page).to have_link "Plant #{crop.name}", href: new_planting_path(crop_id: crop.id) - end - it "has a link to harvest the crop" do - expect(page).to have_link "Harvest #{crop.name}", href: new_harvest_path(crop_id: crop.id) - end - it "has a link to add seeds" do - expect(page).to have_link "Add #{crop.name} seeds to stash", href: new_seed_path(crop_id: crop.id) - end - end - - context "SEO" do - before { subject } - - it "has seed heading with SEO" do - expect(page).to have_content "Find #{crop.name} seeds" + it "has a link to plant the crop" do + expect(page).to have_link "Plant #{crop.name}", href: new_planting_path(crop_id: crop.id) + end + it "has a link to harvest the crop" do + expect(page).to have_link "Harvest #{crop.name}", href: new_harvest_path(crop_id: crop.id) + end + it "has a link to add seeds" do + expect(page).to have_link "Add #{crop.name} seeds to stash", href: new_seed_path(crop_id: crop.id) + end end - it "has harvest heading with SEO" do - expect(page).to have_content "#{crop.name.capitalize} harvests" - end + context "SEO" do + before { subject } - it "has planting heading with SEO" do - expect(page).to have_content "See who's planted #{crop.name.pluralize}" - end + it "has seed heading with SEO" do + expect(page).to have_content "Find #{crop.name} seeds" + end - it "has planting advice with SEO" do - expect(page).to have_content "How to grow #{crop.name}" - end + it "has harvest heading with SEO" do + expect(page).to have_content "#{crop.name.capitalize} harvests" + end - it "has a link to Wikipedia with SEO" do - expect(page).to have_content "Learn more about #{crop.name}" - expect(page).to have_link "Wikipedia (English)", href: crop.en_wikipedia_url - end + it "has planting heading with SEO" do + expect(page).to have_content "See who's planted #{crop.name.pluralize}" + end - it "has a link to OpenFarm" do - expect(page).to have_link "OpenFarm - Growing guide", - href: "https://openfarm.cc/en/crops/#{CGI.escape crop.name}" - end + it "has planting advice with SEO" do + expect(page).to have_content "How to grow #{crop.name}" + end - it "has a link to gardenate" do - expect(page).to have_link "Gardenate - Planting reminders", - href: "https://www.gardenate.com/plant/#{CGI.escape crop.name}" + it "has a link to Wikipedia with SEO" do + expect(page).to have_content "Learn more about #{crop.name}" + expect(page).to have_link "Wikipedia (English)", href: crop.en_wikipedia_url + end + + it "has a link to OpenFarm" do + expect(page).to have_link "OpenFarm - Growing guide", + href: "https://openfarm.cc/en/crops/#{CGI.escape crop.name}" + end + + it "has a link to gardenate" do + expect(page).to have_link "Gardenate - Planting reminders", + href: "https://www.gardenate.com/plant/#{CGI.escape crop.name}" + end end end end @@ -79,16 +81,18 @@ describe "crop detail page", js: true do expect(page).not_to have_content "You have 20 seeds" end - include_context 'signed in member' do - it "User signed in" do - visit crop_path(seed.crop) - expect(page).to have_link "You have 20 seeds of this crop." - end - it "click link to your owned seeds" do - seed.update! owner: member - visit crop_path(seed.crop) - click_link "You have 20 seeds of this crop." - expect(current_path).to eq member_seeds_path(member_slug: member.slug) + context 'signed in' do + include_context 'signed in member' do + it "User signed in" do + visit crop_path(seed.crop) + expect(page).to have_link "You have 20 seeds of this crop." + end + it "click link to your owned seeds" do + seed.update! owner: member + visit crop_path(seed.crop) + click_link "You have 20 seeds of this crop." + expect(current_path).to eq member_seeds_path(member_slug: member.slug) + end end end end diff --git a/spec/features/places/searching_a_place_spec.rb b/spec/features/places/searching_a_place_spec.rb index bf830116a..2231cf4cd 100644 --- a/spec/features/places/searching_a_place_spec.rb +++ b/spec/features/places/searching_a_place_spec.rb @@ -2,7 +2,7 @@ require "rails_helper" describe "User searches" do let!(:located_member) { create :member, location: "Philippines" } - let!(:maize) { create :maize } + let!(:maize) { create :maize } let(:garden) { create :garden, owner: located_member } let!(:seed1) { create :seed, owner: located_member } let!(:planting) { create :planting, garden: garden, owner: located_member, planted_at: Date.parse("2013-3-10") } From a74891f97fc298cb6aa5463418945130df696a87 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 17 Aug 2019 15:30:45 +1200 Subject: [PATCH 131/151] Fix spec --- spec/features/crops/crop_detail_page_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index 51e73f9f6..13be4a75b 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -83,12 +83,12 @@ describe "crop detail page", js: true do context 'signed in' do include_context 'signed in member' do + before { seed.update! owner: member } it "User signed in" do visit crop_path(seed.crop) expect(page).to have_link "You have 20 seeds of this crop." end it "click link to your owned seeds" do - seed.update! owner: member visit crop_path(seed.crop) click_link "You have 20 seeds of this crop." expect(current_path).to eq member_seeds_path(member_slug: member.slug) From cbe58713691d350bc6c91806c847e130381d4d15 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 17 Aug 2019 16:00:18 +1200 Subject: [PATCH 132/151] Send message to everyone in migration (no email tho) --- db/migrate/20190720000625_notifications_to_mailboxer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/migrate/20190720000625_notifications_to_mailboxer.rb b/db/migrate/20190720000625_notifications_to_mailboxer.rb index cd92baca6..1dabd8925 100644 --- a/db/migrate/20190720000625_notifications_to_mailboxer.rb +++ b/db/migrate/20190720000625_notifications_to_mailboxer.rb @@ -7,7 +7,7 @@ class NotificationsToMailboxer < ActiveRecord::Migration[5.2] Notification.find_in_batches.each do |group| group.each do |n| n.body = 'message has no body' if n.body.blank? - receipt = n.send_message + receipt = n.sender.send_message(n.recipient, n.body, n.subject) # Copy over which messages are read receipt.conversation.receipts.each(&:mark_as_read) if n.read # copy over timestamps From a334ea03bf21d4ba6fa0cc2234631a7a7123b956 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 17 Aug 2019 19:20:43 +1200 Subject: [PATCH 133/151] fix spec --- spec/features/percy/percy_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/features/percy/percy_spec.rb b/spec/features/percy/percy_spec.rb index 1cf94d510..6d0a48a3a 100644 --- a/spec/features/percy/percy_spec.rb +++ b/spec/features/percy/percy_spec.rb @@ -333,6 +333,7 @@ rest of the garden. Percy.snapshot(page, name: "#{prefix}/community-menu") click_on 'percy', class: 'nav-link' Percy.snapshot(page, name: "#{prefix}/member-menu") + end end end end From f3346fcadf950ef4723833794d030524538e3764 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 18 Aug 2019 14:31:51 +1200 Subject: [PATCH 134/151] Add rspectre gem --- Gemfile | 1 + Gemfile.lock | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/Gemfile b/Gemfile index 510b993f5..40272e967 100644 --- a/Gemfile +++ b/Gemfile @@ -150,6 +150,7 @@ group :development, :test do gem 'i18n-tasks' # adds tests for finding missing and unused translations gem 'rspec-activemodel-mocks' gem 'rspec-rails' # unit testing framework + gem 'rspectre', require: false # finds unused code in specs gem 'rubocop', '~> 0.71' gem 'rubocop-rails' gem 'rubocop-rspec' diff --git a/Gemfile.lock b/Gemfile.lock index 2b13de429..e747ee738 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,6 +2,7 @@ GEM remote: https://rubygems.org/ remote: https://rails-assets.org/ specs: + abstract_type (0.0.7) actioncable (5.2.2.1) actionpack (= 5.2.2.1) nio4r (~> 2.0) @@ -53,8 +54,15 @@ GEM i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) + adamantium (0.2.0) + ice_nine (~> 0.11.0) + memoizable (~> 0.4.0) addressable (2.6.0) public_suffix (>= 2.0.2, < 4.0) + anima (0.3.1) + abstract_type (~> 0.0.7) + adamantium (~> 0.2) + equalizer (~> 0.0.11) arel (9.0.0) ast (2.4.0) autoprefixer-rails (9.6.0) @@ -130,6 +138,9 @@ GEM sassc-rails (>= 2.0.0) comfy_bootstrap_form (4.0.6) rails (>= 5.0.0) + concord (0.1.5) + adamantium (~> 0.2.0) + equalizer (~> 0.0.9) concurrent-ruby (1.1.5) connection_pool (2.2.2) coveralls (0.8.19) @@ -166,6 +177,7 @@ GEM elasticsearch-transport (6.8.0) faraday multi_json + equalizer (0.0.11) erubi (1.8.0) erubis (2.7.0) excon (0.64.0) @@ -244,6 +256,7 @@ GEM rails-i18n rainbow (>= 2.2.2, < 4.0) terminal-table (>= 1.5.1) + ice_nine (0.11.2) jaro_winkler (1.5.3) jquery-rails (4.3.5) rails-dom-testing (>= 1, < 3) @@ -300,6 +313,8 @@ GEM material_icons (2.2.1) railties (>= 3.2) memcachier (0.0.2) + memoizable (0.4.2) + thread_safe (~> 0.3, >= 0.3.1) method_source (0.9.2) mime-types (3.2.2) mime-types-data (~> 3.2015) @@ -352,6 +367,7 @@ GEM heroics (~> 0.0.25) moneta (~> 1.0.0) popper_js (1.14.5) + procto (0.0.3) public_suffix (3.1.1) puma (4.1.0) nio4r (~> 2.0) @@ -410,6 +426,10 @@ GEM responders (3.0.0) actionpack (>= 5.0) railties (>= 5.0) + rspec (3.8.0) + rspec-core (~> 3.8.0) + rspec-expectations (~> 3.8.0) + rspec-mocks (~> 3.8.0) rspec-activemodel-mocks (1.1.0) activemodel (>= 3.0) activesupport (>= 3.0) @@ -431,6 +451,12 @@ GEM rspec-mocks (~> 3.8.0) rspec-support (~> 3.8.0) rspec-support (3.8.2) + rspectre (0.0.1) + anima (~> 0.3) + concord (~> 0.1) + parser (~> 2.3) + rspec (~> 3.0) + unparser (~> 0.2) rubocop (0.74.0) jaro_winkler (~> 1.5.1) parallel (~> 1.10) @@ -516,6 +542,14 @@ GEM kgio (~> 2.6) raindrops (~> 0.7) uniform_notifier (1.12.1) + unparser (0.4.5) + abstract_type (~> 0.0.7) + adamantium (~> 0.2.0) + concord (~> 0.1.5) + diff-lcs (~> 1.3) + equalizer (~> 0.0.9) + parser (~> 2.6.3) + procto (~> 0.0.2) warden (1.2.8) rack (>= 2.0.6) webdrivers (4.1.2) @@ -615,6 +649,7 @@ DEPENDENCIES responders rspec-activemodel-mocks rspec-rails + rspectre rubocop (~> 0.71) rubocop-rails rubocop-rspec From 756cf1fe3a2b5cad55da4e86c7df1fa896f6d948 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 18 Aug 2019 14:51:24 +1200 Subject: [PATCH 135/151] Removing unused code in specs --- .../api/v1/plantings_controller_spec.rb | 6 ------ spec/controllers/charts/gardens_controller_spec.rb | 1 - spec/controllers/garden_types_controller_spec.rb | 3 --- spec/controllers/likes_controller_spec.rb | 2 -- spec/features/crops/scientific_name_spec.rb | 1 - spec/features/crops/show_spec.rb | 5 +---- spec/features/harvests/harvesting_a_crop_spec.rb | 3 +-- spec/features/likeable_spec.rb | 1 - spec/features/members/deletion_spec.rb | 1 - spec/features/percy/percy_spec.rb | 1 - spec/features/photos/new_photo_spec.rb | 4 ---- spec/features/photos/show_photo_spec.rb | 2 -- spec/features/plantings/planting_a_crop_spec.rb | 1 - spec/features/seeds/misc_seeds_spec.rb | 4 ---- spec/features/shared_examples/append_date.rb | 1 - spec/features/signin_spec.rb | 1 - spec/features/signout_spec.rb | 2 -- spec/models/comment_spec.rb | 2 -- spec/models/crop_spec.rb | 14 +------------- spec/models/garden_spec.rb | 1 - spec/models/planting_spec.rb | 3 --- 21 files changed, 3 insertions(+), 56 deletions(-) diff --git a/spec/controllers/api/v1/plantings_controller_spec.rb b/spec/controllers/api/v1/plantings_controller_spec.rb index 57b450d94..c187e1213 100644 --- a/spec/controllers/api/v1/plantings_controller_spec.rb +++ b/spec/controllers/api/v1/plantings_controller_spec.rb @@ -5,12 +5,6 @@ require 'rails_helper' RSpec.describe Api::V1::PlantingsController, type: :controller do subject { JSON.parse response.body } - let(:headers) do - { - 'Accept' => 'application/vnd.api+json', - 'Content-Type' => 'application/vnd.api+json' - } - end let!(:member) { FactoryBot.create :member } describe '#index' do diff --git a/spec/controllers/charts/gardens_controller_spec.rb b/spec/controllers/charts/gardens_controller_spec.rb index 250b05358..1eb959b29 100644 --- a/spec/controllers/charts/gardens_controller_spec.rb +++ b/spec/controllers/charts/gardens_controller_spec.rb @@ -2,7 +2,6 @@ require 'rails_helper' describe Charts::GardensController do include Devise::Test::ControllerHelpers - let(:valid_params) { { name: 'My second Garden' } } let(:garden) { FactoryBot.create :garden } diff --git a/spec/controllers/garden_types_controller_spec.rb b/spec/controllers/garden_types_controller_spec.rb index 73e59d176..53bc9cae8 100644 --- a/spec/controllers/garden_types_controller_spec.rb +++ b/spec/controllers/garden_types_controller_spec.rb @@ -5,9 +5,6 @@ RSpec.describe GardenTypesController, type: :controller do let(:valid_params) { { name: 'My second GardenType' } } let(:garden_type) { FactoryBot.create :garden_type } - let(:member) { FactoryBot.create(:member) } - let(:admin_member) { FactoryBot.create(:admin) } - context "when not signed in" do describe 'GET new' do before { get :new, params: { id: garden_type.to_param } } diff --git a/spec/controllers/likes_controller_spec.rb b/spec/controllers/likes_controller_spec.rb index 5527a595e..6730b0a8f 100644 --- a/spec/controllers/likes_controller_spec.rb +++ b/spec/controllers/likes_controller_spec.rb @@ -4,7 +4,6 @@ describe LikesController do let(:like) { FactoryBot.create :like, member: member } let(:member) { FactoryBot.create(:member) } let(:blogpost) { FactoryBot.create(:post) } - let(:mypost) { FactoryBot.create(:post, author: member) } before { sign_in member } @@ -22,7 +21,6 @@ describe LikesController do end describe "Liking your own post" do - let(:blogpost) { FactoryBot.create(:post, author: member) } end end diff --git a/spec/features/crops/scientific_name_spec.rb b/spec/features/crops/scientific_name_spec.rb index 3b525c5c3..a5f206fdd 100644 --- a/spec/features/crops/scientific_name_spec.rb +++ b/spec/features/crops/scientific_name_spec.rb @@ -18,7 +18,6 @@ describe "Scientific names", js: true do context "User is a crop wrangler" do let!(:crop_wranglers) { create_list :crop_wrangling_member, 3 } - let(:member) { crop_wranglers.first } include_context 'signed in crop wrangler' do it "Crop wranglers can edit scientific names" do diff --git a/spec/features/crops/show_spec.rb b/spec/features/crops/show_spec.rb index bfab353a4..f6fb15410 100644 --- a/spec/features/crops/show_spec.rb +++ b/spec/features/crops/show_spec.rb @@ -1,10 +1,7 @@ require 'rails_helper' describe "browse crops" do - let(:tomato) { create :tomato } - let(:maize) { create :maize } - let(:pending_crop) { create :crop_request } - let(:rejected_crop) { create :rejected_crop } + let(:tomato) { create :tomato } it "Show crop info" do visit crop_path(tomato) diff --git a/spec/features/harvests/harvesting_a_crop_spec.rb b/spec/features/harvests/harvesting_a_crop_spec.rb index d3ded52e1..7ad9a285a 100644 --- a/spec/features/harvests/harvesting_a_crop_spec.rb +++ b/spec/features/harvests/harvesting_a_crop_spec.rb @@ -4,8 +4,7 @@ require 'custom_matchers' describe "Harvesting a crop", :js, :elasticsearch do include_context 'signed in member' do let!(:maize) { create :maize } - let!(:plant_part) { create :plant_part } - let(:planting) { create :planting, crop: maize, owner: member } + let!(:plant_part) { create :plant_part } before { visit new_harvest_path } diff --git a/spec/features/likeable_spec.rb b/spec/features/likeable_spec.rb index 767bffa07..b2527402a 100644 --- a/spec/features/likeable_spec.rb +++ b/spec/features/likeable_spec.rb @@ -1,7 +1,6 @@ require 'rails_helper' describe 'Likeable', js: true do - let(:member) { FactoryBot.create(:member) } let(:another_member) { FactoryBot.create(:london_member) } let!(:post) { FactoryBot.create(:post, author: member) } let!(:photo) { FactoryBot.create(:photo, owner: member) } diff --git a/spec/features/members/deletion_spec.rb b/spec/features/members/deletion_spec.rb index 35326a0c9..ce3ff7769 100644 --- a/spec/features/members/deletion_spec.rb +++ b/spec/features/members/deletion_spec.rb @@ -10,7 +10,6 @@ describe "member deletion" do let!(:harvest) { FactoryBot.create(:harvest, owner: member) } let!(:seed) { FactoryBot.create(:seed, owner: member) } let!(:secondgarden) { FactoryBot.create(:garden, owner: member) } - let(:admin) { FactoryBot.create(:admin_member) } before do login_as(member) diff --git a/spec/features/percy/percy_spec.rb b/spec/features/percy/percy_spec.rb index 6d0a48a3a..01b32539a 100644 --- a/spec/features/percy/percy_spec.rb +++ b/spec/features/percy/percy_spec.rb @@ -340,7 +340,6 @@ rest of the garden. context 'wrangling crops' do include_context 'signed in crop wrangler' do - let(:prefix) { 'crop-wrangler' } let!(:candy) { FactoryBot.create :crop_request, name: 'candy' } it 'crop wrangling page' do diff --git a/spec/features/photos/new_photo_spec.rb b/spec/features/photos/new_photo_spec.rb index 4bf64065e..93e3a155c 100644 --- a/spec/features/photos/new_photo_spec.rb +++ b/spec/features/photos/new_photo_spec.rb @@ -1,11 +1,7 @@ require 'rails_helper' describe "new photo page" do - let(:photo) { FactoryBot.create :photo } - context "signed in member" do - let(:member) { FactoryBot.create :member } - include_context 'signed in member' do context "viewing a planting" do let(:planting) { FactoryBot.create :planting, owner: member } diff --git a/spec/features/photos/show_photo_spec.rb b/spec/features/photos/show_photo_spec.rb index 664b24aee..779270b0e 100644 --- a/spec/features/photos/show_photo_spec.rb +++ b/spec/features/photos/show_photo_spec.rb @@ -2,8 +2,6 @@ require 'rails_helper' describe "show photo page" do context "signed in member" do - let(:member) { create :member } - include_context 'signed in member' do context "linked to planting" do let(:planting) { create :planting } diff --git a/spec/features/plantings/planting_a_crop_spec.rb b/spec/features/plantings/planting_a_crop_spec.rb index 8ff4b2d96..39ee86bd0 100644 --- a/spec/features/plantings/planting_a_crop_spec.rb +++ b/spec/features/plantings/planting_a_crop_spec.rb @@ -2,7 +2,6 @@ require "rails_helper" require 'custom_matchers' describe "Planting a crop", :js, :elasticsearch do - let(:member) { FactoryBot.create :member } let!(:maize) { FactoryBot.create :maize } let(:garden) { FactoryBot.create :garden, owner: member } let!(:planting) do diff --git a/spec/features/seeds/misc_seeds_spec.rb b/spec/features/seeds/misc_seeds_spec.rb index 467c1acb3..33c8576c7 100644 --- a/spec/features/seeds/misc_seeds_spec.rb +++ b/spec/features/seeds/misc_seeds_spec.rb @@ -1,11 +1,7 @@ require 'rails_helper' describe "seeds", js: true do - let(:member) { create :member } - context "signed in user" do - let(:crop) { create :crop } - include_context 'signed in member' do xit "button on index to edit seed" do let!(:seed) { create :seed, owner: member } diff --git a/spec/features/shared_examples/append_date.rb b/spec/features/shared_examples/append_date.rb index 6f6247736..8dc283c22 100644 --- a/spec/features/shared_examples/append_date.rb +++ b/spec/features/shared_examples/append_date.rb @@ -1,6 +1,5 @@ shared_examples "append date" do let(:this_month) { Time.zone.today.strftime("%b") } - let(:this_year) { Time.zone.today.strftime("%Y") } before { visit path } diff --git a/spec/features/signin_spec.rb b/spec/features/signin_spec.rb index dd7526549..55e31d4b9 100644 --- a/spec/features/signin_spec.rb +++ b/spec/features/signin_spec.rb @@ -4,7 +4,6 @@ describe "signin", js: true do let(:member) { FactoryBot.create :member } let(:recipient) { FactoryBot.create :member } let(:wrangler) { FactoryBot.create :crop_wrangling_member } - let(:notification) { FactoryBot.create :notification, recipient: recipient } def login fill_in 'Login', with: member.login_name diff --git a/spec/features/signout_spec.rb b/spec/features/signout_spec.rb index c94221b1e..d65370ff6 100644 --- a/spec/features/signout_spec.rb +++ b/spec/features/signout_spec.rb @@ -3,8 +3,6 @@ require 'rails_helper' describe "signout" do let(:member) { create :member } - let(:path) {} - it "redirect to previous page after signout" do visit crops_path # some random page click_link 'Sign in' diff --git a/spec/models/comment_spec.rb b/spec/models/comment_spec.rb index 687219386..75166df9f 100644 --- a/spec/models/comment_spec.rb +++ b/spec/models/comment_spec.rb @@ -14,8 +14,6 @@ describe Comment do end context "notifications" do - let(:comment) { FactoryBot.create(:comment) } - it "sends a notification when a comment is posted" do expect do FactoryBot.create(:comment) diff --git a/spec/models/crop_spec.rb b/spec/models/crop_spec.rb index ed17069c9..4b775b4ef 100644 --- a/spec/models/crop_spec.rb +++ b/spec/models/crop_spec.rb @@ -1,9 +1,6 @@ require 'rails_helper' describe Crop do - let(:pp2) { FactoryBot.create(:plant_part) } - let(:pp1) { FactoryBot.create(:plant_part) } - let(:maize) { FactoryBot.create(:maize) } context 'all fields present' do let(:crop) { FactoryBot.create(:tomato) } @@ -50,7 +47,6 @@ describe Crop do context 'popularity' do let(:tomato) { FactoryBot.create(:tomato) } let(:maize) { FactoryBot.create(:maize) } - let(:cucumber) { FactoryBot.create(:crop, name: 'cucumber') } before do FactoryBot.create_list(:planting, 10, crop: maize) @@ -145,8 +141,7 @@ describe Crop do shared_examples 'has default photo' do it { expect(Crop.has_photos).to include(crop) } end - let!(:crop) { FactoryBot.create :tomato } - let(:member) { FactoryBot.create :member } + let!(:crop) { FactoryBot.create :tomato } context 'with a planting photo' do let!(:photo) { FactoryBot.create(:photo, owner: planting.owner) } @@ -296,7 +291,6 @@ describe Crop do context 'interesting' do subject { Crop.interesting } - let(:photo) { FactoryBot.create :photo } # first, a couple of candidate crops let(:crop1) { FactoryBot.create(:crop) } let(:crop2) { FactoryBot.create(:crop) } @@ -349,13 +343,7 @@ describe Crop do end end - let(:maize) { FactoryBot.create(:maize) } - let(:pp1) { FactoryBot.create(:plant_part) } - let(:pp2) { FactoryBot.create(:plant_part) } - context "harvests" do - let(:h1) { FactoryBot.create(:harvest, crop: maize, plant_part: pp1) } - let(:h2) { FactoryBot.create(:harvest, crop: maize, plant_part: pp2) } let!(:crop) { FactoryBot.create(:crop) } let!(:harvest) { FactoryBot.create(:harvest, crop: crop) } diff --git a/spec/models/garden_spec.rb b/spec/models/garden_spec.rb index 522a9bfc1..a6e0b12fb 100644 --- a/spec/models/garden_spec.rb +++ b/spec/models/garden_spec.rb @@ -3,7 +3,6 @@ require 'rails_helper' describe Garden do let(:owner) { FactoryBot.create(:member, login_name: 'hatupatu') } let(:garden) { FactoryBot.create(:garden, owner: owner, name: 'Springfield Community Garden') } - let(:garden_type) { FactoryBot.create(:garden_type, name: "aquaponic") } it "has a slug" do garden.slug.should match(/hatupatu-springfield-community-garden/) diff --git a/spec/models/planting_spec.rb b/spec/models/planting_spec.rb index 32d3da008..56e477f4f 100644 --- a/spec/models/planting_spec.rb +++ b/spec/models/planting_spec.rb @@ -5,9 +5,6 @@ describe Planting do let(:garden_owner) { FactoryBot.create(:member, login_name: 'hatupatu') } let(:garden) { FactoryBot.create(:garden, owner: garden_owner, name: 'Springfield Community Garden') } let(:planting) { FactoryBot.create(:planting, crop: crop, garden: garden, owner: garden.owner) } - let(:finished_planting) do - FactoryBot.create :planting, planted_at: 4.days.ago, finished_at: 2.days.ago, finished: true - end describe 'planting lifespan predictions' do context 'no predications data yet' do From c6894e79174528d28f3cb3c75dbebeea6e691091 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 18 Aug 2019 14:51:46 +1200 Subject: [PATCH 136/151] Setting linters as require: false in gemfile --- Gemfile | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/Gemfile b/Gemfile index 40272e967..cfa8ef248 100644 --- a/Gemfile +++ b/Gemfile @@ -135,26 +135,28 @@ group :development do end group :development, :test do - gem 'bullet' # performance tuning by finding unnecesary queries - gem 'byebug' # debugging - gem 'capybara' # integration tests - gem 'capybara-email' # integration tests for email - gem 'capybara-screenshot' # for test debugging - gem 'coveralls', require: false # coverage analysis + gem 'bullet' # performance tuning by finding unnecesary queries + gem 'byebug' # debugging + gem 'capybara' # integration tests + gem 'capybara-email' # integration tests for email + gem 'capybara-screenshot' # for test debugging gem 'database_cleaner' - gem 'factory_bot_rails' # for creating test data + gem 'factory_bot_rails' # for creating test data gem 'faker' - gem 'haml-i18n-extractor' - gem 'haml-rails' # HTML templating language - gem 'haml_lint', '>= 0.25.1' # Checks haml files for goodness - gem 'i18n-tasks' # adds tests for finding missing and unused translations + gem 'haml-rails' # HTML templating language gem 'rspec-activemodel-mocks' - gem 'rspec-rails' # unit testing framework - gem 'rspectre', require: false # finds unused code in specs - gem 'rubocop', '~> 0.71' + gem 'rspec-rails' # unit testing framework gem 'rubocop-rails' gem 'rubocop-rspec' - gem 'webrat' # provides HTML matchers for view tests + gem 'webrat' # provides HTML matchers for view tests + + # cli utils + gem 'coveralls', require: false # coverage analysis + gem 'haml-i18n-extractor', require: false + gem 'haml_lint', '>= 0.25.1', require: false # Checks haml files for goodness + gem 'i18n-tasks', require: false # adds tests for finding missing and unused translations + gem 'rspectre', require: false # finds unused code in specs + gem 'rubocop', '~> 0.71', require: false end group :test do From 34b399cd8e8ab9fe97984c7e840adc481f3fb712 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 18 Aug 2019 15:06:26 +1200 Subject: [PATCH 137/151] Use more signed in contexts in browse crops spec More member role contexts on alt name spec More member role contexts in crop feature specs Don't wrap the shared_context --- spec/features/admin/admin_spec.rb | 9 +- spec/features/admin/forums_spec.rb | 79 +++--- spec/features/cms_spec.rb | 20 +- .../comments/commenting_a_comment_spec.rb | 45 ++-- spec/features/crops/alternate_name_spec.rb | 51 +++- spec/features/crops/browse_crops_spec.rb | 62 +++-- spec/features/crops/creating_a_crop_spec.rb | 96 +++++-- spec/features/crops/crop_detail_page_spec.rb | 100 ++++--- spec/features/crops/crop_photos_spec.rb | 12 +- spec/features/crops/crop_wranglers_spec.rb | 138 +++++----- .../crops/crop_wrangling_button_spec.rb | 14 +- spec/features/crops/delete_crop_spec.rb | 41 +-- spec/features/crops/request_new_crop_spec.rb | 54 ++-- spec/features/crops/requested_crops_spec.rb | 3 +- spec/features/crops/scientific_name_spec.rb | 107 ++++---- spec/features/gardens/actions_spec.rb | 107 ++++---- spec/features/gardens/adding_gardens_spec.rb | 3 +- spec/features/gardens/gardens_spec.rb | 3 +- spec/features/gardens/index_spec.rb | 105 ++++---- .../features/harvests/browse_harvests_spec.rb | 3 +- .../harvests/harvesting_a_crop_spec.rb | 3 +- spec/features/home/home_spec.rb | 17 +- spec/features/likeable_spec.rb | 133 +++++----- spec/features/members/ban_spec.rb | 17 +- spec/features/members/following_spec.rb | 95 ++++--- spec/features/members/profile_spec.rb | 27 +- spec/features/notifications_spec.rb | 64 +++++ spec/features/percy/percy_spec.rb | 251 +++++++++--------- spec/features/photos/new_photo_spec.rb | 73 +++-- spec/features/photos/show_photo_spec.rb | 95 ++++--- .../features/places/searching_a_place_spec.rb | 47 ++-- .../plantings/planting_a_crop_spec.rb | 4 +- spec/features/posts/posting_a_post_spec.rb | 3 +- spec/features/seeds/adding_seeds_spec.rb | 3 +- spec/features/seeds/misc_seeds_spec.rb | 125 +++++---- spec/features/seeds/seed_photos.rb | 3 +- 36 files changed, 1072 insertions(+), 940 deletions(-) create mode 100644 spec/features/notifications_spec.rb diff --git a/spec/features/admin/admin_spec.rb b/spec/features/admin/admin_spec.rb index 57c8953b1..94c7a8dca 100644 --- a/spec/features/admin/admin_spec.rb +++ b/spec/features/admin/admin_spec.rb @@ -1,10 +1,9 @@ require 'rails_helper' describe "forums", js: true do - include_context 'signed in admin' do - it "navigating to forum admin with js" do - visit admin_path - Percy.snapshot(page, name: 'Admin page') - end + include_context 'signed in admin' + it "navigating to forum admin with js" do + visit admin_path + Percy.snapshot(page, name: 'Admin page') end end diff --git a/spec/features/admin/forums_spec.rb b/spec/features/admin/forums_spec.rb index d22ace435..a327a692a 100644 --- a/spec/features/admin/forums_spec.rb +++ b/spec/features/admin/forums_spec.rb @@ -1,55 +1,54 @@ require 'rails_helper' describe "forums", js: true do - include_context 'signed in admin' do - let(:forum) { create :forum } + include_context 'signed in admin' + let(:forum) { create :forum } - describe "navigating to forum admin with js" do - before do - visit admin_path - within 'ul#site_admin' do - click_link "Forums" - end + describe "navigating to forum admin with js" do + before do + visit admin_path + within 'ul#site_admin' do + click_link "Forums" end - it { expect(current_path).to eq forums_path } - it { expect(page).to have_link "New forum" } end + it { expect(current_path).to eq forums_path } + it { expect(page).to have_link "New forum" } + end - describe "adding a forum" do - before do - visit forums_path - click_link "New forum" - expect(current_path).to eq new_forum_path - fill_in 'Name', with: 'Discussion' - fill_in 'Description', with: "this is a new forum" - click_button 'Save' - end - it { expect(current_path).to eq forum_path(Forum.last) } - it { expect(page).to have_content 'Forum was successfully created' } + describe "adding a forum" do + before do + visit forums_path + click_link "New forum" + expect(current_path).to eq new_forum_path + fill_in 'Name', with: 'Discussion' + fill_in 'Description', with: "this is a new forum" + click_button 'Save' end + it { expect(current_path).to eq forum_path(Forum.last) } + it { expect(page).to have_content 'Forum was successfully created' } + end - describe 'editing forum' do - before do - visit forum_path forum - click_link 'Edit' - fill_in 'Name', with: 'Something else' - click_button 'Save' - forum.reload - end - it { expect(current_path).to eq forum_path(forum) } - it { expect(page).to have_content 'Forum was successfully updated' } - it { expect(page).to have_content 'Something else' } + describe 'editing forum' do + before do + visit forum_path forum + click_link 'Edit' + fill_in 'Name', with: 'Something else' + click_button 'Save' + forum.reload end + it { expect(current_path).to eq forum_path(forum) } + it { expect(page).to have_content 'Forum was successfully updated' } + it { expect(page).to have_content 'Something else' } + end - describe 'deleting forum' do - before do - visit forum_path forum - accept_confirm do - click_link 'Delete' - end + describe 'deleting forum' do + before do + visit forum_path forum + accept_confirm do + click_link 'Delete' end - it { expect(current_path).to eq forums_path } - it { expect(page).to have_content 'Forum was successfully deleted' } end + it { expect(current_path).to eq forums_path } + it { expect(page).to have_content 'Forum was successfully deleted' } end end diff --git a/spec/features/cms_spec.rb b/spec/features/cms_spec.rb index 15e4fd521..d13fc1b42 100644 --- a/spec/features/cms_spec.rb +++ b/spec/features/cms_spec.rb @@ -8,20 +8,18 @@ describe "cms admin" do end context 'signed in' do - include_context 'signed in member' do - it "can't view CMS admin if not an admin member" do - visit comfy_admin_cms_path - expect(current_path).to eq root_path - expect(page).to have_content "Please sign in as an admin user" - end + include_context 'signed in member' + it "can't view CMS admin if not an admin member" do + visit comfy_admin_cms_path + expect(current_path).to eq root_path + expect(page).to have_content "Please sign in as an admin user" end end context 'admin' do - include_context 'signed in admin' do - it "admin members can view CMS admin area" do - visit comfy_admin_cms_path - expect(current_path).to match(/#{comfy_admin_cms_path}/) # match any CMS admin page - end + include_context 'signed in admin' + it "admin members can view CMS admin area" do + visit comfy_admin_cms_path + expect(current_path).to match(/#{comfy_admin_cms_path}/) # match any CMS admin page end end end diff --git a/spec/features/comments/commenting_a_comment_spec.rb b/spec/features/comments/commenting_a_comment_spec.rb index 34907080b..6debc9d14 100644 --- a/spec/features/comments/commenting_a_comment_spec.rb +++ b/spec/features/comments/commenting_a_comment_spec.rb @@ -1,33 +1,32 @@ require 'rails_helper' describe 'Commenting on a post' do - include_context 'signed in member' do - let(:member) { create :member } - let(:post) { create :post, author: member } + include_context 'signed in member' + let(:member) { create :member } + let(:post) { create :post, author: member } - before { visit new_comment_path post_id: post.id } + before { visit new_comment_path post_id: post.id } - it "creating a comment" do - fill_in "comment_body", with: "This is a sample test for comment" - click_button "Post comment" - expect(page).to have_content "comment was successfully created." - expect(page).to have_content "Posted by" - Percy.snapshot(page, name: 'Posting a comment') + it "creating a comment" do + fill_in "comment_body", with: "This is a sample test for comment" + click_button "Post comment" + expect(page).to have_content "comment was successfully created." + expect(page).to have_content "Posted by" + Percy.snapshot(page, name: 'Posting a comment') + end + + context "editing a comment" do + let(:existing_comment) { create :comment, post: post, author: member } + + before do + visit edit_comment_path existing_comment end - context "editing a comment" do - let(:existing_comment) { create :comment, post: post, author: member } - - before do - visit edit_comment_path existing_comment - end - - it "saving edit" do - fill_in "comment_body", with: "Testing edit for comment" - click_button "Post comment" - expect(page).to have_content "comment was successfully updated." - expect(page).to have_content "edited at" - end + it "saving edit" do + fill_in "comment_body", with: "Testing edit for comment" + click_button "Post comment" + expect(page).to have_content "comment was successfully updated." + expect(page).to have_content "edited at" end end end diff --git a/spec/features/crops/alternate_name_spec.rb b/spec/features/crops/alternate_name_spec.rb index acd79bb36..adfc3b4e3 100644 --- a/spec/features/crops/alternate_name_spec.rb +++ b/spec/features/crops/alternate_name_spec.rb @@ -4,21 +4,23 @@ describe "Alternate names", js: true do let!(:alternate_eggplant) { create :alternate_eggplant } let(:crop) { alternate_eggplant.crop } - it "Display alternate names on crop page" do - visit crop_path(alternate_eggplant.crop) - # expect(page.status_code).to equal 200 - expect(page).to have_content alternate_eggplant.name + shared_examples 'show alt names' do + it "can see alternate names on crop page" do + visit crop_path(alternate_eggplant.crop) + # expect(page.status_code).to equal 200 + expect(page).to have_content alternate_eggplant.name + end + + it "can see page for alternate names" do + visit alternate_names_path + expect(page).to have_content alternate_eggplant.name + end end - it "Index page for alternate names" do - visit alternate_names_path - expect(page).to have_content alternate_eggplant.name - end - - include_context 'signed in crop wrangler' do + shared_examples 'edit alt names' do let!(:crop_wranglers) { create_list :crop_wrangling_member, 3 } - it "Crop wranglers can edit alternate names" do + it "can edit alternate names" do visit crop_path(crop) # expect(page.status_code).to equal 200 expect(page).to have_content "CROP WRANGLER" @@ -36,7 +38,7 @@ describe "Alternate names", js: true do expect(page).to have_content 'Alternate name was successfully updated' end - it "Crop wranglers can delete alternate names" do + it "can delete alternate names" do visit crop_path(alternate_eggplant.crop) click_link('aubergine', href: '#') accept_confirm do @@ -46,7 +48,7 @@ describe "Alternate names", js: true do expect(page).to have_content 'Alternate name was successfully deleted' end - it "Crop wranglers can add alternate names" do + it "can add alternate names" do visit crop_path(crop) expect(page).to have_link "Add", href: new_alternate_name_path(crop_id: crop.id) @@ -60,7 +62,7 @@ describe "Alternate names", js: true do expect(page).to have_content 'Alternate name was successfully created' end - it "The show-alternate-name page works" do + it "shows alternate-name page" do visit alternate_name_path(alternate_eggplant) # expect(page.status_code).to equal 200 expect(page).to have_content alternate_eggplant.crop.name @@ -77,4 +79,25 @@ describe "Alternate names", js: true do end end end + + context 'Anonymous' do + include_examples 'show alt names' + end + + context 'Signed in member' do + include_context 'signed in member' + include_examples 'show alt names' + end + + context 'Crop wrangler' do + include_context 'signed in crop wrangler' + include_examples 'show alt names' + include_examples 'edit alt names' + end + + context 'Admin' do + include_context 'signed in admin' + include_examples 'show alt names' + include_examples 'edit alt names' + end end diff --git a/spec/features/crops/browse_crops_spec.rb b/spec/features/crops/browse_crops_spec.rb index 9979cfb8e..d60727bbc 100644 --- a/spec/features/crops/browse_crops_spec.rb +++ b/spec/features/crops/browse_crops_spec.rb @@ -6,31 +6,51 @@ describe "browse crops" do let!(:pending_crop) { FactoryBot.create :crop_request } let!(:rejected_crop) { FactoryBot.create :rejected_crop } - it "has a form for sorting by" do - visit crops_path - expect(page).to have_css "select#sort" - end - - it "shows a list of crops" do - visit crops_path - expect(page).to have_content tomato.name - end - - it "pending crops are not listed" do - visit crops_path - expect(page).not_to have_content pending_crop.name - end - - it "rejected crops are not listed" do - visit crops_path - expect(page).not_to have_content rejected_crop.name - end - - include_context 'signed in crop wrangler' do + shared_examples 'shows crops' do before { visit crops_path } + it "has a form for sorting by" do + expect(page).to have_css "select#sort" + end + it "shows a list of crops" do + expect(page).to have_content tomato.name + end + + it "pending crops are not listed" do + expect(page).not_to have_content pending_crop.name + end + + it "rejected crops are not listed" do + expect(page).not_to have_content rejected_crop.name + end + end + + shared_examples 'add new crop' do it "shows a new crop link" do expect(page).to have_link "Add New Crop" end end + + context 'anon' do + include_examples 'shows crops' + it { expect(page).not_to have_link "Add New Crop" } + end + + context 'member' do + include_context 'signed in member' + include_examples 'shows crops' + include_examples 'add new crop' + end + + context 'wrangler' do + include_context 'signed in crop wrangler' + include_examples 'shows crops' + include_examples 'add new crop' + end + + context 'admin' do + include_context 'signed in admin' + include_examples 'shows crops' + include_examples 'add new crop' + end end diff --git a/spec/features/crops/creating_a_crop_spec.rb b/spec/features/crops/creating_a_crop_spec.rb index 14dd983d2..02b686c83 100644 --- a/spec/features/crops/creating_a_crop_spec.rb +++ b/spec/features/crops/creating_a_crop_spec.rb @@ -1,35 +1,73 @@ require 'rails_helper' -describe "Crop - " do - let!(:crop_wrangler) { FactoryBot.create :crop_wrangling_member } - let!(:member) { FactoryBot.create :member } - - before do - login_as member - visit new_crop_path +describe "Crop", js: true do + shared_examples 'request crop' do + describe "requesting a crop with multiple scientific and alternate name" do + before do + visit new_crop_path + within "form#new_crop" do + fill_in "crop_name", with: "Philippine flower" + fill_in "en_wikipedia_url", with: "https://en.wikipedia.org/wiki/Jasminum_sambac" + click_button "add-sci_name-row" + fill_in "sci_name[1]", with: "Jasminum sambac 1" + fill_in "sci_name[2]", with: "Jasminum sambac 2" + fill_in "alt_name[1]", with: "Sampaguita" + click_button "add-alt_name-row" + click_button "add-alt_name-row" + fill_in "alt_name[2]", with: "Manol" + click_button "add-alt_name-row" + fill_in "alt_name[3]", with: "Jazmin" + fill_in "alt_name[4]", with: "Matsurika" + fill_in "request_notes", with: "This is the Philippine national flower." + click_button "Save" + end + end + it { expect(page).to have_content 'crop was successfully created.' } + it { expect(page).to have_content "This crop is currently pending approval." } + it { expect(page).to have_content "Jasminum sambac 2" } + it { expect(page).to have_content "Matsurika" } + end + end + shared_examples 'create crop' do + describe "creating a crop with multiple scientific and alternate name" do + before do + visit new_crop_path + within "form#new_crop" do + fill_in "crop_name", with: "Philippine flower" + fill_in "en_wikipedia_url", with: "https://en.wikipedia.org/wiki/Jasminum_sambac" + click_button "add-sci_name-row" + fill_in "sci_name[1]", with: "Jasminum sambac 1" + fill_in "sci_name[2]", with: "Jasminum sambac 2" + fill_in "alt_name[1]", with: "Sampaguita" + click_button "add-alt_name-row" + click_button "add-alt_name-row" + fill_in "alt_name[2]", with: "Manol" + click_button "add-alt_name-row" + fill_in "alt_name[3]", with: "Jazmin" + fill_in "alt_name[4]", with: "Matsurika" + click_button "Save" + end + end + it { expect(page).to have_content 'crop was successfully created.' } + it { expect(page).to have_content "Jasminum sambac 2" } + it { expect(page).to have_content "Matsurika" } + end end - it "creating a crop with multiple scientific and alternate name", :js do - within "form#new_crop" do - fill_in "crop_name", with: "Philippine flower" - fill_in "en_wikipedia_url", with: "https://en.wikipedia.org/wiki/Jasminum_sambac" - click_button "add-sci_name-row" - fill_in "sci_name[1]", with: "Jasminum sambac 1" - fill_in "sci_name[2]", with: "Jasminum sambac 2" - fill_in "alt_name[1]", with: "Sampaguita" - click_button "add-alt_name-row" - click_button "add-alt_name-row" - fill_in "alt_name[2]", with: "Manol" - click_button "add-alt_name-row" - fill_in "alt_name[3]", with: "Jazmin" - fill_in "alt_name[4]", with: "Matsurika" - fill_in "request_notes", with: "This is the Philippine national flower." - click_button "Save" - end - - expect(page).to have_content 'crop was successfully created.' - expect(page).to have_content "This crop is currently pending approval." - expect(page).to have_content "Jasminum sambac 2" - expect(page).to have_content "Matsurika" + context 'anon' do + before { visit new_crop_path } + it { expect(page).to have_content 'You need to sign in' } + end + context 'member' do + include_context 'signed in member' + include_examples 'request crop' + end + context 'crop wrangler' do + include_context 'signed in crop wrangler' + include_examples 'create crop' + end + context 'admin' do + include_context 'signed in admin' + include_examples 'create crop' end end diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index 13be4a75b..3d1449a1d 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -21,54 +21,53 @@ describe "crop detail page", js: true do end context 'signed in' do - include_context "signed in member" do - context "action buttons" do - before { subject } + include_context "signed in member" + context "action buttons" do + before { subject } - it "has a link to plant the crop" do - expect(page).to have_link "Plant #{crop.name}", href: new_planting_path(crop_id: crop.id) - end - it "has a link to harvest the crop" do - expect(page).to have_link "Harvest #{crop.name}", href: new_harvest_path(crop_id: crop.id) - end - it "has a link to add seeds" do - expect(page).to have_link "Add #{crop.name} seeds to stash", href: new_seed_path(crop_id: crop.id) - end + it "has a link to plant the crop" do + expect(page).to have_link "Plant #{crop.name}", href: new_planting_path(crop_id: crop.id) + end + it "has a link to harvest the crop" do + expect(page).to have_link "Harvest #{crop.name}", href: new_harvest_path(crop_id: crop.id) + end + it "has a link to add seeds" do + expect(page).to have_link "Add #{crop.name} seeds to stash", href: new_seed_path(crop_id: crop.id) + end + end + + context "SEO" do + before { subject } + + it "has seed heading with SEO" do + expect(page).to have_content "Find #{crop.name} seeds" end - context "SEO" do - before { subject } + it "has harvest heading with SEO" do + expect(page).to have_content "#{crop.name.capitalize} harvests" + end - it "has seed heading with SEO" do - expect(page).to have_content "Find #{crop.name} seeds" - end + it "has planting heading with SEO" do + expect(page).to have_content "See who's planted #{crop.name.pluralize}" + end - it "has harvest heading with SEO" do - expect(page).to have_content "#{crop.name.capitalize} harvests" - end + it "has planting advice with SEO" do + expect(page).to have_content "How to grow #{crop.name}" + end - it "has planting heading with SEO" do - expect(page).to have_content "See who's planted #{crop.name.pluralize}" - end + it "has a link to Wikipedia with SEO" do + expect(page).to have_content "Learn more about #{crop.name}" + expect(page).to have_link "Wikipedia (English)", href: crop.en_wikipedia_url + end - it "has planting advice with SEO" do - expect(page).to have_content "How to grow #{crop.name}" - end + it "has a link to OpenFarm" do + expect(page).to have_link "OpenFarm - Growing guide", + href: "https://openfarm.cc/en/crops/#{CGI.escape crop.name}" + end - it "has a link to Wikipedia with SEO" do - expect(page).to have_content "Learn more about #{crop.name}" - expect(page).to have_link "Wikipedia (English)", href: crop.en_wikipedia_url - end - - it "has a link to OpenFarm" do - expect(page).to have_link "OpenFarm - Growing guide", - href: "https://openfarm.cc/en/crops/#{CGI.escape crop.name}" - end - - it "has a link to gardenate" do - expect(page).to have_link "Gardenate - Planting reminders", - href: "https://www.gardenate.com/plant/#{CGI.escape crop.name}" - end + it "has a link to gardenate" do + expect(page).to have_link "Gardenate - Planting reminders", + href: "https://www.gardenate.com/plant/#{CGI.escape crop.name}" end end end @@ -82,17 +81,16 @@ describe "crop detail page", js: true do end context 'signed in' do - include_context 'signed in member' do - before { seed.update! owner: member } - it "User signed in" do - visit crop_path(seed.crop) - expect(page).to have_link "You have 20 seeds of this crop." - end - it "click link to your owned seeds" do - visit crop_path(seed.crop) - click_link "You have 20 seeds of this crop." - expect(current_path).to eq member_seeds_path(member_slug: member.slug) - end + include_context 'signed in member' + before { seed.update! owner: member } + it "User signed in" do + visit crop_path(seed.crop) + expect(page).to have_link "You have 20 seeds of this crop." + end + it "click link to your owned seeds" do + visit crop_path(seed.crop) + click_link "You have 20 seeds of this crop." + expect(current_path).to eq member_seeds_path(member_slug: member.slug) end end end diff --git a/spec/features/crops/crop_photos_spec.rb b/spec/features/crops/crop_photos_spec.rb index 39654a6bd..13ecc14ac 100644 --- a/spec/features/crops/crop_photos_spec.rb +++ b/spec/features/crops/crop_photos_spec.rb @@ -50,16 +50,14 @@ describe "crop detail page", js: true do end context "when signed in" do - include_context 'signed in member' do - include_examples "shows photos" - end + include_context 'signed in member' + include_examples "shows photos" end context "when signed in as photos owner" do - include_context 'signed in member' do - let(:member) { owner_member } - include_examples "shows photos" - end + include_context 'signed in member' + let(:member) { owner_member } + include_examples "shows photos" end context "when not signed in " do diff --git a/spec/features/crops/crop_wranglers_spec.rb b/spec/features/crops/crop_wranglers_spec.rb index c758fc047..e520f90d3 100644 --- a/spec/features/crops/crop_wranglers_spec.rb +++ b/spec/features/crops/crop_wranglers_spec.rb @@ -2,85 +2,83 @@ require 'rails_helper' describe "crop wranglers", js: true do context "signed in wrangler" do - include_context 'signed in crop wrangler' do - let!(:crop_wranglers) { create_list :crop_wrangling_member, 3 } - let!(:crops) { create_list :crop, 2 } - let!(:requested_crop) { create :crop_request } - let!(:rejected_crop) { create :rejected_crop } + include_context 'signed in crop wrangler' + let!(:crop_wranglers) { create_list :crop_wrangling_member, 3 } + let!(:crops) { create_list :crop, 2 } + let!(:requested_crop) { create :crop_request } + let!(:rejected_crop) { create :rejected_crop } - it "sees crop wranglers listed on the crop wrangler page" do - visit root_path - click_link 'Admin' - click_link 'Crop Wrangling' + it "sees crop wranglers listed on the crop wrangler page" do + visit root_path + click_link 'Admin' + click_link 'Crop Wrangling' - within '.crop_wranglers' do - expect(page).to have_content 'Crop Wranglers:' - crop_wranglers.each do |crop_wrangler| - expect(page).to have_link crop_wrangler.login_name, href: member_path(crop_wrangler) - end + within '.crop_wranglers' do + expect(page).to have_content 'Crop Wranglers:' + crop_wranglers.each do |crop_wrangler| + expect(page).to have_link crop_wrangler.login_name, href: member_path(crop_wrangler) end end - - it "can see list of crops with extra detail of who created a crop" do - visit root_path - click_link 'Admin' - click_link 'Crop Wrangling' - within '#recently-added-crops' do - expect(page).to have_content crops.first.creator.login_name.to_s - end - end - - describe "visiting a crop can see wrangler links" do - before do - visit crop_path(crops.first) - click_link 'Actions' - end - - it { expect(page).to have_content 'You are a CROP WRANGLER' } - it { expect(page).to have_link 'Edit' } - it { expect(page).to have_link 'Delete' } - end - - it "can create a new crop" do - visit root_path - click_link 'Admin' - click_link 'Crop Wrangling' - click_link 'Add Crop' - fill_in 'Name', with: "aubergine" - fill_in 'en_wikipedia_url', with: "http://en.wikipedia.org/wiki/Maize" - fill_in 'sci_name[1]', with: "planticus maximus" - click_on 'Save' - expect(page).to have_content 'crop was successfully created.' - expect(page).to have_content 'planticus maximus' - end - - it "View pending crops" do - visit crop_path(requested_crop) - expect(page).to have_content "This crop is currently pending approval." - expect(page).to have_content "Please approve this even though it's fake." - end - - it "View rejected crops" do - visit crop_path(rejected_crop) - expect(page).to have_content "This crop was rejected for the following reason: Totally fake" - end end - end - context "signed in non-wrangler" do - include_context 'signed in member' do - let!(:crop_wranglers) { create_list :crop_wrangling_member, 3 } + it "can see list of crops with extra detail of who created a crop" do + visit root_path + click_link 'Admin' + click_link 'Crop Wrangling' + within '#recently-added-crops' do + expect(page).to have_content crops.first.creator.login_name.to_s + end + end - it "can't see wrangling page without js", js: false do - visit root_path - expect(page).not_to have_link "Crop Wrangling" + describe "visiting a crop can see wrangler links" do + before do + visit crop_path(crops.first) + click_link 'Actions' end - it "can't see wrangling page with js" do - visit root_path - click_link member.login_name - expect(page).not_to have_link "Crop Wrangling" - end + it { expect(page).to have_content 'You are a CROP WRANGLER' } + it { expect(page).to have_link 'Edit' } + it { expect(page).to have_link 'Delete' } + end + + it "can create a new crop" do + visit root_path + click_link 'Admin' + click_link 'Crop Wrangling' + click_link 'Add Crop' + fill_in 'Name', with: "aubergine" + fill_in 'en_wikipedia_url', with: "http://en.wikipedia.org/wiki/Maize" + fill_in 'sci_name[1]', with: "planticus maximus" + click_on 'Save' + expect(page).to have_content 'crop was successfully created.' + expect(page).to have_content 'planticus maximus' + end + + it "View pending crops" do + visit crop_path(requested_crop) + expect(page).to have_content "This crop is currently pending approval." + expect(page).to have_content "Please approve this even though it's fake." + end + + it "View rejected crops" do + visit crop_path(rejected_crop) + expect(page).to have_content "This crop was rejected for the following reason: Totally fake" end end end + +context "signed in non-wrangler" do + include_context 'signed in member' + let!(:crop_wranglers) { create_list :crop_wrangling_member, 3 } + + it "can't see wrangling page without js", js: false do + visit root_path + expect(page).not_to have_link "Crop Wrangling" + end + + it "can't see wrangling page with js" do + visit root_path + click_link member.login_name + expect(page).not_to have_link "Crop Wrangling" + end +end diff --git a/spec/features/crops/crop_wrangling_button_spec.rb b/spec/features/crops/crop_wrangling_button_spec.rb index 2dfdcda6d..3545db9ff 100644 --- a/spec/features/crops/crop_wrangling_button_spec.rb +++ b/spec/features/crops/crop_wrangling_button_spec.rb @@ -7,16 +7,14 @@ describe "crop wrangling button" do end context "signed in, but not a crop wrangler" do - include_context 'signed in member' do - before { visit crops_path } - it { expect(page).to have_no_link "Wrangle Crops", href: wrangle_crops_path } - end + include_context 'signed in member' + before { visit crops_path } + it { expect(page).to have_no_link "Wrangle Crops", href: wrangle_crops_path } end context "signed in crop wrangler" do - include_context 'signed in crop wrangler' do - before { visit crops_path } - it { expect(page).to have_link "Wrangle Crops", href: wrangle_crops_path } - end + include_context 'signed in crop wrangler' + before { visit crops_path } + it { expect(page).to have_link "Wrangle Crops", href: wrangle_crops_path } end end diff --git a/spec/features/crops/delete_crop_spec.rb b/spec/features/crops/delete_crop_spec.rb index 00a8e7cec..41092c895 100644 --- a/spec/features/crops/delete_crop_spec.rb +++ b/spec/features/crops/delete_crop_spec.rb @@ -1,28 +1,35 @@ require 'rails_helper' describe "Delete crop spec" do - context "As a crop wrangler" do + shared_examples 'delete crop' do let!(:pending_crop) { FactoryBot.create :crop_request } let!(:approved_crop) { FactoryBot.create :crop } - - include_context 'signed in crop wrangler' do - it "deletes approved crop" do - visit crop_path(approved_crop) - click_link 'Actions' - accept_confirm do - click_link 'Delete' - end - expect(page).to have_content "crop was successfully destroyed" + it "deletes approved crop" do + visit crop_path(approved_crop) + click_link 'Actions' + accept_confirm do + click_link 'Delete' end + expect(page).to have_content "crop was successfully destroyed" + end - it "deletes pending crop" do - visit crop_path(pending_crop) - click_link 'Actions' - accept_confirm do - click_link 'Delete' - end - expect(page).to have_content "crop was successfully destroyed" + it "deletes pending crop" do + visit crop_path(pending_crop) + click_link 'Actions' + accept_confirm do + click_link 'Delete' end + expect(page).to have_content "crop was successfully destroyed" end end + + context "As a crop wrangler" do + include_context 'signed in crop wrangler' + include_examples 'delete crop' + end + + context 'admin' do + include_context 'signed in admin' + include_examples 'delete crop' + end end diff --git a/spec/features/crops/request_new_crop_spec.rb b/spec/features/crops/request_new_crop_spec.rb index d2f07a53d..4257e3a69 100644 --- a/spec/features/crops/request_new_crop_spec.rb +++ b/spec/features/crops/request_new_crop_spec.rb @@ -2,40 +2,38 @@ require 'rails_helper' describe "Requesting a new crop" do context "As a regular member" do - include_context 'signed in member' do - it "Submit request" do - visit new_crop_path - fill_in "Name", with: "Couch potato" - fill_in "request_notes", with: "Couch potatoes are real for real." - click_button "Save" - expect(page).to have_content 'crop was successfully created.' - expect(page).to have_content "This crop is currently pending approval." - end + include_context 'signed in member' + it "Submit request" do + visit new_crop_path + fill_in "Name", with: "Couch potato" + fill_in "request_notes", with: "Couch potatoes are real for real." + click_button "Save" + expect(page).to have_content 'crop was successfully created.' + expect(page).to have_content "This crop is currently pending approval." end end context "As a crop wrangler" do - include_context 'signed in crop wrangler' do - let!(:crop) { create :crop_request } - let!(:already_approved) { create :crop } + include_context 'signed in crop wrangler' + let!(:crop) { create :crop_request } + let!(:already_approved) { create :crop } - it "Approve a request" do - visit edit_crop_path(crop) - select "approved", from: "Approval status" - click_button "Save" - expect(page).to have_content "En wikipedia url is not a valid English Wikipedia URL" - fill_in "en_wikipedia_url", with: "http://en.wikipedia.org/wiki/Aung_San_Suu_Kyi" - click_button "Save" - expect(page).to have_content "crop was successfully updated." - end + it "Approve a request" do + visit edit_crop_path(crop) + select "approved", from: "Approval status" + click_button "Save" + expect(page).to have_content "En wikipedia url is not a valid English Wikipedia URL" + fill_in "en_wikipedia_url", with: "http://en.wikipedia.org/wiki/Aung_San_Suu_Kyi" + click_button "Save" + expect(page).to have_content "crop was successfully updated." + end - it "Rejecting a crop" do - visit edit_crop_path(crop) - select "rejected", from: "Approval status" - select "not edible", from: "Reason for rejection" - click_button "Save" - expect(page).to have_content "crop was successfully updated." - end + it "Rejecting a crop" do + visit edit_crop_path(crop) + select "rejected", from: "Approval status" + select "not edible", from: "Reason for rejection" + click_button "Save" + expect(page).to have_content "crop was successfully updated." end end end diff --git a/spec/features/crops/requested_crops_spec.rb b/spec/features/crops/requested_crops_spec.rb index 5692e71fc..e73292c1e 100644 --- a/spec/features/crops/requested_crops_spec.rb +++ b/spec/features/crops/requested_crops_spec.rb @@ -3,7 +3,8 @@ require 'rails_helper' describe "Requesting Crops" do let!(:requested_crop) { create :crop, requester: member, approval_status: 'pending', name: 'puha for dinner' } - include_context 'signed in member' do + context 'signed in' do + include_context 'signed in member' before { visit requested_crops_path } it "creating a crop with multiple scientific and alternate name", :js do diff --git a/spec/features/crops/scientific_name_spec.rb b/spec/features/crops/scientific_name_spec.rb index a5f206fdd..56616b81b 100644 --- a/spec/features/crops/scientific_name_spec.rb +++ b/spec/features/crops/scientific_name_spec.rb @@ -19,67 +19,66 @@ describe "Scientific names", js: true do context "User is a crop wrangler" do let!(:crop_wranglers) { create_list :crop_wrangling_member, 3 } - include_context 'signed in crop wrangler' do - it "Crop wranglers can edit scientific names" do - visit crop_path(crop) - # expect(page.status_code).to equal 200 - expect(page).to have_content "CROP WRANGLER" - expect(page).to have_content zea_mays.name - click_link zea_mays.name - expect(page).to have_link "Edit", href: edit_scientific_name_path(zea_mays) - within('.scientific_names') { click_on "Edit" } - # expect(page.status_code).to equal 200 - expect(page).to have_css "option[value='#{crop.id}'][selected=selected]" - fill_in 'Name', with: "Zea mirabila" - click_on "Save" - expect(page).to have_content "Zea mirabila" - expect(page).to have_content 'crop was successfully updated' - end + include_context 'signed in crop wrangler' + it "Crop wranglers can edit scientific names" do + visit crop_path(crop) + # expect(page.status_code).to equal 200 + expect(page).to have_content "CROP WRANGLER" + expect(page).to have_content zea_mays.name + click_link zea_mays.name + expect(page).to have_link "Edit", href: edit_scientific_name_path(zea_mays) + within('.scientific_names') { click_on "Edit" } + # expect(page.status_code).to equal 200 + expect(page).to have_css "option[value='#{crop.id}'][selected=selected]" + fill_in 'Name', with: "Zea mirabila" + click_on "Save" + expect(page).to have_content "Zea mirabila" + expect(page).to have_content 'crop was successfully updated' + end - it "Crop wranglers can delete scientific names" do - visit crop_path(zea_mays.crop) - click_link zea_mays.name - expect(page).to have_link "Delete", - href: scientific_name_path(zea_mays) - within('.scientific_names') do - accept_confirm do - click_link 'Delete' - end + it "Crop wranglers can delete scientific names" do + visit crop_path(zea_mays.crop) + click_link zea_mays.name + expect(page).to have_link "Delete", + href: scientific_name_path(zea_mays) + within('.scientific_names') do + accept_confirm do + click_link 'Delete' end - # expect(page.status_code).to equal 200 - expect(page).not_to have_content zea_mays.name - expect(page).to have_content 'Scientific name was successfully deleted.' end + # expect(page.status_code).to equal 200 + expect(page).not_to have_content zea_mays.name + expect(page).to have_content 'Scientific name was successfully deleted.' + end - it "Crop wranglers can add scientific names" do - visit crop_path(crop) - expect(page).to have_link "Add", - href: new_scientific_name_path(crop_id: crop.id) - within('.scientific_names') { click_on "Add" } - # expect(page.status_code).to equal 200 - expect(page).to have_css "option[value='#{crop.id}'][selected=selected]" - fill_in 'Name', with: "Zea mirabila" - click_on "Save" - # expect(page.status_code).to equal 200 - expect(page).to have_content "Zea mirabila" - expect(page).to have_content 'crop was successfully created.' - end + it "Crop wranglers can add scientific names" do + visit crop_path(crop) + expect(page).to have_link "Add", + href: new_scientific_name_path(crop_id: crop.id) + within('.scientific_names') { click_on "Add" } + # expect(page.status_code).to equal 200 + expect(page).to have_css "option[value='#{crop.id}'][selected=selected]" + fill_in 'Name', with: "Zea mirabila" + click_on "Save" + # expect(page.status_code).to equal 200 + expect(page).to have_content "Zea mirabila" + expect(page).to have_content 'crop was successfully created.' + end - it "The show-scientific-name page works" do - visit scientific_name_path(zea_mays) - # expect(page.status_code).to equal 200 - expect(page).to have_link zea_mays.crop.name, - href: crop_path(zea_mays.crop) - end + it "The show-scientific-name page works" do + visit scientific_name_path(zea_mays) + # expect(page.status_code).to equal 200 + expect(page).to have_link zea_mays.crop.name, + href: crop_path(zea_mays.crop) + end - context "When scientific name is pending" do - let(:pending_crop) { create :crop_request } - let(:pending_sci_name) { create :scientific_name, crop: pending_crop } + context "When scientific name is pending" do + let(:pending_crop) { create :crop_request } + let(:pending_sci_name) { create :scientific_name, crop: pending_crop } - it "Displays crop pending message" do - visit scientific_name_path(pending_sci_name) - expect(page).to have_content "This crop is currently pending approval" - end + it "Displays crop pending message" do + visit scientific_name_path(pending_sci_name) + expect(page).to have_content "This crop is currently pending approval" end end end diff --git a/spec/features/gardens/actions_spec.rb b/spec/features/gardens/actions_spec.rb index 98f37adcd..0c9336a74 100644 --- a/spec/features/gardens/actions_spec.rb +++ b/spec/features/gardens/actions_spec.rb @@ -5,72 +5,71 @@ describe "Gardens" do context 'logged in' do subject { page } - include_context 'signed in member' do - let(:garden) { member.gardens.first } - let(:other_member_garden) { FactoryBot.create :garden } + include_context 'signed in member' + let(:garden) { member.gardens.first } + let(:other_member_garden) { FactoryBot.create :garden } - describe '#index' do - shared_examples "has buttons bar at top" do - it "has buttons bar at top" do - within '.layout-actions' do - expect(subject).to have_link 'Add a garden' - expect(subject).to have_link 'My gardens' - expect(subject).to have_link "Everyone's gardens" - end - end - end - - context 'my gardens' do - before { visit gardens_path(member_slug: member.slug) } - - include_examples "has buttons bar at top" - - context 'with actions menu expanded' do - before { click_link 'Actions' } - it "has actions on garden" do - expect(subject).to have_link 'Plant something here' - expect(subject).to have_link 'Mark as inactive' - expect(subject).to have_link 'Edit' - expect(subject).to have_link 'Add photo' - expect(subject).to have_link 'Delete' - end - end - end - - context 'all gardens' do - before { visit gardens_path } - - include_examples "has buttons bar at top" - end - - context "other member's garden" do - before { visit gardens_path(member_slug: FactoryBot.create(:member).slug) } - - include_examples "has buttons bar at top" - describe 'does not show actions on other member garden' do - it { is_expected.not_to have_link 'Actions' } + describe '#index' do + shared_examples "has buttons bar at top" do + it "has buttons bar at top" do + within '.layout-actions' do + expect(subject).to have_link 'Add a garden' + expect(subject).to have_link 'My gardens' + expect(subject).to have_link "Everyone's gardens" end end end - describe '#show' do - describe 'my garden' do - before { visit garden_path(garden) } + context 'my gardens' do + before { visit gardens_path(member_slug: member.slug) } - context 'with actions menu expanded' do - before { click_link 'Actions' } - it { is_expected.to have_link 'Edit' } - it { is_expected.to have_link 'Delete' } - it { is_expected.to have_content "Plant something here" } - it { is_expected.to have_content "Add photo" } + include_examples "has buttons bar at top" + + context 'with actions menu expanded' do + before { click_link 'Actions' } + it "has actions on garden" do + expect(subject).to have_link 'Plant something here' + expect(subject).to have_link 'Mark as inactive' + expect(subject).to have_link 'Edit' + expect(subject).to have_link 'Add photo' + expect(subject).to have_link 'Delete' end end + end - describe "someone else's garden" do - before { visit garden_path(other_member_garden) } + context 'all gardens' do + before { visit gardens_path } + + include_examples "has buttons bar at top" + end + + context "other member's garden" do + before { visit gardens_path(member_slug: FactoryBot.create(:member).slug) } + + include_examples "has buttons bar at top" + describe 'does not show actions on other member garden' do it { is_expected.not_to have_link 'Actions' } end end end + + describe '#show' do + describe 'my garden' do + before { visit garden_path(garden) } + + context 'with actions menu expanded' do + before { click_link 'Actions' } + it { is_expected.to have_link 'Edit' } + it { is_expected.to have_link 'Delete' } + it { is_expected.to have_content "Plant something here" } + it { is_expected.to have_content "Add photo" } + end + end + + describe "someone else's garden" do + before { visit garden_path(other_member_garden) } + it { is_expected.not_to have_link 'Actions' } + end + end end end diff --git a/spec/features/gardens/adding_gardens_spec.rb b/spec/features/gardens/adding_gardens_spec.rb index 47f521fd1..7320a1244 100644 --- a/spec/features/gardens/adding_gardens_spec.rb +++ b/spec/features/gardens/adding_gardens_spec.rb @@ -2,7 +2,8 @@ require 'rails_helper' require 'custom_matchers' describe "Gardens", :js do - include_context 'signed in member' do + context 'signed in' do + include_context 'signed in member' before { visit new_garden_path } it "has the required fields help text" do diff --git a/spec/features/gardens/gardens_spec.rb b/spec/features/gardens/gardens_spec.rb index fdb517b08..132997584 100644 --- a/spec/features/gardens/gardens_spec.rb +++ b/spec/features/gardens/gardens_spec.rb @@ -1,7 +1,8 @@ require 'rails_helper' describe "Planting a crop", js: true do - include_context 'signed in member' do + context 'signed in' do + include_context 'signed in member' # name is aaa to ensure it is ordered first let!(:garden) { create :garden, name: 'aaa', owner: member } let!(:planting) { create :planting, garden: garden, owner: garden.owner, planted_at: Date.parse("2013-3-10") } diff --git a/spec/features/gardens/index_spec.rb b/spec/features/gardens/index_spec.rb index 39b422d25..526bba7c9 100644 --- a/spec/features/gardens/index_spec.rb +++ b/spec/features/gardens/index_spec.rb @@ -3,68 +3,67 @@ require 'custom_matchers' describe "Gardens#index", :js do context "Logged in as member" do - include_context 'signed in member' do - let(:member) { FactoryBot.create :member, login_name: 'shadow' } + include_context 'signed in member' + let(:member) { FactoryBot.create :member, login_name: 'shadow' } - context "with 10 gardens" do - before do - FactoryBot.create_list :garden, 10, owner: member - visit member_gardens_path(member_slug: member.slug) - end - - it "displays each of the gardens" do - member.gardens.each do |garden| - expect(page).to have_text garden.name - end - end - it "links to each garden" do - member.gardens.each do |garden| - expect(page).to have_link(garden.name, href: garden_path(garden)) - end - end + context "with 10 gardens" do + before do + FactoryBot.create_list :garden, 10, owner: member + visit member_gardens_path(member_slug: member.slug) end - context "with inactive gardens" do - let!(:active_garden) { FactoryBot.create :garden, name: "My active garden", owner: member } - let!(:inactive_garden) { FactoryBot.create :inactive_garden, name: "retired garden", owner: member } - - before { visit member_gardens_path(member_slug: member.slug) } - - it "show active garden" do - expect(page).to have_text active_garden.name - end - it "does not show inactive garden" do - expect(page).not_to have_text inactive_garden.name - end - it "links to active garden" do - expect(page).to have_link(active_garden.name, href: garden_path(active_garden)) - end - it "does not link to inactive gardens" do - expect(page).not_to have_link(inactive_garden.name, href: garden_path(inactive_garden)) + it "displays each of the gardens" do + member.gardens.each do |garden| + expect(page).to have_text garden.name end end + it "links to each garden" do + member.gardens.each do |garden| + expect(page).to have_link(garden.name, href: garden_path(garden)) + end + end + end - context 'with plantings' do - let(:maize) { FactoryBot.create(:maize) } - let(:tomato) { FactoryBot.create(:tomato) } + context "with inactive gardens" do + let!(:active_garden) { FactoryBot.create :garden, name: "My active garden", owner: member } + let!(:inactive_garden) { FactoryBot.create :inactive_garden, name: "retired garden", owner: member } - let!(:planting) do - FactoryBot.create :planting, owner: member, crop: maize, garden: member.gardens.first - end - let!(:finished_planting) do - FactoryBot.create :finished_planting, owner: member, crop: tomato, garden: member.gardens.first - end + before { visit member_gardens_path(member_slug: member.slug) } - before do - visit member_gardens_path(member_slug: member.slug) - end + it "show active garden" do + expect(page).to have_text active_garden.name + end + it "does not show inactive garden" do + expect(page).not_to have_text inactive_garden.name + end + it "links to active garden" do + expect(page).to have_link(active_garden.name, href: garden_path(active_garden)) + end + it "does not link to inactive gardens" do + expect(page).not_to have_link(inactive_garden.name, href: garden_path(inactive_garden)) + end + end - it "shows planting in garden" do - expect(page).to have_link(planting.crop.name, href: planting_path(planting)) - end - it "does not show finished planting" do - expect(page).not_to have_text(finished_planting.crop.name) - end + context 'with plantings' do + let(:maize) { FactoryBot.create(:maize) } + let(:tomato) { FactoryBot.create(:tomato) } + + let!(:planting) do + FactoryBot.create :planting, owner: member, crop: maize, garden: member.gardens.first + end + let!(:finished_planting) do + FactoryBot.create :finished_planting, owner: member, crop: tomato, garden: member.gardens.first + end + + before do + visit member_gardens_path(member_slug: member.slug) + end + + it "shows planting in garden" do + expect(page).to have_link(planting.crop.name, href: planting_path(planting)) + end + it "does not show finished planting" do + expect(page).not_to have_text(finished_planting.crop.name) end end end diff --git a/spec/features/harvests/browse_harvests_spec.rb b/spec/features/harvests/browse_harvests_spec.rb index bc6b29078..6ead7e231 100644 --- a/spec/features/harvests/browse_harvests_spec.rb +++ b/spec/features/harvests/browse_harvests_spec.rb @@ -5,7 +5,8 @@ describe "browse harvests" do let!(:harvest) { create :harvest, owner: member } - include_context 'signed in member' do + context 'signed in' do + include_context 'signed in member' describe 'blank optional fields' do let!(:harvest) { create :harvest, :no_description } diff --git a/spec/features/harvests/harvesting_a_crop_spec.rb b/spec/features/harvests/harvesting_a_crop_spec.rb index 7ad9a285a..e7aeea3d6 100644 --- a/spec/features/harvests/harvesting_a_crop_spec.rb +++ b/spec/features/harvests/harvesting_a_crop_spec.rb @@ -2,7 +2,8 @@ require 'rails_helper' require 'custom_matchers' describe "Harvesting a crop", :js, :elasticsearch do - include_context 'signed in member' do + context 'signed in' do + include_context 'signed in member' let!(:maize) { create :maize } let!(:plant_part) { create :plant_part } diff --git a/spec/features/home/home_spec.rb b/spec/features/home/home_spec.rb index 42d354f14..c3ad7d8c9 100644 --- a/spec/features/home/home_spec.rb +++ b/spec/features/home/home_spec.rb @@ -79,17 +79,16 @@ describe "home page" do end context "when signed in" do - include_context 'signed in member' do - include_examples 'show crops' - include_examples 'show plantings' - include_examples 'show harvests' - include_examples 'shows seeds' + include_context 'signed in member' + include_examples 'show crops' + include_examples 'show plantings' + include_examples 'show harvests' + include_examples 'shows seeds' - describe 'should say welcome' do - before { visit root_path } + describe 'should say welcome' do + before { visit root_path } - it { expect(page).to have_content "Welcome to #{ENV['GROWSTUFF_SITE_NAME']}, #{member.login_name}" } - end + it { expect(page).to have_content "Welcome to #{ENV['GROWSTUFF_SITE_NAME']}, #{member.login_name}" } end end end diff --git a/spec/features/likeable_spec.rb b/spec/features/likeable_spec.rb index b2527402a..95503efaf 100644 --- a/spec/features/likeable_spec.rb +++ b/spec/features/likeable_spec.rb @@ -1,96 +1,95 @@ require 'rails_helper' describe 'Likeable', js: true do - let(:another_member) { FactoryBot.create(:london_member) } + let(:another_member) { FactoryBot.create(:london_member) } let!(:post) { FactoryBot.create(:post, author: member) } let!(:photo) { FactoryBot.create(:photo, owner: member) } - include_context 'signed in member' do - describe 'photos' do - let(:like_count_class) { "#photo-#{photo.id} .like-count" } + include_context 'signed in member' + describe 'photos' do + let(:like_count_class) { "#photo-#{photo.id} .like-count" } - shared_examples 'photo can be liked' do - it 'can be liked' do - visit path - expect(page).to have_css(like_count_class, text: "0") - click_link '0', class: 'like-btn' - expect(page).to have_css(like_count_class, text: "1") - - # Reload page - visit path - expect(page).to have_css(like_count_class, text: "1") - expect(page).to have_link '1' - - click_link '1', class: 'like-btn' - expect(page).to have_css(like_count_class, text: "0") - end - - it 'displays correct number of likes' do - visit path - expect(page).to have_css(like_count_class, text: "0") - expect(page).to have_link '0' - click_link '0', class: 'like-btn' - expect(page).to have_css(like_count_class, text: "1") - - logout(member) - login_as(another_member) - visit path - - expect(page).to have_css(like_count_class, text: "1") - click_link '1', class: 'like-btn' - expect(page).to have_css(like_count_class, text: "2") - logout(another_member) - end - end - describe 'photos#index' do - let(:path) { photos_path } - include_examples 'photo can be liked' - end - describe 'photos#show' do - let(:path) { photo_path(photo) } - include_examples 'photo can be liked' - end - describe 'crops#show' do - let(:crop) { FactoryBot.create :crop } - let(:planting) { FactoryBot.create :planting, owner: member, crop: crop } - let(:path) { crop_path(crop) } - before { planting.photos << photo } - include_examples 'photo can be liked' - end - end - - describe 'posts' do - let(:like_count_class) { "#post-#{post.id} .like-count" } - before { visit post_path(post) } + shared_examples 'photo can be liked' do it 'can be liked' do + visit path expect(page).to have_css(like_count_class, text: "0") - expect(page).to have_link 'Like' - click_link 'Like', class: 'like-btn' + click_link '0', class: 'like-btn' expect(page).to have_css(like_count_class, text: "1") # Reload page - visit post_path(post) + visit path expect(page).to have_css(like_count_class, text: "1") - expect(page).to have_link 'Unlike' + expect(page).to have_link '1' - click_link 'Unlike', class: 'like-btn' + click_link '1', class: 'like-btn' expect(page).to have_css(like_count_class, text: "0") end it 'displays correct number of likes' do - expect(page).to have_link 'Like' - click_link 'Like', class: 'like-btn' + visit path + expect(page).to have_css(like_count_class, text: "0") + expect(page).to have_link '0' + click_link '0', class: 'like-btn' expect(page).to have_css(like_count_class, text: "1") logout(member) login_as(another_member) - visit post_path(post) + visit path - expect(page).to have_link 'Like' - click_link 'Like', class: 'like-btn' + expect(page).to have_css(like_count_class, text: "1") + click_link '1', class: 'like-btn' expect(page).to have_css(like_count_class, text: "2") logout(another_member) end end + describe 'photos#index' do + let(:path) { photos_path } + include_examples 'photo can be liked' + end + describe 'photos#show' do + let(:path) { photo_path(photo) } + include_examples 'photo can be liked' + end + describe 'crops#show' do + let(:crop) { FactoryBot.create :crop } + let(:planting) { FactoryBot.create :planting, owner: member, crop: crop } + let(:path) { crop_path(crop) } + before { planting.photos << photo } + include_examples 'photo can be liked' + end + end + + describe 'posts' do + let(:like_count_class) { "#post-#{post.id} .like-count" } + before { visit post_path(post) } + it 'can be liked' do + expect(page).to have_css(like_count_class, text: "0") + expect(page).to have_link 'Like' + click_link 'Like', class: 'like-btn' + expect(page).to have_css(like_count_class, text: "1") + + # Reload page + visit post_path(post) + expect(page).to have_css(like_count_class, text: "1") + expect(page).to have_link 'Unlike' + + click_link 'Unlike', class: 'like-btn' + expect(page).to have_css(like_count_class, text: "0") + end + + it 'displays correct number of likes' do + expect(page).to have_link 'Like' + click_link 'Like', class: 'like-btn' + expect(page).to have_css(like_count_class, text: "1") + + logout(member) + login_as(another_member) + visit post_path(post) + + expect(page).to have_link 'Like' + click_link 'Like', class: 'like-btn' + expect(page).to have_css(like_count_class, text: "2") + logout(another_member) + end end end diff --git a/spec/features/members/ban_spec.rb b/spec/features/members/ban_spec.rb index 256083a3e..f6f99e698 100644 --- a/spec/features/members/ban_spec.rb +++ b/spec/features/members/ban_spec.rb @@ -5,16 +5,15 @@ describe "members list" do let!(:admin) { FactoryBot.create :admin_member } context 'logged in as admin' do - include_context 'signed in admin' do - before { visit member_path(spammer) } - it { expect(page).to have_link "Ban member" } - describe 'bans the user' do - before do - accept_confirm { click_link 'Ban member' } - end - it { expect(page).to have_link admin.login_name } - it { expect(page).not_to have_link spammer.login_name } + include_context 'signed in admin' + before { visit member_path(spammer) } + it { expect(page).to have_link "Ban member" } + describe 'bans the user' do + before do + accept_confirm { click_link 'Ban member' } end + it { expect(page).to have_link admin.login_name } + it { expect(page).not_to have_link spammer.login_name } end end end diff --git a/spec/features/members/following_spec.rb b/spec/features/members/following_spec.rb index fea8b5a7f..42a20df34 100644 --- a/spec/features/members/following_spec.rb +++ b/spec/features/members/following_spec.rb @@ -12,62 +12,61 @@ describe "follows", :js do end context "when signed in" do - include_context 'signed in member' do - let(:other_member) { create :member } + include_context 'signed in member' + let(:other_member) { create :member } - it "your profile doesn't have a follow button" do - visit member_path(member) - expect(page).not_to have_link "Follow" - expect(page).not_to have_link "Unfollow" + it "your profile doesn't have a follow button" do + visit member_path(member) + expect(page).not_to have_link "Follow" + expect(page).not_to have_link "Unfollow" + end + + context "following another member" do + before { visit member_path(other_member) } + + it "has a follow button" do + expect(page).to have_link "Follow", href: follows_path(followed: other_member.slug) end - context "following another member" do - before { visit member_path(other_member) } + it "has correct message and unfollow button" do + click_link 'Follow' + expect(page).to have_content "Followed #{other_member.login_name}" + expect(page).to have_link "Unfollow", href: follow_path(member.get_follow(other_member)) + end - it "has a follow button" do - expect(page).to have_link "Follow", href: follows_path(followed: other_member.slug) - end + it "has a followed member listed in the following page" do + click_link 'Follow' + visit member_follows_path(member) + expect(page).to have_content other_member.login_name + end - it "has correct message and unfollow button" do - click_link 'Follow' - expect(page).to have_content "Followed #{other_member.login_name}" - expect(page).to have_link "Unfollow", href: follow_path(member.get_follow(other_member)) - end + it "has correct message and follow button after unfollow" do + click_link 'Follow' + click_link 'Unfollow' + expect(page).to have_content "Unfollowed #{other_member.login_name}" + visit member_path(other_member) # unfollowing redirects to root + expect(page).to have_link "Follow", href: follows_path(followed: other_member.slug) + end - it "has a followed member listed in the following page" do - click_link 'Follow' - visit member_follows_path(member) - expect(page).to have_content other_member.login_name - end + it "has member in following list" do + click_link 'Follow' + visit member_follows_path(member) + expect(page).to have_content other_member.login_name + end - it "has correct message and follow button after unfollow" do - click_link 'Follow' - click_link 'Unfollow' - expect(page).to have_content "Unfollowed #{other_member.login_name}" - visit member_path(other_member) # unfollowing redirects to root - expect(page).to have_link "Follow", href: follows_path(followed: other_member.slug) - end + it "appears in in followed member's followers list" do + click_link 'Follow' + visit member_followers_path(other_member) + expect(page).to have_content member.login_name + end - it "has member in following list" do - click_link 'Follow' - visit member_follows_path(member) - expect(page).to have_content other_member.login_name - end - - it "appears in in followed member's followers list" do - click_link 'Follow' - visit member_followers_path(other_member) - expect(page).to have_content member.login_name - end - - it "removes members from following and followers lists after unfollow" do - click_link 'Follow' - click_link 'Unfollow' - visit member_follows_path(member) - expect(page).not_to have_content other_member.login_name - visit member_followers_path(other_member) - expect(page).to have_content member.login_name - end + it "removes members from following and followers lists after unfollow" do + click_link 'Follow' + click_link 'Unfollow' + visit member_follows_path(member) + expect(page).not_to have_content other_member.login_name + visit member_followers_path(other_member) + expect(page).to have_content member.login_name end end end diff --git a/spec/features/members/profile_spec.rb b/spec/features/members/profile_spec.rb index f00da8b20..4b51b5868 100644 --- a/spec/features/members/profile_spec.rb +++ b/spec/features/members/profile_spec.rb @@ -162,26 +162,25 @@ describe "member profile", js: true do end context "signed in member" do - include_context 'signed in member' do - include_examples 'member details' - include_examples 'member activity' + include_context 'signed in member' + include_examples 'member details' + include_examples 'member activity' - context "your own profile page" do - before { visit member_path(member) } + context "your own profile page" do + before { visit member_path(member) } - it "has a button to edit profile" do - expect(page).to have_link "Edit profile", href: edit_member_registration_path - end + it "has a button to edit profile" do + expect(page).to have_link "Edit profile", href: edit_member_registration_path end + end - context "someone else's profile page" do - before { visit member_path(other_member) } + context "someone else's profile page" do + before { visit member_path(other_member) } - it "has a private message button" do - expect(page).to have_link "Send message", href: new_message_path(recipient_id: other_member.id) - end - it { expect(page).not_to have_link "Edit profile", href: edit_member_registration_path } + it "has a private message button" do + expect(page).to have_link "Send message", href: new_message_path(recipient_id: other_member.id) end + it { expect(page).not_to have_link "Edit profile", href: edit_member_registration_path } end end end diff --git a/spec/features/notifications_spec.rb b/spec/features/notifications_spec.rb new file mode 100644 index 000000000..0221c96f8 --- /dev/null +++ b/spec/features/notifications_spec.rb @@ -0,0 +1,64 @@ +require 'rails_helper' + +describe "Notifications", :js do + let(:sender) { create :member } + let(:recipient) { create :member, login_name: 'beyonce' } + + context 'signed in' do + include_context 'signed in member' + let(:member) { recipient } + + context "On existing notification" do + let!(:notification) do + create :notification, + sender: sender, + recipient: recipient, + body: "Notification body", + post_id: nil + end + before do + visit root_path + click_link 'Your Stuff' + Percy.snapshot(page, name: "notification menu") + visit notification_path(notification) + Percy.snapshot(page, name: "notifications#show") + end + + it "Replying to the notification" do + click_link "Reply" + expect(page).to have_content "Notification body" + Percy.snapshot(page, name: 'Replying to notification') + + fill_in 'notification_body', with: "Response body" + Percy.snapshot(page, name: "notifications#new") + click_button "Send" + + expect(page).to have_content "Message was successfully sent" + end + end + + describe 'pagination' do + before do + FactoryBot.create_list :notification, 34, recipient: recipient + visit notifications_path + end + + it do + Percy.snapshot(page, name: "notifications#index") + end + + it 'has page navigation' do + expect(page).to have_selector 'a[rel="next"]' + end + + it 'paginates at 30 notifications per page' do + expect(page).to have_selector '.message', count: 30 + end + + it 'navigates pages' do + first('a[rel="next"]').click + expect(page).to have_selector '.message', count: 4 + end + end + end +end diff --git a/spec/features/percy/percy_spec.rb b/spec/features/percy/percy_spec.rb index 01b32539a..70ce97092 100644 --- a/spec/features/percy/percy_spec.rb +++ b/spec/features/percy/percy_spec.rb @@ -235,154 +235,151 @@ rest of the garden. context 'when signed in' do let(:prefix) { 'signed-in' } - include_context 'signed in member' do - include_examples 'visit pages' + include_context 'signed in member' + include_examples 'visit pages' - it 'load my plantings#show' do - planting = FactoryBot.create :planting, crop: tomato, owner: member, garden: member.gardens.first - visit planting_path(planting) - Percy.snapshot(page, name: "#{prefix}/self/plantings#show") + it 'load my plantings#show' do + planting = FactoryBot.create :planting, crop: tomato, owner: member, garden: member.gardens.first + visit planting_path(planting) + Percy.snapshot(page, name: "#{prefix}/self/plantings#show") + end + + it 'load my members#show' do + visit member_path(member) + Percy.snapshot(page, name: "#{prefix}/self/members#show") + end + + it 'load my gardens#show' do + garden = FactoryBot.create :garden, name: 'paradise', owner: member + visit garden_path(garden) + Percy.snapshot(page, name: "#{prefix}/self/gardens#show") + end + + describe '#new' do + it 'crops#new' do + visit new_crop_path + Percy.snapshot(page, name: "#{prefix}/crops#new") end - it 'load my members#show' do - visit member_path(member) - Percy.snapshot(page, name: "#{prefix}/self/members#show") + it 'gardens#new' do + visit new_garden_path + Percy.snapshot(page, name: "#{prefix}/gardens#new") end - it 'load my gardens#show' do - garden = FactoryBot.create :garden, name: 'paradise', owner: member - visit garden_path(garden) - Percy.snapshot(page, name: "#{prefix}/self/gardens#show") + it 'harvests#new' do + visit new_harvest_path + Percy.snapshot(page, name: "#{prefix}/harvests#new") + fill_in(id: 'crop', with: 'tom') + Percy.snapshot(page, name: "#{prefix}/harvests#new-autosuggest") end - describe '#new' do - it 'crops#new' do - visit new_crop_path - Percy.snapshot(page, name: "#{prefix}/crops#new") - end - - it 'gardens#new' do - visit new_garden_path - Percy.snapshot(page, name: "#{prefix}/gardens#new") - end - - it 'harvests#new' do - visit new_harvest_path - Percy.snapshot(page, name: "#{prefix}/harvests#new") - fill_in(id: 'crop', with: 'tom') - Percy.snapshot(page, name: "#{prefix}/harvests#new-autosuggest") - end - - it 'plantings#new' do - visit new_planting_path - Percy.snapshot(page, name: "#{prefix}/plantings#new") - fill_in(id: 'crop', with: 'tom') - Percy.snapshot(page, name: "#{prefix}/plantings#new-autosuggest") - end - - it 'seeds#new' do - visit new_seed_path - Percy.snapshot(page, name: "#{prefix}/seeds#new") - fill_in(id: 'crop', with: 'tom') - Percy.snapshot(page, name: "#{prefix}/seeds#new-autosuggest") - end - - it 'posts#new' do - visit new_post_path - Percy.snapshot(page, name: "#{prefix}/posts#new") - end + it 'plantings#new' do + visit new_planting_path + Percy.snapshot(page, name: "#{prefix}/plantings#new") + fill_in(id: 'crop', with: 'tom') + Percy.snapshot(page, name: "#{prefix}/plantings#new-autosuggest") end - describe '#edit' do - it 'loads gardens#edit' do - garden = FactoryBot.create :garden, owner: member - visit edit_garden_path(garden) - Percy.snapshot(page, name: "#{prefix}/gardens#edit") - end - - it 'loads harvests#edit' do - harvest = FactoryBot.create :harvest, owner: member - visit edit_harvest_path(harvest) - Percy.snapshot(page, name: "#{prefix}/harvests#edit") - end - - it 'loads planting#edit' do - planting = FactoryBot.create :planting, owner: member - visit edit_planting_path(planting) - Percy.snapshot(page, name: "#{prefix}/plantings#edit") - end - - it 'loads posts#edit' do - visit edit_post_path(post) - Percy.snapshot(page, name: "#{prefix}/posts#edit") - end - - it 'comments#new' do - visit new_comment_path(post_id: post.id) - Percy.snapshot(page, name: "comments#new") - end + it 'seeds#new' do + visit new_seed_path + Percy.snapshot(page, name: "#{prefix}/seeds#new") + fill_in(id: 'crop', with: 'tom') + Percy.snapshot(page, name: "#{prefix}/seeds#new-autosuggest") end - describe 'expand menus' do - it 'expands crop menu' do - member.update! login_name: 'percy' - visit root_path - click_on 'Crops' - Percy.snapshot(page, name: "#{prefix}/crops-menu") - click_on 'Community' - Percy.snapshot(page, name: "#{prefix}/community-menu") - click_on 'percy', class: 'nav-link' - Percy.snapshot(page, name: "#{prefix}/member-menu") - end + it 'posts#new' do + visit new_post_path + Percy.snapshot(page, name: "#{prefix}/posts#new") + end + end + + describe '#edit' do + it 'loads gardens#edit' do + garden = FactoryBot.create :garden, owner: member + visit edit_garden_path(garden) + Percy.snapshot(page, name: "#{prefix}/gardens#edit") + end + + it 'loads harvests#edit' do + harvest = FactoryBot.create :harvest, owner: member + visit edit_harvest_path(harvest) + Percy.snapshot(page, name: "#{prefix}/harvests#edit") + end + + it 'loads planting#edit' do + planting = FactoryBot.create :planting, owner: member + visit edit_planting_path(planting) + Percy.snapshot(page, name: "#{prefix}/plantings#edit") + end + + it 'loads posts#edit' do + visit edit_post_path(post) + Percy.snapshot(page, name: "#{prefix}/posts#edit") + end + + it 'comments#new' do + visit new_comment_path(post_id: post.id) + Percy.snapshot(page, name: "comments#new") + end + end + + describe 'expand menus' do + it 'expands crop menu' do + member.update! login_name: 'percy' + visit root_path + click_on 'Crops' + Percy.snapshot(page, name: "#{prefix}/crops-menu") + click_on 'Community' + Percy.snapshot(page, name: "#{prefix}/community-menu") + click_on 'percy', class: 'nav-link' + Percy.snapshot(page, name: "#{prefix}/member-menu") end end end context 'wrangling crops' do - include_context 'signed in crop wrangler' do - let!(:candy) { FactoryBot.create :crop_request, name: 'candy' } + include_context 'signed in crop wrangler' + let!(:candy) { FactoryBot.create :crop_request, name: 'candy' } - it 'crop wrangling page' do - visit wrangle_crops_path - Percy.snapshot(page, name: 'crops wrangle') - click_link 'Pending approval' - Percy.snapshot(page, name: 'crops pending approval') - click_link 'candy' - Percy.snapshot(page, name: 'editing pending crop') - end + it 'crop wrangling page' do + visit wrangle_crops_path + Percy.snapshot(page, name: 'crops wrangle') + click_link 'Pending approval' + Percy.snapshot(page, name: 'crops pending approval') + click_link 'candy' + Percy.snapshot(page, name: 'editing pending crop') end end context 'admin' do - include_context 'signed in admin' do - before { visit admin_path } - it 'admin page' do - Percy.snapshot(page, name: 'Admin') - end - it 'Roles' do - click_link 'Roles' - Percy.snapshot(page, name: 'Admin Roles') - end - it 'CMS' do - click_link 'CMS' - Percy.snapshot(page, name: 'CMS') - end - it 'Garden Types' do - click_link 'Garden Types' - Percy.snapshot(page, name: 'Admin Garden type') - end - it 'Alternate names' do - click_link 'Alternate names' - Percy.snapshot(page, name: 'Admin Alternate names') - end - it 'Scientific names' do - click_link 'Scientific names' - Percy.snapshot(page, name: 'Admin Scientific names') - end - it 'Members' do - click_link 'Members' - Percy.snapshot(page, name: 'Admin Members') - end + include_context 'signed in admin' + before { visit admin_path } + it 'admin page' do + Percy.snapshot(page, name: 'Admin') + end + it 'Roles' do + click_link 'Roles' + Percy.snapshot(page, name: 'Admin Roles') + end + it 'CMS' do + click_link 'CMS' + Percy.snapshot(page, name: 'CMS') + end + it 'Garden Types' do + click_link 'Garden Types' + Percy.snapshot(page, name: 'Admin Garden type') + end + it 'Alternate names' do + click_link 'Alternate names' + Percy.snapshot(page, name: 'Admin Alternate names') + end + it 'Scientific names' do + click_link 'Scientific names' + Percy.snapshot(page, name: 'Admin Scientific names') + end + it 'Members' do + click_link 'Members' + Percy.snapshot(page, name: 'Admin Members') end end end diff --git a/spec/features/photos/new_photo_spec.rb b/spec/features/photos/new_photo_spec.rb index 93e3a155c..d52a1ef43 100644 --- a/spec/features/photos/new_photo_spec.rb +++ b/spec/features/photos/new_photo_spec.rb @@ -2,56 +2,55 @@ require 'rails_helper' describe "new photo page" do context "signed in member" do - include_context 'signed in member' do - context "viewing a planting" do - let(:planting) { FactoryBot.create :planting, owner: member } + include_context 'signed in member' + context "viewing a planting" do + let(:planting) { FactoryBot.create :planting, owner: member } - it "add photo" do - visit planting_path(planting) - click_link 'Actions' - within '.planting-actions' do - click_link('Add photo') - end - expect(page).to have_text planting.crop.name - Percy.snapshot(page, name: 'Add photo to planting') + it "add photo" do + visit planting_path(planting) + click_link 'Actions' + within '.planting-actions' do + click_link('Add photo') end + expect(page).to have_text planting.crop.name + Percy.snapshot(page, name: 'Add photo to planting') end + end - context "viewing a harvest" do - let(:harvest) { FactoryBot.create :harvest, owner: member } + context "viewing a harvest" do + let(:harvest) { FactoryBot.create :harvest, owner: member } - it "add photo" do - visit harvest_path(harvest) - click_link 'Actions' - within '.harvest-actions' do - click_link "Add photo" - end - expect(page).to have_text harvest.crop.name + it "add photo" do + visit harvest_path(harvest) + click_link 'Actions' + within '.harvest-actions' do + click_link "Add photo" end + expect(page).to have_text harvest.crop.name end + end - context "viewing a garden" do - let(:garden) { FactoryBot.create :garden, owner: member } + context "viewing a garden" do + let(:garden) { FactoryBot.create :garden, owner: member } - it "add photo" do - visit garden_path(garden) - click_link 'Actions' - within '.garden-actions' do - click_link "Add photo" - end - expect(page).to have_text garden.name + it "add photo" do + visit garden_path(garden) + click_link 'Actions' + within '.garden-actions' do + click_link "Add photo" end + expect(page).to have_text garden.name end + end - describe "viewing a seed" do - let(:seed) { FactoryBot.create :seed, owner: member } + describe "viewing a seed" do + let(:seed) { FactoryBot.create :seed, owner: member } - it "add photo" do - visit seed_path(seed) - click_link 'Actions' - first('.seed-actions').click_link('Add photo') - expect(page).to have_text seed.to_s - end + it "add photo" do + visit seed_path(seed) + click_link 'Actions' + first('.seed-actions').click_link('Add photo') + expect(page).to have_text seed.to_s end end end diff --git a/spec/features/photos/show_photo_spec.rb b/spec/features/photos/show_photo_spec.rb index 779270b0e..f7b101c48 100644 --- a/spec/features/photos/show_photo_spec.rb +++ b/spec/features/photos/show_photo_spec.rb @@ -2,68 +2,67 @@ require 'rails_helper' describe "show photo page" do context "signed in member" do - include_context 'signed in member' do - context "linked to planting" do - let(:planting) { create :planting } - let(:photo) { create :photo, owner: planting.owner } + include_context 'signed in member' + context "linked to planting" do + let(:planting) { create :planting } + let(:photo) { create :photo, owner: planting.owner } - context "shows linkback to planting" do - before do - planting.photos << photo - visit photo_path(photo) - end - - it { - expect(page).to have_link "#{planting.crop.name} planting in #{planting.garden.name} by #{planting.owner}", - href: planting_path(planting) - } - it { expect(page).to have_link planting.crop.name } + context "shows linkback to planting" do + before do + planting.photos << photo + visit photo_path(photo) end + + it { + expect(page).to have_link "#{planting.crop.name} planting in #{planting.garden.name} by #{planting.owner}", + href: planting_path(planting) + } + it { expect(page).to have_link planting.crop.name } end + end - context "linked to harvest" do - let(:photo) { create :photo, owner: harvest.owner } - let(:harvest) { create :harvest } + context "linked to harvest" do + let(:photo) { create :photo, owner: harvest.owner } + let(:harvest) { create :harvest } - context "shows linkback to harvest" do - before do - harvest.photos << photo - visit photo_path(photo) - end - - it { expect(page).to have_link "#{harvest.crop.name} harvest by #{harvest.owner}", href: harvest_path(harvest) } - it { expect(page).to have_link harvest.crop.name } + context "shows linkback to harvest" do + before do + harvest.photos << photo + visit photo_path(photo) end + + it { expect(page).to have_link "#{harvest.crop.name} harvest by #{harvest.owner}", href: harvest_path(harvest) } + it { expect(page).to have_link harvest.crop.name } end + end - context "linked to garden" do - let(:photo) { create :photo, owner: garden.owner } - let(:garden) { create :garden } + context "linked to garden" do + let(:photo) { create :photo, owner: garden.owner } + let(:garden) { create :garden } - context "shows linkback to garden" do - before do - garden.photos << photo - visit photo_path(photo) - Percy.snapshot(page, name: 'Show photo of a garden') - end - - it { expect(page).to have_link "garden named \"#{garden.name}\" by #{garden.owner}", href: garden_path(garden) } + context "shows linkback to garden" do + before do + garden.photos << photo + visit photo_path(photo) + Percy.snapshot(page, name: 'Show photo of a garden') end + + it { expect(page).to have_link "garden named \"#{garden.name}\" by #{garden.owner}", href: garden_path(garden) } end + end - context "linked to seed" do - let(:photo) { create :photo, owner: seed.owner } - let(:seed) { create :seed } + context "linked to seed" do + let(:photo) { create :photo, owner: seed.owner } + let(:seed) { create :seed } - context "shows linkback to seed" do - before do - seed.photos << photo - visit photo_path(photo) - end - - it { expect(page).to have_link "#{seed.crop.name} seeds belonging to #{seed.owner}", href: seed_path(seed) } - it { expect(page).to have_link seed.crop.name } + context "shows linkback to seed" do + before do + seed.photos << photo + visit photo_path(photo) end + + it { expect(page).to have_link "#{seed.crop.name} seeds belonging to #{seed.owner}", href: seed_path(seed) } + it { expect(page).to have_link seed.crop.name } end end end diff --git a/spec/features/places/searching_a_place_spec.rb b/spec/features/places/searching_a_place_spec.rb index 2231cf4cd..5b6985322 100644 --- a/spec/features/places/searching_a_place_spec.rb +++ b/spec/features/places/searching_a_place_spec.rb @@ -26,34 +26,33 @@ describe "User searches" do end describe "Nearby plantings, seed, and members" do - include_context 'signed in member' do - let(:member) { located_member } - before do - visit places_path - search_with "Philippines" - end + include_context 'signed in member' + let(:member) { located_member } + before do + visit places_path + search_with "Philippines" + end - it "shows that there are nearby seeds, plantings, and members" do - expect(page).to have_content "Nearby members" - expect(page).to have_content "Seeds available for trade near Philippines" - expect(page).to have_content "Recent plantings near Philippines" - Percy.snapshot(page, name: 'places map') - end + it "shows that there are nearby seeds, plantings, and members" do + expect(page).to have_content "Nearby members" + expect(page).to have_content "Seeds available for trade near Philippines" + expect(page).to have_content "Recent plantings near Philippines" + Percy.snapshot(page, name: 'places map') + end - it "goes to members' index page" do - click_link 'View all members >>' - expect(current_path).to eq members_path - end + it "goes to members' index page" do + click_link 'View all members >>' + expect(current_path).to eq members_path + end - it "goes to plantings' index page" do - click_link 'View all plantings >>' - expect(current_path).to eq plantings_path - end + it "goes to plantings' index page" do + click_link 'View all plantings >>' + expect(current_path).to eq plantings_path + end - it "goes to seeds' index page" do - click_link 'View all seeds >>' - expect(current_path).to eq seeds_path - end + it "goes to seeds' index page" do + click_link 'View all seeds >>' + expect(current_path).to eq seeds_path end end diff --git a/spec/features/plantings/planting_a_crop_spec.rb b/spec/features/plantings/planting_a_crop_spec.rb index 39ee86bd0..5a262ecbb 100644 --- a/spec/features/plantings/planting_a_crop_spec.rb +++ b/spec/features/plantings/planting_a_crop_spec.rb @@ -7,7 +7,9 @@ describe "Planting a crop", :js, :elasticsearch do let!(:planting) do FactoryBot.create :planting, garden: garden, owner: member, planted_at: Date.parse("2013-03-10") end - include_context 'signed in member' do + + context 'signed in' do + include_context 'signed in member' before { visit new_planting_path } it_behaves_like "crop suggest", "planting" diff --git a/spec/features/posts/posting_a_post_spec.rb b/spec/features/posts/posting_a_post_spec.rb index cde48b467..f1b61bc83 100644 --- a/spec/features/posts/posting_a_post_spec.rb +++ b/spec/features/posts/posting_a_post_spec.rb @@ -1,7 +1,8 @@ require 'rails_helper' describe 'Post a post' do - include_context 'signed in member' do + context 'signed in' do + include_context 'signed in member' before { visit new_post_path } it "creating a post" do diff --git a/spec/features/seeds/adding_seeds_spec.rb b/spec/features/seeds/adding_seeds_spec.rb index cc29ef027..dd667bdb7 100644 --- a/spec/features/seeds/adding_seeds_spec.rb +++ b/spec/features/seeds/adding_seeds_spec.rb @@ -2,7 +2,8 @@ require 'rails_helper' require 'custom_matchers' describe "Seeds", :js, :elasticsearch do - include_context 'signed in member' do + context 'signed in' do + include_context 'signed in member' let!(:maize) { create :maize } before { visit new_seed_path } diff --git a/spec/features/seeds/misc_seeds_spec.rb b/spec/features/seeds/misc_seeds_spec.rb index 33c8576c7..b2205ee8a 100644 --- a/spec/features/seeds/misc_seeds_spec.rb +++ b/spec/features/seeds/misc_seeds_spec.rb @@ -2,92 +2,91 @@ require 'rails_helper' describe "seeds", js: true do context "signed in user" do - include_context 'signed in member' do - xit "button on index to edit seed" do - let!(:seed) { create :seed, owner: member } + include_context 'signed in member' + xit "button on index to edit seed" do + let!(:seed) { create :seed, owner: member } - before do - visit seeds_path - click_link 'Actions' - click_link "Edit" - end - - it { expect(current_path).to eq edit_seed_path(seed) } - it { expect(page).to have_content 'Editing seeds' } + before do + visit seeds_path + click_link 'Actions' + click_link "Edit" end - describe "button on front page to add seeds" do - before do - visit root_path - click_link(href: new_seed_path) - end + it { expect(current_path).to eq edit_seed_path(seed) } + it { expect(page).to have_content 'Editing seeds' } + end - it { expect(current_path).to eq new_seed_path } - it { expect(page).to have_content 'Save seeds' } + describe "button on front page to add seeds" do + before do + visit root_path + click_link(href: new_seed_path) end - describe "Clicking link to owner's profile" do - before do - visit member_seeds_path(member) - click_link "View #{member}'s profile >>" - end + it { expect(current_path).to eq new_seed_path } + it { expect(page).to have_content 'Save seeds' } + end - it { expect(current_path).to eq member_path(member) } + describe "Clicking link to owner's profile" do + before do + visit member_seeds_path(member) + click_link "View #{member}'s profile >>" end - # actually adding seeds is in spec/features/seeds_new_spec.rb + it { expect(current_path).to eq member_path(member) } + end - it "edit seeds" do - seed = create :seed, owner: member + # actually adding seeds is in spec/features/seeds_new_spec.rb + + it "edit seeds" do + seed = create :seed, owner: member + visit seed_path(seed) + click_link 'Actions' + click_link 'Edit' + expect(current_path).to eq edit_seed_path(seed) + fill_in 'Quantity', with: seed.quantity * 2 + click_button 'Save' + expect(current_path).to eq seed_path(seed) + end + + describe "delete seeds" do + let(:seed) { FactoryBot.create :seed, owner: member } + + before do visit seed_path(seed) click_link 'Actions' - click_link 'Edit' - expect(current_path).to eq edit_seed_path(seed) - fill_in 'Quantity', with: seed.quantity * 2 - click_button 'Save' - expect(current_path).to eq seed_path(seed) + accept_confirm do + click_link 'Delete' + end end - describe "delete seeds" do - let(:seed) { FactoryBot.create :seed, owner: member } + it { expect(current_path).to eq seeds_path } + end - before do - visit seed_path(seed) - click_link 'Actions' - accept_confirm do - click_link 'Delete' - end - end + describe '#show' do + before { visit seed_path(seed) } - it { expect(current_path).to eq seeds_path } + describe "view seeds with max and min days until maturity" do + let(:seed) { FactoryBot.create :seed, days_until_maturity_min: 5, days_until_maturity_max: 7 } + + it { expect(page).to have_content "Days until maturity: 5–7" } end - describe '#show' do - before { visit seed_path(seed) } + describe "view seeds with only max days until maturity" do + let(:seed) { FactoryBot.create :seed, days_until_maturity_max: 7 } - describe "view seeds with max and min days until maturity" do - let(:seed) { FactoryBot.create :seed, days_until_maturity_min: 5, days_until_maturity_max: 7 } + it { expect(page).to have_content "Days until maturity: 7" } + end - it { expect(page).to have_content "Days until maturity: 5–7" } - end + describe "view seeds with only min days until maturity" do + let(:seed) { FactoryBot.create :seed, days_until_maturity_min: 5 } - describe "view seeds with only max days until maturity" do - let(:seed) { FactoryBot.create :seed, days_until_maturity_max: 7 } + it { expect(page).to have_content "Days until maturity: 5" } + end - it { expect(page).to have_content "Days until maturity: 7" } - end + describe "view seeds with neither max nor min days until maturity" do + let(:seed) { FactoryBot.create :seed } - describe "view seeds with only min days until maturity" do - let(:seed) { FactoryBot.create :seed, days_until_maturity_min: 5 } - - it { expect(page).to have_content "Days until maturity: 5" } - end - - describe "view seeds with neither max nor min days until maturity" do - let(:seed) { FactoryBot.create :seed } - - it { expect(page).to have_content "Days until maturity: unknown" } - end + it { expect(page).to have_content "Days until maturity: unknown" } end end end diff --git a/spec/features/seeds/seed_photos.rb b/spec/features/seeds/seed_photos.rb index b787e2b87..6f4d9828c 100644 --- a/spec/features/seeds/seed_photos.rb +++ b/spec/features/seeds/seed_photos.rb @@ -2,7 +2,8 @@ require 'rails_helper' require 'custom_matchers' describe "Seeds", :js do - include_context 'signed in member' do + context 'signed in' do + include_context 'signed in member' before { visit seed_path(seed) } subject { page } From 38477c9bfdd7f7e254b4dc9da2c2adc20e045b1b Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 18 Aug 2019 16:15:47 +1200 Subject: [PATCH 138/151] Wrap admin in context --- spec/features/admin/admin_spec.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/spec/features/admin/admin_spec.rb b/spec/features/admin/admin_spec.rb index 94c7a8dca..cbd83bf53 100644 --- a/spec/features/admin/admin_spec.rb +++ b/spec/features/admin/admin_spec.rb @@ -1,9 +1,11 @@ require 'rails_helper' describe "forums", js: true do - include_context 'signed in admin' - it "navigating to forum admin with js" do - visit admin_path - Percy.snapshot(page, name: 'Admin page') + context 'signed in admin' do + include_context 'signed in admin' + it "navigating to forum admin with js" do + visit admin_path + Percy.snapshot(page, name: 'Admin page') + end end end From e48dae006b9473466515877990b6ca050ebac198 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 18 Aug 2019 20:15:55 +1200 Subject: [PATCH 139/151] Delete notifications_spec.rb --- spec/features/notifications_spec.rb | 64 ----------------------------- 1 file changed, 64 deletions(-) delete mode 100644 spec/features/notifications_spec.rb diff --git a/spec/features/notifications_spec.rb b/spec/features/notifications_spec.rb deleted file mode 100644 index 0221c96f8..000000000 --- a/spec/features/notifications_spec.rb +++ /dev/null @@ -1,64 +0,0 @@ -require 'rails_helper' - -describe "Notifications", :js do - let(:sender) { create :member } - let(:recipient) { create :member, login_name: 'beyonce' } - - context 'signed in' do - include_context 'signed in member' - let(:member) { recipient } - - context "On existing notification" do - let!(:notification) do - create :notification, - sender: sender, - recipient: recipient, - body: "Notification body", - post_id: nil - end - before do - visit root_path - click_link 'Your Stuff' - Percy.snapshot(page, name: "notification menu") - visit notification_path(notification) - Percy.snapshot(page, name: "notifications#show") - end - - it "Replying to the notification" do - click_link "Reply" - expect(page).to have_content "Notification body" - Percy.snapshot(page, name: 'Replying to notification') - - fill_in 'notification_body', with: "Response body" - Percy.snapshot(page, name: "notifications#new") - click_button "Send" - - expect(page).to have_content "Message was successfully sent" - end - end - - describe 'pagination' do - before do - FactoryBot.create_list :notification, 34, recipient: recipient - visit notifications_path - end - - it do - Percy.snapshot(page, name: "notifications#index") - end - - it 'has page navigation' do - expect(page).to have_selector 'a[rel="next"]' - end - - it 'paginates at 30 notifications per page' do - expect(page).to have_selector '.message', count: 30 - end - - it 'navigates pages' do - first('a[rel="next"]').click - expect(page).to have_selector '.message', count: 4 - end - end - end -end From fa5b2eea325c58c47819766329a88ca01bc77bf3 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 19 Aug 2019 09:21:28 +1200 Subject: [PATCH 140/151] DRY spec --- spec/features/crops/creating_a_crop_spec.rb | 51 +++++++++------------ 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/spec/features/crops/creating_a_crop_spec.rb b/spec/features/crops/creating_a_crop_spec.rb index 02b686c83..21178ac92 100644 --- a/spec/features/crops/creating_a_crop_spec.rb +++ b/spec/features/crops/creating_a_crop_spec.rb @@ -1,23 +1,30 @@ require 'rails_helper' describe "Crop", js: true do + shared_examples 'fill in form' do + before do + visit new_crop_path + within "form#new_crop" do + fill_in "crop_name", with: "Philippine flower" + fill_in "en_wikipedia_url", with: "https://en.wikipedia.org/wiki/Jasminum_sambac" + click_button "add-sci_name-row" + fill_in "sci_name[1]", with: "Jasminum sambac 1" + fill_in "sci_name[2]", with: "Jasminum sambac 2" + fill_in "alt_name[1]", with: "Sampaguita" + click_button "add-alt_name-row" + click_button "add-alt_name-row" + fill_in "alt_name[2]", with: "Manol" + click_button "add-alt_name-row" + fill_in "alt_name[3]", with: "Jazmin" + fill_in "alt_name[4]", with: "Matsurika" + end + end + end shared_examples 'request crop' do describe "requesting a crop with multiple scientific and alternate name" do + include_examples 'fill in form' before do - visit new_crop_path within "form#new_crop" do - fill_in "crop_name", with: "Philippine flower" - fill_in "en_wikipedia_url", with: "https://en.wikipedia.org/wiki/Jasminum_sambac" - click_button "add-sci_name-row" - fill_in "sci_name[1]", with: "Jasminum sambac 1" - fill_in "sci_name[2]", with: "Jasminum sambac 2" - fill_in "alt_name[1]", with: "Sampaguita" - click_button "add-alt_name-row" - click_button "add-alt_name-row" - fill_in "alt_name[2]", with: "Manol" - click_button "add-alt_name-row" - fill_in "alt_name[3]", with: "Jazmin" - fill_in "alt_name[4]", with: "Matsurika" fill_in "request_notes", with: "This is the Philippine national flower." click_button "Save" end @@ -30,23 +37,9 @@ describe "Crop", js: true do end shared_examples 'create crop' do describe "creating a crop with multiple scientific and alternate name" do + include_examples 'fill in form' before do - visit new_crop_path - within "form#new_crop" do - fill_in "crop_name", with: "Philippine flower" - fill_in "en_wikipedia_url", with: "https://en.wikipedia.org/wiki/Jasminum_sambac" - click_button "add-sci_name-row" - fill_in "sci_name[1]", with: "Jasminum sambac 1" - fill_in "sci_name[2]", with: "Jasminum sambac 2" - fill_in "alt_name[1]", with: "Sampaguita" - click_button "add-alt_name-row" - click_button "add-alt_name-row" - fill_in "alt_name[2]", with: "Manol" - click_button "add-alt_name-row" - fill_in "alt_name[3]", with: "Jazmin" - fill_in "alt_name[4]", with: "Matsurika" - click_button "Save" - end + click_button "Save" end it { expect(page).to have_content 'crop was successfully created.' } it { expect(page).to have_content "Jasminum sambac 2" } From a7735e77d1faf9ebf47ef0b9a2318e2405b5d5a0 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2019 11:44:35 +0000 Subject: [PATCH 141/151] Bump haml_lint from 0.32.0 to 0.33.0 Bumps [haml_lint](https://github.com/sds/haml-lint) from 0.32.0 to 0.33.0. - [Release notes](https://github.com/sds/haml-lint/releases) - [Changelog](https://github.com/sds/haml-lint/blob/master/CHANGELOG.md) - [Commits](https://github.com/sds/haml-lint/compare/v0.32.0...v0.33.0) Signed-off-by: dependabot-preview[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 2b13de429..1c62a1028 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -211,7 +211,7 @@ GEM haml (>= 4.0.6, < 6.0) html2haml (>= 1.0.1) railties (>= 5.1) - haml_lint (0.32.0) + haml_lint (0.33.0) haml (>= 4.0, < 5.2) rainbow rake (>= 10, < 13) From ba224bacbd22c55d48700e0f1bb9337104d52264 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2019 19:13:10 +0000 Subject: [PATCH 142/151] Bump oj from 3.8.1 to 3.9.0 Bumps [oj](https://github.com/ohler55/oj) from 3.8.1 to 3.9.0. - [Release notes](https://github.com/ohler55/oj/releases) - [Changelog](https://github.com/ohler55/oj/blob/develop/CHANGELOG.md) - [Commits](https://github.com/ohler55/oj/compare/v3.8.1...v3.9.0) Signed-off-by: dependabot-preview[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 1c62a1028..1604241a3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -324,7 +324,7 @@ GEM multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) - oj (3.8.1) + oj (3.9.0) omniauth (1.9.0) hashie (>= 3.4.6, < 3.7.0) rack (>= 1.6.2, < 3) From 715f111182ebbc796b971b03978ee7f707a4a7e1 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 20 Aug 2019 08:27:10 +0000 Subject: [PATCH 143/151] Bump will_paginate from 3.1.7 to 3.1.8 Bumps [will_paginate](https://github.com/mislav/will_paginate) from 3.1.7 to 3.1.8. - [Release notes](https://github.com/mislav/will_paginate/releases) - [Commits](https://github.com/mislav/will_paginate/compare/v3.1.7...v3.1.8) Signed-off-by: dependabot-preview[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 1604241a3..db843a85a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -529,7 +529,7 @@ GEM websocket-driver (0.7.1) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.4) - will_paginate (3.1.7) + will_paginate (3.1.8) will_paginate-bootstrap4 (0.2.2) will_paginate (~> 3.0, >= 3.0.0) xmlrpc (0.3.0) From 5ecc010cf5ace919ee81dd41ad61958b77d1c1b7 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 20 Aug 2019 08:28:32 +0000 Subject: [PATCH 144/151] Bump sass-rails from 5.0.7 to 5.1.0 Bumps [sass-rails](https://github.com/rails/sass-rails) from 5.0.7 to 5.1.0. - [Release notes](https://github.com/rails/sass-rails/releases) - [Commits](https://github.com/rails/sass-rails/compare/v5.0.7...v5.1.0) Signed-off-by: dependabot-preview[bot] --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index db843a85a..a52652c51 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -383,7 +383,7 @@ GEM rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.1.0) + rails-html-sanitizer (1.2.0) loofah (~> 2.2, >= 2.2.2) rails-i18n (5.1.3) i18n (>= 0.7, < 2) @@ -454,8 +454,8 @@ GEM sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) - sass-rails (5.0.7) - railties (>= 4.0.0, < 6) + sass-rails (5.1.0) + railties (>= 5.2.0) sass (~> 3.1) sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) From a792b5933fa111a7b0462bafbc19f4d64a14189d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 20 Aug 2019 08:27:44 +0000 Subject: [PATCH 145/151] Bump devise from 4.6.2 to 4.7.0 Bumps [devise](https://github.com/plataformatec/devise) from 4.6.2 to 4.7.0. - [Release notes](https://github.com/plataformatec/devise/releases) - [Changelog](https://github.com/plataformatec/devise/blob/master/CHANGELOG.md) - [Commits](https://github.com/plataformatec/devise/compare/v4.6.2...v4.7.0) Signed-off-by: dependabot-preview[bot] --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index a056ff862..9cc261184 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -154,10 +154,10 @@ GEM activesupport (>= 3.0.0) dalli (2.7.10) database_cleaner (1.7.0) - devise (4.6.2) + devise (4.7.0) bcrypt (~> 3.0) orm_adapter (~> 0.1) - railties (>= 4.1.0, < 6.0) + railties (>= 4.1.0) responders warden (~> 1.2.3) diff-lcs (1.3) From b3520a1b3f38ec2a1d37728cdfad7a9b0c3578f0 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 19 Aug 2019 14:11:29 +1200 Subject: [PATCH 146/151] Search for members in admin/members#index --- app/controllers/admin/members_controller.rb | 8 +++++++- app/views/admin/members/index.html.haml | 17 +++++++++++------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/app/controllers/admin/members_controller.rb b/app/controllers/admin/members_controller.rb index 11b3c0d9b..483a3b699 100644 --- a/app/controllers/admin/members_controller.rb +++ b/app/controllers/admin/members_controller.rb @@ -3,7 +3,9 @@ module Admin before_action :auth! def index - @members = Member.order(:login_name).paginate(page: params[:page]) + @members = Member.all + @members = @members.where("login_name ILIKE ?", "%#{search_term}%") unless search_term.nil? + @members = @members.order(:login_name).paginate(page: params[:page]) end def destroy @@ -14,6 +16,10 @@ module Admin private + def search_term + params[:q] + end + def auth! authorize! :manage, :all end diff --git a/app/views/admin/members/index.html.haml b/app/views/admin/members/index.html.haml index 7bf1e7764..0a8d440ad 100644 --- a/app/views/admin/members/index.html.haml +++ b/app/views/admin/members/index.html.haml @@ -1,6 +1,12 @@ -.pagination - = page_entries_info @members - = will_paginate @members +.row + .col-md-6 + = bootstrap_form_tag url: admin_members_path, method: :get, layout: :horizontal do |f| + .input-group.md-form.form-sm + .input-group-prepend + %span.input-group-text= icon 'fas', 'user' + = f.text_field(:q, 'aria-label': 'search members', placeholder: 'search members', hide_label: true) + = f.submit 'search', class: 'btn btn-secondary' + %table.table.table-striped %thead @@ -17,6 +23,5 @@ = link_to admin_member_path(member), method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-light text-danger' do = icon 'fas', 'ban' Ban member -.pagination - = page_entries_info @members - = will_paginate @members += page_entries_info @members += will_paginate @members From 4241a7c5f5e9140951ebc8c2221be0c04e91c427 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 19 Aug 2019 14:37:41 +1200 Subject: [PATCH 147/151] Tidy up crop wrangling page --- app/views/crops/wrangle.html.haml | 102 ++++++++++++++---------------- 1 file changed, 47 insertions(+), 55 deletions(-) diff --git a/app/views/crops/wrangle.html.haml b/app/views/crops/wrangle.html.haml index 1cb322645..61ee81a69 100644 --- a/app/views/crops/wrangle.html.haml +++ b/app/views/crops/wrangle.html.haml @@ -1,68 +1,60 @@ - content_for :title, "Crop Wrangling" +%h1 Crop Wrangling -%ul - %li= link_to "Full crop hierarchy", hierarchy_crops_path - %li= link_to "Add Crop", new_crop_path +%nav.nav + = link_to "Full crop hierarchy", hierarchy_crops_path, class: 'nav-link' + = link_to "Add Crop", new_crop_path, class: 'btn' -.crop_wranglers - %h2 Crop Wranglers: - %ul - - @crop_wranglers.each do |crop_wrangler| - %li.crop_wrangler - = link_to crop_wrangler.login_name, crop_wrangler +%section + %h2 Crop Wranglers + - @crop_wranglers.each do |crop_wrangler| + = render 'members/tiny', member: crop_wrangler -.tabbable - %ul.nav.nav-tabs - %li{ class: @approval_status.blank? ? 'active' : '' } - = link_to "Recently added", wrangle_crops_path - %li{ class: @approval_status == "pending" ? 'active' : '' } - = link_to "Pending approval", wrangle_crops_path(approval_status: "pending") - %li{ class: @approval_status == "rejected" ? 'active' : '' } - = link_to "Rejected", wrangle_crops_path(approval_status: "rejected") +%hr/ -%h2 - - if @approval_status == "pending" - Requested Crops - - elsif @approval_status == "rejected" - Rejected Crops - - else - Recently added crops +%section + %h2 Crops + %ul#myTab.nav.nav-tabs{role: "tablist"} + %li.nav-item + %a#home-tab.nav-link{ href: wrangle_crops_path, role: "tab", class: @approval_status.blank? ? 'active' : ''} + Recently added + %li.nav-item + %a#profile-tab.nav-link{ href: wrangle_crops_path(approval_status: "pending"), role: "tab", class: @approval_status == "pending" ? 'active' : ''} + Pending approval + %li.nav-item + %a#contact-tab.nav-link{ href: wrangle_crops_path(approval_status: "rejected"), role: "tab", class: @approval_status == "rejected" ? 'active' : ''} Rejected -.pagination - = page_entries_info @crops - = will_paginate @crops - -%table{ class: "table table-striped", - id: @approval_status.blank? ? 'recently-added-crops' : "#{@approval_status}-crops" } - %tr - %th System name - %th English Wikipedia URL - %th Scientific names - %th Requested by - - if @approval_status == "rejected" - %th Rejected by - - if @approval_status != "rejected" && @approval_status != "pending" - %th Added by - %th When - - @crops.each do |c| + %table.table.table-striped.table-bordered.table-sm{id: @approval_status.blank? ? 'recently-added-crops' : "#{@approval_status}-crops" } %tr - %td= link_to c.name, edit_crop_path(c) - %td= link_to c.en_wikipedia_url, c.en_wikipedia_url - %td - - c.scientific_names.each do |s| - = link_to s.name, s - %br/ - %td= c.requester.present? ? (link_to c.requester, c.requester) : "N/A" - - unless @approval_status == "pending" - %td= c.creator.present? ? (link_to c.creator, c.creator) : "N/A" - %td - = distance_of_time_in_words(c.created_at, Time.zone.now) - ago. + %th System name + %th English Wikipedia URL + %th Scientific names + %th Requested by + - if @approval_status == "rejected" + %th Rejected by + - if @approval_status != "rejected" && @approval_status != "pending" + %th Added by + %th When + - @crops.each do |c| + %tr + %td + = link_to edit_crop_path(c) do + = icon 'fas', 'seedling' + = c.name + %td= link_to c.en_wikipedia_url, c.en_wikipedia_url + %td + - c.scientific_names.each do |s| + = link_to s.name, s + %br/ + %td= c.requester.present? ? (link_to c.requester, c.requester) : "N/A" + - unless @approval_status == "pending" + %td= c.creator.present? ? (link_to c.creator, c.creator) : "N/A" + %td + = distance_of_time_in_words(c.created_at, Time.zone.now) + ago. -.pagination = page_entries_info @crops = will_paginate @crops - From ed4aaa1c9c61b49d401b9c51020147070cf7d6fc Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 19 Aug 2019 14:49:18 +1200 Subject: [PATCH 148/151] Tidy up admin landing page --- app/views/admin/index.html.haml | 48 ++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/app/views/admin/index.html.haml b/app/views/admin/index.html.haml index 5586cfec3..57f1871ba 100644 --- a/app/views/admin/index.html.haml +++ b/app/views/admin/index.html.haml @@ -3,25 +3,41 @@ - content_for :breadcrumbs do %li.breadcrumb-item.active= link_to 'Admin', admin_path -%h2 Manage +%h1 Manage #{ENV['GROWSTUFF_SITE_NAME']} .row .col-md-4 - %h2 Site admin - - %ul#site_admin - %li= link_to "Roles", roles_path - %li= link_to "Forums", forums_path - %li= link_to "CMS", comfy_admin_cms_path - %li= link_to t('.garden_types'), garden_types_path + .card + .card-header + %h2 + = icon 'fas', 'tablet-alt' + Site admin + .card-body + %nav.nav + %li= link_to "Roles", roles_path, class: 'nav-link' + %li= link_to "Forums", forums_path, class: 'nav-link' + %li= link_to "CMS", comfy_admin_cms_path, class: 'nav-link' + %li= link_to t('.garden_types'), garden_types_path, class: 'nav-link' .col-md-4 - %h2 Crop data admin - %ul - %li= link_to "Alternate names", alternate_names_path - %li= link_to "Scientific names", scientific_names_path + .card + .card-header + %h2 + = icon 'fas', 'seedling' + Crop data admin + .card-body + %nav.nav + %li= link_to "Crop Wrangling", wrangle_crops_path, class: 'nav-link' + %li= link_to "Alternate names", alternate_names_path, class: 'nav-link' + %li= link_to "Scientific names", scientific_names_path, class: 'nav-link' + .col-md-4 - %h2 Member admin - %ul - %li= link_to "Newsletter subscribers", admin_newsletter_path - %li= link_to "Members", admin_members_path + .card + .card-header + %h2 + = icon 'fas', 'user' + Member admin + .card-body + %nav.nav + %li= link_to "Newsletter subscribers", admin_newsletter_path, class: 'nav-link' + %li= link_to "Members", admin_members_path, class: 'nav-link' From 99228d885021fe7ba6c61daa5cd9c00f6968a740 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 19 Aug 2019 14:53:12 +1200 Subject: [PATCH 149/151] Add css class, so can find in test --- app/views/crops/wrangle.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/crops/wrangle.html.haml b/app/views/crops/wrangle.html.haml index 61ee81a69..caef0cdf7 100644 --- a/app/views/crops/wrangle.html.haml +++ b/app/views/crops/wrangle.html.haml @@ -6,7 +6,7 @@ = link_to "Full crop hierarchy", hierarchy_crops_path, class: 'nav-link' = link_to "Add Crop", new_crop_path, class: 'btn' -%section +%section.crop_wranglers %h2 Crop Wranglers - @crop_wranglers.each do |crop_wrangler| = render 'members/tiny', member: crop_wrangler From c6d4563edc48616a905ec024c5f39610c56fe092 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 19 Aug 2019 14:53:22 +1200 Subject: [PATCH 150/151] Updated spec --- spec/features/crops/crop_wranglers_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/crops/crop_wranglers_spec.rb b/spec/features/crops/crop_wranglers_spec.rb index e520f90d3..5dd8af71f 100644 --- a/spec/features/crops/crop_wranglers_spec.rb +++ b/spec/features/crops/crop_wranglers_spec.rb @@ -14,7 +14,7 @@ describe "crop wranglers", js: true do click_link 'Crop Wrangling' within '.crop_wranglers' do - expect(page).to have_content 'Crop Wranglers:' + expect(page).to have_content 'Crop Wranglers' crop_wranglers.each do |crop_wrangler| expect(page).to have_link crop_wrangler.login_name, href: member_path(crop_wrangler) end From e3f32d8bb4280dda16e8fa848c7f63ddb4f05a65 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 19 Aug 2019 15:46:45 +1200 Subject: [PATCH 151/151] Updated specs --- app/views/admin/index.html.haml | 6 +++--- spec/features/admin/forums_spec.rb | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/admin/index.html.haml b/app/views/admin/index.html.haml index 57f1871ba..a0a458c56 100644 --- a/app/views/admin/index.html.haml +++ b/app/views/admin/index.html.haml @@ -13,7 +13,7 @@ = icon 'fas', 'tablet-alt' Site admin .card-body - %nav.nav + %nav.nav#site_admin %li= link_to "Roles", roles_path, class: 'nav-link' %li= link_to "Forums", forums_path, class: 'nav-link' %li= link_to "CMS", comfy_admin_cms_path, class: 'nav-link' @@ -26,7 +26,7 @@ = icon 'fas', 'seedling' Crop data admin .card-body - %nav.nav + %nav.nav#crop_admin %li= link_to "Crop Wrangling", wrangle_crops_path, class: 'nav-link' %li= link_to "Alternate names", alternate_names_path, class: 'nav-link' %li= link_to "Scientific names", scientific_names_path, class: 'nav-link' @@ -38,6 +38,6 @@ = icon 'fas', 'user' Member admin .card-body - %nav.nav + %nav.nav#member_admin %li= link_to "Newsletter subscribers", admin_newsletter_path, class: 'nav-link' %li= link_to "Members", admin_members_path, class: 'nav-link' diff --git a/spec/features/admin/forums_spec.rb b/spec/features/admin/forums_spec.rb index a327a692a..7a41266c0 100644 --- a/spec/features/admin/forums_spec.rb +++ b/spec/features/admin/forums_spec.rb @@ -7,7 +7,7 @@ describe "forums", js: true do describe "navigating to forum admin with js" do before do visit admin_path - within 'ul#site_admin' do + within 'nav#site_admin' do click_link "Forums" end end