semantic_attributes 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +99 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README +54 -0
  6. data/Rakefile +37 -0
  7. data/gist.rdoc +208 -0
  8. data/lib/active_record/validation_recursion_control.rb +33 -0
  9. data/lib/core_ext/class.rb +14 -0
  10. data/lib/predicates/aliased.rb +22 -0
  11. data/lib/predicates/association.rb +43 -0
  12. data/lib/predicates/base.rb +93 -0
  13. data/lib/predicates/blacklisted.rb +23 -0
  14. data/lib/predicates/domain.rb +31 -0
  15. data/lib/predicates/email.rb +42 -0
  16. data/lib/predicates/enumerated.rb +23 -0
  17. data/lib/predicates/hex_color.rb +24 -0
  18. data/lib/predicates/length.rb +71 -0
  19. data/lib/predicates/number.rb +104 -0
  20. data/lib/predicates/pattern.rb +22 -0
  21. data/lib/predicates/phone_number.rb +62 -0
  22. data/lib/predicates/required.rb +22 -0
  23. data/lib/predicates/same_as.rb +17 -0
  24. data/lib/predicates/size.rb +2 -0
  25. data/lib/predicates/time.rb +43 -0
  26. data/lib/predicates/unique.rb +71 -0
  27. data/lib/predicates/url.rb +62 -0
  28. data/lib/predicates/usa_state.rb +87 -0
  29. data/lib/predicates/usa_zip_code.rb +25 -0
  30. data/lib/predicates/whitelisted.rb +2 -0
  31. data/lib/predicates.rb +3 -0
  32. data/lib/semantic_attributes/attribute.rb +46 -0
  33. data/lib/semantic_attributes/attribute_formats.rb +67 -0
  34. data/lib/semantic_attributes/locale/en.yml +31 -0
  35. data/lib/semantic_attributes/predicates.rb +170 -0
  36. data/lib/semantic_attributes/set.rb +40 -0
  37. data/lib/semantic_attributes/version.rb +3 -0
  38. data/lib/semantic_attributes.rb +37 -0
  39. data/semantic_attributes.gemspec +29 -0
  40. data/test/db/database.yml +3 -0
  41. data/test/db/models.rb +38 -0
  42. data/test/db/schema.rb +33 -0
  43. data/test/fixtures/addresses.yml +15 -0
  44. data/test/fixtures/roles.yml +4 -0
  45. data/test/fixtures/roles_users.yml +6 -0
  46. data/test/fixtures/services.yml +6 -0
  47. data/test/fixtures/subscriptions.yml +16 -0
  48. data/test/fixtures/users.yml +20 -0
  49. data/test/test_helper.rb +67 -0
  50. data/test/unit/active_record_predicates_test.rb +88 -0
  51. data/test/unit/attribute_formats_test.rb +40 -0
  52. data/test/unit/inheritance_test.rb +23 -0
  53. data/test/unit/predicates/aliased_test.rb +17 -0
  54. data/test/unit/predicates/association_predicate_test.rb +51 -0
  55. data/test/unit/predicates/base_test.rb +53 -0
  56. data/test/unit/predicates/blacklisted_predicate_test.rb +28 -0
  57. data/test/unit/predicates/domain_predicate_test.rb +27 -0
  58. data/test/unit/predicates/email_test.rb +82 -0
  59. data/test/unit/predicates/enumerated_predicate_test.rb +22 -0
  60. data/test/unit/predicates/hex_color_predicate_test.rb +29 -0
  61. data/test/unit/predicates/length_predicate_test.rb +85 -0
  62. data/test/unit/predicates/number_test.rb +109 -0
  63. data/test/unit/predicates/pattern_predicate_test.rb +29 -0
  64. data/test/unit/predicates/phone_number_predicate_test.rb +41 -0
  65. data/test/unit/predicates/required_predicate_test.rb +13 -0
  66. data/test/unit/predicates/same_as_predicate_test.rb +19 -0
  67. data/test/unit/predicates/time_test.rb +49 -0
  68. data/test/unit/predicates/unique_test.rb +58 -0
  69. data/test/unit/predicates/url_test.rb +86 -0
  70. data/test/unit/predicates/usa_state_test.rb +31 -0
  71. data/test/unit/predicates/usa_zip_code_test.rb +42 -0
  72. data/test/unit/semantic_attribute_test.rb +18 -0
  73. data/test/unit/semantic_attributes_test.rb +29 -0
  74. data/test/unit/validations_test.rb +121 -0
  75. metadata +235 -0
@@ -0,0 +1,29 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
2
+
3
+ class PatternPredicateTest < SemanticAttributes::TestCase
4
+ def setup
5
+ @predicate = Predicates::Pattern.new(:foo)
6
+ end
7
+
8
+ def test_regexp_pattern
9
+ @predicate.like = /bar$/
10
+
11
+ assert @predicate.validate('foobar', nil)
12
+ assert @predicate.validate(:foobar, nil)
13
+ assert !@predicate.validate('foobario', nil)
14
+ end
15
+
16
+ def test_string_pattern
17
+ @predicate.like = 'bar'
18
+
19
+ assert @predicate.validate('foobar', nil)
20
+ assert @predicate.validate(:bar, nil)
21
+ end
22
+
23
+ def test_line_breaks
24
+ @predicate.like = /^hello world$/
25
+ assert @predicate.validate("malicious\nhello world\ntext", nil)
26
+ @predicate.like = /\Ahello world\Z/
27
+ assert !@predicate.validate("malicious\nhello world\ntext", nil)
28
+ end
29
+ end
@@ -0,0 +1,41 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
2
+
3
+ class PhoneNumberPredicateTest < SemanticAttributes::TestCase
4
+ def setup
5
+ @predicate = Predicates::PhoneNumber.new(:foo)
6
+ end
7
+
8
+ def test_north_american_bias
9
+ assert_equal 1, @predicate.implied_country_code, 'default implied country code is 1 (north america)'
10
+ end
11
+
12
+ def test_to_human
13
+ assert_equal '(222) 333-4444', @predicate.to_human('+12223334444'), 'NANP human format'
14
+ assert_equal '753', @predicate.to_human('753'), 'unknown formats untouched'
15
+ end
16
+
17
+ def test_validate_nanp
18
+ assert !@predicate.validate('12223334444', nil), 'requires country code indicator (+)'
19
+ assert @predicate.validate('+12223334444', nil), 'requires country code indicator (+)'
20
+
21
+ assert !@predicate.validate('+11223334444', nil), 'first digit of area code may not be 1'
22
+ assert !@predicate.validate('+12923334444', nil), 'second digit of area code may not be 9'
23
+ assert !@predicate.validate('+12221334444', nil), 'first digit of exchange code may not be 1'
24
+ assert !@predicate.validate('+1222333444', nil), 'must be 11 characters long'
25
+
26
+ assert !@predicate.validate('+12225550155', nil), 'restricted 555 code'
27
+ assert @predicate.validate('+12225550099', nil), 'allowed 555 code'
28
+ assert @predicate.validate('+12225550200', nil), 'allowed 555 code'
29
+ end
30
+
31
+ def test_normalize
32
+ @predicate.implied_country_code = 99
33
+
34
+ assert_equal '+12223334444', @predicate.normalize('12223334444'), 'recognizes north american country code without +'
35
+ assert_equal '+12223334444', @predicate.normalize('+12223334444'), 'leaves country codes alone if they exist'
36
+ assert_equal '+992223334444', @predicate.normalize('2223334444'), 'adds implied country code'
37
+ assert_equal '+12223334444', @predicate.normalize('1 (222) 333.4444'), 'ignores various formatting characters'
38
+ assert_equal '+992223334444', @predicate.normalize('222typo333oops4444'), 'ignores non-numeric characters'
39
+ assert_equal '', @predicate.normalize(''), 'leaves blanks intact'
40
+ end
41
+ end
@@ -0,0 +1,13 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
2
+
3
+ class RequiredPredicateTest < SemanticAttributes::TestCase
4
+ def setup
5
+ @predicate = Predicates::Required.new(:foo)
6
+ end
7
+
8
+ def test_allow_empty
9
+ assert !@predicate.allow_empty?
10
+ @predicate.or_empty = false
11
+ assert !@predicate.allow_empty?
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
2
+
3
+ class SameAsPredicateTest < SemanticAttributes::TestCase
4
+ def setup
5
+ @predicate = Predicates::SameAs.new(:foo)
6
+ end
7
+
8
+ def test_validation
9
+ @predicate.method = :bar
10
+
11
+ record = mock()
12
+ record.stubs(:bar).returns("something")
13
+
14
+ assert @predicate.validate('something', record)
15
+ assert !@predicate.validate('something else', record)
16
+ assert !@predicate.validate(nil, record)
17
+ assert !@predicate.validate(5, record)
18
+ end
19
+ end
@@ -0,0 +1,49 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
2
+
3
+ class TimePredicateTest < SemanticAttributes::TestCase
4
+ def setup
5
+ @predicate = Predicates::Time.new(:foo)
6
+ end
7
+
8
+ def test_default_validation
9
+ assert !@predicate.validate('2007-07-19 00:00:00', nil), 'value may not be a string, even if string parses'
10
+ assert !@predicate.validate(1184817600, nil), 'value must not be a timestamp'
11
+ assert @predicate.validate(Time.parse('2007-07-19 00:00:00'), nil)
12
+ end
13
+
14
+ def test_validation_with_before
15
+ @predicate.before = '2007-07-19 00:00:00'
16
+ assert_equal Time.parse('2007-07-19 00:00:00'), @predicate.before
17
+
18
+ assert @predicate.validate(Time.parse('2007-07-18 23:59:00'), nil), 'may be earlier'
19
+ assert !@predicate.validate(Time.parse('2007-07-19 00:00:00'), nil), 'may not be equal'
20
+ assert !@predicate.validate(Time.parse('2007-07-19 00:00:01'), nil), 'may not be after'
21
+ end
22
+
23
+ def test_validation_with_after
24
+ @predicate.after = '2007-07-19 00:00:00'
25
+ assert_equal Time.parse('2007-07-19 00:00:00'), @predicate.after
26
+
27
+ assert !@predicate.validate(Time.parse('2007-07-18 23:59:00'), nil), 'may not be before'
28
+ assert !@predicate.validate(Time.parse('2007-07-19 00:00:00'), nil), 'may not be equal'
29
+ assert @predicate.validate(Time.parse('2007-07-19 00:00:01'), nil), 'may be afterwards'
30
+ end
31
+
32
+ def test_validation_with_before_and_after
33
+ @predicate.before = '2007-01-01 00:00:00'
34
+ @predicate.after = '2006-01-01 00:00:00'
35
+
36
+ assert !@predicate.validate(Time.parse('2005-01-01 00:00:00'), nil), 'may not be earlier'
37
+ assert @predicate.validate(Time.parse('2006-06-01 00:00:00'), nil), 'may be inbetween'
38
+ assert !@predicate.validate(Time.parse('2008-01-01 00:00:00'), nil), 'may not be after'
39
+ end
40
+
41
+ def test_validation_with_distance
42
+ @predicate.distance = (-1.hour)..(1.hour)
43
+ assert !@predicate.validate(61.minutes.ago, nil)
44
+ assert @predicate.validate(59.minutes.ago, nil)
45
+ assert @predicate.validate(Time.now, nil)
46
+ assert @predicate.validate(Time.now + 59.minutes, nil)
47
+ assert !@predicate.validate(Time.now + 61.minutes, nil)
48
+ end
49
+ end
@@ -0,0 +1,58 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
2
+
3
+ class UniquePredicateTest < SemanticAttributes::TestCase
4
+ def setup
5
+ User.stub_semantics_with(:login => :unique)
6
+ @predicate = User.semantic_attributes[:login].get(:unique)
7
+
8
+ @fred = User.new(:first_name => 'fred', :last_name => 'flat')
9
+ end
10
+
11
+ def test_defaults
12
+ assert_equal false, @predicate.case_sensitive, 'case insensitive by default'
13
+ assert_equal [], @predicate.scope, 'default scope is empty array'
14
+ end
15
+
16
+ def test_uniqueness_validation_scoping
17
+ assert !@predicate.validate(users(:bob).login, @fred)
18
+ @predicate.scope = :last_name
19
+ assert @predicate.validate(users(:bob).login, @fred), "when scoped, it becomes valid"
20
+ end
21
+
22
+ def test_case_sensitive_uniqueness_validation
23
+ @predicate.case_sensitive = true
24
+
25
+ assert !@predicate.validate(users(:bob).login, @fred), "case match means not unique"
26
+ assert @predicate.validate(users(:bob).login.upcase, @fred), "case mismatch means unique"
27
+ end
28
+
29
+ def test_case_insensitive_uniqueness_validation
30
+ @predicate.case_sensitive = false
31
+
32
+ assert !@predicate.validate(users(:bob).login, @fred), "case match means not unique"
33
+ assert !@predicate.validate(users(:bob).login.upcase, @fred), "case mismatch is still not unique"
34
+ end
35
+
36
+ def test_uniqueness_validation_excludes_self
37
+ @fred.update_attribute(:login, 'fred')
38
+
39
+ assert @predicate.validate(@fred.login, @fred), "still valid after being saved"
40
+ assert !@predicate.validate(users(:bob).login, @fred), "but still not valid when duplicating a *different* record"
41
+ end
42
+
43
+ def test_uniqueness_of_numbers
44
+ Subscription.stub_semantics_with(:user_id => :unique)
45
+
46
+ bobs_second_subscription = Subscription.new(:user => users(:bob), :service => services(:premium))
47
+ assert !bobs_second_subscription.valid?
48
+ assert bobs_second_subscription.errors[:user_id]
49
+ end
50
+
51
+ def test_case_insensitive_is_non_destructive
52
+ @predicate.case_sensitive = false
53
+ @fred.update_attribute(:login, "Fred")
54
+
55
+ @predicate.validate(@fred.login, @fred)
56
+ assert_equal "Fred", @fred.login, "attribute value was not changed by validate()"
57
+ end
58
+ end
@@ -0,0 +1,86 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
2
+
3
+ class UrlPredicateTest < SemanticAttributes::TestCase
4
+ def setup
5
+ @predicate = Predicates::Url.new(:foo)
6
+ end
7
+
8
+ def test_ip_addresses
9
+ assert_equal true, @predicate.allow_ip_address, 'default allow_ip_address is true'
10
+ assert @predicate.validate('http://192.168.0.10', nil), 'ip address'
11
+ assert @predicate.validate('http://www.example.com', nil), 'basic url still works'
12
+
13
+ @predicate.allow_ip_address = false
14
+ assert !@predicate.validate('http://192.168.0.10', nil), 'ip address'
15
+ assert @predicate.validate('http://www.example.com', nil), 'basic url still works'
16
+ end
17
+
18
+ def test_schemes
19
+ assert_equal ['http', 'https'], @predicate.schemes, 'default allowed schemes'
20
+
21
+ assert @predicate.validate('http://example.com/', nil)
22
+ assert !@predicate.validate('ftp://example.com/', nil)
23
+
24
+ @predicate.schemes = ['ftp']
25
+
26
+ assert !@predicate.validate('http://example.com/', nil)
27
+ assert @predicate.validate('ftp://example.com/', nil)
28
+ end
29
+
30
+ def test_domains
31
+ assert_equal nil, @predicate.domains, 'default allows any domain'
32
+
33
+ assert @predicate.validate('http://example.com', nil)
34
+ assert @predicate.validate('http://example.co.uk', nil)
35
+ assert @predicate.validate('http://example.xyz', nil)
36
+ assert !@predicate.validate('http://example', nil)
37
+ assert !@predicate.validate('http://example.', nil)
38
+ assert @predicate.validate('http://127.0.0.1', nil)
39
+
40
+ @predicate.domains = ['com', 'net', 'org']
41
+
42
+ assert @predicate.validate('http://example.com', nil)
43
+ assert !@predicate.validate('http://example.co.uk', nil)
44
+ assert !@predicate.validate('http://example.xyz', nil)
45
+ assert !@predicate.validate('http://example', nil)
46
+ assert !@predicate.validate('http://example.', nil)
47
+ assert !@predicate.validate('http://127.0.0.1', nil)
48
+ end
49
+
50
+ def test_ports
51
+ assert_equal nil, @predicate.ports, 'default allows any port'
52
+
53
+ assert @predicate.validate('http://example.com', nil)
54
+ assert @predicate.validate('http://example.com:80', nil)
55
+ assert @predicate.validate('http://example.com:443', nil)
56
+
57
+ @predicate.ports = [nil, 80]
58
+
59
+ assert @predicate.validate('http://example.com', nil)
60
+ assert @predicate.validate('http://example.com:80', nil)
61
+ assert !@predicate.validate('http://example.com:443', nil)
62
+ end
63
+
64
+ def test_bad_url
65
+ assert !@predicate.validate('http:\\\\example.com\\', nil)
66
+ assert !@predicate.validate('example.com', nil), 'human format does not validate'
67
+
68
+ assert_equal 'http:\\\\example.com\\', @predicate.normalize('http:\\\\example.com\\'), 'malformed human format is preserved'
69
+ end
70
+
71
+ def test_implied_scheme
72
+ assert_equal 'http', @predicate.implied_scheme
73
+
74
+ assert_equal 'http://example.com/', @predicate.normalize('http://example.com/'), 'no changes'
75
+ assert_equal 'ftp://example.com/', @predicate.normalize('ftp://example.com/'), 'no changes when scheme is not default'
76
+ assert_equal 'http://example.com', @predicate.normalize('example.com'), 'basic implied scheme support'
77
+ assert_equal 'http://example.com:443', @predicate.normalize('example.com:443'), 'preserve ports'
78
+
79
+ @predicate.implied_scheme = nil
80
+
81
+ assert_equal 'http://example.com/', @predicate.normalize('http://example.com/')
82
+ assert_equal 'ftp://example.com/', @predicate.normalize('ftp://example.com/')
83
+ assert_equal 'example.com', @predicate.normalize('example.com')
84
+ assert_equal 'example.com:80', @predicate.normalize('example.com:80')
85
+ end
86
+ end
@@ -0,0 +1,31 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
2
+
3
+ class UsaStatePredicateTest < SemanticAttributes::TestCase
4
+ def setup
5
+ @predicate = Predicates::UsaState.new(:foo)
6
+ end
7
+
8
+ def test_fixed_options
9
+ assert_raise NoMethodError do @predicate.options = {} end
10
+ end
11
+
12
+ def test_with_territories
13
+ @predicate.with_territories = true
14
+ assert_equal :us_state_or_territory, @predicate.error_message
15
+
16
+ assert @predicate.options.include?('Guam')
17
+ assert @predicate.options.include?('Minnesota')
18
+ end
19
+
20
+ def test_without_territories
21
+ @predicate.with_territories = false
22
+ assert_equal :us_state, @predicate.error_message
23
+
24
+ assert !@predicate.options.include?('Guam')
25
+ assert @predicate.options.include?('Minnesota')
26
+ end
27
+
28
+ def test_defaults
29
+ assert !@predicate.with_territories?
30
+ end
31
+ end
@@ -0,0 +1,42 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
2
+
3
+ class UsaZipCodePredicateTest < SemanticAttributes::TestCase
4
+ def setup
5
+ @predicate = Predicates::UsaZipCode.new(:foo)
6
+ end
7
+
8
+ def test_fixed_pattern
9
+ assert_raise NoMethodError do @predicate.like = nil end
10
+ end
11
+
12
+ def test_extended_allowed
13
+ @predicate.extended = :allowed
14
+
15
+ assert @predicate.validate(12345, nil)
16
+ assert @predicate.validate('12345', nil)
17
+ assert @predicate.validate('12345-4321', nil)
18
+ assert !@predicate.validate('12345-4', nil)
19
+ end
20
+
21
+ def test_extended_required
22
+ @predicate.extended = :required
23
+
24
+ assert !@predicate.validate(12345, nil)
25
+ assert !@predicate.validate('12345', nil)
26
+ assert @predicate.validate('12345-4321', nil)
27
+ assert !@predicate.validate('12345-4', nil)
28
+ end
29
+
30
+ def test_non_extended
31
+ @predicate.extended = false
32
+
33
+ assert @predicate.validate(12345, nil)
34
+ assert @predicate.validate('12345', nil)
35
+ assert !@predicate.validate('12345-4321', nil)
36
+ assert !@predicate.validate('12345-4', nil)
37
+ end
38
+
39
+ def test_defaults
40
+ assert !@predicate.extended
41
+ end
42
+ end
@@ -0,0 +1,18 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class SemanticAttributeTest < SemanticAttributes::TestCase
4
+ def test_everything
5
+ @field = SemanticAttributes::Attribute.new('a')
6
+ assert_equal :a, @field.field
7
+
8
+ assert !@field.has?('required')
9
+ assert_nothing_raised do @field.add 'required' end
10
+ assert @field.has?('required')
11
+ assert @field.get('required').is_a?(Predicates::Required)
12
+ end
13
+
14
+ def test_short_names
15
+ @attribute = SemanticAttributes::Attribute.new('a')
16
+ assert_equal Predicates::PhoneNumber, @attribute.send(:class_of, 'phone_number')
17
+ end
18
+ end
@@ -0,0 +1,29 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class SemanticAttributesTest < SemanticAttributes::TestCase
4
+ def setup
5
+ @set = SemanticAttributes::Set.new
6
+ end
7
+
8
+ def test_add
9
+ assert @set.instance_variable_get('@set').empty?
10
+ assert_raises ArgumentError, "can't add by symbol" do @set.add :foo end
11
+ assert @set.instance_variable_get('@set').empty?
12
+ assert_nothing_raised "can add a SemanticAttribute instance" do @set.add SemanticAttributes::Attribute.new(:foo) end
13
+ assert @set.instance_variable_get('@set').size == 1
14
+ end
15
+
16
+ def test_find
17
+ assert !@set.include?(:a)
18
+
19
+ # test retrieving a previously set field
20
+ a = SemanticAttributes::Attribute.new(:a)
21
+ @set.add a
22
+ assert @set.include?(:a)
23
+ assert_equal a, @set[:a], 'can find previously set fields'
24
+ end
25
+
26
+ def test_that_find_creates_if_not_found
27
+ assert @set[:a].is_a?(SemanticAttributes::Attribute), 'can create an Attribute by requesting it from the set'
28
+ end
29
+ end
@@ -0,0 +1,121 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class ValidationsTest < SemanticAttributes::TestCase
4
+ def setup
5
+ User.stub_semantics_with(:login => :required)
6
+ @record = User.new
7
+ @login_required = @record.semantic_attributes['login'].get('required')
8
+ end
9
+
10
+ def test_validation_hook
11
+ @record.expects(:validate_predicates)
12
+ @record.valid?
13
+ end
14
+
15
+ def test_validation_errors
16
+ assert !@record.valid?
17
+ assert @record.errors[:login]
18
+ assert_equal ['is required.'], @record.errors[:login]
19
+ end
20
+
21
+ def test_validate_on_default
22
+ assert_equal :both, @record.semantic_attributes['login'].get('required').validate_on
23
+ end
24
+
25
+ ##
26
+ ## attr_valid?
27
+ ##
28
+
29
+ def test_attribute_valid?
30
+ assert !@record.login_valid?
31
+ @record.login = "foo"
32
+ assert @record.login_valid?
33
+ end
34
+
35
+ def test_attribute_valid_with_conditional_validation
36
+ assert !@record.login_valid?
37
+ @record.stubs(:validate_predicate?).returns(false)
38
+ assert @record.login_valid?
39
+ end
40
+
41
+ ##
42
+ ## validate_predicate?
43
+ ##
44
+
45
+ def test_validate_predicate_with_validate_if_symbol
46
+ @record.stubs(:no).returns(false)
47
+ @record.stubs(:yes).returns(true)
48
+
49
+ assert @record.send(:validate_predicate?, @login_required)
50
+
51
+ @record.semantic_attributes['login'].get('required').validate_if = :no
52
+ assert !@record.send(:validate_predicate?, @login_required)
53
+
54
+ @record.semantic_attributes['login'].get('required').validate_if = :yes
55
+ assert @record.send(:validate_predicate?, @login_required)
56
+ end
57
+
58
+ def test_validate_predicate_with_validate_if_proc
59
+ assert @record.send(:validate_predicate?, @login_required)
60
+
61
+ @record.semantic_attributes['login'].get('required').validate_if = proc {false}
62
+ assert !@record.send(:validate_predicate?, @login_required)
63
+
64
+ @record.semantic_attributes['login'].get('required').validate_if = proc {true}
65
+ assert @record.send(:validate_predicate?, @login_required)
66
+ end
67
+
68
+ def test_validate_predicate_with_validate_on_create
69
+ @record = users(:george)
70
+ @record.login = nil
71
+
72
+ # test assumptions
73
+ assert !@record.new_record?
74
+ assert @record.send(:validate_predicate?, @login_required)
75
+
76
+ # the test
77
+ @record.semantic_attributes['login'].get('required').validate_on = :create
78
+ assert !@record.send(:validate_predicate?, @login_required)
79
+ end
80
+
81
+ def test_validate_predicate_with_validate_on_update
82
+ # test assumptions
83
+ assert @record.new_record?
84
+ assert @record.send(:validate_predicate?, @login_required)
85
+
86
+ # the test
87
+ @record.semantic_attributes['login'].get('required').validate_on = :update
88
+ assert !@record.send(:validate_predicate?, @login_required)
89
+ end
90
+
91
+ ##
92
+ ## :or_empty
93
+ ##
94
+
95
+ def test_allow_empty
96
+ User.stub_semantics_with(:login => {:number => {:or_empty => true}})
97
+
98
+ # empty values should skip the validate method
99
+ predicate = @record.semantic_attributes['login'].get('number')
100
+ predicate.expects(:validate).never
101
+
102
+ [nil, '', []].each do |empty_value|
103
+ @record.login = empty_value
104
+ assert @record.valid?
105
+ end
106
+ end
107
+
108
+ def test_disallow_empty
109
+ User.stub_semantics_with(:login => {:number => {:or_empty => false}})
110
+
111
+ # empty values should skip the validate method
112
+ predicate = @record.semantic_attributes['login'].get('number')
113
+ predicate.expects(:validate).never
114
+
115
+ [nil, '', []].each do |empty_value|
116
+ @record.login = empty_value
117
+ assert !@record.valid?
118
+ assert @record.errors[:login]
119
+ end
120
+ end
121
+ end