require "rails_helper"

describe ProjectPolicy do
  subject { described_class }

  let(:account) { build(:account) }
  let(:project) { build(:project, account: account) }
  let(:user_context) { build(:user_context, user: user, account: account) }

  shared_examples "requires project membership" do
    context "without a project membership" do
      let(:project) { create(:project, members: [], account: account) }

      it { is_expected.not_to permit(user_context, project) }
    end

    context "with a project membership" do
      let(:project) { create(:project, members: user, account: account) }

      it { is_expected.to permit(user_context, project) }
    end
  end

  context "for an associate" do
    let(:user) { create(:user, :associate, primary_account: account) }

    permissions :index? do
      it { is_expected.to permit(user_context, project) }
    end
    permissions :create? do
      it { is_expected.not_to permit(user_context, project) }
    end
    permissions :show? do
      include_examples "requires project membership"
    end
    permissions :update? do
      it { is_expected.not_to permit(user_context, project) }
    end
    permissions :destroy? do
      it { is_expected.not_to permit(user_context, project) }
    end
  end

  context "for a manager" do
    let(:user) { create(:user, :manager, primary_account: account) }

    permissions :index? do
      it { is_expected.to permit(user_context, project) }
    end
    permissions :create? do
      it { is_expected.not_to permit(user_context, project) }
    end
    permissions :show? do
      include_examples "requires project membership"
    end
    permissions :update? do
      it { is_expected.to permit(user_context, project) }
    end
    permissions :destroy? do
      it { is_expected.not_to permit(user_context, project) }
    end
  end

  context "for an account manager" do
    let(:user) { create(:user, :account_manager, primary_account: account) }

    permissions :index? do
      it { is_expected.to permit(user_context, project) }
    end
    permissions :create? do
      it { is_expected.to permit(user_context, project) }
    end
    permissions :show? do
      it { is_expected.to permit(user_context, project) }
    end
    permissions :update? do
      it { is_expected.to permit(user_context, project) }
    end
    permissions :destroy? do
      it { is_expected.not_to permit(user_context, project) }
    end
  end

  permissions ".scope" do
    let!(:member_project) { create(:project, name: "Member Project", members: user, account: account) }
    let!(:non_member_project) { create(:project, name: "Non-Member Project", account: account) }
    let!(:outside_project) { create(:project, name: "Outside Project", account: build(:account)) }

    subject { Pundit.policy_scope!(user_context, Project) }

    context "for an associate" do
      let(:user) { create(:user, :associate, primary_account: account) }

      it { is_expected.to include(member_project) }
      it { is_expected.not_to include(non_member_project) }
      it { is_expected.not_to include(outside_project) }
    end

    context "for a manager" do
      let(:user) { create(:user, :manager, primary_account: account) }

      it { is_expected.to include(member_project) }
      it { is_expected.not_to include(non_member_project) }
      it { is_expected.not_to include(outside_project) }
    end

    context "for an account manager" do
      let(:user) { create(:user, :account_manager, primary_account: account) }

      it { is_expected.to include(member_project) }
      it { is_expected.to include(non_member_project) }
      it { is_expected.not_to include(outside_project) }
    end
  end
end
