-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Complex unrefactored Process object - Basic test that does 100% coverage - dependencies file that stubs external dependencies - Gemfile
- Loading branch information
Bohdan Pohorilets
committed
Apr 20, 2018
1 parent
ab057ad
commit a8bf624
Showing
5 changed files
with
345 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
source 'https://rubygems.org' | ||
gem 'rspec' | ||
gem 'rspec-mocks' | ||
gem 'activesupport' | ||
gem 'activemodel' | ||
gem 'simplecov' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
GEM | ||
remote: https://rubygems.org/ | ||
specs: | ||
activemodel (5.1.5) | ||
activesupport (= 5.1.5) | ||
activesupport (5.1.5) | ||
concurrent-ruby (~> 1.0, >= 1.0.2) | ||
i18n (~> 0.7) | ||
minitest (~> 5.1) | ||
tzinfo (~> 1.1) | ||
concurrent-ruby (1.0.5) | ||
diff-lcs (1.3) | ||
i18n (0.9.5) | ||
concurrent-ruby (~> 1.0) | ||
minitest (5.11.3) | ||
rspec (3.7.0) | ||
rspec-core (~> 3.7.0) | ||
rspec-expectations (~> 3.7.0) | ||
rspec-mocks (~> 3.7.0) | ||
rspec-core (3.7.1) | ||
rspec-support (~> 3.7.0) | ||
rspec-expectations (3.7.0) | ||
diff-lcs (>= 1.2.0, < 2.0) | ||
rspec-support (~> 3.7.0) | ||
rspec-mocks (3.7.0) | ||
diff-lcs (>= 1.2.0, < 2.0) | ||
rspec-support (~> 3.7.0) | ||
rspec-support (3.7.1) | ||
thread_safe (0.3.6) | ||
tzinfo (1.2.5) | ||
thread_safe (~> 0.1) | ||
|
||
PLATFORMS | ||
ruby | ||
|
||
DEPENDENCIES | ||
activemodel | ||
activesupport | ||
rspec | ||
rspec-mocks | ||
|
||
BUNDLED WITH | ||
1.16.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
class StaffActionLogger | ||
def initialize(*) | ||
true | ||
end | ||
|
||
def log_name_change(*) | ||
true | ||
end | ||
end | ||
|
||
class User | ||
include ::ActiveModel::Model | ||
attr_accessor :date_of_birth | ||
attr_accessor :name | ||
attr_accessor :user_profile | ||
attr_accessor :locale | ||
attr_accessor :title | ||
attr_accessor :user_option | ||
attr_accessor :custom_fields | ||
|
||
def id | ||
1 | ||
end | ||
|
||
def reload | ||
self | ||
end | ||
|
||
def save | ||
true | ||
end | ||
|
||
def custom_fields | ||
{} | ||
end | ||
|
||
def self.transaction | ||
yield | ||
end | ||
end | ||
|
||
class UserProfile | ||
attr_accessor :card_background | ||
attr_accessor :location | ||
attr_accessor :profile_background | ||
attr_accessor :website | ||
attr_accessor :bio_raw | ||
|
||
def save | ||
true | ||
end | ||
|
||
def website | ||
'http://www.example.com' | ||
end | ||
end | ||
|
||
class Guardian | ||
attr_accessor :user | ||
private | ||
|
||
def initialize(user) | ||
@user = user | ||
end | ||
end | ||
|
||
class SiteSetting | ||
cattr_accessor :sso_url | ||
cattr_writer :enable_sso | ||
cattr_writer :sso_overrides_bio | ||
|
||
def self.enable_sso | ||
@enable_sso || true | ||
end | ||
|
||
def self.sso_overrides_bio | ||
@sso_overrides_bio || false | ||
end | ||
end | ||
|
||
class UserUpdater | ||
CATEGORY_IDS = { | ||
watched_first_post_category_ids: :watching_first_post, | ||
watched_category_ids: :watching, | ||
tracked_category_ids: :tracking, | ||
muted_category_ids: :muted | ||
} | ||
|
||
TAG_NAMES = { | ||
watching_first_post_tags: :watching_first_post, | ||
watched_tags: :watching, | ||
tracked_tags: :tracking, | ||
muted_tags: :muted | ||
} | ||
|
||
OPTION_ATTR = [ | ||
:email_always, | ||
:mailing_list_mode, | ||
:mailing_list_mode_frequency, | ||
:email_digests, | ||
:email_direct, | ||
:email_private_messages, | ||
:external_links_in_new_tab, | ||
:enable_quoting, | ||
:dynamic_favicon, | ||
:disable_jump_reply, | ||
:automatically_unpin_topics, | ||
:digest_after_minutes, | ||
:new_topic_duration_minutes, | ||
:auto_track_topics_after_msecs, | ||
:notification_level_when_replying, | ||
:email_previous_replies, | ||
:email_in_reply_to, | ||
:like_notification_frequency, | ||
:include_tl0_in_digests, | ||
:theme_key, | ||
:allow_private_messages, | ||
:homepage_id, | ||
] | ||
|
||
def can_grant_title?(user) | ||
true | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
require 'active_support' | ||
require 'active_support/core_ext/object/blank' | ||
require 'active_support/core_ext/time/calculations' | ||
require 'active_model' | ||
|
||
require_relative 'dependencies' | ||
|
||
class UserUpdater | ||
delegate :change_post_owner, to: :guardian | ||
|
||
def update(attributes = {}) | ||
save_options = false | ||
saved = nil | ||
old_user_name = user.name.present? ? user.name : "" | ||
|
||
user_profile = user.user_profile | ||
user_profile.location = attributes.fetch(:location) { user_profile.location } | ||
user_profile.dismissed_banner_key = attributes[:dismissed_banner_key] if attributes[:dismissed_banner_key].present? | ||
user_profile.website = format_url(attributes.fetch(:website) { user_profile.website }) | ||
user_profile.profile_background = attributes.fetch(:profile_background) { user_profile.profile_background } | ||
user_profile.card_background = attributes.fetch(:card_background) { user_profile.card_background } | ||
if SiteSetting.enable_sso && !SiteSetting.sso_overrides_bio | ||
user_profile.bio_raw = attributes.fetch(:bio_raw) { user_profile.bio_raw } | ||
end | ||
|
||
user.name = attributes.fetch(:name) { user.name } | ||
user.locale = attributes.fetch(:locale) { user.locale } | ||
user.date_of_birth = attributes.fetch(:date_of_birth) { user.date_of_birth } | ||
if can_grant_title?(user) | ||
user.title = attributes.fetch(:title) { user.title } | ||
end | ||
|
||
# special handling for theme_key cause we need to bump a sequence number | ||
if attributes.key?(:theme_key) && user.user_option.theme_key != attributes[:theme_key] | ||
user.user_option.theme_key_seq += 1 | ||
end | ||
|
||
OPTION_ATTR.each do |attribute| | ||
if attributes.key?(attribute) | ||
save_options = true | ||
|
||
if [true, false].include?(user.user_option.send(attribute)) | ||
val = attributes[attribute].to_s == 'true' | ||
user.user_option.send("#{attribute}=", val) | ||
else | ||
user.user_option.send("#{attribute}=", attributes[attribute]) | ||
end | ||
end | ||
end | ||
|
||
# automatically disable digests when mailing_list_mode is enabled | ||
user.user_option.email_digests = false if user.user_option.mailing_list_mode | ||
|
||
fields = attributes[:custom_fields] | ||
if fields.present? | ||
user.custom_fields = user.custom_fields.merge(fields) | ||
end | ||
|
||
User.transaction do | ||
if user.user_option.save && user_profile.save && user.save | ||
StaffActionLogger.new(@actor).log_name_change( | ||
user.id, | ||
old_user_name, | ||
attributes.fetch(:name) { '' } | ||
) | ||
|
||
saved = true | ||
end | ||
end | ||
|
||
saved | ||
end | ||
|
||
private | ||
|
||
attr_reader :user, :guardian | ||
|
||
def initialize(actor, user, guardian = Guardian.new(actor)) | ||
@user = user | ||
@guardian = guardian | ||
@actor = actor | ||
end | ||
|
||
def format_url(website) | ||
return nil if website.blank? | ||
website =~ /^http/ ? website : "http://#{website}" | ||
end | ||
end |
84 changes: 84 additions & 0 deletions
84
samples/two_level_deep_service_objects/user_updater_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
require 'simplecov' | ||
SimpleCov.start | ||
|
||
require_relative 'user_updater' | ||
|
||
describe UserUpdater do | ||
let( :acting_user ) { User.new( name: 'Acting User', user_profile: UserProfile.new ) } | ||
|
||
describe '#update' do | ||
it 'saves user' do | ||
user = User.new( name: 'Billy Bob', user_profile: UserProfile.new, user_option: spy( email_always: true ) ) | ||
|
||
updater = UserUpdater.new( acting_user, user ) | ||
updater.update( name: 'Jim Tom' ) | ||
|
||
expect( user.reload.name ).to eq 'Jim Tom' | ||
end | ||
|
||
it 'updates various fields' do | ||
user = User.new( name: 'Billy Bob', user_profile: UserProfile.new, user_option: spy( email_always: true ) ) | ||
updater = UserUpdater.new(acting_user, user) | ||
date_of_birth = Time.current | ||
|
||
val = updater.update(bio_raw: 'my new bio', | ||
email_always: 'true', | ||
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_key: 'theme.key', | ||
custom_fields: { one: :two }, | ||
allow_private_messages: false) | ||
|
||
expect(val).to be_truthy | ||
|
||
user.reload | ||
|
||
expect(user.user_profile.bio_raw).to eq 'my new bio' | ||
end | ||
|
||
it "disables email_digests when enabling mailing_list_mode" do | ||
user = User.new( name: 'Billy Bob', user_profile: UserProfile.new, user_option: spy( email_always: true ) ) | ||
updater = UserUpdater.new(acting_user, user) | ||
|
||
val = updater.update(mailing_list_mode: true, email_digests: true) | ||
expect(val).to be_truthy | ||
|
||
user.reload | ||
|
||
expect(user.user_option).to have_received(:mailing_list_mode=). | ||
with( true ) | ||
end | ||
|
||
context 'when sso overrides bio' do | ||
it 'changes bio' do | ||
SiteSetting.sso_url = "https://www.example.com/sso" | ||
SiteSetting.enable_sso = true | ||
SiteSetting.sso_overrides_bio = true | ||
|
||
user = User.new( name: 'Billy Bob', user_profile: UserProfile.new, user_option: spy( email_always: 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).to eq 'new bio' | ||
end | ||
end | ||
|
||
context 'when update fails' do | ||
it 'returns false' do | ||
user = User.new( name: 'Billy Bob', user_profile: UserProfile.new, user_option: spy( email_always: true ) ) | ||
allow(user).to receive( :save ). | ||
and_return( false ) | ||
updater = UserUpdater.new(acting_user, user) | ||
|
||
expect(updater.update).to be_falsey | ||
end | ||
end | ||
end | ||
end |