pivotal/cedar — pull request #295 by xtreme-james-cooper (2014-10-31 17:37:09+00:00)
Title: "Implies" matcher

A simple implies matcher, for use in invariants [#294, #289]. Because in an invariant, unlike a regular hand-written unit test, the exact values of the variables at test-time may not be known, it may be necessary to add in conditionals to ensure the perpetual truth of the invariant:
```objectiveC
invariant(@"should display the appropriate popup on purchase-click", ^{
[subject.payNowButton sendActionsForControlEvent:UIControlEventTouchUpInside];
if (! [AlertviewHelper isViewControllerDisplayingAlertView: subject]) {
subject.confirmDialogue.displayed should be_truthy;
}
});
```
Adding in the implies logical connective as a matcher makes this simpler and more declarative:
```objectiveC
invariant(@"should display the appropriate popup on purchase-click", ^{
[subject.payNowButton sendActionsForControlEvent:UIControlEventTouchUpInside];

BOOL clickPossible = ! [AlertviewHelper isViewControllerDisplayingAlertView: subject];
clickPossible should imply(subject.confirmDialogue.displayed);
});
```

The implies matcher follows the standard logical connective semantics:

X | Y | X implies Y
---|---|----------------
T | T | T
T | F | F
F | T | T
F | F | T

Currently it only supports boolean arguments (or object arguments interpreted as nil/not nil). One possible improvement would be to upgrade it to a full-blown matcher-*combinator*, taking matchers as one or either argument, enabling the user to leverage the full scope of matchers available; although most matchers can be implemented reasonably efficiently as a boolean test (```X should be_instance_of(Y)``` as ```[x isKindOfClass: Y]```, for instance) so this doesn't seem as critical, and it would open the door to nested matcher combinators etc, which is probably not the road to go down just yet.