spec/controllers/assignments_controller_spec.rb
describe AssignmentsController do
let(:assignment) do
build(:assignment, id: 1, name: 'test assignment', instructor_id: 6, staggered_deadline: true, directory_path: 'test_assignment',
participants: [build(:participant)], teams: [build(:assignment_team)], course_id: 1)
end
let(:assignment2) do
build(:assignment, id: 2, name: 'new test assignment', instructor_id: 6, staggered_deadline: true, directory_path: 'new_test_assignment',
participants: [build(:participant)], teams: [build(:assignment_team)], course_id: 1)
end
let(:assignment_form) { double('AssignmentForm', assignment: assignment) }
let(:admin) { build(:admin) }
let(:instructor) { build(:instructor, id: 6) }
let(:instructor2) { build(:instructor, id: 66) }
let(:ta) { build(:teaching_assistant, id: 8) }
let(:student) { build(:student) }
let(:questionnaire) { build(:questionnaire, id: 666) }
let(:assignment_questionnaire) { build(:assignment_questionnaire, id: 1, questionnaire: questionnaire) }
before(:each) do
allow(Assignment).to receive(:find).with('1').and_return(assignment)
stub_current_user(instructor, instructor.role.name, instructor.role)
end
describe '#action_allowed?' do
context 'when params action is edit or update' do
before(:each) do
controller.params = { id: '1', action: 'edit' }
end
context 'when the role name of current user is super admin or admin' do
it 'allows certain action' do
stub_current_user(admin, admin.role.name, admin.role)
expect(controller.send(:action_allowed?)).to be true
end
end
context 'when current user is the instructor of current assignment' do
it 'allows certain action' do
expect(controller.send(:action_allowed?)).to be true
end
end
context 'when current user is the ta of the course which current assignment belongs to' do
it 'allows certain action' do
stub_current_user(ta, ta.role.name, ta.role)
allow(TaMapping).to receive(:exists?).with(ta_id: 8, course_id: 1).and_return(true)
expect(controller.send(:action_allowed?)).to be true
end
end
context 'when current user is a ta but not the ta of the course which current assignment belongs to' do
it 'does not allow certain action' do
stub_current_user(ta, ta.role.name, ta.role)
allow(TaMapping).to receive(:exists?).with(ta_id: 8, course_id: 1).and_return(false)
expect(controller.send(:action_allowed?)).to be false
end
end
context 'when current user is the instructor of the course which current assignment belongs to' do
it 'allows certain action' do
stub_current_user(instructor2, instructor2.role.name, instructor2.role)
allow(Course).to receive(:find).with(1).and_return(double('Course', instructor_id: 66))
expect(controller.send(:action_allowed?)).to be true
end
end
context 'when current user is an instructor but not the instructor of current course or current assignment' do
it 'does not allow certain action' do
stub_current_user(instructor2, instructor2.role.name, instructor2.role)
allow(Course).to receive(:find).with(1).and_return(double('Course', instructor_id: 666))
expect(controller.send(:action_allowed?)).to be false
end
end
end
context 'when params action is not edit and update' do
before(:each) do
controller.params = { id: '1', action: 'new' }
end
context 'when the role current user is super admin/admin/instructor/ta' do
it 'allows certain action except edit and update' do
expect(controller.send(:action_allowed?)).to be true
end
end
context 'when the role current user is student' do
it 'does not allow certain action' do
stub_current_user(student, student.role.name, student.role)
expect(controller.send(:action_allowed?)).to be false
end
end
end
end
describe '#new' do
it 'creates a new AssignmentForm object and renders assignment#new page' do
get :new
expect(response).to render_template(:new)
end
end
describe '#create' do
before(:each) do
allow(AssignmentForm).to receive(:new).with(any_args).and_return(assignment_form)
@used_params = {
button: true,
assignment_form: {
assignment_questionnaire: [{ 'assignment_id' => '1', 'questionnaire_id' => '666', 'dropdown' => 'true',
'questionnaire_weight' => '100', 'notification_limit' => '15', 'used_in_round' => '1' }],
due_date: [{ 'id' => '', 'parent_id' => '', 'round' => '1', 'deadline_type_id' => '1', 'due_at' => '2017/12/05 00:00', 'submission_allowed_id' => '3', 'review_allowed_id' => '1', 'teammate_review_allowed_id' => '3', 'review_of_review_allowed_id' => '1', 'threshold' => '1' },
{ 'id' => '', 'parent_id' => '', 'round' => '1', 'deadline_type_id' => '2', 'due_at' => '2017/12/02 00:00', 'submission_allowed_id' => '1', 'review_allowed_id' => '3', 'teammate_review_allowed_id' => '3', 'review_of_review_allowed_id' => '1', 'threshold' => '1' }],
assignment: {
instructor_id: 2,
course_id: 1,
max_team_size: 1,
id: 1,
name: 'test assignment',
directory_path: '/test',
spec_location: '',
private: false,
show_teammate_reviews: false,
require_quiz: false,
num_quiz_questions: 0,
staggered_deadline: false,
microtask: false,
reviews_visible_to_all: false,
is_calibrated: false,
availability_flag: true,
reputation_algorithm: 'Lauw',
simicheck: -1,
simicheck_threshold: 100
}
}
}
@new_params = {
button: true,
assignment_form: {
assignment_questionnaire: [{ 'assignment_id' => '1', 'questionnaire_id' => '666', 'dropdown' => 'true',
'questionnaire_weight' => '100', 'notification_limit' => '15', 'used_in_round' => '1' }],
due_date: [{ 'id' => '', 'parent_id' => '', 'round' => '1', 'deadline_type_id' => '1', 'due_at' => '2017/12/05 00:00', 'submission_allowed_id' => '3', 'review_allowed_id' => '1', 'teammate_review_allowed_id' => '3', 'review_of_review_allowed_id' => '1', 'threshold' => '1' },
{ 'id' => '', 'parent_id' => '', 'round' => '1', 'deadline_type_id' => '2', 'due_at' => '2017/12/02 00:00', 'submission_allowed_id' => '1', 'review_allowed_id' => '3', 'teammate_review_allowed_id' => '3', 'review_of_review_allowed_id' => '1', 'threshold' => '1' }],
assignment: {
instructor_id: 2,
course_id: 1,
max_team_size: 1,
id: 2,
name: 'new test assignment',
directory_path: 'new_test_assignment',
spec_location: '',
private: false,
show_teammate_reviews: false,
require_quiz: false,
num_quiz_questions: 0,
staggered_deadline: false,
microtask: false,
reviews_visible_to_all: false,
is_calibrated: false,
availability_flag: true,
reputation_algorithm: 'Lauw',
simicheck: -1,
simicheck_threshold: 100
}
}
}
end
context 'when assignment_form is saved successfully' do
it 'redirects to assignment#edit page' do
allow(assignment_form).to receive(:assignment).and_return(assignment2)
allow(Assignment).to receive(:find_by).with(name: 'new test assignment', course_id: 1).and_return(nil)
allow(Assignment).to receive(:find_by).with(directory_path: 'new_test_assignment', course_id: 1).and_return(nil)
allow(assignment_form).to receive(:save).and_return(true)
allow_any_instance_of(AssignmentsController).to receive(:assignment_by_name_and_course).and_return(assignment2)
allow(assignment_form).to receive(:create_assignment_node).and_return(double('node'))
allow(assignment_form).to receive(:update).with(any_args).and_return(true)
allow(Assignment).to receive(:find).and_return(assignment2)
allow(assignment2).to receive(:id).and_return('2')
allow_any_instance_of(AssignmentsController).to receive(:undo_link)
.with('Assignment "new test assignment" has been created successfully. ').and_return(true)
post :create, params: @new_params
expect(response).to redirect_to('/assignments/2/edit')
end
end
context 'when assignment_form is not saved successfully' do
it 'redirect to assignments#new page' do
allow(assignment_form).to receive(:save).and_return(false)
post :create, params: @used_params
expect(response).to redirect_to('/assignments/new?private=1')
end
end
# Create an assignment with name that already exists and expect the create method in assignments_controller_spec.rb to throw error
context 'when assignment_form name already exists and is not saved properly' do
it 'redirects to assignment#new page' do
allow(assignment_form).to receive(:assignment).and_return(assignment)
allow(Assignment).to receive(:find_by).with(any_args).and_return(false)
allow(assignment_form).to receive(:save).and_return(true)
allow(assignment_form).to receive(:create_assignment_node).and_return(double('node'))
allow(assignment_form).to receive(:update).with(any_args).and_return(true)
allow(assignment).to receive(:id).and_return(1)
allow(Assignment).to receive(:find_by).with(course_id: 1, name: 'test assignment').and_return(assignment)
post :create, params: @used_params
expect(flash[:error]).to eq('Failed to create assignment.<br> test assignment already exists as an assignment name')
expect(response).to redirect_to('/assignments/new?private=1')
end
end
end
describe '#edit' do
context 'when assignment has staggered deadlines' do
it 'shows an error flash message and renders edit page' do
allow(SignUpTopic).to receive(:where).with(assignment_id: assignment.id.to_s).and_return([double('SignUpTopic'), double('SignUpTopic')])
allow(AssignmentQuestionnaire).to receive(:where).with(assignment_id: assignment.id.to_s)
.and_return([assignment_questionnaire])
allow(Questionnaire).to receive(:where).with(id: assignment_questionnaire.questionnaire_id).and_return([double('Questionnaire', type: 'ReviewQuestionnaire')])
assignment_due_date = build(:assignment_due_date)
allow(AssignmentDueDate).to receive(:where).with(parent_id: assignment.id.to_s).and_return([assignment_due_date])
allow(assignment).to receive(:num_review_rounds).and_return(1)
request_params = { id: 1 }
user_session = { user: instructor }
get :edit, params: request_params, session: user_session
expect(flash.now[:error]).to eq('You did not specify all the necessary rubrics. You need <b>[AuthorFeedback, TeammateReview] '\
"</b> of assignment <b>test assignment</b> before saving the assignment. You can assign rubrics <a id='go_to_tabs2' style='color: blue;'>here</a>.")
expect(controller.instance_variable_get(:@metareview_allowed)).to be false
expect(controller.instance_variable_get(:@drop_topic_allowed)).to be false
expect(controller.instance_variable_get(:@signup_allowed)).to be false
expect(controller.instance_variable_get(:@team_formation_allowed)).to be false
expect(response).to render_template(:edit)
end
end
end
describe '#update' do
context 'when params does not have key :assignment_form' do
context 'when assignment is saved successfully' do
it 'shows a note flash message and redirects to tree_display#index page' do
allow(assignment).to receive(:save).and_return(true)
request_params = {
id: 1,
course_id: 1
}
user_session = { user: instructor }
post :update, params: request_params, session: user_session
expect(flash[:note]).to eq('The assignment was successfully saved.')
expect(response).to redirect_to('/tree_display/list')
end
end
context 'when assignment is not saved successfully' do
it 'displays an error flash message and redirects to assignments#edit page' do
allow(assignment).to receive(:save).and_return(false)
request_params = {
id: 1,
course_id: 1
}
user_session = { user: instructor }
post :update, params: request_params, session: user_session
expect(flash[:error]).to eq('Failed to save the assignment: ')
expect(response).to redirect_to('/assignments/1/edit')
end
end
end
context 'when params has key :assignment_form' do
before(:each) do
new_assignment_questionnaire = AssignmentQuestionnaire.new
allow(AssignmentQuestionnaire).to receive(:where).with(assignment_id: '1').and_return([assignment_questionnaire])
allow(AssignmentQuestionnaire).to receive(:where).with(assignment_id: 2).and_return([])
allow(AssignmentQuestionnaire).to receive(:where).with(assignment_id: 2, used_in_round: anything).and_return([])
allow(AssignmentQuestionnaire).to receive(:where).with(user_id: anything, assignment_id: nil, questionnaire_id: nil).and_return([])
allow(AssignmentQuestionnaire).to receive(:new).and_return(new_assignment_questionnaire)
allow(Questionnaire).to receive(:find).with('666').and_return(questionnaire)
allow(new_assignment_questionnaire).to receive(:save).and_return(true)
@params = {
vary_by_topic?: true,
id: 1,
course_id: 1,
set_pressed: {
bool: 'true'
},
assignment_form: {
assignment_questionnaire: [{ 'assignment_id' => '1', 'questionnaire_id' => '666', 'dropdown' => 'true',
'questionnaire_weight' => '0', 'notification_limit' => '15', 'used_in_round' => '1' }],
assignment: {
instructor_id: 2,
course_id: 1,
max_team_size: 1,
id: 2,
name: 'test assignment',
directory_path: '/test',
spec_location: '',
show_teammate_reviews: false,
require_quiz: false,
num_quiz_questions: 0,
staggered_deadline: false,
microtask: false,
reviews_visible_to_all: false,
is_calibrated: false,
availability_flag: true,
reputation_algorithm: 'Lauw',
simicheck: -1,
simicheck_threshold: 100
}
}
}
end
context 'when the timezone preference of current user is nil and assignment form updates attributes successfully' do
it 'shows an error message and redirects to assignments#edit page' do
instructor.timezonepref = nil
allow(User).to receive(:find).and_return(double('User', timezonepref: 'Eastern Time (US & Canada)'))
user_session = { user: instructor }
post :update, params: @params, session: user_session
expect(flash[:note]).to eq('The assignment was successfully saved....')
expect(flash[:error]).to eq('We strongly suggest that instructors specify their preferred timezone to guarantee the correct display time. '\
'For now we assume you are in Eastern Time (US & Canada)')
expect(response).to render_template('assignments/edit/_topics')
end
end
context 'when update assignment_form of the assignment with @params attributes' do
it 'renders assignments/edit/_topic page' do
user_session = { user: instructor }
post :update, params: @params, session: user_session
expect(flash[:note]).to eq('The assignment was successfully saved....')
expect(flash[:error]).to be nil
expect(response).to render_template('assignments/edit/_topics')
end
end
context 'when update assignment_form is called on an empty questionnaire of non-zero weight' do
it 'shows an error message and redirects to assignments#edit page' do
@params[:assignment_form][:assignment_questionnaire][0]['questionnaire_weight'] = '100'
user_session = { user: instructor }
post :update, params: @params, session: user_session
expect(flash[:note]).to eq('The assignment was successfully saved....')
expect(flash[:error]).to eq('A rubric has no ScoredQuestions, but still has a weight. Please change the weight to 0.')
expect(response).to render_template('assignments/edit/_topics')
end
end
end
end
describe '#show' do
it 'renders assignments#show page' do
get :show, params: { id: 1 }
expect(response).to render_template(:show)
end
end
describe '#copy' do
let(:new_assignment) { build(:assignment, id: 2, name: 'new_assignment', directory_path: 'new_assignment') }
let(:new_assignment2) { build(:assignment, id: 2, name: 'new_assignment2', directory_path: 'new_assignment2') }
context 'when new assignment id fetches successfully' do
it 'redirects to assignments#edit page' do
allow(assignment).to receive(:dup).and_return(new_assignment)
allow(new_assignment).to receive(:save).and_return(true)
allow(Assignment).to receive(:find).with(2).and_return(new_assignment)
request_params = { id: 1 }
get :copy, params: request_params
expect(flash[:note]).to be_nil
expect(flash[:error]).to be_nil
expect(response).to redirect_to('/assignments/2/edit')
end
end
context 'when new assignment id does not fetch successfully' do
it 'shows an error flash message and redirects to assignments#edit page' do
allow(assignment).to receive(:dup).and_return(new_assignment)
allow(new_assignment).to receive(:save).and_return(false)
request_params = { id: 1 }
get :copy, params: request_params
expect(flash[:note]).to be_nil
expect(flash[:error]).to eq('The assignment was not able to be copied. Please check the original assignment for missing information.')
expect(response).to redirect_to('/tree_display/list')
end
end
end
describe '#delete' do
context 'when assignment is deleted successfully' do
it 'shows a success flash message and redirects to tree_display#list page' do
assignment_form = AssignmentForm.new
allow(AssignmentForm).to receive(:new).and_return(assignment_form)
allow(assignment_form).to receive(:delete).with('true').and_return(true)
request_params = {
id: 1,
force: 'true'
}
user_session = { user: instructor }
post :delete, params: request_params, session: user_session
expect(flash[:error]).to be nil
expect(flash[:success]).to eq('The assignment was successfully deleted.')
expect(response).to redirect_to('/tree_display/list')
end
end
context 'when assignment is not deleted successfully' do
it 'shows an error flash message and redirects to tree_display#list page' do
assignment_form = AssignmentForm.new
allow(AssignmentForm).to receive(:new).and_return(assignment_form)
allow(assignment_form).to receive(:delete).with('true').and_raise('You cannot delete this assignment!')
request_params = {
id: 1,
force: 'true'
}
user_session = { user: instructor }
post :delete, params: request_params, session: user_session
expect(flash[:success]).to be nil
expect(flash[:error]).to eq('You cannot delete this assignment!')
expect(response).to redirect_to('/tree_display/list')
end
end
end
describe '#remove_assignment_from_course' do
context 'when assignment is removed from course successfully' do
it 'removes assignment and redirects to tree_display#list page' do
assignment_form = AssignmentForm.new
allow(AssignmentForm).to receive(:new).and_return(assignment_form)
allow(assignment_form).to receive(:remove_assignment_from_course)
allow(Assignment).to receive(:find).and_return(assignment)
allow(assignment).to receive(:save).and_return(true)
user_session = { user: instructor }
get :remove_assignment_from_course, params: { id: 1 }
expect(flash[:error]).to be nil
expect(response).to redirect_to('/tree_display/list')
end
end
end
describe '#list_submissions' do
context 'when submissions are listed successfully' do
it 'gets list of submissions' do
assignment_form = AssignmentForm.new
allow(AssignmentForm).to receive(:new).and_return(assignment_form)
allow(assignment_form).to receive(:list_submissions).with('true')
request_params = {
id: 1,
force: 'true'
}
user_session = { user: instructor }
get :list_submissions, params: request_params, session: user_session
expect(flash[:error]).to be nil
end
end
end
end