org.assertj.vavr.api.AbstractSeqAssert Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of assertj-vavr Show documentation
Show all versions of assertj-vavr Show documentation
Rich and fluent assertions for testing Vavr tools
/*
* 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.
*
* Copyright 2017-2021 the original author or authors.
*/
package org.assertj.vavr.api;
import io.vavr.collection.Seq;
import org.assertj.core.api.AbstractAssert;
import org.assertj.core.api.Condition;
import org.assertj.core.api.IndexedObjectEnumerableAssert;
import org.assertj.core.data.Index;
import org.assertj.core.internal.ComparatorBasedComparisonStrategy;
import org.assertj.core.internal.ComparisonStrategy;
import org.assertj.core.internal.StandardComparisonStrategy;
import org.assertj.core.util.CheckReturnValue;
import java.util.Comparator;
import java.util.function.Consumer;
import static java.lang.String.format;
import static org.assertj.core.error.ShouldBeSorted.shouldHaveComparableElementsAccordingToGivenComparator;
import static org.assertj.core.error.ShouldContainAtIndex.shouldContainAtIndex;
import static org.assertj.core.error.ShouldNotBeEmpty.shouldNotBeEmpty;
import static org.assertj.core.error.ShouldNotContainAtIndex.shouldNotContainAtIndex;
import static org.assertj.core.util.Preconditions.checkNotNull;
import static org.assertj.vavr.api.SeqShouldBeAtIndex.shouldBeAtIndex;
import static org.assertj.vavr.api.SeqShouldBeSorted.*;
import static org.assertj.vavr.api.SeqShouldHaveAtIndex.shouldHaveAtIndex;
/**
* Assertions for {@link Seq}.
*
* @param the "self" type of this assertion class.
* @param type of elements contained in the {@link Seq}.
* @author Michał Chmielarz
*/
abstract class AbstractSeqAssert,
ACTUAL extends Seq extends ELEMENT>,
ELEMENT,
ELEMENT_ASSERT extends AbstractAssert>
extends AbstractTraversableAssert
implements IndexedObjectEnumerableAssert {
private ComparisonStrategy seqElementComparisonStrategy;
AbstractSeqAssert(ACTUAL elements, Class> selfType) {
super(elements, selfType);
this.seqElementComparisonStrategy = StandardComparisonStrategy.instance();
}
/**
* Use given custom comparator instead of relying on actual type A equals
method to compare the
* {@link Seq} element's object for incoming assertion checks.
*
* @param customComparator the comparator to use for incoming assertion checks.
* @return {@code this} assertion object.
* @throws NullPointerException if the given comparator is {@code null}.
*/
@CheckReturnValue
public SELF usingElementComparator(Comparator super ELEMENT> customComparator) {
seqElementComparisonStrategy = new ComparatorBasedComparisonStrategy(customComparator);
return myself;
}
/**
* Verifies that the actual {@link Seq} contains the given object at the given index.
*
* Example:
*
Seq<Ring> elvesRings = List.of(vilya, nenya, narya);
*
* // assertions will pass
* assertThat(elvesRings).contains(vilya, atIndex(0));
* assertThat(elvesRings).contains(nenya, atIndex(1));
* assertThat(elvesRings).contains(narya, atIndex(2));
*
* // assertions will fail
* assertThat(elvesRings).contains(vilya, atIndex(1));
* assertThat(elvesRings).contains(nenya, atIndex(2));
* assertThat(elvesRings).contains(narya, atIndex(0));
*
* @param value the object to look for.
* @param index the index where the object should be stored in the actual group.
* @return this assertion object.
* @throws AssertionError if the actual group is {@code null} or empty.
* @throws NullPointerException if the given {@code Index} is {@code null}.
* @throws IndexOutOfBoundsException if the value of the given {@code Index} is equal to or greater than the size of the actual
* group.
* @throws AssertionError if the actual group does not contain the given object at the given index.
*/
public SELF contains(ELEMENT value, Index index) {
isNotNull();
assertNotEmpty();
assertIndexIsValid(index);
Object actualElement = actual.get(index.value);
if (!seqElementComparisonStrategy.areEqual(actualElement, value)) {
throwAssertionError(shouldContainAtIndex(actual, value, index, actual.get(index.value)));
}
return myself;
}
/**
* Verifies that the actual group does not contain the given object at the given index.
*
* Example:
*
Seq<Ring> elvesRings = List.of(vilya, nenya, narya);
*
* // assertions will pass
* assertThat(elvesRings).contains(vilya, atIndex(1));
* assertThat(elvesRings).contains(nenya, atIndex(2));
* assertThat(elvesRings).contains(narya, atIndex(0));
*
* // assertions will fail
* assertThat(elvesRings).contains(vilya, atIndex(0));
* assertThat(elvesRings).contains(nenya, atIndex(1));
* assertThat(elvesRings).contains(narya, atIndex(2));
*
* @param value the object to look for.
* @param index the index where the object should not be stored in the actual group.
* @return this assertion object.
* @throws AssertionError if the actual group is {@code null}.
* @throws NullPointerException if the given {@code Index} is {@code null}.
* @throws AssertionError if the actual group contains the given object at the given index.
*/
public SELF doesNotContain(ELEMENT value, Index index) {
isNotNull();
assertNotEmpty();
assertIndexIsValid(index);
Object actualElement = actual.get(index.value);
if (seqElementComparisonStrategy.areEqual(actualElement, value)) {
throwAssertionError(shouldNotContainAtIndex(actual, value, index));
}
return myself;
}
/**
* Verifies that the actual object at the given index in the actual group satisfies the given condition.
*
* @param condition the given condition.
* @param index the index where the object should be stored in the actual group.
* @return this assertion object.
* @throws AssertionError if the given {@link Seq} is {@code null} or empty.
* @throws NullPointerException if the given {@code Index} is {@code null}.
* @throws IndexOutOfBoundsException if the value of the given {@code Index} is equal to or greater than the size of
* the given {@link Seq}.
* @throws NullPointerException if the given {@code Condition} is {@code null}.
* @throws AssertionError if the value in the given {@link Seq} at the given index does not satisfy the given
* {@code Condition} .
*/
public SELF has(Condition super ELEMENT> condition, Index index) {
assertConditionIsMetAtIndex(
condition,
index,
() -> throwAssertionError(shouldHaveAtIndex(actual, condition, index, actual.get(index.value)))
);
return myself;
}
/**
* Verifies that the actual object at the given index in the actual group satisfies the given condition (alias of {@link #has(Condition, Index)}).
*
* @param condition the given condition.
* @param index the index where the object should be stored in the actual group.
* @return this assertion object.
* @throws AssertionError if the given {@link Seq} is {@code null} or empty.
* @throws NullPointerException if the given {@code Index} is {@code null}.
* @throws IndexOutOfBoundsException if the value of the given {@code Index} is equal to or greater than the size of
* the given {@link Seq}.
* @throws NullPointerException if the given {@code Condition} is {@code null}.
* @throws AssertionError if the value in the given {@link Seq} at the given index does not satisfy the given
* {@code Condition} .
*/
public SELF is(Condition super ELEMENT> condition, Index index) {
assertConditionIsMetAtIndex(
condition,
index,
() -> throwAssertionError(shouldBeAtIndex(actual, condition, index, actual.get(index.value)))
);
return myself;
}
/**
* Verifies that the actual sequence is sorted in ascending order according to the natural ordering of its elements.
*
* All sequence elements must implement the {@link Comparable} interface and must be mutually comparable (that is,
* e1.compareTo(e2) must not throw a ClassCastException for any elements e1 and e2 in the sequence), examples :
*
* - a sequence composed of {"a1", "a2", "a3"} is ok because the element type (String) is Comparable
* - a sequence composed of Rectangle {r1, r2, r3} is NOT ok because Rectangle is not Comparable
* - a sequence composed of {True, "abc", False} is NOT ok because elements are not mutually comparable
*
* Empty sequences are considered sorted.
Unique element sequences are considered sorted unless the element type is not Comparable.
*
* @return {@code this} assertion object.
* @throws AssertionError if the actual sequence is not sorted in ascending order according to the natural ordering of its
* elements.
* @throws AssertionError if the actual sequence is null
.
* @throws AssertionError if the actual sequence element type does not implement {@link Comparable}.
* @throws AssertionError if the actual sequence elements are not mutually {@link Comparable}.
*/
public SELF isSorted() {
isNotNull();
if (seqElementComparisonStrategy instanceof ComparatorBasedComparisonStrategy) {
// instead of comparing elements with their natural comparator, use the one set by client.
Comparator> comparator = ((ComparatorBasedComparisonStrategy) seqElementComparisonStrategy).getComparator();
assertIsSortedAccordingToComparator(comparator);
return myself;
}
try {
// sorted assertion is only relevant if elements are Comparable, we assume they are
Seq> comparableSequence = actual.map(e -> (Comparable