valid_attribute 0.1.0 → 0.2.0

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.
data/HISTORY CHANGED
@@ -1,3 +1,7 @@
1
+ == 0.2.0
2
+ Test::Unit::TestCase support. You should use shoulda-context
3
+ Fixed logic bug with #does_not_match?
4
+
1
5
  == 0.1.0
2
6
  Version bump. API is stable
3
7
 
data/README.markdown CHANGED
@@ -4,17 +4,26 @@ ValidAttribute is a minimalist framework for validation BDD.
4
4
 
5
5
  ## Installation ##
6
6
 
7
- If you're using Rails just add the library to your Gemfile
7
+ If you're using `RSpec` just add the `valid_attribute` to your `Gemfile`
8
8
 
9
9
  gem 'valid_attribute'
10
10
 
11
- Then add it to your spec_helper
11
+ Then add it to your `spec_helper.rb`
12
12
 
13
13
  require 'valid_attribute'
14
14
 
15
+ or if you're using `Test::Unit`, you must use [Thoughtbot](http://thoughtbot.com)'s [shoulda-context](https://github.com/thoughtbot/shoulda-context)
16
+
17
+ # Gemfile
18
+ gem 'shoulda-context'
19
+
20
+ # test_helper.rb
21
+ require 'shoulda-context'
22
+ require 'valid_attribute'
23
+
15
24
  ## Usage ##
16
25
 
17
- Instead of having validation specific matchers ValidAttribute only cares if the attribute is valid under certain circumstances
26
+ Instead of having validation specific matchers `ValidAttribute` only cares if the attribute is valid under certain circumstances
18
27
 
19
28
  class User
20
29
  include ActiveModel::Validations
@@ -26,12 +35,13 @@ Instead of having validation specific matchers ValidAttribute only cares if the
26
35
  validates :password, :confirmation => true, :presence => true
27
36
  end
28
37
 
38
+ # RSpec
29
39
  describe User do
30
40
  # The .when method can take any number of values that you want to pass
31
41
  it { should have_valid(:email).when('test@test.com', 'test+spam@gmail.com') }
32
42
  it { should_not have_valid(:email).when('fail', 123) }
33
- it { should have_valid(:name).when('TestName')
34
- it { should_not have_valid(:name).when('Test')
43
+ it { should have_valid(:name).when('TestName') }
44
+ it { should_not have_valid(:name).when('Test') }
35
45
 
36
46
  # Because 'should' works off the the 'subject' in RSpec we can set other values if necessary for a given validation test
37
47
  describe 'password' do
@@ -41,12 +51,29 @@ Instead of having validation specific matchers ValidAttribute only cares if the
41
51
  end
42
52
  end
43
53
 
54
+ # TestUnit
55
+ require 'should/context'
56
+ class UserTest < Test::Unit::TestCase
57
+ # The .when method can take any number of values that you want to pass
58
+ should have_valid(:email).when('test@test.com', 'test+spam@gmail.com')
59
+ should_not have_valid(:email).when('fail', 123)
60
+ should have_valid(:name).when('TestName')
61
+ should_not have_valid(:name).when('Test')
62
+
63
+ # Because 'shoulda-context' works off the the 'subject' we can set other values if necessary for a given validation test
64
+ context 'password' do
65
+ subject { User.new(:password_confirmation => 'password') }
66
+ should have_valid(:password).when('password')
67
+ should_not have_valid(:password).when(nil)
68
+ end
69
+ end
70
+
44
71
  ## Non-ActiveModel models ##
45
72
 
46
- As long as your model responds to the following methods:
73
+ Your model should respond to the following methods:
47
74
 
48
- * valid? - only used to generate errors on the model
49
- * errors - should be a collection of attributes that have validation errors.
75
+ * `valid?` - only used to generate errors on the model
76
+ * `errors` - should be a collection of attributes that have validation errors.
50
77
 
51
78
  Other than that everything should work!
52
79
 
@@ -0,0 +1,71 @@
1
+ module ValidAttribute
2
+ class Matcher
3
+ attr_accessor :attr, :values, :subject, :failed_values, :passed_values
4
+
5
+ def initialize(attr)
6
+ self.attr = attr
7
+ end
8
+
9
+ def when(*values)
10
+ self.values = values
11
+ self
12
+ end
13
+
14
+ def failure_message
15
+ if failed_values.size == 1
16
+ " expected #{subject.class}##{attr} to accept the value: #{quote_values(failed_values)}"
17
+ else
18
+ " expected #{subject.class}##{attr} to accept the values: #{quote_values(failed_values)}"
19
+ end
20
+ end
21
+
22
+ def negative_failure_message
23
+ if passed_values.size == 1
24
+ " expected #{subject.class}##{attr} to not accept the value: #{quote_values(passed_values)}"
25
+ else
26
+ " expected #{subject.class}##{attr} to not accept the values: #{quote_values(passed_values)}"
27
+ end
28
+ end
29
+
30
+ def description
31
+ "be valid when: #{quote_values(values)}"
32
+ end
33
+
34
+ def matches?(subject)
35
+ check_values(subject)
36
+ failed_values.empty?
37
+ end
38
+
39
+ def does_not_match?(subject)
40
+ check_values(subject)
41
+ !failed_values.empty? && passed_values.empty?
42
+ end
43
+
44
+ private
45
+
46
+ def check_values(subject)
47
+ unless values
48
+ raise ::ValidAttribute::NoValues, "you need to set the values with .when on the matcher. Example: have_valid(:name).when('Brian')"
49
+ end
50
+
51
+ self.subject = subject
52
+ self.failed_values = []
53
+ self.passed_values = []
54
+
55
+ values.each do |value|
56
+ subject.send("#{attr}=", value)
57
+ subject.valid?
58
+ if subject.errors.key?(attr)
59
+ self.failed_values << value
60
+ else
61
+ self.passed_values << value
62
+ end
63
+ end
64
+ end
65
+
66
+ def quote_values(values)
67
+ values.map { |value| value.is_a?(String) ? "'#{value}'" : value }.join(', ')
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,38 @@
1
+ module ValidAttribute
2
+ module Method
3
+ # Assert an attribute is valid with any number of test values
4
+ #
5
+ # examples:
6
+ # describe User do
7
+ # it { should have_valid(:name).when('Brian') }
8
+ # it { should_not have_valid(:name).when(nil) }
9
+ #
10
+ # # if we want to test uniqueness we need to setup an existing value
11
+ # context 'email' do
12
+ # before { User.create(:email => 'brian@test.com') }
13
+ # it { should have_valid(:email).when('test@test.com', 'test+spam@gmail.com') }
14
+ # it { should_not have_valid(:email).when('abc', 123, 'brian@test.com') }
15
+ # end
16
+ # end
17
+ #
18
+ # If you are using Test::Unit you should use {http://thoughtbot.com Thoughtbot}'s {https://github.com/thoughtbot/shoulda-context shoulda-context}:
19
+ # class UserTest < Test::Unit::TestCase
20
+ # should have_valid(:name).when('Brian')
21
+ # should_not have_valid(:name).when('nil')
22
+ #
23
+ # # if we want to test uniqueness we need to setup an existing value
24
+ # context 'email' do
25
+ # setup { User.create(:email => 'brian@test.com') }
26
+ # should have_valid(:email).when('test@test.com', 'test+spam@gmail.com')
27
+ # should_not have_valid(:email).when('abc', 123, 'brian@test.com')
28
+ # end
29
+ # end
30
+ #
31
+ # @param [Symbol]
32
+ #
33
+ # @return [ValidAttribute::Matcher]
34
+ def have_valid(attr)
35
+ ::ValidAttribute::Matcher.new(attr)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,3 @@
1
+ module RSpec::Matchers
2
+ include ValidAttribute::Method
3
+ end
@@ -0,0 +1,3 @@
1
+ class Test::Unit::TestCase
2
+ extend ::ValidAttribute::Method
3
+ end
@@ -1,3 +1,3 @@
1
1
  module ValidAttribute
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -1,88 +1,12 @@
1
+ require 'valid_attribute/matcher'
2
+ require 'valid_attribute/method'
3
+
1
4
  module ValidAttribute
2
5
  class NoValues < StandardError; end
3
- # Test if an attribute is valid
4
- #
5
- # examples:
6
- # it { should have_valid(:name).when('Brian') }
7
- # it { should_not have_valid(:name).when(nil) }
8
- # it { should have_valid(:email).when('test@test.com', 'test+spam@gmail.com') }
9
- # it { should_not have_valid(:email).when('abc', 123) }
10
- #
11
- # @param [Symbol]
12
- #
13
- # @return [ValidAttribute::ValidAttributeMatcher]
14
- def have_valid(attr)
15
- ValidAttributeMatcher.new(attr)
16
- end
17
-
18
- class ValidAttributeMatcher
19
- attr_accessor :attr, :values, :subject, :failed_values, :passed_values
20
-
21
- def initialize(attr)
22
- self.attr = attr
23
- end
24
-
25
- def when(*values)
26
- self.values = values
27
- self
28
- end
29
-
30
- def failure_message
31
- if failed_values.size == 1
32
- " expected #{subject.class.model_name}##{attr} to accept the value: #{quote_values(failed_values)}"
33
- else
34
- " expected #{subject.class.model_name}##{attr} to accept the values: #{quote_values(failed_values)}"
35
- end
36
- end
37
-
38
- def negative_failure_message
39
- if passed_values.size == 1
40
- " expected #{subject.class.model_name}##{attr} to not accept the value: #{quote_values(passed_values)}"
41
- else
42
- " expected #{subject.class.model_name}##{attr} to not accept the values: #{quote_values(passed_values)}"
43
- end
44
- end
45
-
46
- def matches?(subject)
47
- check_values(subject)
48
- failed_values.empty?
49
- end
50
-
51
- def does_not_match?(subject)
52
- check_values(subject)
53
- passed_values.empty?
54
- end
55
-
56
- private
57
-
58
- def check_values(subject)
59
- unless values
60
- raise ::ValidAttribute::NoValues, "you need to set the values with .when on the matcher (ex. it { should have_valid(:name).when('Brian') })"
61
- end
62
-
63
- self.subject = subject
64
- self.failed_values = []
65
- self.passed_values = []
66
-
67
- values.each do |value|
68
- subject.send("#{attr}=", value)
69
- subject.valid?
70
- if subject.errors.key?(attr)
71
- self.failed_values << value
72
- else
73
- self.passed_values << value
74
- end
75
- end
76
- end
77
-
78
- def quote_values(values)
79
- values.map { |value| value.is_a?(String) ? "'#{value}'" : value }.join(', ')
80
- end
81
-
82
- end
83
6
  end
84
7
 
85
- module RSpec::Matchers
86
- include ValidAttribute
87
- end if defined?(RSpec)
88
-
8
+ if defined?(RSpec)
9
+ require 'valid_attribute/rspec'
10
+ else
11
+ require 'valid_attribute/test_unit'
12
+ end
data/spec/spec_helper.rb CHANGED
@@ -5,10 +5,10 @@ Bundler.setup
5
5
  $LOAD_PATH.unshift(File.dirname(__FILE__))
6
6
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
7
  require 'ruby-debug'
8
- require 'valid_attribute'
9
8
  require 'rspec'
10
9
  require 'rspec/autorun'
11
10
  require 'bourne'
11
+ require 'valid_attribute'
12
12
 
13
13
  RSpec.configure do |config|
14
14
  config.mock_with :mocha
@@ -0,0 +1,12 @@
1
+ # This is a RSpec spec to test TestUnit... yeah that's right
2
+
3
+ require 'spec_helper'
4
+ require 'test/unit'
5
+ require 'valid_attribute/test_unit'
6
+
7
+ describe 'Test::Unit::TestCase' do
8
+ it '.have_valid' do
9
+ Test::Unit::TestCase.have_valid(:name).should be_instance_of(ValidAttribute::Matcher)
10
+ end
11
+ end
12
+
data/spec/user.rb ADDED
@@ -0,0 +1,12 @@
1
+ class User
2
+ attr_accessor :name
3
+ attr_accessor :email
4
+
5
+ def errors
6
+ @error ||= {}
7
+ end
8
+
9
+ def self.model_name
10
+ 'User'
11
+ end
12
+ end
@@ -1,20 +1,8 @@
1
1
  require 'spec_helper'
2
+ require 'user'
2
3
 
3
4
  class Should
4
- include ValidAttribute
5
- end
6
-
7
- class User
8
- attr_accessor :name
9
- attr_accessor :email
10
-
11
- def errors
12
- @error ||= {}
13
- end
14
-
15
- def self.model_name
16
- 'User'
17
- end
5
+ include ValidAttribute::Method
18
6
  end
19
7
 
20
8
  describe 'ValidAttribute' do
@@ -24,66 +12,83 @@ describe 'ValidAttribute' do
24
12
  @user = User.new
25
13
  end
26
14
 
27
- describe 'valid data' do
28
- before do
29
- @user.stubs(:valid?).returns(true)
30
- end
31
-
32
- it 'passes with values' do
33
- matcher = @should.have_valid(:name).when('Brian', 'Stephanie')
34
- matcher.matches?(@user).should be_true
35
- end
36
- end
37
-
38
- describe 'data is first invalid then invalid' do
39
- before do
40
- @user.stubs(:valid?).returns(false).then.returns(true).then.returns(false).then.returns(true)
41
- @user.stubs(:errors).returns({:name => []}).then.returns({}).then.returns({:name => []}).then.returns({})
42
- @matcher = @should.have_valid(:name).when('abc', 123)
43
- @matches = @matcher.matches?(@user)
44
- @does_not_match = @matcher.does_not_match?(@user)
45
- end
46
-
47
- it 'matches? returns false' do
48
- @matches.should be_false
49
- end
50
-
51
- it 'does_not_match? returns false' do
52
- @does_not_match.should be_false
53
- end
54
-
55
- it 'has a failure message of the failed values' do
56
- @matcher.failure_message.should == " expected User#name to accept the value: 'abc'"
57
- end
58
-
59
- it 'has a negative failure message of the passed values' do
60
- @matcher.negative_failure_message.should == " expected User#name to not accept the value: 123"
61
- end
62
- end
63
-
64
- describe 'data is first invalid then valid then invalid then valid' do
65
- before do
66
- @user.stubs(:valid?).returns(false).then.returns(true).then.returns(false).then.returns(false).then.returns(true).then.returns(false)
67
- @user.stubs(:errors).returns({:name => []}).then.returns({}).then.returns({:name => []}).then.returns({}).then.returns({:name => []}).then.returns({}).then.returns({:name => []}).then.returns({})
68
- @matcher = @should.have_valid(:name).when('abc', 123, 456, 'def')
69
- @matches = @matcher.matches?(@user)
70
- @does_not_match = @matcher.does_not_match?(@user)
71
- end
72
-
73
- it 'matches? returns false' do
74
- @matches.should be_false
75
- end
76
-
77
- it 'does_not_match? returns true' do
78
- @does_not_match.should be_false
15
+ describe 'matcher result' do
16
+ context 'data is valid' do
17
+ before do
18
+ @user.stubs(:valid?).returns(true)
19
+ @user.stubs(:errors).returns({})
20
+ @matcher = @should.have_valid(:name).when('abc', 123)
21
+ end
22
+
23
+ it 'matches? returns true' do
24
+ @matcher.matches?(@user).should be_true
25
+ end
26
+
27
+ it 'does_not_match? returns false' do
28
+ @matcher.does_not_match?(@user).should be_false
29
+ end
30
+
31
+ describe 'messages' do
32
+ it '#negative_failue_message' do
33
+ @matcher.matches?(@user)
34
+ @matcher.negative_failure_message.should == " expected User#name to not accept the values: 'abc', 123"
35
+ end
36
+ end
79
37
  end
80
38
 
81
- it 'has a failure message of the failed values' do
82
- @matcher.failure_message.should == " expected User#name to accept the values: 'abc', 456"
39
+ context 'data is invalid' do
40
+ before do
41
+ @user.stubs(:valid?).returns(false)
42
+ @user.stubs(:errors).returns({:name => []})
43
+ @matcher = @should.have_valid(:name).when('abc', 123)
44
+ end
45
+
46
+ it 'matches? returns false' do
47
+ @matcher.matches?(@user).should be_false
48
+ end
49
+
50
+ it 'does_not_match? returns true' do
51
+ @matcher.does_not_match?(@user).should be_true
52
+ end
53
+
54
+ describe 'messages' do
55
+ it '#failue_message' do
56
+ @matcher.matches?(@user)
57
+ @matcher.failure_message.should == " expected User#name to accept the values: 'abc', 123"
58
+ end
59
+ end
83
60
  end
84
61
 
85
- it 'has a negative failure message of the passed values' do
86
- @matcher.negative_failure_message.should == " expected User#name to not accept the values: 123, 'def'"
62
+ context 'data is valid then invalid' do
63
+ before do
64
+ @user.stubs(:valid?).returns(true).then.returns(false)
65
+ @user.stubs(:errors).returns({}).then.returns({:name => []})
66
+ @matcher = @should.have_valid(:name).when('abc', 123)
67
+ end
68
+
69
+ it 'matches? returns false' do
70
+ @matcher.matches?(@user).should be_false
71
+ end
72
+
73
+ it 'does_not_match? returns false' do
74
+ @matcher.does_not_match?(@user).should be_false
75
+ end
76
+
77
+ describe 'messages' do
78
+ it '#failure_message' do
79
+ @matcher.matches?(@user)
80
+ @matcher.failure_message.should == " expected User#name to accept the value: 123"
81
+ end
82
+
83
+ it '#negative_failure_message' do
84
+ @matcher.matches?(@user)
85
+ @matcher.negative_failure_message.should == " expected User#name to not accept the value: 'abc'"
86
+ end
87
+
88
+ it '#description' do
89
+ @matcher.description.should == "be valid when: 'abc', 123"
90
+ end
91
+ end
87
92
  end
88
93
  end
89
94
 
@@ -91,7 +96,7 @@ describe 'ValidAttribute' do
91
96
  matcher = @should.have_valid(:name)
92
97
  expect do
93
98
  matcher.matches?(@user)
94
- end.to raise_error ValidAttribute::NoValues, "you need to set the values with .when on the matcher (ex. it { should have_valid(:name).when('Brian') })"
99
+ end.to raise_error ValidAttribute::NoValues, "you need to set the values with .when on the matcher. Example: have_valid(:name).when('Brian')"
95
100
  end
96
101
 
97
102
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: valid_attribute
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.0
5
+ version: 0.2.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Brian Cardarella
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-05-07 00:00:00 -04:00
13
+ date: 2011-05-28 00:00:00 -04:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -64,8 +64,14 @@ files:
64
64
  - README.markdown
65
65
  - Rakefile
66
66
  - lib/valid_attribute.rb
67
+ - lib/valid_attribute/matcher.rb
68
+ - lib/valid_attribute/method.rb
69
+ - lib/valid_attribute/rspec.rb
70
+ - lib/valid_attribute/test_unit.rb
67
71
  - lib/valid_attribute/version.rb
68
72
  - spec/spec_helper.rb
73
+ - spec/test_unit_spec.rb
74
+ - spec/user.rb
69
75
  - spec/valid_attribute_spec.rb
70
76
  - valid_attribute.gemspec
71
77
  has_rdoc: true
@@ -98,4 +104,6 @@ specification_version: 3
98
104
  summary: Minimalist validation matcher framework
99
105
  test_files:
100
106
  - spec/spec_helper.rb
107
+ - spec/test_unit_spec.rb
108
+ - spec/user.rb
101
109
  - spec/valid_attribute_spec.rb