Skip to content

Commit cdcf13d

Browse files
authored
Merge branch 'main' into dependabot/bundler/pundit-2.5.1
2 parents 7417275 + 09d841b commit cdcf13d

File tree

11 files changed

+140
-19
lines changed

11 files changed

+140
-19
lines changed

Gemfile.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -307,9 +307,9 @@ GEM
307307
excon (1.2.8)
308308
logger
309309
execjs (2.10.0)
310-
factory_bot (6.5.4)
310+
factory_bot (6.5.5)
311311
activesupport (>= 6.1.0)
312-
factory_bot_rails (6.5.0)
312+
factory_bot_rails (6.5.1)
313313
factory_bot (~> 6.5)
314314
railties (>= 6.1.0)
315315
faker (3.5.2)
@@ -491,7 +491,7 @@ GEM
491491
racc (~> 1.4)
492492
nokogiri (1.18.9-x86_64-linux-gnu)
493493
racc (~> 1.4)
494-
noticed (2.8.0)
494+
noticed (2.8.1)
495495
rails (>= 6.1.0)
496496
optimist (3.2.1)
497497
orm_adapter (0.5.0)
@@ -624,7 +624,7 @@ GEM
624624
responders (3.1.1)
625625
actionpack (>= 5.2)
626626
railties (>= 5.2)
627-
rexml (3.4.1)
627+
rexml (3.4.2)
628628
rgeo (3.0.1)
629629
rgeo-activerecord (8.0.0)
630630
activerecord (>= 7.0)

app/controllers/better_together/events_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class EventsController < FriendlyResourceController # rubocop:todo Metrics/Class
77
include NotificationReadable
88

99
# Prepend resource instance setting for privacy check
10-
prepend_before_action :set_resource_instance, only: %i[show ics]
10+
prepend_before_action :set_resource_instance, only: %i[show edit update destroy ics]
1111
prepend_before_action :set_event_for_privacy_check, only: [:show]
1212

1313
before_action if: -> { Rails.env.development? } do

app/notifiers/better_together/event_invitation_notifier.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,19 @@ class EventInvitationNotifier < ApplicationNotifier # rubocop:todo Style/Documen
1616
def invitation = params[:invitation]
1717
def invitable = params[:invitable] || invitation&.invitable
1818

19+
def locale
20+
params[:invitation]&.locale || I18n.locale || I18n.default_locale
21+
end
22+
1923
def title
20-
I18n.with_locale(params[:invitation].locale) do
24+
I18n.with_locale(locale) do
2125
I18n.t('better_together.notifications.event_invitation.title',
2226
event_name: invitable&.name, default: 'You have been invited to an event')
2327
end
2428
end
2529

2630
def body
27-
I18n.with_locale(params[:invitation].locale) do
31+
I18n.with_locale(locale) do
2832
I18n.t('better_together.notifications.event_invitation.body',
2933
event_name: invitable&.name, default: 'Invitation to %<event_name>s')
3034
end

app/notifiers/better_together/event_update_notifier.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class EventUpdateNotifier < ApplicationNotifier
1212
config.if = -> { recipient_has_email? && should_notify? }
1313
end
1414

15-
param :event, :changed_attributes
15+
required_param :event, :changed_attributes
1616

1717
notification_methods do
1818
delegate :event, :changed_attributes, to: :params

app/notifiers/better_together/joatu/match_notifier.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class MatchNotifier < ApplicationNotifier
1313
config.if = -> { recipient_has_email? && should_notify? }
1414
end
1515

16-
param :offer, :request
16+
required_param :offer, :request
1717

1818
notification_methods do
1919
delegate :offer, :request, to: :event

app/policies/better_together/conversation_policy.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def leave_conversation?
3737
# Returns the people that the agent is permitted to message
3838
def permitted_participants
3939
if permitted_to?('manage_platform')
40-
BetterTogether::Person.all
40+
BetterTogether::Person.includes(:string_translations).all
4141
else
4242
role = BetterTogether::Role.find_by(identifier: 'platform_manager')
4343
manager_ids = BetterTogether::PersonPlatformMembership.where(role_id: role.id).pluck(:member_id)
@@ -46,7 +46,7 @@ def permitted_participants
4646
'preferences @> ?', { receive_messages_from_members: true }.to_json
4747
)
4848

49-
BetterTogether::Person.where(id: manager_ids).or(opted_in).distinct
49+
BetterTogether::Person.includes(:string_translations).where(id: manager_ids).or(opted_in).distinct
5050
end
5151
end
5252

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11

2-
<%# locals: (community:) %>
3-
42
<%= render 'better_together/shared/card', entity: community do %>
5-
63
<% end %>
74

app/views/better_together/conversations/_conversation_content.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
</h4>
1313
<% end %>
1414
<div class="conversation-participants w-100 d-flex align-items-top justify-content-evenly overflow-auto">
15-
<%= render partial: 'better_together/people/mention' , collection: conversation.participants, as: :person,
15+
<%= render partial: 'better_together/people/mention' , collection: conversation.participants.includes(:string_translations).with_attached_profile_image, as: :person,
1616
locals: { flex_layout: 'flex-column' , flex_align_items: 'center' } %>
1717
</div>
1818
<div data-bs-toggle="tooltip" title="<%= t('.options_tooltip') %>" class="align-self-center mx-4">

app/views/better_together/people/_mention.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<%= profile_image_tag(person, class: 'mention', size: 50) %>
88
</div>
99
<div class="h-50 align-self-top">
10-
<a class="text-decoration-none identity-name stretched-link" href="<%= policy(person).show? ? person_path(person) : 'test' %>">
10+
<a class="text-decoration-none identity-name stretched-link" href="<%= policy(person).show? ? person_path(person) : nil %>">
1111
<%= person.name %>
1212
</a>
1313
</div>
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# frozen_string_literal: true
2+
3+
require 'rails_helper'
4+
5+
RSpec.feature 'Event edit preserves data', :as_user do
6+
let!(:community) { create(:community, privacy: 'public') }
7+
8+
before do
9+
configure_host_platform
10+
capybara_login_as_platform_manager
11+
end
12+
13+
scenario 'submitting the edit form without changes keeps the event unchanged', :aggregate_failures, :js do
14+
# Create an event and attach host
15+
event = create(:better_together_event, :upcoming, registration_url: 'https://example.test/register')
16+
BetterTogether::EventHost.create!(event: event, host: community)
17+
18+
# Directly visit the edit page for the event using the route helper (avoids ambiguous clicks)
19+
visit better_together.edit_event_path(event, locale: I18n.locale)
20+
21+
# Try to locate the edit form. Capybara may sometimes not consider the element visible due to JS;
22+
# prefer finding a form by id prefix, but provide a fallback that parses the page HTML and submits via JS.
23+
form = nil
24+
begin
25+
# include non-visible forms (Capybara may treat some forms as hidden during JS rendering)
26+
expect(page).to have_selector('form', wait: 10, visible: :all)
27+
forms = all('form', visible: :all)
28+
form = forms.find { |f| f[:id]&.start_with?('form_event_') } || forms.find do |f|
29+
f[:action]&.include?('/events/')
30+
end || forms.first
31+
rescue Capybara::ElementNotFound
32+
# ignore; we'll try the HTML fallback below
33+
end
34+
35+
# Capture values
36+
# Read values using input name attributes which are stable (inputs use random ids)
37+
name_value = begin
38+
find("input[name='event[name_en]']", visible: false).value
39+
rescue Capybara::ElementNotFound
40+
nil
41+
end
42+
43+
registration_value = begin
44+
find("input[name='event[registration_url]']", visible: false).value
45+
rescue Capybara::ElementNotFound
46+
nil
47+
end
48+
49+
selected_categories = all("select[name='event[category_ids][]'] option[selected]").map(&:text)
50+
51+
location_name = begin
52+
find("input[name='event[location_attributes][name]']", visible: false).value
53+
rescue Capybara::ElementNotFound
54+
nil
55+
end
56+
57+
# For ActionText translations there is a hidden input with the HTML value
58+
description_text = begin
59+
find("input[name='event[description_en]']", visible: false).value
60+
rescue Capybara::ElementNotFound
61+
''
62+
end
63+
64+
# Submit without changes using the specific event edit form to avoid ambiguous Save buttons
65+
# Prefer the form id pattern `form_event_<uuid>` which is generated in the view.
66+
# This is more stable than matching on action which may include host/port variations.
67+
if form
68+
form_action = form[:action]
69+
target_event_id = form_action.split('/').last
70+
71+
# If the form edits a different event than the created one, use that record for assertions
72+
target_event = if target_event_id == event.to_param
73+
event
74+
else
75+
BetterTogether::Event.find(target_event_id)
76+
end
77+
78+
within form do
79+
# Scope the button lookup to the form to avoid other buttons on the page
80+
if has_button?('Save Event')
81+
click_button 'Save Event'
82+
elsif has_button?(I18n.t('helpers.submit.update', model: 'Event', default: 'Update Event'))
83+
click_button I18n.t('helpers.submit.update', model: 'Event', default: 'Update Event')
84+
else
85+
# Fallback to any submit input inside the form
86+
find("input[type='submit']", match: :first).click
87+
end
88+
end
89+
else
90+
# Fallback: parse the raw HTML for a form action and submit it via JS. This bypasses Capybara visibility quirks.
91+
html = page.html
92+
match = html.match(%r{<form[^>]+action=["']([^"']*/events/([^"']+))["'][^>]*>})
93+
unless match
94+
raise Capybara::ElementNotFound, 'Could not locate event edit form on the page (no form element found)'
95+
end
96+
97+
target_event_id = match[2]
98+
target_event = if target_event_id == event.to_param
99+
event
100+
else
101+
BetterTogether::Event.find(target_event_id)
102+
end
103+
# Submit the form via JS (use %Q to allow interpolation and avoid quote collisions)
104+
page.execute_script(%[(function(){ var f = document.querySelector('form[action*="/events/#{target_event_id}"]'); if(f){ f.submit(); } })()]) # rubocop:disable Layout/LineLength
105+
106+
end
107+
108+
# Expect success flash and that we are on an event show page (not asserting exact id)
109+
expect(page).to have_content('Event was successfully updated.')
110+
111+
target_event.reload
112+
113+
expect(target_event.registration_url).to eq(registration_value) if registration_value
114+
115+
expect(target_event.name.to_s.strip).to eq(name_value.to_s.strip) if name_value
116+
117+
expect(target_event.categories.map(&:name)).to include(*selected_categories) if selected_categories.any?
118+
119+
expect(target_event.location&.name.to_s).to eq(location_name.to_s) if location_name
120+
121+
expect(target_event.description.to_s.strip).to include(description_text.strip) if description_text.present?
122+
end
123+
end

0 commit comments

Comments
 (0)