Fix rubocop offenses - Requires Ruby 3.1+
This commit is contained in:
@ -115,16 +115,16 @@ class ApplicationController < ActionController::Base
|
||||
redirect_back fallback_location: :root, allow_other_host: false, alert: message
|
||||
end
|
||||
end
|
||||
format.json { render json: {error: message}, status: status }
|
||||
format.json { render json: {error: message}, status: }
|
||||
end
|
||||
end
|
||||
private :render_error
|
||||
|
||||
def switch_locale(&action)
|
||||
def switch_locale(&)
|
||||
session[:locale] = sanitize_locale(params[:custom_locale] || params[:locale] || session[:locale])
|
||||
locale = session[:locale] || I18n.default_locale
|
||||
Sentry.set_extras(locale: locale)
|
||||
I18n.with_locale(locale, &action)
|
||||
Sentry.set_extras(locale:)
|
||||
I18n.with_locale(locale, &)
|
||||
end
|
||||
private :switch_locale
|
||||
|
||||
|
@ -60,7 +60,7 @@ module CodeOcean
|
||||
yield if block_given?
|
||||
path = options[:path].try(:call) || @object
|
||||
respond_with_valid_object(format, notice: t('shared.object_created', model: @object.class.model_name.human),
|
||||
path: path, status: :created)
|
||||
path:, status: :created)
|
||||
else
|
||||
filename = "#{@object.path || ''}/#{@object.name || ''}#{@object.file_type.try(:file_extension) || ''}"
|
||||
format.html do
|
||||
|
@ -11,7 +11,7 @@ module CommonBehavior
|
||||
notice = result if result.present?
|
||||
end
|
||||
path = options[:path].try(:call) || @object
|
||||
respond_with_valid_object(format, notice: notice, path: path, status: :created)
|
||||
respond_with_valid_object(format, notice:, path:, status: :created)
|
||||
else
|
||||
respond_with_invalid_object(format, template: :new)
|
||||
end
|
||||
@ -51,7 +51,7 @@ module CommonBehavior
|
||||
notice = result if result.present?
|
||||
end
|
||||
path = options[:path] || @object
|
||||
respond_with_valid_object(format, notice: notice, path: path, status: :ok)
|
||||
respond_with_valid_object(format, notice:, path:, status: :ok)
|
||||
else
|
||||
respond_with_invalid_object(format, template: :edit)
|
||||
end
|
||||
|
@ -16,14 +16,14 @@ module FileConversion
|
||||
path = File.dirname(file['name']).sub(%r{^(?>\./|\.)}, '').presence
|
||||
file_type = all_file_types.detect {|ft| ft.file_extension == extension } || FileType.new(file_extension: extension)
|
||||
CodeOcean::File.new(
|
||||
name: name,
|
||||
path: path,
|
||||
name:,
|
||||
path:,
|
||||
size: file['size'],
|
||||
owner: file['owner'],
|
||||
group: file['group'],
|
||||
permissions: file['permissions'],
|
||||
updated_at: file['modificationTime'],
|
||||
file_type: file_type
|
||||
file_type:
|
||||
)
|
||||
end
|
||||
[augment_files_for_download(files), directories]
|
||||
|
@ -124,7 +124,7 @@ module RedirectBehavior
|
||||
session: session.to_hash,
|
||||
submission: @submission.inspect,
|
||||
params: params.as_json,
|
||||
current_user: current_user,
|
||||
current_user:,
|
||||
lti_exercise_id: session[:lti_exercise_id],
|
||||
lti_parameters_id: session[:lti_parameters_id]
|
||||
)
|
||||
|
@ -115,8 +115,8 @@ class ExecutionEnvironmentsController < ApplicationController
|
||||
end
|
||||
|
||||
render locals: {
|
||||
working_time_statistics: working_time_statistics,
|
||||
user_statistics: user_statistics,
|
||||
working_time_statistics:,
|
||||
user_statistics:,
|
||||
}
|
||||
end
|
||||
|
||||
@ -132,7 +132,7 @@ class ExecutionEnvironmentsController < ApplicationController
|
||||
params[:execution_environment]
|
||||
.permit(:docker_image, :editor_mode, :file_extension, :file_type_id, :help, :indent_size, :memory_limit, :cpu_limit, :name,
|
||||
:network_enabled, :privileged_execution, :permitted_execution_time, :pool_size, :run_command, :test_command, :testing_framework)
|
||||
.merge(user_id: current_user.id, user_type: current_user.class.name, exposed_ports: exposed_ports)
|
||||
.merge(user_id: current_user.id, user_type: current_user.class.name, exposed_ports:)
|
||||
end
|
||||
end
|
||||
private :execution_environment_params
|
||||
|
@ -128,15 +128,15 @@ class ExercisesController < ApplicationController
|
||||
status: 'success',
|
||||
message: t('exercises.export_codeharbor.successfully_exported', id: @exercise.id, title: @exercise.title),
|
||||
actions: render_to_string(partial: 'export_actions',
|
||||
locals: {exercise: @exercise, exported: true, error: error}),
|
||||
locals: {exercise: @exercise, exported: true, error:}),
|
||||
}
|
||||
@exercise.save
|
||||
else
|
||||
render json: {
|
||||
status: 'fail',
|
||||
message: t('exercises.export_codeharbor.export_failed', id: @exercise.id, title: @exercise.title, error: error),
|
||||
message: t('exercises.export_codeharbor.export_failed', id: @exercise.id, title: @exercise.title, error:),
|
||||
actions: render_to_string(partial: 'export_actions',
|
||||
locals: {exercise: @exercise, exported: true, error: error}),
|
||||
locals: {exercise: @exercise, exported: true, error:}),
|
||||
}
|
||||
end
|
||||
end
|
||||
@ -146,7 +146,7 @@ class ExercisesController < ApplicationController
|
||||
return render json: {}, status: :unauthorized if user.nil?
|
||||
|
||||
uuid = params[:uuid]
|
||||
exercise = Exercise.find_by(uuid: uuid)
|
||||
exercise = Exercise.find_by(uuid:)
|
||||
|
||||
return render json: {uuid_found: false} if exercise.nil?
|
||||
return render json: {uuid_found: true, update_right: false} unless ExercisePolicy.new(user, exercise).update?
|
||||
@ -163,7 +163,7 @@ class ExercisesController < ApplicationController
|
||||
return render json: {}, status: :unauthorized if user.nil?
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
exercise = ::ProformaService::Import.call(zip: tempfile, user: user)
|
||||
exercise = ::ProformaService::Import.call(zip: tempfile, user:)
|
||||
exercise.save!
|
||||
render json: {}, status: :created
|
||||
end
|
||||
@ -185,7 +185,7 @@ class ExercisesController < ApplicationController
|
||||
private :user_from_api_key
|
||||
|
||||
def user_by_codeharbor_token(api_key)
|
||||
link = CodeharborLink.find_by(api_key: api_key)
|
||||
link = CodeharborLink.find_by(api_key:)
|
||||
link&.user
|
||||
end
|
||||
|
||||
@ -394,8 +394,8 @@ class ExercisesController < ApplicationController
|
||||
def working_times
|
||||
working_time_accumulated = @exercise.accumulated_working_time_for_only(current_user)
|
||||
working_time_75_percentile = @exercise.get_quantiles([0.75]).first
|
||||
render(json: {working_time_75_percentile: working_time_75_percentile,
|
||||
working_time_accumulated: working_time_accumulated})
|
||||
render(json: {working_time_75_percentile:,
|
||||
working_time_accumulated:})
|
||||
end
|
||||
|
||||
def intervention
|
||||
@ -404,7 +404,7 @@ class ExercisesController < ApplicationController
|
||||
render(json: {success: 'false', error: "undefined intervention #{params[:intervention_type]}"})
|
||||
else
|
||||
uei = UserExerciseIntervention.new(
|
||||
user: current_user, exercise: @exercise, intervention: intervention,
|
||||
user: current_user, exercise: @exercise, intervention:,
|
||||
accumulated_worktime_s: @exercise.accumulated_working_time_for_only(current_user)
|
||||
)
|
||||
uei.save
|
||||
@ -483,7 +483,7 @@ class ExercisesController < ApplicationController
|
||||
checked_tags = checked_exercise_tags.collect(&:tag).to_set
|
||||
unchecked_tags = Tag.all.to_set.subtract checked_tags
|
||||
@exercise_tags = checked_exercise_tags + unchecked_tags.collect do |tag|
|
||||
ExerciseTag.new(exercise: @exercise, tag: tag)
|
||||
ExerciseTag.new(exercise: @exercise, tag:)
|
||||
end
|
||||
end
|
||||
|
||||
@ -522,7 +522,7 @@ class ExercisesController < ApplicationController
|
||||
end
|
||||
|
||||
render locals: {
|
||||
user_statistics: user_statistics,
|
||||
user_statistics:,
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -72,7 +72,7 @@ class ExternalUsersController < ApplicationController
|
||||
end
|
||||
|
||||
render locals: {
|
||||
statistics: statistics,
|
||||
statistics:,
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -41,7 +41,7 @@ class FileTypesController < ApplicationController
|
||||
end
|
||||
|
||||
def set_editor_modes
|
||||
@editor_modes = Dir.glob('vendor/assets/javascripts/ace/mode-*.js').sort.map do |filename|
|
||||
@editor_modes = Dir.glob('vendor/assets/javascripts/ace/mode-*.js').map do |filename|
|
||||
name = filename.gsub(%r{\w+/|mode-|.js$}, '')
|
||||
[name, "ace/mode/#{name}"]
|
||||
end
|
||||
|
@ -28,7 +28,7 @@ class FlowrController < ApplicationController
|
||||
# once the programming language model becomes available, the language name can be added to the query to
|
||||
# produce more relevant results
|
||||
query = attributes.map(&:value).join(' ')
|
||||
{submission: submission, error: error, attributes: attributes, query: query}
|
||||
{submission:, error:, attributes:, query:}
|
||||
end
|
||||
|
||||
# Always return JSON
|
||||
|
@ -151,7 +151,7 @@ class InternalUsersController < ApplicationController
|
||||
checked_study_groups = checked_study_group_memberships.collect(&:study_group).sort.to_set
|
||||
unchecked_study_groups = StudyGroup.all.order(name: :asc).to_set.subtract checked_study_groups
|
||||
@study_group_memberships = checked_study_group_memberships + unchecked_study_groups.collect do |study_group|
|
||||
StudyGroupMembership.new(user: @user, study_group: study_group)
|
||||
StudyGroupMembership.new(user: @user, study_group:)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -26,14 +26,14 @@ class LiveStreamsController < ApplicationController
|
||||
runner = Runner.for(current_user, @execution_environment)
|
||||
fallback_location = shell_execution_environment_path(@execution_environment)
|
||||
privileged = params[:sudo] || @execution_environment.privileged_execution?
|
||||
send_runner_file(runner, desired_file, fallback_location, privileged: privileged)
|
||||
send_runner_file(runner, desired_file, fallback_location, privileged:)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def send_runner_file(runner, desired_file, redirect_fallback = root_path, privileged: false)
|
||||
filename = File.basename(desired_file)
|
||||
send_stream(filename: filename, type: 'application/octet-stream', disposition: 'attachment') do |stream|
|
||||
send_stream(filename:, type: 'application/octet-stream', disposition: 'attachment') do |stream|
|
||||
runner.download_file desired_file, privileged_execution: privileged do |chunk, overall_size, _content_type|
|
||||
unless response.committed?
|
||||
# Disable Rack::ETag, which would otherwise cause the response to be cached
|
||||
|
@ -15,7 +15,7 @@ class RemoteEvaluationController < ApplicationController
|
||||
else
|
||||
201
|
||||
end
|
||||
render json: result, status: status
|
||||
render json: result, status:
|
||||
end
|
||||
|
||||
# POST /submit
|
||||
@ -29,7 +29,7 @@ class RemoteEvaluationController < ApplicationController
|
||||
status = result[:status]
|
||||
end
|
||||
|
||||
render json: result, status: status
|
||||
render json: result, status:
|
||||
end
|
||||
|
||||
def try_lti
|
||||
@ -62,7 +62,7 @@ class RemoteEvaluationController < ApplicationController
|
||||
|
||||
def create_and_score_submission(cause)
|
||||
validation_token = remote_evaluation_params[:validation_token]
|
||||
if (remote_evaluation_mapping = RemoteEvaluationMapping.find_by(validation_token: validation_token))
|
||||
if (remote_evaluation_mapping = RemoteEvaluationMapping.find_by(validation_token:))
|
||||
@submission = Submission.create(build_submission_params(cause, remote_evaluation_mapping))
|
||||
@submission.calculate_score
|
||||
else
|
||||
|
@ -146,7 +146,7 @@ class SubmissionsController < ApplicationController
|
||||
end
|
||||
else
|
||||
Rails.logger.info("Unknown command from client: #{event[:cmd]}")
|
||||
Sentry.set_extras(event: event)
|
||||
Sentry.set_extras(event:)
|
||||
Sentry.capture_message("Unknown command from client: #{event[:cmd]}")
|
||||
end
|
||||
rescue JSON::ParserError => e
|
||||
@ -183,19 +183,19 @@ class SubmissionsController < ApplicationController
|
||||
exit_statement =
|
||||
if @testrun[:output].empty? && exit_code.zero?
|
||||
@testrun[:status] = :ok
|
||||
t('exercises.implement.no_output_exit_successful', timestamp: l(Time.zone.now, format: :short), exit_code: exit_code)
|
||||
t('exercises.implement.no_output_exit_successful', timestamp: l(Time.zone.now, format: :short), exit_code:)
|
||||
elsif @testrun[:output].empty?
|
||||
@testrun[:status] = :failed
|
||||
t('exercises.implement.no_output_exit_failure', timestamp: l(Time.zone.now, format: :short), exit_code: exit_code)
|
||||
t('exercises.implement.no_output_exit_failure', timestamp: l(Time.zone.now, format: :short), exit_code:)
|
||||
elsif exit_code.zero?
|
||||
@testrun[:status] = :ok
|
||||
"\n#{t('exercises.implement.exit_successful', timestamp: l(Time.zone.now, format: :short), exit_code: exit_code)}"
|
||||
"\n#{t('exercises.implement.exit_successful', timestamp: l(Time.zone.now, format: :short), exit_code:)}"
|
||||
else
|
||||
@testrun[:status] = :failed
|
||||
"\n#{t('exercises.implement.exit_failure', timestamp: l(Time.zone.now, format: :short), exit_code: exit_code)}"
|
||||
"\n#{t('exercises.implement.exit_failure', timestamp: l(Time.zone.now, format: :short), exit_code:)}"
|
||||
end
|
||||
stream = @testrun[:status] == :ok ? :stdout : :stderr
|
||||
send_and_store client_socket, {cmd: :write, stream: stream, data: "#{exit_statement}\n"}
|
||||
send_and_store client_socket, {cmd: :write, stream:, data: "#{exit_statement}\n"}
|
||||
if exit_code == 137
|
||||
send_and_store client_socket, {cmd: :status, status: :out_of_memory}
|
||||
@testrun[:status] = :out_of_memory
|
||||
@ -307,8 +307,8 @@ class SubmissionsController < ApplicationController
|
||||
exercise_id = @submission.exercise_id
|
||||
|
||||
remote_evaluation_mapping = RemoteEvaluationMapping.create(
|
||||
user: user,
|
||||
exercise_id: exercise_id,
|
||||
user:,
|
||||
exercise_id:,
|
||||
study_group_id: session[:study_group_id]
|
||||
)
|
||||
|
||||
@ -370,7 +370,7 @@ class SubmissionsController < ApplicationController
|
||||
testrun = Testrun.create!(
|
||||
file: @file,
|
||||
passed: @testrun[:passed],
|
||||
cause: cause,
|
||||
cause:,
|
||||
submission: @submission,
|
||||
exit_code: @testrun[:exit_code], # might be nil, e.g., when the run did not finish
|
||||
status: @testrun[:status] || :failed,
|
||||
@ -379,7 +379,7 @@ class SubmissionsController < ApplicationController
|
||||
waiting_for_container_time: @testrun[:waiting_for_container_time]
|
||||
)
|
||||
TestrunMessage.create_for(testrun, @testrun[:messages])
|
||||
TestrunExecutionEnvironment.create(testrun: testrun, execution_environment: @submission.used_execution_environment)
|
||||
TestrunExecutionEnvironment.create(testrun:, execution_environment: @submission.used_execution_environment)
|
||||
end
|
||||
|
||||
def send_hints(tubesock, errors)
|
||||
@ -430,10 +430,10 @@ class SubmissionsController < ApplicationController
|
||||
parsed[:stream] = parsed[:stream].to_sym if parsed.key? :stream
|
||||
parsed
|
||||
else
|
||||
{cmd: :write, stream: stream, data: data}
|
||||
{cmd: :write, stream:, data:}
|
||||
end
|
||||
rescue JSON::ParserError
|
||||
{cmd: :write, stream: stream, data: data}
|
||||
{cmd: :write, stream:, data:}
|
||||
end
|
||||
|
||||
def augment_files_for_download(files)
|
||||
|
@ -58,7 +58,7 @@ class SubscriptionsController < ApplicationController
|
||||
study_group_id = current_user.try(:current_study_group_id)
|
||||
if params[:subscription].present?
|
||||
params[:subscription].permit(:request_for_comment_id, :subscription_type).merge(user_id: current_user_id,
|
||||
user_type: current_user_class_name, study_group_id: study_group_id, deleted: false)
|
||||
user_type: current_user_class_name, study_group_id:, deleted: false)
|
||||
end
|
||||
end
|
||||
private :subscription_params
|
||||
|
@ -82,7 +82,7 @@ class UserExerciseFeedbacksController < ApplicationController
|
||||
else
|
||||
implement_exercise_path(@exercise)
|
||||
end
|
||||
update_and_respond(object: @uef, params: uef_params, path: path)
|
||||
update_and_respond(object: @uef, params: uef_params, path:)
|
||||
else
|
||||
flash.now[:danger] = t('shared.message_failure')
|
||||
redirect_back fallback_location: user_exercise_feedback_path(@uef)
|
||||
@ -126,15 +126,15 @@ class UserExerciseFeedbacksController < ApplicationController
|
||||
user_id = current_user.id
|
||||
user_type = current_user.class.name
|
||||
latest_submission = Submission
|
||||
.where(user_id: user_id, user_type: user_type, exercise_id: exercise_id)
|
||||
.where(user_id:, user_type:, exercise_id:)
|
||||
.order(created_at: :desc).final.first
|
||||
|
||||
authorize(latest_submission, :show?)
|
||||
|
||||
params[:user_exercise_feedback]
|
||||
.permit(:feedback_text, :difficulty, :exercise_id, :user_estimated_worktime)
|
||||
.merge(user_id: user_id,
|
||||
user_type: user_type,
|
||||
.merge(user_id:,
|
||||
user_type:,
|
||||
submission: latest_submission,
|
||||
normalized_score: latest_submission&.normalized_score)
|
||||
end
|
||||
|
@ -8,7 +8,7 @@ module ActionCableHelper
|
||||
ActionCable.server.broadcast(
|
||||
"la_exercises_#{exercise_id}_channel_study_group_#{submission.study_group_id}",
|
||||
type: :rfc,
|
||||
id: id,
|
||||
id:,
|
||||
html: ApplicationController.render(partial: 'request_for_comments/list_entry',
|
||||
locals: {request_for_comment: self})
|
||||
)
|
||||
|
@ -53,9 +53,9 @@ module ApplicationHelper
|
||||
ActionController::Base.helpers.sanitize Kramdown::Document.new(markdown).to_html
|
||||
end
|
||||
|
||||
def row(options = {}, &block)
|
||||
def row(options = {}, &)
|
||||
tag.div(class: 'attribute-row row') do
|
||||
label_column(options[:label]) + value_column(options[:value], &block)
|
||||
label_column(options[:label]) + value_column(options[:value], &)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -11,7 +11,7 @@ module AuthenticatedUrlHelper
|
||||
COOKIE_EXPIRATION = 30.seconds
|
||||
|
||||
def sign(url, object)
|
||||
payload = {object_id: object.id, object_type: object.class.name, url: url, exp: TOKEN_EXPIRATION.from_now.to_i}
|
||||
payload = {object_id: object.id, object_type: object.class.name, url:, exp: TOKEN_EXPIRATION.from_now.to_i}
|
||||
token = JWT.encode payload, TOKEN_SECRET, TOKEN_ALGORITHM
|
||||
|
||||
add_query_parameters(url, {TOKEN_PARAM => token})
|
||||
@ -58,7 +58,7 @@ module AuthenticatedUrlHelper
|
||||
|
||||
def prepare_short_living_cookie(value)
|
||||
{
|
||||
value: value,
|
||||
value:,
|
||||
expires: COOKIE_EXPIRATION.from_now,
|
||||
httponly: true,
|
||||
same_site: :strict,
|
||||
|
@ -9,9 +9,9 @@ class AuthenticationToken < ApplicationRecord
|
||||
def self.generate!(user, study_group)
|
||||
create!(
|
||||
shared_secret: SecureRandom.hex(32),
|
||||
user: user,
|
||||
user:,
|
||||
expire_at: 7.days.from_now,
|
||||
study_group: study_group
|
||||
study_group:
|
||||
)
|
||||
end
|
||||
end
|
||||
|
@ -40,7 +40,7 @@ module CodeOcean
|
||||
scope :visible, -> { where(hidden: false) }
|
||||
|
||||
ROLES.each do |role|
|
||||
scope :"#{role}s", -> { where(role: role) }
|
||||
scope :"#{role}s", -> { where(role:) }
|
||||
end
|
||||
scope :teacher_defined_assessments, -> { where(role: %w[teacher_defined_test teacher_defined_linter]) }
|
||||
|
||||
|
@ -48,7 +48,7 @@ class ExecutionEnvironment < ApplicationRecord
|
||||
|
||||
def to_json(*_args)
|
||||
{
|
||||
id: id,
|
||||
id:,
|
||||
image: docker_image,
|
||||
prewarmingPoolSize: pool_size,
|
||||
cpuLimit: cpu_limit,
|
||||
|
@ -79,7 +79,7 @@ class Exercise < ApplicationRecord
|
||||
end
|
||||
|
||||
def time_maximum_score(user)
|
||||
submissions.where(user: user).where("cause IN ('submit','assess')").where.not(score: nil).order('score DESC, created_at ASC').first.created_at
|
||||
submissions.where(user:).where("cause IN ('submit','assess')").where.not(score: nil).order('score DESC, created_at ASC').first.created_at
|
||||
rescue StandardError
|
||||
Time.zone.at(0)
|
||||
end
|
||||
@ -251,7 +251,7 @@ class Exercise < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
{user_progress: user_progress, additional_user_data: additional_user_data}
|
||||
{user_progress:, additional_user_data:}
|
||||
end
|
||||
|
||||
def get_quantiles(quantiles)
|
||||
@ -495,7 +495,7 @@ class Exercise < ApplicationRecord
|
||||
description = task_node.xpath('p:description/text()')[0].content
|
||||
self.attributes = {
|
||||
title: task_node.xpath('p:meta-data/p:title/text()')[0].content,
|
||||
description: description,
|
||||
description:,
|
||||
instructions: description,
|
||||
}
|
||||
task_node.xpath('p:files/p:file').all? do |file|
|
||||
@ -508,7 +508,7 @@ class Exercise < ApplicationRecord
|
||||
content: file.xpath('text()').first.content,
|
||||
read_only: false,
|
||||
hidden: file_class == 'internal',
|
||||
role: role,
|
||||
role:,
|
||||
feedback_message: role == 'teacher_defined_test' ? feedback_message_nodes.first.content : nil,
|
||||
file_type: FileType.find_by(
|
||||
file_extension: ".#{file_name_split.second}"
|
||||
@ -527,7 +527,7 @@ class Exercise < ApplicationRecord
|
||||
if user
|
||||
# FIXME: where(user: user) will not work here!
|
||||
begin
|
||||
submissions.where(user: user).where("cause IN ('submit','assess')").where.not(score: nil).order('score DESC').first.score || 0
|
||||
submissions.where(user:).where("cause IN ('submit','assess')").where.not(score: nil).order('score DESC').first.score || 0
|
||||
rescue StandardError
|
||||
0
|
||||
end
|
||||
|
@ -14,7 +14,7 @@ class ExerciseTip < ApplicationRecord
|
||||
def tip_chain?
|
||||
# Ensure each referenced parent exercise tip is set for this exercise
|
||||
unless ExerciseTip.exists?(
|
||||
exercise: exercise, id: parent_exercise_tip
|
||||
exercise:, id: parent_exercise_tip
|
||||
)
|
||||
errors.add :parent_exercise_tip,
|
||||
I18n.t('activerecord.errors.messages.together',
|
||||
|
@ -10,7 +10,7 @@ class Intervention < ApplicationRecord
|
||||
|
||||
def self.create_default_interventions
|
||||
%w[BreakIntervention QuestionIntervention].each do |name|
|
||||
Intervention.find_or_create_by(name: name)
|
||||
Intervention.find_or_create_by(name:)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -19,12 +19,12 @@ class LinterCheckRun < ApplicationRecord
|
||||
result: linter_result[:result],
|
||||
line: linter_result[:line],
|
||||
scope: linter_result[:scope],
|
||||
testrun: testrun,
|
||||
file: file
|
||||
testrun:,
|
||||
file:
|
||||
)
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
# Something bad happened. Probably, the RegEx in lib/py_lint_adapter.rb didn't work.
|
||||
Sentry.set_extras(testrun: testrun.inspect, linter_result: linter_result)
|
||||
Sentry.set_extras(testrun: testrun.inspect, linter_result:)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -42,7 +42,7 @@ class ProxyExercise < ApplicationRecord
|
||||
end
|
||||
|
||||
def get_matching_exercise(user)
|
||||
assigned_user_proxy_exercise = user_proxy_exercise_exercises.find_by(user: user)
|
||||
assigned_user_proxy_exercise = user_proxy_exercise_exercises.find_by(user:)
|
||||
if assigned_user_proxy_exercise
|
||||
Rails.logger.debug { "retrieved assigned exercise for user #{user.id}: Exercise #{assigned_user_proxy_exercise.exercise}" }
|
||||
assigned_user_proxy_exercise.exercise
|
||||
@ -57,7 +57,7 @@ class ProxyExercise < ApplicationRecord
|
||||
@reason[:error] = "#{$ERROR_INFO}:\n\t#{e.backtrace.join("\n\t")}"
|
||||
exercises.where('expected_difficulty > 1').sample # difficulty should be > 1 to prevent dummy exercise from being chosen.
|
||||
end
|
||||
user.user_proxy_exercise_exercises << UserProxyExerciseExercise.create(user: user,
|
||||
user.user_proxy_exercise_exercises << UserProxyExerciseExercise.create(user:,
|
||||
exercise: matching_exercise, proxy_exercise: self, reason: @reason.to_json)
|
||||
matching_exercise
|
||||
end
|
||||
@ -105,7 +105,7 @@ class ProxyExercise < ApplicationRecord
|
||||
relative_knowledge_improvement[potex] = 0.0
|
||||
Rails.logger.debug { "review potential exercise #{potex.id}" }
|
||||
tags.each do |tag|
|
||||
tag_ratio = potex.exercise_tags.find_by(tag: tag).factor.to_f / potex.exercise_tags.inject(0) do |sum, et|
|
||||
tag_ratio = potex.exercise_tags.find_by(tag:).factor.to_f / potex.exercise_tags.inject(0) do |sum, et|
|
||||
sum + et.factor
|
||||
end
|
||||
max_topic_knowledge_ratio = potex.expected_difficulty * tag_ratio
|
||||
|
@ -31,9 +31,9 @@ class Runner < ApplicationRecord
|
||||
end
|
||||
|
||||
def self.for(user, execution_environment)
|
||||
runner = find_by(user: user, execution_environment: execution_environment)
|
||||
runner = find_by(user:, execution_environment:)
|
||||
if runner.nil?
|
||||
runner = Runner.create(user: user, execution_environment: execution_environment)
|
||||
runner = Runner.create(user:, execution_environment:)
|
||||
# The `strategy` is added through the before_validation hook `:request_id`.
|
||||
raise Runner::Error::Unknown.new("Runner could not be saved: #{runner.errors.inspect}") unless runner.persisted?
|
||||
else
|
||||
@ -52,8 +52,8 @@ class Runner < ApplicationRecord
|
||||
@strategy.copy_files(files)
|
||||
end
|
||||
|
||||
def download_file(path, **options, &block)
|
||||
@strategy.download_file(path, **options, &block)
|
||||
def download_file(path, **options, &)
|
||||
@strategy.download_file(path, **options, &)
|
||||
end
|
||||
|
||||
def retrieve_files(raise_exception: true, **options)
|
||||
@ -93,7 +93,7 @@ class Runner < ApplicationRecord
|
||||
# initializing its Runner::Connection with the given event loop. The Runner::Connection class ensures that
|
||||
# this event loop is stopped after the socket was closed.
|
||||
event_loop = Runner::EventLoop.new
|
||||
socket = @strategy.attach_to_execution(command, event_loop, starting_time, privileged_execution: privileged_execution, &block)
|
||||
socket = @strategy.attach_to_execution(command, event_loop, starting_time, privileged_execution:, &block)
|
||||
event_loop.wait
|
||||
raise socket.error if socket.error.present?
|
||||
rescue Runner::Error => e
|
||||
@ -120,7 +120,7 @@ class Runner < ApplicationRecord
|
||||
save
|
||||
end
|
||||
|
||||
execution_time = attach_to_execution(command, privileged_execution: privileged_execution) do |socket, starting_time|
|
||||
execution_time = attach_to_execution(command, privileged_execution:) do |socket, starting_time|
|
||||
socket.on :stderr do |data|
|
||||
output[:stderr] << data
|
||||
output[:messages].push({cmd: :write, stream: :stderr, log: data, timestamp: Time.zone.now - starting_time})
|
||||
|
@ -7,7 +7,7 @@ class StructuredError < ApplicationRecord
|
||||
has_many :structured_error_attributes
|
||||
|
||||
def self.create_from_template(template, message_buffer, submission)
|
||||
instance = create(error_template: template, submission: submission)
|
||||
instance = create(error_template: template, submission:)
|
||||
template.error_template_attributes.each do |attribute|
|
||||
StructuredErrorAttribute.create_from_template(attribute, instance, message_buffer)
|
||||
end
|
||||
|
@ -10,7 +10,7 @@ class StructuredErrorAttribute < ApplicationRecord
|
||||
if !result.nil? && result.captures.size.positive?
|
||||
value = result.captures[0]
|
||||
end
|
||||
create(structured_error: structured_error, error_template_attribute: attribute, value: value,
|
||||
create(structured_error:, error_template_attribute: attribute, value:,
|
||||
match: !result.nil?)
|
||||
end
|
||||
end
|
||||
|
@ -88,7 +88,7 @@ class Submission < ApplicationRecord
|
||||
end
|
||||
|
||||
def siblings
|
||||
user.submissions.where(exercise_id: exercise_id)
|
||||
user.submissions.where(exercise_id:)
|
||||
end
|
||||
|
||||
def to_s
|
||||
@ -129,7 +129,7 @@ class Submission < ApplicationRecord
|
||||
end
|
||||
|
||||
def own_unsolved_rfc
|
||||
RequestForComment.unsolved.find_by(exercise_id: exercise, user_id: user_id)
|
||||
RequestForComment.unsolved.find_by(exercise_id: exercise, user_id:)
|
||||
end
|
||||
|
||||
def unsolved_rfc
|
||||
@ -162,11 +162,11 @@ class Submission < ApplicationRecord
|
||||
|
||||
# @raise [Runner::Error] if the code could not be run due to a failure with the runner.
|
||||
# See the specific type and message for more details.
|
||||
def run(file, &block)
|
||||
def run(file, &)
|
||||
run_command = command_for execution_environment.run_command, file.filepath
|
||||
durations = {}
|
||||
prepared_runner do |runner, waiting_duration|
|
||||
durations[:execution_duration] = runner.attach_to_execution(run_command, &block)
|
||||
durations[:execution_duration] = runner.attach_to_execution(run_command, &)
|
||||
durations[:waiting_duration] = waiting_duration
|
||||
rescue Runner::Error => e
|
||||
e.waiting_duration = waiting_duration
|
||||
@ -237,13 +237,13 @@ class Submission < ApplicationRecord
|
||||
def command_substitutions(filename)
|
||||
{
|
||||
class_name: File.basename(filename, File.extname(filename)).upcase_first,
|
||||
filename: filename,
|
||||
filename:,
|
||||
module_name: File.basename(filename, File.extname(filename)).underscore,
|
||||
}
|
||||
end
|
||||
|
||||
def score_file(output, file)
|
||||
assessor = Assessor.new(execution_environment: execution_environment)
|
||||
assessor = Assessor.new(execution_environment:)
|
||||
assessment = assessor.assess(output)
|
||||
passed = ((assessment[:passed] == assessment[:count]) and (assessment[:score]).positive?)
|
||||
testrun_output = passed ? nil : "status: #{output[:status]}\n stdout: #{output[:stdout]}\n stderr: #{output[:stderr]}"
|
||||
@ -256,8 +256,8 @@ class Submission < ApplicationRecord
|
||||
testrun = Testrun.create(
|
||||
submission: self,
|
||||
cause: 'assess', # Required to differ run and assess for RfC show
|
||||
file: file, # Test file that was executed
|
||||
passed: passed,
|
||||
file:, # Test file that was executed
|
||||
passed:,
|
||||
exit_code: output[:exit_code],
|
||||
status: output[:status],
|
||||
output: testrun_output.presence,
|
||||
@ -265,7 +265,7 @@ class Submission < ApplicationRecord
|
||||
waiting_for_container_time: output[:waiting_for_container_time]
|
||||
)
|
||||
TestrunMessage.create_for(testrun, output[:messages])
|
||||
TestrunExecutionEnvironment.create(testrun: testrun, execution_environment: @used_execution_environment)
|
||||
TestrunExecutionEnvironment.create(testrun:, execution_environment: @used_execution_environment)
|
||||
|
||||
filename = file.filepath
|
||||
|
||||
@ -278,7 +278,7 @@ class Submission < ApplicationRecord
|
||||
end
|
||||
|
||||
output.merge!(assessment)
|
||||
output.merge!(filename: filename, message: feedback_message(file, output), weight: file.weight)
|
||||
output.merge!(filename:, message: feedback_message(file, output), weight: file.weight)
|
||||
output.except!(:messages)
|
||||
end
|
||||
|
||||
@ -308,7 +308,7 @@ class Submission < ApplicationRecord
|
||||
update(score: score.to_d)
|
||||
if normalized_score.to_d == BigDecimal('1.0')
|
||||
Thread.new do
|
||||
RequestForComment.where(exercise_id: exercise_id, user_id: user_id, user_type: user_type).find_each do |rfc|
|
||||
RequestForComment.where(exercise_id:, user_id:, user_type:).find_each do |rfc|
|
||||
rfc.full_score_reached = true
|
||||
rfc.save
|
||||
end
|
||||
|
@ -73,7 +73,7 @@ class User < ApplicationRecord
|
||||
|
||||
def to_sentry_context
|
||||
{
|
||||
id: id,
|
||||
id:,
|
||||
type: self.class.name,
|
||||
username: displayname,
|
||||
consumer: consumer.name,
|
||||
|
@ -17,7 +17,7 @@ class UserExerciseFeedback < ApplicationRecord
|
||||
end
|
||||
|
||||
def anomaly_notification
|
||||
AnomalyNotification.where({exercise_id: exercise.id, user_id: user_id, user_type: user_type})
|
||||
AnomalyNotification.where({exercise_id: exercise.id, user_id:, user_type:})
|
||||
.where('created_at < ?', created_at).order('created_at DESC').to_a.first
|
||||
end
|
||||
end
|
||||
|
@ -23,12 +23,12 @@ module ProformaService
|
||||
title: @exercise.title,
|
||||
description: @exercise.description,
|
||||
internal_description: nil,
|
||||
proglang: proglang,
|
||||
proglang:,
|
||||
files: task_files,
|
||||
tests: tests,
|
||||
uuid: uuid,
|
||||
tests:,
|
||||
uuid:,
|
||||
language: DEFAULT_LANGUAGE,
|
||||
model_solutions: model_solutions,
|
||||
model_solutions:,
|
||||
meta_data: {
|
||||
CodeOcean: {
|
||||
public: @exercise.public,
|
||||
|
@ -26,9 +26,9 @@ module ProformaService
|
||||
allow_file_creation: string_to_bool(@task.meta_data[:CodeOcean]&.dig(:allow_file_creation)) || false,
|
||||
allow_auto_completion: string_to_bool(@task.meta_data[:CodeOcean]&.dig(:allow_auto_completion)) || false,
|
||||
expected_difficulty: @task.meta_data[:CodeOcean]&.dig(:expected_difficulty) || 1,
|
||||
execution_environment_id: execution_environment_id,
|
||||
execution_environment_id:,
|
||||
|
||||
files: files
|
||||
files:
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -17,7 +17,7 @@ module ProformaService
|
||||
exercise = base_exercise
|
||||
exercise_files = exercise&.files&.to_a
|
||||
|
||||
exercise = ConvertTaskToExercise.call(task: @task, user: @user, exercise: exercise)
|
||||
exercise = ConvertTaskToExercise.call(task: @task, user: @user, exercise:)
|
||||
exercise_files&.each(&:destroy) # feels suboptimal
|
||||
|
||||
exercise
|
||||
|
@ -8,7 +8,7 @@ json.download_file_url download_file_submission_path(@submission, 'a.', format:
|
||||
unless @embed_options[:disable_download]
|
||||
json.render_url @submission.collect_files.select(&:visible) do |files|
|
||||
host = ApplicationController::RENDER_HOST || request.host
|
||||
url = render_submission_url(@submission, files.filepath, host: host)
|
||||
url = render_submission_url(@submission, files.filepath, host:)
|
||||
|
||||
json.filepath files.filepath
|
||||
json.url AuthenticatedUrlHelper.sign(url, @submission)
|
||||
|
@ -1,6 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
FILENAME_REGEXP = /.+/.freeze unless Kernel.const_defined?(:FILENAME_REGEXP)
|
||||
FILENAME_REGEXP = /.+/ unless Kernel.const_defined?(:FILENAME_REGEXP)
|
||||
|
||||
Rails.application.routes.draw do
|
||||
resources :community_solutions, only: %i[index edit update]
|
||||
|
@ -293,7 +293,7 @@ class MigrateTestruns < ActiveRecord::Migration[6.1]
|
||||
# Using the string keys by design. Otherwise, we would need to call #symbolize_keys!
|
||||
|
||||
message = {
|
||||
testrun: testrun,
|
||||
testrun:,
|
||||
cmd: json['cmd'],
|
||||
# We cannot infer any timestamp and thus use arbitrary, distinct millisecond values (1s = 1000ms)
|
||||
timestamp: ActiveSupport::Duration.build(order / 1000.0),
|
||||
|
@ -10,7 +10,7 @@ class MigratePermissionsToStudyGroup < ActiveRecord::Migration[6.1]
|
||||
|
||||
def create_default_groups
|
||||
Consumer.find_each do |consumer|
|
||||
StudyGroup.find_or_create_by!(consumer: consumer, external_id: nil) do |new_group|
|
||||
StudyGroup.find_or_create_by!(consumer:, external_id: nil) do |new_group|
|
||||
new_group.name = "Default Study Group for #{consumer.name}"
|
||||
end
|
||||
end
|
||||
@ -25,7 +25,7 @@ class MigratePermissionsToStudyGroup < ActiveRecord::Migration[6.1]
|
||||
|
||||
# All platform admins will "just" be a teacher in the study group
|
||||
new_role = %w[admin teacher].include?(user.role) ? :teacher : :learner
|
||||
membership = StudyGroupMembership.find_or_create_by!(study_group: study_group, user: user)
|
||||
membership = StudyGroupMembership.find_or_create_by!(study_group:, user:)
|
||||
membership.update_columns(role: new_role)
|
||||
end
|
||||
end
|
||||
|
@ -13,7 +13,7 @@ passwords = ['password', 'password confirmation'].map do |attribute|
|
||||
end
|
||||
|
||||
if passwords.uniq.length == 1
|
||||
admin = FactoryBot.create(:admin, email: email, name: 'Administrator', password: passwords.first, study_groups: StudyGroup.all)
|
||||
admin = FactoryBot.create(:admin, email:, name: 'Administrator', password: passwords.first, study_groups: StudyGroup.all)
|
||||
else
|
||||
abort('Passwords do not match!')
|
||||
end
|
||||
|
@ -1,10 +1,10 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class CppCatch2Adapter < TestingFrameworkAdapter
|
||||
ALL_PASSED_REGEXP = /in\s+(\d+)\s+test case/.freeze
|
||||
COUNT_REGEXP = /test cases:\s+(\d+)/.freeze
|
||||
FAILURES_REGEXP = / \|\s+(\d+)\s+failed/.freeze
|
||||
ASSERTION_ERROR_REGEXP = /\n(.+)error:(.+);/.freeze
|
||||
ALL_PASSED_REGEXP = /in\s+(\d+)\s+test case/
|
||||
COUNT_REGEXP = /test cases:\s+(\d+)/
|
||||
FAILURES_REGEXP = / \|\s+(\d+)\s+failed/
|
||||
ASSERTION_ERROR_REGEXP = /\n(.+)error:(.+);/
|
||||
|
||||
def self.framework_name
|
||||
'CppCatch2'
|
||||
@ -17,7 +17,7 @@ class CppCatch2Adapter < TestingFrameworkAdapter
|
||||
count = output[:stdout].scan(COUNT_REGEXP).try(:last).try(:first).try(:to_i) || 0
|
||||
failed = output[:stdout].scan(FAILURES_REGEXP).try(:last).try(:first).try(:to_i) || 0
|
||||
error_matches = output[:stdout].scan(ASSERTION_ERROR_REGEXP) || []
|
||||
{count: count, failed: failed, error_messages: error_matches.flatten.compact_blank}
|
||||
{count:, failed:, error_messages: error_matches.flatten.compact_blank}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,9 +1,9 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Junit5Adapter < TestingFrameworkAdapter
|
||||
COUNT_REGEXP = /(\d+) tests found/.freeze
|
||||
FAILURES_REGEXP = /(\d+) tests failed/.freeze
|
||||
ASSERTION_ERROR_REGEXP = /=> java\.lang\.AssertionError:?\s(.*?)\s*org\.junit|=> org\.junit\.ComparisonFailure:\s(.*?)\s*org\.junit|=>\s(.*?)\s*org\.junit\.internal\.ComparisonCriteria\.arrayEquals|=> org\.opentest4j\.AssertionFailedError:?\s(.*?)\s*org.junit/m.freeze
|
||||
COUNT_REGEXP = /(\d+) tests found/
|
||||
FAILURES_REGEXP = /(\d+) tests failed/
|
||||
ASSERTION_ERROR_REGEXP = /=> java\.lang\.AssertionError:?\s(.*?)\s*org\.junit|=> org\.junit\.ComparisonFailure:\s(.*?)\s*org\.junit|=>\s(.*?)\s*org\.junit\.internal\.ComparisonCriteria\.arrayEquals|=> org\.opentest4j\.AssertionFailedError:?\s(.*?)\s*org.junit/m
|
||||
|
||||
def self.framework_name
|
||||
'JUnit 5'
|
||||
@ -13,10 +13,10 @@ class Junit5Adapter < TestingFrameworkAdapter
|
||||
count = output[:stdout].scan(COUNT_REGEXP).try(:last).try(:first).try(:to_i) || 0
|
||||
failed = output[:stdout].scan(FAILURES_REGEXP).try(:last).try(:first).try(:to_i) || 0
|
||||
if failed.zero?
|
||||
{count: count, passed: count}
|
||||
{count:, passed: count}
|
||||
else
|
||||
error_matches = output[:stdout].scan(ASSERTION_ERROR_REGEXP) || []
|
||||
{count: count, failed: failed, error_messages: error_matches.flatten.compact_blank}
|
||||
{count:, failed:, error_messages: error_matches.flatten.compact_blank}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,10 +1,10 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class JunitAdapter < TestingFrameworkAdapter
|
||||
COUNT_REGEXP = /Tests run: (\d+)/.freeze
|
||||
FAILURES_REGEXP = /Failures: (\d+)/.freeze
|
||||
SUCCESS_REGEXP = /OK \((\d+) tests?\)\s*(?:\x1B\]0;|exit)?\s*\z/.freeze
|
||||
ASSERTION_ERROR_REGEXP = /java\.lang\.AssertionError:?\s(.*?)\tat org\.junit|org\.junit\.ComparisonFailure:\s(.*?)\tat org\.junit|\)\r\n(.*?)\tat org\.junit\.internal\.ComparisonCriteria\.arrayEquals\(ComparisonCriteria\.java:50\)/m.freeze
|
||||
COUNT_REGEXP = /Tests run: (\d+)/
|
||||
FAILURES_REGEXP = /Failures: (\d+)/
|
||||
SUCCESS_REGEXP = /OK \((\d+) tests?\)\s*(?:\x1B\]0;|exit)?\s*\z/
|
||||
ASSERTION_ERROR_REGEXP = /java\.lang\.AssertionError:?\s(.*?)\tat org\.junit|org\.junit\.ComparisonFailure:\s(.*?)\tat org\.junit|\)\r\n(.*?)\tat org\.junit\.internal\.ComparisonCriteria\.arrayEquals\(ComparisonCriteria\.java:50\)/m
|
||||
|
||||
def self.framework_name
|
||||
'JUnit 4'
|
||||
@ -17,7 +17,7 @@ class JunitAdapter < TestingFrameworkAdapter
|
||||
count = output[:stdout].scan(COUNT_REGEXP).try(:last).try(:first).try(:to_i) || 0
|
||||
failed = output[:stdout].scan(FAILURES_REGEXP).try(:last).try(:first).try(:to_i) || 0
|
||||
error_matches = output[:stdout].scan(ASSERTION_ERROR_REGEXP) || []
|
||||
{count: count, failed: failed, error_messages: error_matches.flatten.compact_blank}
|
||||
{count:, failed:, error_messages: error_matches.flatten.compact_blank}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,8 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class MochaAdapter < TestingFrameworkAdapter
|
||||
SUCCESS_REGEXP = /(\d+) passing/.freeze
|
||||
FAILURES_REGEXP = /(\d+) failing/.freeze
|
||||
SUCCESS_REGEXP = /(\d+) passing/
|
||||
FAILURES_REGEXP = /(\d+) failing/
|
||||
|
||||
def self.framework_name
|
||||
'Mocha'
|
||||
@ -11,6 +11,6 @@ class MochaAdapter < TestingFrameworkAdapter
|
||||
def parse_output(output)
|
||||
success = output[:stdout].scan(SUCCESS_REGEXP).try(:last).try(:first).try(:to_i) || 0
|
||||
failed = output[:stdout].scan(FAILURES_REGEXP).try(:last).try(:first).try(:to_i) || 0
|
||||
{count: success + failed, failed: failed}
|
||||
{count: success + failed, failed:}
|
||||
end
|
||||
end
|
||||
|
@ -1,8 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class PyLintAdapter < TestingFrameworkAdapter
|
||||
REGEXP = %r{Your code has been rated at (-?\d+\.?\d*)/(\d+\.?\d*)}.freeze
|
||||
ASSERTION_ERROR_REGEXP = /^(.*?\.py):(\d+):(.*?)\(([^,]*?), ([^,]*?),([^,]*?)\) (.*?)$/.freeze
|
||||
REGEXP = %r{Your code has been rated at (-?\d+\.?\d*)/(\d+\.?\d*)}
|
||||
ASSERTION_ERROR_REGEXP = /^(.*?\.py):(\d+):(.*?)\(([^,]*?), ([^,]*?),([^,]*?)\) (.*?)$/
|
||||
|
||||
def self.framework_name
|
||||
'PyLint'
|
||||
@ -41,8 +41,8 @@ class PyLintAdapter < TestingFrameworkAdapter
|
||||
end
|
||||
concatenated_errors = assertion_error_matches.map {|result| "#{result[:name]}: #{result[:result]}" }
|
||||
{
|
||||
count: count,
|
||||
failed: failed,
|
||||
count:,
|
||||
failed:,
|
||||
error_messages: concatenated_errors.flatten.compact_blank,
|
||||
detailed_linter_results: assertion_error_matches.flatten.compact_blank,
|
||||
}
|
||||
@ -69,7 +69,7 @@ class PyLintAdapter < TestingFrameworkAdapter
|
||||
captures = message[:result].match(Regexp.new(regex))&.named_captures&.symbolize_keys
|
||||
|
||||
if captures.nil?
|
||||
Sentry.capture_message({regex: regex, message: message[:result]}.to_json)
|
||||
Sentry.capture_message({regex:, message: message[:result]}.to_json)
|
||||
replacement = {}
|
||||
else
|
||||
replacement = captures.each do |key, value|
|
||||
@ -100,7 +100,7 @@ class PyLintAdapter < TestingFrameworkAdapter
|
||||
def self.get_t(key, default)
|
||||
# key might be "linter.#{severity}.#{name}.#{key}.#{value}"
|
||||
# or something like "linter.#{severity}.#{name}.replacement"
|
||||
translation = I18n.t(key, default: default)
|
||||
translation = I18n.t(key, default:)
|
||||
cleaned_key = key.delete_suffix(".#{default}") # Remove any custom prefix, might have no effect
|
||||
keys = cleaned_key.split('.')
|
||||
final_key = keys.pop
|
||||
@ -111,7 +111,7 @@ class PyLintAdapter < TestingFrameworkAdapter
|
||||
# Read config key
|
||||
I18n.t(keys.append('log_missing').join('.'), default: false)
|
||||
end
|
||||
Sentry.capture_message({key: cleaned_key, default: default}.to_json) if translation == default && log_missing
|
||||
Sentry.capture_message({key: cleaned_key, default:}.to_json) if translation == default && log_missing
|
||||
translation
|
||||
end
|
||||
end
|
||||
|
@ -1,10 +1,10 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class PyUnitAdapter < TestingFrameworkAdapter
|
||||
COUNT_REGEXP = /Ran (\d+) test/.freeze
|
||||
FAILURES_REGEXP = /FAILED \(.*failures=(\d+).*\)/.freeze
|
||||
ERRORS_REGEXP = /FAILED \(.*errors=(\d+).*\)/.freeze
|
||||
ASSERTION_ERROR_REGEXP = /^(ERROR|FAIL):\ (.*?)\ .*?^[^.\n]*?(Error|Exception):\s((\s|\S)*?)(>>>[^>]*?)*\s\s(-|=){70}/m.freeze
|
||||
COUNT_REGEXP = /Ran (\d+) test/
|
||||
FAILURES_REGEXP = /FAILED \(.*failures=(\d+).*\)/
|
||||
ERRORS_REGEXP = /FAILED \(.*errors=(\d+).*\)/
|
||||
ASSERTION_ERROR_REGEXP = /^(ERROR|FAIL):\ (.*?)\ .*?^[^.\n]*?(Error|Exception):\s((\s|\S)*?)(>>>[^>]*?)*\s\s(-|=){70}/m
|
||||
|
||||
def self.framework_name
|
||||
'PyUnit'
|
||||
@ -32,6 +32,6 @@ class PyUnitAdapter < TestingFrameworkAdapter
|
||||
Sentry.capture_message({stderr: output[:stderr], regex: ASSERTION_ERROR_REGEXP}.to_json)
|
||||
assertion_error_matches = []
|
||||
end
|
||||
{count: count, failed: failed + errors, error_messages: assertion_error_matches.flatten.compact_blank}
|
||||
{count:, failed: failed + errors, error_messages: assertion_error_matches.flatten.compact_blank}
|
||||
end
|
||||
end
|
||||
|
@ -1,8 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class RScriptAdapter < TestingFrameworkAdapter
|
||||
REGEXP = /(\d+) examples?, (\d+) passed?/.freeze
|
||||
ASSERTION_ERROR_REGEXP = /AssertionError:\s(.*)/.freeze
|
||||
REGEXP = /(\d+) examples?, (\d+) passed?/
|
||||
ASSERTION_ERROR_REGEXP = /AssertionError:\s(.*)/
|
||||
|
||||
def self.framework_name
|
||||
'R Script'
|
||||
@ -14,6 +14,6 @@ class RScriptAdapter < TestingFrameworkAdapter
|
||||
passed = captures.second
|
||||
failed = count - passed
|
||||
assertion_error_matches = output[:stdout].scan(ASSERTION_ERROR_REGEXP) || []
|
||||
{count: count, failed: failed, error_messages: assertion_error_matches.flatten.compact_blank}
|
||||
{count:, failed:, error_messages: assertion_error_matches.flatten.compact_blank}
|
||||
end
|
||||
end
|
||||
|
@ -1,7 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class RspecAdapter < TestingFrameworkAdapter
|
||||
REGEXP = /(\d+) examples?, (\d+) failures?/.freeze
|
||||
REGEXP = /(\d+) examples?, (\d+) failures?/
|
||||
|
||||
def self.framework_name
|
||||
'RSpec 3'
|
||||
@ -11,6 +11,6 @@ class RspecAdapter < TestingFrameworkAdapter
|
||||
captures = output[:stdout].scan(REGEXP).try(:last).map(&:to_i)
|
||||
count = captures.first
|
||||
failed = captures.second
|
||||
{count: count, failed: failed}
|
||||
{count:, failed:}
|
||||
end
|
||||
end
|
||||
|
@ -128,7 +128,7 @@ class Runner::Strategy::Poseidon < Runner::Strategy
|
||||
|
||||
# First, clean the workspace and second, copy all files to their location.
|
||||
# This ensures that no artifacts from a previous submission remain in the workspace.
|
||||
body = {copy: copy, delete: ['./*']}
|
||||
body = {copy:, delete: ['./*']}
|
||||
response = self.class.http_connection.patch url, body.to_json
|
||||
return if response.status == 204
|
||||
|
||||
@ -143,8 +143,8 @@ class Runner::Strategy::Poseidon < Runner::Strategy
|
||||
def retrieve_files(path: './', recursive: true, privileged_execution: false)
|
||||
url = "#{runner_url}/files"
|
||||
params = {
|
||||
path: path,
|
||||
recursive: recursive,
|
||||
path:,
|
||||
recursive:,
|
||||
privilegedExecution: privileged_execution || @execution_environment.privileged_execution,
|
||||
}
|
||||
Rails.logger.debug { "#{Time.zone.now.getutc.inspect}: Retrieving files at #{runner_url} with #{params}" }
|
||||
@ -199,7 +199,7 @@ class Runner::Strategy::Poseidon < Runner::Strategy
|
||||
end
|
||||
|
||||
def attach_to_execution(command, event_loop, starting_time, privileged_execution: false)
|
||||
websocket_url = execute_command(command, privileged_execution: privileged_execution)
|
||||
websocket_url = execute_command(command, privileged_execution:)
|
||||
socket = Connection.new(websocket_url, self, event_loop)
|
||||
yield(socket, starting_time)
|
||||
socket
|
||||
@ -293,13 +293,13 @@ class Runner::Strategy::Poseidon < Runner::Strategy
|
||||
end
|
||||
|
||||
def self.http_connection
|
||||
@http_connection ||= Faraday.new(ssl: {ca_file: config[:ca_file]}, headers: headers) do |faraday|
|
||||
@http_connection ||= Faraday.new(ssl: {ca_file: config[:ca_file]}, headers:) do |faraday|
|
||||
faraday.adapter :net_http_persistent
|
||||
end
|
||||
end
|
||||
|
||||
def self.new_http_connection
|
||||
Faraday.new(ssl: {ca_file: config[:ca_file]}, headers: headers) do |faraday|
|
||||
Faraday.new(ssl: {ca_file: config[:ca_file]}, headers:) do |faraday|
|
||||
faraday.adapter :net_http
|
||||
end
|
||||
end
|
||||
@ -316,7 +316,7 @@ class Runner::Strategy::Poseidon < Runner::Strategy
|
||||
def execute_command(command, privileged_execution: false)
|
||||
url = "#{runner_url}/execute"
|
||||
body = {
|
||||
command: command,
|
||||
command:,
|
||||
timeLimit: @execution_environment.permitted_execution_time,
|
||||
privilegedExecution: privileged_execution || @execution_environment.privileged_execution,
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class SqlResultSetComparatorAdapter < TestingFrameworkAdapter
|
||||
MISSING_TUPLES_REGEXP = /Missing tuples: \[\]/.freeze
|
||||
UNEXPECTED_TUPLES_REGEXP = /Unexpected tuples: \[\]/.freeze
|
||||
MISSING_TUPLES_REGEXP = /Missing tuples: \[\]/
|
||||
UNEXPECTED_TUPLES_REGEXP = /Unexpected tuples: \[\]/
|
||||
|
||||
def self.framework_name
|
||||
'SqlResultSetComparator'
|
||||
|
@ -133,7 +133,7 @@ namespace :detect_exercise_anomalies do
|
||||
segment.each do |user|
|
||||
reason = "{\"segment\": \"#{key}\", \"feature\": \"#{user[:reason]}\", value: \"#{user[:value]}\"}"
|
||||
AnomalyNotification.create(user_id: user[:user_id], user_type: user[:user_type],
|
||||
exercise: exercise, exercise_collection: collection, reason: reason)
|
||||
exercise:, exercise_collection: collection, reason:)
|
||||
end
|
||||
end
|
||||
|
||||
@ -142,7 +142,7 @@ namespace :detect_exercise_anomalies do
|
||||
user = u[:user_type] == InternalUser.name ? InternalUser.find(u[:user_id]) : ExternalUser.find(u[:user_id])
|
||||
host = CodeOcean::Application.config.action_mailer.default_url_options[:host]
|
||||
feedback_link = Rails.application.routes.url_helpers.url_for(action: :new,
|
||||
controller: :user_exercise_feedbacks, exercise_id: exercise.id, host: host)
|
||||
controller: :user_exercise_feedbacks, exercise_id: exercise.id, host:)
|
||||
UserMailer.exercise_anomaly_needs_feedback(user, exercise, feedback_link).deliver
|
||||
end
|
||||
log("Asked #{users_to_notify.size} users for feedback.", 2)
|
||||
|
@ -9,8 +9,8 @@ namespace :export_exercises do
|
||||
Exercise.where(public: true).each do |exercise|
|
||||
puts "Exporting exercise ##{exercise.id}"
|
||||
error = ExerciseService::PushExternal.call(
|
||||
zip: ProformaService::ExportTask.call(exercise: exercise),
|
||||
codeharbor_link: codeharbor_link
|
||||
zip: ProformaService::ExportTask.call(exercise:),
|
||||
codeharbor_link:
|
||||
)
|
||||
if error.nil?
|
||||
successful_exports << exercise.id
|
||||
|
@ -56,7 +56,7 @@ describe Lti do
|
||||
it 'returns to the tool consumer' do
|
||||
message = I18n.t('sessions.oauth.invalid_consumer')
|
||||
expect(controller).to receive(:return_to_consumer).with(lti_errorlog: message, lti_errormsg: I18n.t('sessions.oauth.failure'))
|
||||
controller.send(:refuse_lti_launch, message: message)
|
||||
controller.send(:refuse_lti_launch, message:)
|
||||
end
|
||||
end
|
||||
|
||||
@ -174,14 +174,14 @@ describe Lti do
|
||||
controller.instance_variable_set(:@exercise, create(:fibonacci))
|
||||
expect(controller.session).to receive(:[]=).with(:external_user_id, anything)
|
||||
expect(controller.session).to receive(:[]=).with(:lti_parameters_id, anything)
|
||||
controller.send(:store_lti_session_data, consumer: build(:consumer), parameters: parameters)
|
||||
controller.send(:store_lti_session_data, consumer: build(:consumer), parameters:)
|
||||
end
|
||||
|
||||
it 'creates an LtiParameter Object' do
|
||||
before_count = LtiParameter.count
|
||||
controller.instance_variable_set(:@current_user, create(:external_user))
|
||||
controller.instance_variable_set(:@exercise, create(:fibonacci))
|
||||
controller.send(:store_lti_session_data, consumer: build(:consumer), parameters: parameters)
|
||||
controller.send(:store_lti_session_data, consumer: build(:consumer), parameters:)
|
||||
expect(LtiParameter.count).to eq(before_count + 1)
|
||||
end
|
||||
end
|
||||
|
@ -76,7 +76,7 @@ describe ApplicationController do
|
||||
context "when using the 'locale' parameter" do
|
||||
it 'overwrites the session' do
|
||||
expect(session).to receive(:[]=).with(:locale, locale)
|
||||
get :welcome, params: {locale: locale}
|
||||
get :welcome, params: {locale:}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -30,7 +30,7 @@ describe CodeOcean::FilesController do
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:submission) { create(:submission, user: user) }
|
||||
let(:submission) { create(:submission, user:) }
|
||||
|
||||
context 'with a valid file' do
|
||||
let(:perform_request) { proc { post :create, params: {code_ocean_file: build(:file, context: submission).attributes, format: :json} } }
|
||||
|
@ -22,7 +22,7 @@ describe CodeharborLinksController do
|
||||
end
|
||||
|
||||
describe 'GET #edit' do
|
||||
let(:codeharbor_link) { create(:codeharbor_link, user: user) }
|
||||
let(:codeharbor_link) { create(:codeharbor_link, user:) }
|
||||
|
||||
before { get :edit, params: {id: codeharbor_link.id} }
|
||||
|
||||
@ -56,7 +56,7 @@ describe CodeharborLinksController do
|
||||
end
|
||||
|
||||
describe 'PUT #update' do
|
||||
let(:codeharbor_link) { create(:codeharbor_link, user: user) }
|
||||
let(:codeharbor_link) { create(:codeharbor_link, user:) }
|
||||
let(:put_request) { patch :update, params: {id: codeharbor_link.id, codeharbor_link: params} }
|
||||
let(:params) { {push_url: 'https://foo.bar/push', check_uuid_url: 'https://foo.bar/check', api_key: 'api_key'} }
|
||||
|
||||
@ -91,7 +91,7 @@ describe CodeharborLinksController do
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
let!(:codeharbor_link) { create(:codeharbor_link, user: user) }
|
||||
let!(:codeharbor_link) { create(:codeharbor_link, user:) }
|
||||
let(:destroy_request) { delete :destroy, params: {id: codeharbor_link.id} }
|
||||
|
||||
it 'deletes codeharbor_link' do
|
||||
|
@ -6,7 +6,7 @@ describe CommentsController do
|
||||
render_views
|
||||
|
||||
let(:user) { create(:learner) }
|
||||
let(:rfc_with_comment) { create(:rfc_with_comment, user: user) }
|
||||
let(:rfc_with_comment) { create(:rfc_with_comment, user:) }
|
||||
let(:comment) { rfc_with_comment.comments.first }
|
||||
let(:updated_comment) { comment.reload }
|
||||
let(:perform_request) { proc { put :update, format: :json, params: {id: comment.id, comment: comment_params} } }
|
||||
|
@ -95,7 +95,7 @@ describe ExecutionEnvironmentsController do
|
||||
runner = instance_double Runner
|
||||
allow(Runner).to receive(:for).with(user, execution_environment).and_return runner
|
||||
allow(runner).to receive(:execute_command).and_return({})
|
||||
post :execute_command, params: {command: command, id: execution_environment.id}
|
||||
post :execute_command, params: {command:, id: execution_environment.id}
|
||||
end
|
||||
|
||||
expect_assigns(execution_environment: :execution_environment)
|
||||
|
@ -37,7 +37,7 @@ describe ExercisesController do
|
||||
expect_assigns(exercise: Exercise)
|
||||
|
||||
it 'clones the exercise' do
|
||||
expect_any_instance_of(Exercise).to receive(:duplicate).with(hash_including(public: false, user: user)).and_call_original
|
||||
expect_any_instance_of(Exercise).to receive(:duplicate).with(hash_including(public: false, user:)).and_call_original
|
||||
expect { perform_request.call }.to change(Exercise, :count).by(1)
|
||||
end
|
||||
|
||||
@ -78,7 +78,7 @@ describe ExercisesController do
|
||||
end
|
||||
|
||||
context 'when including a file' do
|
||||
let(:perform_request) { proc { post :create, params: {exercise: exercise_attributes.merge(files_attributes: files_attributes)} } }
|
||||
let(:perform_request) { proc { post :create, params: {exercise: exercise_attributes.merge(files_attributes:)} } }
|
||||
|
||||
context 'when specifying the file content within the form' do
|
||||
let(:files_attributes) { {'0' => build(:file).attributes} }
|
||||
@ -89,7 +89,7 @@ describe ExercisesController do
|
||||
end
|
||||
|
||||
context 'when uploading a file' do
|
||||
let(:files_attributes) { {'0' => build(:file, file_type: file_type).attributes.merge(content: uploaded_file)} }
|
||||
let(:files_attributes) { {'0' => build(:file, file_type:).attributes.merge(content: uploaded_file)} }
|
||||
|
||||
context 'when uploading a binary file' do
|
||||
let(:file_path) { Rails.root.join('db/seeds/audio_video/devstories.mp4') }
|
||||
@ -255,14 +255,14 @@ describe ExercisesController do
|
||||
end
|
||||
|
||||
describe 'GET #external_user_statistics' do
|
||||
let(:perform_request) { get :external_user_statistics, params: params }
|
||||
let(:perform_request) { get :external_user_statistics, params: }
|
||||
let(:params) { {id: exercise.id, external_user_id: external_user.id} }
|
||||
let(:external_user) { create(:external_user) }
|
||||
|
||||
before do
|
||||
2.times { create(:submission, cause: 'autosave', user: external_user, exercise: exercise) }
|
||||
2.times { create(:submission, cause: 'run', user: external_user, exercise: exercise) }
|
||||
create(:submission, cause: 'assess', user: external_user, exercise: exercise)
|
||||
2.times { create(:submission, cause: 'autosave', user: external_user, exercise:) }
|
||||
2.times { create(:submission, cause: 'run', user: external_user, exercise:) }
|
||||
create(:submission, cause: 'assess', user: external_user, exercise:)
|
||||
end
|
||||
|
||||
context 'when viewing the default submission statistics page without a parameter' do
|
||||
@ -312,8 +312,8 @@ describe ExercisesController do
|
||||
end
|
||||
|
||||
before do
|
||||
create(:lti_parameter, external_user: user, exercise: exercise)
|
||||
submission = build(:submission, exercise: exercise, user: user)
|
||||
create(:lti_parameter, external_user: user, exercise:)
|
||||
submission = build(:submission, exercise:, user:)
|
||||
allow(submission).to receive(:normalized_score).and_return(1)
|
||||
allow(submission).to receive(:calculate_score).and_return(scoring_response)
|
||||
allow(Submission).to receive(:create).and_return(submission)
|
||||
@ -404,13 +404,13 @@ describe ExercisesController do
|
||||
render_views
|
||||
|
||||
let(:post_request) { post :export_external_check, params: {id: exercise.id} }
|
||||
let!(:codeharbor_link) { create(:codeharbor_link, user: user) }
|
||||
let(:external_check_hash) { {message: message, uuid_found: true, update_right: update_right, error: error} }
|
||||
let!(:codeharbor_link) { create(:codeharbor_link, user:) }
|
||||
let(:external_check_hash) { {message:, uuid_found: true, update_right:, error:} }
|
||||
let(:message) { 'message' }
|
||||
let(:update_right) { true }
|
||||
let(:error) { nil }
|
||||
|
||||
before { allow(ExerciseService::CheckExternal).to receive(:call).with(uuid: exercise.uuid, codeharbor_link: codeharbor_link).and_return(external_check_hash) }
|
||||
before { allow(ExerciseService::CheckExternal).to receive(:call).with(uuid: exercise.uuid, codeharbor_link:).and_return(external_check_hash) }
|
||||
|
||||
it 'renders the correct contents as json' do
|
||||
post_request
|
||||
@ -457,14 +457,14 @@ describe ExercisesController do
|
||||
describe 'POST #export_external_confirm' do
|
||||
render_views
|
||||
|
||||
let!(:codeharbor_link) { create(:codeharbor_link, user: user) }
|
||||
let!(:codeharbor_link) { create(:codeharbor_link, user:) }
|
||||
let(:post_request) { post :export_external_confirm, params: {id: exercise.id, codeharbor_link: codeharbor_link.id} }
|
||||
let(:error) { nil }
|
||||
let(:zip) { 'zip' }
|
||||
|
||||
before do
|
||||
allow(ProformaService::ExportTask).to receive(:call).with(exercise: exercise).and_return(zip)
|
||||
allow(ExerciseService::PushExternal).to receive(:call).with(zip: zip, codeharbor_link: codeharbor_link).and_return(error)
|
||||
allow(ProformaService::ExportTask).to receive(:call).with(exercise:).and_return(zip)
|
||||
allow(ExerciseService::PushExternal).to receive(:call).with(zip:, codeharbor_link:).and_return(error)
|
||||
end
|
||||
|
||||
it 'renders correct response' do
|
||||
@ -493,9 +493,9 @@ describe ExercisesController do
|
||||
|
||||
describe 'POST #import_uuid_check' do
|
||||
let(:exercise) { create(:dummy, uuid: SecureRandom.uuid) }
|
||||
let!(:codeharbor_link) { create(:codeharbor_link, user: user) }
|
||||
let!(:codeharbor_link) { create(:codeharbor_link, user:) }
|
||||
let(:uuid) { exercise.reload.uuid }
|
||||
let(:post_request) { post :import_uuid_check, params: {uuid: uuid} }
|
||||
let(:post_request) { post :import_uuid_check, params: {uuid:} }
|
||||
let(:headers) { {'Authorization' => "Bearer #{codeharbor_link.api_key}"} }
|
||||
|
||||
before { request.headers.merge! headers }
|
||||
@ -542,7 +542,7 @@ describe ExercisesController do
|
||||
end
|
||||
|
||||
describe 'POST #import_task' do
|
||||
let(:codeharbor_link) { create(:codeharbor_link, user: user) }
|
||||
let(:codeharbor_link) { create(:codeharbor_link, user:) }
|
||||
let!(:imported_exercise) { create(:fibonacci) }
|
||||
let(:post_request) { post :import_task, body: zip_file_content }
|
||||
let(:zip_file_content) { 'zipped task xml' }
|
||||
@ -560,7 +560,7 @@ describe ExercisesController do
|
||||
|
||||
it 'calls service' do
|
||||
post_request
|
||||
expect(ProformaService::Import).to have_received(:call).with(zip: be_a(Tempfile).and(has_content(zip_file_content)), user: user)
|
||||
expect(ProformaService::Import).to have_received(:call).with(zip: be_a(Tempfile).and(has_content(zip_file_content)), user:)
|
||||
end
|
||||
|
||||
context 'when import fails with ProformaError' do
|
||||
|
@ -61,7 +61,7 @@ describe InternalUsersController do
|
||||
context 'with an already activated user' do
|
||||
before do
|
||||
user.activate!
|
||||
put :activate, params: {id: user.id, internal_user: {activation_token: user.activation_token, password: password, password_confirmation: password}}
|
||||
put :activate, params: {id: user.id, internal_user: {activation_token: user.activation_token, password:, password_confirmation: password}}
|
||||
end
|
||||
|
||||
expect_redirect(:root)
|
||||
@ -80,7 +80,7 @@ describe InternalUsersController do
|
||||
end
|
||||
|
||||
context 'without a valid password confirmation' do
|
||||
before { put :activate, params: {id: user.id, internal_user: {activation_token: user.activation_token, password: password, password_confirmation: ''}} }
|
||||
before { put :activate, params: {id: user.id, internal_user: {activation_token: user.activation_token, password:, password_confirmation: ''}} }
|
||||
|
||||
expect_assigns(user: InternalUser)
|
||||
|
||||
@ -92,7 +92,7 @@ describe InternalUsersController do
|
||||
end
|
||||
|
||||
context 'with valid preconditions' do
|
||||
before { put :activate, params: {id: user.id, internal_user: {activation_token: user.activation_token, password: password, password_confirmation: password}} }
|
||||
before { put :activate, params: {id: user.id, internal_user: {activation_token: user.activation_token, password:, password_confirmation: password}} }
|
||||
|
||||
expect_assigns(user: InternalUser)
|
||||
|
||||
@ -278,7 +278,7 @@ describe InternalUsersController do
|
||||
let(:password) { 'foo' }
|
||||
|
||||
context 'with a matching password confirmation' do
|
||||
let(:perform_request) { proc { put :reset_password, params: {internal_user: {password: password, password_confirmation: password}, id: user.id, token: user.reset_password_token} } }
|
||||
let(:perform_request) { proc { put :reset_password, params: {internal_user: {password:, password_confirmation: password}, id: user.id, token: user.reset_password_token} } }
|
||||
|
||||
before { perform_request.call }
|
||||
|
||||
@ -310,7 +310,7 @@ describe InternalUsersController do
|
||||
|
||||
context 'without a matching password confirmation' do
|
||||
before do
|
||||
put :reset_password, params: {internal_user: {password: password, password_confirmation: ''}, id: user.id, token: user.reset_password_token}
|
||||
put :reset_password, params: {internal_user: {password:, password_confirmation: ''}, id: user.id, token: user.reset_password_token}
|
||||
end
|
||||
|
||||
expect_assigns(user: :user)
|
||||
|
@ -19,7 +19,7 @@ describe RequestForCommentsController do
|
||||
|
||||
it 'shows only rfc`s belonging to selected study group' do
|
||||
my_study_group = create(:study_group)
|
||||
rfc_within_my_study_group = create(:rfc, user: user)
|
||||
rfc_within_my_study_group = create(:rfc, user:)
|
||||
user.update(study_groups: [my_study_group])
|
||||
rfc_within_my_study_group.submission.update(study_group: my_study_group)
|
||||
|
||||
|
@ -9,13 +9,13 @@ describe SessionsController do
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:password) { attributes_for(:teacher)[:password] }
|
||||
let(:user) { InternalUser.create(user_attributes.merge(password: password)) }
|
||||
let(:user) { InternalUser.create(user_attributes.merge(password:)) }
|
||||
let(:user_attributes) { build(:teacher).attributes }
|
||||
|
||||
context 'with valid credentials' do
|
||||
before do
|
||||
user.activate!
|
||||
post :create, params: {email: user.email, password: password, remember_me: 1}
|
||||
post :create, params: {email: user.email, password:, remember_me: 1}
|
||||
end
|
||||
|
||||
expect_flash_message(:notice, :'sessions.create.success')
|
||||
@ -113,7 +113,7 @@ describe SessionsController do
|
||||
|
||||
context 'when LTI outcomes are supported' do
|
||||
# The expected message should be localized in the requested localization
|
||||
let(:message) { I18n.t('sessions.create_through_lti.session_with_outcome', consumer: consumer, locale: locale) }
|
||||
let(:message) { I18n.t('sessions.create_through_lti.session_with_outcome', consumer:, locale:) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:lti_outcome_service?).and_return(true)
|
||||
@ -125,7 +125,7 @@ describe SessionsController do
|
||||
|
||||
context 'when LTI outcomes are not supported' do
|
||||
# The expected message should be localized in the requested localization
|
||||
let(:message) { I18n.t('sessions.create_through_lti.session_without_outcome', consumer: consumer, locale: locale) }
|
||||
let(:message) { I18n.t('sessions.create_through_lti.session_without_outcome', consumer:, locale:) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:lti_outcome_service?).and_return(false)
|
||||
|
@ -116,7 +116,7 @@ describe SubmissionsController do
|
||||
context 'with an invalid filename' do
|
||||
let(:filename) { SecureRandom.hex }
|
||||
|
||||
before { get :render_file, params: {filename: filename, id: submission.id, token: token} }
|
||||
before { get :render_file, params: {filename:, id: submission.id, token:} }
|
||||
|
||||
expect_http_status(:not_found)
|
||||
end
|
||||
@ -125,7 +125,7 @@ describe SubmissionsController do
|
||||
let(:submission) { create(:submission, exercise: create(:audio_video)) }
|
||||
let(:filename) { file.name_with_extension }
|
||||
|
||||
before { get :render_file, params: {filename: filename, id: submission.id, token: token} }
|
||||
before { get :render_file, params: {filename:, id: submission.id, token:} }
|
||||
|
||||
context 'with a binary file' do
|
||||
let(:file) { submission.collect_files.detect {|file| file.file_type.file_extension == '.mp4' } }
|
||||
|
@ -8,7 +8,7 @@ FactoryBot.define do
|
||||
|
||||
trait :singleton_consumer do
|
||||
initialize_with do
|
||||
Consumer.find_or_initialize_by(name: name) do |consumer|
|
||||
Consumer.find_or_initialize_by(name:) do |consumer|
|
||||
consumer.oauth_key = SecureRandom.hex
|
||||
consumer.oauth_secret = SecureRandom.hex
|
||||
end
|
||||
|
@ -6,7 +6,7 @@ FactoryBot.define do
|
||||
default_memory_limit
|
||||
default_cpu_limit
|
||||
docker_image { 'hklement/ubuntu-coffee:latest' }
|
||||
file_type { association :dot_coffee, user: user }
|
||||
file_type { association :dot_coffee, user: }
|
||||
help
|
||||
name { 'CoffeeScript' }
|
||||
network_enabled { false }
|
||||
@ -22,7 +22,7 @@ FactoryBot.define do
|
||||
default_memory_limit
|
||||
default_cpu_limit
|
||||
docker_image { 'hklement/ubuntu-html:latest' }
|
||||
file_type { association :dot_html, user: user }
|
||||
file_type { association :dot_html, user: }
|
||||
help
|
||||
name { 'HTML5' }
|
||||
network_enabled { false }
|
||||
@ -40,7 +40,7 @@ FactoryBot.define do
|
||||
default_memory_limit
|
||||
default_cpu_limit
|
||||
docker_image { 'openhpi/co_execenv_java:8-antlr' }
|
||||
file_type { association :dot_java, user: user }
|
||||
file_type { association :dot_java, user: }
|
||||
help
|
||||
name { 'Java 8' }
|
||||
network_enabled { false }
|
||||
@ -58,7 +58,7 @@ FactoryBot.define do
|
||||
default_memory_limit
|
||||
default_cpu_limit
|
||||
docker_image { 'hklement/ubuntu-jruby:latest' }
|
||||
file_type { association :dot_rb, user: user }
|
||||
file_type { association :dot_rb, user: }
|
||||
help
|
||||
name { 'JRuby 1.7' }
|
||||
network_enabled { false }
|
||||
@ -76,7 +76,7 @@ FactoryBot.define do
|
||||
default_memory_limit
|
||||
default_cpu_limit
|
||||
docker_image { 'hklement/ubuntu-node:latest' }
|
||||
file_type { association :dot_js, user: user }
|
||||
file_type { association :dot_js, user: }
|
||||
help
|
||||
name { 'Node.js' }
|
||||
network_enabled { false }
|
||||
@ -92,7 +92,7 @@ FactoryBot.define do
|
||||
default_memory_limit
|
||||
default_cpu_limit
|
||||
docker_image { 'openhpi/co_execenv_python:3.4' }
|
||||
file_type { association :dot_py, user: user }
|
||||
file_type { association :dot_py, user: }
|
||||
help
|
||||
name { 'Python 3.4' }
|
||||
network_enabled { false }
|
||||
@ -110,7 +110,7 @@ FactoryBot.define do
|
||||
default_memory_limit
|
||||
default_cpu_limit
|
||||
docker_image { 'hklement/ubuntu-ruby:latest' }
|
||||
file_type { association :dot_rb, user: user }
|
||||
file_type { association :dot_rb, user: }
|
||||
help
|
||||
name { 'Ruby 2.2' }
|
||||
network_enabled { false }
|
||||
@ -128,7 +128,7 @@ FactoryBot.define do
|
||||
default_memory_limit
|
||||
default_cpu_limit
|
||||
docker_image { 'hklement/ubuntu-sinatra:latest' }
|
||||
file_type { association :dot_rb, user: user }
|
||||
file_type { association :dot_rb, user: }
|
||||
exposed_ports { [4567] }
|
||||
help
|
||||
name { 'Sinatra' }
|
||||
@ -147,7 +147,7 @@ FactoryBot.define do
|
||||
default_memory_limit
|
||||
default_cpu_limit
|
||||
docker_image { 'hklement/ubuntu-sqlite:latest' }
|
||||
file_type { association :dot_sql, user: user }
|
||||
file_type { association :dot_sql, user: }
|
||||
help
|
||||
name { 'SQLite' }
|
||||
network_enabled { false }
|
||||
@ -173,6 +173,6 @@ FactoryBot.define do
|
||||
end
|
||||
|
||||
trait :singleton_execution_environment do
|
||||
initialize_with { ExecutionEnvironment.where(name: name).first_or_create }
|
||||
initialize_with { ExecutionEnvironment.where(name:).first_or_create }
|
||||
end
|
||||
end
|
||||
|
@ -9,7 +9,7 @@ def create_seed_file(exercise, path, file_attributes = {})
|
||||
user: exercise.user
|
||||
)
|
||||
name = File.basename(path).gsub(file_extension, '')
|
||||
file_attributes.merge!(file_type: file_type, name: name, path: path.split('/')[1..-2].join('/'), role: file_attributes[:role] || 'regular_file')
|
||||
file_attributes.merge!(file_type:, name:, path: path.split('/')[1..-2].join('/'), role: file_attributes[:role] || 'regular_file')
|
||||
if file_type.binary?
|
||||
file_attributes[:native_file] = File.open(SeedsHelper.seed_file_path(path), 'r')
|
||||
else
|
||||
@ -22,7 +22,7 @@ FactoryBot.define do
|
||||
factory :audio_video, class: 'Exercise' do
|
||||
created_by_teacher
|
||||
description { "Try HTML's audio and video capabilities." }
|
||||
execution_environment { association :html, user: user }
|
||||
execution_environment { association :html, user: }
|
||||
instructions { 'Build a simple website including an HTML <audio> and <video> element. Link the following media files: chai.ogg, devstories.mp4.' }
|
||||
title { 'Audio & Video' }
|
||||
|
||||
@ -40,7 +40,7 @@ FactoryBot.define do
|
||||
factory :dummy, class: 'Exercise' do
|
||||
created_by_teacher
|
||||
description { 'Dummy' }
|
||||
execution_environment { association :ruby, user: user }
|
||||
execution_environment { association :ruby, user: }
|
||||
instructions
|
||||
title { 'Dummy' }
|
||||
|
||||
@ -56,7 +56,7 @@ FactoryBot.define do
|
||||
# attributes; `create_list`'s second argument is the number of records
|
||||
# to create and we make sure the user_exercise_feedback is associated properly to the exercise
|
||||
after(:create) do |exercise, evaluator|
|
||||
create_list(:user_exercise_feedback, evaluator.user_feedbacks_count, exercise: exercise)
|
||||
create_list(:user_exercise_feedback, evaluator.user_feedbacks_count, exercise:)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -64,7 +64,7 @@ FactoryBot.define do
|
||||
factory :even_odd, class: 'Exercise' do
|
||||
created_by_teacher
|
||||
description { 'Implement two methods even and odd which return whether a given number is even or odd, respectively.' }
|
||||
execution_environment { association :python, user: user }
|
||||
execution_environment { association :python, user: }
|
||||
instructions
|
||||
title { 'Even/Odd' }
|
||||
|
||||
@ -78,7 +78,7 @@ FactoryBot.define do
|
||||
factory :fibonacci, class: 'Exercise' do
|
||||
created_by_teacher
|
||||
description { 'Implement a recursive function that calculates a requested Fibonacci number.' }
|
||||
execution_environment { association :ruby, user: user }
|
||||
execution_environment { association :ruby, user: }
|
||||
instructions
|
||||
title { 'Fibonacci Sequence' }
|
||||
|
||||
@ -94,7 +94,7 @@ FactoryBot.define do
|
||||
factory :files, class: 'Exercise' do
|
||||
created_by_teacher
|
||||
description { 'Learn how to work with files.' }
|
||||
execution_environment { association :ruby, user: user }
|
||||
execution_environment { association :ruby, user: }
|
||||
instructions
|
||||
title { 'Working with Files' }
|
||||
|
||||
@ -108,7 +108,7 @@ FactoryBot.define do
|
||||
factory :geolocation, class: 'Exercise' do
|
||||
created_by_teacher
|
||||
description { "Use the HTML5 Geolocation API to get the user's geographical position." }
|
||||
execution_environment { association :html, user: user }
|
||||
execution_environment { association :html, user: }
|
||||
instructions
|
||||
title { 'Geolocation' }
|
||||
|
||||
@ -121,7 +121,7 @@ FactoryBot.define do
|
||||
factory :hello_world, class: 'Exercise' do
|
||||
created_by_teacher
|
||||
description { "Write a simple 'Hello World' application." }
|
||||
execution_environment { association :ruby, user: user }
|
||||
execution_environment { association :ruby, user: }
|
||||
instructions
|
||||
title { 'Hello World' }
|
||||
|
||||
@ -134,7 +134,7 @@ FactoryBot.define do
|
||||
factory :math, class: 'Exercise' do
|
||||
created_by_teacher
|
||||
description { 'Implement a recursive math library.' }
|
||||
execution_environment { association :java, user: user }
|
||||
execution_environment { association :java, user: }
|
||||
instructions
|
||||
title { 'Math' }
|
||||
|
||||
@ -149,7 +149,7 @@ FactoryBot.define do
|
||||
factory :primes, class: 'Exercise' do
|
||||
created_by_teacher
|
||||
description { 'Write a function that prints the first n prime numbers.' }
|
||||
execution_environment { association :node_js, user: user }
|
||||
execution_environment { association :node_js, user: }
|
||||
instructions
|
||||
title { 'Primes' }
|
||||
|
||||
@ -161,7 +161,7 @@ FactoryBot.define do
|
||||
factory :sql_select, class: 'Exercise' do
|
||||
created_by_teacher
|
||||
description { 'Learn to use the SELECT statement.' }
|
||||
execution_environment { association :sqlite, user: user }
|
||||
execution_environment { association :sqlite, user: }
|
||||
instructions { "Write a query which selects the full rows for all people with the last name 'Doe'." }
|
||||
title { 'SELECT' }
|
||||
|
||||
@ -175,7 +175,7 @@ FactoryBot.define do
|
||||
factory :tdd, class: 'Exercise' do
|
||||
created_by_teacher
|
||||
description { 'Learn to appreciate test-driven development.' }
|
||||
execution_environment { association :ruby, user: user }
|
||||
execution_environment { association :ruby, user: }
|
||||
instructions { SeedsHelper.read_seed_file('tdd/instructions.md') }
|
||||
title { 'Test-driven Development' }
|
||||
|
||||
@ -188,7 +188,7 @@ FactoryBot.define do
|
||||
factory :web_app, class: 'Exercise' do
|
||||
created_by_teacher
|
||||
description { 'Build a simple Web application with Sinatra.' }
|
||||
execution_environment { association :sinatra, user: user }
|
||||
execution_environment { association :sinatra, user: }
|
||||
instructions
|
||||
title { 'A Simple Web Application' }
|
||||
|
||||
|
@ -17,7 +17,7 @@ FactoryBot.define do
|
||||
|
||||
[ExternalUser, InternalUser].each do |klass|
|
||||
trait :"singleton_#{klass.name.underscore}" do
|
||||
initialize_with { klass.where(email: email).first_or_create }
|
||||
initialize_with { klass.where(email:).first_or_create }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -34,7 +34,7 @@ describe 'Authentication' do
|
||||
end
|
||||
|
||||
context 'with no authentication token' do
|
||||
let(:request_for_comment) { create(:rfc_with_comment, user: user) }
|
||||
let(:request_for_comment) { create(:rfc_with_comment, user:) }
|
||||
let(:rfc_path) { request_for_comment_url(request_for_comment) }
|
||||
|
||||
it 'denies access to the request for comment' do
|
||||
@ -49,7 +49,7 @@ describe 'Authentication' do
|
||||
context 'with an authentication token' do
|
||||
let(:user) { create(:learner) }
|
||||
let(:study_group) { request_for_comment.submission.study_group }
|
||||
let(:request_for_comment) { create(:rfc_with_comment, user: user) }
|
||||
let(:request_for_comment) { create(:rfc_with_comment, user:) }
|
||||
let(:commenting_user) { InternalUser.create(attributes_for(:teacher)) }
|
||||
let(:mail) { UserMailer.got_new_comment(request_for_comment.comments.first, request_for_comment, commenting_user) }
|
||||
let(:rfc_link) { request_for_comment_url(request_for_comment, token: token.shared_secret) }
|
||||
@ -57,7 +57,7 @@ describe 'Authentication' do
|
||||
before { allow(AuthenticationToken).to receive(:generate!).with(user, study_group).and_return(token).once }
|
||||
|
||||
context 'when the token is valid' do
|
||||
let(:token) { create(:authentication_token, user: user, study_group: study_group) }
|
||||
let(:token) { create(:authentication_token, user:, study_group:) }
|
||||
|
||||
it 'allows access to the request for comment' do
|
||||
mail.deliver_now
|
||||
@ -68,7 +68,7 @@ describe 'Authentication' do
|
||||
end
|
||||
|
||||
context 'with an expired authentication token' do
|
||||
let(:token) { create(:authentication_token, :invalid, user: user, study_group: study_group) }
|
||||
let(:token) { create(:authentication_token, :invalid, user:, study_group:) }
|
||||
|
||||
it 'denies access to the request for comment' do
|
||||
mail.deliver_now
|
||||
@ -81,7 +81,7 @@ describe 'Authentication' do
|
||||
end
|
||||
|
||||
context 'when the authentication token is used to login' do
|
||||
let(:token) { create(:authentication_token, user: user, study_group: study_group) }
|
||||
let(:token) { create(:authentication_token, user:, study_group:) }
|
||||
|
||||
it 'invalidates the token on login' do
|
||||
mail.deliver_now
|
||||
@ -108,14 +108,14 @@ describe 'Authentication' do
|
||||
end
|
||||
|
||||
context 'with an authentication token' do
|
||||
let(:request_for_comment) { create(:rfc_with_comment, user: user) }
|
||||
let(:request_for_comment) { create(:rfc_with_comment, user:) }
|
||||
let(:study_group) { request_for_comment.submission.study_group }
|
||||
let(:commenting_user) { InternalUser.create(attributes_for(:teacher)) }
|
||||
let(:mail) { UserMailer.got_new_comment(request_for_comment.comments.first, request_for_comment, commenting_user) }
|
||||
let(:rfc_link) { request_for_comment_url(request_for_comment, token: token.shared_secret) }
|
||||
|
||||
it 'still invalidates the token on login' do
|
||||
token = create(:authentication_token, user: user, study_group: study_group)
|
||||
token = create(:authentication_token, user:, study_group:)
|
||||
mail = UserMailer.got_new_comment(request_for_comment.comments.first, request_for_comment, commenting_user)
|
||||
mail.deliver_now
|
||||
visit(request_for_comment_url(request_for_comment, token: token.shared_secret))
|
||||
|
@ -111,7 +111,7 @@ describe 'Editor', js: true do
|
||||
end
|
||||
|
||||
it 'contains a button for submitting the exercise' do
|
||||
submission = build(:submission, user: user, exercise: exercise)
|
||||
submission = build(:submission, user:, exercise:)
|
||||
allow(submission).to receive(:calculate_score).and_return(scoring_response)
|
||||
allow(Submission).to receive(:find).and_return(submission)
|
||||
click_button(I18n.t('exercises.editor.score'))
|
||||
|
@ -4,15 +4,15 @@ require 'rails_helper'
|
||||
|
||||
describe 'ExternalUserStatistics', js: true do
|
||||
let(:learner) { create(:external_user) }
|
||||
let(:exercise) { create(:dummy, user: user) }
|
||||
let(:exercise) { create(:dummy, user:) }
|
||||
let(:study_group) { create(:study_group) }
|
||||
let(:password) { 'password123456' }
|
||||
|
||||
before do
|
||||
2.times { create(:submission, cause: 'autosave', user: learner, exercise: exercise, study_group: study_group) }
|
||||
2.times { create(:submission, cause: 'run', user: learner, exercise: exercise, study_group: study_group) }
|
||||
create(:submission, cause: 'assess', user: learner, exercise: exercise, study_group: study_group)
|
||||
create(:submission, cause: 'submit', user: learner, exercise: exercise, study_group: study_group)
|
||||
2.times { create(:submission, cause: 'autosave', user: learner, exercise:, study_group:) }
|
||||
2.times { create(:submission, cause: 'run', user: learner, exercise:, study_group:) }
|
||||
create(:submission, cause: 'assess', user: learner, exercise:, study_group:)
|
||||
create(:submission, cause: 'submit', user: learner, exercise:, study_group:)
|
||||
|
||||
study_group.external_users << learner
|
||||
study_group.internal_users << user
|
||||
@ -27,7 +27,7 @@ describe 'ExternalUserStatistics', js: true do
|
||||
end
|
||||
|
||||
context 'when a admin accesses the page' do
|
||||
let(:user) { create(:admin, password: password) }
|
||||
let(:user) { create(:admin, password:) }
|
||||
|
||||
it 'does display the option to enable autosaves' do
|
||||
expect(page).to have_content(I18n.t('exercises.external_users.statistics.toggle_status_on')).or have_content(I18n.t('exercises.external_users.statistics.toggle_status_off'))
|
||||
@ -35,7 +35,7 @@ describe 'ExternalUserStatistics', js: true do
|
||||
end
|
||||
|
||||
context 'when a teacher accesses the page' do
|
||||
let(:user) { create(:teacher, password: password) }
|
||||
let(:user) { create(:teacher, password:) }
|
||||
|
||||
it 'does not display the option to enable autosaves' do
|
||||
expect(page).not_to have_content(I18n.t('exercises.external_users.statistics.toggle_status_on'))
|
||||
|
@ -6,7 +6,7 @@ describe Assessor do
|
||||
let(:assessor) { described_class.new(execution_environment: build(:ruby)) }
|
||||
|
||||
describe '#assess' do
|
||||
let(:assess) { assessor.assess(stdout: stdout) }
|
||||
let(:assess) { assessor.assess(stdout:) }
|
||||
let(:stdout) { "Finished in 0.1 seconds (files took 0.1 seconds to load)\n2 examples, 1 failure" }
|
||||
|
||||
context 'when an error occurs' do
|
||||
@ -39,7 +39,7 @@ describe Assessor do
|
||||
describe '#calculate_score' do
|
||||
let(:count) { 42 }
|
||||
let(:passed) { 17 }
|
||||
let(:test_outcome) { {count: count, passed: passed} }
|
||||
let(:test_outcome) { {count:, passed:} }
|
||||
|
||||
it 'returns the correct score' do
|
||||
expect(assessor.send(:calculate_score, test_outcome)).to eq(passed.to_f / count)
|
||||
|
@ -13,7 +13,7 @@ describe JunitAdapter do
|
||||
let(:error_matches) { [] }
|
||||
|
||||
it 'returns the correct numbers' do
|
||||
expect(adapter.parse_output(stdout: stdout)).to eq(count: count, failed: failed, error_messages: error_matches)
|
||||
expect(adapter.parse_output(stdout:)).to eq(count:, failed:, error_messages: error_matches)
|
||||
end
|
||||
end
|
||||
|
||||
@ -22,7 +22,7 @@ describe JunitAdapter do
|
||||
let(:stdout) { "OK (#{count} tests)" }
|
||||
|
||||
it 'returns the correct numbers' do
|
||||
expect(adapter.parse_output(stdout: stdout)).to eq(count: count, passed: count)
|
||||
expect(adapter.parse_output(stdout:)).to eq(count:, passed: count)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -10,7 +10,7 @@ describe MochaAdapter do
|
||||
|
||||
describe '#parse_output' do
|
||||
it 'returns the correct numbers' do
|
||||
expect(adapter.parse_output(stdout: stdout)).to eq(count: count, failed: failed)
|
||||
expect(adapter.parse_output(stdout:)).to eq(count:, failed:)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -11,7 +11,7 @@ describe PyUnitAdapter do
|
||||
|
||||
describe '#parse_output' do
|
||||
it 'returns the correct numbers' do
|
||||
expect(adapter.parse_output(stderr: stderr)).to eq(count: count, failed: failed, error_messages: error_matches)
|
||||
expect(adapter.parse_output(stderr:)).to eq(count:, failed:, error_messages: error_matches)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -10,7 +10,7 @@ describe RspecAdapter do
|
||||
|
||||
describe '#parse_output' do
|
||||
it 'returns the correct numbers' do
|
||||
expect(adapter.parse_output(stdout: stdout)).to eq(count: count, failed: failed)
|
||||
expect(adapter.parse_output(stdout:)).to eq(count:, failed:)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -145,7 +145,7 @@ describe Runner::Strategy::Poseidon do
|
||||
it "returns true on status #{status}" do
|
||||
faraday_connection = instance_double Faraday::Connection
|
||||
allow(described_class).to receive(:http_connection).and_return(faraday_connection)
|
||||
allow(faraday_connection).to receive(:put).and_return(Faraday::Response.new(status: status))
|
||||
allow(faraday_connection).to receive(:put).and_return(Faraday::Response.new(status:))
|
||||
expect(action.call).to be_truthy
|
||||
end
|
||||
end
|
||||
@ -154,7 +154,7 @@ describe Runner::Strategy::Poseidon do
|
||||
it "raises an exception on status #{status}" do
|
||||
faraday_connection = instance_double Faraday::Connection
|
||||
allow(described_class).to receive(:http_connection).and_return(faraday_connection)
|
||||
allow(faraday_connection).to receive(:put).and_return(Faraday::Response.new(status: status))
|
||||
allow(faraday_connection).to receive(:put).and_return(Faraday::Response.new(status:))
|
||||
expect { action.call }.to raise_exception Runner::Error::UnexpectedResponse
|
||||
end
|
||||
end
|
||||
@ -248,7 +248,7 @@ describe Runner::Strategy::Poseidon do
|
||||
.stub_request(:post, "#{described_class.config[:url]}/runners/#{runner_id}/execute")
|
||||
.with(
|
||||
body: {
|
||||
command: command,
|
||||
command:,
|
||||
timeLimit: execution_environment.permitted_execution_time,
|
||||
privilegedExecution: execution_environment.privileged_execution,
|
||||
},
|
||||
|
@ -10,7 +10,7 @@ describe SqlResultSetComparatorAdapter do
|
||||
let(:stdout) { "Missing tuples: [1]\nUnexpected tuples: []" }
|
||||
|
||||
it 'considers the test as failed' do
|
||||
expect(adapter.parse_output(stdout: stdout)).to eq(count: 1, failed: 1)
|
||||
expect(adapter.parse_output(stdout:)).to eq(count: 1, failed: 1)
|
||||
end
|
||||
end
|
||||
|
||||
@ -18,7 +18,7 @@ describe SqlResultSetComparatorAdapter do
|
||||
let(:stdout) { "Missing tuples: []\nUnexpected tuples: [1]" }
|
||||
|
||||
it 'considers the test as failed' do
|
||||
expect(adapter.parse_output(stdout: stdout)).to eq(count: 1, failed: 1)
|
||||
expect(adapter.parse_output(stdout:)).to eq(count: 1, failed: 1)
|
||||
end
|
||||
end
|
||||
|
||||
@ -26,7 +26,7 @@ describe SqlResultSetComparatorAdapter do
|
||||
let(:stdout) { "Missing tuples: []\nUnexpected tuples: []" }
|
||||
|
||||
it 'considers the test as passed' do
|
||||
expect(adapter.parse_output(stdout: stdout)).to eq(count: 1, passed: 1)
|
||||
expect(adapter.parse_output(stdout:)).to eq(count: 1, passed: 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -11,19 +11,19 @@ describe TestingFrameworkAdapter do
|
||||
describe '#augment_output' do
|
||||
context 'when missing the count of all tests' do
|
||||
it 'adds the count of all tests' do
|
||||
expect(adapter.send(:augment_output, failed: failed, passed: passed)).to include(count: count)
|
||||
expect(adapter.send(:augment_output, failed:, passed:)).to include(count:)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when missing the count of failed tests' do
|
||||
it 'adds the count of failed tests' do
|
||||
expect(adapter.send(:augment_output, count: count, passed: passed)).to include(failed: failed)
|
||||
expect(adapter.send(:augment_output, count:, passed:)).to include(failed:)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when missing the count of passed tests' do
|
||||
it 'adds the count of passed tests' do
|
||||
expect(adapter.send(:augment_output, count: count, failed: failed)).to include(passed: passed)
|
||||
expect(adapter.send(:augment_output, count:, failed:)).to include(passed:)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -42,7 +42,7 @@ describe TestingFrameworkAdapter do
|
||||
|
||||
describe '#test_outcome' do
|
||||
it 'calls the framework-specific implementation' do
|
||||
allow(adapter).to receive(:parse_output).and_return(count: count, failed: failed, passed: passed)
|
||||
allow(adapter).to receive(:parse_output).and_return(count:, failed:, passed:)
|
||||
expect(adapter).to receive(:parse_output)
|
||||
adapter.test_outcome('')
|
||||
end
|
||||
|
@ -63,8 +63,8 @@ describe UserMailer do
|
||||
|
||||
describe '#got_new_comment' do
|
||||
let(:user) { create(:learner) }
|
||||
let(:token) { AuthenticationToken.find_by(user: user) }
|
||||
let(:request_for_comment) { create(:rfc_with_comment, user: user) }
|
||||
let(:token) { AuthenticationToken.find_by(user:) }
|
||||
let(:request_for_comment) { create(:rfc_with_comment, user:) }
|
||||
let(:commenting_user) { InternalUser.create(attributes_for(:teacher)) }
|
||||
let(:mail) { described_class.got_new_comment(request_for_comment.comments.first, request_for_comment, commenting_user).deliver_now }
|
||||
|
||||
@ -116,9 +116,9 @@ describe UserMailer do
|
||||
|
||||
describe '#got_new_comment_for_subscription' do
|
||||
let(:user) { create(:learner) }
|
||||
let(:token) { AuthenticationToken.find_by(user: user) }
|
||||
let(:request_for_comment) { create(:rfc_with_comment, user: user) }
|
||||
let(:subscription) { Subscription.create(request_for_comment: request_for_comment, user: user, study_group_id: user.current_study_group_id) }
|
||||
let(:token) { AuthenticationToken.find_by(user:) }
|
||||
let(:request_for_comment) { create(:rfc_with_comment, user:) }
|
||||
let(:subscription) { Subscription.create(request_for_comment:, user:, study_group_id: user.current_study_group_id) }
|
||||
let(:from_user) { InternalUser.create(attributes_for(:teacher)) }
|
||||
let(:mail) { described_class.got_new_comment_for_subscription(request_for_comment.comments.first, subscription, from_user).deliver_now }
|
||||
|
||||
@ -172,7 +172,7 @@ describe UserMailer do
|
||||
let(:user) { create(:learner) }
|
||||
let(:receiver) { create(:teacher) }
|
||||
let(:token) { AuthenticationToken.find_by(user: receiver) }
|
||||
let(:request_for_comment) { create(:rfc_with_comment, user: user) }
|
||||
let(:request_for_comment) { create(:rfc_with_comment, user:) }
|
||||
let(:mail) { described_class.send_thank_you_note(request_for_comment, receiver).deliver_now }
|
||||
|
||||
it 'sets the correct sender' do
|
||||
|
@ -7,7 +7,7 @@ describe Exercise do
|
||||
let(:users) { create_list(:external_user, 10) }
|
||||
|
||||
def create_submissions
|
||||
create_list(:submission, 10, cause: 'submit', exercise: exercise, score: Forgery(:basic).number, user: users.sample)
|
||||
create_list(:submission, 10, cause: 'submit', exercise:, score: Forgery(:basic).number, user: users.sample)
|
||||
end
|
||||
|
||||
it 'validates the number of main files' do
|
||||
@ -113,7 +113,7 @@ describe Exercise do
|
||||
|
||||
it 'overwrites the supplied attributes' do
|
||||
title = Forgery(:basic).text
|
||||
expect(exercise.duplicate(title: title).title).to eq(title)
|
||||
expect(exercise.duplicate(title:).title).to eq(title)
|
||||
end
|
||||
|
||||
it 'duplicates all associated files' do
|
||||
|
@ -24,7 +24,7 @@ describe InternalUser do
|
||||
end
|
||||
|
||||
it 'validates the confirmation of the password' do
|
||||
user.update(password: password, password_confirmation: '')
|
||||
user.update(password:, password_confirmation: '')
|
||||
expect(user.errors[:password_confirmation]).to be_present
|
||||
end
|
||||
|
||||
@ -40,7 +40,7 @@ describe InternalUser do
|
||||
before { user.deliver_reset_password_instructions! }
|
||||
|
||||
it 'validates the confirmation of the password' do
|
||||
user.update(password: password, password_confirmation: '')
|
||||
user.update(password:, password_confirmation: '')
|
||||
expect(user.errors[:password_confirmation]).to be_present
|
||||
end
|
||||
|
||||
@ -54,7 +54,7 @@ describe InternalUser do
|
||||
let(:user) { create(:teacher, activation_state: 'active') }
|
||||
|
||||
it 'does not validate the confirmation of the password' do
|
||||
user.update(password: password, password_confirmation: '')
|
||||
user.update(password:, password_confirmation: '')
|
||||
expect(user.errors[:password_confirmation]).not_to be_present
|
||||
end
|
||||
|
||||
|
@ -31,7 +31,7 @@ describe Runner do
|
||||
describe '::strategy_class' do
|
||||
shared_examples 'uses the strategy defined in the constant' do |strategy, strategy_class|
|
||||
let(:codeocean_config) { instance_double(CodeOcean::Config) }
|
||||
let(:runner_management_config) { {runner_management: {enabled: true, strategy: strategy}} }
|
||||
let(:runner_management_config) { {runner_management: {enabled: true, strategy:}} }
|
||||
|
||||
before do
|
||||
# Ensure to reset the memorized helper
|
||||
@ -166,7 +166,7 @@ describe Runner do
|
||||
describe 'creation' do
|
||||
let(:user) { create(:external_user) }
|
||||
let(:execution_environment) { create(:ruby) }
|
||||
let(:create_action) { -> { described_class.create(user: user, execution_environment: execution_environment) } }
|
||||
let(:create_action) { -> { described_class.create(user:, execution_environment:) } }
|
||||
|
||||
it 'requests a runner id from the runner management' do
|
||||
expect(strategy_class).to receive(:request_from_management)
|
||||
@ -254,7 +254,7 @@ describe Runner do
|
||||
end
|
||||
|
||||
context 'when a runner already exists' do
|
||||
let!(:existing_runner) { create(:runner, user: user, execution_environment: exercise.execution_environment) }
|
||||
let!(:existing_runner) { create(:runner, user:, execution_environment: exercise.execution_environment) }
|
||||
|
||||
it 'returns the existing runner' do
|
||||
new_runner = described_class.for(user, exercise.execution_environment)
|
||||
|
@ -67,7 +67,7 @@ describe Submission do
|
||||
end
|
||||
|
||||
describe '#siblings' do
|
||||
let(:siblings) { described_class.find_by(user: user).siblings }
|
||||
let(:siblings) { described_class.find_by(user:).siblings }
|
||||
let(:user) { create(:external_user) }
|
||||
|
||||
before do
|
||||
@ -93,7 +93,7 @@ describe Submission do
|
||||
context 'with no exercise feedback' do
|
||||
let(:exercise) { create(:dummy) }
|
||||
let(:user) { build(:external_user, id: (11 - (exercise.created_at.to_i % 10)) % 10) }
|
||||
let(:submission) { build(:submission, exercise: exercise, user: user) }
|
||||
let(:submission) { build(:submission, exercise:, user:) }
|
||||
|
||||
it 'sends 10% of users to feedback page' do
|
||||
expect(submission.send(:redirect_to_feedback?)).to be_truthy
|
||||
@ -101,7 +101,7 @@ describe Submission do
|
||||
|
||||
it 'does not redirect other users' do
|
||||
9.times do |i|
|
||||
submission = build(:submission, exercise: exercise, user: build(:external_user, id: (11 - (exercise.created_at.to_i % 10)) - i - 1))
|
||||
submission = build(:submission, exercise:, user: build(:external_user, id: (11 - (exercise.created_at.to_i % 10)) - i - 1))
|
||||
expect(submission.send(:redirect_to_feedback?)).to be_falsey
|
||||
end
|
||||
end
|
||||
@ -110,7 +110,7 @@ describe Submission do
|
||||
context 'with little exercise feedback' do
|
||||
let(:exercise) { create(:dummy_with_user_feedbacks) }
|
||||
let(:user) { build(:external_user, id: (11 - (exercise.created_at.to_i % 10)) % 10) }
|
||||
let(:submission) { build(:submission, exercise: exercise, user: user) }
|
||||
let(:submission) { build(:submission, exercise:, user:) }
|
||||
|
||||
it 'sends 10% of users to feedback page' do
|
||||
expect(submission.send(:redirect_to_feedback?)).to be_truthy
|
||||
@ -118,7 +118,7 @@ describe Submission do
|
||||
|
||||
it 'does not redirect other users' do
|
||||
9.times do |i|
|
||||
submission = build(:submission, exercise: exercise, user: build(:external_user, id: (11 - (exercise.created_at.to_i % 10)) - i - 1))
|
||||
submission = build(:submission, exercise:, user: build(:external_user, id: (11 - (exercise.created_at.to_i % 10)) - i - 1))
|
||||
expect(submission.send(:redirect_to_feedback?)).to be_falsey
|
||||
end
|
||||
end
|
||||
|
@ -215,7 +215,7 @@ describe ExercisePolicy do
|
||||
before do
|
||||
[admin, teacher].each do |user|
|
||||
[true, false].each do |public|
|
||||
create(:dummy, public: public, user_id: user.id, user_type: InternalUser.name)
|
||||
create(:dummy, public:, user_id: user.id, user_type: InternalUser.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -15,7 +15,7 @@ require 'pundit/rspec'
|
||||
# run twice. It is recommended that you do not name files matching this glob to
|
||||
# end with _spec.rb. You can configure this pattern with with the --pattern
|
||||
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
|
||||
Dir[Rails.root.join('spec/support/**/*.rb')].sort.each {|f| require f }
|
||||
Dir[Rails.root.join('spec/support/**/*.rb')].each {|f| require f }
|
||||
|
||||
# Checks for pending migrations before tests are run.
|
||||
# If you are not using ActiveRecord, you can remove this line.
|
||||
|
@ -4,7 +4,7 @@ require 'rails_helper'
|
||||
|
||||
describe ExerciseService::CheckExternal do
|
||||
describe '.new' do
|
||||
subject(:export_service) { described_class.new(uuid: uuid, codeharbor_link: codeharbor_link) }
|
||||
subject(:export_service) { described_class.new(uuid:, codeharbor_link:) }
|
||||
|
||||
let(:uuid) { SecureRandom.uuid }
|
||||
let(:codeharbor_link) { build(:codeharbor_link) }
|
||||
@ -19,7 +19,7 @@ describe ExerciseService::CheckExternal do
|
||||
end
|
||||
|
||||
describe '#execute' do
|
||||
subject(:check_external_service) { described_class.call(uuid: uuid, codeharbor_link: codeharbor_link) }
|
||||
subject(:check_external_service) { described_class.call(uuid:, codeharbor_link:) }
|
||||
|
||||
let(:uuid) { SecureRandom.uuid }
|
||||
let(:codeharbor_link) { build(:codeharbor_link) }
|
||||
@ -38,7 +38,7 @@ describe ExerciseService::CheckExternal do
|
||||
|
||||
it 'submits the correct body' do
|
||||
expect(check_external_service).to have_requested(:post, codeharbor_link.check_uuid_url)
|
||||
.with(body: {uuid: uuid}.to_json)
|
||||
.with(body: {uuid:}.to_json)
|
||||
end
|
||||
|
||||
context 'when response contains a JSON with expected keys' do
|
||||
|
@ -4,7 +4,7 @@ require 'rails_helper'
|
||||
|
||||
RSpec.describe ExerciseService::PushExternal do
|
||||
describe '.new' do
|
||||
subject(:push_external) { described_class.new(zip: zip, codeharbor_link: codeharbor_link) }
|
||||
subject(:push_external) { described_class.new(zip:, codeharbor_link:) }
|
||||
|
||||
let(:zip) { ProformaService::ExportTask.call(exercise: build(:dummy)) }
|
||||
let(:codeharbor_link) { build(:codeharbor_link) }
|
||||
@ -19,14 +19,14 @@ RSpec.describe ExerciseService::PushExternal do
|
||||
end
|
||||
|
||||
describe '#execute' do
|
||||
subject(:push_external) { described_class.call(zip: zip, codeharbor_link: codeharbor_link) }
|
||||
subject(:push_external) { described_class.call(zip:, codeharbor_link:) }
|
||||
|
||||
let(:zip) { ProformaService::ExportTask.call(exercise: build(:dummy)) }
|
||||
let(:codeharbor_link) { build(:codeharbor_link) }
|
||||
let(:status) { 200 }
|
||||
let(:response) { '' }
|
||||
|
||||
before { stub_request(:post, codeharbor_link.push_url).to_return(status: status, body: response) }
|
||||
before { stub_request(:post, codeharbor_link.push_url).to_return(status:, body: response) }
|
||||
|
||||
it 'calls the correct url' do
|
||||
expect(push_external).to have_requested(:post, codeharbor_link.push_url)
|
||||
|
@ -4,7 +4,7 @@ require 'rails_helper'
|
||||
|
||||
RSpec.describe ProformaService::ConvertExerciseToTask do
|
||||
describe '.new' do
|
||||
subject(:convert_to_task) { described_class.new(exercise: exercise) }
|
||||
subject(:convert_to_task) { described_class.new(exercise:) }
|
||||
|
||||
let(:exercise) { build(:dummy) }
|
||||
|
||||
@ -16,10 +16,10 @@ RSpec.describe ProformaService::ConvertExerciseToTask do
|
||||
describe '#execute' do
|
||||
subject(:task) { convert_to_task.execute }
|
||||
|
||||
let(:convert_to_task) { described_class.new(exercise: exercise) }
|
||||
let(:convert_to_task) { described_class.new(exercise:) }
|
||||
let(:exercise) do
|
||||
create(:dummy,
|
||||
execution_environment: execution_environment,
|
||||
execution_environment:,
|
||||
instructions: 'instruction',
|
||||
uuid: SecureRandom.uuid,
|
||||
files: files + tests)
|
||||
@ -85,7 +85,7 @@ RSpec.describe ProformaService::ConvertExerciseToTask do
|
||||
|
||||
context 'when exercise has a regular file' do
|
||||
let(:files) { [file] }
|
||||
let(:file) { build(:file, role: 'regular_file', hidden: hidden, read_only: read_only) }
|
||||
let(:file) { build(:file, role: 'regular_file', hidden:, read_only:) }
|
||||
let(:hidden) { true }
|
||||
let(:read_only) { true }
|
||||
|
||||
|
@ -4,7 +4,7 @@ require 'rails_helper'
|
||||
|
||||
describe ProformaService::ConvertTaskToExercise do
|
||||
describe '.new' do
|
||||
subject(:convert_to_exercise_service) { described_class.new(task: task, user: user, exercise: exercise) }
|
||||
subject(:convert_to_exercise_service) { described_class.new(task:, user:, exercise:) }
|
||||
|
||||
let(:task) { Proforma::Task.new }
|
||||
let(:user) { build(:teacher) }
|
||||
@ -24,7 +24,7 @@ describe ProformaService::ConvertTaskToExercise do
|
||||
end
|
||||
|
||||
describe '#execute' do
|
||||
subject(:convert_to_exercise_service) { described_class.call(task: task, user: user, exercise: exercise) }
|
||||
subject(:convert_to_exercise_service) { described_class.call(task:, user:, exercise:) }
|
||||
|
||||
before { create(:dot_txt) }
|
||||
|
||||
@ -36,10 +36,10 @@ describe ProformaService::ConvertTaskToExercise do
|
||||
uuid: 'uuid',
|
||||
parent_uuid: 'parent_uuid',
|
||||
language: 'language',
|
||||
meta_data: meta_data,
|
||||
model_solutions: model_solutions,
|
||||
files: files,
|
||||
tests: tests
|
||||
meta_data:,
|
||||
model_solutions:,
|
||||
files:,
|
||||
tests:
|
||||
)
|
||||
end
|
||||
let(:user) { create(:teacher) }
|
||||
@ -63,7 +63,7 @@ describe ProformaService::ConvertTaskToExercise do
|
||||
description: 'description',
|
||||
uuid: be_blank,
|
||||
unpublished: true,
|
||||
user: user,
|
||||
user:,
|
||||
files: be_empty,
|
||||
public: false,
|
||||
hide_file_tree: false,
|
||||
@ -80,11 +80,11 @@ describe ProformaService::ConvertTaskToExercise do
|
||||
let(:meta_data) do
|
||||
{
|
||||
CodeOcean: {
|
||||
public: public,
|
||||
hide_file_tree: hide_file_tree,
|
||||
allow_file_creation: allow_file_creation,
|
||||
allow_auto_completion: allow_auto_completion,
|
||||
expected_difficulty: expected_difficulty,
|
||||
public:,
|
||||
hide_file_tree:,
|
||||
allow_file_creation:,
|
||||
allow_auto_completion:,
|
||||
expected_difficulty:,
|
||||
execution_environment_id: execution_environment&.id,
|
||||
files: files_meta_data,
|
||||
},
|
||||
@ -98,7 +98,7 @@ describe ProformaService::ConvertTaskToExercise do
|
||||
description: 'description',
|
||||
uuid: be_blank,
|
||||
unpublished: true,
|
||||
user: user,
|
||||
user:,
|
||||
files: be_empty,
|
||||
public: true,
|
||||
hide_file_tree: true,
|
||||
@ -125,13 +125,13 @@ describe ProformaService::ConvertTaskToExercise do
|
||||
let(:file) do
|
||||
Proforma::TaskFile.new(
|
||||
id: 'id',
|
||||
content: content,
|
||||
filename: filename,
|
||||
content:,
|
||||
filename:,
|
||||
used_by_grader: 'used_by_grader',
|
||||
visible: 'yes',
|
||||
usage_by_lms: usage_by_lms,
|
||||
binary: binary,
|
||||
mimetype: mimetype
|
||||
usage_by_lms:,
|
||||
binary:,
|
||||
mimetype:
|
||||
)
|
||||
end
|
||||
let(:filename) { "#{path}filename.txt" }
|
||||
@ -192,7 +192,7 @@ describe ProformaService::ConvertTaskToExercise do
|
||||
let(:content) { 'test' * (10**5) }
|
||||
|
||||
it 'creates an exercise with a file that has the correct attributes' do
|
||||
expect(convert_to_exercise_service.files.first).to have_attributes(content: content)
|
||||
expect(convert_to_exercise_service.files.first).to have_attributes(content:)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -4,7 +4,7 @@ require 'rails_helper'
|
||||
|
||||
describe ProformaService::ExportTask do
|
||||
describe '.new' do
|
||||
subject(:export_task) { described_class.new(exercise: exercise) }
|
||||
subject(:export_task) { described_class.new(exercise:) }
|
||||
|
||||
let(:exercise) { build(:dummy) }
|
||||
|
||||
@ -22,15 +22,15 @@ describe ProformaService::ExportTask do
|
||||
end
|
||||
|
||||
describe '#execute' do
|
||||
subject(:export_task) { described_class.call(exercise: exercise) }
|
||||
subject(:export_task) { described_class.call(exercise:) }
|
||||
|
||||
let(:task) { Proforma::Task.new }
|
||||
let(:exercise) { build(:dummy) }
|
||||
let(:exporter) { instance_double(Proforma::Exporter, perform: 'zip') }
|
||||
|
||||
before do
|
||||
allow(ProformaService::ConvertExerciseToTask).to receive(:call).with(exercise: exercise).and_return(task)
|
||||
allow(Proforma::Exporter).to receive(:new).with(task: task, custom_namespaces: [{prefix: 'CodeOcean', uri: 'codeocean.openhpi.de'}]).and_return(exporter)
|
||||
allow(ProformaService::ConvertExerciseToTask).to receive(:call).with(exercise:).and_return(task)
|
||||
allow(Proforma::Exporter).to receive(:new).with(task:, custom_namespaces: [{prefix: 'CodeOcean', uri: 'codeocean.openhpi.de'}]).and_return(exporter)
|
||||
end
|
||||
|
||||
it do
|
||||
|
@ -4,7 +4,7 @@ require 'rails_helper'
|
||||
|
||||
describe ProformaService::Import do
|
||||
describe '.new' do
|
||||
subject(:import_service) { described_class.new(zip: zip, user: user) }
|
||||
subject(:import_service) { described_class.new(zip:, user:) }
|
||||
|
||||
let(:zip) { Tempfile.new('proforma_test_zip_file') }
|
||||
let(:user) { build(:teacher) }
|
||||
@ -27,14 +27,14 @@ describe ProformaService::Import do
|
||||
let(:exercise) do
|
||||
create(:dummy,
|
||||
instructions: 'instruction',
|
||||
execution_environment: execution_environment,
|
||||
execution_environment:,
|
||||
files: files + tests,
|
||||
hide_file_tree: true,
|
||||
allow_file_creation: false,
|
||||
allow_auto_completion: true,
|
||||
expected_difficulty: 7,
|
||||
uuid: uuid,
|
||||
user: user)
|
||||
uuid:,
|
||||
user:)
|
||||
end
|
||||
|
||||
let(:uuid) { nil }
|
||||
|
@ -2,6 +2,6 @@
|
||||
|
||||
module Authentication
|
||||
def sign_in(user, password)
|
||||
page.driver.post(sessions_url, email: user.email, password: password)
|
||||
page.driver.post(sessions_url, email: user.email, password:)
|
||||
end
|
||||
end
|
||||
|
Reference in New Issue
Block a user