Skip to content

Commit 77b59b5

Browse files
committed
Refactor UsersController#invited
* Add test coverage * Simplify controller action * Move finder code to Invite class
1 parent e5fd294 commit 77b59b5

5 files changed

Lines changed: 215 additions & 24 deletions

File tree

app/controllers/users_controller.rb

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -66,29 +66,17 @@ def preferences
6666
end
6767

6868
def invited
69-
params.require(:username)
70-
params.permit(:filter)
71-
72-
by_user = fetch_user_from_params
73-
74-
invited = Invite.where(invited_by_id: by_user.id)
75-
.includes(:user => :user_stat)
76-
.order('CASE WHEN invites.user_id IS NOT NULL THEN 0 ELSE 1 END',
77-
'user_stats.time_read DESC',
78-
'invites.redeemed_at DESC')
79-
.limit(SiteSetting.invites_shown)
80-
.references('user_stats')
69+
inviter = fetch_user_from_params
8170

82-
unless guardian.can_see_pending_invites_from?(by_user)
83-
invited = invited.where('invites.user_id IS NOT NULL')
71+
invites = if guardian.can_see_pending_invites_from?(inviter)
72+
Invite.find_all_invites_from(inviter)
73+
else
74+
Invite.find_redeemed_invites_from(inviter)
8475
end
8576

86-
if params[:filter].present?
87-
invited = invited.where('(LOWER(invites.email) LIKE :filter) or (LOWER(users.username) LIKE :filter)', filter: "%#{params[:filter].downcase}%")
88-
.references(:users)
89-
end
77+
invites = invites.filter_by(params[:filter])
9078

91-
render_serialized(invited.to_a, InviteSerializer)
79+
render_serialized(invites.to_a, InviteSerializer)
9280
end
9381

9482
def is_local_username

app/models/invite.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,30 @@ def self.invite_by_email(email, invited_by, topic=nil)
6868
invite
6969
end
7070

71+
def self.find_all_invites_from(inviter)
72+
Invite.where(invited_by_id: inviter.id)
73+
.includes(:user => :user_stat)
74+
.order('CASE WHEN invites.user_id IS NOT NULL THEN 0 ELSE 1 END',
75+
'user_stats.time_read DESC',
76+
'invites.redeemed_at DESC')
77+
.limit(SiteSetting.invites_shown)
78+
.references('user_stats')
79+
end
80+
81+
def self.find_redeemed_invites_from(inviter)
82+
find_all_invites_from(inviter).where('invites.user_id IS NOT NULL')
83+
end
84+
85+
def self.filter_by(email_or_username)
86+
if email_or_username
87+
where(
88+
'(LOWER(invites.email) LIKE :filter) or (LOWER(users.username) LIKE :filter)',
89+
filter: "%#{email_or_username.downcase}%"
90+
)
91+
else
92+
scoped
93+
end
94+
end
7195
end
7296

7397
# == Schema Information

spec/controllers/users_controller_spec.rb

Lines changed: 132 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -813,15 +813,142 @@ def post_user
813813
end
814814
end
815815

816-
describe '.invited' do
817-
818-
let(:user) { Fabricate(:user) }
819-
816+
describe '#invited' do
820817
it 'returns success' do
818+
user = Fabricate(:user)
819+
821820
xhr :get, :invited, username: user.username
822-
response.should be_success
821+
822+
expect(response).to be_success
823+
end
824+
825+
it 'filters by email' do
826+
inviter = Fabricate(:user)
827+
invitee = Fabricate(:user)
828+
invite = Fabricate(
829+
:invite,
830+
email: 'billybob@example.com',
831+
invited_by: inviter,
832+
user: invitee
833+
)
834+
Fabricate(
835+
:invite,
836+
email: 'jimtom@example.com',
837+
invited_by: inviter,
838+
user: invitee
839+
)
840+
841+
xhr :get, :invited, username: inviter.username, filter: 'billybob'
842+
843+
invites = JSON.parse(response.body)
844+
expect(invites).to have(1).item
845+
expect(invites.first).to include('email' => 'billybob@example.com')
846+
end
847+
848+
it 'filters by username' do
849+
inviter = Fabricate(:user)
850+
invitee = Fabricate(:user, username: 'billybob')
851+
invite = Fabricate(
852+
:invite,
853+
invited_by: inviter,
854+
email: 'billybob@example.com',
855+
user: invitee
856+
)
857+
Fabricate(
858+
:invite,
859+
invited_by: inviter,
860+
user: Fabricate(:user, username: 'jimtom')
861+
)
862+
863+
xhr :get, :invited, username: inviter.username, filter: 'billybob'
864+
865+
invites = JSON.parse(response.body)
866+
expect(invites).to have(1).item
867+
expect(invites.first).to include('email' => 'billybob@example.com')
868+
end
869+
870+
context 'with guest' do
871+
context 'with pending invites' do
872+
it 'does not return invites' do
873+
inviter = Fabricate(:user)
874+
Fabricate(:invite, invited_by: inviter)
875+
876+
xhr :get, :invited, username: inviter.username
877+
878+
invites = JSON.parse(response.body)
879+
expect(invites).to be_empty
880+
end
881+
end
882+
883+
context 'with redeemed invites' do
884+
it 'returns invites' do
885+
inviter = Fabricate(:user)
886+
invitee = Fabricate(:user)
887+
invite = Fabricate(:invite, invited_by: inviter, user: invitee)
888+
889+
xhr :get, :invited, username: inviter.username
890+
891+
invites = JSON.parse(response.body)
892+
expect(invites).to have(1).item
893+
expect(invites.first).to include('email' => invite.email)
894+
end
895+
end
823896
end
824897

898+
context 'with authenticated user' do
899+
context 'with pending invites' do
900+
context 'with permission to see pending invites' do
901+
it 'returns invites' do
902+
user = log_in
903+
inviter = Fabricate(:user)
904+
invite = Fabricate(:invite, invited_by: inviter)
905+
stub_guardian(user) do |guardian|
906+
guardian.stubs(:can_see_pending_invites_from?).
907+
with(inviter).returns(true)
908+
end
909+
910+
xhr :get, :invited, username: inviter.username
911+
912+
invites = JSON.parse(response.body)
913+
expect(invites).to have(1).item
914+
expect(invites.first).to include("email" => invite.email)
915+
end
916+
end
917+
918+
context 'without permission to see pending invites' do
919+
it 'does not return invites' do
920+
user = log_in
921+
inviter = Fabricate(:user)
922+
invitee = Fabricate(:user)
923+
Fabricate(:invite, invited_by: inviter)
924+
stub_guardian(user) do |guardian|
925+
guardian.stubs(:can_see_pending_invites_from?).
926+
with(inviter).returns(false)
927+
end
928+
929+
xhr :get, :invited, username: inviter.username
930+
931+
invites = JSON.parse(response.body)
932+
expect(invites).to be_empty
933+
end
934+
end
935+
end
936+
937+
context 'with redeemed invites' do
938+
it 'returns invites' do
939+
user = log_in
940+
inviter = Fabricate(:user)
941+
invitee = Fabricate(:user)
942+
invite = Fabricate(:invite, invited_by: inviter, user: invitee)
943+
944+
xhr :get, :invited, username: inviter.username
945+
946+
invites = JSON.parse(response.body)
947+
expect(invites).to have(1).item
948+
expect(invites.first).to include('email' => invite.email)
949+
end
950+
end
951+
end
825952
end
826953

827954
describe '#update' do

spec/models/invite_spec.rb

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,4 +276,50 @@
276276
end
277277
end
278278

279+
describe '.find_all_invites_from' do
280+
context 'with user that has invited' do
281+
it 'returns invites' do
282+
inviter = Fabricate(:user)
283+
invite = Fabricate(:invite, invited_by: inviter)
284+
285+
invites = Invite.find_all_invites_from(inviter)
286+
287+
expect(invites).to include invite
288+
end
289+
end
290+
291+
context 'with user that has not invited' do
292+
it 'does not return invites' do
293+
user = Fabricate(:user)
294+
invite = Fabricate(:invite)
295+
296+
invites = Invite.find_all_invites_from(user)
297+
298+
expect(invites).to be_empty
299+
end
300+
end
301+
end
302+
303+
describe '.find_redeemed_invites_from' do
304+
it 'returns redeemed invites only' do
305+
inviter = Fabricate(:user)
306+
pending_invite = Fabricate(
307+
:invite,
308+
invited_by: inviter,
309+
user_id: nil,
310+
email: 'pending@example.com'
311+
)
312+
redeemed_invite = Fabricate(
313+
:invite,
314+
invited_by: inviter,
315+
user_id: 123,
316+
email: 'redeemed@example.com'
317+
)
318+
319+
invites = Invite.find_redeemed_invites_from(inviter)
320+
321+
expect(invites).to have(1).items
322+
expect(invites.first).to eq redeemed_invite
323+
end
324+
end
279325
end

spec/support/helpers.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,10 @@ def generate_username(length=10)
4343
range = [*'a'..'z']
4444
Array.new(length){range.sample}.join
4545
end
46+
47+
def stub_guardian(user)
48+
guardian = Guardian.new(user)
49+
yield(guardian) if block_given?
50+
Guardian.stubs(new: guardian).with(user)
51+
end
4652
end

0 commit comments

Comments
 (0)