diff --git a/.rubocop.yml b/.rubocop.yml index 7935d9186..5f80c35e6 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,4 +1,8 @@ -require: rubocop-rails +require: + - rubocop-rails + - rubocop-capybara + - rubocop-factory_bot + - rubocop-graphql AllCops: NewCops: enable Exclude: @@ -47,6 +51,10 @@ Metrics/PerceivedComplexity: Max: 13 Naming/PredicateName: Enabled: false +Naming/BlockForwarding: + EnforcedStyle: explicit +Style/ArgumentsForwarding: + UseAnonymousForwarding: false Metrics/ModuleLength: Exclude: - app/helpers/**/* @@ -63,4 +71,4 @@ Style/WordArray: Rails/EagerEvaluationLogMessage: Enabled: false Rails/I18nLocaleTexts: - Enabled: false \ No newline at end of file + Enabled: false diff --git a/Gemfile b/Gemfile index 8b2997f63..d0a31bbfb 100644 --- a/Gemfile +++ b/Gemfile @@ -63,6 +63,9 @@ group :development do gem 'better_errors' gem 'binding_of_caller' + gem 'rubocop-capybara' + gem 'rubocop-factory_bot' + gem 'rubocop-graphql' gem 'rubocop-rails' gem 'spring', '4.0.0' # Access an interactive console on exception pages or by calling 'console' anywhere in the code. diff --git a/Gemfile.lock b/Gemfile.lock index db22b2bb6..bfd2f29ca 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -318,6 +318,12 @@ GEM unicode-display_width (>= 2.4.0, < 3.0) rubocop-ast (1.32.3) parser (>= 3.3.1.0) + rubocop-capybara (2.21.0) + rubocop (~> 1.41) + rubocop-factory_bot (2.26.1) + rubocop (~> 1.61) + rubocop-graphql (1.5.4) + rubocop (>= 1.50, < 2) rubocop-rails (2.26.1) activesupport (>= 4.2.0) rack (>= 1.1) @@ -411,6 +417,9 @@ DEPENDENCIES puma (~> 6.4) rails (~> 6.1) react-rails + rubocop-capybara + rubocop-factory_bot + rubocop-graphql rubocop-rails rubyzip selenium-webdriver diff --git a/app/channels/graphql_channel.rb b/app/channels/graphql_channel.rb index 6ec43dd2e..7f81ccc53 100644 --- a/app/channels/graphql_channel.rb +++ b/app/channels/graphql_channel.rb @@ -14,16 +14,16 @@ def execute(data) access_cache: {}, # Re-implement whatever context methods you need # in this channel or ApplicationCable::Channel - current_user: current_user, + current_user:, # Make sure the channel is in the context channel: self, } result = HourglassSchema.execute( query, - context: context, - variables: variables, - operation_name: operation_name, + context:, + variables:, + operation_name:, ) payload = { diff --git a/app/controllers/api/student/exams_controller.rb b/app/controllers/api/student/exams_controller.rb index dc58139e9..7fb5d9713 100644 --- a/app/controllers/api/student/exams_controller.rb +++ b/app/controllers/api/student/exams_controller.rb @@ -30,7 +30,7 @@ def require_current_user_unique_session user_id: e.user.id, exam_id: params[:exam_id], ) - Anomaly.create(registration: registration, reason: e.message) if registration + Anomaly.create(registration:, reason: e.message) if registration render json: { lockout: true, reason: e.message } end @@ -92,7 +92,7 @@ def start_exam! start: @registration.start_time, stop: @registration.effective_end_time, }, - answers: answers, + answers:, } end diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb index e29aadf6d..7a62e014d 100644 --- a/app/controllers/graphql_controller.rb +++ b/app/controllers/graphql_controller.rb @@ -22,14 +22,14 @@ def execute query = params[:query] operation_name = params[:operationName] context = { - current_user: current_user, - true_user: true_user, + current_user:, + true_user:, impersonate_user: ->(user) { impersonate_user(user) }, stop_impersonating_user: -> { stop_impersonating_user }, - bottlenose_api: bottlenose_api, + bottlenose_api:, access_cache: {}, } - result = HourglassSchema.execute(query, variables: variables, context: context, operation_name: operation_name) + result = HourglassSchema.execute(query, variables:, context:, operation_name:) render json: result end diff --git a/app/models/anomaly.rb b/app/models/anomaly.rb index 041c10184..c522970e4 100644 --- a/app/models/anomaly.rb +++ b/app/models/anomaly.rb @@ -27,7 +27,7 @@ def exam_version def trigger_subscription exam_id = HourglassSchema.id_from_object(exam, Types::ExamType, {}) - HourglassSchema.subscriptions.trigger(:anomaly_was_created, { exam_id: exam_id }, self) + HourglassSchema.subscriptions.trigger(:anomaly_was_created, { exam_id: }, self) end def visible_to?(check_user, role_for_exam, _role_for_course) diff --git a/app/models/body_item.rb b/app/models/body_item.rb index f21ab3826..fda0b620f 100644 --- a/app/models/body_item.rb +++ b/app/models/body_item.rb @@ -52,9 +52,9 @@ def valid_file_refs_code_tag before_save do if rubrics.empty? rubrics.build( - exam_version: exam_version, - question: question, - part: part, + exam_version:, + question:, + part:, body_item: self, type: 'None', ) @@ -83,12 +83,12 @@ def as_json(format:) else if format == :graphql return { - info: info, + info:, id: HourglassSchema.id_from_object(self, Types::BodyItemType, {}), } end - send("as_json_#{info['type']}", format: format) + send("as_json_#{info['type']}", format:) end end @@ -100,7 +100,7 @@ def rubric_as_json(format:) if root_rubric.nil? || root_rubric.is_a?(None) nil else - root_rubric.as_json(format: format).deep_stringify_keys + root_rubric.as_json(format:).deep_stringify_keys end end @@ -116,7 +116,7 @@ def as_json_AllThatApply(format:) 'options' => info['options'].zip(answer).map do |opt, ans| { BodyItem.html_val(format, opt) => ans } end, - 'rubric' => rubric_as_json(format: format), + 'rubric' => rubric_as_json(format:), }.compact, } end @@ -142,7 +142,7 @@ def as_json_Code(format:) else MarksProcessor.process_marks_reverse(answer['text'], answer['marks']) end, - 'rubric' => rubric_as_json(format: format), + 'rubric' => rubric_as_json(format:), }.compact, } end @@ -174,7 +174,7 @@ def as_json_CodeTag(format:) 'filename' => answer['selectedFile'], 'line' => answer['lineNumber'], }, - 'rubric' => rubric_as_json(format: format), + 'rubric' => rubric_as_json(format:), }.compact, } end @@ -188,7 +188,7 @@ def as_json_Matching(format:) 'prompts' => BodyItem.html_vals(format, info['prompts']), 'values' => BodyItem.html_vals(format, info['values']), 'correctAnswers' => answer, - 'rubric' => rubric_as_json(format: format), + 'rubric' => rubric_as_json(format:), }.compact, } end @@ -199,7 +199,7 @@ def as_json_MultipleChoice(format:) 'prompt' => BodyItem.html_val(format, info['prompt']), 'options' => BodyItem.html_vals(format, info['options']), 'correctAnswer' => answer, - 'rubric' => rubric_as_json(format: format), + 'rubric' => rubric_as_json(format:), }.compact, } end @@ -214,7 +214,7 @@ def as_json_Text(format:) else BodyItem.html_val(format, answer&.dig('text')) end, - 'rubric' => rubric_as_json(format: format), + 'rubric' => rubric_as_json(format:), }.compact, } end @@ -229,7 +229,7 @@ def as_json_YesNo(format:) 'YesNo' => { 'prompt' => BodyItem.html_val(format, info['prompt']), 'correctAnswer' => answer, - 'rubric' => rubric_as_json(format: format), + 'rubric' => rubric_as_json(format:), }.compact, } end @@ -241,7 +241,7 @@ def as_json_YesNo(format:) 'TrueFalse' => { 'prompt' => BodyItem.html_val(format, info['prompt']), 'correctAnswer' => answer, - 'rubric' => rubric_as_json(format: format), + 'rubric' => rubric_as_json(format:), }.compact, } end @@ -281,7 +281,7 @@ def html_vals(format, val) def from_yaml_AllThatApply(type, options:, prompt: nil) BodyItem.new( info: { - type: type, + type:, prompt: html_val(:graphql, prompt), options: html_vals(:graphql, options.map(&:keys).flatten), }.compact, @@ -311,12 +311,12 @@ def from_yaml_Code(type, initial: nil, prompt: nil, lang: nil, correct_answer: n end BodyItem.new( info: { - type: type, + type:, prompt: html_val(:graphql, prompt), - lang: lang, - initial: initial, + lang:, + initial:, }.compact, - answer: answer, + answer:, ) end @@ -334,9 +334,9 @@ def from_yaml_CodeSnippet(type, initial: nil, lang: nil) end BodyItem.new( info: { - type: type, - lang: lang, - initial: initial, + type:, + lang:, + initial:, }.compact, ) end @@ -344,8 +344,8 @@ def from_yaml_CodeSnippet(type, initial: nil, lang: nil) def from_yaml_CodeTag(type, choices:, correct_answer:, prompt: nil) BodyItem.new( info: { - type: type, - choices: choices, + type:, + choices:, prompt: html_val(:graphql, prompt), }.compact, answer: { @@ -367,7 +367,7 @@ def from_yaml_Matching( ) BodyItem.new( info: { - type: type, + type:, prompt: html_val(:graphql, prompt), promptsLabel: html_val(:graphql, prompts_label), valuesLabel: html_val(:graphql, values_label), @@ -382,7 +382,7 @@ def from_yaml_Matching( def from_yaml_MultipleChoice(type, options:, correct_answer:, prompt: nil) BodyItem.new( info: { - type: type, + type:, prompt: html_val(:graphql, prompt), options: html_vals(:graphql, options), }.compact, @@ -393,7 +393,7 @@ def from_yaml_MultipleChoice(type, options:, correct_answer:, prompt: nil) def from_yaml_Text(type, entire_value: nil, prompt: nil, correct_answer: nil) BodyItem.new( info: { - type: type, + type:, prompt: html_val(:graphql, prompt || entire_value.to_s), }.compact, answer: correct_answer, @@ -414,7 +414,7 @@ def from_yaml_TrueFalse(_type, entire_value: nil, prompt: nil, correct_answer: n noLabel: 'False', prompt: html_val(:graphql, prompt.to_s), }.compact, - answer: answer, + answer:, ) end @@ -432,7 +432,7 @@ def from_yaml_YesNo(_type, entire_value: nil, prompt: nil, correct_answer: nil) noLabel: 'No', prompt: html_val(:graphql, prompt.to_s), }.compact, - answer: answer, + answer:, ) end # rubocop:enable Naming/MethodName diff --git a/app/models/course.rb b/app/models/course.rb index af6a35936..ed98c139b 100644 --- a/app/models/course.rb +++ b/app/models/course.rb @@ -25,15 +25,15 @@ class Course < ApplicationRecord validates :bottlenose_id, presence: true def user_is_student?(user) - student_registrations.exists?(user: user) + student_registrations.exists?(user:) end def user_is_staff?(user) - staff_registrations.exists?(user: user) + staff_registrations.exists?(user:) end def user_is_professor?(user) - professor_course_registrations.exists?(user: user) + professor_course_registrations.exists?(user:) end def all_staff diff --git a/app/models/exam.rb b/app/models/exam.rb index 2868aeb6f..cef975eae 100644 --- a/app/models/exam.rb +++ b/app/models/exam.rb @@ -69,7 +69,7 @@ def proctors_and_professors end def user_is_proctor?(user) - proctor_registrations.exists?(user: user) + proctor_registrations.exists?(user:) end # All students and proctors registered for the exam. @@ -114,28 +114,28 @@ def time_window def checklist_complete(reason) { status: :complete, - reason: reason, + reason:, } end def checklist_warning(reason) { status: :warning, - reason: reason, + reason:, } end def checklist_not_started(reason) { status: :not_started, - reason: reason, + reason:, } end def checklist_na(reason) { status: :na, - reason: reason, + reason:, } end @@ -240,7 +240,7 @@ def initialize_grading_locks!(reset: false) existing_pairs = existing_pairs.to_set missing = pairs_by_version[registration.exam_version_id].reject { |qp| existing_pairs.member? qp } new_locks = missing.map do |qp| - { registration: registration, question: qp[:question], part: qp[:part] } + { registration:, question: qp[:question], part: qp[:part] } end # For safety's sake, validate these new locks # No need to validate the uniqueness criterion, since we're specifically diff --git a/app/models/exam_version.rb b/app/models/exam_version.rb index 04ff7ee89..4b822762e 100644 --- a/app/models/exam_version.rb +++ b/app/models/exam_version.rb @@ -190,17 +190,17 @@ def as_json(format:) elsif root_rubric.nil? || root_rubric.is_a?(None) nil else - root_rubric.as_json(format: format).deep_stringify_keys + root_rubric.as_json(format:).deep_stringify_keys end { 'policies' => policies, 'contents' => { 'instructions' => compact_blank(instructions), - 'questions' => db_questions.map { |q| q.as_json(format: format) }, + 'questions' => db_questions.map { |q| q.as_json(format:) }, (format == :export ? 'reference' : 'references') => compact_blank(db_references.where( question: nil, part: nil, - ).map { |ref| ref.as_json(format: format) }), + ).map { |ref| ref.as_json(format:) }), 'examRubric' => rubric_as_json, }.compact, } @@ -209,12 +209,12 @@ def as_json(format:) def rubric_as_json(format:) rubric_tree = multi_group_by(rubrics_for_grading, [:question_id, :part_id, :body_item_id], true) preset_comments_in_use = preset_comments.joins(:grading_comments).pluck(:id) - exam_rubric = rubric_tree.delete(nil)&.dig(nil, nil)&.as_json(preset_comments_in_use, format: format) + exam_rubric = rubric_tree.delete(nil)&.dig(nil, nil)&.as_json(preset_comments_in_use, format:) q_rubrics = rubric_tree.sort.map do |_qnum, rubrics_q| - question_rubric = rubrics_q.delete(nil)&.dig(nil)&.as_json(preset_comments_in_use, format: format) + question_rubric = rubrics_q.delete(nil)&.dig(nil)&.as_json(preset_comments_in_use, format:) p_rubrics = rubrics_q.sort.map do |_pnum, rubrics_p| - part_rubric = rubrics_p.delete(nil)&.as_json(preset_comments_in_use, format: format) - b_rubrics = rubrics_p.sort.map { |_, b| b.as_json(preset_comments_in_use, format: format) } + part_rubric = rubrics_p.delete(nil)&.as_json(preset_comments_in_use, format:) + b_rubrics = rubrics_p.sort.map { |_, b| b.as_json(preset_comments_in_use, format:) } { partRubric: part_rubric, body: b_rubrics, diff --git a/app/models/part.rb b/app/models/part.rb index 02a7da8cd..4e0d99fca 100644 --- a/app/models/part.rb +++ b/app/models/part.rb @@ -27,8 +27,8 @@ def exam_version before_save do if rubrics.empty? rubrics.build( - exam_version: exam_version, - question: question, + exam_version:, + question:, part: self, body_item: nil, type: 'None', @@ -47,7 +47,7 @@ def as_json(format:) elsif root_rubric.nil? || root_rubric.is_a?(None) nil else - root_rubric.as_json(format: format).deep_stringify_keys + root_rubric.as_json(format:).deep_stringify_keys end { 'name' => ApplicationHelper.make_html(format, compact_blank(name)), @@ -55,10 +55,10 @@ def as_json(format:) 'points' => points, 'extraCredit' => extra_credit || nil, (format == :export ? 'reference' : 'references') => - compact_blank(references.order(:index).map { |ref| ref.as_json(format: format) }), + compact_blank(references.order(:index).map { |ref| ref.as_json(format:) }), 'partRubric' => rubric_as_json, (format == :export ? 'body' : 'bodyItems') => - body_items.order(:index).map { |b| b.as_json(format: format) }, + body_items.order(:index).map { |b| b.as_json(format:) }, }.compact end diff --git a/app/models/preset_comment.rb b/app/models/preset_comment.rb index 916b467c4..95ca6489e 100644 --- a/app/models/preset_comment.rb +++ b/app/models/preset_comment.rb @@ -23,10 +23,10 @@ def in_use? def as_json(preset_comments_in_use = nil, format:) { - label: label, + label:, graderHint: grader_hint, studentFeedback: student_feedback, - points: points, + points:, inUse: if format == :export nil diff --git a/app/models/question.rb b/app/models/question.rb index f37320ee2..5cbb8f3f5 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -22,7 +22,7 @@ def course before_save do if rubrics.empty? rubrics.build( - exam_version: exam_version, + exam_version:, question: self, part: nil, body_item: nil, @@ -42,7 +42,7 @@ def as_json(format:) elsif root_rubric.nil? || root_rubric.is_a?(None) nil else - root_rubric.as_json(format: format).deep_stringify_keys + root_rubric.as_json(format:).deep_stringify_keys end { 'name' => ApplicationHelper.make_html(format, compact_blank(name)), @@ -50,9 +50,9 @@ def as_json(format:) 'extraCredit' => extra_credit || nil, 'separateSubparts' => separate_subparts, (format == :export ? 'reference' : 'references') => - compact_blank(references.where(part: nil).order(:index).map { |ref| ref.as_json(format: format) }), + compact_blank(references.where(part: nil).order(:index).map { |ref| ref.as_json(format:) }), 'questionRubric' => rubric_as_json, - 'parts' => parts.order(:index).map { |p| p.as_json(format: format) }, + 'parts' => parts.order(:index).map { |p| p.as_json(format:) }, }.compact end diff --git a/app/models/reference.rb b/app/models/reference.rb index 15a22b55c..d6c066e05 100644 --- a/app/models/reference.rb +++ b/app/models/reference.rb @@ -48,8 +48,8 @@ def self.inheritance_column def as_json(format:) if format == :graphql { - type: type, - path: path, + type:, + path:, } else { type => path } diff --git a/app/models/registration.rb b/app/models/registration.rb index 3adca5089..1dfd22ed7 100644 --- a/app/models/registration.rb +++ b/app/models/registration.rb @@ -209,7 +209,7 @@ def save_answers(answers) json = current_answers return true if json == answers - Snapshot.create(registration: self, answers: answers) + Snapshot.create(registration: self, answers:) end def current_score diff --git a/app/models/rubric.rb b/app/models/rubric.rb index ad8e0274f..96e4836ec 100644 --- a/app/models/rubric.rb +++ b/app/models/rubric.rb @@ -168,7 +168,7 @@ def compute_grade_for(reg, comments, checks, qpb) def grading_complete_for(reg) # NOTE: need to eliminate any ids that are nil, so we don't select too small a range of comments - coords = { question_id: question_id, part_id: part_id, body_item_id: body_item_id }.compact + coords = { question_id:, part_id:, body_item_id: }.compact comments = multi_group_by( reg.grading_comments.includes(:preset_comment).where(coords), [:question_id, :part_id, :body_item_id, :preset_comment_id], @@ -182,14 +182,14 @@ def out_of end def as_json(preset_comments_in_use = nil, format:) - rubric_preset_as_json = rubric_preset&.as_json(preset_comments_in_use, format: format) + rubric_preset_as_json = rubric_preset&.as_json(preset_comments_in_use, format:) subsections_as_json = subsections.sort_by(&:order).map do |s| - s.as_json(preset_comments_in_use, format: format) + s.as_json(preset_comments_in_use, format:) end { type: type.downcase, - description: description, - points: points, + description:, + points:, choices: rubric_preset_as_json || subsections_as_json, inUse: if format == :export diff --git a/app/models/rubric_preset.rb b/app/models/rubric_preset.rb index 0963fe952..9a33659bc 100644 --- a/app/models/rubric_preset.rb +++ b/app/models/rubric_preset.rb @@ -42,12 +42,12 @@ def compute_grade_for(_reg, max_points, comments, checks, qpb) def as_json(preset_comments_in_use = nil, format:) presets_as_json = preset_comments.sort_by(&:order).map do |p| - p.as_json(preset_comments_in_use, format: format) + p.as_json(preset_comments_in_use, format:) end { - label: label, - direction: direction, - mercy: mercy, + label:, + direction:, + mercy:, presets: presets_as_json, inUse: format == :export ? nil : presets_as_json.any? { |p| p['inUse'] }, }.compact diff --git a/lib/archive_utils.rb b/lib/archive_utils.rb index d2fb817c0..c5bbc6abb 100644 --- a/lib/archive_utils.rb +++ b/lib/archive_utils.rb @@ -717,7 +717,7 @@ def self.entries(file, mime, from_stream: nil) src_dir[:contents][filename] = { name: filename, type: :symlink, - target: target, + target:, } end end @@ -751,16 +751,16 @@ def self.entries(file, mime, from_stream: nil) private_class_method def self.file_to_json(name, contents, perms) { - name: name, + name:, type: :file, - contents: contents, - perms: perms, + contents:, + perms:, } end private_class_method def self.dir_to_json(name) { - name: name, + name:, type: :dir, contents: {}, } diff --git a/lib/bottlenose.rb b/lib/bottlenose.rb index 848fa5dd4..ac86bc828 100644 --- a/lib/bottlenose.rb +++ b/lib/bottlenose.rb @@ -57,25 +57,25 @@ def sync_course_regs(course) student_regs = sec.student_registrations.includes(:user).index_by(&:user_id) sec_obj['students'].each do |student| user = sync_user(student, all_users) - reg = student_regs[user.id] || StudentRegistration.new(section: sec, user: user) + reg = student_regs[user.id] || StudentRegistration.new(section: sec, user:) reg.save! end staff_regs = sec.staff_registrations.includes(:user).index_by(&:user_id) sec_obj['graders'].each do |grader| user = sync_user(grader, all_users) - reg = staff_regs[user.id] || StaffRegistration.new(section: sec, user: user) + reg = staff_regs[user.id] || StaffRegistration.new(section: sec, user:) reg.ta = false reg.save! end sec_obj['assistants'].each do |ta| user = sync_user(ta, all_users) - reg = staff_regs[user.id] || StaffRegistration.new(section: sec, user: user) + reg = staff_regs[user.id] || StaffRegistration.new(section: sec, user:) reg.ta = true reg.save! end sec_obj['professors'].each do |prof| user = sync_user(prof, all_users) - reg = prof_regs[user.id] || ProfessorCourseRegistration.new(course: course, user: user) + reg = prof_regs[user.id] || ProfessorCourseRegistration.new(course:, user:) prof_regs[user.id] = reg if prof_regs[user.id].nil? reg.save! end @@ -108,8 +108,8 @@ def sync_user(raw_user, all_users) user end - def bottlenose_send(method, *args) - bottlenose_token.send(method, *args).parsed + def bottlenose_send(method, *) + bottlenose_token.send(method, *).parsed rescue OAuth2::Error => e case e.response.status when 401 @@ -121,12 +121,12 @@ def bottlenose_send(method, *args) raise Bottlenose::ConnectionFailed end - def bottlenose_post(*args) - bottlenose_send(:post, *args) + def bottlenose_post(*) + bottlenose_send(:post, *) end - def bottlenose_get(*args) - bottlenose_send(:get, *args) + def bottlenose_get(*) + bottlenose_send(:get, *) end def bottlenose_oauth_client diff --git a/test/controllers/api/professor/versions_controller_test.rb b/test/controllers/api/professor/versions_controller_test.rb index 5e9b7d131..6eb6e3882 100644 --- a/test/controllers/api/professor/versions_controller_test.rb +++ b/test/controllers/api/professor/versions_controller_test.rb @@ -10,7 +10,7 @@ class VersionsControllerTest < ActionDispatch::IntegrationTest sign_in reg.user UploadTestHelper.with_test_uploaded_fixture_zip 'cs3500final-v1' do |upload| post import_api_professor_versions_path(exam), params: { - upload: upload, + upload:, } end assert_response :created diff --git a/test/factories/exam_version.rb b/test/factories/exam_version.rb index 3340187e0..85e3d8871 100644 --- a/test/factories/exam_version.rb +++ b/test/factories/exam_version.rb @@ -11,7 +11,7 @@ trait :blank do name { 'Blank exam' } transient do - upload { create(:upload, :blank) } + upload { association(:upload, :blank) } end before(:create) do |ev, _context| ev.db_questions.each do |q| @@ -32,7 +32,7 @@ trait :cs2500_v1 do name { 'CS2500 Midterm Version 1' } transient do - upload { create(:upload, :cs2500_v1) } + upload { association(:upload, :cs2500_v1) } end end @@ -43,21 +43,21 @@ trait :cs2500_v2 do name { 'CS2500 Midterm Version 2' } transient do - upload { create(:upload, :cs2500_v2) } + upload { association(:upload, :cs2500_v2) } end end trait :cs3500_v1 do name { 'CS3500 Final Version 1' } transient do - upload { create(:upload, :cs3500_v1) } + upload { association(:upload, :cs3500_v1) } end end trait :cs3500_v2 do name { 'CS3500 Final Version 2' } transient do - upload { create(:upload, :cs3500_v2) } + upload { association(:upload, :cs3500_v2) } end end diff --git a/test/factories/grading_check.rb b/test/factories/grading_check.rb index ca9cac4fd..ad291e235 100644 --- a/test/factories/grading_check.rb +++ b/test/factories/grading_check.rb @@ -3,7 +3,7 @@ FactoryBot.define do factory :grading_check do transient do - staff_registration { create(:staff_registration) } + staff_registration { association(:staff_registration) } end registration diff --git a/test/factories/grading_comment.rb b/test/factories/grading_comment.rb index d79a4cbb0..fc6d80e0b 100644 --- a/test/factories/grading_comment.rb +++ b/test/factories/grading_comment.rb @@ -3,7 +3,7 @@ FactoryBot.define do factory :grading_comment do transient do - staff_registration { create(:staff_registration) } + staff_registration { association(:staff_registration) } end registration diff --git a/test/factories/grading_lock.rb b/test/factories/grading_lock.rb index 10da9326f..7846d0b01 100644 --- a/test/factories/grading_lock.rb +++ b/test/factories/grading_lock.rb @@ -3,7 +3,7 @@ FactoryBot.define do factory :grading_lock do transient do - staff_registration { create(:staff_registration) } + staff_registration { association(:staff_registration) } end registration diff --git a/test/factories/message.rb b/test/factories/message.rb index dd1d0d40a..1d51ba8ec 100644 --- a/test/factories/message.rb +++ b/test/factories/message.rb @@ -3,7 +3,11 @@ FactoryBot.define do factory :message do transient do + # rubocop:disable FactoryBot/FactoryAssociationWithStrategy + # Need the professor to be fully created and saved, so that + # exam.proctors_and_professors can find it later during validation prof_reg { create(:professor_course_registration, course: registration.exam.course) } + # rubocop:enable FactoryBot/FactoryAssociationWithStrategy end sender { prof_reg.user } diff --git a/test/factories/registration.rb b/test/factories/registration.rb index 463927761..031c703d6 100644 --- a/test/factories/registration.rb +++ b/test/factories/registration.rb @@ -3,7 +3,11 @@ FactoryBot.define do factory :registration do transient do + # rubocop:disable FactoryBot/FactoryAssociationWithStrategy + # need registration to be fully saved so that the user has an id, + # for validation purposes later on student_registration { create(:student_registration, course: exam_version.course) } + # rubocop:enable FactoryBot/FactoryAssociationWithStrategy end user { student_registration.user } diff --git a/test/factories/student_registration.rb b/test/factories/student_registration.rb index 2d90c0900..8e4063baa 100644 --- a/test/factories/student_registration.rb +++ b/test/factories/student_registration.rb @@ -3,10 +3,10 @@ FactoryBot.define do factory :student_registration do transient do - course { create(:course) } + course { association(:course) } end user - section { create(:section, course: course) } + section { association(:section, course:) } end end diff --git a/test/integration/exam_version_administration_test.rb b/test/integration/exam_version_administration_test.rb index 1215b9726..c58a7a3e0 100644 --- a/test/integration/exam_version_administration_test.rb +++ b/test/integration/exam_version_administration_test.rb @@ -44,7 +44,7 @@ def try_update(ver, new_name:, user:) def assert_updatable(ver, user:) new_name = 'New version name' - result = try_update(ver, new_name: new_name, user: user) + result = try_update(ver, new_name:, user:) assert_not result['errors'] ver.reload assert_equal new_name, ver.name @@ -52,7 +52,7 @@ def assert_updatable(ver, user:) def assert_not_updatable(ver, user:) old_name = ver.name - result = try_update(ver, new_name: "#{old_name}!", user: user) + result = try_update(ver, new_name: "#{old_name}!", user:) assert result['errors'] assert_not result['errors'].empty? ver.reload @@ -67,7 +67,7 @@ def try_destroy(ver, user:) end def assert_not_destroyable(ver, user:) - result = try_destroy(ver, user: user) + result = try_destroy(ver, user:) assert result['errors'] assert_not result['errors'].empty? ver.reload @@ -78,7 +78,7 @@ def assert_not_destroyable(ver, user:) def assert_destroyable(ver, user:) exam = ver.exam old_length = exam.exam_versions.length - result = try_destroy(ver, user: user) + result = try_destroy(ver, user:) assert_not result['errors'] assert_raise { ver.reload } exam.reload diff --git a/test/integration/grading_locks_test.rb b/test/integration/grading_locks_test.rb index c540e0810..20f1f4ce0 100644 --- a/test/integration/grading_locks_test.rb +++ b/test/integration/grading_locks_test.rb @@ -70,9 +70,9 @@ def setup def attempt_lock(user, reg, qnum, pnum, steal: false, raw: false) ans = HourglassSchema.do_mutation!('REQUEST_LOCK_MUTATION', user, { registrationId: HourglassSchema.id_from_object(reg, Types::RegistrationType, {}), - qnum: qnum, - pnum: pnum, - steal: steal, + qnum:, + pnum:, + steal:, }) return ans if raw @@ -83,9 +83,9 @@ def attempt_lock(user, reg, qnum, pnum, steal: false, raw: false) def attempt_postpone(user, reg, qnum, pnum, notes, raw: false) ans = HourglassSchema.do_mutation!('POSTPONE_LOCK_MUTATION', user, { registrationId: HourglassSchema.id_from_object(reg, Types::RegistrationType, {}), - qnum: qnum, - pnum: pnum, - notes: notes, + qnum:, + pnum:, + notes:, }) return ans if raw @@ -99,8 +99,8 @@ def attempt_grade_next(user, reg, qnum, pnum, allow_change_problems: false, raw: ans = HourglassSchema.do_mutation!('GRADE_NEXT_MUTATION', user, { examId: HourglassSchema.id_from_object(exam, Types::ExamType, {}), examVersionId: HourglassSchema.id_from_object(exam_version, Types::ExamVersionType, {}), - qnum: qnum, - pnum: pnum, + qnum:, + pnum:, allowChangeProblems: allow_change_problems, }) return ans if raw @@ -112,8 +112,8 @@ def attempt_grade_next(user, reg, qnum, pnum, allow_change_problems: false, raw: def attempt_unlock(user, reg, qnum, pnum, complete, raw: false) ans = HourglassSchema.do_mutation!('RELEASE_LOCK_MUTATION', user, { registrationId: HourglassSchema.id_from_object(reg, Types::RegistrationType, {}), - qnum: qnum, - pnum: pnum, + qnum:, + pnum:, markComplete: complete, }) return ans if raw diff --git a/test/integration/snapshot_perf_test.rb b/test/integration/snapshot_perf_test.rb index 3a5a7f6b4..218dfb34f 100644 --- a/test/integration/snapshot_perf_test.rb +++ b/test/integration/snapshot_perf_test.rb @@ -14,9 +14,9 @@ def snapshot_speed $stdout.sync = true exam = create(:exam) create(:professor_course_registration, course: exam.course) - ev = create(:exam_version, :cs3500_v1, exam: exam) + ev = create(:exam_version, :cs3500_v1, exam:) course = exam.course - 3.times { create(:section, course: course) } + create_list(:section, 3, course:) sections = course.sections NUM_REGISTRATIONS.times do |i| s = create(:student_registration, section: sections[i % sections.count], user: create(:user)) diff --git a/test/models/accommodation_test.rb b/test/models/accommodation_test.rb index e720eba99..d0634aa5c 100644 --- a/test/models/accommodation_test.rb +++ b/test/models/accommodation_test.rb @@ -48,9 +48,9 @@ def setup test 'accommodated duration with expansion and real values' do start_time = DateTime.now end_time = start_time + 20.minutes - exam = build(:exam, duration: 8.minutes, start_time: start_time, end_time: end_time) - exam_version = build(:exam_version, exam: exam) - reg = build(:registration, :early_start, exam_version: exam_version) + exam = build(:exam, duration: 8.minutes, start_time:, end_time:) + exam_version = build(:exam_version, exam:) + reg = build(:registration, :early_start, exam_version:) build(:accommodation, registration: reg, percent_time_expansion: 25) extra_duration = 2.minutes assert_equal extra_duration, reg.accommodated_extra_duration @@ -78,7 +78,7 @@ def setup reg = build(:registration) exam = reg.exam new_start_time = exam.start_time - 1.hour - build(:accommodation, registration: reg, new_start_time: new_start_time) + build(:accommodation, registration: reg, new_start_time:) assert_equal new_start_time, reg.accommodated_start_time end @@ -120,7 +120,7 @@ def setup exam_version = reg.exam_version exam_version.start_time = exam.start_time - 2.hours new_start_time = exam.start_time - 1.hour - build(:accommodation, registration: reg, new_start_time: new_start_time) + build(:accommodation, registration: reg, new_start_time:) assert_equal new_start_time, reg.accommodated_start_time assert_not_equal exam_version.effective_start_time, reg.accommodated_start_time assert_not_equal exam.start_time, reg.accommodated_start_time diff --git a/test/models/grading_comment_test.rb b/test/models/grading_comment_test.rb index b1ad25fe9..57c6cea08 100644 --- a/test/models/grading_comment_test.rb +++ b/test/models/grading_comment_test.rb @@ -39,8 +39,8 @@ def create_comment(reg, question, part, bodyitem, preset) GradingComment.create!( creator: @grader, registration: reg, - question: question, - part: part, + question:, + part:, body_item: bodyitem, preset_comment: preset, points: preset.points, diff --git a/test/models/registration_test.rb b/test/models/registration_test.rb index 9b4c3b361..a8dc4e9a1 100644 --- a/test/models/registration_test.rb +++ b/test/models/registration_test.rb @@ -54,8 +54,8 @@ class RegistrationTest < ActiveSupport::TestCase test 'early bird start time over' do start_time = DateTime.now end_time = start_time + 20.minutes - exam = build(:exam, duration: 8.minutes, start_time: start_time, end_time: end_time) - ver = build(:exam_version, exam: exam) + exam = build(:exam, duration: 8.minutes, start_time:, end_time:) + ver = build(:exam_version, exam:) reg = build(:registration, :early_start, exam_version: ver) assert_equal 0, reg.accommodated_extra_duration assert_equal 8.minutes, reg.accommodated_duration diff --git a/test/system/extra_credit_test.rb b/test/system/extra_credit_test.rb index a55bedb07..a1249e984 100644 --- a/test/system/extra_credit_test.rb +++ b/test/system/extra_credit_test.rb @@ -113,8 +113,8 @@ def create_comment(reg, question, part, bodyitem, preset) GradingComment.create!( creator: @ta, registration: reg, - question: question, - part: part, + question:, + part:, body_item: bodyitem, preset_comment: preset, points: preset.points,