require "rails_helper" RSpec.describe ProjectMembership, type: :model do describe "associations" do it { is_expected.to belong_to(:project) } it { is_expected.to belong_to(:user) } end describe "validations" do describe "#user_id" do subject do account = build(:account) build(:project_membership, user: build(:user, primary_account: account), project: build(:project, account: account)) end it { is_expected.to validate_uniqueness_of(:user_id).scoped_to(:project_id).with_message("already belongs to this Project") } end it "does not allow account managers" do account = build(:account) account_manager = create(:user, :account_manager, accounts: [account]) project = build(:project, account: account) project_membership = ProjectMembership.new(user: account_manager, project: project) expect(project_membership).to be_invalid expect(project_membership.errors[:user]).not_to be_empty expect(project_membership.errors.full_messages.first).to eq "User is already an account manager" end end describe "#save_and_update_account_membership" do let(:project) { create(:project) } context "when no user exists for the given email" do let(:membership) { ProjectMembership.new(project: project, user_email: "new.user@test.com") } it "returns true" do expect(membership.save_and_update_account_membership).to be_truthy end it "creates the user" do expect { membership.save_and_update_account_membership }.to change(User, :count).by(1) user = User.last expect(user.email).to eq "new.user@test.com" end it "creates account membership" do expect { membership.save_and_update_account_membership }.to change(AccountAuth, :count).by(1) account_auth = AccountAuth.last user = User.last expect(account_auth.account).to eq project.account expect(account_auth.user).to eq user end it "creates project membership" do expect { membership.save_and_update_account_membership }.to change(ProjectMembership, :count).by(1) user = User.last expect(membership.project).to eq project expect(membership.user).to eq user end end context "when user exists but has no account access" do let!(:user) { create(:user, email: "existing.user@test.com") } let(:membership) { ProjectMembership.new(project: project, user_email: "existing.user@test.com") } it "returns true" do expect(membership.save_and_update_account_membership).to be_truthy end it "creates account membership" do expect { membership.save_and_update_account_membership }.to change(AccountAuth, :count).by(1) account_auth = AccountAuth.last expect(account_auth.account).to eq project.account expect(account_auth.user).to eq user end it "creates project membership" do expect { membership.save_and_update_account_membership }.to change(ProjectMembership, :count).by(1) expect(membership.project).to eq project expect(membership.user).to eq user end end context "when user exists and has account access" do let!(:user) { create(:user, email: "existing.user@test.com", accounts: [project.account]) } let(:membership) { ProjectMembership.new(project: project, user_email: "existing.user@test.com") } it "returns true" do expect(membership.save_and_update_account_membership).to be_truthy end it "creates project membership" do expect { membership.save_and_update_account_membership }.to change(ProjectMembership, :count).by(1) expect(membership.project).to eq project expect(membership.user).to eq user end end shared_examples "creates no records and returns false" do it "returns false" do expect(membership.save_and_update_account_membership).to be_falsey end it "does not create new records" do expect { membership.save_and_update_account_membership }. to change(ProjectMembership, :count).by(0). and change(AccountAuth, :count).by(0). and change(User, :count).by(0) end end context "when user cannot be saved" do let(:membership) { ProjectMembership.new(project: project, user_email: "new.user@test.com") } before do allow_any_instance_of(Oath::Services::SignUp).to receive(:perform).and_return(build(:user)) allow_any_instance_of(User).to receive(:save).and_return(false) end include_examples "creates no records and returns false" end context "when account auth cannot be saved" do let(:membership) { ProjectMembership.new(project: project, user_email: "new.user@test.com") } before do allow_any_instance_of(AccountAuth).to receive(:save).and_return(false) end include_examples "creates no records and returns false" end context "when project membership cannot be saved" do let(:membership) { ProjectMembership.new(project: project, user_email: "new.user@test.com") } before do allow_any_instance_of(ProjectMembership).to receive(:save).and_return(false) end include_examples "creates no records and returns false" end end end