main
  1//
  2//  KWHaveValueMatcher.m
  3//  Kiwi
  4//
  5//  Created by Luke Redpath on 24/01/2011.
  6//  Copyright 2011 Allen Ding. All rights reserved.
  7//
  8
  9#import "KWHaveValueMatcher.h"
 10#import "KWGenericMatchingAdditions.h"
 11#import "KWGenericMatcher.h"
 12#import "KWFormatter.h"
 13
 14@interface KWHaveValueMatcher()
 15
 16#pragma mark -
 17#pragma mark Properties
 18
 19@property (nonatomic, retain) NSString *expectedKey;
 20@property (nonatomic, retain) NSString *expectedKeyPath;
 21@property (nonatomic, retain) id expectedValue;
 22
 23- (id)subjectValue;
 24
 25@end
 26
 27@implementation KWHaveValueMatcher
 28
 29@synthesize expectedKey, expectedKeyPath, expectedValue;
 30
 31- (void)dealloc
 32{
 33  [expectedKeyPath release];
 34  [expectedKey release];
 35  [expectedValue release];
 36  [super dealloc];
 37}
 38
 39#pragma mark -
 40#pragma mark Getting Matcher Strings
 41
 42+ (NSArray *)matcherStrings {
 43  return @[@"haveValue:forKey:",
 44          @"haveValueForKey:",
 45          @"haveValue:forKeyPath:",
 46          @"haveValueForKeyPath:"];
 47}
 48
 49#pragma mark -
 50#pragma mark Matching
 51
 52- (BOOL)evaluate {
 53  BOOL matched = NO;
 54
 55  @try {
 56    id value = [self subjectValue];
 57
 58    if (value) {
 59      matched = YES;
 60
 61      if (self.expectedValue) {
 62        matched = [self.expectedValue isEqualOrMatches:value];
 63      }
 64    }
 65  }
 66  @catch (NSException * e) {} // catch KVO non-existent key errors
 67
 68  return matched;
 69}
 70
 71- (NSString *)failureMessageForShould {
 72    if (self.expectedValue == nil) {
 73        return [NSString stringWithFormat:@"expected subject to have a value for key %@",
 74                                          [KWFormatter formatObject:self.expectedKey]];
 75    }
 76    id subjectValue = [self subjectValue];
 77    if (subjectValue) {
 78        return [NSString stringWithFormat:@"expected subject to have value %@ for key %@, but it had value %@ instead",
 79                                          [KWFormatter formatObject:self.expectedValue],
 80                                          [KWFormatter formatObject:self.expectedKey],
 81                                          [KWFormatter formatObject:subjectValue]];
 82    } else {
 83        return [NSString stringWithFormat:@"expected subject to have value %@ for key %@, but the key was not present",
 84                                          [KWFormatter formatObject:self.expectedValue],
 85                                          [KWFormatter formatObject:self.expectedKey]];
 86    }
 87}
 88
 89- (id)subjectValue
 90{
 91  id value = nil;
 92
 93  if (self.expectedKey) {
 94    value = [self.subject valueForKey:self.expectedKey];
 95  } else
 96  if (self.expectedKeyPath) {
 97    value = [self.subject valueForKeyPath:self.expectedKeyPath];
 98  }
 99  return value;
100}
101
102- (NSString *)description
103{
104  NSString *keyDescription = nil;
105
106  if (self.expectedKey) {
107    keyDescription = [NSString stringWithFormat:@"key %@", [KWFormatter formatObject:self.expectedKey]];
108  }
109  else {
110    keyDescription = [NSString stringWithFormat:@"keypath %@", [KWFormatter formatObject:self.expectedKeyPath]];
111  }
112
113  NSString *valueDescription = nil;
114
115  if (self.expectedValue) {
116    valueDescription = [NSString stringWithFormat:@"value %@", [KWFormatter formatObject:self.expectedValue]];
117  }
118  else {
119    valueDescription = @"value";
120  }
121
122  return [NSString stringWithFormat:@"have %@ for %@", valueDescription, keyDescription];
123}
124
125#pragma mark -
126#pragma mark Configuring Matchers
127
128- (void)haveValue:(id)value forKey:(NSString *)key;
129{
130    self.expectedKey = key;
131    self.expectedValue = value;
132}
133
134- (void)haveValue:(id)value forKeyPath:(NSString *)key;
135{
136    self.expectedKeyPath = key;
137    self.expectedValue = value;
138}
139
140- (void)haveValueForKey:(NSString *)key;
141{
142    self.expectedKey = key;
143    self.expectedValue = nil;
144}
145
146- (void)haveValueForKeyPath:(NSString *)keyPath;
147{
148    self.expectedKeyPath = keyPath;
149    self.expectedValue = nil;
150}
151
152@end