diff --git a/core/app/models/spree/promotion_code.rb b/core/app/models/spree/promotion_code.rb index fbd37349b1b..640ed4ad8fd 100644 --- a/core/app/models/spree/promotion_code.rb +++ b/core/app/models/spree/promotion_code.rb @@ -5,12 +5,12 @@ class Spree::PromotionCode < Spree::Base belongs_to :promotion_code_batch, class_name: "Spree::PromotionCodeBatch", optional: true has_many :adjustments + before_validation :normalize_code + validates :value, presence: true, uniqueness: { allow_blank: true, case_sensitive: true } validates :promotion, presence: true validate :promotion_not_apply_automatically, on: :create - before_save :normalize_code - self.whitelisted_ransackable_attributes = ['value'] # Whether the promotion code has exceeded its usage restrictions diff --git a/core/spec/models/spree/promotion_code_spec.rb b/core/spec/models/spree/promotion_code_spec.rb index c838007ac5f..d2f6e21d79b 100644 --- a/core/spec/models/spree/promotion_code_spec.rb +++ b/core/spec/models/spree/promotion_code_spec.rb @@ -8,22 +8,54 @@ describe '#normalize_code' do let(:promotion) { create(:promotion, code: code) } - let(:promotion_code) { promotion.codes.first } before { subject } - context 'with mixed case' do - let(:code) { 'NewCoDe' } + context 'when no other code with the same value exists' do + let(:promotion_code) { promotion.codes.first } - it 'downcases the value before saving' do - expect(promotion_code.value).to eq('newcode') + context 'with mixed case' do + let(:code) { 'NewCoDe' } + + it 'downcases the value before saving' do + expect(promotion_code.value).to eq('newcode') + end + end + + context 'with extra spacing' do + let(:code) { ' new code ' } + + it 'removes surrounding whitespace' do + expect(promotion_code.value).to eq 'new code' + end end end - context 'with extra spacing' do - let(:code) { ' new code ' } - it 'removes surrounding whitespace' do - expect(promotion_code.value).to eq 'new code' + context 'when another code with the same value exists' do + let(:promotion_code) { promotion.codes.build(value: code) } + + context 'with mixed case' do + let(:code) { 'NewCoDe' } + + it 'does not save the record and marks it as invalid' do + expect(promotion_code.valid?).to eq false + + expect(promotion_code.errors.messages[:value]).to contain_exactly( + 'has already been taken' + ) + end + end + + context 'with extra spacing' do + let(:code) { ' new code ' } + + it 'does not save the record and marks it as invalid' do + expect(promotion_code.valid?).to eq false + + expect(promotion_code.errors.messages[:value]).to contain_exactly( + 'has already been taken' + ) + end end end end