Refactor UsersController#invited

* Add test coverage
* Simplify controller action
* Move finder code to Invite class
This commit is contained in:
Scott Albertson 2013-11-08 11:11:41 -08:00
parent e5fd2946e0
commit 77b59b54ce
5 changed files with 215 additions and 24 deletions

View File

@ -66,29 +66,17 @@ class UsersController < ApplicationController
end end
def invited def invited
params.require(:username) inviter = fetch_user_from_params
params.permit(:filter)
by_user = fetch_user_from_params invites = if guardian.can_see_pending_invites_from?(inviter)
Invite.find_all_invites_from(inviter)
invited = Invite.where(invited_by_id: by_user.id) else
.includes(:user => :user_stat) Invite.find_redeemed_invites_from(inviter)
.order('CASE WHEN invites.user_id IS NOT NULL THEN 0 ELSE 1 END',
'user_stats.time_read DESC',
'invites.redeemed_at DESC')
.limit(SiteSetting.invites_shown)
.references('user_stats')
unless guardian.can_see_pending_invites_from?(by_user)
invited = invited.where('invites.user_id IS NOT NULL')
end end
if params[:filter].present? invites = invites.filter_by(params[:filter])
invited = invited.where('(LOWER(invites.email) LIKE :filter) or (LOWER(users.username) LIKE :filter)', filter: "%#{params[:filter].downcase}%")
.references(:users)
end
render_serialized(invited.to_a, InviteSerializer) render_serialized(invites.to_a, InviteSerializer)
end end
def is_local_username def is_local_username

View File

@ -68,6 +68,30 @@ class Invite < ActiveRecord::Base
invite invite
end end
def self.find_all_invites_from(inviter)
Invite.where(invited_by_id: inviter.id)
.includes(:user => :user_stat)
.order('CASE WHEN invites.user_id IS NOT NULL THEN 0 ELSE 1 END',
'user_stats.time_read DESC',
'invites.redeemed_at DESC')
.limit(SiteSetting.invites_shown)
.references('user_stats')
end
def self.find_redeemed_invites_from(inviter)
find_all_invites_from(inviter).where('invites.user_id IS NOT NULL')
end
def self.filter_by(email_or_username)
if email_or_username
where(
'(LOWER(invites.email) LIKE :filter) or (LOWER(users.username) LIKE :filter)',
filter: "%#{email_or_username.downcase}%"
)
else
scoped
end
end
end end
# == Schema Information # == Schema Information

View File

@ -813,15 +813,142 @@ describe UsersController do
end end
end end
describe '.invited' do describe '#invited' do
let(:user) { Fabricate(:user) }
it 'returns success' do it 'returns success' do
user = Fabricate(:user)
xhr :get, :invited, username: user.username xhr :get, :invited, username: user.username
response.should be_success
expect(response).to be_success
end end
it 'filters by email' do
inviter = Fabricate(:user)
invitee = Fabricate(:user)
invite = Fabricate(
:invite,
email: 'billybob@example.com',
invited_by: inviter,
user: invitee
)
Fabricate(
:invite,
email: 'jimtom@example.com',
invited_by: inviter,
user: invitee
)
xhr :get, :invited, username: inviter.username, filter: 'billybob'
invites = JSON.parse(response.body)
expect(invites).to have(1).item
expect(invites.first).to include('email' => 'billybob@example.com')
end
it 'filters by username' do
inviter = Fabricate(:user)
invitee = Fabricate(:user, username: 'billybob')
invite = Fabricate(
:invite,
invited_by: inviter,
email: 'billybob@example.com',
user: invitee
)
Fabricate(
:invite,
invited_by: inviter,
user: Fabricate(:user, username: 'jimtom')
)
xhr :get, :invited, username: inviter.username, filter: 'billybob'
invites = JSON.parse(response.body)
expect(invites).to have(1).item
expect(invites.first).to include('email' => 'billybob@example.com')
end
context 'with guest' do
context 'with pending invites' do
it 'does not return invites' do
inviter = Fabricate(:user)
Fabricate(:invite, invited_by: inviter)
xhr :get, :invited, username: inviter.username
invites = JSON.parse(response.body)
expect(invites).to be_empty
end
end
context 'with redeemed invites' do
it 'returns invites' do
inviter = Fabricate(:user)
invitee = Fabricate(:user)
invite = Fabricate(:invite, invited_by: inviter, user: invitee)
xhr :get, :invited, username: inviter.username
invites = JSON.parse(response.body)
expect(invites).to have(1).item
expect(invites.first).to include('email' => invite.email)
end
end
end
context 'with authenticated user' do
context 'with pending invites' do
context 'with permission to see pending invites' do
it 'returns invites' do
user = log_in
inviter = Fabricate(:user)
invite = Fabricate(:invite, invited_by: inviter)
stub_guardian(user) do |guardian|
guardian.stubs(:can_see_pending_invites_from?).
with(inviter).returns(true)
end
xhr :get, :invited, username: inviter.username
invites = JSON.parse(response.body)
expect(invites).to have(1).item
expect(invites.first).to include("email" => invite.email)
end
end
context 'without permission to see pending invites' do
it 'does not return invites' do
user = log_in
inviter = Fabricate(:user)
invitee = Fabricate(:user)
Fabricate(:invite, invited_by: inviter)
stub_guardian(user) do |guardian|
guardian.stubs(:can_see_pending_invites_from?).
with(inviter).returns(false)
end
xhr :get, :invited, username: inviter.username
invites = JSON.parse(response.body)
expect(invites).to be_empty
end
end
end
context 'with redeemed invites' do
it 'returns invites' do
user = log_in
inviter = Fabricate(:user)
invitee = Fabricate(:user)
invite = Fabricate(:invite, invited_by: inviter, user: invitee)
xhr :get, :invited, username: inviter.username
invites = JSON.parse(response.body)
expect(invites).to have(1).item
expect(invites.first).to include('email' => invite.email)
end
end
end
end end
describe '#update' do describe '#update' do

View File

@ -276,4 +276,50 @@ describe Invite do
end end
end end
describe '.find_all_invites_from' do
context 'with user that has invited' do
it 'returns invites' do
inviter = Fabricate(:user)
invite = Fabricate(:invite, invited_by: inviter)
invites = Invite.find_all_invites_from(inviter)
expect(invites).to include invite
end
end
context 'with user that has not invited' do
it 'does not return invites' do
user = Fabricate(:user)
invite = Fabricate(:invite)
invites = Invite.find_all_invites_from(user)
expect(invites).to be_empty
end
end
end
describe '.find_redeemed_invites_from' do
it 'returns redeemed invites only' do
inviter = Fabricate(:user)
pending_invite = Fabricate(
:invite,
invited_by: inviter,
user_id: nil,
email: 'pending@example.com'
)
redeemed_invite = Fabricate(
:invite,
invited_by: inviter,
user_id: 123,
email: 'redeemed@example.com'
)
invites = Invite.find_redeemed_invites_from(inviter)
expect(invites).to have(1).items
expect(invites.first).to eq redeemed_invite
end
end
end end

View File

@ -43,4 +43,10 @@ module Helpers
range = [*'a'..'z'] range = [*'a'..'z']
Array.new(length){range.sample}.join Array.new(length){range.sample}.join
end end
def stub_guardian(user)
guardian = Guardian.new(user)
yield(guardian) if block_given?
Guardian.stubs(new: guardian).with(user)
end
end end