diff --git a/app/controllers/answers_controller.rb b/app/controllers/answers_controller.rb index 43ab3127fc..742996f629 100644 --- a/app/controllers/answers_controller.rb +++ b/app/controllers/answers_controller.rb @@ -99,8 +99,15 @@ def create_or_update template = @section.phase.template remove_list_after = remove_list(@plan) - all_question_ids = @plan.questions.pluck(:id) + + # Destroy all answers for removed questions + remove_list_after.each do |id| + Answer.where(question_id: id, plan: @plan).each do |a| + Answer.destroy(a.id) + end + end + # rubocop pointed out that these variable is not used # all_answers = @plan.answers qn_data = { diff --git a/app/helpers/conditions_helper.rb b/app/helpers/conditions_helper.rb index 9ea082a326..6338ee278d 100644 --- a/app/helpers/conditions_helper.rb +++ b/app/helpers/conditions_helper.rb @@ -27,7 +27,7 @@ def answer_remove_list(answer, user = nil) opts = cond.option_list.map(&:to_i).sort action = cond.action_type chosen = answer.question_option_ids.sort - if chosen == opts + if !opts.empty? && !chosen.empty? && !(chosen & opts).empty? if action == 'remove' rems = cond.remove_data.map(&:to_i) id_list += rems diff --git a/app/javascript/src/answers/edit.js b/app/javascript/src/answers/edit.js index 9dbbdd6b7b..b38fc9f61b 100644 --- a/app/javascript/src/answers/edit.js +++ b/app/javascript/src/answers/edit.js @@ -5,7 +5,7 @@ import { } from '../utils/isType'; import { Tinymce } from '../utils/tinymce.js'; import debounce from '../utils/debounce'; -import { updateSectionProgress, getQuestionDiv } from '../utils/sectionUpdate'; +import { updateSectionProgress, getQuestionDiv , deleteAllAnswersForQuestion } from '../utils/sectionUpdate'; import datePicker from '../utils/datePicker'; import TimeagoFactory from '../utils/timeagoFactory.js.erb'; @@ -23,7 +23,9 @@ $(() => { updateSectionProgress(section.sec_id, section.no_ans, section.no_qns); }); data.qn_data.to_hide.forEach((questionid) => { + deleteAllAnswersForQuestion(questionid); getQuestionDiv(questionid).slideUp(); + }); data.qn_data.to_show.forEach((questionid) => { getQuestionDiv(questionid).slideDown(); diff --git a/app/javascript/src/utils/sectionUpdate.js b/app/javascript/src/utils/sectionUpdate.js index a6bec9c0df..8a120fd573 100644 --- a/app/javascript/src/utils/sectionUpdate.js +++ b/app/javascript/src/utils/sectionUpdate.js @@ -1,3 +1,5 @@ +import { Tinymce } from '../utils/tinymce.js'; + // update details in section progress panel export const updateSectionProgress = (id, numSecAnswers, numSecQuestions) => { const progressDiv = $(`#section-panel-${id}`).find('.section-status'); @@ -25,3 +27,30 @@ export const updateSectionProgress = (id, numSecAnswers, numSecQuestions) => { // given a question id find the containing div // used inconditional questions export const getQuestionDiv = (id) => $(`#answer-form-${id}`).closest('.question-body'); + +// Clear an answers for a given question id. +export const deleteAllAnswersForQuestion = (questionid) => { + const answerFormDiv = $(`#answer-form-${questionid}`); + const editAnswerForm = $(`#answer-form-${questionid}`).find('.form-answer'); + + editAnswerForm.find('input:checkbox').prop('checked', false); + editAnswerForm.find('input:radio').prop('checked', false); + editAnswerForm.find('option').prop('selected', false); + editAnswerForm.find('input:text').text(''); + + // Get the TinyMce editor textarea and rest content to '' + const editorAnswerTextAreaId = `answer-text-${questionid}`; + const tinyMceAnswerEditor = Tinymce.findEditorById(editorAnswerTextAreaId); + if (tinyMceAnswerEditor) { + tinyMceAnswerEditor.setContent(''); + } + // Date fields in form are input of type="date" + // The editAnswerForm.find('input:date') throws error, so + // we need an alternate way to reset date. + editAnswerForm.find('#answer_text').each ( (el) => { + if($(el).attr('type') === 'date') { + $(el).val(''); + } + + }); +}; diff --git a/app/models/condition.rb b/app/models/condition.rb index ef0d79cca3..aa2fed5012 100644 --- a/app/models/condition.rb +++ b/app/models/condition.rb @@ -38,6 +38,10 @@ class Condition < ApplicationRecord def deep_copy(**options) copy = dup copy.question_id = options.fetch(:question_id, nil) + copy.option_list = options.fetch(:option_list, option_list) + copy.remove_data = options.fetch(:remove_data, remove_data) + copy.action_type = options.fetch(:action_type, action_type) + copy.action_type = options.fetch(:webhook_data, webhook_data) # TODO: why call validate false here copy.save!(validate: false) if options.fetch(:save, false) copy diff --git a/spec/controllers/answers_controller_with_conditional_questions_spec.rb b/spec/controllers/answers_controller_with_conditional_questions_spec.rb new file mode 100644 index 0000000000..90e0519847 --- /dev/null +++ b/spec/controllers/answers_controller_with_conditional_questions_spec.rb @@ -0,0 +1,341 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe AnswersController, type: :controller do + include RolesHelper + + before(:each) do + template = create(:template, phases: 1, sections: 1) + @section = template.sections.first + + # List1: Different types of questions (than can have conditional options) + @checkbox_conditional_question = create(:question, :checkbox, section: @section, options: 5) + @radiobutton_conditional_question = create(:question, :radiobuttons, section: @section, options: 5) + @dropdown_conditional_question = create(:question, :dropdown, section: @section, options: 5) + + # List2: Questions that do not have conditional options for adding or removing + @textarea_questions = create_list(:question, 7, :textarea, section: @section) + @textfield_questions = create_list(:question, 7, :textfield, section: @section) + @date_questions = create_list(:question, 7, :date, section: @section) + @rda_metadata_questions = create_list(:question, 7, :radiobuttons, section: @section, options: 3) + @checkbox_questions = create_list(:question, 7, :checkbox, section: @section, options: 3) + @radiobuttons_questions = create_list(:question, 7, :radiobuttons, section: @section, options: 3) + @dropdown_questions = create_list(:question, 7, :dropdown, section: @section, options: 3) + @multiselectbox_questions = create_list(:question, 7, :multiselectbox, section: @section, options: 3) + + @plan = create(:plan, :creator, template: template) + @user = @plan.owner + + # Answer the questions in List2 + @textarea_answers = @textarea_questions.each.map do |question| + create(:answer, plan: @plan, question: question, user: @user) + end + + @textfield_answers = @textfield_questions.each.map do |question| + create(:answer, plan: @plan, question: question, user: @user) + end + + @date_answers = @date_questions.each.map do |question| + create(:answer, plan: @plan, question: question, user: @user) + end + + @rda_metadata_answers = @rda_metadata_questions.each.map do |question| + create(:answer, plan: @plan, question: question, user: @user) + end + + @checkbox_answers = @checkbox_questions.each.map do |question| + create(:answer, plan: @plan, question: question, user: @user) + end + + @radiobuttons_answers = @radiobuttons_questions.each.map do |question| + create(:answer, plan: @plan, question: question, user: @user) + end + + @dropdown_answers = @dropdown_questions.each.map do |question| + create(:answer, plan: @plan, question: question, user: @user) + end + + @multiselectbox_answers = @multiselectbox_questions.each.map do |question| + create(:answer, plan: @plan, question: question, user: @user) + end + + sign_in(@user) + end + + # NOTE: Condition is only implemented for checkboxes, radio buttons and dropdowns. In these cases, currently + # the option_list only takes one option in the UI. + # As functionality for more than option per condition does not yet exist in code. + # So all Conditions are created with option_list with a single option id. + + describe 'POST /answers/create_or_update (where atleast one question has one or more conditional options)' do + context 'with conditional checkbox question' do + it 'handles single option (with condition) in option_list ' do + condition = create(:condition, question: @checkbox_conditional_question, + option_list: [@checkbox_conditional_question.question_options[2].id], + action_type: 'remove', + remove_data: [@textarea_questions[5].id, @textfield_questions[5].id, + @date_questions[5].id, @rda_metadata_questions[5].id, @checkbox_questions[5].id, + @radiobuttons_questions[5].id, @dropdown_questions[5].id, @multiselectbox_questions[5].id]) + + # We chose an option that is in the option_list of the condition defined above. + args = { + question_option_ids: [@checkbox_conditional_question.question_options[2].id], + user_id: @user.id, + question_id: @checkbox_conditional_question.id, + plan_id: @plan.id, + lock_version: 0 + } + + post :create_or_update, params: { answer: args } + + json = JSON.parse(response.body).with_indifferent_access + # Hide list match + expect(json[:qn_data][:to_hide]).to match_array(condition.remove_data) + # Show list match + expect(json[:qn_data][:to_show]) + # Answers destroyed + expect(Answer.exists?(@textarea_answers[5].id)).to be_falsey + expect(Answer.exists?(@textfield_answers[5].id)).to be_falsey + expect(Answer.exists?(@date_answers[5].id)).to be_falsey + expect(Answer.exists?(@rda_metadata_answers[5].id)).to be_falsey + expect(Answer.exists?(@checkbox_answers[5].id)).to be_falsey + expect(Answer.exists?(@radiobuttons_answers[5].id)).to be_falsey + expect(Answer.exists?(@dropdown_answers[5].id)).to be_falsey + expect(Answer.exists?(@multiselectbox_answers[5].id)).to be_falsey + # + expect(Answer.exists?(@multiselectbox_answers[0].id)).to be_truthy + end + it 'handles single option (without condition) in option_list' do + create(:condition, question: @checkbox_conditional_question, + option_list: [@checkbox_conditional_question.question_options[1].id], + action_type: 'remove', + remove_data: [@textarea_questions[3].id, @textfield_questions[3].id, + @date_questions[3].id, @rda_metadata_questions[3].id, @checkbox_questions[3].id, + @dropdown_questions[3].id, @multiselectbox_questions[3].id]) + + create(:condition, question: @checkbox_conditional_question, + option_list: [@checkbox_conditional_question.question_options[4].id], + action_type: 'remove', + remove_data: [@textarea_questions[0].id, @textfield_questions[0].id, + @date_questions[0].id, @rda_metadata_questions[0].id, @checkbox_questions[0].id, + @dropdown_questions[0].id, @multiselectbox_questions[0].id]) + + # We choose an option that is not in the option_list of the conditions defined above. + args = { + question_option_ids: [@checkbox_conditional_question.question_options[0].id], + user_id: @user.id, + question_id: @checkbox_conditional_question.id, + plan_id: @plan.id, + lock_version: 0 + } + + post :create_or_update, params: { answer: args } + + json = JSON.parse(response.body).with_indifferent_access + expect(json[:qn_data][:to_hide]).to match_array([]) + end + + it 'handles multiple options (some with conditions) in option_list' do + condition1 = create(:condition, question: @checkbox_conditional_question, + option_list: [@checkbox_conditional_question.question_options[2].id], + action_type: 'remove', + remove_data: [@textarea_questions[0].id, @textfield_questions[0].id, + @date_questions[0].id, @rda_metadata_questions[0].id, @checkbox_questions[0].id, + @dropdown_questions[0].id, @multiselectbox_questions[0].id]) + + condition2 = create(:condition, question: @checkbox_conditional_question, + option_list: [@checkbox_conditional_question.question_options[4].id], + action_type: 'remove', + remove_data: [@textarea_questions[3].id, @textfield_questions[3].id, + @date_questions[3].id, @rda_metadata_questions[3].id, @checkbox_questions[3].id, + @dropdown_questions[3].id, @multiselectbox_questions[3].id]) + + # We choose options that is in the option_list of the conditions defined above as well as an option with no condition defined. + args = { + question_option_ids: [@checkbox_conditional_question.question_options[1].id, @checkbox_conditional_question.question_options[2].id, + @checkbox_conditional_question.question_options[4].id], + user_id: @user.id, + question_id: @checkbox_conditional_question.id, + plan_id: @plan.id, + lock_version: 0 + } + + post :create_or_update, params: { answer: args } + + json = JSON.parse(response.body).with_indifferent_access + expect(json[:qn_data][:to_hide]).to match_array(condition1.remove_data + condition2.remove_data) + end + end + + context 'with conditional radiobuttons question' do + it 'handles single option (with condition) in option_list ' do + condition = create(:condition, question: @radiobutton_conditional_question, + option_list: [@radiobutton_conditional_question.question_options[2].id], + action_type: 'remove', + remove_data: [@textarea_questions[5].id, @textfield_questions[5].id, + @date_questions[5].id, @rda_metadata_questions[5].id, @checkbox_questions[5].id, + @radiobuttons_questions[5].id, @dropdown_questions[5].id, @multiselectbox_questions[5].id]) + + # We choose an option that is in the option_list of the condition defined above. + args = { + question_option_ids: [@radiobutton_conditional_question.question_options[2].id], + user_id: @user.id, + question_id: @radiobutton_conditional_question.id, + plan_id: @plan.id, + lock_version: 0 + } + + post :create_or_update, params: { answer: args } + + json = JSON.parse(response.body).with_indifferent_access + expect(json[:qn_data][:to_hide]).to match_array(condition.remove_data) + end + it 'handles single option (without condition) in option_list' do + create(:condition, question: @radiobutton_conditional_question, + option_list: [@radiobutton_conditional_question.question_options[1].id], + action_type: 'remove', + remove_data: [@textarea_questions[3].id, @textfield_questions[3].id, + @date_questions[3].id, @rda_metadata_questions[3].id, @checkbox_questions[3].id, + @dropdown_questions[3].id, @multiselectbox_questions[3].id]) + + create(:condition, question: @radiobutton_conditional_question, + option_list: [@radiobutton_conditional_question.question_options[4].id], + action_type: 'remove', + remove_data: [@textarea_questions[0].id, @textfield_questions[0].id, + @date_questions[0].id, @rda_metadata_questions[0].id, @checkbox_questions[0].id, + @dropdown_questions[0].id, @multiselectbox_questions[0].id]) + + # We choose an option that is not in the option_list of the conditions defined above. + args = { + question_option_ids: [@radiobutton_conditional_question.question_options[0].id], + user_id: @user.id, + question_id: @radiobutton_conditional_question.id, + plan_id: @plan.id, + lock_version: 0 + } + + post :create_or_update, params: { answer: args } + + json = JSON.parse(response.body).with_indifferent_access + expect(json[:qn_data][:to_hide]).to match_array([]) + end + + it 'handles multiple options (some with conditions) in option_list' do + condition1 = create(:condition, question: @radiobutton_conditional_question, + option_list: [@radiobutton_conditional_question.question_options[2].id], + action_type: 'remove', + remove_data: [@textarea_questions[0].id, @textfield_questions[0].id, + @date_questions[0].id, @rda_metadata_questions[0].id, @checkbox_questions[0].id, + @dropdown_questions[0].id, @multiselectbox_questions[0].id]) + + condition2 = create(:condition, question: @radiobutton_conditional_question, + option_list: [@radiobutton_conditional_question.question_options[4].id], + action_type: 'remove', + remove_data: [@textarea_questions[3].id, @textfield_questions[3].id, + @date_questions[3].id, @rda_metadata_questions[3].id, @checkbox_questions[3].id, + @dropdown_questions[3].id, @multiselectbox_questions[3].id]) + + # We choose options that is in the option_list of the conditions defined above as well as an option with no condition defined. + args = { + question_option_ids: [@radiobutton_conditional_question.question_options[1].id, @radiobutton_conditional_question.question_options[2].id, + @radiobutton_conditional_question.question_options[4].id], + user_id: @user.id, + question_id: @radiobutton_conditional_question.id, + plan_id: @plan.id, + lock_version: 0 + } + + post :create_or_update, params: { answer: args } + + json = JSON.parse(response.body).with_indifferent_access + expect(json[:qn_data][:to_hide]).to match_array(condition1.remove_data + condition2.remove_data) + end + end + + context 'with conditional dropdown question' do + it 'handles single option (with condition) in option_list ' do + condition = create(:condition, question: @dropdown_conditional_question, + option_list: [@dropdown_conditional_question.question_options[2].id], + action_type: 'remove', + remove_data: [@textarea_questions[5].id, @textfield_questions[5].id, + @date_questions[5].id, @rda_metadata_questions[5].id, @checkbox_questions[5].id, + @radiobuttons_questions[5].id, @dropdown_questions[5].id, @multiselectbox_questions[5].id]) + + # We chose an option that is in the option_list of the condition defined above. + args = { + question_option_ids: [@dropdown_conditional_question.question_options[2].id], + user_id: @user.id, + question_id: @dropdown_conditional_question.id, + plan_id: @plan.id, + lock_version: 0 + } + + post :create_or_update, params: { answer: args } + + json = JSON.parse(response.body).with_indifferent_access + expect(json[:qn_data][:to_hide]).to match_array(condition.remove_data) + end + it 'handles single option (without condition) in option_list' do + create(:condition, question: @dropdown_conditional_question, + option_list: [@dropdown_conditional_question.question_options[1].id], + action_type: 'remove', + remove_data: [@textarea_questions[3].id, @textfield_questions[3].id, + @date_questions[3].id, @rda_metadata_questions[3].id, @checkbox_questions[3].id, + @dropdown_questions[3].id, @multiselectbox_questions[3].id]) + + create(:condition, question: @dropdown_conditional_question, + option_list: [@dropdown_conditional_question.question_options[4].id], + action_type: 'remove', + remove_data: [@textarea_questions[0].id, @textfield_questions[0].id, + @date_questions[0].id, @rda_metadata_questions[0].id, + @checkbox_questions[0].id, @dropdown_questions[0].id, @multiselectbox_questions[0].id]) + + # We choose an option that is not in the option_list of the conditions defined above. + args = { + question_option_ids: [@dropdown_conditional_question.question_options[0].id], + user_id: @user.id, + question_id: @dropdown_conditional_question.id, + plan_id: @plan.id, + lock_version: 0 + } + + post :create_or_update, params: { answer: args } + + json = JSON.parse(response.body).with_indifferent_access + expect(json[:qn_data][:to_hide]).to match_array([]) + end + + it 'handles multiple options (some with conditions) in option_list' do + condition1 = create(:condition, question: @dropdown_conditional_question, + option_list: [@dropdown_conditional_question.question_options[2].id], + action_type: 'remove', + remove_data: [@textarea_questions[0].id, @textfield_questions[0].id, + @date_questions[0].id, @rda_metadata_questions[0].id, @checkbox_questions[0].id, + @dropdown_questions[0].id, @multiselectbox_questions[0].id]) + + condition2 = create(:condition, question: @dropdown_conditional_question, + option_list: [@dropdown_conditional_question.question_options[4].id], + action_type: 'remove', + remove_data: [@textarea_questions[3].id, @textfield_questions[3].id, + @date_questions[3].id, @rda_metadata_questions[3].id, @checkbox_questions[3].id, + @dropdown_questions[3].id, @multiselectbox_questions[3].id]) + + # We choose options that is in the option_list of the conditions defined above as well as an option with no condition defined. + args = { + question_option_ids: [@dropdown_conditional_question.question_options[1].id, @dropdown_conditional_question.question_options[2].id, + @dropdown_conditional_question.question_options[4].id], + user_id: @user.id, + question_id: @dropdown_conditional_question.id, + plan_id: @plan.id, + lock_version: 0 + } + + post :create_or_update, params: { answer: args } + + json = JSON.parse(response.body).with_indifferent_access + expect(json[:qn_data][:to_hide]).to match_array(condition1.remove_data + condition2.remove_data) + end + end + end +end diff --git a/spec/factories/answers.rb b/spec/factories/answers.rb index 447c549bb1..f90efea5c2 100644 --- a/spec/factories/answers.rb +++ b/spec/factories/answers.rb @@ -34,5 +34,11 @@ plan user question + trait :question_options do + question_options { [create(:question_option), create(:question_option)] } + end + trait :lock_version do + lock_version { 0 } + end end end diff --git a/spec/factories/conditions.rb b/spec/factories/conditions.rb index afaf5fdea2..813fb366fa 100644 --- a/spec/factories/conditions.rb +++ b/spec/factories/conditions.rb @@ -28,5 +28,17 @@ factory :condition do option_list { nil } remove_data { nil } + action_type { nil } + # the webhook_data is a Json string of form: + # '{"name":"Joe Bloggs","email":"joe.bloggs@example.com","subject":"Large data volume","message":"A message."}' + webhook_data do + # Generates string from hash + JSON.generate({ + name: Faker::Name.name, + email: Faker::Internet.email, + subject: Faker::Lorem.sentence(word_count: 4), + message: Faker::Lorem.paragraph(sentence_count: 2) + }) + end end end diff --git a/spec/features/questions/conditions_questions_spec.rb b/spec/features/questions/conditions_questions_spec.rb new file mode 100644 index 0000000000..6b95dba850 --- /dev/null +++ b/spec/features/questions/conditions_questions_spec.rb @@ -0,0 +1,145 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Question::Conditions questions', type: :feature do + before do + @user = create(:user) + @template = create(:template, :default, :published) + @plan = create(:plan, :creator, template: @template) + @phase = create(:phase, template: @template) + @section = create(:section, phase: @phase) + + # Different types of questions (than can have conditional options) + @checkbox_question = create(:question, :checkbox, section: @section, options: 5) + @radiobutton_question = create(:question, :radiobuttons, section: @section, options: 5) + @dropdown_question = create(:question, :dropdown, section: @section, options: 5) + + create(:role, :creator, :editor, :commenter, user: @user, plan: @plan) + sign_in(@user) + end + + # NOTE: Condition is only implemented for checkboxes, radio buttons and dropdowns. In these cases, currently + # the option_list only takes one option in the UI. + # As functionality for more than option per condition does not yet exist in code. + # So all Conditions are created with option_list with a single option id. + + scenario 'User answers multiple options for a checkbox with conditional options', :js do + chk_condition1 = create(:condition, question: @checkbox_question, + option_list: [@checkbox_question.question_options[2].id], + action_type: 'remove', + remove_data: [create(:question, :dropdown, section: @section, options: 3).id, + create(:question, :date, section: @section).id, + create(:question, :textfield, section: @section).id]) + + chk_condition2 = create(:condition, question: @checkbox_question, + option_list: [@checkbox_question.question_options[1].id], + action_type: 'remove', + remove_data: [create(:question, :checkbox, section: @section, options: 3).id, + create(:question, :date, section: @section).id, + create(:question, :textfield, section: @section).id]) + + chk_condition3 = create(:condition, question: @checkbox_question, + option_list: [@checkbox_question.question_options[3].id], + action_type: 'remove', + remove_data: [create(:question, :radiobuttons, section: @section, options: 3).id, + create(:question, :rda_metadata, section: @section).id, + create(:question, :textarea, + section: @section).id]) + + visit overview_plan_path(@plan) + + click_link 'Write plan' + + find("#section-panel-#{@section.id}").click + + save_screenshot + expect(page).to have_text('(0 / 12)') + + within("#answer-form-#{@checkbox_question.id}") do + check @checkbox_question.question_options[2].text + click_button 'Save' + end + + save_screenshot + expect(page).to have_text('Answered just now') + expect(page).not_to have_selector("#answer-form-#{chk_condition1.remove_data[0]}") + expect(page).to have_text('(1 / 9)') + + within("#answer-form-#{@checkbox_question.id}") do + check @checkbox_question.question_options[1].text + click_button 'Save' + end + + save_screenshot + expect(page).to have_text('Answered just now') + expect(page).not_to have_selector("#answer-form-#{chk_condition2.remove_data[2]}") + expect(page).to have_text('(1 / 6)') + + # within("#answer-form-#{question2.id}") do + # select q2_options.last.text + # click_button 'Save' + # end + + # expect(page).to have_text('Answered just now') + # expect(page).not_to have_selector("#answer-form-#{question5.id}") + # # As one question has been removed, the total of questions is 3 + # expect(page).to have_text('(2 / 5)') + end + + # scenario 'Conditions with multiple options selected', :js do + # question = create(:question, :checkbox, section: @section, options: 4) + # dependent_question = create(:question, :textfield, section: @section) + + # options = question.question_options + + # create(:condition, question: question, + # option_list: [options[0].id, options[1].id], + # action_type: 'remove', + # remove_data: [dependent_question.id]) + + # visit edit_plan_path(@plan) + + # find("#section-panel-#{@section.id}").click + + # within("#answer-form-#{question.id}") do + # check options[0].text + # check options[2].text + # click_button 'Save' + # end + + # expect(page).to have_selector("#answer-form-#{dependent_question.id}") + + # within("#answer-form-#{question.id}") do + # check options[1].text + # click_button 'Save' + # end + + # expect(page).not_to have_selector("#answer-form-#{dependent_question.id}") + # end + + # scenario 'User answers question', :js do + # # Setup + # visit overview_plan_path(@plan) + + # # Action + # click_link 'Write plan' + + # # Expectations + # expect(current_path).to eql(edit_plan_path(@plan)) + # expect(page).to have_text('(4 / 5)') + + # # # Action + # find("#section-panel-#{@section.id}").click + # # # Fill in the answer form... + # within("#answer-form-#{@questions[0].id}") do + # check @questions[0].question_options.first.text + # click_button 'Save' + # end + + # # # Expectations + # # expect(page).to have_text 'Answered just now' + # # expect(page).to have_text '(1 / 1)' + # # expect(Answer.where(question_id: @question.id)).to be_any + # end +end diff --git a/spec/models/condition_spec.rb b/spec/models/condition_spec.rb index f5b8d10d45..4d7bde5c87 100644 --- a/spec/models/condition_spec.rb +++ b/spec/models/condition_spec.rb @@ -3,5 +3,62 @@ require 'rails_helper' RSpec.describe Condition, type: :model do - pending "add some examples to (or delete) #{__FILE__}" + context 'associations' do + it { is_expected.to belong_to :question } + end + + describe '.deep_copy with no options passed in.' do + let!(:question) { build(:question) } + + let!(:condition) do + build(:condition, question: question, option_list: [1, 5], + action_type: 'remove', + remove_data: [7, 8, 9]) + end + + subject { condition.deep_copy } + + it 'creates a new record' do + expect(subject).not_to eql(condition) + end + it 'copies the option_list attribute' do + expect(subject.option_list).to contain_exactly(1, 5) + end + + it 'copies the action_type attribute' do + expect(subject.action_type).to eql('remove') + end + + it 'copies the remove_data attribute' do + expect(subject.remove_data).to contain_exactly(7, 8, 9) + end + end + + describe '.deep_copy with options passed in.' do + let!(:question) { build(:question) } + + let!(:condition) do + build(:condition, question: question, option_list: [1, 5], + action_type: 'remove', + remove_data: [7, 8, 9]) + end + let!(:options) { { option_list: [100, 101], action_type: 'remove', remove_data: [200, 220] } } + + subject { condition.deep_copy(**options) } + + it 'creates a new record' do + expect(subject).not_to eql(condition) + end + it 'replaces the option_list attribute with passed option_list' do + expect(subject.option_list).to contain_exactly(100, 101) + end + + it 'replaces the action_type attribute with passed in action_type' do + expect(subject.action_type).to eql('remove') + end + + it 'replaces the remove_data attribute with passed in remove_data' do + expect(subject.remove_data).to contain_exactly(200, 220) + end + end end