spec/models/team_spec.rb
describe Team do
let(:assignment) { build(:assignment, id: 1, name: 'no assgt') }
let(:participant) { build(:participant, user_id: 1) }
let(:participant2) { build(:participant, user_id: 2) }
let(:participant3) { build(:participant, user_id: 3) }
let(:user) { build(:student, id: 1, name: 'no name', fullname: 'no one', participants: [participant]) }
let(:user2) { build(:student, id: 2) }
let(:user3) { build(:student, id: 3) }
let(:team) { build(:assignment_team, id: 1, name: 'no team', users: [user]) }
let(:team_user) { build(:team_user, id: 1, user: user) }
before(:each) do
allow(TeamsUser).to receive(:where).with(team_id: 1).and_return([team_user])
end
describe '#participant' do
it 'gets the participants of current team, by default returns an empty array' do
expect(team.participants).to eq([])
end
end
describe '#responses' do
it 'gets the response done by participants in current team, by default returns an empty array' do
expect(team.responses).to eq([])
end
end
describe '#delete' do
it 'deletes the current team and related objects and return self' do
allow(TeamsUser).to receive_message_chain(:where, :find_each).with(team_id: 1).with(no_args).and_yield(team_user)
allow(team_user).to receive(:destroy).and_return(team_user)
node = double('TeamNode')
allow(TeamNode).to receive(:find_by).with(node_object_id: 1).and_return(node)
allow(node).to receive(:destroy).and_return(node)
expect(team.delete).to eq(team)
end
end
describe '#node_type' do
it 'always returns TeamNode' do
expect(team.node_type).to eq('TeamNode')
end
end
describe '#author_names' do
it 'returns an array of author\'s name' do
expect(team.author_names).to eq(['no one'])
end
end
describe '#user?' do
context 'when users in current team includes the parameterized user' do
it 'returns true' do
expect(team.user?(user)).to be true
end
end
context 'when users in current team does not include the parameterized user' do
it 'returns false' do
expect(team.user?(double('User'))).to be false
end
end
end
describe '#full?' do
context 'when the parent_id of current team is nil' do
it 'returns false' do
team.parent_id = nil
expect(team.full?).to be false
end
end
context 'when the parent_id of current team is not nil' do
before(:each) do
allow(Assignment).to receive(:find).with(1).and_return(assignment)
end
context 'when the current team size is bigger than or equal to max team members' do
it 'returns true' do
allow(Team).to receive(:size).and_return(6)
expect(team.full?).to be true
end
end
context 'when the current team size is smaller than max team members' do
it 'returns false' do
allow(Team).to receive(:size).and_return(1)
expect(team.full?).to be false
end
end
end
end
describe '#add_member' do
context 'when parameterized user has already joined in current team' do
it 'raise an error' do
expect { team.add_member(user) }.to raise_error(RuntimeError, "The user #{user.name} is already a member of the team #{team.name}")
end
end
context 'when parameterized user did not join in current team yet' do
context 'when current team is not full' do
it 'does not raise an error' do
allow_any_instance_of(Team).to receive(:user?).with(user).and_return(false)
allow_any_instance_of(Team).to receive(:full?).and_return(false)
allow(TeamsUser).to receive(:create).with(user_id: 1, team_id: 1).and_return(team_user)
allow(TeamNode).to receive(:find_by).with(node_object_id: 1).and_return(double('TeamNode', id: 1))
allow_any_instance_of(Team).to receive(:add_participant).with(1, user).and_return(double('Participant'))
expect(team.add_member(user)).to be true
end
end
end
end
describe '.size' do
it 'returns the size of current team' do
expect(Team.size(1)).to eq(1)
end
end
describe '#copy_members' do
it 'copies members from current team to a new team' do
allow(TeamsUser).to receive(:create).with(team_id: 2, user_id: 1).and_return(team_user)
allow(Assignment).to receive(:find).with(1).and_return(assignment)
expect(team.copy_members(double('Team', id: 2))).to eq([team_user])
end
end
describe '.check_for_existing' do
context 'when team exists' do
it 'raises a TeamExistsError' do
allow(AssignmentTeam).to receive(:where).with(parent_id: 1, name: 'no name').and_return([team])
expect { Team.check_for_existing(assignment, 'no name', 'Assignment') }
.to raise_error(TeamExistsError, 'The team name no name is already in use.')
end
end
context 'when team exists' do
it 'returns nil' do
allow(AssignmentTeam).to receive(:where).with(parent_id: 1, name: 'no name').and_return([])
expect(Team.check_for_existing(assignment, 'no name', 'Assignment')).to be nil
end
end
end
describe '.randomize_all_by_parent' do
it 'forms teams and assigns team members automatically' do
allow(Participant).to receive(:where).with(parent_id: 1, type: 'AssignmentParticipant', can_mentor: [false, nil])
.and_return([participant, participant2, participant3])
allow(User).to receive(:find).with(1).and_return(user)
allow(User).to receive(:find).with(2).and_return(user2)
allow(User).to receive(:find).with(3).and_return(user3)
allow(Team).to receive(:where).with(parent_id: 1, type: 'AssignmentTeam').and_return([team])
allow(Team).to receive(:size).with(any_args).and_return(1)
allow_any_instance_of(Team).to receive(:add_member).with(any_args).and_return(true)
expect(Team.randomize_all_by_parent(assignment, 'Assignment', 2)).to eq([1])
end
end
describe '.generate_team_name' do
it 'generates the unused team name' do
expect(Team.generate_team_name('Assignment')).to eq('Assignment Team_1')
end
end
describe '.import_team_members' do
context 'when cannot find a user by name' do
it 'raises an ImportError' do
allow(User).to receive(:find_by).with(name: 'no name').and_return(nil)
expect { team.import_team_members(teammembers: ['no name']) }.to raise_error(ImportError,
"The user 'no name' was not found. <a href='/users/new'>Create</a> this user?")
end
end
context 'when can find certain user' do
it 'adds the user to current team' do
allow(User).to receive(:find_by).with(name: 'no name').and_return(user)
allow(TeamsUser).to receive(:find_by).with(team_id: 1, user_id: 1).and_return(nil)
allow_any_instance_of(Team).to receive(:add_member).with(user).and_return(true)
expect(team.import_team_members(teammembers: ['no name'])).to eq(['no name'])
end
end
end
# E1991 : we check whether anonymized view
# sets the team name to anonymized. the test
# case should test both when anonymized view
# is set and when anonymized view is not set
describe '#anonymized_view' do
it 'returns anonymized name of team when anonymized view is set' do
allow(User).to receive(:anonymized_view?).and_return(true)
expect(team.name).to eq 'Anonymized_Team_' + team.id.to_s
expect(team.name).not_to eq 'no team'
end
it 'returns real name of team when anonymized view is not set' do
allow(User).to receive(:anonymized_view?).and_return(false)
expect(team.name).not_to eq 'Team_' + team.id.to_s
expect(team.name).to eq 'no team'
end
end
describe '.import' do
context 'when row is empty and has_column_names option is not true' do
it 'raises an ArgumentError' do
expect { Team.import({}, 1, { has_column_names: 'false' }, AssignmentTeam.new) }
.to raise_error(ArgumentError, 'Not enough fields on this line.')
end
end
# Add tests to handle duplicates in various ways, in .import method and handle_duplicates method
context 'when there are duplicates in new teams with existing teams' do
let(:row) do
{ teammembers: %w[member1 member2], teamname: 'name' }
end
let(:options) do
{ has_teamname: 'true_first' }
end
let(:id) { 1 }
before(:each) do
allow(Team).to receive_message_chain(:where, :first).with(['name =? && parent_id =?', row[:teamname], id]).with(no_args).and_return(team)
allow(AssignmentTeam).to receive(:create_team_and_node).with(id).and_return(team)
allow(team).to receive(:save).and_return(true)
allow(team).to receive(:import_team_members)
end
context 'when choosing to ignore the new team' do
it 'handles duplicates with "ignore" argument' do
options[:handle_dups] = 'ignore'
allow(Team).to receive(:handle_duplicate).with(team, row[:teamname], id, 'ignore', AssignmentTeam).and_return(nil)
expect(Team).to receive(:handle_duplicate).with(team, row[:teamname], id, 'ignore', AssignmentTeam).and_return(nil)
Team.import(row, id, options, AssignmentTeam)
end
end
context 'when choosing to replace the existing team with the new team' do
it 'handles duplicates with "replace" argument' do
options[:handle_dups] = 'replace'
allow(Team).to receive(:handle_duplicate).with(team, row[:teamname], id, 'replace', AssignmentTeam).and_return(row[:teamname])
expect(Team).to receive(:handle_duplicate).with(team, row[:teamname], id, 'replace', AssignmentTeam).and_return(row[:teamname])
Team.import(row, id, options, AssignmentTeam)
end
end
context 'when choosing to insert any new members to existing team' do
it 'handles duplicates with "insert" argument' do
options[:handle_dups] = 'insert'
allow(Team).to receive(:handle_duplicate).with(team, row[:teamname], id, 'insert', AssignmentTeam).and_return(nil)
expect(Team).to receive(:handle_duplicate).with(team, row[:teamname], id, 'insert', AssignmentTeam).and_return(nil)
Team.import(row, id, options, AssignmentTeam)
end
end
context 'when choosing to rename the new team and import' do
it 'handles duplicates with "rename" argument' do
options[:handle_dups] = 'rename'
allow(Team).to receive(:handle_duplicate).with(team, row[:teamname], id, 'rename', AssignmentTeam).and_return(row[:teamname])
expect(Team).to receive(:handle_duplicate).with(team, row[:teamname], id, 'rename', AssignmentTeam).and_return(row[:teamname])
Team.import(row, id, options, AssignmentTeam)
end
end
context 'when choosing to rename the existing team and import' do
it 'handles duplicates with "rename_existing" argument' do
options[:handle_dups] = 'rename_existing'
allow(Team).to receive(:handle_duplicate).with(team, row[:teamname], id, 'rename_existing', AssignmentTeam).and_return(row[:teamname])
expect(Team).to receive(:handle_duplicate).with(team, row[:teamname], id, 'rename_existing', AssignmentTeam).and_return(row[:teamname])
Team.import(row, id, options, AssignmentTeam)
end
end
end
# E1776 (Fall 2017)
#
# The tests below are no longer reflective of the current import that uses row_hash ==> {teammembers: ['name', 'name'], teamname: 'teamname'}.
#
# context 'when has_column_names option is true' do
# it 'handles duplicated teams and imports team members' do
# allow(Team).to receive(:find_by).with(name: 'no team', parent_id: 1).and_return(team)
# allow_any_instance_of(Team).to receive(:handle_duplicate)
# .with(team, 'no team', 1, 'rename', AssignmentTeam.new).and_return('new team name')
# allow(AssignmentTeam).to receive(:create_team_and_node).with(1).and_return(AssignmentTeam.new)
# allow_any_instance_of(Team).to receive(:import_team_members).with(1, ['no team', 'another field']).and_return(true)
# expect(Team.import(['no team', 'another field'], 1, {has_column_names: 'true'}, AssignmentTeam.new)).to be true
# end
# end
#
# context 'when has_column_names option is not true' do
# it 'generated team name directly and imports team members' do
# allow(Assignment).to receive(:find).with(1).and_return(assignment)
# allow(Team).to receive(:generate_team_name).with('no assgt').and_return('new team name')
# allow(AssignmentTeam).to receive(:create_team_and_node).with(1).and_return(AssignmentTeam.new)
# allow_any_instance_of(Team).to receive(:import_team_members).with(0, ['no team', 'another field']).and_return(true)
# expect(Team.import(['no team', 'another field'], 1, {has_column_names: 'false'}, AssignmentTeam.new)).to be true
# end
# end
end
describe '.handle_duplicate' do
context 'when parameterized team is nil' do
it 'returns team name' do
expect(Team.handle_duplicate(nil, 'no name', 1, 'replace', CourseTeam.new)).to eq('no name')
end
end
context 'when parameterized team is not nil' do
context 'when handle_dups option is ignore' do
it 'does not create the new team and returns nil' do
expect(Team.handle_duplicate(team, 'no name', 1, 'ignore', CourseTeam.new)).to be nil
end
end
context 'when handle_dups option is rename' do
it 'returns new team name' do
allow(Course).to receive(:find).with(1).and_return(double('Course', name: 'no course'))
allow(Assignment).to receive(:find).with(1).and_return(double('Assignment', name: 'no assignment'))
allow(Team).to receive(:generate_team_name).with('no course').and_return('new team name')
allow(Team).to receive(:generate_team_name).with('no assignment').and_return('new team name')
expect(Team.handle_duplicate(team, 'no name', 1, 'rename', CourseTeam.new)).to eq('new team name')
expect(Team.handle_duplicate(team, 'no name', 1, 'rename', AssignmentTeam.new)).to eq('new team name')
end
end
context 'when handle_dups option is replace' do
it 'deletes the old team' do
allow(team).to receive(:delete)
expect(Team.handle_duplicate(team, 'no name', 1, 'replace', CourseTeam.new)).to eq('no name')
end
end
context 'when handle_dups option is insert' do
it 'does nothing and returns nil' do
expect(Team.handle_duplicate(team, 'no name', 1, 'insert', CourseTeam.new)).to be nil
end
end
# By the time this test is added (by E1949), the renaming existing team function does not exist yet,
# so it should fail unless the function is implemented and the existing team is renamed and saved.
context 'when handle_dups option is rename_existing' do
it 'renames the existing team and returns nil' do
allow(Course).to receive(:find).with(1).and_return(double('Course', name: 'no course'))
allow(Assignment).to receive(:find).with(1).and_return(double('Assignment', name: 'no assignment'))
allow(Team).to receive(:generate_team_name).with('no course').and_return('new team name')
allow(Team).to receive(:generate_team_name).with('no assignment').and_return('new team name')
allow(team).to receive(:name=).with('new team name')
allow(team).to receive(:save)
expect(Team.handle_duplicate(team, 'no name', 1, 'replace_existing', CourseTeam.new)).to be nil
expect(Team.handle_duplicate(team, 'no name', 1, 'replace_existing', AssignmentTeam.new)).to be nil
end
end
end
end
describe '.export' do
it 'exports teams to csv' do
allow(AssignmentTeam).to receive(:where).with(parent_id: 1).and_return([team])
allow(TeamsUser).to receive(:where).with(team_id: 1).and_return([team_user])
expect(Team.export([], 1, { team_name: 'false' }, AssignmentTeam.new)).to eq([['no team', 'no name']])
end
end
end