live coder seeding - completes #16
This commit is contained in:
parent
393fd15ab5
commit
2b55fed1bc
@ -10,7 +10,9 @@ $(function(){
|
|||||||
$("#question_input_type").on('change', function(){
|
$("#question_input_type").on('change', function(){
|
||||||
var qid = $(this).attr('data-qid') === undefined ? '' : "/" + $(this).attr('data-qid');
|
var qid = $(this).attr('data-qid') === undefined ? '' : "/" + $(this).attr('data-qid');
|
||||||
// /admin/question(/:question_id)/options/:input_type
|
// /admin/question(/:question_id)/options/:input_type
|
||||||
$("[data-id=input-options-wrapper]").load("/admin/question" + qid + "/options/" + $(this).val());
|
$("[data-id=input-options-wrapper]").load("/admin/question" + qid + "/options/" + $(this).val(), function(){
|
||||||
|
$(".code-input textarea").linedtextarea();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -60,9 +60,9 @@ module Admin
|
|||||||
def process_question_params
|
def process_question_params
|
||||||
question = question_params
|
question = question_params
|
||||||
question[:input_options] = question_params[:multi_choice] unless question_params[:multi_choice].nil?
|
question[:input_options] = question_params[:multi_choice] unless question_params[:multi_choice].nil?
|
||||||
question[:input_options] = question_params[:live_coder] unless question_params[:live_coder].nil?
|
question[:input_options] = question_params[:live_code] unless question_params[:live_code].nil?
|
||||||
question.delete(:multi_choice)
|
question.delete(:multi_choice)
|
||||||
question.delete(:live_coder)
|
question.delete(:live_code)
|
||||||
question
|
question
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
class Question < ApplicationRecord
|
class Question < ApplicationRecord
|
||||||
serialize :input_options, Array
|
serialize :input_options
|
||||||
|
|
||||||
has_many :answers
|
has_many :answers
|
||||||
belongs_to :quiz
|
belongs_to :quiz
|
||||||
|
|
||||||
|
after_initialize :prepare_input_options
|
||||||
before_validation :compact_input_options
|
before_validation :compact_input_options
|
||||||
|
|
||||||
validates :quiz_id, presence: true
|
validates :quiz_id, presence: true
|
||||||
@ -15,6 +16,11 @@ class Question < ApplicationRecord
|
|||||||
private
|
private
|
||||||
|
|
||||||
def compact_input_options
|
def compact_input_options
|
||||||
self.input_options = input_options.reject(&:blank?)
|
self.input_options = input_options.reject { |_k, v| v.blank? } if input_options.class == Hash
|
||||||
|
self.input_options = input_options.reject(&:blank?) if input_options.class == Array
|
||||||
|
end
|
||||||
|
|
||||||
|
def prepare_input_options
|
||||||
|
self.input_options = input_options || {}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -31,7 +31,9 @@ class AnswerFormatValidator < ActiveModel::EachValidator
|
|||||||
end
|
end
|
||||||
|
|
||||||
def live_code record, attribute, value
|
def live_code record, attribute, value
|
||||||
return unless value.nil? || value.values.join.blank?
|
seed = (Question.find_by(id: record.question_id) || Question.new).input_options
|
||||||
|
|
||||||
|
return unless value.nil? || value.values.join.blank? || !match_seed?(value, seed)
|
||||||
|
|
||||||
record.errors[attribute] << (options[:message] || live_code_error_message(value))
|
record.errors[attribute] << (options[:message] || live_code_error_message(value))
|
||||||
end
|
end
|
||||||
@ -44,4 +46,16 @@ class AnswerFormatValidator < ActiveModel::EachValidator
|
|||||||
end
|
end
|
||||||
"You must write comments or code in one of the textareas to progress."
|
"You must write comments or code in one of the textareas to progress."
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def match_seed? value, seed
|
||||||
|
s_value = value.stringify_keys
|
||||||
|
s_seed = seed.stringify_keys
|
||||||
|
keys = s_value.merge(s_seed).keys.uniq
|
||||||
|
|
||||||
|
matches = keys.inject([]) do |memo, k|
|
||||||
|
memo << (s_value[k].to_s.strip == s_seed[k].to_s.strip)
|
||||||
|
end
|
||||||
|
|
||||||
|
matches.include? false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,29 +1,18 @@
|
|||||||
<%
|
|
||||||
|
|
||||||
return nil
|
|
||||||
|
|
||||||
# don't load this partial yet. Will finish in issue #16
|
|
||||||
# https://gitlab.perficientxd.com/pdr/skill-assessment-app/issues/16
|
|
||||||
options = { 'text' => '', 'html' => '', 'css' => '', 'js' => '' }
|
|
||||||
%>
|
|
||||||
|
|
||||||
|
|
||||||
<div data-id="live-coder-answer">
|
<div data-id="live-coder-answer">
|
||||||
<div class="code-input">
|
<div class="code-input">
|
||||||
<label for="question_input_options_html">HTML</label>
|
<label for="question_input_options_html">HTML</label>
|
||||||
<%= text_area_tag 'question[live_code][html]', options['html'], { data: {id: 'code-html', last: options['html']}, class: 'code-answer code-html' } %>
|
<%= text_area_tag 'question[live_code][html]', question.input_options['html'], { data: {id: 'code-html', last: question.input_options['html']}, class: 'code-answer code-html' } %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="code-input">
|
<div class="code-input">
|
||||||
<label for="question_input_options_css">CSS</label>
|
<label for="question_input_options_css">CSS</label>
|
||||||
<%= text_area_tag 'question[live_code][css]', options['css'], { data: {id: 'code-css', last: options['css']}, class: 'code-answer code-css' } %>
|
<%= text_area_tag 'question[live_code][css]', question.input_options['css'], { data: {id: 'code-css', last: question.input_options['css']}, class: 'code-answer code-css' } %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="code-input">
|
<div class="code-input">
|
||||||
<label for="question_input_options_js">JS</label>
|
<label for="question_input_options_js">JS</label>
|
||||||
<%= text_area_tag 'question[live_code][js]', options['js'], { data: {id: 'code-js', last: options['js']}, class: 'code-answer code-js' } %>
|
<%= text_area_tag 'question[live_code][js]', question.input_options['js'], { data: {id: 'code-js', last: question.input_options['js']}, class: 'code-answer code-js' } %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="results" data-id="results"></div>
|
<div class="results" data-id="results"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -5,7 +5,12 @@
|
|||||||
name: "answer[#{question.input_type}][later]",
|
name: "answer[#{question.input_type}][later]",
|
||||||
checked: Array(question.answer).include?('finish-later')
|
checked: Array(question.answer).include?('finish-later')
|
||||||
}
|
}
|
||||||
|
|
||||||
answers = answer.try(:answer) || answer
|
answers = answer.try(:answer) || answer
|
||||||
|
value_text = answers['text'] || question.input_options['text']
|
||||||
|
value_html = answers['html'] || question.input_options['html']
|
||||||
|
value_css = answers['css'] || question.input_options['css']
|
||||||
|
value_js = answers['js'] || question.input_options['js']
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<%= render partial: "quiz/answer_errors", locals: {question: question, answer: answer} %>
|
<%= render partial: "quiz/answer_errors", locals: {question: question, answer: answer} %>
|
||||||
@ -38,21 +43,21 @@
|
|||||||
|
|
||||||
<div id="answer<%= question.question_id %>" data-id="live-coder-answer" style="display: none;">
|
<div id="answer<%= question.question_id %>" data-id="live-coder-answer" style="display: none;">
|
||||||
<label for="answer_live_code_text">Enter answer here</label>
|
<label for="answer_live_code_text">Enter answer here</label>
|
||||||
<%= text_area_tag 'answer[live_code][text]', (answers['text']), { disabled: true, data: {last: answers['text']}} %>
|
<%= text_area_tag 'answer[live_code][text]', value_text, { disabled: true, data: {last: answers['text']}} %>
|
||||||
|
|
||||||
<div class="code-input">
|
<div class="code-input">
|
||||||
<label for="answer_live_code_html">HTML</label>
|
<label for="answer_live_code_html">HTML</label>
|
||||||
<%= text_area_tag 'answer[live_code][html]', (answers['html']), { disabled: true, data: {id: 'code-html', last: answers['html']}, class: 'code-answer code-html' } %>
|
<%= text_area_tag 'answer[live_code][html]', value_html, { disabled: true, data: {id: 'code-html', last: answers['html']}, class: 'code-answer code-html' } %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="code-input">
|
<div class="code-input">
|
||||||
<label for="answer_live_code_css">CSS</label>
|
<label for="answer_live_code_css">CSS</label>
|
||||||
<%= text_area_tag 'answer[live_code][css]', (answers['css']), { disabled: true, data: {id: 'code-css', last: answers['css']}, class: 'code-answer code-css' } %>
|
<%= text_area_tag 'answer[live_code][css]', value_css, { disabled: true, data: {id: 'code-css', last: answers['css']}, class: 'code-answer code-css' } %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="code-input">
|
<div class="code-input">
|
||||||
<label for="answer_live_code_js">JS</label>
|
<label for="answer_live_code_js">JS</label>
|
||||||
<%= text_area_tag 'answer[live_code][js]', (answers['js']), { disabled: true, data: {id: 'code-js', last: answers['js']}, class: 'code-answer code-js' } %>
|
<%= text_area_tag 'answer[live_code][js]', value_js, { disabled: true, data: {id: 'code-js', last: answers['js']}, class: 'code-answer code-js' } %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="results" data-id="results"></div>
|
<div class="results" data-id="results"></div>
|
||||||
|
@ -39,7 +39,7 @@ class CandidateQuizQuestion
|
|||||||
end
|
end
|
||||||
|
|
||||||
def input_options
|
def input_options
|
||||||
YAML.load(row["input_options"].to_s)
|
YAML.load(row["input_options"].to_s) || {}
|
||||||
end
|
end
|
||||||
|
|
||||||
def answer
|
def answer
|
||||||
|
2
test/fixtures/questions.yml
vendored
2
test/fixtures/questions.yml
vendored
@ -68,6 +68,8 @@ fed7:
|
|||||||
category: Javascript
|
category: Javascript
|
||||||
input_type: live_code
|
input_type: live_code
|
||||||
input_options:
|
input_options:
|
||||||
|
:html: "<p>sample seed html</p>"
|
||||||
|
:css: "body { color: #644; }"
|
||||||
sort: 6
|
sort: 6
|
||||||
active: true
|
active: true
|
||||||
|
|
||||||
|
@ -15,4 +15,13 @@ class QuestionLiveCoderTest < ActionDispatch::IntegrationTest
|
|||||||
# TODO: add in capybara and test form post
|
# TODO: add in capybara and test form post
|
||||||
# assert_redirected summary_path
|
# assert_redirected summary_path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "should load seed data into live coder" do
|
||||||
|
setup_auth candidates(:juan)
|
||||||
|
question = questions(:fed7)
|
||||||
|
|
||||||
|
get question_path(question.id)
|
||||||
|
assert_response :success
|
||||||
|
assert_select '#answer_live_code_html', question.input_options['html']
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -11,4 +11,11 @@ class QuestionTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
assert_equal 2, question.input_options.count
|
assert_equal 2, question.input_options.count
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test 'should have seed input for live_coder' do
|
||||||
|
question = Question.find questions(:fed7).to_i
|
||||||
|
|
||||||
|
assert_kind_of Hash, question.input_options
|
||||||
|
assert question.input_options.keys.include? :html
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -3,13 +3,15 @@ class AnswerValidatable
|
|||||||
|
|
||||||
attr_accessor :answer
|
attr_accessor :answer
|
||||||
attr_accessor :question
|
attr_accessor :question
|
||||||
|
attr_accessor :question_id
|
||||||
|
|
||||||
validates :answer, answer_format: true
|
validates :answer, answer_format: true
|
||||||
|
|
||||||
MockQuestion = Struct.new(:input_type)
|
MockQuestion = Struct.new(:input_type)
|
||||||
|
|
||||||
def initialize input_type
|
def initialize input_type, qid = nil
|
||||||
@input_type = input_type
|
@input_type = input_type
|
||||||
|
@question_id = qid
|
||||||
end
|
end
|
||||||
|
|
||||||
def question
|
def question
|
||||||
|
@ -48,4 +48,20 @@ class AnswerFormatValidatorTest < ActiveSupport::TestCase
|
|||||||
assert obj.valid?
|
assert obj.valid?
|
||||||
assert obj.errors.messages.empty?
|
assert obj.errors.messages.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "live_code should PASS using seed data" do
|
||||||
|
obj = AnswerValidatable.new('live_code', questions(:fed7).id)
|
||||||
|
obj.answer = { text: "no thanks", html: "<p>sample seed html</p>", css: "body { color: #644; }", js: "" }
|
||||||
|
|
||||||
|
assert obj.valid?
|
||||||
|
assert obj.errors.messages.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
test "live_code should FAIL with seed data only" do
|
||||||
|
obj = AnswerValidatable.new('live_code', questions(:fed7).id)
|
||||||
|
obj.answer = { text: "", html: "<p>sample seed html</p>", css: "body { color: #644; }", js: "" }
|
||||||
|
|
||||||
|
refute obj.valid?
|
||||||
|
assert_match(/write.*code/, obj.errors.messages[:answer][0])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user