motion-expect 2.0.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 (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.travis.yml +8 -0
  4. data/CHANGELOG.md +4 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +34 -0
  8. data/Rakefile +1 -0
  9. data/lib/motion-expect.rb +9 -0
  10. data/lib/motion-expect/bacon_context.rb +4 -0
  11. data/lib/motion-expect/exceptions.rb +4 -0
  12. data/lib/motion-expect/expectation.rb +37 -0
  13. data/lib/motion-expect/fail_message_renderer.rb +100 -0
  14. data/lib/motion-expect/matcher/be.rb +11 -0
  15. data/lib/motion-expect/matcher/be_false.rb +12 -0
  16. data/lib/motion-expect/matcher/be_generic.rb +7 -0
  17. data/lib/motion-expect/matcher/be_nil.rb +11 -0
  18. data/lib/motion-expect/matcher/be_true.rb +11 -0
  19. data/lib/motion-expect/matcher/be_within.rb +21 -0
  20. data/lib/motion-expect/matcher/change.rb +28 -0
  21. data/lib/motion-expect/matcher/end_with.rb +15 -0
  22. data/lib/motion-expect/matcher/eq.rb +11 -0
  23. data/lib/motion-expect/matcher/eql.rb +9 -0
  24. data/lib/motion-expect/matcher/have_generic.rb +16 -0
  25. data/lib/motion-expect/matcher/have_items.rb +22 -0
  26. data/lib/motion-expect/matcher/include.rb +15 -0
  27. data/lib/motion-expect/matcher/match.rb +11 -0
  28. data/lib/motion-expect/matcher/match_array.rb +21 -0
  29. data/lib/motion-expect/matcher/matchers.rb +91 -0
  30. data/lib/motion-expect/matcher/raise_error.rb +31 -0
  31. data/lib/motion-expect/matcher/respond_to.rb +28 -0
  32. data/lib/motion-expect/matcher/satisfy.rb +15 -0
  33. data/lib/motion-expect/matcher/single_method.rb +22 -0
  34. data/lib/motion-expect/matcher/start_with.rb +15 -0
  35. data/motion-expect.gemspec +22 -0
  36. data/run-tests.sh +3 -0
  37. data/spec_app/.repl_history +0 -0
  38. data/spec_app/Gemfile +5 -0
  39. data/spec_app/Rakefile +15 -0
  40. data/spec_app/app/app_delegate.rb +5 -0
  41. data/spec_app/resources/Default-568h@2x.png +0 -0
  42. data/spec_app/spec/helpers/bacon_context.rb +5 -0
  43. data/spec_app/spec/matchers/be_false_spec.rb +22 -0
  44. data/spec_app/spec/matchers/be_generic_spec.rb +28 -0
  45. data/spec_app/spec/matchers/be_nil_spec.rb +22 -0
  46. data/spec_app/spec/matchers/be_true_spec.rb +22 -0
  47. data/spec_app/spec/matchers/be_within_spec.rb +21 -0
  48. data/spec_app/spec/matchers/change_spec.rb +44 -0
  49. data/spec_app/spec/matchers/end_with_spec.rb +13 -0
  50. data/spec_app/spec/matchers/equality_spec.rb +37 -0
  51. data/spec_app/spec/matchers/have_generic_spec.rb +26 -0
  52. data/spec_app/spec/matchers/have_items_spec.rb +17 -0
  53. data/spec_app/spec/matchers/include_spec.rb +32 -0
  54. data/spec_app/spec/matchers/match_array_spec.rb +22 -0
  55. data/spec_app/spec/matchers/match_spec.rb +21 -0
  56. data/spec_app/spec/matchers/raise_error_spec.rb +65 -0
  57. data/spec_app/spec/matchers/respond_to_spec.rb +30 -0
  58. data/spec_app/spec/matchers/satisfy_spec.rb +17 -0
  59. data/spec_app/spec/matchers/start_with_spec.rb +13 -0
  60. metadata +131 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 31eee27b240ba338e3267efd2a74d3080f28d4d4
4
+ data.tar.gz: 0f4b4aba9cdc883561ec08a601d0594a34e9755e
5
+ SHA512:
6
+ metadata.gz: 3205d44d297e65cb9eec6d8359b6947dd77fe26c6804d8e23f63767f021760232da6dfeb0fe401b8a64d76ef5400a826adcaefbc855d9df18f46d6f6b6f6e972
7
+ data.tar.gz: 19428d3b5ee5a9afa6b06f814e52d4acee7a19948cac739ca177feee50e56454136b85701378ed02336efc3d96d18eaa140f6ea58dd8906f6252f082a13d0d2e
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ spec_app/build/*
@@ -0,0 +1,8 @@
1
+ language: objective-c
2
+ before_install:
3
+ - (ruby --version)
4
+ - (motion --version)
5
+ - sudo chown -R travis ~/Library/RubyMotion
6
+ - mkdir -p ~/Library/RubyMotion/build
7
+ - sudo motion update
8
+ script: "./run-tests.sh"
@@ -0,0 +1,4 @@
1
+ [2.0.0]
2
+
3
+ - Renamed gem to motion-expect (based on discussion with original owner - https://github.com/ijpiantanida/bacon-expect/issues/4)
4
+ - Updated for RubyMotion 6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in motion-expect.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Ignacio Piantanida
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,34 @@
1
+ # MotionExpect [![Build Status](https://travis-ci.org/rubymotion-community/motion-expect.svg?branch=master)](https://travis-ci.org/rubymotion-community/motion-expect) [![Code Climate](https://codeclimate.com/github/rubymotion-community/motion-expect.png)](https://codeclimate.com/github/rubymotion-community/motion-expect)
2
+
3
+ Bring [RSpec 3.0 expect syntax](https://www.relishapp.com/rspec/rspec-expectations/v/3-0/docs/built-in-matchers) to RubyMotion's MacBacon.
4
+ ```ruby
5
+ expect(view("Tap me")).not_to be_hidden
6
+ ```
7
+
8
+ Expect syntax allows a cleaner implementation because it doesn't need to monkey-patch the Object class to install the `should` method.
9
+
10
+ # Installation
11
+ ```
12
+ gem install motion-expect
13
+
14
+ # or in Gemfile
15
+ gem 'motion-expect'
16
+ ```
17
+
18
+ # Usage
19
+ This gem ports most of the built-in matchers found in [RSpec 3.0](https://www.relishapp.com/rspec/rspec-expectations/v/3-0/docs/built-in-matchers)
20
+
21
+ **A full list of matchers examples can be found in the [sample app specs.](spec_app/spec/matchers)**
22
+
23
+ Examples:
24
+ ```ruby
25
+ expect(nil).to be_nil
26
+ expect(true).not_to be_false
27
+
28
+ expect("super").to end_with("per")
29
+ expect{ 1/0 }.to raise_error(ZeroDivisionError)
30
+ expect{ raise ArgumentError.new("with a message") }.to raise_error(ArgumentError, /message/)
31
+ expect([1,2,3]).to have(3).items
32
+ expect("string").to respond_to(:upcase)
33
+ ```
34
+
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,9 @@
1
+ unless defined?(Motion::Project::Config)
2
+ raise "This file must be required within a RubyMotion project Rakefile."
3
+ end
4
+
5
+ Motion::Project::App.setup do |app|
6
+ Dir.glob(File.join(File.dirname(__FILE__), 'motion-expect/**/*.rb')).sort.reverse.each do |file|
7
+ app.spec_files << file
8
+ end
9
+ end
@@ -0,0 +1,4 @@
1
+ class Bacon::Context
2
+ include MotionExpect::Expectation::BaconContext
3
+ include MotionExpect::Matcher::BaconContext
4
+ end
@@ -0,0 +1,4 @@
1
+ module MotionExpect
2
+ class FailedExpectation < RuntimeError; end
3
+ class InvalidMatcher < RuntimeError; end
4
+ end
@@ -0,0 +1,37 @@
1
+ module MotionExpect
2
+ class Expectation
3
+ module BaconContext
4
+ def expect(subject = nil, &block)
5
+ Expectation.new(subject, &block)
6
+ end
7
+ end
8
+
9
+ def initialize(subject, &subject_block)
10
+ @subject = subject
11
+ @subject_block = subject_block
12
+ end
13
+
14
+ def to(matcher)
15
+ fail(matcher, false) unless matcher_passes(matcher)
16
+ assert
17
+ end
18
+
19
+ def not_to(matcher)
20
+ fail(matcher, true) if matcher_passes(matcher)
21
+ assert
22
+ end
23
+ alias_method :to_not, :not_to
24
+
25
+ def matcher_passes(matcher)
26
+ matcher.matches?(@subject, &@subject_block)
27
+ end
28
+
29
+ def fail(matcher, negated)
30
+ raise matcher.fail!(@subject, negated, &@subject_block)
31
+ end
32
+
33
+ def assert
34
+ true.should == true
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,100 @@
1
+ module MotionExpect
2
+ class FailMessageRenderer
3
+ def self.expectation(negated)
4
+ "#{negated ? " not" : ""} expected"
5
+ end
6
+
7
+ def self.message_for_be_false(negated, subject)
8
+ "#{subject.inspect}#{expectation(negated)} to be false"
9
+ end
10
+
11
+ def self.message_for_be_true(negated, subject)
12
+ "#{subject.inspect}#{expectation(negated)} to be true"
13
+ end
14
+
15
+ def self.message_for_be_nil(negated, subject)
16
+ "#{subject.inspect}#{expectation(negated)} to be nil"
17
+ end
18
+
19
+ def self.message_for_be(negated, subject, method_name, values)
20
+ message = "#{subject.inspect} ##{method_name}"
21
+ message += "(#{values.map(&:inspect).join(', ')})" unless values.empty?
22
+ message += "#{expectation(negated)} to return true"
23
+ message
24
+ end
25
+
26
+ def self.message_for_be_within(negated, subject, range, center_value)
27
+ "#{subject.inspect}#{expectation(negated)} to be within #{range} of #{center_value}"
28
+ end
29
+
30
+ def self.message_for_change(negated, change_amount, value_diff)
31
+ message = "Block#{expectation(negated)} to change value"
32
+ message += " by #{change_amount}" if change_amount
33
+ message += " but changed by #{value_diff}" if change_amount && !negated
34
+ message
35
+ end
36
+
37
+ def self.message_for_end_with(negated, subject, end_string)
38
+ "#{subject.inspect}#{expectation(negated)} to end with #{end_string.inspect}"
39
+ end
40
+
41
+ def self.message_for_start_with(negated, subject, start_string)
42
+ "#{subject.inspect}#{expectation(negated)} to start with #{start_string.inspect}"
43
+ end
44
+
45
+ def self.message_for_be_equal(negated, subject, value)
46
+ "#{subject.inspect}#{expectation(negated)} to be same object as #{value.inspect}"
47
+ end
48
+
49
+ def self.message_for_be_eq(negated, subject, value)
50
+ "#{subject.inspect}#{expectation(negated)} to be == to #{value.inspect}"
51
+ end
52
+
53
+ def self.message_for_have_generic(negated, subject, method_name, values)
54
+ message = "#{subject.inspect} #has_#{method_name}?"
55
+ message += "(#{values.map(&:inspect).join(', ')})" unless values.empty?
56
+ message += "#{expectation(negated)} to return true"
57
+ message
58
+ end
59
+
60
+ def self.message_for_have_items(negated, subject, expected_number_of_items, actual_number_of_items, key_type_name)
61
+ message = "#{subject.inspect}#{expectation(negated)} to have #{expected_number_of_items} #{key_type_name}"
62
+ message += " but had #{actual_number_of_items}" unless negated
63
+ message
64
+ end
65
+
66
+ def self.message_for_include(negated, subject, values)
67
+ values_message = values.size == 1 ? values.first : values
68
+ message = "#{subject.inspect}#{expectation(negated)} to include #{values_message.inspect}"
69
+ message
70
+ end
71
+
72
+ def self.message_for_match_array(negated, subject_array, expected_array)
73
+ message = "#{subject_array.inspect}#{expectation(negated)} to match array"
74
+ message += " #{expected_array.inspect}"
75
+ message
76
+ end
77
+
78
+ def self.message_for_match(negated, subject, match)
79
+ "#{subject.inspect}#{expectation(negated)} to match #{match.inspect}"
80
+ end
81
+
82
+ def self.message_for_raise_error(negated, show_class, error_class, show_message, error_message, rescued_exception)
83
+ message = "Block#{expectation(negated)} to raise error"
84
+ message += " of type #{error_class}" if show_class
85
+ message += " with message matching #{error_message.inspect}" if show_message
86
+ message += " but was #{rescued_exception.inspect}" if rescued_exception && !negated
87
+ message
88
+ end
89
+
90
+ def self.message_for_respond_to(negated, subject, method_name, number_of_args)
91
+ message = "#{subject.inspect}#{expectation(negated)} to respond to ##{method_name}"
92
+ message += " with #{number_of_args} arguments" if number_of_args
93
+ message
94
+ end
95
+
96
+ def self.message_for_satisfy(negated)
97
+ "Block#{expectation(negated)} to satisfy condition"
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,11 @@
1
+ module MotionExpect; module Matcher
2
+ class Be < SingleMethod
3
+ def initialize(value)
4
+ super(:equal?, value)
5
+ end
6
+
7
+ def fail_message(subject, negated)
8
+ FailMessageRenderer.message_for_be_equal(negated, subject, @values.first)
9
+ end
10
+ end
11
+ end; end
@@ -0,0 +1,12 @@
1
+ module MotionExpect; module Matcher
2
+ class BeFalse
3
+ def matches?(value)
4
+ !value
5
+ end
6
+
7
+ def fail!(subject, negated)
8
+ message = FailMessageRenderer.message_for_be_false(negated, subject)
9
+ raise FailedExpectation.new(message)
10
+ end
11
+ end
12
+ end; end
@@ -0,0 +1,7 @@
1
+ module MotionExpect; module Matcher
2
+ class BeGeneric < SingleMethod
3
+ def initialize(method_name, *values)
4
+ super("#{method_name}?", *values)
5
+ end
6
+ end
7
+ end; end
@@ -0,0 +1,11 @@
1
+ module MotionExpect; module Matcher
2
+ class BeNil
3
+ def matches?(value)
4
+ value == nil
5
+ end
6
+
7
+ def fail!(subject, negated)
8
+ raise FailedExpectation.new(FailMessageRenderer.message_for_be_nil(negated, subject))
9
+ end
10
+ end
11
+ end; end
@@ -0,0 +1,11 @@
1
+ module MotionExpect; module Matcher
2
+ class BeTrue
3
+ def matches?(value)
4
+ value == true
5
+ end
6
+
7
+ def fail!(subject, negated)
8
+ raise FailedExpectation.new(FailMessageRenderer.message_for_be_true(negated, subject))
9
+ end
10
+ end
11
+ end; end
@@ -0,0 +1,21 @@
1
+ module MotionExpect; module Matcher
2
+ class BeWithin
3
+ def initialize(range)
4
+ @range = range
5
+ end
6
+
7
+ def of(center_value)
8
+ @center_value = center_value
9
+ self
10
+ end
11
+
12
+ def matches?(subject)
13
+ raise InvalidMatcher.new("be_within matcher incomplete. Missing .of value") unless @center_value
14
+ (subject - @center_value).abs <= @range
15
+ end
16
+
17
+ def fail!(subject, negated)
18
+ raise FailedExpectation.new(FailMessageRenderer.message_for_be_within(negated, subject, @range, @center_value))
19
+ end
20
+ end
21
+ end; end
@@ -0,0 +1,28 @@
1
+ module MotionExpect; module Matcher
2
+ class Change
3
+ def initialize(change_block)
4
+ @change_block = change_block
5
+ end
6
+
7
+ def by(amount)
8
+ @change_amount = amount
9
+ self
10
+ end
11
+
12
+ def matches?(subject, &expectation_block)
13
+ old_value = @change_block.call
14
+ expectation_block.call
15
+ new_value = @change_block.call
16
+ if @change_amount
17
+ @value_diff = new_value - old_value
18
+ @value_diff == @change_amount
19
+ else
20
+ new_value != old_value
21
+ end
22
+ end
23
+
24
+ def fail!(subject, negated)
25
+ raise FailedExpectation.new(FailMessageRenderer.message_for_change(negated, @change_amount, @value_diff))
26
+ end
27
+ end
28
+ end; end
@@ -0,0 +1,15 @@
1
+ module MotionExpect; module Matcher
2
+ class EndWith
3
+ def initialize(end_string)
4
+ @end_string = end_string
5
+ end
6
+
7
+ def matches?(subject)
8
+ subject[-@end_string.size..-1] == @end_string
9
+ end
10
+
11
+ def fail!(subject, negated)
12
+ raise FailedExpectation.new(FailMessageRenderer.message_for_end_with(negated, subject, @end_string))
13
+ end
14
+ end
15
+ end; end
@@ -0,0 +1,11 @@
1
+ module MotionExpect; module Matcher
2
+ class Eq < SingleMethod
3
+ def initialize(value)
4
+ super(:==, value)
5
+ end
6
+
7
+ def fail_message(subject, negated)
8
+ FailMessageRenderer.message_for_be_eq(negated, subject, @values.first)
9
+ end
10
+ end
11
+ end; end
@@ -0,0 +1,9 @@
1
+ module MotionExpect
2
+ module Matcher
3
+ class Eql < SingleMethod
4
+ def initialize(value)
5
+ super(:eql?, value)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,16 @@
1
+ module MotionExpect; module Matcher
2
+ class HaveGeneric
3
+ def initialize(method_name, *args)
4
+ @method_name = method_name
5
+ @args = args
6
+ end
7
+
8
+ def matches?(subject)
9
+ subject.send("has_#{@method_name}?", *@args)
10
+ end
11
+
12
+ def fail!(subject, negated)
13
+ raise FailedExpectation.new(FailMessageRenderer.message_for_have_generic(negated, subject, @method_name, @args))
14
+ end
15
+ end
16
+ end; end
@@ -0,0 +1,22 @@
1
+ module MotionExpect; module Matcher
2
+ class HaveItems
3
+ def initialize(number_of_items)
4
+ @number_of_items = number_of_items
5
+ end
6
+
7
+ def matches?(value)
8
+ value.size == @number_of_items
9
+ end
10
+
11
+ [:items, :item, :keys, :values].each do |key_type_name|
12
+ define_method(key_type_name) do
13
+ @key_type_name = key_type_name
14
+ self
15
+ end
16
+ end
17
+
18
+ def fail!(subject, negated)
19
+ raise FailedExpectation.new(FailMessageRenderer.message_for_have_items(negated, subject, @number_of_items, subject.size, @key_type_name))
20
+ end
21
+ end
22
+ end; end