/* Copyright 2014 Red Hat, Inc. and/or its affiliates. This file is part of darcy-ui. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.redhat.darcy.ui; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import com.redhat.darcy.ui.annotations.Context; import com.redhat.darcy.ui.annotations.NotRequired; import com.redhat.darcy.ui.annotations.Require; import com.redhat.darcy.ui.annotations.RequireAll; import com.redhat.darcy.ui.api.Locator; import com.redhat.darcy.ui.api.ViewElement; import com.redhat.darcy.ui.api.elements.Element; import com.redhat.darcy.ui.api.elements.Findable; import com.redhat.darcy.ui.testing.doubles.NeverDisplayedElement; import com.redhat.darcy.ui.testing.doubles.NeverFoundElement; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import java.util.ArrayList; import java.util.List; @RunWith(JUnit4.class) public class AbstractViewElementIsPresentTest { @Test(expected = NoRequiredElementsException.class) public void shouldThrowNoRequiredElementsExceptionIfCalledWithoutAnyAnnotatedElements() { ViewElement testView = new AbstractViewElement(mock(Locator.class)) { Element element = new NeverDisplayedElement(); }; testView.isPresent(); } @Test public void shouldReturnTrueIfAllRequiredFindablesArePresent() { ViewElement testView = new AbstractViewElement(mock(Locator.class)) { @Require private Element test = new NeverDisplayedElement(); }; assertTrue("isPresent should return true if all required elements are present.", testView.isPresent()); } @Test public void shouldReturnFalseIfNotAllRequiredElementsArePresent() { ViewElement testView = new AbstractViewElement(mock(Locator.class)) { @Require private Element present = new NeverDisplayedElement(); @Require private Element notPresent = new NeverFoundElement(); }; assertFalse("isPresent should return false if not all required elements are present.", testView.isPresent()); } @Test public void shouldReturnTrueIfRequireAllIsUsedAndAllElementsArePresent() { @RequireAll class TestViewElement extends AbstractViewElement { private Element present = new NeverDisplayedElement(); private Element present2 = new NeverDisplayedElement(); TestViewElement(Locator parent) { super(parent); } } ViewElement testView = new TestViewElement(mock(Locator.class)); assertTrue("isPresent should return true if all required elements are present and " + "RequireAll annotation is used.", testView.isPresent()); } @Test public void shouldReturnFalseIfRequireAllIsUsedAndNotAllElementsArePresent() { @RequireAll class TestViewElement extends AbstractViewElement { private Element present = new NeverDisplayedElement(); private Element notPresent = new NeverFoundElement(); TestViewElement(Locator parent) { super(parent); } } ViewElement testView = new TestViewElement(mock(Locator.class)); assertFalse("isPresent should return false if not all required elements are present " + "and RequireAll annotation is used.", testView.isPresent()); } @Test public void shouldReturnTrueIfOnlyElementNotPresentIsNotRequired() { @RequireAll class TestViewElement extends AbstractViewElement { private Element present = new NeverDisplayedElement(); @NotRequired private Element notPresent = new NeverFoundElement(); TestViewElement(Locator parent) { super(parent); } } ViewElement testView = new TestViewElement(mock(Locator.class)); assertTrue("isPresent should return true if only element not present is not required " + "when RequireAll annotation is used.", testView.isPresent()); } @Test public void shouldReturnFalseIfOnlyElementPresentIsNotRequired() { @RequireAll class TestViewElement extends AbstractViewElement { @NotRequired private Element present = new NeverDisplayedElement(); private Element notPresent = new NeverFoundElement(); TestViewElement(Locator parent) { super(parent); } } ViewElement testView = new TestViewElement(mock(Locator.class)); assertFalse("isPresent should return false if only element actually present is not " + "required when RequireAll annotation is used.", testView.isPresent()); } @Test public void shouldAllowBeingOverridden() { ViewElement testView = new AbstractViewElement(mock(Locator.class)) { @Require private Element present = new NeverDisplayedElement(); @Override public boolean isPresent() { return super.isPresent(); } }; assertTrue(testView.isPresent()); } @Test(expected = TestException.class) public void shouldPropagateUncheckedExceptions() { Element throwsExceptionOnIsPresent = mock(Element.class); when(throwsExceptionOnIsPresent.isPresent()).thenThrow(TestException.class); ViewElement testView = new AbstractViewElement(mock(Locator.class)) { @Require Element element = throwsExceptionOnIsPresent; }; testView.isPresent(); } @Test public void shouldReturnTrueIfRequiredViewIsPresentButNotDisplayedOrLoaded() { ViewElement mockElement = mock(ViewElement.class); when(mockElement.isPresent()).thenReturn(true); when(mockElement.isDisplayed()).thenReturn(false); when(mockElement.isLoaded()).thenReturn(false); ViewElement testView = new AbstractViewElement(mock(Locator.class)) { @Require ViewElement element = mockElement; }; assertTrue("Expected ViewElement to be present due to single required field that is a " + "present view.", testView.isPresent()); } // This scenario doesn't make any sense, but serves to prove we're not looking at isLoaded for // isPresent. @Test public void shouldReturnFalseIfRequiredViewIsNotPresentButIsLoadedAndDisplayed() { ViewElement mockElement = mock(ViewElement.class); when(mockElement.isDisplayed()).thenReturn(true); when(mockElement.isLoaded()).thenReturn(true); when(mockElement.isPresent()).thenReturn(false); ViewElement testView = new AbstractViewElement(mock(Locator.class)) { @Require ViewElement element = mockElement; }; assertFalse("Expected ViewElement to not be present due to single required field that " + "is a not present view.", testView.isPresent()); } @Test public void shouldReturnTrueIfRequiredFindableIsPresent() { Findable mockFindable = mock(Findable.class); when(mockFindable.isPresent()).thenReturn(true); ViewElement testView = new AbstractViewElement(mock(Locator.class)) { @Require Findable findable = mockFindable; }; assertTrue("Expected ViewElement to be present due to single required field that is a " + "present findable.", testView.isPresent()); } @Test public void shouldReturnFalseIfRequiredFindableIsNotPresent() { Findable mockFindable = mock(Findable.class); when(mockFindable.isPresent()).thenReturn(false); ViewElement testView = new AbstractViewElement(mock(Locator.class)) { @Require Findable findable = mockFindable; }; assertFalse("Expected ViewElement to not be present due to single required field that is " + "a " + "non-present findable.", testView.isPresent()); } @Test(expected = NoRequiredElementsException.class) public void shouldIgnoreFieldsAnnotatedWithContext() { @RequireAll class TestViewElement extends AbstractViewElement { @Context Findable findable = mock(Findable.class); public TestViewElement() { super(mock(Locator.class)); } }; TestViewElement testView = new TestViewElement(); testView.isPresent(); } @Test(expected = NoRequiredElementsException.class) public void shouldNotConsiderIrrelevantFieldsAsAbleToBeRequired() { @RequireAll class TestViewElement extends AbstractViewElement { String aString; public TestViewElement() { super(mock(Locator.class)); } }; TestViewElement testView = new TestViewElement(); testView.isPresent(); } @Test(expected = NoRequiredElementsException.class) public void shouldReconsiderEmptyConditionsListIfFieldIsAmbiguous() { @RequireAll class TestViewElement extends AbstractViewElement { List<String> stringList; public TestViewElement() { super(mock(Locator.class)); } }; TestViewElement testView = new TestViewElement(); testView.isPresent(); } @Test public void shouldReturnTrueIfRequireIsSpecifiedForAListWithASingleElementLoaded() { class TestViewElement extends AbstractViewElement { @Require private List<Findable> findables; public TestViewElement() { super(mock(Locator.class)); findables = new ArrayList<Findable>(); findables.add(new NeverDisplayedElement()); } } TestViewElement view = new TestViewElement(); assertTrue("isPresent should return true if no specific requirement limit is specified for" + " for a list that has at least a single element present.", view.isPresent()); } @Test public void shouldReturnFalseIfRequireIsSpecifiedForAListWithNoElementsLoaded() { class TestViewElement extends AbstractViewElement { @Require private List<Findable> findables; public TestViewElement() { super(mock(Locator.class)); findables = new ArrayList<Findable>(); } } TestViewElement view = new TestViewElement(); assertFalse("isPresent should return false if a list with no elements present is specified" + " required with no requirement limit.", view.isPresent()); } @Test public void shouldReturnTrueIfExactNumberOfRequiredElementsArePresent() { class TestViewElement extends AbstractViewElement { @Require(exactly = 5) List<Findable> findables; public TestViewElement() { super(mock(Locator.class)); findables = new ArrayList<Findable>(); while (findables.size() < 5) { findables.add(new NeverDisplayedElement()); } } } TestViewElement element = new TestViewElement(); assertTrue("isPresent should return true if a list with exactly as many elements as specified" + " are present.", element.isPresent()); } @Test public void shouldReturnFalseIfExactNumberOfRequiredElementsAreNotPresent() { class TestViewElement extends AbstractViewElement { @Require(exactly = 5) List<Findable> findables; public TestViewElement() { super(mock(Locator.class)); findables = new ArrayList<Findable>(); while (findables.size() < 4) { findables.add(new NeverDisplayedElement()); } findables.add(new NeverFoundElement()); } } TestViewElement element = new TestViewElement(); assertFalse("isPresent should return false if a list with less than exactly as many elements as specified" + " are present.", element.isPresent()); } @Test public void shouldReturnTrueIfAtLeastAsManyRequiredElementsArePresent() { class TestViewElement extends AbstractViewElement { @Require(atLeast = 5) List<Findable> findables; public TestViewElement() { super(mock(Locator.class)); findables = new ArrayList<Findable>(); while (findables.size() < 5) { findables.add(new NeverDisplayedElement()); } } } TestViewElement element = new TestViewElement(); assertTrue("isPresent should return true if at least a number of elements are present as" + " specified to be required.", element.isPresent()); } @Test public void shouldReturnTrueIfAtLeastAsManyRequiredElementsArePresentWithUnpresentElements() { class TestViewElement extends AbstractViewElement { @Require(atLeast = 5) List<Findable> findables; public TestViewElement() { super(mock(Locator.class)); findables = new ArrayList<Findable>(); while (findables.size() < 5) { findables.add(new NeverDisplayedElement()); } while (findables.size() < 10) { findables.add(new NeverFoundElement()); } } } TestViewElement element = new TestViewElement(); assertTrue("isPresent should return true if at least a number of elements are present as" + " specified to be required, with any number of non-present elements.", element.isPresent()); } @Test public void shouldReturnFalseIfLessThanTheMinimumRequiredElementsArePresent() { class TestViewElement extends AbstractViewElement { @Require(atLeast = 5) List<Findable> findables; public TestViewElement() { super(mock(Locator.class)); findables = new ArrayList<Findable>(); while (findables.size() < 4) { findables.add(new NeverDisplayedElement()); } while (findables.size() < 10) { findables.add(new NeverFoundElement()); } } } TestViewElement element = new TestViewElement(); assertFalse("isPresent should return false if a number of elements less than specified " + " as required are present.", element.isPresent()); } @Test public void shouldReturnTrueIfAtMostAsManyRequiredElementsArePresent() { class TestViewElement extends AbstractViewElement { @Require(atMost = 5) List<Findable> findables; public TestViewElement() { super(mock(Locator.class)); findables = new ArrayList<Findable>(); while (findables.size() < 5) { findables.add(new NeverDisplayedElement()); } } } TestViewElement element = new TestViewElement(); assertTrue("isPresent should return true if at most a number of elements are present as" + " specified to be required.", element.isPresent()); } @Test public void shouldReturnTrueIfAtMostAsManyRequiredElementsArePresentWithUnpresentElements() { class TestViewElement extends AbstractViewElement { @Require(atMost = 5) List<Findable> findables; public TestViewElement() { super(mock(Locator.class)); findables = new ArrayList<Findable>(); while (findables.size() < 4) { findables.add(new NeverDisplayedElement()); } while (findables.size() < 10) { findables.add(new NeverFoundElement()); } } } TestViewElement element = new TestViewElement(); assertTrue("isPresent should return true if at least a number of elements are present as" + " specified to be required, with any number of non-present elements.", element.isPresent()); } @Test public void shouldReturnFalseIfMoreThanTheMaximumRequiredElementsArePresent() { class TestViewElement extends AbstractViewElement { @Require(atMost = 5) List<Findable> findables; public TestViewElement() { super(mock(Locator.class)); findables = new ArrayList<Findable>(); while (findables.size() < 6) { findables.add(new NeverDisplayedElement()); } while (findables.size() < 10) { findables.add(new NeverFoundElement()); } } } TestViewElement element = new TestViewElement(); assertFalse("isPresent should return false if a number of elements less than specified " + " as required are present.", element.isPresent()); } class TestException extends RuntimeException {} }