accept_values_for 0.2.1 → 0.3.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/Readme.textile CHANGED
@@ -2,25 +2,67 @@ h1. Accept values for
2
2
 
3
3
  h2. Description
4
4
 
5
- In order to spec a complex validation for ActiveRecord models.
6
- Implemented accept_values_for custom matcher.
7
- With this matcher you can specify which values of model attribute should be accepted by model validation and which should not.
5
+ In order to spec ActiveRecord models.
6
+ I decided to write a few custom matchers that makes the work match easier:
8
7
 
9
8
 
10
- h2. Usage
9
+ h2. Matchers
11
10
 
12
- <pre>
13
- describe User do
11
+ * accept_values_for
12
+ * discover
14
13
 
15
- subject { User.new(@valid_attributes)}
16
-
14
+ h3. Accept values for
17
15
 
16
+ "Rpec matcher to test the validation":http://gusiev.com/2010/06/ultimate-rspec-matcher-to-test-validation/
18
17
 
19
- it { should accept_values_for(:email, "john@example.com", "lambda@gusiev.com") }
20
- it { should_not accept_values_for(:email, "invalid", nil, "a@b", "john@.com") }
18
+ <pre>
19
+ describe User do
21
20
 
21
+ subject { User.new(@valid_attributes)}
22
+
23
+
24
+
25
+ it { should accept_values_for(:email, "john@example.com", "lambda@gusiev.com") }
26
+ it { should_not accept_values_for(:email, "invalid", nil, "a@b", "john@.com") }
27
+
28
+ end</pre>
29
+
30
+ h3. Discovery matcher
31
+
32
+ "Rspec matcher to test named scopes":http://gusiev.com/2010/07/bdd-rspec-matcher-to-test-named_scope-scoped-rails
33
+
34
+
35
+ <pre><code>describe "#by_category_id named scope" do
36
+ let(:given_category) do
37
+ Factory.create(:given_category)
38
+ end
39
+
40
+
41
+ let(:product_in_given_category) do
42
+ Factory.create(
43
+ :product,
44
+ :categories => [category]
45
+ )
46
+ end
47
+
48
+ let(:product_not_in_given_category) do
49
+ Factory.create(
50
+ :product,
51
+ :categories => [Factory.create(:category)]
52
+ )
22
53
  end
23
- </pre>
54
+
55
+ # This might be tricky to redefine subject as the finder result
56
+ # but in this way we can delegate the matcher to subject and
57
+ # avoid writing test descriptions.
58
+ subject { described_class.by_category_id(given_category.id) }
59
+
60
+ it { should discover(product_in_given_category) }
61
+ it { should_not discover(product_not_in_given_category) }
62
+
63
+ end
64
+ </code></pre>
65
+
24
66
 
25
67
  h2. Dependencies
26
68
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.1
1
+ 0.3.0
@@ -0,0 +1,57 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{accept_values_for}
8
+ s.version = "0.3.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Bogdan Gusiev"]
12
+ s.date = %q{2010-07-12}
13
+ s.description = %q{Rspec: When you have a complex validation(e.g. regexp or custom method) on ActiveRecord model
14
+ you have to write annoying easy specs on which values should be accepted by your validation method and which should not.
15
+ accepts_values_for rspec matcher simplify the code. See example for more information.
16
+ }
17
+ s.email = %q{agresso@gmail.com}
18
+ s.files = [
19
+ "Gemfile",
20
+ "Rakefile",
21
+ "Readme.textile",
22
+ "VERSION",
23
+ "accept_values_for.gemspec",
24
+ "lib/accept_values_for.rb",
25
+ "lib/discover.rb",
26
+ "spec/accept_values_for_spec.rb",
27
+ "spec/discover_spec.rb",
28
+ "spec/spec_helper.rb"
29
+ ]
30
+ s.homepage = %q{http://github.com/bogdan/accept_values_for}
31
+ s.rdoc_options = ["--charset=UTF-8"]
32
+ s.require_paths = ["lib"]
33
+ s.rubygems_version = %q{1.3.6}
34
+ s.summary = %q{In order to test a complex validation for ActiveRecord models Implemented accept_values_for custom rspec matcher}
35
+ s.test_files = [
36
+ "spec/discover_spec.rb",
37
+ "spec/accept_values_for_spec.rb",
38
+ "spec/spec_helper.rb"
39
+ ]
40
+
41
+ if s.respond_to? :specification_version then
42
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
43
+ s.specification_version = 3
44
+
45
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
46
+ s.add_runtime_dependency(%q<activerecord>, [">= 0"])
47
+ s.add_runtime_dependency(%q<rspec>, [">= 0"])
48
+ else
49
+ s.add_dependency(%q<activerecord>, [">= 0"])
50
+ s.add_dependency(%q<rspec>, [">= 0"])
51
+ end
52
+ else
53
+ s.add_dependency(%q<activerecord>, [">= 0"])
54
+ s.add_dependency(%q<rspec>, [">= 0"])
55
+ end
56
+ end
57
+
data/lib/discover.rb ADDED
@@ -0,0 +1,127 @@
1
+ if defined?(ActiveRecord)
2
+
3
+ # In order to spec ActiveRecord finders
4
+ # Implemented discover custom matcher
5
+ #
6
+ # :call-seq:
7
+ # Class.named_scope.should discover(model1, model2)
8
+ # Class.named_scope.should_not discover(model3, model4)
9
+ #
10
+ # matcher subject should be an instance of ActiverRecord::NamedScope::Scoped or Array
11
+ # models should be an instace of ActiverRecord::Base
12
+ #
13
+ # Use this if you need to check the inclution of objects ActiveRecord finders result
14
+ # and it's order
15
+ #
16
+ # == Examples
17
+ #
18
+ # class Group < AR::Base
19
+ # named_scope :approved, :conditions => "approved = true"
20
+ # named_scope :order_by_name, :order => "name"
21
+ # end
22
+ #
23
+ # Group.approved.should discover(Group.create!(:approved => true))
24
+ # Group.approved.should_not discover(Group.create!(:approved => false))
25
+ # Group.order_by_name.should discover(Group.create!(:name => "apple"), Group.create!(:name => "bear").with_exact_order)
26
+ #
27
+ #
28
+ def discover(*objects)
29
+ Rspec::Discover.new(*objects)
30
+ end
31
+
32
+ end
33
+
34
+ module Rspec
35
+ class Discover #:nodoc:
36
+
37
+ def initialize(*objects)
38
+ @objects = objects
39
+ end
40
+
41
+ def with_exact_order
42
+ @with_exact_order = true
43
+ self
44
+ end
45
+
46
+ def matches?(scope)
47
+ @scope = scope
48
+ return valid_findness? && valid_indexes?
49
+ end
50
+
51
+ def does_not_match?(scope)
52
+ @scope = scope
53
+ if @with_exact_order
54
+ raise "calling #with_exact_order is not allowed with should_not match"
55
+ end
56
+ return valid_not_findness?
57
+ end
58
+
59
+ def failure_message_for_should
60
+ result = @not_found_object_ids.any? ?
61
+ "expected #{@scope.inspect} to include objects: #{@not_found_object_ids.inspect}" :
62
+ "expected #{@scope.inspect} to be ordered as: #{@objects.map(&:id).inspect}"
63
+ result += ", but it was not. "
64
+ if @not_found_object_ids.any?
65
+ result += found_objects_string
66
+ end
67
+ result
68
+ end
69
+
70
+ def failure_message_for_should_not
71
+ result = "expected #{@scope.inspect} to not include objects: #{@found_object_ids.inspect}"
72
+ result += ", but it was. "
73
+ result += found_objects_string
74
+ result
75
+ end
76
+
77
+
78
+ def description
79
+ "discover #{@objects.map(&:inspect).join(', ')} " + ordering_string
80
+ end
81
+
82
+ protected
83
+
84
+ def valid_findness?
85
+ result = true
86
+ @not_found_object_ids = []
87
+ @objects.each do |object|
88
+ unless @scope.include?(object)
89
+ @not_found_object_ids << object.id
90
+ result = false
91
+ end
92
+ end
93
+ result
94
+ end
95
+
96
+
97
+ def valid_indexes?
98
+ return true unless @with_exact_order
99
+ indexes = @objects.map{|o| @scope.index(o)}
100
+ return indexes.sort == indexes
101
+ end
102
+
103
+ def valid_not_findness?
104
+ result = true
105
+ @found_object_ids = []
106
+ @objects.each do |object|
107
+ if @scope.include?(object)
108
+ @found_object_ids << object.id
109
+ result = false
110
+ end
111
+ end
112
+ result
113
+ end
114
+
115
+ def found_objects_string
116
+ "Found objects: " + @scope.map(&:id).inspect
117
+ end
118
+
119
+
120
+ def ordering_string
121
+ @with_exact_order ? "with exact order" : ""
122
+ end
123
+
124
+ end
125
+ end
126
+
127
+
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Discover" do
4
+
5
+
6
+ let(:named_scope) {
7
+ Group.by_char("j")
8
+ }
9
+ let(:java) { Group.create!(:name => "java") }
10
+ let(:json) { Group.create!(:name => "json") }
11
+ let(:jruby) { Group.create!(:name => "jruby") }
12
+ let(:ruby) { Group.create!(:name => "ruby")}
13
+ let(:python) { Group.create!(:name => "python")}
14
+
15
+ describe "#does_not_match?" do
16
+
17
+ context "if scope contains any of the specified values" do
18
+ subject { discover(java, ruby) }
19
+ before(:each) do
20
+ subject.does_not_match?(named_scope).should be_false
21
+ end
22
+
23
+ it { subject.failure_message_for_should_not.should == "expected #{named_scope.inspect} to not include objects: #{[java.id].inspect}, but it was. Found objects: #{named_scope.map(&:id).inspect}"}
24
+
25
+ end
26
+
27
+ end
28
+
29
+ describe "#matches?" do
30
+ context "if scope doesn't contain any of the specified objects" do
31
+ subject { discover(java, ruby) }
32
+ before(:each) do
33
+ subject.matches?(named_scope).should be_false
34
+ end
35
+
36
+ it {subject.failure_message_for_should.should == "expected #{named_scope.inspect} to include objects: #{[ruby.id].inspect}, but it was not. Found objects: #{named_scope.map(&:id).inspect}"}
37
+ end
38
+
39
+ context "if scope contain all of the specified objects but without correct order" do
40
+ subject { discover(jruby, java).with_exact_order }
41
+ before(:each) do
42
+ subject.matches?(named_scope).should be_false
43
+ end
44
+
45
+ it "should render error message correctly" do
46
+ subject.failure_message_for_should.should == "expected #{named_scope.inspect} to be ordered as: #{[jruby.id, java.id].inspect}, but it was not. "
47
+ end
48
+ end
49
+ end
50
+
51
+ describe "api" do
52
+ subject {
53
+ named_scope
54
+ }
55
+
56
+ it { should discover(java) }
57
+
58
+ it { should discover(json, java, jruby) }
59
+ it { should discover(java, jruby, json).with_exact_order }
60
+ it { should discover(java, json).with_exact_order }
61
+
62
+ it { should_not discover(ruby) }
63
+ it { should_not discover(ruby, python) }
64
+
65
+ end
66
+
67
+
68
+ end
data/spec/spec_helper.rb CHANGED
@@ -3,6 +3,7 @@ require 'spec'
3
3
  require 'spec/autorun'
4
4
  require 'active_record'
5
5
  require 'lib/accept_values_for'
6
+ require 'lib/discover'
6
7
 
7
8
  ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
8
9
  ActiveRecord::Base.configurations = true
@@ -13,6 +14,7 @@ ActiveRecord::Schema.define(:version => 1) do
13
14
  create_table :people do |t|
14
15
  t.string :gender
15
16
  t.integer :group_id
17
+ t.string :name
16
18
  end
17
19
 
18
20
  create_table :groups do |t|
@@ -23,7 +25,14 @@ end
23
25
  Spec::Runner.configure do |config|
24
26
  config.before(:each) do
25
27
  class ::Group < ActiveRecord::Base
26
-
28
+ has_many :people
29
+
30
+ named_scope :by_char, lambda { |char|
31
+ {
32
+ :conditions => ["name like ?", char + "%"],
33
+ :order => "name"
34
+ }
35
+ }
27
36
  end
28
37
 
29
38
  class ::Person < ActiveRecord::Base
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 2
8
- - 1
9
- version: 0.2.1
7
+ - 3
8
+ - 0
9
+ version: 0.3.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Bogdan Gusiev
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-06-29 00:00:00 +03:00
17
+ date: 2010-07-12 00:00:00 +03:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -58,8 +58,11 @@ files:
58
58
  - Rakefile
59
59
  - Readme.textile
60
60
  - VERSION
61
+ - accept_values_for.gemspec
61
62
  - lib/accept_values_for.rb
63
+ - lib/discover.rb
62
64
  - spec/accept_values_for_spec.rb
65
+ - spec/discover_spec.rb
63
66
  - spec/spec_helper.rb
64
67
  has_rdoc: true
65
68
  homepage: http://github.com/bogdan/accept_values_for
@@ -92,5 +95,6 @@ signing_key:
92
95
  specification_version: 3
93
96
  summary: In order to test a complex validation for ActiveRecord models Implemented accept_values_for custom rspec matcher
94
97
  test_files:
98
+ - spec/discover_spec.rb
95
99
  - spec/accept_values_for_spec.rb
96
100
  - spec/spec_helper.rb