mirror of
https://github.com/discourse/discourse.git
synced 2026-08-07 13:19:19 +08:00
Related: https://meta.discourse.org/t/multi-language-preferences-for-displaying-localized-content/381116 Allow anon and logged in users to set more than one language that they understand, when content localization is enabled. ### User preferences In user preferences, we now include a Content Languages section when the site has Content Localization enabled. ### Topic menu In topics where there are any languages that's not the user's language, the option will appear to set their preferred content languages. This appears for anon and logged in users, but anon users will be asked to logged in to set the languages. __________ These preferences apply only to topic titles and posts. They do not affect navigational features like categories, tags, or sidebar content. The per-post option to show the original remains independent of the user's preferences. This PR temporarily retains `show_original_content` as a compatibility field computed from `automatically_translate`, keeping cached clients and rolling deployments safe. A follow-up PR will remove the legacy API and frontend compatibility code, then retire the old database column through the staged column-removal process.
722 lines
25 KiB
Ruby
Vendored
722 lines
25 KiB
Ruby
Vendored
# frozen_string_literal: true
|
||
|
||
RSpec.describe UserUpdater do
|
||
fab!(:user)
|
||
fab!(:u1, :user)
|
||
fab!(:u2, :user)
|
||
fab!(:u3, :user)
|
||
|
||
let(:acting_user) { Fabricate.build(:user) }
|
||
|
||
describe "#update_muted_users" do
|
||
it "has no cross talk" do
|
||
updater = UserUpdater.new(u1, u1)
|
||
updater.update_muted_users("#{u2.username},#{u3.username}")
|
||
|
||
updater = UserUpdater.new(u2, u2)
|
||
updater.update_muted_users("#{u3.username},#{u1.username}")
|
||
|
||
updater = UserUpdater.new(u3, u3)
|
||
updater.update_muted_users("")
|
||
|
||
expect(MutedUser.where(user_id: u2.id).pluck(:muted_user_id)).to match_array([u3.id, u1.id])
|
||
expect(MutedUser.where(user_id: u1.id).pluck(:muted_user_id)).to match_array([u2.id, u3.id])
|
||
expect(MutedUser.where(user_id: u3.id).count).to eq(0)
|
||
end
|
||
|
||
it "excludes acting user" do
|
||
updater = UserUpdater.new(u1, u1)
|
||
updater.update_muted_users("#{u1.username},#{u2.username}")
|
||
|
||
expect(MutedUser.where(muted_user_id: u2.id).pluck(:muted_user_id)).to match_array([u2.id])
|
||
end
|
||
end
|
||
|
||
describe "#update" do
|
||
fab!(:category)
|
||
fab!(:tag)
|
||
fab!(:tag2, :tag)
|
||
|
||
it "saves user" do
|
||
user = Fabricate(:user, name: "Billy Bob")
|
||
updater = UserUpdater.new(user, user)
|
||
|
||
updater.update(name: "Jim Tom")
|
||
|
||
expect(user.reload.name).to eq "Jim Tom"
|
||
end
|
||
|
||
it "keeps the interface locale among the user's understood languages" do
|
||
user.update!(locale: "en")
|
||
user.user_option.update!(understood_languages: ["en"])
|
||
|
||
UserUpdater.new(user, user).update(locale: "ja", understood_languages: [])
|
||
|
||
expect(user.reload.locale).to eq("ja")
|
||
expect(user.user_option.understood_languages).to eq(["ja"])
|
||
end
|
||
|
||
it "uses the effective interface locale when user locales are disabled" do
|
||
SiteSetting.default_locale = "en"
|
||
SiteSetting.allow_user_locale = false
|
||
user.update!(locale: "fr")
|
||
|
||
UserUpdater.new(user, user).update(understood_languages: [])
|
||
|
||
expect(user.user_option.understood_languages).to eq(["en"])
|
||
end
|
||
|
||
it "adapts legacy show-original updates to the positive preference" do
|
||
UserUpdater.new(user, user).update(show_original_content: true)
|
||
expect(user.reload.user_option.automatically_translate).to eq(false)
|
||
|
||
UserUpdater.new(user, user).update(show_original_content: true, automatically_translate: true)
|
||
expect(user.reload.user_option.automatically_translate).to eq(true)
|
||
end
|
||
|
||
describe "the within_user_updater_transaction event" do
|
||
it "allows plugins to perform additional updates" do
|
||
update_attributes = { name: "Jimmmy Johnny" }
|
||
handler =
|
||
Proc.new do |user, attrs|
|
||
user.user_profile.update!(bio_raw: "hello world I'm Jimmmy")
|
||
expect(attrs).to eq(update_attributes)
|
||
end
|
||
DiscourseEvent.on(:within_user_updater_transaction, &handler)
|
||
|
||
updater = UserUpdater.new(user, user)
|
||
updater.update(update_attributes)
|
||
|
||
expect(user.reload.name).to eq("Jimmmy Johnny")
|
||
expect(user.user_profile.bio_raw).to eq("hello world I'm Jimmmy")
|
||
ensure
|
||
DiscourseEvent.off(:within_user_updater_transaction, &handler)
|
||
end
|
||
|
||
it "can cancel the whole update transaction if a handler raises" do
|
||
error_class = Class.new(StandardError)
|
||
handler = Proc.new { raise error_class.new }
|
||
|
||
DiscourseEvent.on(:within_user_updater_transaction, &handler)
|
||
|
||
old_name = user.name
|
||
updater = UserUpdater.new(user, user)
|
||
|
||
expect { updater.update(name: "Failure McClario") }.to raise_error(error_class)
|
||
|
||
expect(user.reload.name).to eq(old_name)
|
||
ensure
|
||
DiscourseEvent.off(:within_user_updater_transaction, &handler)
|
||
end
|
||
end
|
||
|
||
it "can update categories and tags" do
|
||
updater = UserUpdater.new(user, user)
|
||
updater.update(watched_tags: "#{tag.name},#{tag2.name}", muted_category_ids: [category.id])
|
||
|
||
expect(
|
||
TagUser.where(
|
||
user_id: user.id,
|
||
tag_id: tag.id,
|
||
notification_level: TagUser.notification_levels[:watching],
|
||
).exists?,
|
||
).to eq(true)
|
||
|
||
expect(
|
||
TagUser.where(
|
||
user_id: user.id,
|
||
tag_id: tag2.id,
|
||
notification_level: TagUser.notification_levels[:watching],
|
||
).exists?,
|
||
).to eq(true)
|
||
|
||
expect(
|
||
CategoryUser.where(
|
||
user_id: user.id,
|
||
category_id: category.id,
|
||
notification_level: CategoryUser.notification_levels[:muted],
|
||
).count,
|
||
).to eq(1)
|
||
end
|
||
|
||
context "with a staged user" do
|
||
let(:staged_user) { Fabricate(:staged) }
|
||
|
||
context "when allow_changing_staged_user_tracking is false" do
|
||
before { SiteSetting.allow_changing_staged_user_tracking = false }
|
||
|
||
it "doesn't update muted categories and watched tags" do
|
||
updater = UserUpdater.new(Fabricate(:admin), staged_user)
|
||
updater.update(watched_tags: "#{tag.name}", muted_category_ids: [category.id])
|
||
expect(TagUser.exists?(user_id: staged_user.id)).to eq(false)
|
||
expect(CategoryUser.exists?(user_id: staged_user.id)).to eq(false)
|
||
end
|
||
end
|
||
|
||
context "when allow_changing_staged_user_tracking is true" do
|
||
before { SiteSetting.allow_changing_staged_user_tracking = true }
|
||
|
||
it "updates muted categories and watched tags" do
|
||
updater = UserUpdater.new(Fabricate(:admin), staged_user)
|
||
updater.update(watched_tags: "#{tag.name}", muted_category_ids: [category.id])
|
||
expect(
|
||
TagUser.exists?(
|
||
user_id: staged_user.id,
|
||
tag_id: tag.id,
|
||
notification_level: TagUser.notification_levels[:watching],
|
||
),
|
||
).to eq(true)
|
||
|
||
expect(
|
||
CategoryUser.exists?(
|
||
user_id: staged_user.id,
|
||
category_id: category.id,
|
||
notification_level: CategoryUser.notification_levels[:muted],
|
||
),
|
||
).to eq(true)
|
||
end
|
||
end
|
||
end
|
||
|
||
it "doesn't remove notification prefs when updating something else" do
|
||
TagUser.create!(
|
||
user: user,
|
||
tag: tag,
|
||
notification_level: TagUser.notification_levels[:watching],
|
||
)
|
||
CategoryUser.create!(
|
||
user: user,
|
||
category: category,
|
||
notification_level: CategoryUser.notification_levels[:muted],
|
||
)
|
||
|
||
updater = UserUpdater.new(acting_user, user)
|
||
updater.update(name: "Steve Dave")
|
||
|
||
expect(TagUser.where(user: user).count).to eq(1)
|
||
expect(CategoryUser.where(user: user).count).to eq(1)
|
||
end
|
||
|
||
it "updates various fields" do
|
||
updater = UserUpdater.new(acting_user, user)
|
||
date_of_birth = Time.zone.now
|
||
SiteSetting.disable_mailing_list_mode = false
|
||
|
||
theme = Fabricate(:theme, user_selectable: true)
|
||
|
||
seq = user.user_option.theme_key_seq
|
||
|
||
val =
|
||
updater.update(
|
||
bio_raw: "my new bio",
|
||
email_level: UserOption.email_level_types[:always],
|
||
mailing_list_mode: true,
|
||
digest_after_minutes: "45",
|
||
new_topic_duration_minutes: 100,
|
||
auto_track_topics_after_msecs: 101,
|
||
notification_level_when_replying: 3,
|
||
email_in_reply_to: false,
|
||
date_of_birth: date_of_birth,
|
||
theme_ids: [theme.id],
|
||
allow_private_messages: false,
|
||
)
|
||
|
||
expect(val).to be_truthy
|
||
|
||
user.reload
|
||
|
||
expect(user.user_profile.bio_raw).to eq "my new bio"
|
||
expect(user.user_option.email_level).to eq UserOption.email_level_types[:always]
|
||
expect(user.user_option.mailing_list_mode).to eq true
|
||
expect(user.user_option.digest_after_minutes).to eq 45
|
||
expect(user.user_option.new_topic_duration_minutes).to eq 100
|
||
expect(user.user_option.auto_track_topics_after_msecs).to eq 101
|
||
expect(user.user_option.notification_level_when_replying).to eq 3
|
||
expect(user.user_option.email_in_reply_to).to eq false
|
||
expect(user.user_option.theme_ids.first).to eq theme.id
|
||
expect(user.user_option.theme_key_seq).to eq(seq + 1)
|
||
expect(user.user_option.allow_private_messages).to eq(false)
|
||
expect(user.date_of_birth).to eq(date_of_birth.to_date)
|
||
end
|
||
|
||
it "allows user to update profile header when the user has required group" do
|
||
user = Fabricate(:user, trust_level: TrustLevel[2])
|
||
updater = UserUpdater.new(user, user)
|
||
upload = Fabricate(:upload)
|
||
SiteSetting.profile_background_allowed_groups = Group::AUTO_GROUPS[:trust_level_2]
|
||
val = updater.update(profile_background_upload_url: upload.url)
|
||
expect(val).to be_truthy
|
||
user.reload
|
||
expect(user.profile_background_upload).to eq(upload)
|
||
success = updater.update(profile_background_upload_url: "")
|
||
expect(success).to eq(true)
|
||
user.reload
|
||
expect(user.profile_background_upload).to eq(nil)
|
||
end
|
||
|
||
it "allows user to update user card background when the user has required group" do
|
||
user = Fabricate(:user, trust_level: TrustLevel[2])
|
||
updater = UserUpdater.new(user, user)
|
||
upload = Fabricate(:upload)
|
||
SiteSetting.user_card_background_allowed_groups = Group::AUTO_GROUPS[:trust_level_2]
|
||
val = updater.update(card_background_upload_url: upload.url)
|
||
expect(val).to be_truthy
|
||
user.reload
|
||
expect(user.card_background_upload).to eq(upload)
|
||
success = updater.update(card_background_upload_url: "")
|
||
expect(success).to eq(true)
|
||
user.reload
|
||
expect(user.card_background_upload).to eq(nil)
|
||
end
|
||
|
||
it "disables email_digests when enabling mailing_list_mode" do
|
||
updater = UserUpdater.new(acting_user, user)
|
||
SiteSetting.disable_mailing_list_mode = false
|
||
|
||
val = updater.update(mailing_list_mode: true, email_digests: true)
|
||
expect(val).to be_truthy
|
||
|
||
user.reload
|
||
|
||
expect(user.user_option.email_digests).to eq false
|
||
expect(user.user_option.mailing_list_mode).to eq true
|
||
end
|
||
|
||
it "filters theme_ids blank values before updating preferences" do
|
||
user.user_option.update!(theme_ids: [1])
|
||
updater = UserUpdater.new(acting_user, user)
|
||
|
||
updater.update(theme_ids: [""])
|
||
user.reload
|
||
expect(user.user_option.theme_ids).to eq([])
|
||
|
||
updater.update(theme_ids: [nil])
|
||
user.reload
|
||
expect(user.user_option.theme_ids).to eq([])
|
||
|
||
theme = Fabricate(:theme)
|
||
child = Fabricate(:theme, component: true)
|
||
theme.add_relative_theme!(:child, child)
|
||
theme.set_default!
|
||
|
||
updater.update(theme_ids: [theme.id.to_s, child.id.to_s, "", nil])
|
||
user.reload
|
||
expect(user.user_option.theme_ids).to eq([theme.id, child.id])
|
||
end
|
||
|
||
let(:schedule_attrs) do
|
||
{
|
||
enabled: true,
|
||
day_0_start_time: 30,
|
||
day_0_end_time: 60,
|
||
day_1_start_time: 30,
|
||
day_1_end_time: 60,
|
||
day_2_start_time: 30,
|
||
day_2_end_time: 60,
|
||
day_3_start_time: 30,
|
||
day_3_end_time: 60,
|
||
day_4_start_time: 30,
|
||
day_4_end_time: 60,
|
||
day_5_start_time: 30,
|
||
day_5_end_time: 60,
|
||
day_6_start_time: 30,
|
||
day_6_end_time: 60,
|
||
}
|
||
end
|
||
|
||
context "with user_notification_schedule" do
|
||
it "allows users to create their notification schedule when it doesn't exist previously" do
|
||
expect(user.user_notification_schedule).to be_nil
|
||
updater = UserUpdater.new(acting_user, user)
|
||
|
||
updater.update(user_notification_schedule: schedule_attrs)
|
||
user.reload
|
||
expect(user.user_notification_schedule.enabled).to eq(true)
|
||
expect(user.user_notification_schedule.day_0_start_time).to eq(30)
|
||
expect(user.user_notification_schedule.day_0_end_time).to eq(60)
|
||
expect(user.user_notification_schedule.day_6_start_time).to eq(30)
|
||
expect(user.user_notification_schedule.day_6_end_time).to eq(60)
|
||
end
|
||
|
||
it "allows users to update their notification schedule" do
|
||
UserNotificationSchedule.create({ user: user }.merge(UserNotificationSchedule::DEFAULT))
|
||
updater = UserUpdater.new(acting_user, user)
|
||
updater.update(user_notification_schedule: schedule_attrs)
|
||
user.reload
|
||
expect(user.user_notification_schedule.enabled).to eq(true)
|
||
expect(user.user_notification_schedule.day_0_start_time).to eq(30)
|
||
expect(user.user_notification_schedule.day_0_end_time).to eq(60)
|
||
expect(user.user_notification_schedule.day_6_start_time).to eq(30)
|
||
expect(user.user_notification_schedule.day_6_end_time).to eq(60)
|
||
end
|
||
|
||
it "processes the schedule and do_not_disturb_timings are created" do
|
||
updater = UserUpdater.new(acting_user, user)
|
||
|
||
expect { updater.update(user_notification_schedule: schedule_attrs) }.to change {
|
||
user.do_not_disturb_timings.count
|
||
}.by(4)
|
||
end
|
||
|
||
it "removes do_not_disturb_timings when the schedule is disabled" do
|
||
updater = UserUpdater.new(acting_user, user)
|
||
updater.update(user_notification_schedule: schedule_attrs)
|
||
expect(user.user_notification_schedule.enabled).to eq(true)
|
||
|
||
schedule_attrs[:enabled] = false
|
||
updater.update(user_notification_schedule: schedule_attrs)
|
||
|
||
expect(user.user_notification_schedule.enabled).to eq(false)
|
||
expect(user.do_not_disturb_timings.count).to eq(0)
|
||
end
|
||
end
|
||
|
||
context "when sso overrides bio" do
|
||
it "does not change bio" do
|
||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||
SiteSetting.discourse_connect_secret = "x" * 10
|
||
SiteSetting.enable_discourse_connect = true
|
||
SiteSetting.discourse_connect_overrides_bio = true
|
||
|
||
updater = UserUpdater.new(acting_user, user)
|
||
|
||
expect(updater.update(bio_raw: "new bio")).to be_truthy
|
||
|
||
user.reload
|
||
expect(user.user_profile.bio_raw).not_to eq "new bio"
|
||
end
|
||
end
|
||
|
||
context "when sso overrides location" do
|
||
it "does not change location" do
|
||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||
SiteSetting.discourse_connect_secret = "x" * 10
|
||
SiteSetting.enable_discourse_connect = true
|
||
SiteSetting.discourse_connect_overrides_location = true
|
||
|
||
updater = UserUpdater.new(acting_user, user)
|
||
|
||
expect(updater.update(location: "new location")).to be_truthy
|
||
|
||
user.reload
|
||
expect(user.user_profile.location).not_to eq "new location"
|
||
end
|
||
end
|
||
|
||
context "when sso overrides website" do
|
||
it "does not change website" do
|
||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||
SiteSetting.discourse_connect_secret = "x" * 10
|
||
SiteSetting.enable_discourse_connect = true
|
||
SiteSetting.discourse_connect_overrides_website = true
|
||
|
||
updater = UserUpdater.new(acting_user, user)
|
||
|
||
expect(updater.update(website: "https://google.com")).to be_truthy
|
||
|
||
user.reload
|
||
expect(user.user_profile.website).not_to eq "https://google.com"
|
||
end
|
||
end
|
||
|
||
context "when updating primary group" do
|
||
let(:new_group) { Group.create(name: "new_group") }
|
||
|
||
it "updates when setting is enabled" do
|
||
SiteSetting.user_selected_primary_groups = true
|
||
user.groups << new_group
|
||
user.update(primary_group_id: nil)
|
||
UserUpdater.new(acting_user, user).update(primary_group_id: new_group.id)
|
||
|
||
user.reload
|
||
expect(user.primary_group_id).to eq new_group.id
|
||
end
|
||
|
||
it "does not update when setting is disabled" do
|
||
SiteSetting.user_selected_primary_groups = false
|
||
user.groups << new_group
|
||
user.update(primary_group_id: nil)
|
||
UserUpdater.new(acting_user, user).update(primary_group_id: new_group.id)
|
||
|
||
user.reload
|
||
expect(user.primary_group_id).to eq nil
|
||
end
|
||
|
||
it "does not update when changing other profile data" do
|
||
SiteSetting.user_selected_primary_groups = true
|
||
user.groups << new_group
|
||
user.update(primary_group_id: new_group.id)
|
||
UserUpdater.new(acting_user, user).update(website: "http://example.com")
|
||
|
||
user.reload
|
||
expect(user.primary_group_id).to eq new_group.id
|
||
end
|
||
|
||
it "can be removed by the user when setting is enabled" do
|
||
SiteSetting.user_selected_primary_groups = true
|
||
user.groups << new_group
|
||
user.update(primary_group_id: new_group.id)
|
||
UserUpdater.new(acting_user, user).update(primary_group_id: "")
|
||
|
||
user.reload
|
||
expect(user.primary_group_id).to eq nil
|
||
end
|
||
|
||
it "cannot be removed by the user when setting is disabled" do
|
||
SiteSetting.user_selected_primary_groups = false
|
||
user.groups << new_group
|
||
user.update(primary_group_id: new_group.id)
|
||
UserUpdater.new(acting_user, user).update(primary_group_id: "")
|
||
|
||
user.reload
|
||
expect(user.primary_group_id).to eq new_group.id
|
||
end
|
||
end
|
||
|
||
context "when updating flair group" do
|
||
let(:group) do
|
||
Fabricate(
|
||
:group,
|
||
name: "Group",
|
||
flair_bg_color: "#111111",
|
||
flair_color: "#999999",
|
||
flair_icon: "icon",
|
||
)
|
||
end
|
||
|
||
it "updates when setting is enabled" do
|
||
group.add(user)
|
||
|
||
UserUpdater.new(acting_user, user).update(flair_group_id: group.id)
|
||
expect(user.reload.flair_group_id).to eq(group.id)
|
||
|
||
UserUpdater.new(acting_user, user).update(flair_group_id: "")
|
||
expect(user.reload.flair_group_id).to eq(nil)
|
||
end
|
||
end
|
||
|
||
context "when update fails" do
|
||
it "returns false" do
|
||
user.stubs(save: false)
|
||
updater = UserUpdater.new(acting_user, user)
|
||
|
||
expect(updater.update).to be_falsey
|
||
end
|
||
end
|
||
|
||
context "with permission to update title" do
|
||
it "allows user to change title" do
|
||
user = Fabricate(:user, title: "Emperor")
|
||
Guardian.any_instance.stubs(:can_grant_title?).with(user, "Minion").returns(true)
|
||
updater = UserUpdater.new(acting_user, user)
|
||
|
||
updater.update(title: "Minion")
|
||
|
||
expect(user.reload.title).to eq "Minion"
|
||
end
|
||
end
|
||
|
||
context "when title is from a badge" do
|
||
fab!(:user) { Fabricate(:user, title: "Emperor") }
|
||
fab!(:badge) { Fabricate(:badge, name: "Minion") }
|
||
|
||
context "when badge can be used as a title" do
|
||
before { badge.update(allow_title: true) }
|
||
|
||
it "can use as title, sets granted_title_badge_id" do
|
||
BadgeGranter.grant(badge, user)
|
||
updater = UserUpdater.new(user, user)
|
||
updater.update(title: badge.name)
|
||
user.reload
|
||
expect(user.user_profile.granted_title_badge_id).to eq(badge.id)
|
||
end
|
||
|
||
it "badge has not been granted, does not change title" do
|
||
badge.update(allow_title: true)
|
||
updater = UserUpdater.new(user, user)
|
||
updater.update(title: badge.name)
|
||
user.reload
|
||
expect(user.title).not_to eq(badge.name)
|
||
expect(user.user_profile.granted_title_badge_id).to be_nil
|
||
end
|
||
|
||
it "changing to a title that is not from a badge, unsets granted_title_badge_id" do
|
||
user.update(title: badge.name)
|
||
user.user_profile.update(granted_title_badge_id: badge.id)
|
||
|
||
Guardian.any_instance.stubs(:can_grant_title?).with(user, "Dancer").returns(true)
|
||
|
||
updater = UserUpdater.new(user, user)
|
||
updater.update(title: "Dancer")
|
||
user.reload
|
||
expect(user.title).to eq("Dancer")
|
||
expect(user.user_profile.granted_title_badge_id).to be_nil
|
||
end
|
||
end
|
||
|
||
it "cannot use as title, does not change title" do
|
||
BadgeGranter.grant(badge, user)
|
||
updater = UserUpdater.new(user, user)
|
||
updater.update(title: badge.name)
|
||
user.reload
|
||
expect(user.title).not_to eq(badge.name)
|
||
expect(user.user_profile.granted_title_badge_id).to be_nil
|
||
end
|
||
end
|
||
|
||
context "without permission to update title" do
|
||
it "does not allow user to change title" do
|
||
user = Fabricate(:user, title: "Emperor")
|
||
Guardian.any_instance.stubs(:can_grant_title?).with(user, "Minion").returns(false)
|
||
updater = UserUpdater.new(acting_user, user)
|
||
|
||
updater.update(title: "Minion")
|
||
|
||
expect(user.reload.title).not_to eq "Minion"
|
||
end
|
||
end
|
||
|
||
context "when website includes http" do
|
||
it "does not add http before updating" do
|
||
updater = UserUpdater.new(acting_user, user)
|
||
|
||
updater.update(website: "http://example.com")
|
||
|
||
expect(user.reload.user_profile.website).to eq "http://example.com"
|
||
end
|
||
end
|
||
|
||
context "when website does not include http" do
|
||
it "adds http before updating if no scheme" do
|
||
updater = UserUpdater.new(acting_user, user)
|
||
|
||
updater.update(website: "example.com")
|
||
|
||
expect(user.reload.user_profile.website).to eq "http://example.com"
|
||
end
|
||
|
||
it "returns an error for non-http scheme" do
|
||
updater = UserUpdater.new(acting_user, user)
|
||
|
||
expect(updater.update(website: "ftp://example.com")).to eq false
|
||
expect(updater.update(website: "file://example.com")).to eq false
|
||
expect(updater.update(website: "mailto://example.com")).to eq false
|
||
expect(updater.update(website: "something://example.com")).to eq false
|
||
end
|
||
end
|
||
|
||
context "when website includes http but with uppercase" do
|
||
it "does not add an additional http:// before" do
|
||
updater = UserUpdater.new(acting_user, user)
|
||
updater.update(website: "Http://example.com")
|
||
expect(user.reload.user_profile.website).to eq "Http://example.com"
|
||
updater.update(website: "hTtp://example.com")
|
||
expect(user.reload.user_profile.website).to eq "hTtp://example.com"
|
||
updater.update(website: "HTTP://example.com")
|
||
expect(user.reload.user_profile.website).to eq "HTTP://example.com"
|
||
updater.update(website: "HttpS://example.com")
|
||
expect(user.reload.user_profile.website).to eq "HttpS://example.com"
|
||
end
|
||
end
|
||
|
||
context "when website is invalid" do
|
||
it "returns an error" do
|
||
updater = UserUpdater.new(acting_user, user)
|
||
|
||
expect(updater.update(website: "ʔ<")).to eq false
|
||
expect(updater.update(website: "http://bad-domain-no-period")).to eq false
|
||
end
|
||
end
|
||
|
||
context "when custom_fields is empty string" do
|
||
it "update is successful" do
|
||
user.custom_fields = { "import_username" => "my_old_username" }
|
||
user.save
|
||
updater = UserUpdater.new(acting_user, user)
|
||
|
||
updater.update(website: "example.com", custom_fields: "")
|
||
expect(user.reload.custom_fields).to eq("import_username" => "my_old_username")
|
||
end
|
||
end
|
||
|
||
context "when skip_new_user_tips is edited" do
|
||
it "updates seen_popups too" do
|
||
UserUpdater.new(Discourse.system_user, user).update(skip_new_user_tips: true)
|
||
|
||
expect(user.user_option.skip_new_user_tips).to eq(true)
|
||
expect(user.user_option.seen_popups).to eq([-1])
|
||
end
|
||
|
||
it "does not reset seen_popups" do
|
||
user.user_option.update!(seen_popups: [1, 2, 3])
|
||
|
||
UserUpdater.new(Discourse.system_user, user).update(skip_new_user_tips: false)
|
||
|
||
expect(user.user_option.skip_new_user_tips).to eq(false)
|
||
expect(user.user_option.seen_popups).to eq([1, 2, 3])
|
||
end
|
||
end
|
||
|
||
context "when updating the name" do
|
||
it "logs the action" do
|
||
user = Fabricate(:user, name: "Billy Bob")
|
||
|
||
expect do UserUpdater.new(user, user).update(name: "Jim Tom") end.to change {
|
||
UserHistory.count
|
||
}.by(1)
|
||
|
||
expect(UserHistory.last.action).to eq(UserHistory.actions[:change_name])
|
||
|
||
expect do UserUpdater.new(user, user).update(name: "JiM TOm") end.to_not change {
|
||
UserHistory.count
|
||
}
|
||
|
||
expect do UserUpdater.new(user, user).update(bio_raw: "foo bar") end.to_not change {
|
||
UserHistory.count
|
||
}
|
||
|
||
user_without_name = Fabricate(:user, name: nil)
|
||
|
||
expect do
|
||
UserUpdater.new(user_without_name, user_without_name).update(bio_raw: "foo bar")
|
||
end.to_not change { UserHistory.count }
|
||
|
||
expect do
|
||
UserUpdater.new(user_without_name, user_without_name).update(name: "Jim Tom")
|
||
end.to change { UserHistory.count }.by(1)
|
||
|
||
expect(UserHistory.last.action).to eq(UserHistory.actions[:change_name])
|
||
|
||
expect do UserUpdater.new(user, user).update(name: "") end.to change {
|
||
UserHistory.count
|
||
}.by(1)
|
||
|
||
expect(UserHistory.last.action).to eq(UserHistory.actions[:change_name])
|
||
end
|
||
end
|
||
|
||
context "when updating required fields" do
|
||
it "logs the action" do
|
||
user = Fabricate(:user)
|
||
Fabricate(:user_field, name: "favorite_pokemon", requirement: "for_all_users")
|
||
|
||
UserRequiredFieldsVersion.create!
|
||
|
||
expect do
|
||
UserUpdater.new(user, user).update(custom_fields: { "favorite_pokemon" => "Mudkip" })
|
||
end.to change { UserHistory.count }.by(1)
|
||
|
||
user.bump_required_fields_version
|
||
|
||
expect do
|
||
UserUpdater.new(user, user).update(custom_fields: { "favorite_pokemon" => "Mudkip" })
|
||
end.not_to change { UserHistory.count }
|
||
end
|
||
end
|
||
|
||
it "clears the homepage_id when the special 'custom' id is chosen" do
|
||
UserUpdater.new(user, user).update(homepage_id: "-1")
|
||
expect(user.user_option.homepage_id).to eq(nil)
|
||
end
|
||
end
|
||
end
|