require 'rails_helper' RSpec.describe Phase, type: :model do context "validations" do it { is_expected.to validate_presence_of(:title) } it { is_expected.to validate_presence_of(:number) } it { is_expected.to validate_presence_of(:template) } it { is_expected.to validate_uniqueness_of(:number) .scoped_to(:template_id) .with_message("must be unique") } it { is_expected.to allow_values(true, false).for(:modifiable) } it { is_expected.not_to allow_value(nil).for(:modifiable) } end context "associations" do it { is_expected.to belong_to(:template) } it { is_expected.to have_one :prefix_section } it { is_expected.to have_many :sections } it { is_expected.to have_many :template_sections } it { is_expected.to have_many :suffix_sections } end describe ".titles" do let!(:phase) { create(:phase) } let!(:template) { phase.template } subject { Phase.titles(template.id) } before do @related_phases = create_list(:phase, 2, template: template) @strange_phases = create_list(:phase, 2) end it "returns related phases" do @related_phases.each do |phase| expect(subject).to include(phase) end end it "excludes phases of different Templates" do @strange_phases.each do |phase| expect(subject).not_to include(phase) end end end describe "#deep_copy" do let!(:phase) { create(:phase, modifiable: false) } let!(:options) { Hash.new } subject { phase.deep_copy(options) } context "when no options are provided" do before do create_list(:section, 2, phase: phase) end it "doesn't persist the record" do expect(subject).to be_a_new_record end it "copies the description attribute" do expect(subject.description).to eql(phase.description) end it "copies the modifiable attribute" do expect(subject.modifiable).to eql(phase.modifiable) end it "copies the number attribute" do expect(subject.number).to eql(phase.number) end it "copies the title attribute" do expect(subject.title).to eql(phase.title) end it "sets template_id to nil" do expect(subject.template_id).to be_nil end it "duplicates the sections belonging to the Phase" do expect(subject.sections.count).to eql(subject.sections.count) end end context "when modifiable option is true" do let!(:options) { { modifiable: true } } it "sets the modifiable flag to true" do expect(subject.modifiable).to eql(true) end end context "when template_id option is present" do let!(:options) { { template_id: create(:template).id } } it "sets the template_id to new value" do expect(subject.template_id).to eql(options[:template_id]) end end context "when save option is true" do let!(:options) { { save: true } } it "persists the record" do expect(subject).to be_persisted end end end describe "#num_answered_questions" do let!(:phase) { create(:phase) } subject { phase.num_answered_questions(plan) } context "when plan is nil" do let!(:plan) { nil } it "returns 0" do expect(subject).to be_zero end end context "when plan is present" do let!(:phase) { create(:phase, template: template) } let!(:section) { create(:section, phase: phase) } let!(:plan) { create(:plan) } let!(:template) { plan.template } before do question = create(:question, section: section) create(:answer, question: question, plan: plan, text: '') question = create(:question, section: section) create(:answer, question: question, plan: plan) question = create(:question, section: section) create(:answer, question: question, plan: plan) end it "returns the sum of Plan's Phase's num_answered_questions" do expect(subject).to eql(2) end end end describe "#num_questions" do let!(:phase) { create(:phase) } before do create_list(:section, 2, phase: phase).each do |section| create_list(:question, 2, section: section) end end it "returns the number of related questions" do expect(phase.num_questions).to eql(4) end end end