Merge branch 'master' into user_exercise_feedback_backend
# Conflicts: # app/views/application/_navigation.html.slim
This commit is contained in:
18
app/assets/javascripts/error_templates.js
Normal file
18
app/assets/javascripts/error_templates.js
Normal file
@@ -0,0 +1,18 @@
|
||||
$(function() {
|
||||
if ($.isController('error_templates')) {
|
||||
$('#add-attribute').find('button').on('click', function () {
|
||||
$.ajax(location + '/attribute.json', {
|
||||
method: 'POST',
|
||||
data: {
|
||||
_method: 'PUT',
|
||||
dataType: 'json',
|
||||
error_template_attribute_id: $('#add-attribute').find('select').val()
|
||||
}
|
||||
}).success(function () {
|
||||
location.reload();
|
||||
}).error(function (error) {
|
||||
$.flash.danger({text: error.statusText});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
9
app/assets/stylesheets/error_templates.scss
Normal file
9
app/assets/stylesheets/error_templates.scss
Normal file
@@ -0,0 +1,9 @@
|
||||
#add-attribute {
|
||||
display: flex;
|
||||
max-width: 400px;
|
||||
margin-top: 30px;
|
||||
|
||||
button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
@@ -9,6 +9,14 @@ module SubmissionScoring
|
||||
assessment = assessor.assess(output)
|
||||
passed = ((assessment[:passed] == assessment[:count]) and (assessment[:score] > 0))
|
||||
testrun_output = passed ? nil : 'message: ' + output[:message].to_s + "\n stdout: " + output[:stdout].to_s + "\n stderr: " + output[:stderr].to_s
|
||||
if !testrun_output.blank?
|
||||
submission.exercise.execution_environment.error_templates.each do |template|
|
||||
pattern = Regexp.new(template.signature).freeze
|
||||
if pattern.match(testrun_output)
|
||||
StructuredError.create_from_template(template, testrun_output)
|
||||
end
|
||||
end
|
||||
end
|
||||
Testrun.new(submission: submission, cause: 'assess', file: file, passed: passed, output: testrun_output).save
|
||||
output.merge!(assessment)
|
||||
output.merge!(filename: file.name_with_extension, message: feedback_message(file, output[:score]), weight: file.weight)
|
||||
|
86
app/controllers/error_template_attributes_controller.rb
Normal file
86
app/controllers/error_template_attributes_controller.rb
Normal file
@@ -0,0 +1,86 @@
|
||||
class ErrorTemplateAttributesController < ApplicationController
|
||||
before_action :set_error_template_attribute, only: [:show, :edit, :update, :destroy]
|
||||
|
||||
def authorize!
|
||||
authorize(@error_template_attributes || @error_template_attribute)
|
||||
end
|
||||
private :authorize!
|
||||
|
||||
# GET /error_template_attributes
|
||||
# GET /error_template_attributes.json
|
||||
def index
|
||||
@error_template_attributes = ErrorTemplateAttribute.all.order('important DESC', :key, :id).paginate(page: params[:page])
|
||||
authorize!
|
||||
end
|
||||
|
||||
# GET /error_template_attributes/1
|
||||
# GET /error_template_attributes/1.json
|
||||
def show
|
||||
authorize!
|
||||
end
|
||||
|
||||
# GET /error_template_attributes/new
|
||||
def new
|
||||
@error_template_attribute = ErrorTemplateAttribute.new
|
||||
authorize!
|
||||
end
|
||||
|
||||
# GET /error_template_attributes/1/edit
|
||||
def edit
|
||||
authorize!
|
||||
end
|
||||
|
||||
# POST /error_template_attributes
|
||||
# POST /error_template_attributes.json
|
||||
def create
|
||||
@error_template_attribute = ErrorTemplateAttribute.new(error_template_attribute_params)
|
||||
authorize!
|
||||
|
||||
respond_to do |format|
|
||||
if @error_template_attribute.save
|
||||
format.html { redirect_to @error_template_attribute, notice: 'Error template attribute was successfully created.' }
|
||||
format.json { render :show, status: :created, location: @error_template_attribute }
|
||||
else
|
||||
format.html { render :new }
|
||||
format.json { render json: @error_template_attribute.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# PATCH/PUT /error_template_attributes/1
|
||||
# PATCH/PUT /error_template_attributes/1.json
|
||||
def update
|
||||
authorize!
|
||||
respond_to do |format|
|
||||
if @error_template_attribute.update(error_template_attribute_params)
|
||||
format.html { redirect_to @error_template_attribute, notice: 'Error template attribute was successfully updated.' }
|
||||
format.json { render :show, status: :ok, location: @error_template_attribute }
|
||||
else
|
||||
format.html { render :edit }
|
||||
format.json { render json: @error_template_attribute.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# DELETE /error_template_attributes/1
|
||||
# DELETE /error_template_attributes/1.json
|
||||
def destroy
|
||||
authorize!
|
||||
@error_template_attribute.destroy
|
||||
respond_to do |format|
|
||||
format.html { redirect_to error_template_attributes_url, notice: 'Error template attribute was successfully destroyed.' }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_error_template_attribute
|
||||
@error_template_attribute = ErrorTemplateAttribute.find(params[:id])
|
||||
end
|
||||
|
||||
# Never trust parameters from the scary internet, only allow the white list through.
|
||||
def error_template_attribute_params
|
||||
params[:error_template_attribute].permit(:key, :description, :regex, :important)
|
||||
end
|
||||
end
|
104
app/controllers/error_templates_controller.rb
Normal file
104
app/controllers/error_templates_controller.rb
Normal file
@@ -0,0 +1,104 @@
|
||||
class ErrorTemplatesController < ApplicationController
|
||||
before_action :set_error_template, only: [:show, :edit, :update, :destroy, :add_attribute, :remove_attribute]
|
||||
|
||||
def authorize!
|
||||
authorize(@error_templates || @error_template)
|
||||
end
|
||||
private :authorize!
|
||||
|
||||
# GET /error_templates
|
||||
# GET /error_templates.json
|
||||
def index
|
||||
@error_templates = ErrorTemplate.all.order(:execution_environment_id, :name).paginate(page: params[:page])
|
||||
authorize!
|
||||
end
|
||||
|
||||
# GET /error_templates/1
|
||||
# GET /error_templates/1.json
|
||||
def show
|
||||
authorize!
|
||||
end
|
||||
|
||||
# GET /error_templates/new
|
||||
def new
|
||||
@error_template = ErrorTemplate.new
|
||||
authorize!
|
||||
end
|
||||
|
||||
# GET /error_templates/1/edit
|
||||
def edit
|
||||
authorize!
|
||||
end
|
||||
|
||||
# POST /error_templates
|
||||
# POST /error_templates.json
|
||||
def create
|
||||
@error_template = ErrorTemplate.new(error_template_params)
|
||||
authorize!
|
||||
|
||||
respond_to do |format|
|
||||
if @error_template.save
|
||||
format.html { redirect_to @error_template, notice: 'Error template was successfully created.' }
|
||||
format.json { render :show, status: :created, location: @error_template }
|
||||
else
|
||||
format.html { render :new }
|
||||
format.json { render json: @error_template.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# PATCH/PUT /error_templates/1
|
||||
# PATCH/PUT /error_templates/1.json
|
||||
def update
|
||||
authorize!
|
||||
respond_to do |format|
|
||||
if @error_template.update(error_template_params)
|
||||
format.html { redirect_to @error_template, notice: 'Error template was successfully updated.' }
|
||||
format.json { render :show, status: :ok, location: @error_template }
|
||||
else
|
||||
format.html { render :edit }
|
||||
format.json { render json: @error_template.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# DELETE /error_templates/1
|
||||
# DELETE /error_templates/1.json
|
||||
def destroy
|
||||
authorize!
|
||||
@error_template.destroy
|
||||
respond_to do |format|
|
||||
format.html { redirect_to error_templates_url, notice: 'Error template was successfully destroyed.' }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
end
|
||||
|
||||
def add_attribute
|
||||
authorize!
|
||||
@error_template.error_template_attributes << ErrorTemplateAttribute.find(params['error_template_attribute_id'])
|
||||
respond_to do |format|
|
||||
format.html { redirect_to @error_template }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
end
|
||||
|
||||
def remove_attribute
|
||||
authorize!
|
||||
@error_template.error_template_attributes.delete(ErrorTemplateAttribute.find(params['error_template_attribute_id']))
|
||||
respond_to do |format|
|
||||
format.html { redirect_to @error_template }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_error_template
|
||||
@error_template = ErrorTemplate.find(params[:id])
|
||||
end
|
||||
|
||||
# Never trust parameters from the scary internet, only allow the white list through.
|
||||
def error_template_params
|
||||
params[:error_template].permit(:name, :execution_environment_id, :signature, :description, :hint)
|
||||
end
|
||||
end
|
@@ -6,7 +6,7 @@ class SubmissionsController < ApplicationController
|
||||
include SubmissionScoring
|
||||
include Tubesock::Hijack
|
||||
|
||||
before_action :set_submission, only: [:download, :download_file, :render_file, :run, :score, :show, :statistics, :stop, :test]
|
||||
before_action :set_submission, only: [:download, :download_file, :render_file, :run, :score, :extract_errors, :show, :statistics, :stop, :test]
|
||||
before_action :set_docker_client, only: [:run, :test]
|
||||
before_action :set_files, only: [:download, :download_file, :render_file, :show]
|
||||
before_action :set_file, only: [:download_file, :render_file]
|
||||
@@ -191,6 +191,9 @@ class SubmissionsController < ApplicationController
|
||||
end
|
||||
|
||||
def kill_socket(tubesock)
|
||||
# search for errors and save them as StructuredError (for scoring runs see submission_scoring.rb)
|
||||
extract_errors
|
||||
|
||||
# save the output of this "run" as a "testrun" (scoring runs are saved in submission_scoring.rb)
|
||||
save_run_output
|
||||
|
||||
@@ -199,6 +202,17 @@ class SubmissionsController < ApplicationController
|
||||
tubesock.close
|
||||
end
|
||||
|
||||
def extract_errors
|
||||
if !@message_buffer.blank?
|
||||
@submission.exercise.execution_environment.error_templates.each do |template|
|
||||
pattern = Regexp.new(template.signature).freeze
|
||||
if pattern.match(@message_buffer)
|
||||
StructuredError.create_from_template(template, @message_buffer)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def handle_message(message, tubesock, container)
|
||||
@run_output ||= ""
|
||||
# Handle special commands first
|
||||
|
2
app/helpers/error_template_attributes_helper.rb
Normal file
2
app/helpers/error_template_attributes_helper.rb
Normal file
@@ -0,0 +1,2 @@
|
||||
module ErrorTemplateAttributesHelper
|
||||
end
|
2
app/helpers/error_templates_helper.rb
Normal file
2
app/helpers/error_templates_helper.rb
Normal file
@@ -0,0 +1,2 @@
|
||||
module ErrorTemplatesHelper
|
||||
end
|
8
app/models/error_template.rb
Normal file
8
app/models/error_template.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
class ErrorTemplate < ActiveRecord::Base
|
||||
belongs_to :execution_environment
|
||||
has_and_belongs_to_many :error_template_attributes
|
||||
|
||||
def to_s
|
||||
"#{id} [#{name}]"
|
||||
end
|
||||
end
|
7
app/models/error_template_attribute.rb
Normal file
7
app/models/error_template_attribute.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
class ErrorTemplateAttribute < ActiveRecord::Base
|
||||
has_and_belongs_to_many :error_template
|
||||
|
||||
def to_s
|
||||
"#{id} [#{key}]"
|
||||
end
|
||||
end
|
@@ -11,6 +11,7 @@ class ExecutionEnvironment < ActiveRecord::Base
|
||||
has_many :exercises
|
||||
belongs_to :file_type
|
||||
has_many :hints
|
||||
has_many :error_templates
|
||||
|
||||
scope :with_exercises, -> { where('id IN (SELECT execution_environment_id FROM exercises)') }
|
||||
|
||||
|
@@ -36,8 +36,8 @@ class ProxyExercise < ActiveRecord::Base
|
||||
Rails.logger.debug("retrieved assigned exercise for user #{user.id}: Exercise #{assigned_user_proxy_exercise.exercise}" )
|
||||
assigned_user_proxy_exercise.exercise
|
||||
else
|
||||
Rails.logger.debug("find new matching exercise for user #{user.id}" )
|
||||
matching_exercise =
|
||||
Rails.logger.debug("find new matching exercise for user #{user.id}" )
|
||||
begin
|
||||
find_matching_exercise(user)
|
||||
rescue => e #fallback
|
||||
@@ -72,7 +72,7 @@ class ProxyExercise < ActiveRecord::Base
|
||||
|
||||
# find exercises
|
||||
potential_recommended_exercises = []
|
||||
exercises.where("expected_difficulty > 1").each do |ex|
|
||||
exercises.where("expected_difficulty >= 1").each do |ex|
|
||||
## find exercises which have only tags the user has already seen
|
||||
if (ex.tags - tags_user_has_seen).empty?
|
||||
potential_recommended_exercises << ex
|
||||
@@ -85,8 +85,7 @@ class ProxyExercise < ActiveRecord::Base
|
||||
@reason[:reason] = "easiest exercise in pool. empty potential exercises"
|
||||
select_easiest_exercise(exercises)
|
||||
else
|
||||
recommended_exercise = select_best_matching_exercise(user, exercises_user_has_accessed, potential_recommended_exercises)
|
||||
recommended_exercise
|
||||
select_best_matching_exercise(user, exercises_user_has_accessed, potential_recommended_exercises)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -238,4 +237,4 @@ class ProxyExercise < ActiveRecord::Base
|
||||
exercises.order(:expected_difficulty).first
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
12
app/models/structured_error.rb
Normal file
12
app/models/structured_error.rb
Normal file
@@ -0,0 +1,12 @@
|
||||
class StructuredError < ActiveRecord::Base
|
||||
belongs_to :error_template
|
||||
belongs_to :file, class_name: 'CodeOcean::File'
|
||||
|
||||
def self.create_from_template(template, message_buffer)
|
||||
instance = self.create(error_template: template)
|
||||
template.error_template_attributes.each do |attribute|
|
||||
StructuredErrorAttribute.create_from_template(attribute, instance, message_buffer)
|
||||
end
|
||||
instance
|
||||
end
|
||||
end
|
17
app/models/structured_error_attribute.rb
Normal file
17
app/models/structured_error_attribute.rb
Normal file
@@ -0,0 +1,17 @@
|
||||
class StructuredErrorAttribute < ActiveRecord::Base
|
||||
belongs_to :structured_error
|
||||
belongs_to :error_template_attribute
|
||||
|
||||
def self.create_from_template(attribute, structured_error, message_buffer)
|
||||
match = false
|
||||
value = nil
|
||||
result = message_buffer.match(attribute.regex)
|
||||
if result != nil
|
||||
match = true
|
||||
if result.captures.size > 0
|
||||
value = result.captures[0]
|
||||
end
|
||||
end
|
||||
self.create(structured_error: structured_error, error_template_attribute: attribute, value: value, match: match)
|
||||
end
|
||||
end
|
3
app/policies/error_template_attribute_policy.rb
Normal file
3
app/policies/error_template_attribute_policy.rb
Normal file
@@ -0,0 +1,3 @@
|
||||
class ErrorTemplateAttributePolicy < AdminOnlyPolicy
|
||||
|
||||
end
|
9
app/policies/error_template_policy.rb
Normal file
9
app/policies/error_template_policy.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
class ErrorTemplatePolicy < AdminOnlyPolicy
|
||||
def add_attribute?
|
||||
admin?
|
||||
end
|
||||
|
||||
def remove_attribute?
|
||||
admin?
|
||||
end
|
||||
end
|
@@ -8,7 +8,8 @@
|
||||
- if current_user.admin?
|
||||
li = link_to(t('breadcrumbs.dashboard.show'), admin_dashboard_path)
|
||||
li.divider
|
||||
- models = [ExecutionEnvironment, Exercise, ExerciseCollection, ProxyExercise, Tag, Consumer, CodeHarborLink, ExternalUser, FileType, FileTemplate, InternalUser, UserExerciseFeedback].sort_by { |model| model.model_name.human(count: 2) }
|
||||
- models = [ExecutionEnvironment, Exercise, ExerciseCollection, ProxyExercise, Tag, Consumer, CodeHarborLink, UserExerciseFeedback,
|
||||
ErrorTemplate, ErrorTemplateAttribute, ExternalUser, FileType, FileTemplate, InternalUser].sort_by {|model| model.model_name.human(count: 2) }
|
||||
- models.each do |model|
|
||||
- if policy(model).index?
|
||||
li = link_to(model.model_name.human(count: 2), send(:"#{model.model_name.collection}_path"))
|
||||
|
16
app/views/error_template_attributes/_form.html.slim
Normal file
16
app/views/error_template_attributes/_form.html.slim
Normal file
@@ -0,0 +1,16 @@
|
||||
= form_for(@error_template_attribute) do |f|
|
||||
= render('shared/form_errors', object: @error_template_attribute)
|
||||
.form-group
|
||||
= f.label(:key)
|
||||
= f.text_field(:key, class: 'form-control', required: true)
|
||||
.form-group
|
||||
= f.label(:description)
|
||||
= f.text_field(:description, class: 'form-control')
|
||||
.form-group
|
||||
= f.label(:regex)
|
||||
= f.text_field(:regex, class: 'form-control', required: true)
|
||||
.help-block == t('error_templates.hints.signature')
|
||||
.form-group
|
||||
= f.check_box(:important)
|
||||
= t('activerecord.attributes.error_template_attribute.important')
|
||||
.actions = render('shared/submit_button', f: f, object: @error_template_attribute)
|
3
app/views/error_template_attributes/edit.html.slim
Normal file
3
app/views/error_template_attributes/edit.html.slim
Normal file
@@ -0,0 +1,3 @@
|
||||
h1 = @error_template_attribute
|
||||
|
||||
= render('form')
|
28
app/views/error_template_attributes/index.html.slim
Normal file
28
app/views/error_template_attributes/index.html.slim
Normal file
@@ -0,0 +1,28 @@
|
||||
h1 = ErrorTemplateAttribute.model_name.human(count: 2)
|
||||
|
||||
.table-responsive
|
||||
table.sortable.table
|
||||
thead
|
||||
tr
|
||||
th
|
||||
th = t('activerecord.attributes.error_template_attribute.key')
|
||||
th = t('activerecord.attributes.error_template_attribute.description')
|
||||
th = t('activerecord.attributes.error_template_attribute.regex')
|
||||
th colspan=5 = t('shared.actions')
|
||||
tbody
|
||||
- @error_template_attributes.each do |error_template_attribute|
|
||||
tr
|
||||
td
|
||||
- if error_template_attribute.important
|
||||
span class="fa fa-star" aria-hidden="true"
|
||||
- else
|
||||
span class="fa fa-star-o" aria-hidden="true"
|
||||
td = error_template_attribute.key
|
||||
td = error_template_attribute.description
|
||||
td = error_template_attribute.regex
|
||||
td = link_to(t('shared.show'), error_template_attribute)
|
||||
td = link_to(t('shared.edit'), edit_error_template_attribute_path(error_template_attribute))
|
||||
td = link_to(t('shared.destroy'), error_template_attribute, data: {confirm: t('shared.confirm_destroy')}, method: :delete)
|
||||
|
||||
= render('shared/pagination', collection: @error_template_attributes)
|
||||
p = render('shared/new_button', model: ErrorTemplateAttribute)
|
3
app/views/error_template_attributes/new.html.slim
Normal file
3
app/views/error_template_attributes/new.html.slim
Normal file
@@ -0,0 +1,3 @@
|
||||
h1 = t('shared.new_model', model: ErrorTemplateAttribute.model_name.human)
|
||||
|
||||
= render('form')
|
8
app/views/error_template_attributes/show.html.slim
Normal file
8
app/views/error_template_attributes/show.html.slim
Normal file
@@ -0,0 +1,8 @@
|
||||
h1
|
||||
= @error_template_attribute
|
||||
= render('shared/edit_button', object: @error_template_attribute)
|
||||
|
||||
- [:key, :description, :regex, :important].each do |attribute|
|
||||
= row(label: "error_template_attribute.#{attribute}", value: @error_template_attribute.send(attribute))
|
||||
|
||||
// todo: used by
|
19
app/views/error_templates/_form.html.slim
Normal file
19
app/views/error_templates/_form.html.slim
Normal file
@@ -0,0 +1,19 @@
|
||||
= form_for(@error_template) do |f|
|
||||
= render('shared/form_errors', object: @error_template)
|
||||
.form-group
|
||||
= f.label(:name)
|
||||
= f.text_field(:name, class: 'form-control', required: true)
|
||||
.form-group
|
||||
= f.label(:execution_environment_id)
|
||||
= f.collection_select(:execution_environment_id, ExecutionEnvironment.all.order(:name), :id, :name, {include_blank: false}, class: 'form-control')
|
||||
.form-group
|
||||
= f.label(:signature)
|
||||
= f.text_field(:signature, class: 'form-control')
|
||||
.help-block == t('error_templates.hints.signature')
|
||||
.form-group
|
||||
= f.label(:description)
|
||||
= f.text_field(:description, class: 'form-control')
|
||||
.form-group
|
||||
= f.label(:hint)
|
||||
= f.text_field(:hint, class: 'form-control')
|
||||
.actions = render('shared/submit_button', f: f, object: @error_template)
|
3
app/views/error_templates/edit.html.slim
Normal file
3
app/views/error_templates/edit.html.slim
Normal file
@@ -0,0 +1,3 @@
|
||||
h1 = @error_template
|
||||
|
||||
= render('form')
|
22
app/views/error_templates/index.html.slim
Normal file
22
app/views/error_templates/index.html.slim
Normal file
@@ -0,0 +1,22 @@
|
||||
h1 = ErrorTemplate.model_name.human(count: 2)
|
||||
|
||||
.table-responsive
|
||||
table.sortable.table
|
||||
thead
|
||||
tr
|
||||
th = t('activerecord.attributes.error_template.name')
|
||||
th = t('activerecord.attributes.error_template.description')
|
||||
th = t('activerecord.attributes.exercise.execution_environment')
|
||||
th colspan=3 = t('shared.actions')
|
||||
tbody
|
||||
- @error_templates.each do |error_template|
|
||||
tr
|
||||
td = error_template.name
|
||||
td = error_template.description
|
||||
td = link_to(error_template.execution_environment)
|
||||
td = link_to(t('shared.show'), error_template)
|
||||
td = link_to(t('shared.edit'), edit_error_template_path(error_template))
|
||||
td = link_to(t('shared.destroy'), error_template, data: {confirm: t('shared.confirm_destroy')}, method: :delete)
|
||||
|
||||
= render('shared/pagination', collection: @error_templates)
|
||||
p = render('shared/new_button', model: ErrorTemplate)
|
3
app/views/error_templates/new.html.slim
Normal file
3
app/views/error_templates/new.html.slim
Normal file
@@ -0,0 +1,3 @@
|
||||
h1 = t('shared.new_model', model: ErrorTemplate.model_name.human)
|
||||
|
||||
= render('form')
|
40
app/views/error_templates/show.html.slim
Normal file
40
app/views/error_templates/show.html.slim
Normal file
@@ -0,0 +1,40 @@
|
||||
h1
|
||||
= @error_template
|
||||
= render('shared/edit_button', object: @error_template)
|
||||
|
||||
= row(label: 'error_template.name', value: @error_template.name)
|
||||
= row(label: 'exercise.execution_environment', value: link_to(@error_template.execution_environment))
|
||||
- [:signature, :description, :hint].each do |attribute|
|
||||
= row(label: "error_template.#{attribute}", value: @error_template.send(attribute))
|
||||
|
||||
h3
|
||||
= t 'error_templates.attributes'
|
||||
|
||||
.table-responsive
|
||||
table.sortable.table
|
||||
thead
|
||||
tr
|
||||
th
|
||||
th = t('activerecord.attributes.error_template_attribute.key')
|
||||
th = t('activerecord.attributes.error_template_attribute.description')
|
||||
th = t('activerecord.attributes.error_template_attribute.regex')
|
||||
th colspan=3 = t('shared.actions')
|
||||
tbody
|
||||
- @error_template.error_template_attributes.order('important DESC', :key).each do |attribute|
|
||||
tr
|
||||
td
|
||||
- if attribute.important
|
||||
span class="fa fa-star" aria-hidden="true"
|
||||
- else
|
||||
span class="fa fa-star-o" aria-hidden="true"
|
||||
td = attribute.key
|
||||
td = attribute.description
|
||||
td = attribute.regex
|
||||
td = link_to(t('shared.show'), attribute)
|
||||
td = link_to(t('shared.destroy'), attribute_error_template_url(:error_template_attribute_id => attribute.id), :method => :delete)
|
||||
|
||||
#add-attribute
|
||||
= collection_select({}, :error_template_attribute_id,
|
||||
ErrorTemplateAttribute.where.not(id: @error_template.error_template_attributes.select(:id).to_a).order('important DESC', :key),
|
||||
:id, :key, {include_blank: false}, class: '')
|
||||
button.btn.btn-default = t('error_templates.add_attribute')
|
@@ -3,7 +3,7 @@
|
||||
- consumer_id = @current_user.respond_to?(:external_id) ? @current_user.consumer_id : '' #'tests' #(@current_user.uuid.present? ? @current_user.uuid : '')
|
||||
- show_break_interventions = @show_break_interventions || "false"
|
||||
- show_rfc_interventions = @show_rfc_interventions || "false"
|
||||
#editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id data-user-external-id=external_user_external_id data-working-times-url=working_times_exercise_path data-intervention-save-url=intervention_exercise_path data-rfc-interventions=show_rfc_interventions data-break-interventions=show_break_interventions data-course_token=@course_token data-search-save-url=search_exercise_path
|
||||
#editor.row data-exercise-id=@exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id data-user-external-id=external_user_external_id data-working-times-url=working_times_exercise_path(@exercise) data-intervention-save-url=intervention_exercise_path(@exercise) data-rfc-interventions=show_rfc_interventions data-break-interventions=show_break_interventions data-course_token=@course_token data-search-save-url=search_exercise_path(@exercise)
|
||||
div id="sidebar" class=(@exercise.hide_file_tree ? 'sidebar-col-collapsed' : 'sidebar-col') = render('editor_file_tree', exercise: @exercise, files: @files)
|
||||
div id='output_sidebar' class='output-col-collapsed' = render('exercises/editor_output', external_user_id: external_user_id, consumer_id: consumer_id )
|
||||
div id='frames' class='editor-col'
|
||||
@@ -24,4 +24,4 @@
|
||||
|
||||
|
||||
= render('shared/modal', id: 'comment-modal', title: t('exercises.implement.comment.request'), template: 'exercises/_request_comment_dialogcontent')
|
||||
= render('shared/modal', id: 'break-intervention-modal', title: t('exercises.implement.break_intervention.title'), template: 'interventions/_break_intervention_modal')
|
||||
= render('shared/modal', id: 'break-intervention-modal', title: t('exercises.implement.break_intervention.title'), template: 'interventions/_break_intervention_modal')
|
||||
|
@@ -39,4 +39,8 @@ Rails.application.configure do
|
||||
|
||||
# Raises error for missing translations
|
||||
# config.action_view.raise_on_missing_translations = true
|
||||
|
||||
#config.logger = Logger.new(STDOUT)
|
||||
# Set log level
|
||||
#config.log_level = :DEBUG
|
||||
end
|
||||
|
@@ -111,6 +111,16 @@ de:
|
||||
name: "Name"
|
||||
file_type: "Dateityp"
|
||||
content: "Code"
|
||||
error_template:
|
||||
name: Name
|
||||
signature: Regulärer Ausdruck
|
||||
description: Beschreibung
|
||||
hint: Hinweis
|
||||
error_template_attribute:
|
||||
important: "Wichtig"
|
||||
key: "Name"
|
||||
description: "Beschreibung"
|
||||
regex: "Regulärer Ausdruck"
|
||||
exercise_collections:
|
||||
id: "ID"
|
||||
name: "Name"
|
||||
@@ -130,6 +140,12 @@ de:
|
||||
error:
|
||||
one: Fehler
|
||||
other: Fehler
|
||||
error_template:
|
||||
one: Fehlertemplate
|
||||
other: Fehlertemplates
|
||||
error_template_attribute:
|
||||
one: Fehlertemplatettribut
|
||||
other: Fehlertemplatettribute
|
||||
execution_environment:
|
||||
one: Ausführungsumgebung
|
||||
other: Ausführungsumgebungen
|
||||
@@ -646,10 +662,14 @@ de:
|
||||
estimated_time_20_to_30: "zwischen 20 und 30 Minuten"
|
||||
estimated_time_more_30: "mehr als 30 Minuten"
|
||||
working_time: "Geschätze Bearbeitungszeit für diese Aufgabe:"
|
||||
error_templates:
|
||||
hints:
|
||||
signature: "Ein regulärer Ausdruck in Ruby-Syntax und ohne führende und schließende \"/\""
|
||||
attributes: "Attribute"
|
||||
add_attribute: "Attribut hinzufügen"
|
||||
comments:
|
||||
deleted: "Gelöscht"
|
||||
save_update: "Speichern"
|
||||
subscriptions:
|
||||
successfully_unsubscribed: "Ihr Abonnement für weitere Kommentare auf dieser Kommentaranfrage wurde erfolgreich beendet."
|
||||
subscription_not_existent: "Das Abonnement, von dem Sie sich abmelden wollen, existiert nicht."
|
||||
|
||||
|
@@ -111,6 +111,16 @@ en:
|
||||
name: "Name"
|
||||
file_type: "File Type"
|
||||
content: "Content"
|
||||
error_template:
|
||||
name: Name
|
||||
signature: Signature Regular Expression
|
||||
description: Description
|
||||
hint: Hint
|
||||
error_template_attribute:
|
||||
important: "Important"
|
||||
key: "Identifier"
|
||||
description: "Description"
|
||||
regex: "Regular Expression"
|
||||
exercise_collections:
|
||||
id: "ID"
|
||||
name: "Name"
|
||||
@@ -130,6 +140,12 @@ en:
|
||||
error:
|
||||
one: Error
|
||||
other: Errors
|
||||
error_template:
|
||||
one: Error Template
|
||||
other: Error Templates
|
||||
error_template_attribute:
|
||||
one: Error Template Attribute
|
||||
other: Error Template Attributes
|
||||
execution_environment:
|
||||
one: Execution Environment
|
||||
other: Execution Environments
|
||||
@@ -646,6 +662,11 @@ en:
|
||||
estimated_time_20_to_30: "between 20 and 30 minutes"
|
||||
estimated_time_more_30: "more than 30 minutes"
|
||||
working_time: "Estimated time working on this exercise:"
|
||||
error_templates:
|
||||
hints:
|
||||
signature: "A regular expression in Ruby syntax without leading and trailing \"/\""
|
||||
attributes: "Attributes"
|
||||
add_attribute: "Add attribute"
|
||||
comments:
|
||||
deleted: "Deleted"
|
||||
save_update: "Save"
|
||||
|
@@ -1,6 +1,13 @@
|
||||
FILENAME_REGEXP = /[\w\.]+/ unless Kernel.const_defined?(:FILENAME_REGEXP)
|
||||
|
||||
Rails.application.routes.draw do
|
||||
resources :error_template_attributes
|
||||
resources :error_templates do
|
||||
member do
|
||||
put 'attribute', to: 'error_templates#add_attribute'
|
||||
delete 'attribute', to: 'error_templates#remove_attribute'
|
||||
end
|
||||
end
|
||||
resources :file_templates do
|
||||
collection do
|
||||
get 'by_file_type/:file_type_id', as: :by_file_type, action: :by_file_type
|
||||
|
11
db/migrate/20170703075832_create_error_templates.rb
Normal file
11
db/migrate/20170703075832_create_error_templates.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
class CreateErrorTemplates < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :error_templates do |t|
|
||||
t.belongs_to :execution_environment
|
||||
t.string :name
|
||||
t.string :signature
|
||||
|
||||
t.timestamps null: false
|
||||
end
|
||||
end
|
||||
end
|
@@ -0,0 +1,11 @@
|
||||
class CreateErrorTemplateAttributes < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :error_template_attributes do |t|
|
||||
t.belongs_to :error_template
|
||||
t.string :key
|
||||
t.string :regex
|
||||
|
||||
t.timestamps null: false
|
||||
end
|
||||
end
|
||||
end
|
10
db/migrate/20170703080205_create_structured_errors.rb
Normal file
10
db/migrate/20170703080205_create_structured_errors.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
class CreateStructuredErrors < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :structured_errors do |t|
|
||||
t.references :error_template
|
||||
t.belongs_to :file
|
||||
|
||||
t.timestamps null: false
|
||||
end
|
||||
end
|
||||
end
|
@@ -0,0 +1,11 @@
|
||||
class CreateStructuredErrorAttributes < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :structured_error_attributes do |t|
|
||||
t.belongs_to :structured_error
|
||||
t.references :error_template_attribute
|
||||
t.string :value
|
||||
|
||||
t.timestamps null: false
|
||||
end
|
||||
end
|
||||
end
|
@@ -0,0 +1,9 @@
|
||||
class AddDescriptionAndHintToErrorTemplate < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :error_templates, :description, :text
|
||||
add_column :error_templates, :hint, :text
|
||||
|
||||
add_column :error_template_attributes, :description, :text
|
||||
add_column :error_template_attributes, :important, :boolean
|
||||
end
|
||||
end
|
@@ -0,0 +1,6 @@
|
||||
class ChangeErrorTemplateAttributeRelationshipToNToM < ActiveRecord::Migration
|
||||
def change
|
||||
remove_belongs_to :error_template_attributes, :error_template
|
||||
create_join_table :error_templates, :error_template_attributes
|
||||
end
|
||||
end
|
@@ -0,0 +1,5 @@
|
||||
class AddMatchToStructuredErrorAttribute < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :structured_error_attributes, :match, :boolean
|
||||
end
|
||||
end
|
40
db/schema.rb
40
db/schema.rb
@@ -47,6 +47,30 @@ ActiveRecord::Schema.define(version: 20170920145852) do
|
||||
t.string "oauth_secret", limit: 255
|
||||
end
|
||||
|
||||
create_table "error_template_attributes", force: :cascade do |t|
|
||||
t.string "key"
|
||||
t.string "regex"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.text "description"
|
||||
t.boolean "important"
|
||||
end
|
||||
|
||||
create_table "error_template_attributes_templates", id: false, force: :cascade do |t|
|
||||
t.integer "error_template_id", null: false
|
||||
t.integer "error_template_attribute_id", null: false
|
||||
end
|
||||
|
||||
create_table "error_templates", force: :cascade do |t|
|
||||
t.integer "execution_environment_id"
|
||||
t.string "name"
|
||||
t.string "signature"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.text "description"
|
||||
t.text "hint"
|
||||
end
|
||||
|
||||
create_table "errors", force: :cascade do |t|
|
||||
t.integer "execution_environment_id"
|
||||
t.text "message"
|
||||
@@ -268,6 +292,22 @@ ActiveRecord::Schema.define(version: 20170920145852) do
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
create_table "structured_error_attributes", force: :cascade do |t|
|
||||
t.integer "structured_error_id"
|
||||
t.integer "error_template_attribute_id"
|
||||
t.string "value"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.boolean "match"
|
||||
end
|
||||
|
||||
create_table "structured_errors", force: :cascade do |t|
|
||||
t.integer "error_template_id"
|
||||
t.integer "file_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "submissions", force: :cascade do |t|
|
||||
t.integer "exercise_id"
|
||||
t.float "score"
|
||||
|
@@ -25,31 +25,23 @@ describe Lti do
|
||||
|
||||
describe '#external_user_name' do
|
||||
let(:first_name) { 'Jane' }
|
||||
let(:full_name) { 'John Doe' }
|
||||
let(:last_name) { 'Doe' }
|
||||
let(:full_name) { 'John Doe' }
|
||||
let(:provider) { double }
|
||||
let(:provider_full) { double(:lis_person_name_full => full_name) }
|
||||
|
||||
context 'when a full name is provided' do
|
||||
it 'returns the full name' do
|
||||
expect(provider).to receive(:lis_person_name_full).twice.and_return(full_name)
|
||||
expect(controller.send(:external_user_name, provider)).to eq(full_name)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when first and last name are provided' do
|
||||
it 'returns the concatenated names' do
|
||||
expect(provider).to receive(:lis_person_name_full)
|
||||
expect(provider).to receive(:lis_person_name_given).twice.and_return(first_name)
|
||||
expect(provider).to receive(:lis_person_name_family).twice.and_return(last_name)
|
||||
expect(controller.send(:external_user_name, provider)).to eq("#{first_name} #{last_name}")
|
||||
expect(provider_full).to receive(:lis_person_name_full).twice.and_return(full_name)
|
||||
expect(controller.send(:external_user_name, provider_full)).to eq(full_name)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when only partial information is provided' do
|
||||
it 'returns the first available name' do
|
||||
expect(provider).to receive(:lis_person_name_full)
|
||||
expect(provider).to receive(:lis_person_name_given).twice.and_return(first_name)
|
||||
expect(provider).to receive(:lis_person_name_family)
|
||||
expect(provider).to receive(:lis_person_name_given).and_return(first_name)
|
||||
expect(provider).not_to receive(:lis_person_name_family)
|
||||
expect(controller.send(:external_user_name, provider)).to eq(first_name)
|
||||
end
|
||||
end
|
||||
@@ -122,6 +114,7 @@ describe Lti do
|
||||
|
||||
context 'when grading is not supported' do
|
||||
it 'returns a corresponding status' do
|
||||
skip('ralf: this does not work, since send_score pulls data from the database, which then returns an empty array. On this is called .first, which returns nil and lets the test fail. Before Toms changes, this was taken from the session, which could be mocked')
|
||||
expect_any_instance_of(IMS::LTI::ToolProvider).to receive(:outcome_service?).and_return(false)
|
||||
expect(controller.send(:send_score, submission.exercise_id, score, submission.user_id)[:status]).to eq('unsupported')
|
||||
end
|
||||
@@ -140,10 +133,12 @@ describe Lti do
|
||||
end
|
||||
|
||||
it 'sends the score' do
|
||||
skip('ralf: this does not work, since send_score pulls data from the database, which then returns an empty array. On this is called .first, which returns nil and lets the test fail. Before Toms changes, this was taken from the session, which could be mocked')
|
||||
controller.send(:send_score, submission.exercise_id, score, submission.user_id)
|
||||
end
|
||||
|
||||
it 'returns code, message, and status' do
|
||||
skip('ralf: this does not work, since send_score pulls data from the database, which then returns an empty array. On this is called .first, which returns nil and lets the test fail. Before Toms changes, this was taken from the session, which could be mocked')
|
||||
result = controller.send(:send_score, submission.exercise_id, score, submission.user_id)
|
||||
expect(result[:code]).to eq(response.response_code)
|
||||
expect(result[:message]).to eq(response.body)
|
||||
|
@@ -183,6 +183,41 @@ describe SubmissionsController do
|
||||
expect_template(:show)
|
||||
end
|
||||
|
||||
describe 'GET #show.json' do
|
||||
# Render views requested in controller tests in order to get json responses
|
||||
# https://github.com/rails/jbuilder/issues/32
|
||||
render_views
|
||||
|
||||
before(:each) { get :show, id: submission.id, format: :json }
|
||||
expect_assigns(submission: :submission)
|
||||
expect_status(200)
|
||||
|
||||
[:render, :run, :test].each do |action|
|
||||
describe "##{action}_url" do
|
||||
let(:url) { JSON.parse(response.body).with_indifferent_access.fetch("#{action}_url") }
|
||||
|
||||
it "starts like the #{action} path" do
|
||||
filename = File.basename(__FILE__)
|
||||
expect(url).to start_with(Rails.application.routes.url_helpers.send(:"#{action}_submission_path", submission, filename).sub(filename, ''))
|
||||
end
|
||||
|
||||
it 'ends with a placeholder' do
|
||||
expect(url).to end_with(Submission::FILENAME_URL_PLACEHOLDER)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
[:score, :stop].each do |action|
|
||||
describe "##{action}_url" do
|
||||
let(:url) { JSON.parse(response.body).with_indifferent_access.fetch("#{action}_url") }
|
||||
|
||||
it "corresponds to the #{action} path" do
|
||||
expect(url).to eq(Rails.application.routes.url_helpers.send(:"#{action}_submission_path", submission))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #score' do
|
||||
let(:request) { proc { get :score, id: submission.id } }
|
||||
before(:each) { request.call }
|
||||
|
@@ -16,21 +16,6 @@ describe Submission do
|
||||
expect(described_class.create.errors[:user_type]).to be_present
|
||||
end
|
||||
|
||||
[:render, :run, :test].each do |action|
|
||||
describe "##{action}_url" do
|
||||
let(:url) { submission.send(:"#{action}_url") }
|
||||
|
||||
it "starts like the #{action} path" do
|
||||
filename = File.basename(__FILE__)
|
||||
expect(url).to start_with(Rails.application.routes.url_helpers.send(:"#{action}_submission_path", submission, filename).sub(filename, ''))
|
||||
end
|
||||
|
||||
it 'ends with a placeholder' do
|
||||
expect(url).to end_with(Submission::FILENAME_URL_PLACEHOLDER)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#main_file' do
|
||||
let(:submission) { FactoryGirl.create(:submission) }
|
||||
|
||||
@@ -78,16 +63,6 @@ describe Submission do
|
||||
end
|
||||
end
|
||||
|
||||
[:score, :stop].each do |action|
|
||||
describe "##{action}_url" do
|
||||
let(:url) { submission.send(:"#{action}_url") }
|
||||
|
||||
it "corresponds to the #{action} path" do
|
||||
expect(url).to eq(Rails.application.routes.url_helpers.send(:"#{action}_submission_path", submission))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#siblings' do
|
||||
let(:siblings) { described_class.find_by(user: user).siblings }
|
||||
let(:user) { FactoryGirl.create(:external_user) }
|
||||
|
@@ -82,4 +82,7 @@ RSpec.configure do |config|
|
||||
# a real object. This is generally recommended.
|
||||
mocks.verify_partial_doubles = true
|
||||
end
|
||||
|
||||
# Save test results to persistence file to enable usage of --next-failure flag in local testing/debugging
|
||||
config.example_status_persistence_file_path = 'tmp/rspec_persistence_file.txt'
|
||||
end
|
||||
|
@@ -0,0 +1,49 @@
|
||||
require 'test_helper'
|
||||
|
||||
class ErrorTemplateAttributesControllerTest < ActionController::TestCase
|
||||
setup do
|
||||
@error_template_attribute = error_template_attributes(:one)
|
||||
end
|
||||
|
||||
test "should get index" do
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_not_nil assigns(:error_template_attributes)
|
||||
end
|
||||
|
||||
test "should get new" do
|
||||
get :new
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should create error_template_attribute" do
|
||||
assert_difference('ErrorTemplateAttribute.count') do
|
||||
post :create, error_template_attribute: { }
|
||||
end
|
||||
|
||||
assert_redirected_to error_template_attribute_path(assigns(:error_template_attribute))
|
||||
end
|
||||
|
||||
test "should show error_template_attribute" do
|
||||
get :show, id: @error_template_attribute
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should get edit" do
|
||||
get :edit, id: @error_template_attribute
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should update error_template_attribute" do
|
||||
patch :update, id: @error_template_attribute, error_template_attribute: { }
|
||||
assert_redirected_to error_template_attribute_path(assigns(:error_template_attribute))
|
||||
end
|
||||
|
||||
test "should destroy error_template_attribute" do
|
||||
assert_difference('ErrorTemplateAttribute.count', -1) do
|
||||
delete :destroy, id: @error_template_attribute
|
||||
end
|
||||
|
||||
assert_redirected_to error_template_attributes_path
|
||||
end
|
||||
end
|
49
test/controllers/error_templates_controller_test.rb
Normal file
49
test/controllers/error_templates_controller_test.rb
Normal file
@@ -0,0 +1,49 @@
|
||||
require 'test_helper'
|
||||
|
||||
class ErrorTemplatesControllerTest < ActionController::TestCase
|
||||
setup do
|
||||
@error_template = error_templates(:one)
|
||||
end
|
||||
|
||||
test "should get index" do
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_not_nil assigns(:error_templates)
|
||||
end
|
||||
|
||||
test "should get new" do
|
||||
get :new
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should create error_template" do
|
||||
assert_difference('ErrorTemplate.count') do
|
||||
post :create, error_template: { }
|
||||
end
|
||||
|
||||
assert_redirected_to error_template_path(assigns(:error_template))
|
||||
end
|
||||
|
||||
test "should show error_template" do
|
||||
get :show, id: @error_template
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should get edit" do
|
||||
get :edit, id: @error_template
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should update error_template" do
|
||||
patch :update, id: @error_template, error_template: { }
|
||||
assert_redirected_to error_template_path(assigns(:error_template))
|
||||
end
|
||||
|
||||
test "should destroy error_template" do
|
||||
assert_difference('ErrorTemplate.count', -1) do
|
||||
delete :destroy, id: @error_template
|
||||
end
|
||||
|
||||
assert_redirected_to error_templates_path
|
||||
end
|
||||
end
|
@@ -1,14 +0,0 @@
|
||||
require 'test_helper'
|
||||
|
||||
class ExerciseCollectionsControllerTest < ActionController::TestCase
|
||||
test "should get index" do
|
||||
get :index
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should get show" do
|
||||
get :show
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
end
|
7
test/factories/error_template_attributes.rb
Normal file
7
test/factories/error_template_attributes.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
FactoryGirl.define do
|
||||
factory :error_template_attribute do
|
||||
error_template nil
|
||||
key "MyString"
|
||||
regex "MyString"
|
||||
end
|
||||
end
|
7
test/factories/error_templates.rb
Normal file
7
test/factories/error_templates.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
FactoryGirl.define do
|
||||
factory :error_template do
|
||||
execution_environment nil
|
||||
name "MyString"
|
||||
signature "MyString"
|
||||
end
|
||||
end
|
7
test/factories/structured_error_attributes.rb
Normal file
7
test/factories/structured_error_attributes.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
FactoryGirl.define do
|
||||
factory :structured_error_attribute do
|
||||
structured_error nil
|
||||
error_template_attribute nil
|
||||
value "MyString"
|
||||
end
|
||||
end
|
6
test/factories/structured_errors.rb
Normal file
6
test/factories/structured_errors.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
FactoryGirl.define do
|
||||
factory :structured_error do
|
||||
error_template nil
|
||||
file nil
|
||||
end
|
||||
end
|
@@ -1,7 +0,0 @@
|
||||
FactoryGirl.define do
|
||||
factory :subscription do
|
||||
user nil
|
||||
request_for_comments nil
|
||||
type ""
|
||||
end
|
||||
end
|
@@ -1,6 +1,6 @@
|
||||
require 'test_helper'
|
||||
|
||||
class SubscriptionControllerTest < ActionController::TestCase
|
||||
class ErrorTemplateAttributeTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
@@ -1,6 +1,6 @@
|
||||
require 'test_helper'
|
||||
|
||||
class SubscriptionTest < ActiveSupport::TestCase
|
||||
class ErrorTemplateTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
7
test/models/structured_error_attribute_test.rb
Normal file
7
test/models/structured_error_attribute_test.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
require 'test_helper'
|
||||
|
||||
class StructuredErrorAttributeTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
7
test/models/structured_error_test.rb
Normal file
7
test/models/structured_error_test.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
require 'test_helper'
|
||||
|
||||
class StructuredErrorTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
Reference in New Issue
Block a user