KWUserDefinedMatcher.m 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. //
  2. // KWUserDefinedMatcher.m
  3. // Kiwi
  4. //
  5. // Created by Luke Redpath on 16/06/2011.
  6. // Copyright 2011 Allen Ding. All rights reserved.
  7. //
  8. #import "KWUserDefinedMatcher.h"
  9. @interface KWUserDefinedMatcher(){}
  10. @property (nonatomic, copy) NSInvocation *invocation;
  11. @end
  12. @implementation KWUserDefinedMatcher
  13. @synthesize selector;
  14. @synthesize failureMessageForShould;
  15. @synthesize failureMessageForShouldNot;
  16. @synthesize matcherBlock;
  17. @synthesize description;
  18. + (id)matcherWithSubject:(id)aSubject block:(KWUserDefinedMatcherBlock)aBlock {
  19. return [[self alloc] initWithSubject:aSubject block:aBlock];
  20. }
  21. - (id)initWithSubject:(id)aSubject block:(KWUserDefinedMatcherBlock)aBlock {
  22. self = [super initWithSubject:aSubject];
  23. if (self) {
  24. matcherBlock = [aBlock copy];
  25. self.description = @"match user defined matcher";
  26. }
  27. return self;
  28. }
  29. - (BOOL)evaluate {
  30. BOOL result;
  31. if (self.invocation.methodSignature.numberOfArguments == 3) {
  32. id argument;
  33. [self.invocation getArgument:&argument atIndex:2];
  34. result = matcherBlock(self.subject, argument);
  35. } else {
  36. result = matcherBlock(self.subject);
  37. }
  38. return result;
  39. }
  40. #pragma mark - Message forwarding
  41. - (BOOL)respondsToSelector:(SEL)aSelector {
  42. if (aSelector == self.selector) {
  43. return YES;
  44. }
  45. return [super respondsToSelector:aSelector];
  46. }
  47. - (void)forwardInvocation:(NSInvocation *)anInvocation {
  48. _invocation = anInvocation;
  49. }
  50. - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
  51. if (aSelector == self.selector) {
  52. NSString *selectorString = NSStringFromSelector(self.selector);
  53. /**
  54. * TODO: find a way of doing this that:
  55. * - doesn't require dummy methods (create the method signatures manually)
  56. * - supports an unlimited number of arguments
  57. */
  58. if ([selectorString hasSuffix:@":"]) {
  59. return [self methodSignatureForSelector:@selector(matcherMethodWithArgument:)];
  60. } else {
  61. return [self methodSignatureForSelector:@selector(matcherMethodWithoutArguments)];
  62. }
  63. }
  64. return [super methodSignatureForSelector:aSelector];
  65. }
  66. - (void)matcherMethodWithoutArguments {}
  67. - (void)matcherMethodWithArgument:(id)argument {}
  68. @end
  69. #pragma mark -
  70. @interface KWUserDefinedMatcherBuilder ()
  71. @property (nonatomic, strong) KWUserDefinedMatcher *matcher;
  72. @property (nonatomic, copy) KWUserDefinedMatcherMessageBlock failureMessageForShouldBlock;
  73. @property (nonatomic, copy) KWUserDefinedMatcherMessageBlock failureMessageForShouldNotBlock;
  74. @property (nonatomic, copy) NSString *matcherBuilderDescription;
  75. @end
  76. @implementation KWUserDefinedMatcherBuilder
  77. + (id)builder {
  78. return [self builderForSelector:nil];
  79. }
  80. + (id)builderForSelector:(SEL)aSelector {
  81. return [[self alloc] initWithSelector:aSelector];
  82. }
  83. - (id)initWithSelector:(SEL)aSelector {
  84. self = [super init];
  85. if (self) {
  86. _matcher = [[KWUserDefinedMatcher alloc] init];
  87. _matcher.selector = aSelector;
  88. }
  89. return self;
  90. }
  91. - (NSString *)key {
  92. return NSStringFromSelector(self.matcher.selector);
  93. }
  94. #pragma mark - Configuring The Matcher
  95. - (void)match:(KWUserDefinedMatcherBlock)block {
  96. self.matcher.matcherBlock = block;
  97. }
  98. - (void)failureMessageForShould:(KWUserDefinedMatcherMessageBlock)block {
  99. self.failureMessageForShouldBlock = block;
  100. }
  101. - (void)failureMessageForShouldNot:(KWUserDefinedMatcherMessageBlock)block {
  102. self.failureMessageForShouldNotBlock = block;
  103. }
  104. - (void)description:(NSString *)aDescription {
  105. self.matcherBuilderDescription = aDescription;
  106. }
  107. #pragma mark - Buiding The Matcher
  108. - (KWUserDefinedMatcher *)buildMatcherWithSubject:(id)subject {
  109. [self.matcher setSubject:subject];
  110. if (self.failureMessageForShouldBlock) {
  111. [self.matcher setFailureMessageForShould:self.failureMessageForShouldBlock(subject)];
  112. }
  113. if (self.failureMessageForShouldNotBlock) {
  114. [self.matcher setFailureMessageForShouldNot:self.failureMessageForShouldNotBlock(subject)];
  115. }
  116. if (self.matcherBuilderDescription) {
  117. [self.matcher setDescription:self.matcherBuilderDescription];
  118. }
  119. return self.matcher;
  120. }
  121. @end