#import "ExpectationGroupTest.h"

@interface ExpectationGroupTest (Privates)

- (void)assertIsNullExpectation:(AbstractExpectation *)expectation withName:(NSString *)name;
- (void)assertVerifyPassesForGroup:(ExpectationGroup *)expectationGroup;
- (void)assertVerifyRaisesExceptionForGroup:(ExpectationGroup *)expectationGroup withReason:(NSString *)reason;

@end

@implementation ExpectationGroupTest

- (void)testReturnsNullCounterForNotAddedCounter {
    ExpectationGroup *expectationGroup = [[[ExpectationGroup alloc] initWithName:@"My Group"] autorelease];
    ExpectationCounter *counter = [expectationGroup counterNamed:@"My Counter"];
    
    [self assertIsNullExpectation:counter withName:@"My Counter"];
}

- (void)testVerifyAddedCounterPasses {
    ExpectationGroup *expectationGroup = [[[ExpectationGroup alloc] initWithName:@"My Group"] autorelease];

    [[expectationGroup addedCounterWithName:@"My Counter"] setExpectedCount:1];
    [[expectationGroup counterNamed:@"My Counter"] increment];

    [self assertVerifyPassesForGroup:expectationGroup];
}

- (void)testVerifyAddedCounterFails {
    ExpectationGroup *expectationGroup = [[[ExpectationGroup alloc] initWithName:@"My Group"] autorelease];

    [[expectationGroup addedCounterWithName:@"My Counter"] setExpectedCount:1];

    [self assertVerifyRaisesExceptionForGroup:expectationGroup withReason:@"My Counter expected 1, was 0"];
}

- (void)testReturnsNullValueForNotAddedValue {
    ExpectationGroup *expectationGroup = [[[ExpectationGroup alloc] initWithName:@"My Group"] autorelease];
    ExpectationValue *value = [expectationGroup valueNamed:@"My Value"];

    [self assertIsNullExpectation:value withName:@"My Value"];
}

- (void)testVerifyAddedValuePasses {
    ExpectationGroup *expectationGroup = [[[ExpectationGroup alloc] initWithName:@"My Group"] autorelease];

    [[expectationGroup addedValueWithName:@"My Value"] setExpectedObject:@"Expected"];
    [[expectationGroup valueNamed:@"My Value"] setActualObject:@"Expected"];

    [self assertVerifyPassesForGroup:expectationGroup];
}

- (void)testVerifyAddedValueFails {
    ExpectationGroup *expectationGroup = [[[ExpectationGroup alloc] initWithName:@"My Group"] autorelease];

    [[expectationGroup addedValueWithName:@"My Value"] setExpectedObject:@"Expected"];

    [self assertVerifyRaisesExceptionForGroup:expectationGroup withReason:@"My Value expected Expected, was (null)"];
}

- (void)testReturnsNullListForNotAddedList {
    ExpectationGroup *expectationGroup = [[[ExpectationGroup alloc] initWithName:@"My Group"] autorelease];
    ExpectationList *list = [expectationGroup listNamed:@"My List"];

    [self assertIsNullExpectation:list withName:@"My List"];
}

- (void)testVerifyAddedListPasses {
    ExpectationGroup *expectationGroup = [[[ExpectationGroup alloc] initWithName:@"My Group"] autorelease];

    [[expectationGroup addedListWithName:@"My List"] addExpectedObject:@"Expected"];
    [[expectationGroup listNamed:@"My List"] addActualObject:@"Expected"];

    NS_DURING
        [expectationGroup verify];
    NS_HANDLER
        [self fail:@"Shouldn't raise exception"];
    NS_ENDHANDLER    
}

- (void)testVerifyAddedListFails {
    ExpectationGroup *expectationGroup = [[[ExpectationGroup alloc] initWithName:@"My Group"] autorelease];

    [[expectationGroup addedListWithName:@"My List"] addExpectedObject:@"Expected"];

    [self assertVerifyRaisesExceptionForGroup:expectationGroup withReason:@"My List expected (Expected), was ()"];    
}

- (void)testReturnsNullSetForNotAddedSet {
    ExpectationGroup *expectationGroup = [[[ExpectationGroup alloc] initWithName:@"My Group"] autorelease];
    ExpectationSet *set = [expectationGroup setNamed:@"My Set"];

    [self assertIsNullExpectation:set withName:@"My Set"];
}

- (void)testVerifyAddedSetPasses {
    ExpectationGroup *expectationGroup = [[[ExpectationGroup alloc] initWithName:@"My Group"] autorelease];

    [[expectationGroup addedSetWithName:@"My Set"] addExpectedObject:@"Expected"];
    [[expectationGroup setNamed:@"My Set"] addActualObject:@"Expected"];

    [self assertVerifyPassesForGroup:expectationGroup];
}

- (void)testVerifyAddedSetFails {
    ExpectationGroup *expectationGroup = [[[ExpectationGroup alloc] initWithName:@"My Group"] autorelease];

    [[expectationGroup addedSetWithName:@"My Set"] addExpectedObject:@"Expected"];

    [self assertVerifyRaisesExceptionForGroup:expectationGroup withReason:@"My Set expected (Expected), was ()"];
}

@end

@implementation ExpectationGroupTest (Privates)

- (void)assertIsNullExpectation:(AbstractExpectation *)expectation withName:(NSString *)aName {
    [self assertNotNil:expectation];
    [self assertFalse:[expectation hasExpectations]];
    [self assertString:[expectation name] equals:[@"My Group." stringByAppendingString:aName]];
}

- (void)assertVerifyPassesForGroup:(ExpectationGroup *)expectationGroup {
    NS_DURING
        [expectationGroup verify];
    NS_HANDLER
        [self fail:@"Shouldn't raise exception"];
    NS_ENDHANDLER
}

- (void)assertVerifyRaisesExceptionForGroup:(ExpectationGroup *)expectationGroup withReason:(NSString *)reason {
    NSException *exception = nil;

    NS_DURING
        [expectationGroup verify];
    NS_HANDLER
        exception = localException;
    NS_ENDHANDLER

    [self assertNotNil:exception message:@"Should raise exception"];
    [self assertString:[exception name] equals:@"AssertionFailedException"];
    [self assertString:[exception reason] equals:[@"My Group." stringByAppendingString:reason]];
}


@end
