Newer
Older
dmpopidor / spec / models / phase_spec.rb
@Bodacious Bodacious on 27 Jul 2018 4 KB Add specs for all models
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