View Javadoc

1   package com.atlassian.pageobjects.binder;
2   
3   import com.atlassian.pageobjects.Page;
4   import com.atlassian.pageobjects.PageBinder;
5   import com.atlassian.pageobjects.ProductInstance;
6   import com.atlassian.pageobjects.TestedProduct;
7   import com.atlassian.pageobjects.Tester;
8   import com.atlassian.pageobjects.browser.Browser;
9   import com.atlassian.pageobjects.browser.IgnoreBrowser;
10  import com.atlassian.pageobjects.browser.RequireBrowser;
11  import com.atlassian.pageobjects.inject.ConfigurableInjectionContext;
12  import com.google.inject.Binder;
13  import com.google.inject.Module;
14  import org.hamcrest.CoreMatchers;
15  import org.junit.Before;
16  import org.junit.Test;
17  import org.junit.runner.RunWith;
18  import org.mockito.Mock;
19  import org.mockito.runners.MockitoJUnitRunner;
20  
21  import javax.inject.Inject;
22  
23  import static org.junit.Assert.assertEquals;
24  import static org.junit.Assert.assertFalse;
25  import static org.junit.Assert.assertNotNull;
26  import static org.junit.Assert.assertThat;
27  import static org.junit.Assert.assertTrue;
28  import static org.mockito.Mockito.verify;
29  import static org.mockito.Mockito.when;
30  
31  @SuppressWarnings("unchecked")
32  @RunWith(MockitoJUnitRunner.class)
33  public class TestInjectPageBinder
34  {
35      private MyTestedProduct product;
36  
37      @Mock
38      private ProductInstance productInstance;
39  
40      @Mock
41      private Tester tester;
42  
43      @Before
44      public void setUp() throws Exception
45      {
46          product = new MyTestedProduct(new SetTester());
47      }
48  
49      @Test
50      public void testInject()
51      {
52          PageBinder binder = createBinder(StringField.class, StringFieldImpl.class);
53          OneFieldPage page = binder.bind(OneFieldPage.class);
54          assertEquals("Bob", page.name.getValue());
55      }
56  
57      @Test
58      public void testInjectDefaults()
59      {
60          PageBinder binder = createBinder();
61          DefaultsPage page = binder.bind(DefaultsPage.class);
62          assertNotNull(page.testedProduct);
63          assertNotNull(page.myTestedProduct);
64          assertNotNull(page.tester);
65          assertNotNull(page.setTester);
66          assertNotNull(page.pageBinder);
67          assertNotNull(page.productInstance);
68      }
69  
70      @Test(expected = IllegalArgumentException.class)
71      public void testInjectMissing()
72      {
73          PageBinder binder = createBinder();
74          binder.bind(OneFieldPage.class);
75      }
76  
77      @Test
78      public void testInjectWithArgument()
79      {
80          PageBinder binder = createBinder();
81          ConstructorArgumentPage page = binder.bind(ConstructorArgumentPage.class, "foo");
82          assertEquals("foo", page.name);
83      }
84  
85      @Test
86      public void testInstantiateWithPrimitiveArguments()
87      {
88          PageBinder binder = createBinder();
89          ConstructorArgumentPrimitive object = binder.bind(ConstructorArgumentPrimitive.class, 5, true);
90          assertNotNull(object);
91          assertEquals(5, object.intField);
92          assertTrue(object.booleanField);
93      }
94  
95      @Test
96      public void testInjectWithArgumentSubclass()
97      {
98          PageBinder binder = createBinder();
99          ConstructorArgumentPage page = binder.bind(ConstructorArgumentPage.class, 43);
100         assertEquals(43, page.age);
101     }
102 
103     @Test
104     public void testInitAfterInject()
105     {
106         PageBinder binder = createBinder(StringField.class, StringFieldImpl.class);
107         OneFieldWithInitPage page = binder.bind(OneFieldWithInitPage.class);
108         assertEquals("Bob Jones", page.name);
109     }
110 
111     @Test
112     public void testPrivateInitAfterInject()
113     {
114         PageBinder binder = createBinder(StringField.class, StringFieldImpl.class);
115         OneFieldWithPrivateInitPage page = binder.bind(OneFieldWithPrivateInitPage.class);
116         assertEquals("Bob Private", page.name);
117     }
118 
119     @Test
120     public void testOneFieldWithSuperClassInit()
121     {
122         PageBinder binder = createBinder(StringField.class, StringFieldImpl.class);
123         OneFieldWithSuperClassInitPage page = binder.bind(OneFieldWithSuperClassInitPage.class);
124         assertEquals("Bob Private", page.getName());
125 
126     }
127 
128     @Test
129     public void testProtectedInitAfterInject()
130     {
131         PageBinder binder = createBinder(StringField.class, StringFieldImpl.class);
132         OneFieldWithProtectedInitPage page = binder.bind(OneFieldWithProtectedInitPage.class);
133         assertEquals("Bob Protected", page.name);
134     }
135 
136     @Test
137     public void testParentInject()
138     {
139         PageBinder binder = createBinder(StringField.class, StringFieldImpl.class);
140         ChildNoNamePage page = binder.bind(ChildNoNamePage.class);
141         assertEquals("Bob", page.name.getValue());
142     }
143 
144     @Test
145     public void shouldImplementConfigurableInjectionContext()
146     {
147         final PageBinder binder = createBinder(StringField.class, StringFieldImpl.class);
148         assertThat(binder, CoreMatchers.instanceOf(ConfigurableInjectionContext.class));
149         assertEquals("Bob", binder.bind(OneFieldPage.class).name.getValue());
150         ConfigurableInjectionContext.class.cast(binder)
151                 .configure()
152                 .addImplementation(StringField.class, AnotherStringFieldImpl.class)
153                 .finish();
154         assertEquals("Rob", binder.bind(OneFieldPage.class).name.getValue());
155     }
156 
157     @Test
158     public void shouldAllowConfiguringNewSingletonInstanceThatIsSubclassOfInterfaceType()
159     {
160         final PageBinder binder = createBinder();
161         ConfigurableInjectionContext.class.cast(binder)
162                 .configure()
163                 .addSingleton(StringField.class, new StringFieldImpl())
164                 .finish();
165         assertEquals("Bob", binder.bind(OneFieldPage.class).name.getValue());
166     }
167 
168     @Test
169     public void shouldAllowConfiguringNewImplementationInstance()
170     {
171         PageBinder binder = createBinder(StringField.class, StringFieldImpl.class);
172         assertEquals("Bob", binder.bind(OneFieldPage.class).name.getValue());
173         ConfigurableInjectionContext.class.cast(binder)
174                 .configure()
175                 .addSingleton(StringField.class, new StringField()
176                 {
177                     @Override
178                     public String getValue()
179                     {
180                         return "Boom!";
181                     }
182                 })
183                 .finish();
184         assertEquals("Boom!", binder.bind(OneFieldPage.class).name.getValue());
185     }
186 
187     @Test
188     public void shouldIncludePostInjectionProcessorsAddedViaInjectionContext()
189     {
190         PageBinder binder = createBinder();
191         assertEquals("Default", binder.bind(MutablePage.class).getValue());
192 
193         ConfigurableInjectionContext.class.cast(binder)
194                 .configure()
195                 .addSingleton(MutablePageProcessor.class, new MutablePageProcessor())
196                 .finish();
197 
198         // post processor should be invoked
199         assertEquals("Post processed", binder.bind(MutablePage.class).getValue());
200     }
201 
202     @Test
203     public void visitUrlShouldRemoveExtraSlashAfterHostname() throws Exception
204     {
205         when(productInstance.getBaseUrl()).thenReturn("http://localhost/");
206 
207         final PageBinder binder = createBinder(StringField.class, StringFieldImpl.class);
208         binder.navigateToAndBind(OneFieldPage.class);
209 
210         verify(tester).gotoUrl("http://localhost/path");
211     }
212 
213     @Test
214     public void visitUrlShouldAddMissingSlashAfterHostname() throws Exception
215     {
216         when(productInstance.getBaseUrl()).thenReturn("http://localhost");
217 
218         final PageBinder binder = createBinder(StringField.class, StringFieldImpl.class);
219         binder.navigateToAndBind(PageWithNoLeadingSlash.class);
220 
221         verify(tester).gotoUrl("http://localhost/path");
222     }
223 
224     @Test
225     public void shouldCheckForIgnoreBrowserAndRequireBrowserAnnotation()
226     {
227         // should invoke all init methods
228         PageObjectWithRequiredAndIgnoredBrowsers pageObject = createBinderWithBrowser(Browser.FIREFOX)
229                 .bind(PageObjectWithRequiredAndIgnoredBrowsers.class);
230 
231         assertTrue(pageObject.initIgnoredInvoked);
232         assertTrue(pageObject.initRequiredInvoked);
233 
234         // should _not_ invoke init ignored
235         pageObject = createBinderWithBrowser(Browser.HTMLUNIT).bind(PageObjectWithRequiredAndIgnoredBrowsers.class);
236 
237         assertFalse(pageObject.initIgnoredInvoked);
238         assertTrue(pageObject.initRequiredInvoked);
239 
240         // should _not_ invoke init required
241         pageObject = createBinderWithBrowser(Browser.SAFARI).bind(PageObjectWithRequiredAndIgnoredBrowsers.class);
242 
243         assertTrue(pageObject.initIgnoredInvoked);
244         assertFalse(pageObject.initRequiredInvoked);
245 
246         // should _not_ invoke any init
247         pageObject = createBinderWithBrowser(Browser.HTMLUNIT_NOJS).bind(PageObjectWithRequiredAndIgnoredBrowsers.class);
248 
249         assertFalse(pageObject.initIgnoredInvoked);
250         assertFalse(pageObject.initRequiredInvoked);
251     }
252 
253     @Test
254     public void shouldSupportIgnoreAllAndRequireAll()
255     {
256         for (Browser browser : Browser.values())
257         {
258             PageObjectWithRequiredAndIgnoredBrowsers pageObject = createBinderWithBrowser(browser)
259                     .bind(PageObjectWithRequiredAndIgnoredBrowsers.class);
260 
261             assertFalse(pageObject.initIgnoreAllInvoked);
262             assertTrue(pageObject.initRequireAllInvoked);
263         }
264     }
265 
266     private InjectPageBinder createBinder()
267     {
268         return createBinder(null, null);
269     }
270 
271     private InjectPageBinder createBinder(final Class<?> key, final Class impl)
272     {
273         return new InjectPageBinder(productInstance, tester, new StandardModule(product),
274                 new Module()
275                 {
276                     public void configure(Binder binder)
277                     {
278                         if (key != null)
279                         {
280                             binder.bind(key).to(impl);
281                         }
282                     }
283                 });
284     }
285 
286     private InjectPageBinder createBinderWithBrowser(Browser browser)
287     {
288         InjectPageBinder pageBinder = createBinder();
289         ConfigurableInjectionContext.class.cast(pageBinder).configure()
290                 .addSingleton(Browser.class, browser).finish();
291 
292         return pageBinder;
293     }
294 
295     static class AbstractPage implements Page
296     {
297         public String getUrl()
298         {
299             return "/path";
300         }
301     }
302 
303     static class OneFieldPage extends AbstractPage
304     {
305         @Inject
306         private StringField name;
307     }
308 
309     static class PageWithNoLeadingSlash extends AbstractPage
310     {
311         @Override
312         public String getUrl()
313         {
314             return "path";
315         }
316     }
317 
318     static class ConstructorArgumentPrimitive
319     {
320         private final int intField;
321         private final boolean booleanField;
322 
323         public ConstructorArgumentPrimitive(int intArg, boolean booleanArg)
324         {
325             this.intField = intArg;
326             this.booleanField = booleanArg;
327         }
328     }
329 
330     static class ConstructorArgumentPage extends AbstractPage
331     {
332         private final String name;
333         private final Number age;
334 
335         @SuppressWarnings("UnusedDeclaration")
336         public ConstructorArgumentPage(String name)
337         {
338             this.name = name;
339             this.age = null;
340         }
341 
342         @SuppressWarnings("UnusedDeclaration")
343         public ConstructorArgumentPage(Number age)
344         {
345             this.age = age;
346             this.name = null;
347         }
348     }
349 
350     static class ParentNamePage extends AbstractPage
351     {
352         @Inject
353         protected StringField name;
354     }
355 
356     static class ChildNoNamePage extends ParentNamePage
357     {
358     }
359 
360     static class DefaultsPage extends AbstractPage
361     {
362         @Inject
363         private ProductInstance productInstance;
364 
365         @Inject
366         private TestedProduct testedProduct;
367 
368         @Inject
369         private MyTestedProduct myTestedProduct;
370 
371         @Inject
372         private Tester tester;
373 
374         @Inject
375         private SetTester setTester;
376 
377         @Inject
378         private PageBinder pageBinder;
379     }
380 
381     static class OneFieldWithInitPage extends AbstractPage
382     {
383         @Inject
384         private StringField field;
385 
386         private String name;
387         @Init
388         public void init()
389         {
390             name = field.getValue() + " Jones";
391         }
392     }
393 
394     static interface StringField
395     {
396         String getValue();
397     }
398 
399     static class StringFieldImpl implements StringField
400     {
401         public String getValue()
402         {
403             return "Bob";
404         }
405     }
406 
407     static class AnotherStringFieldImpl implements StringField
408     {
409         public String getValue()
410         {
411             return "Rob";
412         }
413     }
414 
415     static class OneFieldWithPrivateInitPage extends AbstractPage
416     {
417         @Inject
418         private StringField field;
419 
420         private String name;
421 
422         @Init
423         @SuppressWarnings("UnusedDeclaration")
424         private void init()
425         {
426             name = field.getValue() + " Private";
427         }
428 
429         public String getName()
430         {
431             return name;
432         }
433     }
434 
435     static class OneFieldWithProtectedInitPage extends AbstractPage
436     {
437         @Inject
438         private StringField field;
439 
440         private String name;
441 
442         @Init
443         protected void init()
444         {
445             name = field.getValue() + " Protected";
446         }
447     }
448 
449     static class OneFieldWithSuperClassInitPage extends OneFieldWithPrivateInitPage
450     {
451     }
452 
453     static class MutablePage
454     {
455         private String value = "Default";
456 
457         public String getValue()
458         {
459             return value;
460         }
461 
462         public void setValue(String value)
463         {
464             this.value = value;
465         }
466     }
467 
468     static class MutablePageProcessor implements PostInjectionProcessor
469     {
470         @Override
471         public <T> T process(T pageObject)
472         {
473             if (pageObject instanceof MutablePage)
474             {
475                 MutablePage.class.cast(pageObject).setValue("Post processed");
476             }
477             return pageObject;
478         }
479     }
480 
481     static class PageObjectWithRequiredAndIgnoredBrowsers
482     {
483         boolean initIgnoredInvoked;
484         boolean initRequiredInvoked;
485 
486         boolean initIgnoreAllInvoked;
487         boolean initRequireAllInvoked;
488 
489         @Init
490         @IgnoreBrowser(Browser.ALL)
491         public void initIgnoreAll()
492         {
493             initIgnoreAllInvoked = true;
494         }
495 
496         @Init
497         @IgnoreBrowser({ Browser.HTMLUNIT, Browser.HTMLUNIT_NOJS })
498         public void initIgnored()
499         {
500             initIgnoredInvoked = true;
501         }
502 
503         @Init
504         @RequireBrowser(Browser.ALL)
505         public void initRequireAll()
506         {
507             initRequireAllInvoked = true;
508         }
509 
510         @Init
511         @RequireBrowser({ Browser.CHROME, Browser.FIREFOX, Browser.HTMLUNIT })
512         public void initRequired()
513         {
514             initRequiredInvoked = true;
515         }
516     }
517 
518 }