/*******************************************************************************
* Copyright 2014 JHC Systems Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package jhc.redsniff.internal.expectations;
import static jhc.redsniff.core.Describer.newDescription;
import static jhc.redsniff.core.FindingExpectations.absenceOf;
import static jhc.redsniff.core.FindingExpectations.expectationOf;
import static jhc.redsniff.core.FindingExpectations.expectationOfSome;
import static jhc.redsniff.core.FindingExpectations.presenceOf;
import static jhc.redsniff.internal.core.CollectionOf.collectionOf;
import static jhc.redsniff.internal.finders.OnlyFinder.only;
import static jhc.redsniff.util.Util.failWith;
import jhc.redsniff.core.Finder;
import jhc.redsniff.core.MFinder;
import jhc.redsniff.core.SFinder;
import jhc.redsniff.internal.core.Quantity;
import jhc.redsniff.internal.predicates.SingleItemMatching;
import org.hamcrest.Matcher;
public class ExpectationChecker<C> {
private final C context;
public ExpectationChecker(C context) {
this.context = context;
}
public <I, Q extends Quantity<I>> void assertThe(FindingExpectation<I, Q, C> expectation) {
assertedResultOfChecking(expectation);
}
public <I, Q extends Quantity<I>> Object find(Finder<I, Q, C>finder) {
return quantityFoundBy(expectationOfSome(finder)).get();
}
public <I, Q extends Quantity<I>> Quantity<I> quantityFoundBy(FindingExpectation<I, Q, C> expectation) {
return thatWhichIsFoundBy(expectation);
}
public <I, Q extends Quantity<I>> boolean isSatisfied(FindingExpectation<I, Q, C> expectation) {
return isMet(expectation);
}
public <I, Q extends Quantity<I>> void assertAbsenceOf(Finder<I, Q, C>finder) {
assertThe(absenceOf(finder));
}
public <I, Q extends Quantity<I>> void assertPresenceOf(Finder<I, Q, C> finder) {
assertThe(presenceOf(finder));
}
public <I> void assertPresenceOf(Matcher<Integer> expectedNumberOfElements, MFinder<I, C>finder) {
assertThe(presenceOf(expectedNumberOfElements, finder));
}
public <I, Q extends Quantity<I>> void assertThatThe(Finder<I, Q, C> finder, Matcher<I> matcher) {
assertThe(expectationOf(SingleItemMatching.<I>singleItemMatches(matcher), only(finder)));
}
public <I, Q extends Quantity<I>> boolean isPresent(Finder<I, Q, C>finder) {
return isMet(expectationOfSome(finder));
}
//TODO this works now but would be better if it returned a higher level class/interface
public <C1, E0 extends C1> WithinEachContextChecker<C1,E0, C> inEachContextFoundBy(MFinder<E0, C> contextFinder){
return new WithinEachContextChecker<C1,E0, C>(collectionOf(context), contextFinder, null, "each");
}
//TODO this works now but would be better if it returned a higher level class/interface so inEach().inThe works
public <C1, E0 extends C1> WithinSingleContextChecker<C1,E0, C> inSingleContextFoundBy(SFinder<E0, C> contextFinder){
return new WithinSingleContextChecker<C1,E0, C>(this, contextFinder, null, " ");
}
private <E, Q extends Quantity<E>>
ExpectationCheckResult<E, Q> assertedResultOfChecking(FindingExpectation<E, Q, C> expectation) {
ExpectationCheckResult<E, Q> result = resultOfChecking(expectation);
if (!result.meetsExpectation())
failWithExpectationAndResultMessage(expectation, result);
return result;
}
public <E, Q extends Quantity<E>>
ExpectationCheckResult<E, Q> resultOfChecking(FindingExpectation<E, Q, C> expectation) {
return expectation.checkFrom(context);
}
public <E, Q extends Quantity<E>>
ExpectationCheckResult<E, Q> resultOfCheckingFailFast(FindingExpectation<E, Q, C> expectation) {
return expectation.checkFromFailFast(context);
}
public <E, Q extends Quantity<E>>
Q thatWhichIsFoundBy(FindingExpectation<E, Q, C> expectation) {
ExpectationCheckResult<E, Q> result = assertedResultOfChecking(expectation);
return result.foundQuantity();
}
public <E, Q extends Quantity<E>>
boolean isMet(FindingExpectation<E, Q, C> expectation) {
return resultOfChecking(expectation).meetsExpectation();
}
public <E, Q extends Quantity<E>>
void assertSatisfied(FindingExpectation<E, Q, C> expectation) {
assertedResultOfChecking(expectation);
}
protected <E, Q extends Quantity<E>> void failWithExpectationAndResultMessage(
FindingExpectation<E, Q, C> expectation, ExpectationCheckResult<E, Q> result) {
failWith(newDescription()
.appendText("Expected: ")
.appendDescriptionOf(expectation)
.appendText("\nbut:\n")
.appendDescriptionOf(result));
}
public static <C> ExpectationChecker<C> checkerFor(C context){
return new ExpectationChecker<C>(context);
}
}