Skip to content

Commit

Permalink
(fix) Apply requested PR changes; all specs passing
Browse files Browse the repository at this point in the history
  • Loading branch information
ojbucao committed Dec 18, 2024
1 parent 6024452 commit 3815598
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 98 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module AccreditedRepresentativePortal
class PowerOfAttorneyForm < ApplicationRecord
belongs_to :power_of_attorney_request,
class_name: 'AccreditedRepresentativePortal::PowerOfAttorneyRequest',
inverse_of: :form
inverse_of: :power_of_attorney_form

has_kms_key

Expand All @@ -15,10 +15,6 @@ class PowerOfAttorneyForm < ApplicationRecord
blind_index :zipcode

# Validations
validates :power_of_attorney_request_id, uniqueness: true
validates :data_ciphertext, presence: true
validates :city_bidx, presence: true, length: { is: 44 }
validates :state_bidx, presence: true, length: { is: 44 }
validates :zipcode_bidx, presence: true, length: { is: 44 }
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,14 @@

module AccreditedRepresentativePortal
class PowerOfAttorneyRequest < ApplicationRecord
belongs_to :claimant,
class_name: 'UserAccount'
belongs_to :claimant, class_name: 'UserAccount'

has_one :form,
has_one :power_of_attorney_form,
class_name: 'AccreditedRepresentativePortal::PowerOfAttorneyForm',
inverse_of: :power_of_attorney_request,
dependent: :destroy
inverse_of: :power_of_attorney_request

has_one :resolution,
class_name: 'AccreditedRepresentativePortal::PowerOfAttorneyRequestResolution',
inverse_of: :power_of_attorney_request,
dependent: :destroy

# Validations
validates :created_at, presence: true
inverse_of: :power_of_attorney_request
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@

module AccreditedRepresentativePortal
class PowerOfAttorneyRequestDecision < ApplicationRecord
include PowerOfAttorneyRequestResolution::Resolving

self.inheritance_column = nil

belongs_to :creator,
class_name: 'UserAccount'

has_one :power_of_attorney_request_resolution,
as: :resolving,
inverse_of: :resolving,
dependent: :destroy

validates :type, presence: true, length: { maximum: 255 }
validates :type, presence: true
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@

module AccreditedRepresentativePortal
class PowerOfAttorneyRequestExpiration < ApplicationRecord
has_one :power_of_attorney_request_resolution,
as: :resolving,
inverse_of: :resolving,
dependent: :destroy

# Validations
validates :id, presence: true
include PowerOfAttorneyRequestResolution::Resolving
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,20 @@ class PowerOfAttorneyRequestResolution < ApplicationRecord
'AccreditedRepresentativePortal::PowerOfAttorneyRequestDecision'
].freeze

delegated_type :resolving, types: RESOLVING_TYPES, dependent: :destroy, optional: true
delegated_type :resolving, types: RESOLVING_TYPES

has_kms_key

has_encrypted :reason, key: :kms_key, **lockbox_options

# Validations
validates :power_of_attorney_request_id, uniqueness: true
validates :resolving_type, presence: true, inclusion: { in: RESOLVING_TYPES, allow_nil: true }
validates :resolving_id, presence: true, if: -> { resolving_type.present? }
validates :created_at, presence: true
validates :resolving_type, presence: true, inclusion: { in: RESOLVING_TYPES }

module Resolving
extend ActiveSupport::Concern

included do
has_one :power_of_attorney_request_resolution, as: :resolving
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,34 @@
resolving_type { 'AccreditedRepresentativePortal::PowerOfAttorneyRequestDecision' }
resolving { create(:power_of_attorney_request_decision) }
end

trait :with_invalid_type do
resolving_type { 'AccreditedRepresentativePortal::InvalidType' }
resolving { AccreditedRepresentativePortal::InvalidType.new }
end
end
end

module AccreditedRepresentativePortal
class InvalidType
def method_missing(_method, *_args) = self

def respond_to_missing?(_method, _include_private = false) = true

def id = nil

def self.method_missing(_method, *_args) = NullObject.new

def self.respond_to_missing?(_method, _include_private = false) = true
end

class NullObject
def method_missing(_method, *_args) = self

def respond_to_missing?(*) = true

def nil? = true

def to_s = ''
end
end
Original file line number Diff line number Diff line change
@@ -1,25 +1,14 @@
# frozen_string_literal: true

require 'rails_helper'
require_relative '../../rails_helper'

RSpec.describe AccreditedRepresentativePortal::PowerOfAttorneyForm, type: :model do
describe 'associations' do
it { is_expected.to belong_to(:power_of_attorney_request) }
end

describe 'validations' do
it 'validates uniqueness of power_of_attorney_request_id' do
form = create(:power_of_attorney_form)
duplicate_form = build(:power_of_attorney_form, power_of_attorney_request: form.power_of_attorney_request)

expect(duplicate_form).not_to be_valid
expect(duplicate_form.errors[:power_of_attorney_request_id]).to include('has already been taken')
end

it { is_expected.to validate_presence_of(:data_ciphertext) }
it { is_expected.to validate_length_of(:city_bidx).is_equal_to(44) }
it { is_expected.to validate_length_of(:state_bidx).is_equal_to(44) }
it { is_expected.to validate_length_of(:zipcode_bidx).is_equal_to(44) }
end

describe 'creation' do
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,10 @@
# frozen_string_literal: true

require 'rails_helper'
require_relative '../../rails_helper'

RSpec.describe AccreditedRepresentativePortal::PowerOfAttorneyRequestDecision, type: :model do
describe 'associations' do
it { is_expected.to belong_to(:creator).class_name('UserAccount') }
it { is_expected.to have_one(:power_of_attorney_request_resolution).dependent(:destroy) }
end

describe 'validations' do
it { is_expected.to validate_presence_of(:type) }
it { is_expected.to validate_length_of(:type).is_at_most(255) }
end

describe 'creation' do
it 'creates a valid record' do
user = UserAccount.create!(id: SecureRandom.uuid)
decision = build(:power_of_attorney_request_decision, creator: user)
expect(decision).to be_valid
end
it { is_expected.to have_one(:power_of_attorney_request_resolution) }
end
end
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# frozen_string_literal: true

require 'rails_helper'
require_relative '../../rails_helper'

RSpec.describe AccreditedRepresentativePortal::PowerOfAttorneyRequestExpiration, type: :model do
describe 'associations' do
it { is_expected.to have_one(:power_of_attorney_request_resolution).dependent(:destroy) }
it { is_expected.to have_one(:power_of_attorney_request_resolution) }
end

describe 'validations' do
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# frozen_string_literal: true

require 'rails_helper'
require_relative '../../rails_helper'

RSpec.describe AccreditedRepresentativePortal::PowerOfAttorneyRequestResolution, type: :model do
mod = AccreditedRepresentativePortal
RSpec.describe mod::PowerOfAttorneyRequestResolution, type: :model do
describe 'associations' do
let(:power_of_attorney_request) { create(:power_of_attorney_request) }

Expand Down Expand Up @@ -35,41 +36,115 @@
end
end

describe 'validations' do
subject { create(:power_of_attorney_request_resolution, :with_decision) }

it { is_expected.to validate_uniqueness_of(:power_of_attorney_request_id).ignoring_case_sensitivity }
it { is_expected.to validate_inclusion_of(:resolving_type).in_array(described_class::RESOLVING_TYPES) }

it 'validates presence of resolving_id if resolving_type is present' do
resolution = build(:power_of_attorney_request_resolution, resolving_type: described_class::RESOLVING_TYPES.first,
resolving_id: nil)
expect(resolution).not_to be_valid
expect(resolution.errors[:resolving_id]).to include("can't be blank")
end
end

describe 'delegated_type resolving' do
it 'is valid with expiration resolving' do
resolution = create(:power_of_attorney_request_resolution, :with_expiration)
expect(resolution).to be_valid
expect(resolution.resolving).to be_a(AccreditedRepresentativePortal::PowerOfAttorneyRequestExpiration)
expect(resolution.resolving).to be_a(mod::PowerOfAttorneyRequestExpiration)
end

it 'is valid with decision resolving' do
resolution = create(:power_of_attorney_request_resolution, :with_decision)
expect(resolution).to be_valid
expect(resolution.resolving).to be_a(AccreditedRepresentativePortal::PowerOfAttorneyRequestDecision)
expect(resolution.resolving).to be_a(mod::PowerOfAttorneyRequestDecision)
end

it 'is invalid with null resolving_type and resolving_id' do
resolution = build(:power_of_attorney_request_resolution, resolving_type: nil, resolving_id: nil)
expect(resolution).not_to be_valid
end

it 'is invalid with invalid resolving_type' do
resolution = build(:power_of_attorney_request_resolution, resolving_type: 'invalid_type')
it 'does not allow invalid resolving_type values' do
resolution = build(:power_of_attorney_request_resolution, :with_invalid_type)
resolution.resolving_type = 'AccreditedRepresentativePortal::InvalidType'

expect(resolution).not_to be_valid
expect(resolution.errors[:resolving_type]).to include('is not included in the list')
end
end

describe 'heterogeneous list behavior' do
it 'conveniently returns heterogeneous lists' do
travel_to Time.zone.parse('2024-11-25T09:46:24Z') do
creator = create(:user_account)

ids = []

# Persisted resolving records
decision_acceptance = mod::PowerOfAttorneyRequestDecision.create!(
type: 'acceptance',
creator: creator
)
decision_declination = mod::PowerOfAttorneyRequestDecision.create!(
type: 'declination',
creator: creator
)
expiration = mod::PowerOfAttorneyRequestExpiration.create!

# Associate resolving records
ids << described_class.create!(
power_of_attorney_request: create(:power_of_attorney_request),
resolving: decision_acceptance,
encrypted_kms_key: SecureRandom.hex(16),
created_at: Time.current
).id

ids << described_class.create!(
power_of_attorney_request: create(:power_of_attorney_request),
resolving: decision_declination,
encrypted_kms_key: SecureRandom.hex(16),
created_at: Time.current
).id

ids << described_class.create!(
power_of_attorney_request: create(:power_of_attorney_request),
resolving: expiration,
encrypted_kms_key: SecureRandom.hex(16),
created_at: Time.current
).id

resolutions = described_class.includes(:resolving).find(ids)

# Serialize for comparison
actual =
resolutions.map do |resolution|
serialized =
case resolution.resolving
when mod::PowerOfAttorneyRequestDecision
{
type: 'decision',
decision_type: resolution.resolving.type
}
when mod::PowerOfAttorneyRequestExpiration
{
type: 'expiration'
}
end

serialized.merge!(
created_at: resolution.created_at.iso8601
)
end

expect(actual).to eq(
[
{
type: 'decision',
decision_type: 'acceptance',
created_at: '2024-11-25T09:46:24Z'
},
{
type: 'decision',
decision_type: 'declination',
created_at: '2024-11-25T09:46:24Z'
},
{
type: 'expiration',
created_at: '2024-11-25T09:46:24Z'
}
]
)
end
end
end
end
Original file line number Diff line number Diff line change
@@ -1,23 +1,11 @@
# frozen_string_literal: true

require 'rails_helper'
require_relative '../../rails_helper'

RSpec.describe AccreditedRepresentativePortal::PowerOfAttorneyRequest, type: :model do
describe 'associations' do
it { is_expected.to belong_to(:claimant).class_name('UserAccount') }
it { is_expected.to have_one(:form).dependent(:destroy) }
it { is_expected.to have_one(:resolution).dependent(:destroy) }
end

describe 'validations' do
it { is_expected.to validate_presence_of(:created_at) }
end

describe 'creation' do
it 'creates a valid record' do
user = UserAccount.create!(id: SecureRandom.uuid)
request = build(:power_of_attorney_request, claimant: user)
expect(request).to be_valid
end
it { is_expected.to have_one(:power_of_attorney_form) }
it { is_expected.to have_one(:resolution) }
end
end

0 comments on commit 3815598

Please sign in to comment.