require 'rails_helper' describe Plan do include RolesHelper include TemplateHelper context "validations" do it { is_expected.to validate_presence_of(:title) } it { is_expected.to validate_presence_of(:template) } it { is_expected.to allow_values(true, false).for(:feedback_requested) } it { is_expected.not_to allow_value(nil).for(:feedback_requested) } it { is_expected.to allow_values(true, false).for(:complete) } it { is_expected.not_to allow_value(nil).for(:complete) } end context "associations" do it { is_expected.to belong_to :template } it { is_expected.to have_many :phases } it { is_expected.to have_many :sections } it { is_expected.to have_many :questions } it { is_expected.to have_many :themes } it { is_expected.to have_many :answers } it { is_expected.to have_many :notes } it { is_expected.to have_many :roles } it { is_expected.to have_many :users } it { is_expected.to have_many :exported_plans } it { is_expected.to have_many :setting_objects } it { is_expected.to have_many :research_outputs } end describe ".publicly_visible" do subject { Plan.publicly_visible } context "when plan visibility is publicly_visible" do let!(:plan) { create(:plan, :creator, :publicly_visible) } it { is_expected.to include(plan) } end context "when plan visibility is organisationally_visible" do let!(:plan) { create(:plan, :creator, :organisationally_visible) } it { is_expected.not_to include(plan) } end context "when plan visibility is is_test" do let!(:plan) { create(:plan, :creator, :is_test) } it { is_expected.not_to include(plan) } end context "when plan visibility is privately_visible" do let!(:plan) { create(:plan, :creator, :privately_visible) } it { is_expected.not_to include(plan) } end end describe ".organisationally_visible" do subject { Plan.organisationally_visible } context "when plan visibility is publicly_visible" do let!(:plan) { create(:plan, :creator, :publicly_visible) } it { is_expected.not_to include(plan) } end context "when plan visibility is organisationally_visible" do let!(:plan) { create(:plan, :creator, :organisationally_visible) } it { is_expected.to include(plan) } end context "when plan visibility is is_test" do let!(:plan) { create(:plan, :creator, :is_test) } it { is_expected.not_to include(plan) } end context "when plan visibility is privately_visible" do let!(:plan) { create(:plan, :creator, :privately_visible) } it { is_expected.not_to include(plan) } end end describe ".privately_visible" do subject { Plan.privately_visible } context "when plan visibility is publicly_visible" do let!(:plan) { create(:plan, :creator, :publicly_visible) } it { is_expected.not_to include(plan) } end context "when plan visibility is organisationally_visible" do let!(:plan) { create(:plan, :creator, :organisationally_visible) } it { is_expected.not_to include(plan) } end context "when plan visibility is is_test" do let!(:plan) { create(:plan, :creator, :is_test) } it { is_expected.not_to include(plan) } end context "when plan visibility is privately_visible" do let!(:plan) { create(:plan, :creator, :privately_visible) } it { is_expected.to include(plan) } end end describe ".organisationally_or_publicly_visible" do let!(:user) { create(:user) } subject { Plan.organisationally_or_publicly_visible(user) } context "when user is creator" do before do create(:role, :creator, user: user, plan: plan) end let!(:plan) { create(:plan, :creator, :publicly_visible) } it { is_expected.not_to include(plan) } end context "when user is administrator" do before do create(:role, :administrator, user: user, plan: plan) end let!(:plan) { create(:plan, :creator, :publicly_visible) } it { is_expected.not_to include(plan) } end context "when user is commenter" do before do create(:role, :commenter, user: user, plan: plan) end let!(:plan) { create(:plan, :creator, :publicly_visible) } it { is_expected.not_to include(plan) } end context "when user is editor" do before do create(:role, :editor, user: user, plan: plan) end let!(:plan) { create(:plan, :creator, :publicly_visible) } it { is_expected.not_to include(plan) } end context "when plan visibility is publicly_visible" do before do new_user = create(:user, org: user.org) create(:role, :creator, :administrator, :editor, :commenter, user: new_user, plan: plan) end let!(:template) { build_template(1, 1, 1) } let!(:plan) { create(:plan, :creator, :organisationally_visible, template: template) } let!(:answer) { create(:answer, plan: plan, question: template.phases.first.sections.first.questions.first) } it "includes publicly_visible plans" do is_expected.to include(plan) end end context "when plan visibility is organisationally_visible" do before do new_user = create(:user, org: user.org) create(:role, :creator, :administrator, :editor, :commenter, user: new_user, plan: plan) end let!(:template) { build_template(1, 1, 1) } let!(:plan) { create(:plan, :creator, :organisationally_visible, template: template) } let!(:answer) { create(:answer, plan: plan, question: template.phases.first.sections.first.questions.first) } it "includes organisationally_visible plans" do is_expected.to include(plan) end end context "when plan is not complete" do before do new_user = create(:user, org: user.org) create(:role, :creator, :administrator, :editor, :commenter, user: new_user, plan: plan) end let!(:plan) { create(:plan, :creator, :organisationally_visible) } it "includes organisationally_visible plans" do is_expected.not_to include(plan) end end context "when plan visibility is is_test" do let!(:plan) { create(:plan, :creator, :is_test) } it { is_expected.not_to include(plan) } end context "when plan visibility is privately_visible" do let!(:plan) { create(:plan, :creator, :privately_visible) } it { is_expected.not_to include(plan) } end context "when plan has no active roles" do let!(:plan) { build_plan } it "should not be included" do plan.roles.inject{ |r| r.deactivate! } is_expected.to_not include(plan) end end end describe ".is_test" do subject { Plan.is_test } context "when plan visibility is publicly_visible" do let!(:plan) { create(:plan, :creator, :publicly_visible) } it { is_expected.not_to include(plan) } end context "when plan visibility is organisationally_visible" do let!(:plan) { create(:plan, :creator, :organisationally_visible) } it { is_expected.not_to include(plan) } end context "when plan visibility is is_test" do let!(:plan) { create(:plan, :creator, :is_test) } it { is_expected.to include(plan) } end context "when plan visibility is privately_visible" do let!(:plan) { create(:plan, :creator, :privately_visible) } it { is_expected.not_to include(plan) } end end describe ".active" do let!(:plan) { create(:plan, :creator) } let!(:user) { create(:user) } subject { Plan.active(user) } context "where user role is active" do before do create(:role, :active, :creator, user: user, plan: plan) end it { is_expected.to include(plan) } end context "where user role is not active" do before do create(:role, :inactive, :creator, user: user, plan: plan) end it { is_expected.not_to include(plan) } end end describe ".load_for_phase" do let!(:template) { create(:template) } let!(:plan) { create(:plan, :creator, template: template) } let!(:phase) { create(:phase, template: template) } let!(:section) { create(:section, phase: phase) } let!(:question) { create(:question, section: section) } subject { Plan.load_for_phase(plan.id, phase.id) } context "when Plan ID is valid and Phase ID is valid child" do it "returns an Array" do expect(subject).to be_an(Array) end it "returns the Plan first" do expect(subject.first).to eql(plan) end it "returns the Phase second" do expect(subject.second).to eql(phase) end end context "when Plan ID is valid and Phase ID is not valid child" do let!(:phase) { create(:phase) } it "raises an exception" do # TODO: This is not ideal behaviour. Fix this. expect { subject }.to raise_error(NoMethodError) end end context "when Plan ID is not valid" do let!(:plan) { stub(id: 0) } it "raises an exception" do # TODO: This is not ideal behaviour. Fix this. expect { subject }.to raise_error(NoMethodError) end end end describe ".deep_copy" do let!(:plan) { create(:plan, :creator, research_outputs: 1, answers: 2, guidance_groups: 2, feedback_requested: true) } subject { Plan.deep_copy(plan) } it "prepends the title with 'Copy'" do expect(subject.title).to include("Copy") end it "sets feedback_requested to false" do expect(subject.feedback_requested).to eql(false) end it "copies the title from source" do expect(subject.title).to include(plan.title) end it "persists the record" do expect(subject).to be_persisted end it "creates new copies of the answers" do expect(subject.answers).to have(2).items end it "duplicates the guidance groups" do expect(subject.guidance_groups).to have(2).items end end describe ".search" do subject { Plan.search("foo") } context "when Plan title matches term" do let!(:plan) { create(:plan, title: "foolike title") } it { is_expected.to include(plan) } end context "when Template title matches term" do let!(:template) { create(:template, title: "foolike title") } let!(:plan) { create(:plan, template: template) } it { is_expected.to include(plan) } end context "when neither title matches term" do let!(:plan) { create(:plan, description: "foolike desc") } it { is_expected.not_to include(plan) } end end describe "#answer" do let!(:plan) { create(:plan, :creator, answers: 1) } let!(:research_output) { create(:research_output, plan: plan) } let!(:question) { create(:question) } subject { plan.answer(question.id, create_if_missing, research_output.id) } context "when create_if_missing is true and answer exists on the DB" do let!(:create_if_missing) { true } let!(:answer) { create(:answer, plan: plan, question: question, research_output: research_output) } it "returns the existing Answer" do expect(subject).to eql(answer) end end context "when create_if_missing is true and answer doesn't exist on the DB" do let!(:create_if_missing) { true } it "returns a new Answer" do expect(subject).to be_an(Answer) end it "doesn't persist the new Answer" do expect(subject).to be_new_record end end context "when create_if_missing is false and qid exists on the DB" do let!(:create_if_missing) { false } let!(:answer) { create(:answer, plan: plan, question: question, research_output: research_output) } it "returns the existing Answer" do expect(subject).to eql(answer) end end context "when create_if_missing is false and qid doesn't exist on the DB" do let!(:create_if_missing) { false } let!(:answer) { nil } it "returns nil" do expect(subject).to be_nil end end end describe "#guidance_group_options" do let!(:plan) { create(:plan, :creator) } subject { plan.guidance_group_options } before do @phase = create(:phase, template: plan.template) @section = create(:section, phase: @phase) @question = create(:question, section: @section) @theme = create(:theme) @guidance = create(:guidance) @guidance_group = @guidance.guidance_group @question.themes << @theme @theme.guidances << @guidance end context "when guidance groups are unpublished" do before do @guidance_group.update(published: false) end it "excludes the guidance group from options" do expect(subject).not_to include(@guidance_group) end end context "when guidance groups are published" do it "includes the guidance group in options" do expect(subject).to include(@guidance_group) end end end describe "#request_feedback" do subject { plan.request_feedback(user) } let!(:org) { create(:org, contact_email: nil) } let!(:user) { create(:user, org: org) } let!(:plan) { create(:plan, :creator) } before do # Create 2 Org admins for this Org. create_list(:user, 2, org: org).each do |user| user.perms << Perm.where(name: 'modify_guidance').first_or_create end ActionMailer::Base.deliveries = [] end it "changes plan's feedback_requested value to true" do expect { subject }.to change { plan.reload.feedback_requested }.from(false).to(true) end it "doesn't send any emails" do expect { subject }.not_to change { ActionMailer::Base.deliveries.size } end context "when org contact_email present" do before do org.update!(contact_email: Faker::Internet.safe_email) end it "emails the admins" do expect { subject }.to change { ActionMailer::Base.deliveries.size }.by(1) end end end describe "#complete_feedback" do subject { plan.complete_feedback(user) } let!(:org) { create(:org) } let!(:user) { create(:user, org: org) } let!(:admin) { create(:user) } let!(:template) { create(:template, phases: 2) } let!(:plan) { create(:plan, feedback_requested: true, template: template) } before do create(:role, :creator, plan: plan, user: user) # This person gets the email notification create(:role, :administrator, plan: plan, user: admin) end it "changes plan's feedback_requested value to false" do expect { subject }.to change { plan.reload.feedback_requested }.from(true).to(false) end it "doesn't send any emails" do User.any_instance.stubs(:get_preferences) .returns(:users => { :feedback_provided => false }) expect { subject }.not_to change { ActionMailer::Base.deliveries.size } end context "when user feedback provided pref is true" do before do User.any_instance.stubs(:get_preferences) .returns(:users => { :feedback_provided => true }) end it "emails the owners" do expect { subject }.to change { ActionMailer::Base.deliveries.size }.by(2) end end end describe "#guidance_by_question_as_hash" do end describe "#editable_by?" do let!(:plan) { build_plan(true, true, true) } subject { plan } it "when role is inactive" do role = subject.roles.editor.first role.deactivate! user = role.user expect(subject.editable_by?(user.id)).to eql(false) end it "when user is a creator" do # All creators should be able to edit subject.roles.creator.pluck(:user_id).each do |user_id| expect(subject.editable_by?(user_id)).to eql(true) end end it "when user is a administrator" do # All administrators (aka coowners) should be able to edit subject.roles.administrator.pluck(:user_id).each do |user_id| expect(subject.editable_by?(user_id)).to eql(true) end end it "when user is a editor" do # All editors should be able to edit subject.roles.editor.pluck(:user_id).each do |user_id| expect(subject.editable_by?(user_id)).to eql(true) end end it "when user is a commenter" do # Commenters should only be able to edit if they are also # a creator, administrator or editor subject.roles.commenter.each do |role| expect(subject.editable_by?(role.user.id)).to eql(role.editor?) end end end describe "#readable_by?" do let!(:user) { create(:user, org: create(:org)) } let!(:plan) { build_plan(true, true, true) } let!(:org) { create(:org, is_other: true) } subject { plan } context "config allows for admin viewing" do it "super admins" do Branding.expects(:fetch) .with(:service_configuration, :plans, :super_admins_read_all) .returns(true) user.perms << create(:perm, name: "add_organisations") expect(subject.readable_by?(user.id)).to eql(true) end it "org admins" do Branding.expects(:fetch) .with(:service_configuration, :plans, :org_admins_read_all) .returns(true) user.org_id = plan.owner.org_id user.save user.perms << create(:perm, name: "modify_guidance") expect(subject.readable_by?(user.id)).to eql(true) end end context "config does not allow admin viewing" do it "super admins" do Branding.expects(:fetch) .with(:service_configuration, :plans, :super_admins_read_all) .returns(false) user.perms << create(:perm, name: "add_organisations") expect(subject.readable_by?(user.id)).to eql(false) end it "org admins" do Branding.expects(:fetch) .with(:service_configuration, :plans, :org_admins_read_all) .returns(false) user.perms << create(:perm, name: "modify_guidance") expect(subject.readable_by?(user.id)).to eql(false) end end context "non-admin user" do it "when role is inactive" do role = subject.roles.commenter.first role.deactivate! user = role.user expect(subject.readable_by?(user.id)).to eql(false) end it "when user is a creator" do # All creators should be able to read subject.roles.creator.pluck(:user_id).each do |user_id| expect(subject.readable_by?(user_id)).to eql(true) end end it "when user is a administrator" do # All administrators should be able to read subject.roles.administrator.pluck(:user_id).each do |user_id| expect(subject.readable_by?(user_id)).to eql(true) end end it "when user is a editor" do # All editors should be able to read subject.roles.editor.pluck(:user_id).each do |user_id| expect(subject.readable_by?(user_id)).to eql(true) end end it "when user is a commenter" do # All commenters should be able to read subject.roles.commenter.pluck(:user_id).each do |user_id| expect(subject.readable_by?(user_id)).to eql(true) end end context "When user is a reviewer" do before do user.org = plan.owner.org user.save user.perms << create(:perm, :review_org_plans) end it "when user is a reviewer and feedback requested" do # All reviewers of the same org should be able to comment plan.feedback_requested = true plan.save expect(subject.readable_by?(user.id)).to eql(true) end it "when user is a reviewer and feedback not requested" do Branding.expects(:fetch) .with(:service_configuration, :plans, :org_admins_read_all) .returns(false) plan.feedback_requested = false plan.save expect(subject.readable_by?(user.id)).to eql(false) end it "when user is a reviewer of a different org and feedback requested" do # reviewers of other orgs should have no access user.org = create(:org) user.save user.perms << create(:perm, :review_org_plans) plan.feedback_requested = true plan.save expect(subject.readable_by?(user.id)).to eql(false) end end it "when user is not reviewer, has no roles on the plan and feedback requested" do # All reviewers should be able to comment user.org = plan.owner.org user.save plan.feedback_requested = true plan.save expect(subject.readable_by?(user.id)).to eql(false) end end context "explicit sharing does not conflict with admin-viewing" do it "super admins" do Branding.expects(:fetch) .with(:service_configuration, :plans, :super_admins_read_all) .at_most_once .returns(false) user.perms << create(:perm, name: "add_organisations") role = subject.roles.commenter.first role.user_id = user.id role.save! expect(subject.readable_by?(user.id)).to eql(true) end it "org admins" do Branding.expects(:fetch) .with(:service_configuration, :plans, :org_admins_read_all) .at_most_once .returns(false) user.perms << create(:perm, name: "modify_guidance") role = subject.roles.commenter.first role.user_id = user.id role.save! expect(subject.readable_by?(user.id)).to eql(true) end end end describe "#commentable_by?" do let!(:plan) { build_plan(true, true, true) } subject { plan } it "when role is inactive" do role = subject.roles.commenter.first role.deactivate! user = role.user expect(subject.commentable_by?(user.id)).to eql(false) end it "when user is a creator" do # All creators should be able to comment subject.roles.creator.pluck(:user_id).each do |user_id| expect(subject.commentable_by?(user_id)).to eql(true) end end it "when user is a administrator" do # All administrators should be able to comment subject.roles.administrator.pluck(:user_id).each do |user_id| expect(subject.commentable_by?(user_id)).to eql(true) end end it "when user is a editor" do # All editors should be able to comment subject.roles.editor.pluck(:user_id).each do |user_id| expect(subject.commentable_by?(user_id)).to eql(true) end end it "when user is a commenter" do # All commenters should be able to comment subject.roles.commenter.pluck(:user_id).each do |user_id| expect(subject.commentable_by?(user_id)).to eql(true) end end let(:user) { create(:user) } let!(:org) { create(:org, is_other: true) } context "when user is a reviewer" do before do user.org = plan.owner.org user.save user.perms << create(:perm, :review_org_plans) end it "of the same org and feedback requested" do # All reviewers of the same org should be able to comment plan.feedback_requested = true plan.save expect(subject.commentable_by?(user.id)).to eql(true) end it "of the same org and feedback not requested" do plan.feedback_requested = false plan.save expect(subject.commentable_by?(user.id)).to eql(false) end it "of a different org and feedback requested" do # All reviewers of other orgs should not be able to comment user.org = create(:org) user.save # re-add permissions as org-admins will have these removed on save user.perms << create(:perm, :review_org_plans) plan.feedback_requested = true plan.save expect(subject.commentable_by?(user.id)).to eql(false) end end it "when user is not reviewer, has no roles on the plan and feedback requested" do # All reviewers should be able to comment user.org = plan.owner.org user.save plan.feedback_requested = true plan.save expect(subject.commentable_by?(user.id)).to eql(false) end end describe "#administerable_by?" do let!(:plan) { build_plan(true, true, true) } subject { plan } it "when role is inactive" do role = subject.roles.administrator.first role.deactivate! user = role.user expect(subject.administerable_by?(user.id)).to eql(false) end it "when user is a creator" do # All creators should be able to administer subject.roles.creator.pluck(:user_id).each do |user_id| expect(subject.administerable_by?(user_id)).to eql(true) end end it "when user is a administrator" do # All administrators should be able to administer subject.roles.administrator.pluck(:user_id).each do |user_id| expect(subject.administerable_by?(user_id)).to eql(true) end end it "when user is a editor" do # Editors should only be able to administer if they are also # a creator or administrator subject.roles.editor.each do |role| expect(subject.administerable_by?(role.user.id)).to eql(role.administrator?) end end it "when user is a commenter" do # Commenters should only be able to administer if they are also # a creator or administrator subject.roles.commenter.each do |role| expect(subject.administerable_by?(role.user.id)).to eql(role.administrator?) end end end describe "#reviewable_by?" do let!(:plan) { build_plan(true, true, true) } let!(:user) { create(:user) } let!(:org) { create(:org, is_other: true) } before do plan.feedback_requested = true plan.save create(:perm, :review_org_plans) end subject { plan } it "when user is not a reviewer" do expect(subject.reviewable_by?(user.id)).to eql(false) end it "when user is a reviewer" do user.org = plan.owner.org user.save user.perms << Perm.review_plans expect(subject.owner.org).to eql(user.org) expect(user.can_review_plans?).to eql(true) expect(plan.feedback_requested?).to eql(true) expect(subject.reviewable_by?(user.id)).to eql(true) end end describe "#latest_update" do let!(:plan) { create(:plan, :creator, updated_at: 5.minutes.ago) } subject { plan.latest_update.to_i } context "when plan updated_at is latest" do before do create_list(:phase, 2, template: plan.template, updated_at: 6.minutes.ago) end it "returns the plan's updated_at value" do is_expected.to be_within(5.seconds).of(5.minutes.ago.to_i) end end context "when plan has phases updated_at latest" do before do create_list(:phase, 2, template: plan.template) end it "returns the plan's updated_at value" do is_expected.to be_within(5.seconds).of(Time.current.to_i) end end end describe "#name" do let!(:plan) { build(:plan, :creator, title: "Foo bar") } it "returns the title" do expect(plan.name).to eql("Foo bar") end end describe "#owner" do let!(:plan) { build_plan(true, true, true) } subject { plan } it "is the creator" do user = subject.roles.creator.first.user expect(subject.owner).to eql(user) end it "is the administrator if there is no creator" do subject.roles.creator.first.deactivate! user = subject.roles.where(active: true).administrator.first.user expect(subject.owner).to eql(user) end end describe "#add_user" do let!(:user) { create(:user, org: create(:org)) } let!(:plan) { build_plan } subject { plan } it "returns false if user does not exist" do expect(subject.add_user!(326465)).to eql(false) end it "adds the creator" do expect(subject.add_user!(user.id, :creator)).to eql(true) role = Role.find_by(user_id: user.id, plan_id: subject.id) expect(role.creator?).to eql(true) expect(role.administrator?).to eql(true) expect(role.editor?).to eql(true) expect(role.commenter?).to eql(true) expect(role.reviewer?).to eql(false) end it "adds the administrator" do expect(subject.add_user!(user.id, :administrator)).to eql(true) role = Role.find_by(user_id: user.id, plan_id: subject.id) expect(role.creator?).to eql(false) expect(role.administrator?).to eql(true) expect(role.editor?).to eql(true) expect(role.commenter?).to eql(true) expect(role.reviewer?).to eql(false) end it "adds the editor" do expect(subject.add_user!(user.id, :editor)).to eql(true) role = Role.find_by(user_id: user.id, plan_id: subject.id) expect(role.creator?).to eql(false) expect(role.administrator?).to eql(false) expect(role.editor?).to eql(true) expect(role.commenter?).to eql(true) expect(role.reviewer?).to eql(false) end it "adds the commenter" do expect(subject.add_user!(user.id, :commenter)).to eql(true) role = Role.find_by(user_id: user.id, plan_id: subject.id) expect(role.creator?).to eql(false) expect(role.administrator?).to eql(false) expect(role.editor?).to eql(false) expect(role.commenter?).to eql(true) expect(role.reviewer?).to eql(false) end it "defaults to commenter if access_level is not a known symbol" do expect(subject.add_user!(user.id)).to eql(true) role = Role.find_by(user_id: user.id, plan_id: subject.id) expect(role.creator?).to eql(false) expect(role.administrator?).to eql(false) expect(role.editor?).to eql(false) expect(role.commenter?).to eql(true) expect(role.reviewer?).to eql(false) end end describe "#shared?" do it "is not shared if the only user is the creator" do plan = build_plan expect(plan.shared?).to eql(false) end it "is shared if the plan has an administrator" do plan = build_plan(true, false, false) expect(plan.shared?).to eql(true) end it "is shared if the plan has an editor" do plan = build_plan(false, true, false) expect(plan.shared?).to eql(true) end it "is shared if the plan has an commenter" do plan = build_plan(false, false, true) expect(plan.shared?).to eql(true) end end describe "#owner_and_coowners" do let!(:plan) { build_plan(true, true, true) } subject { plan } it "includes the creator" do user = subject.roles.creator.first.user expect(subject.owner_and_coowners).to include(user) end it "includes the administrator" do user = subject.roles.administrator.first.user expect(subject.owner_and_coowners).to include(user) end it "does not include the editor" do # Only if the editor is not also an administrator or creator subject.roles.editor.each do |role| if !role.creator? && !role.administrator? expect(subject.owner_and_coowners).to_not include(role.user) end end end it "does not include the commenter" do # Only if the commenter is not also an administrator or creator subject.roles.commenter.each do |role| if !role.creator? && !role.administrator? expect(subject.owner_and_coowners).to_not include(role.user) end end end end describe ".authors" do let!(:plan) { build_plan(true, true, true) } subject { plan } it "includes the creator" do user = subject.roles.creator.first.user expect(subject.authors).to include(user) end it "includes the administrator" do user = subject.roles.administrator.first.user expect(subject.authors).to include(user) end it "includes the editor" do user = subject.roles.editor.first.user expect(subject.authors).to include(user) end it "does not include the commenter" do # Only if the commenter is not also an editor, administrator or creator subject.roles.commenter.each do |role| if !role.creator? && !role.administrator? && !role.editor? expect(subject.authors).to_not include(role.user) end end end end describe "#num_answered_questions" do let!(:template) { create(:template) } let!(:plan) { create(:plan, :creator, template: template) } subject { plan.num_answered_questions } before do @phase = create(:phase, template: template) @section = create(:section, phase: @phase) @questions = create_list(:question, 3, :textarea, section: @section) # 2 valid answers @questions.first(2).each do |question| create(:answer, question: question, plan: plan) end # 1 valid answers @questions.last(1).each do |question| create(:answer, question: question, plan: plan, text: nil) end end it "returns the number of questions with valid answers" do expect(subject).to eql(2) end end describe "#num_questions" do let!(:template) { create(:template) } let!(:plan) { create(:plan, :creator, template: template) } subject { plan.num_questions } before do create_list(:phase, 2, template: template) do |phase| create_list(:section, 2, phase: phase) do |section| create_list(:question, 3, section: section) end end end it "returns the number of questions belonging to this plan's sections" do expect(subject).to eql(12) end end describe "#visibility_allowed?" do let!(:template) { create(:template) } let!(:plan) { create(:plan, :creator, template: template) } let!(:research_output) { create(:research_output, plan: plan) } subject { plan.visibility_allowed? } before do @phase = create(:phase, template: template) @section = create(:section, phase: @phase) @questions = create_list(:question, 4, :textarea, section: @section) @questions.take(3).each do |question| create(:answer, question: question, plan: plan, research_output: research_output) end end context "when requisite number of questions answered" do before do Rails.application.config.default_plan_percentage_answered = 75 end it { is_expected.to eql(true) } end context "when requisite number of questions not answered" do before do Rails.application.config.default_plan_percentage_answered = 76 end it { is_expected.to eql(false) } end end describe "#question_exists?" do context "when Question with ID and Plan exists" do let!(:question) { create(:question) } let!(:plan) { create(:plan, :creator, template: question.section.phase.template) } subject { plan.question_exists?(question.id) } it { is_expected.to eql(true) } end context "when Question with ID and Plan don't exist" do let!(:question) { create(:question) } let!(:plan) { create(:plan, :creator) } subject { plan.question_exists?(question.id) } it { is_expected.to eql(false) } end end describe "#no_questions_matches_no_answers?" do let!(:plan) { create(:plan, :creator) } subject { plan.no_questions_matches_no_answers? } context "when has no answers" do it { is_expected.to eql(true) } end context "when has answers that are not valid" do let!(:question) { create(:question, :textarea) } before do create_list(:answer, 1, text: "", plan: plan, question: question) end it { is_expected.to eql(true) } end context "when has answers that are valid" do let!(:question) { create(:question, :textarea) } before do create_list(:answer, 1, plan: plan, question: question) end it { is_expected.to eql(false) } end end end