JonathanTron-rspec_sequel_matchers 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
@@ -0,0 +1,30 @@
1
+ module RspecSequel
2
+
3
+ class Association < Base
4
+
5
+ def description
6
+ desc = "have a #{association_type} association #{@attribute.inspect}"
7
+ desc << " with #{hash_to_nice_string @options}" unless @options.empty?
8
+ desc
9
+ end
10
+
11
+ def valid?(db, i, c, attribute, options)
12
+ @association = c.association_reflection(attribute) || {}
13
+ if @association.empty?
14
+ @suffix << "(no association #{@attribute.inspect} found)"
15
+ false
16
+ else
17
+ matching = @association[:type] == association_type
18
+ options.each{|key, value|
19
+ if @association[key]!=value
20
+ @suffix << "expected #{key.inspect} == #{value.inspect} but found #{@association[key].inspect} instead"
21
+ matching = false
22
+ end
23
+ }
24
+ matching
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ end
@@ -2,6 +2,7 @@ module RspecSequel
2
2
 
3
3
  class Base
4
4
  def initialize(attribute, options={})
5
+ raise ArgumentError, "not enough params for matcher, required attribute is missing" if attribute.nil?
5
6
  @attribute = attribute.to_sym
6
7
  @options = options
7
8
  @description = []
@@ -25,7 +26,7 @@ module RspecSequel
25
26
  [@prefix, "not", description, @suffix].flatten.compact.join(" ")
26
27
  end
27
28
  def hash_to_nice_string(hash)
28
- hash.sort.collect{|param| param.join(" => ")}.join(", ")
29
+ hash.sort{|a,b| a[0].to_s<=>b[0].to_s}.collect{|param| param.collect{|v| v.inspect}.join(" => ")}.join(", ")
29
30
  end
30
31
  end
31
32
 
@@ -3,7 +3,7 @@ module RspecSequel
3
3
 
4
4
  class HaveColumnMatcher < RspecSequel::Base
5
5
  def description
6
- desc = "have a column :#{@attribute}"
6
+ desc = "have a column #{@attribute.inspect}"
7
7
  desc << " with type #{@options[:type]}" if @options[:type]
8
8
  desc
9
9
  end
@@ -0,0 +1,22 @@
1
+ module RspecSequel
2
+ module Matchers
3
+
4
+ class HaveManyToManyMatcher < RspecSequel::Association
5
+ def association_type
6
+ :many_to_many
7
+ end
8
+
9
+ def valid?(db, i, c, attribute, options)
10
+ matching = super
11
+
12
+ # check that association model exists, etc.
13
+ matching
14
+ end
15
+ end
16
+
17
+ def have_many_to_many(*args)
18
+ HaveManyToManyMatcher.new(*args)
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ module RspecSequel
2
+ module Matchers
3
+
4
+ class HaveManyToOneMatcher < RspecSequel::Association
5
+ def association_type
6
+ :many_to_one
7
+ end
8
+
9
+ def valid?(db, i, c, attribute, options)
10
+ matching = super
11
+
12
+ # check that association model exists, etc.
13
+ matching
14
+ end
15
+ end
16
+
17
+ def have_many_to_one(*args)
18
+ HaveManyToOneMatcher.new(*args)
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ module RspecSequel
2
+ module Matchers
3
+
4
+ class HaveOneToManyMatcher < RspecSequel::Association
5
+ def association_type
6
+ :one_to_many
7
+ end
8
+
9
+ def valid?(db, i, c, attribute, options)
10
+ matching = super
11
+
12
+ # check that association model exists, etc.
13
+ matching
14
+ end
15
+ end
16
+
17
+ def have_one_to_many(*args)
18
+ HaveOneToManyMatcher.new(*args)
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ module RspecSequel
2
+ module Matchers
3
+
4
+ class ValidateExactLengthMatcher < RspecSequel::Validation
5
+ def description
6
+ desc = "validate exact length of #{@attribute.inspect} to #{@additionnal.inspect}"
7
+ desc << " with #{hash_to_nice_string @options}" unless @options.empty?
8
+ desc
9
+ end
10
+
11
+ def additionnal_param_type
12
+ Fixnum
13
+ end
14
+
15
+ def validation_type
16
+ :validates_exact_length
17
+ end
18
+ end
19
+
20
+ def validate_exact_length(*args)
21
+ ValidateExactLengthMatcher.new(*args)
22
+ end
23
+
24
+ end
25
+ end
@@ -1,33 +1,15 @@
1
1
  module RspecSequel
2
2
  module Matchers
3
3
 
4
- class ValidatePresenceMatcher < RspecSequel::Base
4
+ class ValidatePresenceMatcher < RspecSequel::Validation
5
5
  def description
6
- desc = "validate presence of :#{@attribute}"
7
- unless @options.empty?
8
- desc << " with #{hash_to_nice_string @options}"
9
- end
6
+ desc = "validate presence of #{@attribute.inspect}"
7
+ desc << " with #{hash_to_nice_string @options}" unless @options.empty?
10
8
  desc
11
9
  end
12
10
 
13
- def valid?(db, i, c, attribute, options)
14
-
15
- # check column existance
16
- called_count = 0
17
- i = i.dup
18
- i.stub!(:validates_presence).and_return{|*args|
19
- if args.shift==attribute
20
- if options.empty?
21
- called_count += 1
22
- else
23
- called_options = args.shift
24
- @suffix << "(called with #{hash_to_nice_string called_options})"
25
- called_count +=1 if called_options==options
26
- end
27
- end
28
- }
29
- i.valid?
30
- called_count==1
11
+ def validation_type
12
+ :validates_presence
31
13
  end
32
14
  end
33
15
 
@@ -0,0 +1,73 @@
1
+ module RspecSequel
2
+
3
+ class Validation < Base
4
+
5
+ def initialize(*args)
6
+ # initialize Base
7
+ options = args.last.is_a?(Hash) ? args.pop : {}
8
+ super(args.pop, options)
9
+
10
+ # check additionnal param
11
+ if additionnal_param_required?
12
+ if args.size>1
13
+ raise ArgumentError, "too many params for matcher"
14
+ else
15
+ @additionnal = args.pop
16
+ raise ArgumentError, "expected matcher first parameter to be #{additionnal_param_type.inspect} but received #{@additionnal.class.inspect} instead" unless @additionnal.kind_of?(additionnal_param_type)
17
+ end
18
+ else
19
+ raise ArgumentError, "too many params for matcher" unless args.empty?
20
+ end
21
+ end
22
+
23
+ def additionnal_param_type
24
+ NilClass
25
+ end
26
+
27
+ def additionnal_param_required?
28
+ additionnal_param_type!=NilClass
29
+ end
30
+
31
+ def valid_options
32
+ [:allow_blank, :allow_missing, :allow_nil, :message]
33
+ end
34
+
35
+ def valid?(db, i, c, attribute, options)
36
+ # check options
37
+ invalid_options = options.keys.reject{|o| valid_options.include?(o)}
38
+ invalid_options.each{|o|
39
+ @suffix << "but option #{o.inspect} is not valid"
40
+ }
41
+ return false unless invalid_options.empty?
42
+
43
+ # check validation itself
44
+ called_count = 0
45
+ i = i.dup
46
+ i.class.columns # ensure colums are read again after .dup
47
+ i.stub!(validation_type).and_return{|*args|
48
+ called_options = args.last.is_a?(Hash) ? args.pop : {}
49
+ called_attributes = [args.pop].flatten
50
+ called_additionnal = args.shift if additionnal_param_required?
51
+ if !args.empty?
52
+ @suffix << "but called with too many params"
53
+ elsif called_attributes.include?(attribute)
54
+ if additionnal_param_required? && @additionnal!=called_additionnal
55
+ @suffix << "but called with #{called_additionnal} instead"
56
+ elsif !options.empty? && called_options!=options
57
+ @suffix << "but called with option(s) #{hash_to_nice_string called_options} instead"
58
+ else
59
+ called_count += 1
60
+ end
61
+ end
62
+ }
63
+ i.valid?
64
+ if called_count>1
65
+ @suffix << "but validation is called too many times"
66
+ return false
67
+ end
68
+ called_count==1
69
+ end
70
+
71
+ end
72
+
73
+ end
@@ -1,5 +1,7 @@
1
1
  # Load base
2
- require File.join(File.dirname(__FILE__), "rspec_sequel", "base")
2
+ ["base", "association", "validation"].each do |file|
3
+ require File.join(File.dirname(__FILE__), "rspec_sequel", file)
4
+ end
3
5
 
4
6
  # Add matchers
5
7
  Dir[File.join(File.dirname(__FILE__), "rspec_sequel", "matchers", "*.rb")].each do |file|
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{rspec_sequel_matchers}
5
- s.version = "0.0.1"
5
+ s.version = "0.0.2"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Jonathan Tron", "Joseph Halter"]
9
- s.date = %q{2009-08-05}
9
+ s.date = %q{2009-08-13}
10
10
  s.email = %q{jonathan@tron.name}
11
11
  s.extra_rdoc_files = [
12
12
  "LICENSE",
@@ -19,14 +19,26 @@ Gem::Specification.new do |s|
19
19
  "README.rdoc",
20
20
  "Rakefile",
21
21
  "VERSION",
22
+ "lib/rspec_sequel/association.rb",
22
23
  "lib/rspec_sequel/base.rb",
23
24
  "lib/rspec_sequel/matchers/have_column.rb",
25
+ "lib/rspec_sequel/matchers/have_many_to_many.rb",
26
+ "lib/rspec_sequel/matchers/have_many_to_one.rb",
27
+ "lib/rspec_sequel/matchers/have_one_to_many.rb",
28
+ "lib/rspec_sequel/matchers/validate_exact_length.rb",
24
29
  "lib/rspec_sequel/matchers/validate_presence.rb",
30
+ "lib/rspec_sequel/validation.rb",
25
31
  "lib/rspec_sequel_matchers.rb",
26
32
  "rspec_sequel_matchers.gemspec",
27
33
  "spec/have_column_matcher_spec.rb",
34
+ "spec/have_many_to_many_matcher_spec.rb",
35
+ "spec/have_many_to_one_matcher_spec.rb",
36
+ "spec/have_one_to_many_matcher_spec.rb",
28
37
  "spec/migrations/001_create_items.rb",
38
+ "spec/migrations/002_create_comments.rb",
39
+ "spec/migrations/003_create_comments_items.rb",
29
40
  "spec/spec_helper.rb",
41
+ "spec/validate_exact_length_matcher_spec.rb",
30
42
  "spec/validate_presence_matcher_spec.rb"
31
43
  ]
32
44
  s.has_rdoc = true
@@ -37,8 +49,14 @@ Gem::Specification.new do |s|
37
49
  s.summary = %q{TODO}
38
50
  s.test_files = [
39
51
  "spec/have_column_matcher_spec.rb",
52
+ "spec/have_many_to_many_matcher_spec.rb",
53
+ "spec/have_many_to_one_matcher_spec.rb",
54
+ "spec/have_one_to_many_matcher_spec.rb",
40
55
  "spec/migrations/001_create_items.rb",
56
+ "spec/migrations/002_create_comments.rb",
57
+ "spec/migrations/003_create_comments_items.rb",
41
58
  "spec/spec_helper.rb",
59
+ "spec/validate_exact_length_matcher_spec.rb",
42
60
  "spec/validate_presence_matcher_spec.rb"
43
61
  ]
44
62
 
@@ -1,10 +1,11 @@
1
1
  require File.dirname(__FILE__) + "/spec_helper"
2
2
 
3
- class Item < Sequel::Model
4
- end
5
-
6
3
  describe "have_column_matcher" do
7
4
 
5
+ before :all do
6
+ define_model :item
7
+ end
8
+
8
9
  subject{ Item }
9
10
 
10
11
  describe "messages" do
@@ -17,7 +18,7 @@ describe "have_column_matcher" do
17
18
  @matcher = have_column :name
18
19
  @matcher.matches? subject
19
20
  @matcher.failure_message.should == "expected Item to have a column :name"
20
- @matcher.negative_failure_message.should == "expected Item to not have a column :name"
21
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to have", "to not have")
21
22
  end
22
23
  end
23
24
  describe "with type as symbol" do
@@ -29,7 +30,7 @@ describe "have_column_matcher" do
29
30
  @matcher = have_column :password, :type => :string
30
31
  @matcher.matches? subject
31
32
  @matcher.failure_message.should == "expected Item to have a column :password with type string"
32
- @matcher.negative_failure_message.should == "expected Item to not have a column :password with type string"
33
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to have", "to not have")
33
34
  end
34
35
  end
35
36
  describe "with type as object" do
@@ -41,21 +42,21 @@ describe "have_column_matcher" do
41
42
  @matcher = have_column :password, :type => String
42
43
  @matcher.matches? subject
43
44
  @matcher.failure_message.should == "expected Item to have a column :password with type String"
44
- @matcher.negative_failure_message.should == "expected Item to not have a column :password with type String"
45
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to have", "to not have")
45
46
  end
46
47
  it "should explicit found type if different than expected" do
47
48
  @matcher = have_column :name, :type => Integer
48
49
  @matcher.matches? subject
49
50
  @matcher.failure_message.should == "expected Item to have a column :name with type Integer (type found: string, varchar(255))"
50
- @matcher.negative_failure_message.should == "expected Item to not have a column :name with type Integer (type found: string, varchar(255))"
51
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to have", "to not have")
51
52
  end
52
53
  end
53
54
  describe "on anonymous Sequel::Model class" do
54
55
  it "should set failure messages" do
55
56
  @matcher = have_column :password
56
- @matcher.matches? Sequel::Model(:items)
57
- @matcher.failure_message.should == "expected items to have a column :password"
58
- @matcher.negative_failure_message.should == "expected items to not have a column :password"
57
+ @matcher.matches? Sequel::Model(:comments)
58
+ @matcher.failure_message.should == "expected comments to have a column :password"
59
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to have", "to not have")
59
60
  end
60
61
  end
61
62
  describe "on Sequel::Model class" do
@@ -63,7 +64,7 @@ describe "have_column_matcher" do
63
64
  @matcher = have_column :password
64
65
  @matcher.matches? Item
65
66
  @matcher.failure_message.should == "expected Item to have a column :password"
66
- @matcher.negative_failure_message.should == "expected Item to not have a column :password"
67
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to have", "to not have")
67
68
  end
68
69
  end
69
70
  describe "on Sequel::Model instance" do
@@ -71,7 +72,7 @@ describe "have_column_matcher" do
71
72
  @matcher = have_column :password
72
73
  @matcher.matches? Item.new
73
74
  @matcher.failure_message.should == "expected #<Item @values={}> to have a column :password"
74
- @matcher.negative_failure_message.should == "expected #<Item @values={}> to not have a column :password"
75
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to have", "to not have")
75
76
  end
76
77
  end
77
78
  end
@@ -0,0 +1,55 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
3
+ describe "have_many_to_many_matcher" do
4
+
5
+ before :all do
6
+ define_model :item
7
+ define_model :comment do
8
+ many_to_many :items
9
+ end
10
+ end
11
+
12
+ subject{ Comment }
13
+
14
+ describe "messages" do
15
+ describe "without option" do
16
+ it "should contain a description" do
17
+ @matcher = have_many_to_many :items
18
+ @matcher.description.should == "have a many_to_many association :items"
19
+ end
20
+ it "should set failure messages" do
21
+ @matcher = have_many_to_many :items
22
+ @matcher.matches? subject
23
+ @matcher.failure_message.should == "expected Comment to have a many_to_many association :items"
24
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to have", "to not have")
25
+ end
26
+ end
27
+ describe "with options" do
28
+ it "should contain a description" do
29
+ @matcher = have_many_to_many :items, :class_name => "Item"
30
+ @matcher.description.should == 'have a many_to_many association :items with :class_name => "Item"'
31
+ end
32
+ it "should set failure messages" do
33
+ @matcher = have_many_to_many :items, :class_name => "Item"
34
+ @matcher.matches? subject
35
+ @matcher.failure_message.should == 'expected Comment to have a many_to_many association :items with :class_name => "Item"'
36
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to have", "to not have")
37
+ end
38
+ it "should explicit used options if different than expected" do
39
+ @matcher = have_many_to_many :items, :class_name => "Price"
40
+ @matcher.matches? subject
41
+ @matcher.failure_message.should == 'expected Comment to have a many_to_many association :items with :class_name => "Price" expected :class_name == "Price" but found "Item" instead'
42
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to have", "to not have")
43
+ end
44
+ end
45
+ end
46
+
47
+ describe "matchers" do
48
+ it{ should have_many_to_many(:items) }
49
+ it{ should have_many_to_many(:items, :class_name => "Item", :join_table => :comments_items) }
50
+ it{ should_not have_many_to_many(:prices) }
51
+ it{ should_not have_many_to_many(:items, :class_name => "Price") }
52
+ it{ should_not have_many_to_many(:items, :join_table => :items_comments) }
53
+ end
54
+
55
+ end
@@ -0,0 +1,54 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
3
+ describe "have_many_to_one_matcher" do
4
+
5
+ before :all do
6
+ define_model :item
7
+ define_model :comment do
8
+ many_to_one :item
9
+ end
10
+ end
11
+
12
+ subject{ Comment }
13
+
14
+ describe "messages" do
15
+ describe "without option" do
16
+ it "should contain a description" do
17
+ @matcher = have_many_to_one :item
18
+ @matcher.description.should == "have a many_to_one association :item"
19
+ end
20
+ it "should set failure messages" do
21
+ @matcher = have_many_to_one :item
22
+ @matcher.matches? subject
23
+ @matcher.failure_message.should == "expected Comment to have a many_to_one association :item"
24
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to have", "to not have")
25
+ end
26
+ end
27
+ describe "with options" do
28
+ it "should contain a description" do
29
+ @matcher = have_many_to_one :item, :class_name => "Item"
30
+ @matcher.description.should == 'have a many_to_one association :item with :class_name => "Item"'
31
+ end
32
+ it "should set failure messages" do
33
+ @matcher = have_many_to_one :item, :class_name => "Item"
34
+ @matcher.matches? subject
35
+ @matcher.failure_message.should == 'expected Comment to have a many_to_one association :item with :class_name => "Item"'
36
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to have", "to not have")
37
+ end
38
+ it "should explicit used options if different than expected" do
39
+ @matcher = have_many_to_one :item, :class_name => "Price"
40
+ @matcher.matches? subject
41
+ @matcher.failure_message.should == 'expected Comment to have a many_to_one association :item with :class_name => "Price" expected :class_name == "Price" but found "Item" instead'
42
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to have", "to not have")
43
+ end
44
+ end
45
+ end
46
+
47
+ describe "matchers" do
48
+ it{ should have_many_to_one(:item) }
49
+ it{ should have_many_to_one(:item, :class_name => "Item") }
50
+ it{ should_not have_many_to_one(:price) }
51
+ it{ should_not have_many_to_one(:item, :class_name => "Price") }
52
+ end
53
+
54
+ end
@@ -0,0 +1,54 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
3
+ describe "have_one_to_many_matcher" do
4
+
5
+ before :all do
6
+ define_model :item do
7
+ one_to_many :comments
8
+ end
9
+ define_model :comment
10
+ end
11
+
12
+ subject{ Item }
13
+
14
+ describe "messages" do
15
+ describe "without option" do
16
+ it "should contain a description" do
17
+ @matcher = have_one_to_many :comments
18
+ @matcher.description.should == "have a one_to_many association :comments"
19
+ end
20
+ it "should set failure messages" do
21
+ @matcher = have_one_to_many :comments
22
+ @matcher.matches? subject
23
+ @matcher.failure_message.should == "expected Item to have a one_to_many association :comments"
24
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to have", "to not have")
25
+ end
26
+ end
27
+ describe "with options" do
28
+ it "should contain a description" do
29
+ @matcher = have_one_to_many :comments, :class_name => "Comment"
30
+ @matcher.description.should == 'have a one_to_many association :comments with :class_name => "Comment"'
31
+ end
32
+ it "should set failure messages" do
33
+ @matcher = have_one_to_many :comments, :class_name => "Comment"
34
+ @matcher.matches? subject
35
+ @matcher.failure_message.should == 'expected Item to have a one_to_many association :comments with :class_name => "Comment"'
36
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to have", "to not have")
37
+ end
38
+ it "should explicit used options if different than expected" do
39
+ @matcher = have_one_to_many :comments, :class_name => "Price"
40
+ @matcher.matches? subject
41
+ @matcher.failure_message.should == 'expected Item to have a one_to_many association :comments with :class_name => "Price" expected :class_name == "Price" but found "Comment" instead'
42
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to have", "to not have")
43
+ end
44
+ end
45
+ end
46
+
47
+ describe "matchers" do
48
+ it{ should have_one_to_many(:comments) }
49
+ it{ should have_one_to_many(:comments, :class_name => "Comment") }
50
+ it{ should_not have_one_to_many(:prices) }
51
+ it{ should_not have_one_to_many(:comments, :class_name => "Price") }
52
+ end
53
+
54
+ end
@@ -0,0 +1,17 @@
1
+ class CreateComments < Sequel::Migration
2
+
3
+ def up
4
+ create_table :comments do
5
+ primary_key :id
6
+ foreign_key :item_id, :items, :type => Fixnum
7
+ String :content
8
+ DateTime :created_at
9
+ index :item_id
10
+ end
11
+ end
12
+
13
+ def down
14
+ drop_table :comments
15
+ end
16
+
17
+ end
@@ -0,0 +1,15 @@
1
+ class CreateCommentsItems < Sequel::Migration
2
+
3
+ def up
4
+ create_table :comments_items do
5
+ foreign_key :comment_id, :comments, :type => Fixnum
6
+ foreign_key :item_id, :items, :type => Fixnum
7
+ index [:comment_id, :item_id], :unique => true
8
+ end
9
+ end
10
+
11
+ def down
12
+ drop_table :comments_items
13
+ end
14
+
15
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require "spec"
2
2
  require "rubygems"
3
3
  require "sequel"
4
+ require "sequel/extensions/inflector"
4
5
  require "sequel/extensions/migration"
5
6
  require File.join(File.dirname(__FILE__), "..", "lib", "rspec_sequel_matchers")
6
7
 
@@ -9,19 +10,37 @@ begin
9
10
  Sequel.sqlite
10
11
  rescue Sequel::AdapterNotFound
11
12
  puts "sqlite not available. Install it with: sudo gem install sqlite3-ruby"
13
+ exit 1 # failure
14
+ end
15
+
16
+ # drop all tables and migrate on start
17
+ db = Sequel::Model.db
18
+ db.tables.each do |table_name|
19
+ db.drop_table table_name
20
+ end
21
+ Sequel::Migrator.apply(db, File.join(File.dirname(__FILE__), "migrations"))
22
+
23
+ def define_model(model, &block)
24
+ model_name = model.to_s.camelize.to_sym
25
+ table_name = model.to_s.tableize.to_sym
26
+ @defined_models ||= []
27
+ @defined_models << model_name
28
+ klass = Object.const_set model_name, Sequel::Model(table_name)
29
+ klass.class_eval &block if block_given?
12
30
  end
13
31
 
14
32
  Spec::Runner.configure do |config|
15
33
  config.include(RspecSequel::Matchers)
16
-
17
- config.before(:all) do
18
- db = Sequel::Model.db
19
- db.tables.each do |table_name|
20
- db["DROP #{table_name}"]
21
- end
22
- Sequel::Migrator.apply(db, File.join(File.dirname(__FILE__), "migrations"))
34
+
35
+ # undefine models defined via define_model (if any)
36
+ config.after(:all) do
37
+ @defined_models.each{|model_name|
38
+ Object.send(:remove_const, model_name)
39
+ }
40
+ @defined_models = nil
23
41
  end
24
42
 
43
+ # truncate all tables between each spec
25
44
  config.after(:each) do
26
45
  db = Sequel::Model.db
27
46
  db.tables.each do |table_name|
@@ -0,0 +1,86 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
3
+ describe "validate_exact_length_matcher" do
4
+
5
+ before :all do
6
+ define_model :item do
7
+ plugin :validation_helpers
8
+ def validate
9
+ validates_exact_length 4, :name, :allow_nil => true
10
+ end
11
+ end
12
+ end
13
+
14
+ subject{ Item }
15
+
16
+ describe "arguments" do
17
+ it "should require attribute" do
18
+ lambda{
19
+ @matcher = validate_exact_length
20
+ }.should raise_error(ArgumentError)
21
+ end
22
+ it "should require additionnal parameters" do
23
+ lambda{
24
+ @matcher = validate_exact_length :name
25
+ }.should raise_error(ArgumentError)
26
+ end
27
+ it "should refuse invalid additionnal parameters" do
28
+ lambda{
29
+ @matcher = validate_exact_length :id, :name
30
+ }.should raise_error(ArgumentError)
31
+ end
32
+ it "should accept valid additionnal parameters" do
33
+ lambda{
34
+ @matcher = validate_exact_length 4, :name
35
+ }.should_not raise_error(ArgumentError)
36
+ end
37
+ end
38
+
39
+ describe "messages" do
40
+ describe "without option" do
41
+ it "should contain a description" do
42
+ @matcher = validate_exact_length 4, :name
43
+ @matcher.description.should == "validate exact length of :name to 4"
44
+ end
45
+ it "should set failure messages" do
46
+ @matcher = validate_exact_length 4, :name
47
+ @matcher.matches? subject
48
+ @matcher.failure_message.should == "expected Item to validate exact length of :name to 4"
49
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to validate", "to not validate")
50
+ end
51
+ end
52
+ describe "with options" do
53
+ it "should contain a description" do
54
+ @matcher = validate_exact_length 4, :name, :allow_nil => true
55
+ @matcher.description.should == "validate exact length of :name to 4 with :allow_nil => true"
56
+ end
57
+ it "should set failure messages" do
58
+ @matcher = validate_exact_length 4, :price, :allow_nil => true
59
+ @matcher.matches? subject
60
+ @matcher.failure_message.should == "expected Item to validate exact length of :price to 4 with :allow_nil => true"
61
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to validate", "to not validate")
62
+ end
63
+ it "should explicit used options if different than expected" do
64
+ @matcher = validate_exact_length 4, :name, :allow_blank => true
65
+ @matcher.matches? subject
66
+ @matcher.failure_message.should == "expected Item to validate exact length of :name to 4 with :allow_blank => true but called with option(s) :allow_nil => true instead"
67
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to validate", "to not validate")
68
+ end
69
+ it "should warn if invalid options are used" do
70
+ @matcher = validate_exact_length 4, :name, :allow_anything => true
71
+ @matcher.matches? subject
72
+ @matcher.failure_message.should == "expected Item to validate exact length of :name to 4 with :allow_anything => true but option :allow_anything is not valid"
73
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to validate", "to not validate")
74
+ end
75
+ end
76
+ end
77
+
78
+ describe "matchers" do
79
+ it{ should validate_exact_length(4, :name) }
80
+ it{ should validate_exact_length(4, :name, :allow_nil => true) }
81
+ it{ should_not validate_exact_length(4, :price) }
82
+ it{ should_not validate_exact_length(3, :name) }
83
+ it{ should_not validate_exact_length(4, :name, :allow_blank => true) }
84
+ end
85
+
86
+ end
@@ -1,16 +1,31 @@
1
1
  require File.dirname(__FILE__) + "/spec_helper"
2
2
 
3
- class Item < Sequel::Model
4
- plugin :validation_helpers
5
- def validate
6
- validates_presence :name, :allow_nil => true
7
- end
8
- end
9
-
10
3
  describe "validate_presence_matcher" do
11
4
 
5
+ before :all do
6
+ define_model :item do
7
+ plugin :validation_helpers
8
+ def validate
9
+ validates_presence [:id, :name], :allow_nil => true
10
+ end
11
+ end
12
+ end
13
+
12
14
  subject{ Item }
13
15
 
16
+ describe "arguments" do
17
+ it "should require attribute" do
18
+ lambda{
19
+ @matcher = validate_presence
20
+ }.should raise_error(ArgumentError)
21
+ end
22
+ it "should refuse additionnal parameters" do
23
+ lambda{
24
+ @matcher = validate_presence :name, :id
25
+ }.should raise_error(ArgumentError)
26
+ end
27
+ end
28
+
14
29
  describe "messages" do
15
30
  describe "without option" do
16
31
  it "should contain a description" do
@@ -21,25 +36,31 @@ describe "validate_presence_matcher" do
21
36
  @matcher = validate_presence :name
22
37
  @matcher.matches? subject
23
38
  @matcher.failure_message.should == "expected Item to validate presence of :name"
24
- @matcher.negative_failure_message.should == "expected Item to not validate presence of :name"
39
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to validate", "to not validate")
25
40
  end
26
41
  end
27
42
  describe "with options" do
28
43
  it "should contain a description" do
29
44
  @matcher = validate_presence :name, :allow_nil => true
30
- @matcher.description.should == "validate presence of :name with allow_nil => true"
45
+ @matcher.description.should == "validate presence of :name with :allow_nil => true"
31
46
  end
32
47
  it "should set failure messages" do
33
48
  @matcher = validate_presence :price, :allow_nil => true
34
49
  @matcher.matches? subject
35
- @matcher.failure_message.should == "expected Item to validate presence of :price with allow_nil => true"
36
- @matcher.negative_failure_message.should == "expected Item to not validate presence of :price with allow_nil => true"
50
+ @matcher.failure_message.should == "expected Item to validate presence of :price with :allow_nil => true"
51
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to validate", "to not validate")
37
52
  end
38
53
  it "should explicit used options if different than expected" do
39
54
  @matcher = validate_presence :name, :allow_blank => true
40
55
  @matcher.matches? subject
41
- @matcher.failure_message.should == "expected Item to validate presence of :name with allow_blank => true (called with allow_nil => true)"
42
- @matcher.negative_failure_message.should == "expected Item to not validate presence of :name with allow_blank => true (called with allow_nil => true)"
56
+ @matcher.failure_message.should == "expected Item to validate presence of :name with :allow_blank => true but called with option(s) :allow_nil => true instead"
57
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to validate", "to not validate")
58
+ end
59
+ it "should warn if invalid options are used" do
60
+ @matcher = validate_presence :name, :allow_anything => true
61
+ @matcher.matches? subject
62
+ @matcher.failure_message.should == "expected Item to validate presence of :name with :allow_anything => true but option :allow_anything is not valid"
63
+ @matcher.negative_failure_message.should == @matcher.failure_message.gsub("to validate", "to not validate")
43
64
  end
44
65
  end
45
66
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: JonathanTron-rspec_sequel_matchers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Tron
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-08-05 00:00:00 -07:00
13
+ date: 2009-08-13 00:00:00 -07:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -49,14 +49,26 @@ files:
49
49
  - README.rdoc
50
50
  - Rakefile
51
51
  - VERSION
52
+ - lib/rspec_sequel/association.rb
52
53
  - lib/rspec_sequel/base.rb
53
54
  - lib/rspec_sequel/matchers/have_column.rb
55
+ - lib/rspec_sequel/matchers/have_many_to_many.rb
56
+ - lib/rspec_sequel/matchers/have_many_to_one.rb
57
+ - lib/rspec_sequel/matchers/have_one_to_many.rb
58
+ - lib/rspec_sequel/matchers/validate_exact_length.rb
54
59
  - lib/rspec_sequel/matchers/validate_presence.rb
60
+ - lib/rspec_sequel/validation.rb
55
61
  - lib/rspec_sequel_matchers.rb
56
62
  - rspec_sequel_matchers.gemspec
57
63
  - spec/have_column_matcher_spec.rb
64
+ - spec/have_many_to_many_matcher_spec.rb
65
+ - spec/have_many_to_one_matcher_spec.rb
66
+ - spec/have_one_to_many_matcher_spec.rb
58
67
  - spec/migrations/001_create_items.rb
68
+ - spec/migrations/002_create_comments.rb
69
+ - spec/migrations/003_create_comments_items.rb
59
70
  - spec/spec_helper.rb
71
+ - spec/validate_exact_length_matcher_spec.rb
60
72
  - spec/validate_presence_matcher_spec.rb
61
73
  has_rdoc: true
62
74
  homepage: http://github.com/JonathanTron/rspec_sequel_matchers
@@ -87,6 +99,12 @@ specification_version: 2
87
99
  summary: TODO
88
100
  test_files:
89
101
  - spec/have_column_matcher_spec.rb
102
+ - spec/have_many_to_many_matcher_spec.rb
103
+ - spec/have_many_to_one_matcher_spec.rb
104
+ - spec/have_one_to_many_matcher_spec.rb
90
105
  - spec/migrations/001_create_items.rb
106
+ - spec/migrations/002_create_comments.rb
107
+ - spec/migrations/003_create_comments_items.rb
91
108
  - spec/spec_helper.rb
109
+ - spec/validate_exact_length_matcher_spec.rb
92
110
  - spec/validate_presence_matcher_spec.rb