Skip to content

Commit

Permalink
#837: Fix attribute assertions to pass at the first matching element.…
Browse files Browse the repository at this point in the history
… Also update javadocs to reflect correct behaviour.
  • Loading branch information
picimako committed Jun 9, 2019
1 parent 3b9a978 commit ae1693a
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 40 deletions.
Expand Up @@ -10,15 +10,15 @@
public interface AttributeAssert<T> { public interface AttributeAssert<T> {


/** /**
* Checks if the list of elements all have the given property. * Checks if at least one element in a list of elements has the given property.
* *
* @param attribute the attribute to find * @param attribute the attribute to find
* @return a new assert object with the actual attribute value * @return a new assert object with the actual attribute value
*/ */
T hasAttribute(String attribute); T hasAttribute(String attribute);


/** /**
* Checks if the element or among a list of elements none has the given property. * Checks if the element doesn't have, or no element in a list of elements has, the given property.
* *
* @param attribute attribute to find the absence of * @param attribute attribute to find the absence of
* @return {@code this} assertion object. * @return {@code this} assertion object.
Expand Down
Expand Up @@ -9,71 +9,73 @@
public interface FluentAssert { public interface FluentAssert {


/** /**
* check if the element or list of elements contains the text * Checks if the element, or at least one element in a list of elements, contain the text.
* *
* @param textToFind text to find * @param textToFind text to find
* @return {@code this} assertion object. * @return {@code this} assertion object.
*/ */
AbstractAssert hasText(String textToFind); AbstractAssert hasText(String textToFind);


/** /**
* check if the element or list of elements matches the given regex * Checks if the element, or at least one element in a list of elements, matches the given regex
* *
* @param regexToBeMatched regex to be matched * @param regexToBeMatched regex to be matched
* @return {@code this} assertion object. * @return {@code this} assertion object.
*/ */
AbstractAssert hasTextMatching(String regexToBeMatched); AbstractAssert hasTextMatching(String regexToBeMatched);


/** /**
* check if the element or list of elements does not contain the text * Checks if the element does not contain, or none of the elements in a list of elements contain the text
* *
* @param textToFind text to find * @param textToFind text to find
* @return {@code this} assertion object. * @return {@code this} assertion object.
*/ */
AbstractAssert hasNotText(String textToFind); AbstractAssert hasNotText(String textToFind);


/** /**
* check if the element or list of elements has the given id * Checks if the element, or at least one element in a list of elements, has the given id
* *
* @param idToFind id to find * @param idToFind id to find
* @return {@code this} assertion object. * @return {@code this} assertion object.
*/ */
AbstractAssert hasId(String idToFind); AbstractAssert hasId(String idToFind);


/** /**
* check if the element or list of elements has the class * Checks if the element, or at least one element in a list of elements, has the class.
* <p>
* This is not an exact match validation of the value of the class attribute.
* *
* @param classToFind class to find * @param classToFind class to find
* @return {@code this} assertion object. * @return {@code this} assertion object.
*/ */
AbstractAssert hasClass(String classToFind); AbstractAssert hasClass(String classToFind);


/** /**
* check if the element or list of elements has given value * Check if the element, or at least one element in a list of elements, has given value
* *
* @param value value to find * @param value value to find
* @return {@code this} assertion object. * @return {@code this} assertion object.
*/ */
AbstractAssert hasValue(String value); AbstractAssert hasValue(String value);


/** /**
* check if the element or list of elements has given name * Checks if the element, or at least one element in a list of elements, has given name
* *
* @param name name to find * @param name name to find
* @return {@code this} assertion object. * @return {@code this} assertion object.
*/ */
AbstractAssert hasName(String name); AbstractAssert hasName(String name);


/** /**
* check if the element or list of elements has given tag * Checks if the element, or at least one element in a list of elements, has given tag
* *
* @param tagName tag name to find * @param tagName tag name to find
* @return {@code this} assertion object. * @return {@code this} assertion object.
*/ */
AbstractAssert hasTagName(String tagName); AbstractAssert hasTagName(String tagName);


/** /**
* check if the element or list of elements has property with given value * Checks if the element, or at least one element in a list of elements, has property with the exact given value
* *
* @param attribute attribute to find * @param attribute attribute to find
* @param value property value to match with actual * @param value property value to match with actual
Expand All @@ -82,7 +84,7 @@ public interface FluentAssert {
AbstractAssert hasAttributeValue(String attribute, String value); AbstractAssert hasAttributeValue(String attribute, String value);


/** /**
* check if the element or list of elements has given dimension * Checks if the element, or at least one element in a list of elements, has given dimension
* *
* @param dimension dimension to find * @param dimension dimension to find
* @return {@code this} assertion object. * @return {@code this} assertion object.
Expand Down
Expand Up @@ -168,16 +168,18 @@ public FluentListAssert hasAttributeValue(String attribute, String value) {
@Override @Override
public ListAssert<String> hasAttribute(String attribute) { public ListAssert<String> hasAttribute(String attribute) {
List<String> actualValues = actual.attributes(attribute); List<String> actualValues = actual.attributes(attribute);
if (actualValues.isEmpty() || actualValues.stream().anyMatch(Objects::isNull)) { checkListEmptiness(actualValues);
failWithMessage("Not all selected elements have attribute " + attribute); if (actualValues.stream().allMatch(Objects::isNull)) {
failWithMessage("No selected element has attribute " + attribute);
} }
return new ListAssert<>(actualValues); return new ListAssert<>(actualValues);
} }


@Override @Override
public FluentListAssert hasNotAttribute(String attribute) { public FluentListAssert hasNotAttribute(String attribute) {
List<String> actualValues = actual.attributes(attribute); List<String> actualValues = actual.attributes(attribute);
if (!actualValues.isEmpty() && actualValues.stream().anyMatch(Objects::nonNull)) { checkListEmptiness(actualValues);
if (actualValues.stream().anyMatch(Objects::nonNull)) {
failWithMessage("At least one selected element has attribute " + attribute); failWithMessage("At least one selected element has attribute " + attribute);
} }
return this; return this;
Expand Down
Expand Up @@ -8,22 +8,10 @@
public interface ListAttributeAssert extends AttributeAssert<ListAssert<String>> { public interface ListAttributeAssert extends AttributeAssert<ListAssert<String>> {


/** /**
* Checks if the list of elements all have the given property. * Checks if at least one of the elements in the list of elements has the given property.
* <p> * <p>
* It allows users to do not just presence validation but apply chained String assertions * It allows users to do not just presence validation but apply chained List assertions
* to further validate the attribute value. * to further validate the attribute values.
* <p>
* Examples:
* <p>
* Validating the presence of an attribute on all elements of a {@link org.fluentlenium.core.domain.FluentList}:
* <pre>
* assertThat(elementList).hasAttribute("href");
* </pre>
* <p>
* Validating both the presence of an attribute on all elements of a list, and the value of all of those attributes:
* <pre>
* assertThat(elementList).hasAttribute("href").matches("^https.*$");
* </pre>
* *
* @param attribute the attribute to find * @param attribute the attribute to find
* @return a new {@code ListAssert} object with the actual attribute values * @return a new {@code ListAssert} object with the actual attribute values
Expand Down
Expand Up @@ -14,11 +14,13 @@


import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.fluentlenium.assertj.AssertionTestSupport.assertThatAssertionErrorIsThrownBy; import static org.fluentlenium.assertj.AssertionTestSupport.assertThatAssertionErrorIsThrownBy;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;


/**
* Unit test for {@link FluentListAssert}.
*/
public class FluentListAssertTest { public class FluentListAssertTest {


@Mock @Mock
Expand Down Expand Up @@ -297,23 +299,27 @@ public void testHasAttributeValueKo() {
@Test @Test
public void shouldHaveAttribute() { public void shouldHaveAttribute() {
when(fluentList.attributes("name")).thenReturn(Lists.newArrayList("name-one", "name-two")); when(fluentList.attributes("name")).thenReturn(Lists.newArrayList("name-one", "name-two"));
assertThatCode(() -> listAssert.hasAttribute("name")).doesNotThrowAnyException(); listAssert.hasAttribute("name");
} }


@Test @Test
public void shouldFailWhenDoesNotHaveAttribute() { public void shouldFailWhenNoElementHasAttribute() {
assertThatAssertionErrorIsThrownBy(() -> listAssert.hasAttribute("name")); when(fluentList.attributes("name")).thenReturn(Lists.newArrayList(null, null));
assertThatAssertionErrorIsThrownBy(() -> listAssert.hasAttribute("name"))
.hasMessage("No selected element has attribute name");
} }


@Test @Test
public void shouldNotHaveAttribute() { public void shouldNotHaveAttribute() {
assertThatCode(() -> listAssert.hasNotAttribute("name")).doesNotThrowAnyException(); when(fluentList.attributes("name")).thenReturn(Lists.newArrayList(null, null));
listAssert.hasNotAttribute("name");
} }


@Test @Test
public void shouldFailWhenHasAttribute() { public void shouldFailWhenHasAttribute() {
when(fluentList.attributes("name")).thenReturn(Lists.newArrayList("name-one", "name-two")); when(fluentList.attributes("name")).thenReturn(Lists.newArrayList("name-one", "name-two"));
assertThatAssertionErrorIsThrownBy(() -> listAssert.hasNotAttribute("name")); assertThatAssertionErrorIsThrownBy(() -> listAssert.hasNotAttribute("name"))
.hasMessage("At least one selected element has attribute name");
} }


@Test @Test
Expand Down
Expand Up @@ -18,10 +18,10 @@ public void shouldHaveAttribute() {
} }


@Test @Test
public void shouldFailWhenDoesNotHaveAttribute() { public void shouldFailWhenNoElementHasAttribute() {
goTo(DEFAULT_URL); goTo(DEFAULT_URL);
assertThatAssertionErrorIsThrownBy(() -> assertThat($("input")).hasAttribute("style")) assertThatAssertionErrorIsThrownBy(() -> assertThat($("input")).hasAttribute("data-type"))
.hasMessage("Not all selected elements have attribute style"); .hasMessage("No selected element has attribute data-type");
} }


@Test @Test
Expand All @@ -31,7 +31,7 @@ public void shouldNotHaveAttribute() {
} }


@Test @Test
public void shouldFailWhenHasAttribute() { public void shouldFailWhenAtLeastOneElementHasAttribute() {
goTo(DEFAULT_URL); goTo(DEFAULT_URL);
assertThatAssertionErrorIsThrownBy(() -> assertThat($("input")).hasNotAttribute("style")) assertThatAssertionErrorIsThrownBy(() -> assertThat($("input")).hasNotAttribute("style"))
.hasMessage("At least one selected element has attribute style"); .hasMessage("At least one selected element has attribute style");
Expand Down

0 comments on commit ae1693a

Please sign in to comment.