View Javadoc

1   package com.atlassian.pageobjects.elements.test.search;
2   
3   import com.atlassian.pageobjects.elements.CheckboxElement;
4   import com.atlassian.pageobjects.elements.PageElement;
5   import com.atlassian.pageobjects.elements.PageElementFinder;
6   import com.atlassian.pageobjects.elements.PageElements;
7   import com.atlassian.pageobjects.elements.WebDriverElement;
8   import com.atlassian.pageobjects.elements.query.TimedQuery;
9   import com.atlassian.pageobjects.elements.search.AnyQuery;
10  import com.atlassian.pageobjects.elements.search.PageElementQuery;
11  import com.atlassian.pageobjects.elements.search.PageElementSearch;
12  import com.atlassian.pageobjects.elements.search.SearchQuery;
13  import com.atlassian.pageobjects.elements.test.AbstractPageElementBrowserTest;
14  import com.atlassian.pageobjects.elements.test.pageobjects.page.PageElementSearchPage;
15  import com.atlassian.pageobjects.elements.timeout.TimeoutType;
16  import org.hamcrest.FeatureMatcher;
17  import org.hamcrest.Matcher;
18  import org.hamcrest.Matchers;
19  import org.junit.Before;
20  import org.junit.Test;
21  import org.openqa.selenium.By;
22  
23  import javax.inject.Inject;
24  
25  import static com.atlassian.pageobjects.elements.PageElements.getDataAttribute;
26  import static com.atlassian.pageobjects.elements.PageElements.hasClass;
27  import static com.atlassian.pageobjects.elements.PageElements.hasDataAttribute;
28  import static com.atlassian.pageobjects.elements.query.Poller.waitUntil;
29  import static com.atlassian.pageobjects.elements.query.Poller.waitUntilTrue;
30  import static com.atlassian.pageobjects.elements.testing.PageElementMatchers.asMatcherOf;
31  import static com.atlassian.pageobjects.elements.testing.PageElementMatchers.isChecked;
32  import static com.atlassian.pageobjects.elements.testing.PageElementMatchers.withAttribute;
33  import static com.atlassian.pageobjects.elements.testing.PageElementMatchers.withClass;
34  import static com.atlassian.pageobjects.elements.testing.PageElementMatchers.withDataAttribute;
35  import static com.atlassian.pageobjects.elements.testing.PageElementMatchers.withId;
36  import static com.atlassian.pageobjects.elements.testing.PageElementMatchers.withText;
37  import static com.atlassian.webdriver.testing.matcher.MatcherPredicate.withMatcher;
38  import static org.hamcrest.Matchers.contains;
39  import static org.hamcrest.Matchers.emptyIterable;
40  import static org.hamcrest.Matchers.equalTo;
41  import static org.hamcrest.Matchers.everyItem;
42  import static org.hamcrest.Matchers.hasItems;
43  import static org.hamcrest.Matchers.is;
44  import static org.hamcrest.Matchers.not;
45  import static org.junit.Assert.assertEquals;
46  import static org.junit.Assert.assertNotNull;
47  import static org.junit.Assert.assertThat;
48  import static org.junit.Assert.assertTrue;
49  import static org.openqa.selenium.By.className;
50  import static org.openqa.selenium.By.id;
51  import static org.openqa.selenium.By.tagName;
52  
53  @SuppressWarnings("unchecked")
54  public class TestPageElementSearch extends AbstractPageElementBrowserTest
55  {
56      @Inject
57      private PageElementSearch page;
58  
59      @Inject
60      private PageElementFinder elementFinder;
61  
62      private PageElementSearchPage searchPage;
63  
64      @Before
65      public void goToElementSearchPage()
66      {
67          searchPage = product.visit(PageElementSearchPage.class);
68      }
69  
70      @Test
71      public void shouldFindSinglePageElementById()
72      {
73          PageElement result = page.search()
74                  .by(id("single-element"))
75                  .first();
76  
77          assertNotNull(result);
78          assertTrue(result.isPresent());
79          assertEquals("single-element", result.getAttribute("id"));
80      }
81  
82      @Test
83      public void shouldFindSinglePageElementByIdAsIterable()
84      {
85          assertResult(page.search().by(id("single-element")), contains(withAttribute("id", "single-element")));
86      }
87  
88      @Test
89      public void shouldReturnEmptyImmediatelyWhenSearchingFromNotExistingRoot()
90      {
91          Iterable<PageElement> result = elementFinder.find(By.id("no-such-id")).search()
92                  .by(id("nested-id"))
93                  .by(tagName("ul"))
94                  .by(tagName("li")).filter(hasDataAttribute("pick-me"))
95                  .now();
96  
97          assertThat(result, emptyIterable());
98      }
99  
100     @Test
101     public void shouldFindRowsWithFilter()
102     {
103         PageElementQuery<PageElement> result = page.search()
104                 .by(id("table-list"))
105                 .by(id("the-table"))
106                 .by(tagName("tr"), hasClass("even-row"));
107 
108         assertResult(result, contains(
109                 withDataAttribute("name", "Even Row 1"),
110                 withDataAttribute("name", "Even Row 2"),
111                 withDataAttribute("name", "Even Row 3")
112         ));
113     }
114 
115     @Test
116     public void shouldApplyFlatMap()
117     {
118         AnyQuery<String> result = page.search()
119                 .by(id("table-list"))
120                 .by(id("the-table"))
121                 .by(tagName("tr"), hasClass("even-row"))
122                 .flatMap(PageElements.getCssClasses());
123 
124         assertResult(result, contains("even-row", "two", "even-row", "four", "even-row", "six"));
125     }
126 
127     @Test
128     public void shouldFindRowsFromTableRoot()
129     {
130         Iterable<PageElement> result = searchPage.getTableRoot().search()
131                 .by(id("the-table"))
132                 .by(tagName("tr"))
133                 .now();
134 
135         assertThat(result, Matchers.<PageElement>iterableWithSize(7));
136     }
137 
138     @Test
139     public void shouldFindRowsWithFilterAndTransformOnResult()
140     {
141         AnyQuery<String> result = page.search()
142                 .by(id("table-list"))
143                 .by(id("the-table"))
144                 .by(tagName("tr"))
145                 .filter(hasClass("uneven-row"))
146                 .map(getDataAttribute("name"));
147 
148         assertResult(result, contains("Uneven Row 1", "Uneven Row 2", "Uneven Row 3"));
149     }
150 
151 
152     @Test
153     public void shouldFindRowsWithFilterOnResultUsingMatcher()
154     {
155         AnyQuery<String> result = page.search()
156                 .by(id("table-list"))
157                 .by(id("the-table"))
158                 .by(tagName("tr"))
159                 .filter(withMatcher(withClass("uneven-row")))
160                 .map(getDataAttribute("name"));
161 
162         assertResult(result, contains("Uneven Row 1", "Uneven Row 2", "Uneven Row 3"));
163     }
164 
165     @Test
166     public void shouldFindRowsWithFilterAndBindOnResult()
167     {
168         AnyQuery<RowWrapper> result = page.search()
169                 .by(id("table-list"))
170                 .by(id("the-table"))
171                 .by(tagName("tr"))
172                 .filter(hasClass("even-row"))
173                 .bindTo(RowWrapper.class);
174 
175         assertResult(result, contains(
176                 rowWithName("Even Row 1"),
177                 rowWithName("Even Row 2"),
178                 rowWithName("Even Row 3")));
179     }
180 
181     @Test
182     public void findFirstNestedElement()
183     {
184         PageElementQuery<PageElement> query = page.search()
185                 .by(id("parent-1"))
186                 .by(className("parent-2-class")).filter(hasDataAttribute("find-me"))
187                 .by(tagName("ul"))
188                 .by(tagName("li")).filter(withMatcher(withDataAttribute("pick-me", "yes")));
189 
190         PageElement element = findFirst(query);
191         assertTrue(element.isPresent());
192         assertEquals("Yes-1", element.getText());
193     }
194 
195     @Test
196     public void findMergeMultipleDomBranches()
197     {
198         PageElementQuery<PageElement> result = page.search()
199                 .by(id("parent-1"))
200                 .by(className("parent-2-class"))
201                 .by(tagName("ul"))
202                 .by(tagName("li"));
203 
204         assertResultStrict(result, Matchers.<PageElement>iterableWithSize(5));
205         assertResultStrict(result, hasItems(
206                 withText("WRONG!"),
207                 withText("No"),
208                 withText("Yes-1"),
209                 withText("Yes-2"))
210         );
211     }
212 
213     @Test
214     public void shouldWaitForSearchResultsToMatch() {
215         TimedQuery<Iterable<PageElement>> result = searchPage.getAsyncRoot().search()
216                 .by(className("async-parent-level-2-class"))
217                 .by(tagName("li"), hasDataAttribute("state", "2"))
218                 .timed();
219         waitUntil(result, emptyIterable());
220 
221         // switch to state-2
222         searchPage.clickAsyncButton(2);
223         waitUntil(result, Matchers.<PageElement>iterableWithSize(2));
224 
225         // reset back to state-1
226         searchPage.clickAsyncButton(1);
227         waitUntil(result, emptyIterable());
228     }
229 
230     @Test
231     public void shouldAssignCustomTimeoutType()
232     {
233         PageElementQuery<PageElement> result = page.search()
234                 .by(id("table-list"))
235                 .by(id("the-table"))
236                 .by(tagName("tr"), hasClass("even-row"))
237                 .withTimeout(TimeoutType.PAGE_LOAD);
238 
239         assertResultStrict(result, everyItem(hasTimeoutType(TimeoutType.PAGE_LOAD)));
240     }
241 
242     @Test
243     public void shouldReturnResultAsCheckboxes()
244     {
245         PageElementQuery<CheckboxElement> result = page.search()
246                 .by(id("checkbox-parent"))
247                 .by(tagName("input"))
248                 .as(CheckboxElement.class)
249                 .filter(withMatcher(not(isChecked())));
250 
251         // only unchecked checkboxes should be returned
252         assertResult(result, contains(
253                 asMatcherOf(CheckboxElement.class, withId("checkbox-2")),
254                 asMatcherOf(CheckboxElement.class, withId("checkbox-3"))
255         ));
256     }
257 
258     private static <R> void assertResult(SearchQuery<R, ?> result, Matcher<Iterable<? extends R>> matcher)
259     {
260         waitUntil(result.timed(), matcher);
261         assertThat(result.get(), matcher);
262         assertThat(result.now(), matcher);
263     }
264 
265     private static <R> void assertResultStrict(SearchQuery<R, ?> result, Matcher<Iterable<R>> matcher)
266     {
267         waitUntil(result.timed(), matcher);
268         assertThat(result.get(), matcher);
269         assertThat(result.now(), matcher);
270     }
271 
272     private static PageElement findFirst(PageElementQuery<?> query)
273     {
274         waitUntilTrue(query.hasResult());
275 
276         return query.first();
277     }
278 
279     private static Matcher<PageElement> hasTimeoutType(TimeoutType expectedTimeout)
280     {
281         return new FeatureMatcher<PageElement, TimeoutType>(is(expectedTimeout), "timeout type", "timeoutType")
282         {
283             @Override
284             protected TimeoutType featureValueOf(PageElement pageElement)
285             {
286                 return WebDriverElement.class.cast(pageElement).getDefaultTimeout();
287             }
288         };
289     }
290 
291     private static Matcher<RowWrapper> rowWithName(final String name)
292     {
293         return new FeatureMatcher<RowWrapper, String>(equalTo(name), "row name", "name")
294         {
295             @Override
296             protected String featureValueOf(RowWrapper rowWrapper)
297             {
298                 return rowWrapper.getName();
299             }
300         };
301     }
302 
303     public static class RowWrapper
304     {
305         private final PageElement row;
306 
307         public RowWrapper(PageElement element)
308         {
309             this.row = element;
310         }
311 
312         String getName()
313         {
314             return getDataAttribute("name").apply(row);
315         }
316     }
317 }