Skip to content

Instantly share code, notes, and snippets.

@itsthejb
Created January 28, 2014 16:47
Show Gist options
  • Save itsthejb/8671459 to your computer and use it in GitHub Desktop.
Save itsthejb/8671459 to your computer and use it in GitHub Desktop.
Expecta matcher for collection containing an instance of a given class
//
// EXPMatchers+containObject.h
// Created by Jonathan Crooke on 28/01/2014.
//
#import "Expecta.h"
/**
* Match a collection that contains at least one object that is
* an instance of expected
*/
EXPMatcherInterface(containInstanceOf, (Class expected));
/**
* Match a collection that contains at least one object that is
* a kind of expected
*/
EXPMatcherInterface(containKindOf, (Class expected));
// TODO: master matcher that uses a block?
//
// EXPMatchers+containObject.m
// Created by Jonathan Crooke on 28/01/2014.
//
EXPMatcherImplementationBegin(containInstanceOf, (Class expected)) {
BOOL actualIsNil = (actual == nil);
BOOL expectedIsNil = (expected == nil);
BOOL actualIsCompatible = (!actualIsNil &&
([actual isKindOfClass:[NSString class]] ||
[actual respondsToSelector:@selector(count)]));
__block NSArray *matches = nil;
prerequisite(^BOOL{
return actualIsCompatible && !expectedIsNil;
});
match(^BOOL{
if (actualIsCompatible) {
matches = [actual filteredArrayUsingPredicate:
[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject,
NSDictionary *bindings)
{
return [evaluatedObject class] == expected;
}]];
return !!matches.count;
}
return NO;
});
NSString*(^incompatibilityMessage)(void) = ^NSString* (void) {
if(!actualIsCompatible)
return [NSString stringWithFormat:
@"%@ is not an instance of NSString, "
"NSArray, NSSet, NSOrderedSet, or NSDictionary",
EXPDescribeObject(actual)];
if(actualIsNil)
return @"the actual value is nil/null";
if(expectedIsNil)
return @"the expected value is nil/null";
return nil;
};
failureMessageForTo(^NSString *{
return incompatibilityMessage() ?:
[NSString stringWithFormat:
@"expected: collection containing at least one instance of %@, "
"got: collection containing %@",
[expected class], actual];
});
failureMessageForNotTo(^NSString *{
return incompatibilityMessage() ?:
[NSString stringWithFormat:
@"expected: collection not containing any instances of %@, "
"got: collection containing %@, %d instance(s) of %@",
[expected class], matches, matches.count, [expected class]];
});
}
EXPMatcherImplementationEnd
#pragma mark -
EXPMatcherImplementationBegin(containKindOf, (Class expected)) {
BOOL actualIsNil = (actual == nil);
BOOL expectedIsNil = (expected == nil);
BOOL actualIsCompatible = (!actualIsNil &&
([actual isKindOfClass:[NSString class]] ||
[actual respondsToSelector:@selector(count)]));
__block NSArray *matches = nil;
prerequisite(^BOOL{
return actualIsCompatible && !expectedIsNil;
});
match(^BOOL{
if (actualIsCompatible) {
matches = [actual filteredArrayUsingPredicate:
[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject,
NSDictionary *bindings)
{
return [evaluatedObject isKindOfClass:[expected class]];
}]];
return !!matches.count;
}
return NO;
});
NSString*(^incompatibilityMessage)(void) = ^NSString* (void) {
if(!actualIsCompatible)
return [NSString stringWithFormat:
@"%@ is not an instance of NSString, "
"NSArray, NSSet, NSOrderedSet, or NSDictionary",
EXPDescribeObject(actual)];
if(actualIsNil)
return @"the actual value is nil/null";
if(expectedIsNil)
return @"the expected value is nil/null";
return nil;
};
failureMessageForTo(^NSString *{
return incompatibilityMessage() ?:
[NSString stringWithFormat:
@"expected: collection containing at least one object that's a kind of %@, "
"got: collection containing %@",
[expected class], actual];
});
failureMessageForNotTo(^NSString *{
return incompatibilityMessage() ?:
[NSString stringWithFormat:
@"expected: collection not containing any objects that are a kind of %@, "
"got: collection containing %@, %d instance(s) of %@",
[expected class], matches, matches.count, [expected class]];
});
}
EXPMatcherImplementationEnd
@itsthejb
Copy link
Author

Copy & paste 😞, TODO: DRY out, and block matcher

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment