CSC/ECE 517 Fall 2017/E1746 Refactor user.rb

From Expertiza_Wiki
Revision as of 22:21, 27 October 2017 by Tfei3 (talk | contribs)
Jump to navigation Jump to search

E1746 [Test First Development] Refactor user.rb

This page provides a description of the Expertiza based OSS project.

About Expertiza

Expertiza is an open source project based on Ruby on Rails framework. Expertiza allows the instructor to create new assignments and customize new or existing assignments. It also allows the instructor to create a list of topics the students can sign up for. Students can form teams in Expertiza to work on various projects and assignments. Students can also peer review other students' submissions. Expertiza supports submission across various document types, including the URLs and wiki pages.

Problem Statement

The following tasks were accomplished in this project:

  • Complete the pending tests in user_spec.rb
  • Refactor get_user_list method
  • Refactor self.search_users method
  • Rename method and change all other places it is used
  • Use find_by instead of dynamic method

Current Implementation

Missions and Solutions
  • Mission 1:Complete the pending tests in user_spec.rb
There are many pending tests in the file 'user.rb'. What we have done is finishing these pending tests and makes them pass.The user_spec.rb file on github is below.
include Rails.application.routes.url_helpers

describe User do

 let(:user) do
   User.new name: 'abc', fullname: 'abc xyz', email: 'abcxyz@gmail.com', password: '12345678', password_confirmation: '12345678',
            email_on_submission: 1, email_on_review: 1, email_on_review_of_review: 0, copy_of_emails: 1, handle: 'handle'
 end
 let(:user1) { User.new name: 'abc', fullname: 'abc bbc', email: 'abcbbc@gmail.com', password: '123456789', password_confirmation: '123456789' }
 let(:user2) { User.new name: 'abc', fullname: 'abc bbc', email: 'abcbbe@gmail.com', password: '123456789', password_confirmation: '123456789' }
 describe '#name' do
   it 'returns the name of the user' do
     expect(user.name).to eq('abc')
   end
   it 'Validate presence of name which cannot be blank' do
     expect(user).to be_valid
     user.name = '  '
     expect(user).not_to be_valid
   end
   it 'Validate that name is always unique' do
     expect(user1).to validate_uniqueness_of(:name)
   end
 end
 describe '#fullname' do
   it 'returns the full name of the user' do
     expect(user.fullname).to eq('abc xyz')
   end
 end
 describe '#email' do
   it 'returns the email of the user' do
     expect(user.email).to eq('abcxyz@gmail.com')
   end
   it 'Validate presence of email which cannot be blank' do
     user.email = '  '
     expect(user).not_to be_valid
   end
   it 'Validate the email format' do
     user.email = 'a@x'
     expect(user).not_to be_valid
   end
   it 'Validate the email format' do
     user.email = 'ax.com'
     expect(user).not_to be_valid
   end
   it 'Validate the email format' do
     user.email = 'axc'
     expect(user).not_to be_valid
   end
   it 'Validate the email format' do
     user.email = '123'
     expect(user).not_to be_valid
   end
   it 'Validate the email format correctness' do
     user.email = 'a@x.com'
     expect(user).to be_valid
   end
 end
 describe '#salt_first?' do
   it 'will always return true' do
     expect(user.salt_first?).to be true
   end
 end
 describe '#get_available_users' do
   before(:each) do
     role = Role.new
   end
   it 'returns the first 10 visible users' do
     all_users = double
     user_mock1 = double(:role=>'Instructor')
     user_mock2 = double(:role=>'Administrator')
     user_mock3 = double(:role=>'Student')
     allow(@role).to receive(:get_parents).and_return(['Instructor','Administrator'])
     allow(User).to receive(:all).and_return([user_mock1,user_mock2,user_mock3])
     allow(all_users).to receive(:select).and_yield(user_mock2).and_yield(user_mock2).and_yield(user_mock3)
     expect(user.get_available_users("abc")).to eq ([user_mock1,user_mock2])
   end
 end
 describe '#can_impersonate?' do
   it 'can impersonate target user if current user is super admin' do
     allow(user1).to receive_message_chain("role.super_admin?"){true}
     expect(user1.can_impersonate?(user)).to be true
   end
   it 'can impersonate target user if current user is the TA of target user'do
     allow(user1).to receive_message_chain("role.super_admin?"){false}
     allow(user1).to receive(:is_teaching_assistant_for?).and_return(user)
     expect(user1.can_impersonate?(user)).to be true
   end
   it 'can impersonate target user if current user is the recursively parent of target user'do
     allow(user1).to receive_message_chain("role.super_admin?"){true}
     allow(user1).to receive(:is_recursively_parent_of).and_return(user)
     expect(user1.can_impersonate?(user)).to be true
   end
   it 'cannot impersonate target user if current user does not satisfy all requirements'do
     allow(user1).to receive_message_chain("role.super_admin?"){false}
     allow(user1).to receive_message_chain("role.ta?"){false}
     expect(user1.can_impersonate?(user)).to be false
   end
 end
 describe '#is_recursively_parent_of' do
   context 'when the parent of target user (user) is nil' do
     it 'returns false' do
       allow(user).to receive(:parent).and_return(nil)
       expect(user1.is_recursively_parent_of(user)).to eq false
     end
   end
   context 'when the parent of target user (user) is current user (user1)' do
     it 'returns true' do
       allow(user).to receive(:parent).and_return(user1)
       expect(user1.is_recursively_parent_of(user)).to eq true
     end
   end
   context 'when the parent of target user (user) is not current user (user1), but super admin (user2)' do
     it 'returns false' do
       allow(user).to receive(:parent).and_return(user2)
       allow(user2).to receive_message_chain("role.super_admin?") { true }
       expect(user1.is_recursively_parent_of(user)).to eq false
     end
   end
 end
 describe '#get_user_list' do
   context 'when current user is super admin' do
     it 'fetches all users' do
       user_list=double.as_null_object
       allow(user).to receive_message_chain("role.super_admin?"){ true }
       allow(User).to receive_message_chain("all.find_each").and_yield(user1).and_yield(user2)
       allow(user).to receive_message_chain("role.instructor?"){ false }
       allow(user).to receive_message_chain("role.ta?"){false}
       User.all.find_each do |user|
         user_list<<user
       end
       user.get_user_list
       end
     end
   context 'when current user is an instructor' do
     before(:each) do
       course = Course.new
       assignment = Assignment.new
     end
     it 'fetches all users in his/her course/assignment' do
       user_list = double
       course = double
       assignment = double
       allow(user).to receive_message_chain("role.super_admin?"){ false }
       allow(user).to receive_message_chain("role.instructor?"){ true }
       allow(Course).to receive_message_chain(:where,:find_each).and_yield(course)
       allow(course).to receive(:get_participants).and_return(user1)
       allow(Assignment).to receive_message_chain(:where,:find_each).and_yield(assignment)
       allow(assignment).to receive(:participants).and_return(user2)
       allow_any_instance_of(User).to receive(:empty?).and_return(false)
       allow_any_instance_of(User).to receive(:each).and_yield(user)
       allow_any_instance_of(User).to receive(:user).and_return(user)
       allow_any_instance_of(User).to receive_message_chain(:role,:hasAllPrivilegesOf).and_return(true)
       allow(user).to receive_message_chain("role.ta?"){false}
       expect(user.get_user_list).to eq ([user])
     end
   end
   context 'when current user is a TA' do
     before(:each) do
       course = Course.new
       end
     it 'fetches all users in his/her courses'do
       courses=double
       course=double
       allow(user).to receive_message_chain("role.super_admin?"){ false }
       allow(user).to receive_message_chain("role.ta?"){ true }
       allow(user).to receive_message_chain("role.instructor?"){ false }
       allow(Ta).to receive(:get_mapped_courses).and_return(courses)
       allow(courses).to receive(:each).and_yield(course)
       allow(Course).to receive(:find).and_return(course)
       allow(course).to receive(:get_participants).and_return(user1)
       allow_any_instance_of(User).to receive(:empty?).and_return(false)
       allow_any_instance_of(User).to receive(:each).and_yield(user)
       allow_any_instance_of(User).to receive(:user).and_return(user)
       allow_any_instance_of(User).to receive_message_chain(:role,:hasAllPrivilegesOf).and_return(true)
       expect(user.get_user_list).to eq ([user])
   end
   end
 end
 describe '#super_admin?' do
   it 'returns ture if role name is Super-Administrator' do
     allow(user).to receive_message_chain("role.name"){'Super-Administrator'}
     expect(user.super_admin?).to be_truthy
   end
   it 'returns false if role name is not Super-Administrator' do
     allow(user).to receive_message_chain("role.name"){'CAt'}
     expect(user.super_admin?).to be_falsey
   end
 end
 describe '#is_creator_of?' do
   it 'returns true of current user (user) is the creator of target user (user1)' do
     allow(user1).to receive(:creator).and_return(user)
     expect(user.is_creator_of?(user1)).to be true
   end
   it 'returns false of current user (user) is not the creator of target user (user1)' do
     allow(user1).to receive(:creator).and_return(user2)
     expect(user.is_creator_of?(user1)).to be false
     expect(user2.is_creator_of?(user1)).to be true
   end
 end
 describe '.import' do
   it 'raises error if import column does not equal to 3' do
     row = ["abc","abc xyz"]
     _row_header = double
     seesion = {:user=>user}
     _id = double
     expect { User.import(row, _row_header,seesion,_id) }.to raise_error("Not enough items: expect 3 columns: your login name, your full name (first and last name, not seperated with the delimiter), and your email.")
   end
   it 'updates an existing user with info from impor file' do
     row = ["abc","abc xyz","abcxyz@gamil.com"]
     _row_header = double
     seesion = {:user=>user}
     _id = double
     allow(User).to receive(:find_by_name).and_return(user)
     allow_any_instance_of(User).to receive(:nil?).and_return(false)
     allow_any_instance_of(User).to receive(:id).and_return(1)
     expect_any_instance_of(User).to receive(:save)
     User.import(row,_row_header,seesion,_id)
   end
 end
 describe '.yesorno' do
   it 'returns yes when input is true' do
     expect(User.yesorno(true)).to eq "yes"
   end
   it 'returns no when input is false' do
     expect(User.yesorno(false)).to eq "no"
   end
   it 'returns empty string when input is other content' do
     content = "TEXT"
     expect(User.yesorno(content)).to eq ""
   end
 end
 describe '.find_by_login' do
   context 'when user\'s email is stored in DB' do
     it 'finds user by email' do
       email = 'abcxyz@gmail.com'
       allow(User).to receive(:find_by_email).with(email).and_return(user)
       expect(User.find_by_login(email)).to eq user
     end
   end
   context 'when user\'s email is not stored in DB' do
     it 'finds user by email if the local part of email is the same as username' do
       allow(User).to receive(:find_by_email).and_return(nil)
       allow(User).to receive(:where).and_return([{name: 'abc', fullname: 'abc bbc'}])
       expect(User.find_by_login('abcxyz@gmail.com')).to eq ({:name=>"abc", :fullname=>"abc bbc"})
     end
   end
 end
 describe '#get_instructor' do
   it 'gets the instructor id' do
     allow(user).to receive(:id).and_return(123)
     expect(user.get_instructor).to eq(123)
     end
 end
 describe '#instructor_id' do
   it 'returns id when role of current user is a super admin' do
     allow(user).to receive_message_chain(:role,:name).and_return('Super-Administrator')
     allow(user).to receive(:id).and_return(1)
     expect(user.instructor_id).to eq(1)
   end
   it 'returns id when role of current user is an Administrator' do
     allow(user).to receive_message_chain(:role,:name).and_return('Administrator')
     allow(user).to receive(:id).and_return(2)
     expect(user.instructor_id).to eq(2)
   end
   it 'returns id when role of current user is an Instructor' do
     allow(user).to receive_message_chain(:role,:name).and_return('Instructor')
     allow(user).to receive(:id).and_return(3)
     expect(user.instructor_id).to eq(3)
   end
   it 'returns instructor_id when role of current user is a TA' do
     allow(user).to receive_message_chain(:role,:name).and_return('Teaching Assistant')
     allow(Ta).to receive(:get_my_instructor).and_return(4)
     expect(user.instructor_id).to eq(4)
   end
   it 'raise an error when role of current user is other type' do
     allow(user).to receive_message_chain(:role,:name).and_return('abc')
     expect{user.instructor_id}.to raise_error(NotImplementedError,"for role abc")
   end
 end
 describe '.export' do
   before(:each) do
     allow(user).to receive_message_chain(:role,:name).and_return('abc')
     allow(user).to receive_message_chain(:parent,:name).and_return('abc')
     allow(User).to receive(:all).and_return([user])
     allow_any_instance_of(User).to receive(:each).and_yield(user)
   end
   it 'exports all information setting in options' do
     options={"personal_details"=>"true", "role"=>"true","parent"=>"true","email_options"=>"true","handle"=>"true"}
     csv=[]
     User.export(csv,0 , options)
     expect(csv).to eq([[user.name,user.fullname,user.email,
                                                user.role.name,user.parent.name,user.email_on_submission, user.email_on_review,
                                                user.email_on_review_of_review, user.copy_of_emails,user.handle]])
   end
   it 'exports only personal_details'do
     options={"personal_details"=>"true", "role"=>"false","parent"=>"false","email_options"=>"false","handle"=>"false"}
     csv=[]
     User.export(csv,0 , options)
     expect(csv).to eq(user.name,user.fullname,user.email)
   end
   it 'exports only current role and parent' do
     options={"personal_details"=>"false", "role"=>"true","parent"=>"true","email_options"=>"false","handle"=>"false"}
     csv=[]
     User.export(csv,0 , options)
     expect(csv).to eq(user.role.name,user.parent.name)
   end
   it 'exports only email_options' do
     options={"personal_details"=>"false", "role"=>"false","parent"=>"false","email_options"=>"true","handle"=>"false"}
     csv=[]
     User.export(csv,0 , options)
     expect(csv).to eq(user.email_on_submission, user.email_on_review,user.email_on_review_of_review, user.copy_of_emails)
   end
   it 'exports only handle' do
     options={"personal_details"=>"false", "role"=>"false","parent"=>"false","email_options"=>"false","handle"=>"true"}
     csv=[]
     User.export(csv,0 , options)
     expect(csv).to eq(user.handle)
   end
 end
 describe '.export_fields' do
   it 'exports all information setting in options' do
     options={"personal_details"=>"true","role"=>"true","parent"=>"true","email_options"=>"true","handle"=>"true"}
     expect(User.export_fields(options)).to eq(["name","full name","email","role","parent","email on submission","email on review","email on metareview","handle"])
   end
   it 'exports only personal_details' do
     options={"personal_details"=>"true","role"=>"false","parent"=>"false","email_options"=>"false","handle"=>"false"}
     expect(User.export_fields(options)).to eq(["name","full name","email"])
   end
   it 'exports only current role and parent' do
     options={"personal_details"=>"false","role"=>"true","parent"=>"true","email_options"=>"false","handle"=>"false"}
     expect(User.export_fields(options)).to eq(["role","parent"])
   end
   it 'exports only email_options' do
     options={"personal_details"=>"false","role"=>"false","parent"=>"false","email_options"=>"true","handle"=>"false"}
     expect(User.export_fields(options)).to eq(["email on submission","email on review","email on metareview"])
   end
   it 'exports only handle' do
     options={"personal_details"=>"false","role"=>"false","parent"=>"false","email_options"=>"false","handle"=>"true"}
     expect(User.export_fields(options)).to eq(["handle"])
   end
 end
 describe '.from_params' do
   it 'returns user by user_id fetching from params' do
     params = {
       :user_id => 1,
     }
     allow(User).to receive(:find).and_return(user)
     expect(User.from_params(params)).to eq user
   end
   it 'returns user by user name fetching from params' do
     params = {
       :user => {
         :name => 'abc'
       }
     }
     allow(User).to receive(:find_by_name).and_return(user)
     expect(User.from_params(params)).to eq user
   end
   it 'raises an error when Expertiza cannot find user' do
     params = {
       :user => {
         :name => 'ncsu'
       }
     }
     allow(user).to receive(:nil?).and_return(true)
     expect {User.from_params(params)}.to raise_error("Please <a href='http://localhost:3000/users/new'>create an account</a> for this user to continue.")
   end
 end
 describe '#is_teaching_assistant_for?' do
   it 'returns false if current user is not a TA' do
     allow(user1).to receive_message_chain("role.ta?"){ false }
     expect(user1.is_teaching_assistant_for?(user)).to be_falsey
   end
   it 'returns false if current user is a TA, but target user is not a student'do
     allow(user1).to receive_message_chain("role.ta?"){true }
     allow(user).to receive_message_chain("role.name").and_return('teacher')
     expect(user1.is_teaching_assistant_for?(user)).to be_falsey
   end
   it 'returns true if current user is a TA of target user'do
   allow(Ta).to receive(:find).and_return(user1)
   allow(user1).to receive_message_chain("role.ta?"){ true }
   allow(user).to receive_message_chain("role.name").and_return('Student')
   c1=Course.new
   allow(user1).to receive_message_chain(:courses_assisted_with,:any?).and_yield(c1)
   allow_any_instance_of(Course).to receive_message_chain(:assignments,:map,:flatten,:map,:include?,:user).and_return(true)
   expect(user1.is_teaching_assistant_for?(user)).to be true
   end
 end
 describe '#is_teaching_assistant?' do
   it 'returns true if current user is a TA' do
     allow(user).to receive_message_chain("role.ta?"){ true }
     expect(user.is_teaching_assistant?).to be true
   end
   it 'returns false if current user is not a TA' do
     allow(user).to receive_message_chain("role.ta?"){ false }
     expect(user.is_teaching_assistant?).to be_falsey
   end
 end

end