package com.algocrafts.selenium; import com.algocrafts.clickables.Button; import com.algocrafts.clickables.Link; import com.algocrafts.conditions.StringContains; import com.algocrafts.converters.ElementAtIndex; import com.algocrafts.converters.Filter; import com.algocrafts.converters.FirstItem; import com.algocrafts.converters.StreamToList; import com.algocrafts.locators.Locators; import org.openqa.selenium.By; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.SearchContext; import org.openqa.selenium.WebElement; import java.util.List; import java.util.Optional; import java.util.function.Supplier; import java.util.stream.Stream; import static com.algocrafts.conditions.ElementPredicates.DISPLAYED; import static com.algocrafts.conditions.ElementPredicates.NOT_NULL; import static com.algocrafts.converters.GetText.SRC; import static com.algocrafts.locators.Locators.element; import static com.algocrafts.selectors.TagName.IMG; import static java.util.stream.Collectors.toList; public interface SearchScope<T extends SearchScope<T>> extends SearchContext, //<1> ExplicitWait<T> { /** * Find the first element or throw NoSuchElementException * * @param by selector * @return the first element or throw NoSuchElementException */ @Deprecated //<2> @Override default Element findElement(By by) { return new ElementFinder(by).locate(this); } @Deprecated //<3> @Override default List<WebElement> findElements(By by) { return by.findElements(this).stream().map(Element::new).collect(toList()); } /** * Find the first element or return empty Optional if nothing found. * * @param by selector * @return the first element or return empty Optional if nothing found. */ default Optional<Element> optionalElement(Supplier<By> by) { try { return Optional.of(findElement(by.get())); } catch (NoSuchElementException e) { return Optional.empty(); } } /** * Find the first element until timeout then throw NoSuchElementException * * @param by selector * @return the first element or throw NoSuchElementException */ default Element untilFound(Supplier<By> by) { return until(by); } /** * Find all elements within the area using the given search method. * * @param by selector * @return A stream of all {@link Element}s, or an empty stream if nothing matches. * @see org.openqa.selenium.By */ default Stream<Element> findElements(Supplier<By> by) { //<6> return findElements(by.get()).stream().map(Element::new); } /** * Find the first button meeting the By selector. * method to find the button. * * @param by selector ˜ * @return the first button meeting the By selector. */ default Clickable button(Supplier<By> by) { return button(by, 0); } /** * If there are multiple buttons with the same name on the same page, use this * method to find the button. * * @param by selector * @param index given index * @return the button by index in the list */ @SuppressWarnings("unchecked") default Clickable button(Supplier<By> by, int index) { return new Button<>((T) this, Locators.<T>elements(by) .andThen(new StreamToList<>()) .andThen(new ElementAtIndex<>(index))); } /** * If the button can't be found using the previous two methods, use this. * * @param locator locator * @return button found by the locator */ @SuppressWarnings("unchecked") default Clickable button(Locator<T, Element> locator) { return new Button<>((T) this, locator); } /** * The first image using the image file. * * @param fileName file name * @return first image found by using the image file. */ default Optional<Element> image(String fileName) { return new FirstItem<Element>().locate(images(fileName)); } /** * The image at the given index using the same image file. * * @param fileName file name * @param index index * @return image at the given index using the same image file. */ default Element image(String fileName, int index) { return new StreamToList<Element>() .andThen(new ElementAtIndex<>(index)) .locate(images(fileName)); } /** * Find the images using the same image file. * * @param fileName file name * @return the images found by using the same image file. */ default Stream<Element> images(String fileName) { return Locators.<T>elements(IMG) .andThen(new Filter<>(NOT_NULL.and(DISPLAYED) .and(SRC.and(new StringContains(fileName))))) .locate((T) this); } /** * Find the link using the selector. * * @param selector selector * @return the link found by using the selector. */ @SuppressWarnings("unchecked") default Clickable link(Supplier<By> selector) { return new Link<>((T) this, element(selector)); } }