motion-spec 0.2.0 → 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.
Files changed (34) hide show
  1. checksums.yaml +8 -8
  2. data/.hound.yml +2 -0
  3. data/.rubocop.yml +3 -0
  4. data/Gemfile.lock +1 -1
  5. data/lib/motion-spec/context.rb +4 -0
  6. data/lib/motion-spec/context_helper/expectation.rb +10 -0
  7. data/lib/motion-spec/context_helper/matchers.rb +95 -0
  8. data/lib/motion-spec/context_helper/should.rb +12 -0
  9. data/lib/motion-spec/error.rb +4 -0
  10. data/lib/motion-spec/expectation.rb +32 -0
  11. data/lib/motion-spec/fail_message_renderer.rb +101 -0
  12. data/lib/motion-spec/matcher/be.rb +16 -0
  13. data/lib/motion-spec/matcher/be_false.rb +15 -0
  14. data/lib/motion-spec/matcher/be_generic.rb +10 -0
  15. data/lib/motion-spec/matcher/be_nil.rb +16 -0
  16. data/lib/motion-spec/matcher/be_true.rb +16 -0
  17. data/lib/motion-spec/matcher/be_within.rb +30 -0
  18. data/lib/motion-spec/matcher/change.rb +35 -0
  19. data/lib/motion-spec/matcher/end_with.rb +22 -0
  20. data/lib/motion-spec/matcher/eq.rb +14 -0
  21. data/lib/motion-spec/matcher/eql.rb +10 -0
  22. data/lib/motion-spec/matcher/have_generic.rb +23 -0
  23. data/lib/motion-spec/matcher/have_items.rb +29 -0
  24. data/lib/motion-spec/matcher/include.rb +20 -0
  25. data/lib/motion-spec/matcher/match.rb +14 -0
  26. data/lib/motion-spec/matcher/match_array.rb +28 -0
  27. data/lib/motion-spec/matcher/raise_error.rb +47 -0
  28. data/lib/motion-spec/matcher/respond_to.rb +40 -0
  29. data/lib/motion-spec/matcher/satisfy.rb +20 -0
  30. data/lib/motion-spec/matcher/single_method.rb +25 -0
  31. data/lib/motion-spec/matcher/start_with.rb +22 -0
  32. data/lib/motion-spec/version.rb +1 -1
  33. data/lib/motion-spec.rb +20 -10
  34. metadata +28 -2
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ODlmZDBkZDQ2ODE2ODhiMzBmZGZiNzM5NmNmMTZlM2NmYmFhYTJiMA==
4
+ MDBmZjcyMjlmMTg2NDcyMWVjN2Q5NDJmZGE3MGZlYzAzMGY1MDhhMA==
5
5
  data.tar.gz: !binary |-
6
- ODIyMWE2MTExNjU3ZGQ4N2FhZjVlZDE5ZjI2ODdkOTBlMDcxNTFkOA==
6
+ M2ExODNlMzdhZWE2YmYwODY5OTBiY2ZhODVjNjg3ZGI1MDdmY2JjNg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- Y2Y5NmUzYzE5NDgzZGE5MDljMDE1MGE0Zjg0OTEyMDQ0NTZlNTk5YTFhYjIy
10
- NTNhNjdmNTA1YjQxZTkzNWNkMDdkZTAzOTkxMjRhM2ZmZTQ1Y2Y2ZTNiOWVj
11
- ODRhNjNmNTc5MDg5OGEyY2M0YTE2YjQ2ZjM0NjUyMWIzMjE1M2U=
9
+ YWVjYjI1YTNhMDQxZmMwMDY3OGIzYTkyNjYzZjIzYWY5Nzk4ZjlhZDI2MjQ5
10
+ ZDhhOTZhNzkwMDMwNGQ0YjlkZTI2NWQ0YmI4NzI3ZjhjY2RmNWYzMjM1MGNk
11
+ MzU0OTA3YmNhOTM3MmE0OTI4MjJjNmVmNmQ5ZDQzODM4NmQzMWI=
12
12
  data.tar.gz: !binary |-
13
- NTY2NTUzNmNlM2M3MDIyMjRlYTU5YjUwMTgyNGZhYzcwMDgxOTNjNmQ2Njky
14
- OTUyZjg5MGE2YWQxMWE5MTk4OWNjY2Q4OWUxYzllZjlhY2JhYTYzZmUyOTZm
15
- NzA1NTgyYjg1YjkzNWFmMzIzYjEwZjQ4ZDAxMjAxN2Q5ZDhiMGI=
13
+ MTg0YzkzNGYwZDZlYWYwNTlmMGNlYmQyODYwNTI5ZmVmYmM2YmQ5NWVlZWI1
14
+ MGExNWNlNmQyNmM4ZGQ5MDgwMTNlMzNjYzZlOTViZGU1ZTQ5ZmExNWZjZGFk
15
+ M2ZjZmMxY2U3ZjY5OTJkN2ZhMWZiN2NjNjJmMDk0MWQ5OWEwNzI=
data/.hound.yml ADDED
@@ -0,0 +1,2 @@
1
+ ruby:
2
+ config_file: .rubocop.yml
data/.rubocop.yml CHANGED
@@ -27,6 +27,9 @@ Metrics/ClassLength:
27
27
  Enabled: true
28
28
  Max: 100
29
29
 
30
+ Metrics/LineLength:
31
+ Max: 120
32
+
30
33
  Metrics/ModuleLength:
31
34
  Description: 'Avoid modules longer than 100 lines of code.'
32
35
  Enabled: true
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- motion-spec (0.2.0)
4
+ motion-spec (0.3.0)
5
5
  motion-require (>= 0.0.6)
6
6
 
7
7
  GEM
@@ -1,6 +1,10 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  module MotionSpec
3
3
  class Context
4
+ include ContextHelper::Matchers
5
+ include ContextHelper::Should
6
+ include ContextHelper::Expectation
7
+
4
8
  attr_reader :name, :block
5
9
 
6
10
  def initialize(name, before = nil, after = nil, &block)
@@ -0,0 +1,10 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module ContextHelper
4
+ module Expectation
5
+ def expect(subject = nil, &block)
6
+ MotionSpec::Expectation.new(subject, &block)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,95 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module ContextHelper
4
+ module Matchers
5
+ def be_nil
6
+ MotionSpec::Matcher::BeNil.new
7
+ end
8
+
9
+ def be_true
10
+ MotionSpec::Matcher::BeTrue.new
11
+ end
12
+
13
+ def be_false
14
+ MotionSpec::Matcher::BeFalse.new
15
+ end
16
+
17
+ def raise_error(exception_class = Exception, message = '')
18
+ MotionSpec::Matcher::RaiseError.new(exception_class, message)
19
+ end
20
+ alias_method :raise_exception, :raise_error
21
+
22
+ def eql(value)
23
+ MotionSpec::Matcher::Eql.new(value)
24
+ end
25
+
26
+ def be(value)
27
+ MotionSpec::Matcher::Be.new(value)
28
+ end
29
+ alias_method :equal, :be
30
+
31
+ def eq(value)
32
+ MotionSpec::Matcher::Eq.new(value)
33
+ end
34
+
35
+ def match(regex)
36
+ MotionSpec::Matcher::Match.new(regex)
37
+ end
38
+
39
+ def match_array(array)
40
+ MotionSpec::Matcher::MatchArray.new(array)
41
+ end
42
+ alias_method :contain_exactly, :match_array
43
+
44
+ def include(*values)
45
+ MotionSpec::Matcher::Include.new(*values)
46
+ end
47
+
48
+ def have(number)
49
+ MotionSpec::Matcher::HaveItems.new(number)
50
+ end
51
+
52
+ def satisfy(&block)
53
+ MotionSpec::Matcher::Satisfy.new(&block)
54
+ end
55
+
56
+ def respond_to(method_name)
57
+ MotionSpec::Matcher::RespondTo.new(method_name)
58
+ end
59
+
60
+ def start_with(substring)
61
+ MotionSpec::Matcher::StartWith.new(substring)
62
+ end
63
+
64
+ def end_with(substring)
65
+ MotionSpec::Matcher::EndWith.new(substring)
66
+ end
67
+
68
+ def change(&change_block)
69
+ MotionSpec::Matcher::Change.new(change_block)
70
+ end
71
+
72
+ def be_within(range)
73
+ MotionSpec::Matcher::BeWithin.new(range)
74
+ end
75
+
76
+ def method_missing(method_name, *args, &block)
77
+ string_method_name = method_name.to_s
78
+ match_be = string_method_name.match(/^be_(.*)/)
79
+
80
+ if match_be
81
+ return MotionSpec::Matcher::BeGeneric.new(match_be[1], *args)
82
+ end
83
+
84
+ match_have = string_method_name.match(/^have_(.*)/)
85
+
86
+ if match_have
87
+ return MotionSpec::Matcher::HaveGeneric.new(match_have[1], *args)
88
+ end
89
+
90
+ super
91
+ # raise "method name not found #{method_name}"
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,12 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module ContextHelper
4
+ module Should
5
+ def should(*args, &block)
6
+ return it('should ' + args.first, &block) if Counter[:depth] == 0
7
+
8
+ super(*args, &block)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -8,4 +8,8 @@ module MotionSpec
8
8
  super message
9
9
  end
10
10
  end
11
+
12
+ class FailedExpectation < RuntimeError; end
13
+
14
+ class InvalidMatcher < RuntimeError; end
11
15
  end
@@ -0,0 +1,32 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ class Expectation
4
+ def initialize(subject, &subject_block)
5
+ @subject = subject
6
+ @subject_block = subject_block
7
+ end
8
+
9
+ def to(matcher)
10
+ fail(matcher, false) unless matcher_passes(matcher)
11
+ assert
12
+ end
13
+
14
+ def not_to(matcher)
15
+ fail(matcher, true) if matcher_passes(matcher)
16
+ assert
17
+ end
18
+ alias_method :to_not, :not_to
19
+
20
+ def matcher_passes(matcher)
21
+ matcher.matches?(@subject, &@subject_block)
22
+ end
23
+
24
+ def fail(matcher, negated)
25
+ raise matcher.fail!(@subject, negated, &@subject_block)
26
+ end
27
+
28
+ def assert
29
+ true.should == true
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,101 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ class FailMessageRenderer
4
+ def self.expectation(negated)
5
+ "#{negated ? ' not' : ''} expected"
6
+ end
7
+
8
+ def self.message_for_be_false(negated, subject)
9
+ "#{subject.inspect}#{expectation(negated)} to be false"
10
+ end
11
+
12
+ def self.message_for_be_true(negated, subject)
13
+ "#{subject.inspect}#{expectation(negated)} to be true"
14
+ end
15
+
16
+ def self.message_for_be_nil(negated, subject)
17
+ "#{subject.inspect}#{expectation(negated)} to be nil"
18
+ end
19
+
20
+ def self.message_for_be(negated, subject, method_name, values)
21
+ message = "#{subject.inspect} ##{method_name}"
22
+ message += "(#{values.map(&:inspect).join(', ')})" unless values.empty?
23
+ message += "#{expectation(negated)} to return true"
24
+ message
25
+ end
26
+
27
+ def self.message_for_be_within(negated, subject, range, center_value)
28
+ "#{subject.inspect}#{expectation(negated)} to be within #{range} of #{center_value}"
29
+ end
30
+
31
+ def self.message_for_change(negated, change_amount, value_diff)
32
+ message = "Block#{expectation(negated)} to change value"
33
+ message += " by #{change_amount}" if change_amount
34
+ message += " but changed by #{value_diff}" if change_amount && !negated
35
+ message
36
+ end
37
+
38
+ def self.message_for_end_with(negated, subject, end_string)
39
+ "#{subject.inspect}#{expectation(negated)} to end with #{end_string.inspect}"
40
+ end
41
+
42
+ def self.message_for_start_with(negated, subject, start_string)
43
+ "#{subject.inspect}#{expectation(negated)} to start with #{start_string.inspect}"
44
+ end
45
+
46
+ def self.message_for_be_equal(negated, subject, value)
47
+ "#{subject.inspect}#{expectation(negated)} to be same object as #{value.inspect}"
48
+ end
49
+
50
+ def self.message_for_be_eq(negated, subject, value)
51
+ "#{subject.inspect}#{expectation(negated)} to be == to #{value.inspect}"
52
+ end
53
+
54
+ def self.message_for_have_generic(negated, subject, method_name, values)
55
+ message = "#{subject.inspect} #has_#{method_name}?"
56
+ message += "(#{values.map(&:inspect).join(', ')})" unless values.empty?
57
+ message += "#{expectation(negated)} to return true"
58
+ message
59
+ end
60
+
61
+ def self.message_for_have_items(negated, subject, expected_number_of_items, actual_number_of_items, key_type_name)
62
+ message = "#{subject.inspect}#{expectation(negated)} to have #{expected_number_of_items} #{key_type_name}"
63
+ message += " but had #{actual_number_of_items}" unless negated
64
+ message
65
+ end
66
+
67
+ def self.message_for_include(negated, subject, values)
68
+ values_message = values.size == 1 ? values.first : values
69
+ message = "#{subject.inspect}#{expectation(negated)} to include #{values_message.inspect}"
70
+ message
71
+ end
72
+
73
+ def self.message_for_match_array(negated, subject_array, expected_array)
74
+ message = "#{subject_array.inspect}#{expectation(negated)} to match array"
75
+ message += " #{expected_array.inspect}"
76
+ message
77
+ end
78
+
79
+ def self.message_for_match(negated, subject, match)
80
+ "#{subject.inspect}#{expectation(negated)} to match #{match.inspect}"
81
+ end
82
+
83
+ def self.message_for_raise_error(negated, show_class, error_class, show_message, error_message, rescued_exception)
84
+ message = "Block#{expectation(negated)} to raise error"
85
+ message += " of type #{error_class}" if show_class
86
+ message += " with message matching #{error_message.inspect}" if show_message
87
+ message += " but was #{rescued_exception.inspect}" if rescued_exception && !negated
88
+ message
89
+ end
90
+
91
+ def self.message_for_respond_to(negated, subject, method_name, number_of_args)
92
+ message = "#{subject.inspect}#{expectation(negated)} to respond to ##{method_name}"
93
+ message += " with #{number_of_args} arguments" if number_of_args
94
+ message
95
+ end
96
+
97
+ def self.message_for_satisfy(negated)
98
+ "Block#{expectation(negated)} to satisfy condition"
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,16 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module Matcher
4
+ class Be < SingleMethod
5
+ def initialize(value)
6
+ super(:equal?, value)
7
+ end
8
+
9
+ def fail_message(subject, negated)
10
+ FailMessageRenderer.message_for_be_equal(
11
+ negated, subject, @values.first
12
+ )
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module Matcher
4
+ class BeFalse
5
+ def matches?(value)
6
+ !value
7
+ end
8
+
9
+ def fail!(subject, negated)
10
+ message = FailMessageRenderer.message_for_be_false(negated, subject)
11
+ raise FailedExpectation.new(message)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module Matcher
4
+ class BeGeneric < SingleMethod
5
+ def initialize(method_name, *values)
6
+ super("#{method_name}?", *values)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,16 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module Matcher
4
+ class BeNil
5
+ def matches?(value)
6
+ value == nil
7
+ end
8
+
9
+ def fail!(subject, negated)
10
+ raise FailedExpectation.new(
11
+ FailMessageRenderer.message_for_be_nil(negated, subject)
12
+ )
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module Matcher
4
+ class BeTrue
5
+ def matches?(value)
6
+ value == true
7
+ end
8
+
9
+ def fail!(subject, negated)
10
+ raise FailedExpectation.new(
11
+ FailMessageRenderer.message_for_be_true(negated, subject)
12
+ )
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,30 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module Matcher
4
+ class BeWithin
5
+ INVALID_MATCH_ERROR = 'be_within matcher incomplete. Missing .of value'
6
+
7
+ def initialize(range)
8
+ @range = range
9
+ end
10
+
11
+ def of(center_value)
12
+ @center_value = center_value
13
+ self
14
+ end
15
+
16
+ def matches?(subject)
17
+ raise InvalidMatcher.new(INVALID_MATCH_ERROR) unless @center_value
18
+ (subject - @center_value).abs <= @range
19
+ end
20
+
21
+ def fail!(subject, negated)
22
+ raise FailedExpectation.new(
23
+ FailMessageRenderer.message_for_be_within(
24
+ negated, subject, @range, @center_value
25
+ )
26
+ )
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,35 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module Matcher
4
+ class Change
5
+ def initialize(change_block)
6
+ @change_block = change_block
7
+ end
8
+
9
+ def by(amount)
10
+ @change_amount = amount
11
+ self
12
+ end
13
+
14
+ def matches?(subject, &expectation_block)
15
+ old_value = @change_block.call
16
+ expectation_block.call
17
+ new_value = @change_block.call
18
+ if @change_amount
19
+ @value_diff = new_value - old_value
20
+ @value_diff == @change_amount
21
+ else
22
+ new_value != old_value
23
+ end
24
+ end
25
+
26
+ def fail!(subject, negated)
27
+ raise FailedExpectation.new(
28
+ FailMessageRenderer.message_for_change(
29
+ negated, @change_amount, @value_diff
30
+ )
31
+ )
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module Matcher
4
+ class EndWith
5
+ def initialize(end_string)
6
+ @end_string = end_string
7
+ end
8
+
9
+ def matches?(subject)
10
+ subject[-@end_string.size..-1] == @end_string
11
+ end
12
+
13
+ def fail!(subject, negated)
14
+ raise FailedExpectation.new(
15
+ FailMessageRenderer.message_for_end_with(
16
+ negated, subject, @end_string
17
+ )
18
+ )
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module Matcher
4
+ class Eq < SingleMethod
5
+ def initialize(value)
6
+ super(:==, value)
7
+ end
8
+
9
+ def fail_message(subject, negated)
10
+ FailMessageRenderer.message_for_be_eq(negated, subject, @values.first)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module Matcher
4
+ class Eql < SingleMethod
5
+ def initialize(value)
6
+ super(:eql?, value)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module Matcher
4
+ class HaveGeneric
5
+ def initialize(method_name, *args)
6
+ @method_name = method_name
7
+ @args = args
8
+ end
9
+
10
+ def matches?(subject)
11
+ subject.send("has_#{@method_name}?", *@args)
12
+ end
13
+
14
+ def fail!(subject, negated)
15
+ raise FailedExpectation.new(
16
+ FailMessageRenderer.message_for_have_generic(
17
+ negated, subject, @method_name, @args
18
+ )
19
+ )
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,29 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module Matcher
4
+ class HaveItems
5
+ def initialize(number_of_items)
6
+ @number_of_items = number_of_items
7
+ end
8
+
9
+ def matches?(value)
10
+ value.size == @number_of_items
11
+ end
12
+
13
+ [:items, :item, :keys, :values].each do |key_type_name|
14
+ define_method(key_type_name) do
15
+ @key_type_name = key_type_name
16
+ self
17
+ end
18
+ end
19
+
20
+ def fail!(subject, negated)
21
+ raise FailedExpectation.new(
22
+ FailMessageRenderer.message_for_have_items(
23
+ negated, subject, @number_of_items, subject.size, @key_type_name
24
+ )
25
+ )
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,20 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module Matcher
4
+ class Include
5
+ def initialize(*values)
6
+ @values = *values
7
+ end
8
+
9
+ def matches?(subject)
10
+ @values.all? { |v| subject.include?(v) }
11
+ end
12
+
13
+ def fail!(subject, negated)
14
+ raise FailedExpectation.new(
15
+ FailMessageRenderer.message_for_include(negated, subject, @values)
16
+ )
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module Matcher
4
+ class Match < SingleMethod
5
+ def initialize(value)
6
+ super(:match, value)
7
+ end
8
+
9
+ def fail_message(subject, negated)
10
+ FailMessageRenderer.message_for_match(negated, subject, @values.first)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,28 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module Matcher
4
+ class MatchArray
5
+ def initialize(expected_array)
6
+ @expected_array = expected_array
7
+ end
8
+
9
+ def matches?(subject_array)
10
+ return false unless subject_array.size == @expected_array.size
11
+ array_copy = subject_array.dup
12
+ @expected_array.all? do |item|
13
+ has = array_copy.include?(item)
14
+ array_copy.delete(item) if has
15
+ has
16
+ end
17
+ end
18
+
19
+ def fail!(subject_array, negated)
20
+ raise FailedExpectation.new(
21
+ FailMessageRenderer.message_for_match_array(
22
+ negated, subject_array, @expected_array
23
+ )
24
+ )
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,47 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module Matcher
4
+ class RaiseError
5
+ def initialize(error_class = Exception, message = '')
6
+ @error_class = error_class.is_a?(Class) ? error_class : Exception
7
+ @error_message = (error_class.is_a?(String) || error_class.is_a?(Regexp)) ? error_class : message
8
+ end
9
+
10
+ def matches?(value, &block)
11
+ block.call
12
+ false
13
+ rescue Exception => e
14
+ @rescued_exception = e
15
+ exception_matches(e)
16
+ end
17
+
18
+ def exception_matches(exception)
19
+ return false unless exception.is_a?(@error_class)
20
+
21
+ is_match = case @error_message
22
+ when String
23
+ exception.message.include?(@error_message)
24
+ when Regexp
25
+ @error_message.match(exception.message)
26
+ else
27
+ false
28
+ end
29
+
30
+ return false unless is_match
31
+
32
+ true
33
+ end
34
+
35
+ def fail!(subject, negated)
36
+ show_class = @error_class != Exception
37
+ show_message = !@error_message.is_a?(String) || !@error_message.empty?
38
+ raise FailedExpectation.new(
39
+ FailMessageRenderer.message_for_raise_error(
40
+ negated, show_class, @error_class, show_message, @error_message,
41
+ @rescued_exception
42
+ )
43
+ )
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,40 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module Matcher
4
+ class RespondTo
5
+ def initialize(method_name)
6
+ @method_name = method_name
7
+ end
8
+
9
+ def with(number_of_args)
10
+ @number_of_args = number_of_args
11
+ self
12
+ end
13
+
14
+ def arguments
15
+ self
16
+ end
17
+ alias_method :argument, :arguments
18
+
19
+ def matches?(subject)
20
+ valid = true
21
+
22
+ valid &&= subject.respond_to?(@method_name)
23
+
24
+ if valid && @number_of_args
25
+ valid &&= subject.method(@method_name).arity == @number_of_args
26
+ end
27
+
28
+ valid
29
+ end
30
+
31
+ def fail!(subject, negated)
32
+ raise FailedExpectation.new(
33
+ FailMessageRenderer.message_for_respond_to(
34
+ negated, subject, @method_name, @number_of_args
35
+ )
36
+ )
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,20 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module Matcher
4
+ class Satisfy
5
+ def initialize(&condition_block)
6
+ @condition_block = condition_block
7
+ end
8
+
9
+ def matches?(*values)
10
+ @condition_block.call(*values)
11
+ end
12
+
13
+ def fail!(subject, negated)
14
+ raise FailedExpectation.new(
15
+ FailMessageRenderer.message_for_satisfy(negated)
16
+ )
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module Matcher
4
+ class SingleMethod
5
+ def initialize(method_name, *values)
6
+ @values = values
7
+ @method_name = method_name
8
+ end
9
+
10
+ def matches?(subject)
11
+ subject.send(@method_name, *@values)
12
+ end
13
+
14
+ def fail!(subject, negated)
15
+ raise FailedExpectation.new(fail_message(subject, negated))
16
+ end
17
+
18
+ def fail_message(subject, negated = false)
19
+ FailMessageRenderer.message_for_be(
20
+ negated, subject, @method_name, @values
21
+ )
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module MotionSpec
3
+ module Matcher
4
+ class StartWith
5
+ def initialize(start_string)
6
+ @start_string = start_string
7
+ end
8
+
9
+ def matches?(subject)
10
+ subject[0...@start_string.size] == @start_string
11
+ end
12
+
13
+ def fail!(subject, negated)
14
+ raise FailedExpectation.new(
15
+ FailMessageRenderer.message_for_start_with(
16
+ negated, subject, @start_string
17
+ )
18
+ )
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,5 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
3
  module MotionSpec
4
- VERSION = '0.2.0'
4
+ VERSION = '0.3.0'
5
5
  end
data/lib/motion-spec.rb CHANGED
@@ -7,16 +7,16 @@ require 'motion-require'
7
7
 
8
8
  # Proper load order of all the classes/modules
9
9
  ###
10
- def require_lib_file(file)
11
- case file
10
+ def require_lib_files(files)
11
+ case files
12
12
  when String
13
- files = expanded_file_path(file)
14
- files = Dir.glob(files) if file.include? '*'
13
+ file_paths = expanded_file_path(files)
14
+ file_paths = Dir.glob(file_paths) if files.include? '*'
15
15
  when Array
16
- files = file.map { |f| expanded_file_path(f) }
16
+ file_paths = files.map { |f| expanded_file_path(f) }
17
17
  end
18
18
 
19
- Motion::Require.all(files)
19
+ Motion::Require.all(file_paths)
20
20
  end
21
21
 
22
22
  def expanded_file_path(file)
@@ -24,16 +24,26 @@ def expanded_file_path(file)
24
24
  end
25
25
 
26
26
  # Let's start off with what version we're running
27
- require_lib_file('version')
27
+ require_lib_files('version')
28
28
 
29
29
  # Load the output before the core so the core knows how to print
30
- require_lib_file('output/*')
30
+ require_lib_files('output/*')
31
+
32
+ # Add on to the context of specs
33
+ require_lib_files('context_helper/*')
31
34
 
32
35
  # All the other core modules in the proper order
33
- require_lib_file(%w(core error specification platform context should))
36
+ require_lib_files(%w(
37
+ core error specification platform context should expectation
38
+ fail_message_renderer
39
+ ))
40
+
41
+ # Load expectation matchers
42
+ require_lib_files('matcher/single_method')
43
+ require_lib_files('matcher/*')
34
44
 
35
45
  # Monkeypatch core objects to respond to test methods
36
- require_lib_file('extensions/*')
46
+ require_lib_files('extensions/*')
37
47
 
38
48
  # FIXME : Need better detection for iPhone Simulator
39
49
  if defined?(UIDevice) &&
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: motion-spec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Bender
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-04 00:00:00.000000000 Z
11
+ date: 2015-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: motion-require
@@ -47,6 +47,7 @@ extra_rdoc_files: []
47
47
  files:
48
48
  - .codeclimate.yml
49
49
  - .gitignore
50
+ - .hound.yml
50
51
  - .rubocop.yml
51
52
  - .travis.yml
52
53
  - Gemfile
@@ -57,14 +58,39 @@ files:
57
58
  - app/app_delegate.rb
58
59
  - lib/motion-spec.rb
59
60
  - lib/motion-spec/context.rb
61
+ - lib/motion-spec/context_helper/expectation.rb
62
+ - lib/motion-spec/context_helper/matchers.rb
63
+ - lib/motion-spec/context_helper/should.rb
60
64
  - lib/motion-spec/core.rb
61
65
  - lib/motion-spec/error.rb
66
+ - lib/motion-spec/expectation.rb
62
67
  - lib/motion-spec/extensions/boolean.rb
63
68
  - lib/motion-spec/extensions/exception.rb
64
69
  - lib/motion-spec/extensions/kernel.rb
65
70
  - lib/motion-spec/extensions/numeric.rb
66
71
  - lib/motion-spec/extensions/object.rb
67
72
  - lib/motion-spec/extensions/proc.rb
73
+ - lib/motion-spec/fail_message_renderer.rb
74
+ - lib/motion-spec/matcher/be.rb
75
+ - lib/motion-spec/matcher/be_false.rb
76
+ - lib/motion-spec/matcher/be_generic.rb
77
+ - lib/motion-spec/matcher/be_nil.rb
78
+ - lib/motion-spec/matcher/be_true.rb
79
+ - lib/motion-spec/matcher/be_within.rb
80
+ - lib/motion-spec/matcher/change.rb
81
+ - lib/motion-spec/matcher/end_with.rb
82
+ - lib/motion-spec/matcher/eq.rb
83
+ - lib/motion-spec/matcher/eql.rb
84
+ - lib/motion-spec/matcher/have_generic.rb
85
+ - lib/motion-spec/matcher/have_items.rb
86
+ - lib/motion-spec/matcher/include.rb
87
+ - lib/motion-spec/matcher/match.rb
88
+ - lib/motion-spec/matcher/match_array.rb
89
+ - lib/motion-spec/matcher/raise_error.rb
90
+ - lib/motion-spec/matcher/respond_to.rb
91
+ - lib/motion-spec/matcher/satisfy.rb
92
+ - lib/motion-spec/matcher/single_method.rb
93
+ - lib/motion-spec/matcher/start_with.rb
68
94
  - lib/motion-spec/output/colorized.rb
69
95
  - lib/motion-spec/output/fast.rb
70
96
  - lib/motion-spec/output/knock.rb