diff --git a/app/api/tutorials_api.rb b/app/api/tutorials_api.rb index b768f6792..57b554c88 100644 --- a/app/api/tutorials_api.rb +++ b/app/api/tutorials_api.rb @@ -65,7 +65,7 @@ class TutorialsApi < Grape::API requires :meeting_location, type: String, desc: 'The tutorials location', allow_blank: false requires :meeting_day, type: String, desc: 'Day of the tutorial', allow_blank: false requires :meeting_time, type: String, desc: 'Time of the tutorial', allow_blank: false - optional :tutorial_stream_abbr, type: String, desc: 'Abbreviation of the associated tutorial stream', allow_blank: false + requires :tutorial_stream_abbr, type: String, desc: 'Abbreviation of the associated tutorial stream', allow_blank: false end end post '/tutorials' do @@ -83,6 +83,10 @@ class TutorialsApi < Grape::API tutorial_stream_abbr = tut_params[:tutorial_stream_abbr] tutorial_stream = unit.tutorial_streams.find_by!(abbreviation: tutorial_stream_abbr) unless tutorial_stream_abbr.nil? + unless tutorial_stream + error!({ error: 'Tutorial must belong to a tutorial stream' }, 403) + end + tutorial = unit.add_tutorial(tut_params[:meeting_day], tut_params[:meeting_time], tut_params[:meeting_location], tutor, campus, tut_params[:capacity], tut_params[:abbreviation], tutorial_stream) present tutorial, with: Entities::TutorialEntity diff --git a/app/models/overseer_assessment.rb b/app/models/overseer_assessment.rb index 84a2077dd..13c76218e 100644 --- a/app/models/overseer_assessment.rb +++ b/app/models/overseer_assessment.rb @@ -20,7 +20,7 @@ class OverseerAssessment < ApplicationRecord # TODO: we might not have an overseerStepResult because a new test was added later # Creates an OverseerAssessment object for a new submission - def self.create_for(task, test_submission) + def self.create_for(task, _timestamp, test_submission) # Create only if: # unit's assessment is enabled && # task's assessment is enabled && @@ -60,6 +60,7 @@ def has_submission_files? end def submission_zip_file_name + # /submission_history/{UNIT}/{USERNAME}/done/submission.zip "#{output_path}/submission.zip" end @@ -77,6 +78,8 @@ def copy_latest_files_to_submission task.compress_new_to_done zip_file_path: zip_file_path, rm_task_dir: false, rename_files: true else puts "Copying done file to submission at: #{zip_file_path}" + # TODO: here is where we might want to refactor submission history - enabling it separate from overseer + # TODO: so if "submission history" is enabled for an upload req, task.copy_done_to zip_file_path end end diff --git a/app/models/submission_history.rb b/app/models/submission_history.rb new file mode 100644 index 000000000..c05f12ddf --- /dev/null +++ b/app/models/submission_history.rb @@ -0,0 +1,61 @@ +class SubmissionHistory < ApplicationRecord + + # TODO: so a submission history is going to be created after AcceptSubmissionJob completes successfully + + belongs_to :task, optional: false + has_one :project, through: :task + + def self.create_for(task) + task_definition = task.task_definition + unit = task_definition.unit + + result = SubmissionHistory.create!( + # task: task, + # status: :pre_queued, + submission_timestamp: Time.now.utc.to_i + ) + + # Create the submission folder and give access + FileUtils.mkdir_p result.output_path + result.grant_access_to_submission + + result.copy_latest_files_to_submission + + result + end + + def has_submission_files? + File.exist? submission_zip_file_name + end + + def submission_zip_file_name + # /submission_history/{UNIT}/{USERNAME}/done/submission.zip + "#{output_path}/submission.zip" + end + + def grant_access_to_submission + # TODO: Use FACL instead in future. + `chmod o+w #{output_path}` + end + + def copy_latest_files_to_submission + zip_file_path = submission_zip_file_name + + if task.has_new_files? + puts "Copying new files to submission at: #{zip_file_path}" + # Generate a zip file for this particular submission with timestamp value and put it here + task.compress_new_to_done zip_file_path: zip_file_path, rm_task_dir: false, rename_files: true + else + puts "Copying done file to submission at: #{zip_file_path}" + # TODO: here is where we might want to refactor submission history - enabling it separate from overseer + # TODO: so if "submission history" is enabled for an upload req, + task.copy_done_to zip_file_path + end + end + + # Path to where the submission and output are stored - includes the submission when it is to be processed + def output_path + FileHelper.task_submission_identifier_path_with_timestamp(:done, task, submission_timestamp) + end + +end diff --git a/app/sidekiq/accept_submission_job.rb b/app/sidekiq/accept_submission_job.rb index 15a92d084..a690aa0bc 100644 --- a/app/sidekiq/accept_submission_job.rb +++ b/app/sidekiq/accept_submission_job.rb @@ -60,13 +60,16 @@ def perform(task_id, user_id, accepted_tii_eula, test_submission) task.send_documents_to_tii(user, accepted_tii_eula: accepted_tii_eula) end - if task.overseer_enabled? || test_submission - overseer_assessment = OverseerAssessment.create_for(task, test_submission) + # Save a snapshot of the submission files to view later + # TODO: enable historu for a task definition? or per upload requirement? + submission_history = SubmissionHistory.create_for(task) + + if submission_history.present? && (task.overseer_enabled? || test_submission) + # TODO: pass the submission_history ID or timestamp to overseer, to access the submission_history directory + overseer_assessment = OverseerAssessment.create_for(submission_history.timestamp, task, test_submission) if overseer_assessment.present? logger.info "Launching Overseer assessment for task_def_id: #{task.task_definition.id} task_id: #{task.id}" - overseer_assessment.send_to_overseer(test_submission: test_submission) - else logger.info "Overseer assessment for task_def_id: #{task.task_definition.id} task_id: #{task.id} was not performed #{overseer_assessment.inspect}" end diff --git a/db/migrate/20260227012857_create_submission_histories.rb b/db/migrate/20260227012857_create_submission_histories.rb new file mode 100644 index 000000000..891cb7234 --- /dev/null +++ b/db/migrate/20260227012857_create_submission_histories.rb @@ -0,0 +1,9 @@ +class CreateSubmissionHistories < ActiveRecord::Migration[8.0] + def change + create_table :submission_histories do |t| + t.references :task + t.integer :submission_timestamp + t.timestamps + end + end +end diff --git a/test/api/tutorials_test.rb b/test/api/tutorials_test.rb index 159003e5b..63e27fc3c 100644 --- a/test/api/tutorials_test.rb +++ b/test/api/tutorials_test.rb @@ -16,7 +16,7 @@ def app # --------------------------------------------------------------------------- # - #####----------POST tests - Create tutorial----------##### + # ####----------POST tests - Create tutorial----------##### def assert_tutorial_model_response(response, expected) assert_json_matches_model expected, response, %w[id meeting_day meeting_time meeting_location abbreviation campus_id capacity] @@ -28,6 +28,7 @@ def test_unit_main_convenor_can_post_tutorials campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: unit.id, @@ -37,7 +38,8 @@ def test_unit_main_convenor_can_post_tutorials abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation } data_to_post = { @@ -69,6 +71,7 @@ def test_unit_admin_can_post_tutorials campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: unit.id, @@ -78,7 +81,9 @@ def test_unit_admin_can_post_tutorials abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation + } data_to_post = { @@ -115,6 +120,7 @@ def test_post_tutorial_with_string_meeting_time campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.second + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: unit.id, @@ -124,7 +130,9 @@ def test_post_tutorial_with_string_meeting_time abbreviation: 'La011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: 'string' + meeting_time: 'string', + tutorial_stream_abbr: tutorial_stream.abbreviation + } data_to_post = { @@ -155,6 +163,7 @@ def test_post_tutorial_with_incorrect_auth_token campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: unit.id, @@ -164,7 +173,9 @@ def test_post_tutorial_with_incorrect_auth_token abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation + } data_to_post = { @@ -192,6 +203,7 @@ def test_post_tutorial_with_empty_auth_token campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: unit.id, @@ -201,7 +213,9 @@ def test_post_tutorial_with_empty_auth_token abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation + } data_to_post = { @@ -211,8 +225,8 @@ def test_post_tutorial_with_empty_auth_token # Add username and auth_token to Header add_auth_header_for(user: User.first) - #Override header for empty auth_token - header 'auth_token','' + # Override header for empty auth_token + header 'auth_token', '' # Number of tutorials before POST number_of_tutorials = Tutorial.all.length @@ -232,6 +246,7 @@ def test_post_tutorial_with_string_unit_id campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: 'string', @@ -241,7 +256,9 @@ def test_post_tutorial_with_string_unit_id abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation + } data_to_post = { @@ -270,6 +287,7 @@ def test_post_tutorial_with_string_tutor_id campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: unit.id, @@ -279,7 +297,9 @@ def test_post_tutorial_with_string_tutor_id abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation + } data_to_post = { @@ -308,6 +328,7 @@ def test_post_existing_values campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: unit.id, @@ -317,7 +338,9 @@ def test_post_existing_values abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation + } data_to_post = { @@ -366,6 +389,7 @@ def test_post_tutorial_with_empty_unit_id campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: '', @@ -375,7 +399,9 @@ def test_post_tutorial_with_empty_unit_id abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation + } data_to_post = { @@ -404,6 +430,7 @@ def test_post_tutorial_with_empty_tutor_id campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: unit.id, @@ -413,7 +440,9 @@ def test_post_tutorial_with_empty_tutor_id abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation + } data_to_post = { @@ -442,6 +471,7 @@ def test_post_tutorial_with_empty_abbreviation campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: unit.id, @@ -451,7 +481,8 @@ def test_post_tutorial_with_empty_abbreviation abbreviation: '', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation } data_to_post = { @@ -480,6 +511,7 @@ def test_post_tutorial_with_empty_meeting_location campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: unit.id, @@ -489,7 +521,9 @@ def test_post_tutorial_with_empty_meeting_location abbreviation: 'LA011', meeting_location: '', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation + } data_to_post = { @@ -518,6 +552,7 @@ def test_post_tutorial_with_empty_meeting_day campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: unit.id, @@ -527,7 +562,9 @@ def test_post_tutorial_with_empty_meeting_day abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: '', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation + } data_to_post = { @@ -556,6 +593,7 @@ def test_post_tutorial_with_empty_meeting_time campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: unit.id, @@ -565,7 +603,9 @@ def test_post_tutorial_with_empty_meeting_time abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '' + meeting_time: '', + tutorial_stream_abbr: tutorial_stream.abbreviation + } data_to_post = { @@ -594,6 +634,7 @@ def test_tutor_cannot_post_tutorials campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: unit.id, @@ -603,11 +644,12 @@ def test_tutor_cannot_post_tutorials abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation } data_to_post = { - tutorial: tutorial, + tutorial: tutorial } # Create and add a dedicated tutor into the unit @@ -636,6 +678,7 @@ def test_student_cannot_post_tutorials campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: unit.id, @@ -645,11 +688,12 @@ def test_student_cannot_post_tutorials abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation } data_to_post = { - tutorial: tutorial, + tutorial: tutorial } number_of_tutorials = Tutorial.all.length @@ -669,7 +713,7 @@ def test_student_cannot_post_tutorials assert_equal Tutorial.all.length, number_of_tutorials end - #####----------PUT tests - Update a tutorial----------##### + # ####----------PUT tests - Update a tutorial----------##### # Testing for successful PUT operations def test_admin_can_put_tutorials @@ -680,6 +724,7 @@ def test_admin_can_put_tutorials campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { id: tutorial_old.id, @@ -690,7 +735,8 @@ def test_admin_can_put_tutorials abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation } data_to_put = { @@ -725,6 +771,7 @@ def test_put_tutorials_with_empty_abbreviation campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { id: tutorial_old.id, @@ -735,7 +782,8 @@ def test_put_tutorials_with_empty_abbreviation abbreviation: '', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation } data_to_put = { @@ -770,6 +818,7 @@ def test_tutorials_put_empty_meeting_location campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { id: tutorial_old.id, @@ -780,7 +829,8 @@ def test_tutorials_put_empty_meeting_location abbreviation: 'LA011', meeting_location: '', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation } data_to_put = { @@ -815,6 +865,7 @@ def test_put_tutorials_with_empty_meeting_day campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { id: tutorial_old.id, @@ -825,7 +876,8 @@ def test_put_tutorials_with_empty_meeting_day abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: '', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation } data_to_put = { @@ -860,6 +912,7 @@ def test_tutorials_put_empty_meeting_time campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { id: tutorial_old.id, @@ -870,7 +923,8 @@ def test_tutorials_put_empty_meeting_time abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '' + meeting_time: '', + tutorial_stream_abbr: tutorial_stream.abbreviation } data_to_put = { @@ -906,6 +960,7 @@ def test_put_tutorials_with_empty_auth_token campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: unit.id, @@ -915,7 +970,8 @@ def test_put_tutorials_with_empty_auth_token abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation } data_to_put = { @@ -925,8 +981,8 @@ def test_put_tutorials_with_empty_auth_token # Add username and auth_token to Header add_auth_header_for(user: User.first) - #Override header for empty auth_token - header 'auth_token','' + # Override header for empty auth_token + header 'auth_token', '' # perform the PUT with empty auth token put_json "/api/tutorials/#{tutorial_old.id}", data_to_put @@ -943,6 +999,7 @@ def test_put_tutorials_with_incorrect_auth_token campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: unit.id, @@ -952,7 +1009,8 @@ def test_put_tutorials_with_incorrect_auth_token abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation } data_to_put = { @@ -977,6 +1035,7 @@ def test_main_convenor_cannot_replace_tutorials campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: unit.id, @@ -986,7 +1045,8 @@ def test_main_convenor_cannot_replace_tutorials abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation } data_to_put = { @@ -1004,13 +1064,14 @@ def test_main_convenor_cannot_replace_tutorials end def test_tutor_cannot_replace_tutorial - # Create a dummy tutorial - tutorial_old = FactoryBot.create(:tutorial) + # Create a dummy tutorial + tutorial_old = FactoryBot.create(:tutorial) - # Create dummy attributes for the tutorial - campus = FactoryBot.create(:campus) - unit = FactoryBot.create(:unit) - tutor = unit.tutors.first + # Create dummy attributes for the tutorial + campus = FactoryBot.create(:campus) + unit = FactoryBot.create(:unit) + tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: unit.id, @@ -1020,7 +1081,9 @@ def test_tutor_cannot_replace_tutorial abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation + } data_to_put = { @@ -1050,6 +1113,7 @@ def test_student_cannot_replace_tutorials campus = FactoryBot.create(:campus) unit = FactoryBot.create(:unit) tutor = unit.tutors.first + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: unit.id, @@ -1059,7 +1123,9 @@ def test_student_cannot_replace_tutorials abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation + } data_to_put = { @@ -1079,7 +1145,7 @@ def test_student_cannot_replace_tutorials assert_equal 403, last_response.status end - #####----------DELETE tests - Delete a tutorial----------##### + # ####----------DELETE tests - Delete a tutorial----------##### # Testing for successful DELETEs def test_admin_delete_tutorial @@ -1113,7 +1179,7 @@ def test_admin_delete_tutorial assert_equal number_of_tutorials - 1, Tutorial.all.length # Check that you can't find the deleted id - refute Tutorial.exists?(tutorial.id) + assert_not Tutorial.exists?(tutorial.id) end def test_convenor_delete_tutorial @@ -1142,7 +1208,7 @@ def test_convenor_delete_tutorial assert_equal number_of_tutorials - 1, Tutorial.all.length # Check that you can't find the deleted id - refute Tutorial.exists?(tutorial.id) + assert_not Tutorial.exists?(tutorial.id) end # Testing for DELELTE failures @@ -1211,8 +1277,8 @@ def test_delete_tutorials_with_empty_auth_token # Add username and auth_token to Header add_auth_header_for(user: User.first) - #Override header for empty auth_token - header 'auth_token','' + # Override header for empty auth_token + header 'auth_token', '' # perform the delete with empty auth token delete_json "/api/tutorials/#{tutorial.id}" @@ -1221,7 +1287,7 @@ def test_delete_tutorials_with_empty_auth_token assert_equal 419, last_response.status # Check number of tutorials does not change - assert_equal number_of_tutorials , Tutorial.all.length + assert_equal number_of_tutorials, Tutorial.all.length # Check that you still can find the deleted id assert Tutorial.exists?(tutorial.id) @@ -1234,8 +1300,8 @@ def test_delete_tutorials_with_incorrect_auth_token # Add username and auth_token to Header add_auth_header_for(username: 'aadmin', auth_token: 'incorrect_auth_token') - # Number of tutorials before DELETE - number_of_tutorials = Tutorial.all.length + # Number of tutorials before DELETE + number_of_tutorials = Tutorial.all.length # perform the delete with incorrect auth token delete_json "/api/tutorials/#{tutorial.id}" @@ -1244,7 +1310,7 @@ def test_delete_tutorials_with_incorrect_auth_token assert_equal 419, last_response.status # Check number of tutorials does not change - assert_equal number_of_tutorials , Tutorial.all.length + assert_equal number_of_tutorials, Tutorial.all.length # Check that you still can find the deleted id assert Tutorial.exists?(tutorial.id) @@ -1252,7 +1318,7 @@ def test_delete_tutorials_with_incorrect_auth_token def test_student_cannot_delete_tutorial # Tutorial to delete - tutorial = FactoryBot.create (:tutorial) + tutorial = FactoryBot.create(:tutorial) # Number of tutorials before deletion number_of_tutorials = Tutorial.count @@ -1305,6 +1371,84 @@ def test_student_change_tutorial assert_equal 403, last_response.status - refute project.enrolled_in? tutorial + assert_not project.enrolled_in? tutorial + end + + def test_post_tutorial_with_no_tutorial_stream + # Create dummy attributes for the tutorial + campus = FactoryBot.create(:campus) + unit = FactoryBot.create(:unit) + tutor = unit.tutors.first + + tutorial = { + unit_id: unit.id, + tutor_id: tutor.id, + campus_id: campus.id, + capacity: 10, + abbreviation: 'LA011', + meeting_location: 'LAB34', + meeting_day: 'Tuesday', + meeting_time: '18:00', + tutorial_stream_abbr: '' + } + + data_to_post = { + tutorial: tutorial + } + + # Number of tutorials before POST + number_of_tutorials = Tutorial.all.length + + # Add username and auth_token to Header + add_auth_header_for(user: unit.main_convenor_user) + + # perform the post with the unit main convenor auth token + post_json '/api/tutorials', data_to_post + + # Check for error in creation + assert_equal 400, last_response.status + assert last_response_body['error'].include? 'tutorial[tutorial_stream_abbr] is empty' + + # Check if there is no new tutorial + assert_equal Tutorial.all.length, number_of_tutorials + end + + def test_post_tutorial_with_invalid_tutorial_stream + # Create dummy attributes for the tutorial + campus = FactoryBot.create(:campus) + unit = FactoryBot.create(:unit) + tutor = unit.tutors.first + + tutorial = { + unit_id: unit.id, + tutor_id: tutor.id, + campus_id: campus.id, + capacity: 10, + abbreviation: 'LA011', + meeting_location: 'LAB34', + meeting_day: 'Tuesday', + meeting_time: '18:00', + tutorial_stream_abbr: 'non-existing-tutorial-stream' + } + + data_to_post = { + tutorial: tutorial + } + + # Number of tutorials before POST + number_of_tutorials = Tutorial.all.length + + # Add username and auth_token to Header + add_auth_header_for(user: unit.main_convenor_user) + + # perform the post with the unit main convenor auth token + post_json '/api/tutorials', data_to_post + + # Check for error in creation + assert_equal 404, last_response.status, last_response_body + assert last_response_body['error'].include?('Unable to find requested TutorialStream'), last_response_body['error'] + + # Check if there is no new tutorial + assert_equal Tutorial.all.length, number_of_tutorials end end diff --git a/test/api/units_api_test.rb b/test/api/units_api_test.rb index 5342ae80f..9ff3ed5d0 100644 --- a/test/api/units_api_test.rb +++ b/test/api/units_api_test.rb @@ -163,6 +163,7 @@ def test_post_create_unit_empty_token def test_add_tutorial_to_unit unit = FactoryBot.create :unit, with_students: false, stream_count: 0 count_tutorials = Tutorial.all.length + tutorial_stream = FactoryBot.create(:tutorial_stream, unit: unit) tutorial = { unit_id: unit.id, @@ -172,7 +173,8 @@ def test_add_tutorial_to_unit abbreviation: 'LA011', meeting_location: 'LAB34', meeting_day: 'Tuesday', - meeting_time: '18:00' + meeting_time: '18:00', + tutorial_stream_abbr: tutorial_stream.abbreviation } data_to_post = { diff --git a/test/factories/submission_histories.rb b/test/factories/submission_histories.rb new file mode 100644 index 000000000..5eb42cb32 --- /dev/null +++ b/test/factories/submission_histories.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory :submission_history do + + end +end diff --git a/test/models/submission_history_test.rb b/test/models/submission_history_test.rb new file mode 100644 index 000000000..3d169aaea --- /dev/null +++ b/test/models/submission_history_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +describe SubmissionHistory do + # it "does a thing" do + # value(1+1).must_equal 2 + # end +end