Commit 79620de

mo <mo.khan@gmail.com>
2019-01-10 04:40:52
start to add array validations
1 parent 2bcb193
Changed files (3)
lib/scim/kit/v2/attribute.rb
@@ -13,6 +13,7 @@ module Scim
 
         validate :presence_of_value, if: proc { |x| x.type.required }
         validate :inclusion_of_value, if: proc { |x| x.type.canonical_values }
+        validate :validate_array, if: proc { |x| x.type.multi_valued }
 
         def initialize(type:, value: nil)
           @type = type
@@ -37,6 +38,12 @@ module Scim
 
           errors.add(type.name, I18n.t('errors.messages.inclusion'))
         end
+
+        def validate_array
+          return if _value.respond_to?(:each) && _value.all? { |x| type.valid?(x) }
+
+          errors.add(type.name, I18n.t('errors.messages.invalid'))
+        end
       end
     end
   end
lib/scim/kit/v2/attribute_type.rb
@@ -6,6 +6,7 @@ module Scim
       # Represents a scim Attribute type
       class AttributeType
         include Templatable
+        BASE64_FORMAT = %r(\A([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?\Z).freeze
         DATATYPES = {
           string: 'string',
           boolean: 'boolean',
@@ -23,6 +24,13 @@ module Scim
           datetime: ->(x) { x.is_a?(::String) ? DateTime.parse(x) : x },
           binary: ->(x) { Base64.strict_encode64(x) }
         }.freeze
+        VALIDATIONS = {
+          string: ->(x) { x.is_a?(String) },
+          decimal: ->(x) { x.is_a?(Float) },
+          integer: ->(x) { x&.integer? },
+          datetime: ->(x) { x.is_a?(DateTime) },
+          binary: ->(x) { x.is_a?(String) && !!x.match(BASE64_FORMAT) }
+        }
         attr_accessor :canonical_values
         attr_accessor :case_exact
         attr_accessor :description
@@ -89,6 +97,10 @@ module Scim
           coercion ? coercion.call(value) : value
         end
 
+        def valid?(value)
+          VALIDATIONS[type]&.call(value)
+        end
+
         private
 
         def string?
spec/scim/kit/v2/attribute_spec.rb
@@ -13,6 +13,7 @@ RSpec.describe Scim::Kit::V2::Attribute do
 
       specify { expect(subject._value).to eql(user_name) }
       specify { expect(subject.as_json[:userName]).to eql(user_name) }
+      specify { expect(subject).to be_valid }
     end
 
     context 'when multiple values are allowed' do
@@ -22,6 +23,28 @@ RSpec.describe Scim::Kit::V2::Attribute do
       end
 
       specify { expect(subject._value).to match_array(%w[superman batman]) }
+
+      context "when a single value is provided" do
+        before do
+          type.multi_valued = true
+          subject._value = 'batman'
+          subject.valid?
+        end
+
+        specify { expect(subject).not_to be_valid }
+        specify { expect(subject.errors[:user_name]).to be_present }
+      end
+
+      context "when the wrong type is used" do
+        before do
+          type.multi_valued = true
+          subject._value = [1.0, 2.0]
+          subject.valid?
+        end
+
+        specify { expect(subject).not_to be_valid }
+        specify { expect(subject.errors[:user_name]).to be_present }
+      end
     end
 
     context 'when integer' do