Skip to content

Instantly share code, notes, and snippets.

@samstokes
Created October 8, 2011 02:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save samstokes/1271784 to your computer and use it in GitHub Desktop.
Save samstokes/1271784 to your computer and use it in GitHub Desktop.
[].should include_such_that {|item| p(item) }
commit e5e4aebccc334809c355b7387dc1469e18be2377
Author: Sam Stokes <sam@rapportive.com>
Date: Wed Oct 5 17:02:47 2011 -0700
[2, 4, 6].should_not include_such_that(&:odd?)
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index c6b006b..03aeec5 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -19,6 +19,7 @@ Spec::Runner.configure do |config|
config.include WebMock::API
config.include DataModelMatchers
config.include HashMatchers
+ config.include EnumerableMatchers
config.include StringMatchers
# If you're not using ActiveRecord you should remove these
diff --git a/spec/support/enumerable_matchers.rb b/spec/support/enumerable_matchers.rb
new file mode 100644
index 0000000..331fcbb
--- /dev/null
+++ b/spec/support/enumerable_matchers.rb
@@ -0,0 +1,46 @@
+module EnumerableMatchers
+ def include_such_that(predicate = nil, &block)
+ IncludeSuchThatMatcher.new(predicate, &block)
+ end
+ class IncludeSuchThatMatcher < Spec::Matchers::Matcher
+ def initialize(predicate = nil, &block)
+ predicate ||= block
+ raise ArgumentError, '".should include_such_that" takes a predicate (must use {} not do/end)' unless predicate.respond_to?(:call)
+
+ super :include_such_that do
+ match do |actual|
+ @passing = actual.select do |item|
+ begin
+ if item.is_a?(Array)
+ predicate.call(*item)
+ else
+ predicate.call(item)
+ end
+ rescue Spec::Expectations::ExpectationNotMetError
+ false
+ end
+ end
+ !@passing.empty?
+ end
+
+ failure_message_for_should do |actual|
+ "expected #{actual.class} to include an entry passing the predicate, but did not"
+ end
+
+ failure_message_for_should_not do |actual|
+ "expected #{actual.class} not to include any entries passing the predicate, but included #{@passing.map(&:inspect).join(', ')}"
+ end
+ end
+ end
+
+ def matches?(actual)
+ raise_block_syntax_error if block_given?
+ super
+ end
+
+ private
+ def raise_block_syntax_error
+ raise MatcherError, 'block passed to should or should_not include_such_that must use {} instead of do/end'
+ end
+ end
+end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment