motion-spec 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|