package org.fluentlenium.core.search;
import org.assertj.core.api.ThrowableAssert;
import org.fluentlenium.adapter.FluentAdapter;
import org.fluentlenium.core.components.DefaultComponentInstantiator;
import org.fluentlenium.core.domain.FluentList;
import org.fluentlenium.core.domain.FluentWebElement;
import org.fluentlenium.core.filter.AttributeFilter;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyCollection;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class SearchTest {
@Mock
private WebDriver driver;
@Mock
private SearchContext searchContext;
@Mock
private AttributeFilter filter1;
@Mock
private AttributeFilter filter2;
private Search search;
@Before
public void before() {
FluentAdapter fluentAdapter = new FluentAdapter();
fluentAdapter.initFluent(driver);
DefaultComponentInstantiator instantiator = new DefaultComponentInstantiator(fluentAdapter);
search = new Search(searchContext, this, instantiator, fluentAdapter);
}
@After
public void after() {
reset(searchContext);
}
@Test
public void findCheckCssIsWellFormed() {
WebElement webElement = mock(WebElement.class);
WebElement webElement2 = mock(WebElement.class);
List<WebElement> webElements = new ArrayList<>(Arrays.asList(webElement, webElement2));
when(searchContext.findElements(By.cssSelector("cssStyle[generated=true][checked=ok]"))).thenReturn(webElements);
String name = "cssStyle";
AttributeFilter[] filters = new AttributeFilter[] {filter1, filter2};
when(filter1.isCssFilterSupported()).thenReturn(true);
when(filter1.getCssFilter()).thenReturn("[generated=true]");
when(filter2.isCssFilterSupported()).thenReturn(true);
when(filter2.getCssFilter()).thenReturn("[checked=ok]");
search.find(name, filters).now();
verify(searchContext).findElements(By.cssSelector("cssStyle[generated=true][checked=ok]"));
}
@Test
public void canLoopIntoFluentWebElementAfterASearch() {
WebElement webElement = mock(WebElement.class);
WebElement webElement2 = mock(WebElement.class);
List<WebElement> webElements = new ArrayList<>(Arrays.asList(webElement, webElement2));
when(searchContext.findElements(By.cssSelector("cssStyle"))).thenReturn(webElements);
for (FluentWebElement fluentWebElement : search.find("cssStyle")) {
//just to check the cast
assertThat(fluentWebElement).isInstanceOf(FluentWebElement.class);
}
}
@Test
public void findCheckCssIsWellFormedWithPostSelector() {
WebElement webElement = mock(WebElement.class);
WebElement webElement2 = mock(WebElement.class);
List<WebElement> webElements = new ArrayList<>(Arrays.asList(webElement, webElement2));
when(searchContext.findElements(By.cssSelector("cssStyle[generated=true]"))).thenReturn(webElements);
String name = "cssStyle";
AttributeFilter[] filters = new AttributeFilter[] {filter1, filter2};
when(filter1.isCssFilterSupported()).thenReturn(true);
when(filter1.getCssFilter()).thenReturn("[generated=true]");
when(filter2.isCssFilterSupported()).thenReturn(false);
when(filter2.applyFilter(anyCollection())).thenAnswer(new Answer<Collection<FluentWebElement>>() {
@Override
public Collection<FluentWebElement> answer(InvocationOnMock invocation) throws Throwable {
return (Collection<FluentWebElement>) invocation.getArguments()[0];
}
});
search.find(name, filters).present();
verify(searchContext).findElements(By.cssSelector("cssStyle[generated=true]"));
}
@Test
public void findCheckCssIsWellFormedWithPostSelectorAndByLocator() {
WebElement webElement = mock(WebElement.class);
WebElement webElement2 = mock(WebElement.class);
List<WebElement> webElements = new ArrayList<>(Arrays.asList(webElement, webElement2));
when(searchContext.findElements(By.cssSelector("cssStyle[generated=true]"))).thenReturn(webElements);
By locator = By.cssSelector("cssStyle");
AttributeFilter[] filters = new AttributeFilter[] {filter1, filter2};
when(filter1.applyFilter(anyCollection())).thenAnswer(new Answer<Collection<FluentWebElement>>() {
@Override
public Collection<FluentWebElement> answer(InvocationOnMock invocation) throws Throwable {
return (Collection<FluentWebElement>) invocation.getArguments()[0];
}
});
when(filter2.applyFilter(anyCollection())).thenAnswer(new Answer<Collection<FluentWebElement>>() {
@Override
public Collection<FluentWebElement> answer(InvocationOnMock invocation) throws Throwable {
return (Collection<FluentWebElement>) invocation.getArguments()[0];
}
});
search.find(locator, filters).present();
verify(searchContext).findElements(By.cssSelector("cssStyle")); // By parameter doesn't support CSS filtering.
}
@Test
public void findPostSelectorFilterWithElementThatMatch() {
String name = "cssStyle";
AttributeFilter[] filters = new AttributeFilter[] {filter1};
when(filter1.isCssFilterSupported()).thenReturn(false);
when(filter1.applyFilter(anyCollection())).thenAnswer(new Answer<Collection<FluentWebElement>>() {
@Override
public Collection<FluentWebElement> answer(InvocationOnMock invocation) throws Throwable {
return (Collection<FluentWebElement>) invocation.getArguments()[0];
}
});
WebElement webElement = mock(WebElement.class);
when(searchContext.findElements(By.cssSelector("cssStyle"))).thenReturn(Collections.singletonList(webElement));
FluentList fluentList = search.find(name, filters);
assertThat(fluentList).hasSize(1);
}
@Test
public void findPostSelectorFilterWithElementThatDontMatch() {
String name = "cssStyle";
AttributeFilter[] filters = new AttributeFilter[] {filter1};
when(filter1.isCssFilterSupported()).thenReturn(false);
WebElement webElement = mock(WebElement.class);
when(searchContext.findElements(By.cssSelector("cssStyle"))).thenReturn(Collections.singletonList(webElement));
assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
@Override
public void call() throws Throwable {
search.find(name, filters).now();
}
}).isExactlyInstanceOf(NoSuchElementException.class);
assertThat(search.find(name, filters).present()).isFalse();
assertThat(search.find(name, filters).optional().isPresent()).isFalse();
}
@Test
public void findPostSelectorFilterWithFilterOnText() {
String name = "cssStyle";
AttributeFilter[] filters = new AttributeFilter[] {filter1};
when(filter1.isCssFilterSupported()).thenReturn(false);
WebElement webElement = mock(WebElement.class);
when(searchContext.findElements(By.cssSelector("cssStyle"))).thenReturn(Collections.singletonList(webElement));
assertThat(search.find(name, filters).present()).isFalse();
assertThat(search.find(name, filters).optional().isPresent()).isFalse();
verify(filter1, times(2)).applyFilter(any(Collection.class));
}
@Test
public void findByPosition() {
String name = "cssStyle";
WebElement webElement1 = mock(WebElement.class);
WebElement webElement2 = mock(WebElement.class);
when(webElement2.getTagName()).thenReturn("a");
List<WebElement> webElements = new ArrayList<>();
webElements.add(webElement1);
webElements.add(webElement2);
when(searchContext.findElements(By.cssSelector("cssStyle"))).thenReturn(webElements);
FluentWebElement fluentWebElement = search.find(name).index(1);
assertThat(fluentWebElement.tagName()).isEqualTo("a");
}
@Test(expected = NoSuchElementException.class)
public void shouldThrowErrorWhenPositionNotFound() {
String name = "cssStyle";
search.find(name).index(0).now();
}
@Test
public void findFirstShouldReturnFirst() {
String name = "cssStyle";
WebElement webElement1 = mock(WebElement.class);
when(webElement1.getTagName()).thenReturn("span");
WebElement webElement2 = mock(WebElement.class);
List<WebElement> webElements = new ArrayList<>();
webElements.add(webElement1);
webElements.add(webElement2);
when(searchContext.findElements(By.cssSelector("cssStyle"))).thenReturn(webElements);
FluentWebElement fluentWebElement = search.el(name);
assertThat(fluentWebElement.tagName()).isEqualTo("span");
}
@Test(expected = NoSuchElementException.class)
public void shouldThrowErrorWhenFirstNotFound() {
String name = "cssStyle";
FluentWebElement fluentWebElement = search.el(name);
assertThat(fluentWebElement.tagName()).isEqualTo("span");
}
public void findWithRawSelemenium() {
WebElement mock = Mockito.mock(WebElement.class);
FluentWebElement el = search.el(mock);
assertThat(el.getElement()).isSameAs(mock);
}
}