sequel_spec 0.1.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.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +22 -0
  6. data/README.md +91 -0
  7. data/Rakefile +1 -0
  8. data/lib/sequel_spec.rb +8 -0
  9. data/lib/sequel_spec/association.rb +13 -0
  10. data/lib/sequel_spec/association/association_matcher.rb +32 -0
  11. data/lib/sequel_spec/association/have_many_to_many_matcher.rb +15 -0
  12. data/lib/sequel_spec/association/have_many_to_one_matcher.rb +15 -0
  13. data/lib/sequel_spec/association/have_one_through_one_matcher.rb +15 -0
  14. data/lib/sequel_spec/association/have_one_to_many_matcher.rb +15 -0
  15. data/lib/sequel_spec/association/have_one_to_one_matcher.rb +15 -0
  16. data/lib/sequel_spec/base.rb +45 -0
  17. data/lib/sequel_spec/integration/rspec.rb +6 -0
  18. data/lib/sequel_spec/validation.rb +18 -0
  19. data/lib/sequel_spec/validation/validate_format_matcher.rb +42 -0
  20. data/lib/sequel_spec/validation/validate_includes_matcher.rb +43 -0
  21. data/lib/sequel_spec/validation/validate_integer_matcher.rb +23 -0
  22. data/lib/sequel_spec/validation/validate_length_matcher.rb +81 -0
  23. data/lib/sequel_spec/validation/validate_matcher.rb +67 -0
  24. data/lib/sequel_spec/validation/validate_not_null_matcher.rb +21 -0
  25. data/lib/sequel_spec/validation/validate_numeric_matcher.rb +23 -0
  26. data/lib/sequel_spec/validation/validate_presence_matcher.rb +23 -0
  27. data/lib/sequel_spec/validation/validate_schema_types_matcher.rb +23 -0
  28. data/lib/sequel_spec/validation/validate_type_matcher.rb +42 -0
  29. data/lib/sequel_spec/validation/validate_unique_matcher.rb +31 -0
  30. data/lib/sequel_spec/version.rb +3 -0
  31. data/sequel_spec.gemspec +25 -0
  32. data/spec/migrations/001_create_tables.rb +26 -0
  33. data/spec/sequel_spec/association/have_many_to_many_matcher_spec.rb +57 -0
  34. data/spec/sequel_spec/association/have_many_to_one_matcher_spec.rb +57 -0
  35. data/spec/sequel_spec/association/have_one_through_one_matcher_spec.rb +57 -0
  36. data/spec/sequel_spec/association/have_one_to_many_matcher_spec.rb +57 -0
  37. data/spec/sequel_spec/association/have_one_to_one_matcher_spec.rb +57 -0
  38. data/spec/sequel_spec/validation/validate_format_matcher_spec.rb +88 -0
  39. data/spec/sequel_spec/validation/validate_includes_matcher_spec.rb +88 -0
  40. data/spec/sequel_spec/validation/validate_integer_matcher_spec.rb +76 -0
  41. data/spec/sequel_spec/validation/validate_length_matcher_spec.rb +252 -0
  42. data/spec/sequel_spec/validation/validate_not_null_matcher_spec.rb +83 -0
  43. data/spec/sequel_spec/validation/validate_numeric_matcher_spec.rb +76 -0
  44. data/spec/sequel_spec/validation/validate_presence_matcher_spec.rb +77 -0
  45. data/spec/sequel_spec/validation/validate_schema_types_matcher_spec.rb +83 -0
  46. data/spec/sequel_spec/validation/validate_type_matcher_spec.rb +88 -0
  47. data/spec/sequel_spec/validation/validate_unique_matcher_spec.rb +83 -0
  48. data/spec/spec_helper.rb +33 -0
  49. data/spec/support/test_helpers.rb +19 -0
  50. metadata +164 -0
@@ -0,0 +1,23 @@
1
+ module SequelSpec
2
+ module Matchers
3
+ module Validation
4
+ class ValidateIntegerMatcher < ValidateMatcher
5
+ def description
6
+ desc = "validate that #{@attribute.inspect} is a valid integer"
7
+ desc << " with option(s) #{hash_to_nice_string @options}" unless @options.empty?
8
+ desc
9
+ end
10
+
11
+ def validation_type
12
+ :validates_integer
13
+ end
14
+ end
15
+
16
+ def validate_integer(attribute)
17
+ ValidateIntegerMatcher.new(attribute)
18
+ end
19
+
20
+ alias :validate_integrity_of :validate_integer
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,81 @@
1
+ module SequelSpec
2
+ module Matchers
3
+ module Validation
4
+ class ValidateLengthMatcher < ValidateMatcher
5
+ attr_reader :validation_type
6
+
7
+ def description
8
+ desc = "validate that length of #{@attribute.inspect} "
9
+ desc << case validation_type
10
+ when :validates_exact_length then "is exactly"
11
+ when :validates_min_length then "is greater than or equal to"
12
+ when :validates_max_length then "is less than or equal to"
13
+ when :validates_length_range then "is included in"
14
+ end << " #{@additionnal.inspect}"
15
+
16
+ desc << " with option(s) #{hash_to_nice_string @options}" unless @options.empty?
17
+ desc
18
+ end
19
+
20
+ def additionnal_param_required?
21
+ true
22
+ end
23
+
24
+ def additionnal_param_check
25
+ unless validation_type && @additionnal
26
+ raise ArgumentError, "You should specify the type of validation using #is, #is_at_least, #is_at_most or #is_between"
27
+ end
28
+ end
29
+
30
+ def is(value)
31
+ unless value.is_a?(Fixnum)
32
+ raise ArgumentError, "#is expects a Fixnum, #{value.class} given"
33
+ end
34
+
35
+ @additionnal = value
36
+ @validation_type = :validates_exact_length
37
+ self
38
+ end
39
+
40
+ alias :is_equal_to :is
41
+
42
+ def is_at_least(value)
43
+ unless value.is_a?(Fixnum)
44
+ raise ArgumentError, "#is_at_least expects a Fixnum, #{value.class} given"
45
+ end
46
+
47
+ @additionnal = value
48
+ @validation_type = :validates_min_length
49
+ self
50
+ end
51
+
52
+ def is_at_most(value)
53
+ unless value.is_a?(Fixnum)
54
+ raise ArgumentError, "#is_at_most expects a Fixnum, #{value.class} given"
55
+ end
56
+
57
+ @additionnal = value
58
+ @validation_type = :validates_max_length
59
+ self
60
+ end
61
+
62
+ def is_between(value)
63
+ unless value.is_a?(Range)
64
+ raise ArgumentError, "#is_between expects a Range, #{value.class} given"
65
+ end
66
+
67
+ @additionnal = value
68
+ @validation_type = :validates_length_range
69
+ self
70
+ end
71
+ end
72
+
73
+ def validate_length(attribute)
74
+ ValidateLengthMatcher.new(attribute)
75
+ end
76
+
77
+ alias :validate_length_of :validate_length
78
+ alias :ensure_length_of :validate_length
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,67 @@
1
+ module SequelSpec
2
+ module Matchers
3
+ module Validation
4
+ class ValidateMatcher < Base
5
+ def valid?(db, instance, klass, attribute, options)
6
+ additionnal_param_check if self.respond_to?(:additionnal_param_check)
7
+
8
+ instance = instance.dup
9
+ instance.class.columns
10
+
11
+ called = false
12
+
13
+ proxy = Proc.new do |args|
14
+ called_options = args.last.is_a?(Hash) ? args.pop : {}
15
+ called_attributes = args_to_called_attributes(args)
16
+ called_additionnal = args.shift if additionnal_param_required?
17
+
18
+ if !args.empty?
19
+ @suffix << "but called with too many params"
20
+ elsif called_attributes.include?(attribute)
21
+ if additionnal_param_required? && @additionnal != called_additionnal
22
+ @suffix << "but called with #{called_additionnal} instead"
23
+ elsif !options.empty? && called_options != options
24
+ @suffix << "but called with option(s) #{hash_to_nice_string called_options} instead"
25
+ else
26
+ called = true
27
+ end
28
+ end
29
+ end
30
+
31
+ instance.singleton_class.send(:define_method, validation_type,
32
+ Proc.new { |*args| proxy.call(args) }
33
+ )
34
+
35
+ # Run validations
36
+ instance.valid?
37
+
38
+ called
39
+ end
40
+
41
+ def allowing_nil
42
+ with_options :allow_nil => true
43
+ end
44
+
45
+ def allowing_blank
46
+ with_options :allow_blank => true
47
+ end
48
+
49
+ def allowing_missing
50
+ with_options :allow_missing => true
51
+ end
52
+
53
+ def with_message(message)
54
+ with_options :message => message
55
+ end
56
+
57
+ def additionnal_param_required?
58
+ false
59
+ end
60
+
61
+ def args_to_called_attributes(args)
62
+ [args.pop].flatten
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,21 @@
1
+ module SequelSpec
2
+ module Matchers
3
+ module Validation
4
+ class ValidateNotNullMatcher < ValidateMatcher
5
+ def description
6
+ desc = "validate that #{@attribute.inspect} is not null"
7
+ desc << " with option(s) #{hash_to_nice_string @options}" unless @options.empty?
8
+ desc
9
+ end
10
+
11
+ def validation_type
12
+ :validates_not_null
13
+ end
14
+ end
15
+
16
+ def validate_not_null(attribute)
17
+ ValidateNotNullMatcher.new(attribute)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ module SequelSpec
2
+ module Matchers
3
+ module Validation
4
+ class ValidateNumericMatcher < ValidateMatcher
5
+ def description
6
+ desc = "validate that #{@attribute.inspect} is a valid float"
7
+ desc << " with option(s) #{hash_to_nice_string @options}" unless @options.empty?
8
+ desc
9
+ end
10
+
11
+ def validation_type
12
+ :validates_numeric
13
+ end
14
+ end
15
+
16
+ def validate_numeric(attribute)
17
+ ValidateNumericMatcher.new(attribute)
18
+ end
19
+
20
+ alias :validate_numericality_of :validate_numeric
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ module SequelSpec
2
+ module Matchers
3
+ module Validation
4
+ class ValidatePresenceMatcher < ValidateMatcher
5
+ def description
6
+ desc = "validate presence of #{@attribute.inspect}"
7
+ desc << " with option(s) #{hash_to_nice_string @options}" unless @options.empty?
8
+ desc
9
+ end
10
+
11
+ def validation_type
12
+ :validates_presence
13
+ end
14
+ end
15
+
16
+ def validate_presence(attribute)
17
+ ValidatePresenceMatcher.new(attribute)
18
+ end
19
+
20
+ alias :validate_presence_of :validate_presence
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ module SequelSpec
2
+ module Matchers
3
+ module Validation
4
+ class ValidateSchemaTypesMatcher < ValidateMatcher
5
+ def description
6
+ desc = "validate schema types of #{@attribute.inspect}"
7
+ desc << " with option(s) #{hash_to_nice_string @options}" unless @options.empty?
8
+ desc
9
+ end
10
+
11
+ def validation_type
12
+ :validates_schema_types
13
+ end
14
+ end
15
+
16
+ def validate_schema_types(attribute)
17
+ ValidateSchemaTypesMatcher.new(attribute)
18
+ end
19
+
20
+ alias :validate_schema_types_of :validate_schema_types
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,42 @@
1
+ module SequelSpec
2
+ module Matchers
3
+ module Validation
4
+ class ValidateTypeMatcher < ValidateMatcher
5
+ def description
6
+ desc = "validate that type of #{@attribute.inspect} is #{@additionnal.inspect}"
7
+ desc << " with option(s) #{hash_to_nice_string @options}" unless @options.empty?
8
+ desc
9
+ end
10
+
11
+ def additionnal_param_required?
12
+ true
13
+ end
14
+
15
+ def additionnal_param_check
16
+ unless @additionnal
17
+ raise ArgumentError, "You should specify the accepted types using #is"
18
+ end
19
+ end
20
+
21
+ def is(value)
22
+ unless value.is_a?(Class) || value.is_a?(Array)
23
+ raise ArgumentError, "#with expects a Class or an array of Classes"
24
+ end
25
+
26
+ @additionnal = value
27
+ self
28
+ end
29
+
30
+ def validation_type
31
+ :validates_type
32
+ end
33
+ end
34
+
35
+ def validate_type(attribute)
36
+ ValidateTypeMatcher.new(attribute)
37
+ end
38
+
39
+ alias :validate_type_of :validate_type
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,31 @@
1
+ module SequelSpec
2
+ module Matchers
3
+ module Validation
4
+ class ValidateUniqueMatcher < ValidateMatcher
5
+ def description
6
+ desc = "validate uniqueness of #{@attribute.inspect}"
7
+ desc << " with option(s) #{hash_to_nice_string @options}" unless @options.empty?
8
+ desc
9
+ end
10
+
11
+ def validation_type
12
+ :validates_unique
13
+ end
14
+
15
+ def args_to_called_attributes(args)
16
+ called_attributes = []
17
+ until args.empty?
18
+ called_attributes << args.shift
19
+ end
20
+ called_attributes
21
+ end
22
+ end
23
+
24
+ def validate_unique(attribute)
25
+ ValidateUniqueMatcher.new(attribute)
26
+ end
27
+
28
+ alias :validate_uniqueness_of :validate_unique
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module SequelSpec
2
+ VERSION = "0.1.0".freeze
3
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ $: << File.expand_path('../lib', __FILE__)
3
+
4
+ require 'sequel_spec/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "sequel_spec"
8
+ spec.version = SequelSpec::VERSION
9
+ spec.authors = ["Adrià Planas", "Jonathan Tron", "Joseph Halter"]
10
+ spec.email = ["adriaplanas@liquidcodeworks.com"]
11
+ spec.summary = %q{RSpec Matchers for Sequel}
12
+ spec.homepage = "https://github.com/planas/sequel_spec"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.test_files = spec.files.grep('spec')
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_runtime_dependency "sequel", "~> 4.0"
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rspec", "~> 2.0"
23
+ spec.add_development_dependency "database_cleaner"
24
+ spec.add_development_dependency "sqlite3"
25
+ end
@@ -0,0 +1,26 @@
1
+ Sequel.migration do
2
+ change do
3
+ create_table :items do
4
+ primary_key :id
5
+ String :name
6
+ String :manufacturer
7
+ String :origin
8
+ String :owner
9
+ Float :price
10
+ end
11
+
12
+ create_table :comments do
13
+ primary_key :id
14
+ foreign_key :item_id, :items, :type => Fixnum
15
+ String :content
16
+ DateTime :created_at
17
+ index :item_id
18
+ end
19
+
20
+ create_table :comments_items do
21
+ foreign_key :comment_id, :comments, :type => Fixnum
22
+ foreign_key :item_id, :items, :type => Fixnum
23
+ index [:comment_id, :item_id], :unique => true
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe "have_many_to_many_matcher" do
4
+ before :all do
5
+ define_model :item
6
+ define_model :comment do
7
+ many_to_many :items
8
+ end
9
+ end
10
+
11
+ subject{ Comment }
12
+
13
+ describe "messages" do
14
+ describe "without option" do
15
+ it "should contain a description" do
16
+ @matcher = have_many_to_many :items
17
+ @matcher.description.should == "have a many_to_many association :items"
18
+ end
19
+
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 " + @matcher.description
24
+ @matcher.negative_failure_message.should == "expected Comment to not " + @matcher.description
25
+ end
26
+ end
27
+ describe "with options" do
28
+ it "should contain a description" do
29
+ @matcher = have_many_to_many(:items).with_options :class_name => "Item"
30
+ @matcher.description.should == 'have a many_to_many association :items with option(s) :class_name => "Item"'
31
+ end
32
+
33
+ it "should set failure messages" do
34
+ @matcher = have_many_to_many(:items).with_options :class_name => "Item"
35
+ @matcher.matches? subject
36
+ @matcher.failure_message.should == "expected Comment to " + @matcher.description
37
+ @matcher.negative_failure_message.should == "expected Comment to not " + @matcher.description
38
+ end
39
+
40
+ it "should explicit used options if different than expected" do
41
+ @matcher = have_many_to_many(:items).with_options :class_name => "Price"
42
+ @matcher.matches? subject
43
+ explanation = ' expected :class_name == "Price" but found "Item" instead'
44
+ @matcher.failure_message.should == "expected Comment to " + @matcher.description + explanation
45
+ @matcher.negative_failure_message.should == "expected Comment to not " + @matcher.description + explanation
46
+ end
47
+ end
48
+ end
49
+
50
+ describe "matchers" do
51
+ it{ should have_many_to_many(:items) }
52
+ it{ should have_many_to_many(:items).with_options :class_name => "Item", :join_table => :comments_items }
53
+ it{ should_not have_many_to_many(:prices) }
54
+ it{ should_not have_many_to_many(:items).with_options :class_name => "Price" }
55
+ it{ should_not have_many_to_many(:items).with_options :join_table => :items_comments }
56
+ end
57
+ end