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.
- checksums.yaml +8 -8
- data/.hound.yml +2 -0
- data/.rubocop.yml +3 -0
- data/Gemfile.lock +1 -1
- data/lib/motion-spec/context.rb +4 -0
- data/lib/motion-spec/context_helper/expectation.rb +10 -0
- data/lib/motion-spec/context_helper/matchers.rb +95 -0
- data/lib/motion-spec/context_helper/should.rb +12 -0
- data/lib/motion-spec/error.rb +4 -0
- data/lib/motion-spec/expectation.rb +32 -0
- data/lib/motion-spec/fail_message_renderer.rb +101 -0
- data/lib/motion-spec/matcher/be.rb +16 -0
- data/lib/motion-spec/matcher/be_false.rb +15 -0
- data/lib/motion-spec/matcher/be_generic.rb +10 -0
- data/lib/motion-spec/matcher/be_nil.rb +16 -0
- data/lib/motion-spec/matcher/be_true.rb +16 -0
- data/lib/motion-spec/matcher/be_within.rb +30 -0
- data/lib/motion-spec/matcher/change.rb +35 -0
- data/lib/motion-spec/matcher/end_with.rb +22 -0
- data/lib/motion-spec/matcher/eq.rb +14 -0
- data/lib/motion-spec/matcher/eql.rb +10 -0
- data/lib/motion-spec/matcher/have_generic.rb +23 -0
- data/lib/motion-spec/matcher/have_items.rb +29 -0
- data/lib/motion-spec/matcher/include.rb +20 -0
- data/lib/motion-spec/matcher/match.rb +14 -0
- data/lib/motion-spec/matcher/match_array.rb +28 -0
- data/lib/motion-spec/matcher/raise_error.rb +47 -0
- data/lib/motion-spec/matcher/respond_to.rb +40 -0
- data/lib/motion-spec/matcher/satisfy.rb +20 -0
- data/lib/motion-spec/matcher/single_method.rb +25 -0
- data/lib/motion-spec/matcher/start_with.rb +22 -0
- data/lib/motion-spec/version.rb +1 -1
- data/lib/motion-spec.rb +20 -10
- metadata +28 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MDBmZjcyMjlmMTg2NDcyMWVjN2Q5NDJmZGE3MGZlYzAzMGY1MDhhMA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
M2ExODNlMzdhZWE2YmYwODY5OTBiY2ZhODVjNjg3ZGI1MDdmY2JjNg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YWVjYjI1YTNhMDQxZmMwMDY3OGIzYTkyNjYzZjIzYWY5Nzk4ZjlhZDI2MjQ5
|
10
|
+
ZDhhOTZhNzkwMDMwNGQ0YjlkZTI2NWQ0YmI4NzI3ZjhjY2RmNWYzMjM1MGNk
|
11
|
+
MzU0OTA3YmNhOTM3MmE0OTI4MjJjNmVmNmQ5ZDQzODM4NmQzMWI=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MTg0YzkzNGYwZDZlYWYwNTlmMGNlYmQyODYwNTI5ZmVmYmM2YmQ5NWVlZWI1
|
14
|
+
MGExNWNlNmQyNmM4ZGQ5MDgwMTNlMzNjYzZlOTViZGU1ZTQ5ZmExNWZjZGFk
|
15
|
+
M2ZjZmMxY2U3ZjY5OTJkN2ZhMWZiN2NjNjJmMDk0MWQ5OWEwNzI=
|
data/.hound.yml
ADDED
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
data/lib/motion-spec/context.rb
CHANGED
@@ -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
|
data/lib/motion-spec/error.rb
CHANGED
@@ -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,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,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
|
data/lib/motion-spec/version.rb
CHANGED
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
|
11
|
-
case
|
10
|
+
def require_lib_files(files)
|
11
|
+
case files
|
12
12
|
when String
|
13
|
-
|
14
|
-
|
13
|
+
file_paths = expanded_file_path(files)
|
14
|
+
file_paths = Dir.glob(file_paths) if files.include? '*'
|
15
15
|
when Array
|
16
|
-
|
16
|
+
file_paths = files.map { |f| expanded_file_path(f) }
|
17
17
|
end
|
18
18
|
|
19
|
-
Motion::Require.all(
|
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
|
-
|
27
|
+
require_lib_files('version')
|
28
28
|
|
29
29
|
# Load the output before the core so the core knows how to print
|
30
|
-
|
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
|
-
|
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
|
-
|
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.
|
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-
|
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
|