+
My account
+
+ <%= render(SidebarSectionComponent.new(title: 'Password')) do %>
+ <%= form_with(url: password_path, method: :patch, builder: TailwindFormBuilder) do |form| %>
+ <% if flash[:incorrect_password] %>
+ <%= render ErrorBoxComponent.new(title: 'Incorrect password').with_content(flash[:incorrect_password]) %>
+ <% end %>
+ <% if @user.errors.include?(:password) %>
+ <%= render ModelErrorComponent.new(model: @user) %>
+ <% end %>
+ <%= form.password_field :current_password, required: true, autofocus: true, autocomplete: "current-password", class: "w-full mb-3" %>
+ <%= form.password_field :password, label: { text: "New password"}, required: true, autocomplete: "new-password", class: "w-full mb-3" %>
+ <%= form.password_field :password_confirmation, label: { text: "Confirm new password"}, required: true, autocomplete: "new-password", class: "w-full mb-3" %>
+
+ <%= form.submit "Save changes", class: "mt-3" %>
+
+ <% end %>
+ <% end %>
+
+ <%= render(SidebarSectionComponent.new(title: 'Email address')) do %>
+ <% unless Current.user.verified? %>
+
+
We sent a verification email to the address below. Check that email and follow those instructions to confirm it's your email address.
+
<%= button_to "Re-send verification email", identity_email_verification_path, class: 'py-3 px-5 bg-amber-600 hover:bg-amber-500 text-white font-medium cursor-pointer my-3' %>
+
+ <% end %>
+
+ <%= form_with(url: identity_email_path, method: :patch, builder: TailwindFormBuilder) do |form| %>
+ <% if flash[:emails_update_password_incorrect] %>
+ <%= render ErrorBoxComponent.new(title: 'Incorrect password').with_content(flash[:emails_update_password_incorrect]) %>
+ <% end %>
+ <% if @user.errors.include?(:email) %>
+ <%= render ModelErrorComponent.new(model: @user) %>
+ <% end %>
+ <%= form.email_field :email, label: { text: "New email" }, required: true, autofocus: true, class: 'w-full mb-3' %>
+ <%= form.password_field :current_password, required: true, autocomplete: "current-password", class: 'w-full mb-3' %>
+
+ <%= form.submit "Save changes", class: 'mt-3' %>
+
+ <% end %>
+ <% end %>
+
+ <%= render(SidebarSectionComponent.new(title: 'Payout details')) do %>
+
We use Wise to make payouts once a month. Wise will email you at <%= Current.user.email %> to ask for your bank details. To make the payment we need the following:
+
+ <% payout_detail = @user.payout_detail || PayoutDetail.new(user: @user) %>
+ <%= form_with(model: payout_detail, class: "contents", builder: TailwindFormBuilder) do |form| %>
+ <%= render ModelErrorComponent.new(model: payout_detail) %>
+ <%= form.text_field :name, placeholder: 'Bartholomew J. Simpson', class: 'w-full' %>
+
Your full name as used on your bank account.
+
+ <%= form.select :country, options_for_payout_details_country_select, include_blank: true, label: { text: 'Country / Region' }, class: 'w-full' %>
+
We support payouts to the regions/countries that Wise supports.
+
+
+ <% if payout_detail.persisted? %>
+ <%= form.submit "Save changes", class: 'mt-3'%>
+ <% else %>
+ <%= form.submit "Add payout details", class: 'mt-3'%>
+ <% end %>
+
+ <% end %>
<% end %>
-
diff --git a/config/routes.rb b/config/routes.rb
index 1cb37ef3..f06f9382 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -17,12 +17,12 @@
get 'collection', to: 'collections#show'
resources :sessions, only: %i[index show destroy]
- resource :password, only: %i[edit update]
- resource :payout_detail, only: %i[new create edit update]
+ resource :password, only: %i[update]
+ resource :payout_detail, only: %i[create update]
resolve('PayoutDetail') { [:payout_detail] }
namespace :identity do
- resource :email, only: %i[edit update]
+ resource :email, only: %i[update]
resource :email_verification, only: %i[show create]
resource :password_reset, only: %i[new edit create update]
end
diff --git a/test/components/error_box_component_test.rb b/test/components/error_box_component_test.rb
new file mode 100644
index 00000000..fb1a0a45
--- /dev/null
+++ b/test/components/error_box_component_test.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'test_helper'
+
+class ErrorBoxComponentTest < ViewComponent::TestCase
+ def setup
+ render_inline(ErrorBoxComponent.new(title: 'Title').with_content('Content'))
+ end
+
+ def test_component_renders_title
+ assert_text 'Title'
+ end
+
+ def test_component_renders_content
+ assert_text 'Content'
+ end
+end
diff --git a/test/components/model_error_component_test.rb b/test/components/model_error_component_test.rb
new file mode 100644
index 00000000..c35a03db
--- /dev/null
+++ b/test/components/model_error_component_test.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'test_helper'
+
+class ModelErrorComponentTest < ViewComponent::TestCase
+ def setup
+ @model = User.new
+ end
+
+ def test_component_renders_nothing_when_model_has_no_errors
+ assert render_inline(ModelErrorComponent.new(model: @model)).to_html.blank?
+ end
+
+ def test_component_renders_title_model_has_errors
+ @model.email = nil
+ @model.save
+
+ render_inline(ModelErrorComponent.new(model: @model))
+
+ assert_text 'errors prohibited this user from being saved'
+ end
+
+ def test_component_renders_errors_when_model_has_errors
+ @model.email = nil
+ @model.save
+
+ render_inline(ModelErrorComponent.new(model: @model))
+
+ assert_text "Email can't be blank"
+ end
+end
diff --git a/test/components/previews/error_box_component_preview.rb b/test/components/previews/error_box_component_preview.rb
new file mode 100644
index 00000000..e9df9a95
--- /dev/null
+++ b/test/components/previews/error_box_component_preview.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class ErrorBoxComponentPreview < ViewComponent::Preview
+ def default
+ render(
+ ErrorBoxComponent.new(title: 'Title')
+ ) do
+ tag.div do
+ content_tag(:span, 'Error box content')
+ end
+ end
+ end
+end
diff --git a/test/components/previews/model_error_component_preview.rb b/test/components/previews/model_error_component_preview.rb
new file mode 100644
index 00000000..9f36e49e
--- /dev/null
+++ b/test/components/previews/model_error_component_preview.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class ModelErrorComponentPreview < ViewComponent::Preview
+ def default
+ model = User.new
+ model.save
+
+ render(ModelErrorComponent.new(model:))
+ end
+end
diff --git a/test/components/sidebar_section_component_test.rb b/test/components/sidebar_section_component_test.rb
new file mode 100644
index 00000000..a819d63a
--- /dev/null
+++ b/test/components/sidebar_section_component_test.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'test_helper'
+
+class SidebarSectionComponentTest < ViewComponent::TestCase
+ def test_component_renders_something_useful
+ # assert_equal(
+ # %(
Hello, components!),
+ # render_inline(SidebarSectionComponent.new(message: "Hello, components!")).css("span").to_html
+ # )
+ end
+end
diff --git a/test/controllers/identity/email_verifications_controller_test.rb b/test/controllers/identity/email_verifications_controller_test.rb
index 84956f50..5449941f 100644
--- a/test/controllers/identity/email_verifications_controller_test.rb
+++ b/test/controllers/identity/email_verifications_controller_test.rb
@@ -29,7 +29,7 @@ class EmailVerificationsControllerTest < ActionDispatch::IntegrationTest
get identity_email_verification_url(sid: sid_exp, email: @user.email)
- assert_redirected_to edit_identity_email_url
+ assert_redirected_to root_url
assert_equal 'That email verification link is invalid', flash[:alert]
end
end
diff --git a/test/controllers/identity/emails_controller_test.rb b/test/controllers/identity/emails_controller_test.rb
index c0199fb0..35989d26 100644
--- a/test/controllers/identity/emails_controller_test.rb
+++ b/test/controllers/identity/emails_controller_test.rb
@@ -8,21 +8,16 @@ class EmailsControllerTest < ActionDispatch::IntegrationTest
@user = log_in_as(create(:user))
end
- test 'should get edit' do
- get edit_identity_email_url
- assert_response :success
- end
-
test 'should update email' do
patch identity_email_url, params: { email: 'new_email@hey.com', current_password: 'Secret1*3*5*' }
- assert_redirected_to root_url
+ assert_redirected_to account_path
end
test 'should not update email with wrong current password' do
patch identity_email_url, params: { email: 'new_email@hey.com', current_password: 'SecretWrong1*3' }
- assert_redirected_to edit_identity_email_url
- assert_equal 'The password you entered is incorrect', flash[:alert]
+ assert_redirected_to account_path
+ assert_equal 'The password you entered is incorrect', flash[:emails_update_password_incorrect]
end
end
end
diff --git a/test/controllers/passwords_controller_test.rb b/test/controllers/passwords_controller_test.rb
index c453d4f2..1efec87f 100644
--- a/test/controllers/passwords_controller_test.rb
+++ b/test/controllers/passwords_controller_test.rb
@@ -7,15 +7,10 @@ class PasswordsControllerTest < ActionDispatch::IntegrationTest
@user = log_in_as(create(:user))
end
- test 'should get edit' do
- get edit_password_url
- assert_response :success
- end
-
test 'should update password' do
patch password_url,
params: { current_password: 'Secret1*3*5*', password: 'Secret6*4*2*', password_confirmation: 'Secret6*4*2*' }
- assert_redirected_to root_url
+ assert_redirected_to account_path
end
test 'should not update password with wrong current password' do
@@ -23,7 +18,7 @@ class PasswordsControllerTest < ActionDispatch::IntegrationTest
params: { current_password: 'SecretWrong1*3', password: 'Secret6*4*2*',
password_confirmation: 'Secret6*4*2*' }
- assert_redirected_to edit_password_url
- assert_equal 'The current password you entered is incorrect', flash[:alert]
+ assert_redirected_to account_path
+ assert_equal 'The current password you entered is incorrect', flash[:incorrect_password]
end
end
diff --git a/test/controllers/payout_details_controller_test.rb b/test/controllers/payout_details_controller_test.rb
index 037931ba..306de1e9 100644
--- a/test/controllers/payout_details_controller_test.rb
+++ b/test/controllers/payout_details_controller_test.rb
@@ -8,11 +8,6 @@ def setup
log_in_as(@user)
end
- test '#new' do
- get new_payout_detail_url
- assert_response :success
- end
-
test '#create creates a new PayoutDetail and redirects to account_url' do
assert_difference('PayoutDetail.count') do
post payout_detail_url, params: { payout_detail: { name: 'Alice', country: 'country' } }
@@ -47,31 +42,9 @@ def setup
assert_response :not_found
end
-
- test '#edit' do
- create(:payout_detail, user: @user)
-
- get edit_payout_detail_url
- assert_response :success
- end
-
- test '#edit 404s if user has no payout detail' do
- get edit_payout_detail_url
- assert_response :not_found
- end
end
class PayoutDetailsControllerTestSignedOut < ActionDispatch::IntegrationTest
- test '#new' do
- get new_payout_detail_url
- assert_redirected_to log_in_url
- end
-
- test '#edit' do
- get edit_payout_detail_url
- assert_redirected_to log_in_url
- end
-
test '#update' do
patch payout_detail_url
assert_redirected_to log_in_url
diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb
index 54c24379..ce2fb635 100644
--- a/test/controllers/users_controller_test.rb
+++ b/test/controllers/users_controller_test.rb
@@ -12,16 +12,6 @@ class UsersControllerTestSignedIn < ActionDispatch::IntegrationTest
get account_url
assert_response :success
end
-
- test '#show has a link to change password' do
- get account_url
- assert_select 'a', href: edit_password_path
- end
-
- test '#show has a link to change email address' do
- get account_url
- assert_select 'a', href: edit_identity_email_path
- end
end
class UserControllerTestSignedOut < ActionDispatch::IntegrationTest
diff --git a/test/mailers/purchase_mailer_test.rb b/test/mailers/purchase_mailer_test.rb
index cc5d0d27..8e453c98 100644
--- a/test/mailers/purchase_mailer_test.rb
+++ b/test/mailers/purchase_mailer_test.rb
@@ -50,7 +50,7 @@ class PurchaseMailerTest < ActionMailer::TestCase
purchase = build(:purchase, album:, price: 7.00)
mail = PurchaseMailer.with(purchase:).notify_artist
- assert_includes mail.body.to_s, new_payout_detail_url
+ assert_includes mail.body.to_s, account_url
end
test 'notify_artist allows user to change/verify payout details' do
@@ -61,7 +61,7 @@ class PurchaseMailerTest < ActionMailer::TestCase
purchase = build(:purchase, album:, price: 7.00)
mail = PurchaseMailer.with(purchase:).notify_artist
- assert_includes mail.body.to_s, edit_payout_detail_url
+ assert_includes mail.body.to_s, account_url
end
test 'do not notify artist of purchase if sending is suppressed' do
diff --git a/test/system/identity/emails_test.rb b/test/system/identity/emails_test.rb
index 0d1c3073..ab0669d7 100644
--- a/test/system/identity/emails_test.rb
+++ b/test/system/identity/emails_test.rb
@@ -8,27 +8,56 @@ class EmailsTest < ApplicationSystemTestCase
@user = log_in_as(create(:user))
end
- test 'updating the email' do
- click_on 'avatar'
- click_on 'My account'
- click_on 'Change email address'
+ test 'when I update my email address I should be prompted to verify it' do
+ visit account_path
- fill_in 'New email', with: 'new_email@hey.com'
- fill_in 'Current password', with: 'Secret1*3*5*'
- click_on 'Save changes'
+ within(email_address_section) do
+ fill_in 'New email', with: 'new_email@example.com'
+ fill_in 'Current password', with: 'Secret1*3*5*'
+ click_on 'Save changes'
+ end
assert_text 'Your email has been changed'
- end
- test 'sending a verification email' do
- @user.update! verified: false
+ visit account_path
+ assert_text 'We sent a verification email to the address below'
- click_on 'avatar'
- click_on 'My account'
- click_on 'Change email address'
click_on 'Re-send verification email'
-
assert_text 'We sent a verification email to your email address'
end
+
+ test 'updating my email address fails if my current password is wrong' do
+ visit account_path
+
+ within(email_address_section) do
+ fill_in 'New email', with: 'new_email@example.com'
+ fill_in 'Current password', with: 'wrongpassword'
+ click_on 'Save changes'
+ end
+
+ assert_text 'The password you entered is incorrect'
+ refute_text 'We sent a verification email to the address below'
+ end
+
+ test 'updating my email address fails if I use an existing email' do
+ existing_user = create(:user)
+
+ visit account_path
+
+ within(email_address_section) do
+ fill_in 'New email', with: existing_user.email
+ fill_in 'Current password', with: 'Secret1*3*5*'
+ click_on 'Save changes'
+ end
+
+ assert_text 'Email has already been taken'
+ refute_text 'We sent a verification email to the address below'
+ end
+
+ private
+
+ def email_address_section
+ find('h2', text: 'Email address').ancestor('section')
+ end
end
end
diff --git a/test/system/passwords_test.rb b/test/system/passwords_test.rb
index 41608de0..0e0bacdc 100644
--- a/test/system/passwords_test.rb
+++ b/test/system/passwords_test.rb
@@ -8,15 +8,36 @@ class PasswordsTest < ApplicationSystemTestCase
end
test 'updating the password' do
- click_on 'avatar'
- click_on 'My account'
- click_on 'Change password'
+ visit account_path
- fill_in 'Current password', with: 'Secret1*3*5*'
- fill_in 'New password', with: 'Secret6*4*2*'
- fill_in 'Confirm new password', with: 'Secret6*4*2*'
- click_on 'Save changes'
+ within(password_section) do
+ fill_in 'Current password', with: 'Secret1*3*5*'
+ fill_in 'New password', with: 'Secret6*4*2*'
+ fill_in 'Confirm new password', with: 'Secret6*4*2*'
+ click_on 'Save changes'
+ end
assert_text 'Your password has been changed'
+ assert_current_path account_path
+ end
+
+ test 'when password is too short' do
+ visit account_path
+
+ within(password_section) do
+ fill_in 'Current password', with: 'Secret1*3*5*'
+ fill_in 'New password', with: 'short'
+ fill_in 'Confirm new password', with: 'short'
+ click_on 'Save changes'
+ end
+
+ assert_text 'Password is too short'
+ assert_current_path account_path
+ end
+
+ private
+
+ def password_section
+ find('h2', text: 'Password').ancestor('section')
end
end
diff --git a/test/system/payout_details_test.rb b/test/system/payout_details_test.rb
index 9d27b9bc..3cedf868 100644
--- a/test/system/payout_details_test.rb
+++ b/test/system/payout_details_test.rb
@@ -10,12 +10,35 @@ class PayoutDetailsTest < ApplicationSystemTestCase
test 'adding payout details' do
visit account_url
- click_on 'Add payout details'
- fill_in 'Name', with: 'John Lennon'
- select '🇬🇧 United Kingdom (GBP)', from: 'Country / Region'
- click_on 'Save'
+ within(payout_details_section) do
+ fill_in 'Name', with: 'John Lennon'
+ select '🇬🇧 United Kingdom (GBP)', from: 'Country / Region'
+ click_on 'Add payout details'
+ end
+
+ assert_text 'Payout details added'
assert_equal 'John Lennon', @user.payout_detail.name
assert_equal 'united_kingdom', @user.payout_detail.country
end
+
+ test 'updating payout details' do
+ create(:payout_detail, user: @user)
+
+ visit account_url
+
+ within(payout_details_section) do
+ fill_in 'Name', with: 'John Smith'
+ select '🇬🇧 United Kingdom (GBP)', from: 'Country / Region'
+ click_on 'Save changes'
+ end
+
+ assert_text 'Payout details updated'
+ end
+
+ private
+
+ def payout_details_section
+ find('h2', text: 'Payout details').ancestor('section')
+ end
end