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.inject.ConfigurableInjectionContext;
9 import com.google.inject.Binder;
10 import com.google.inject.Module;
11 import org.hamcrest.CoreMatchers;
12 import org.junit.Before;
13 import org.junit.Test;
14 import org.junit.runner.RunWith;
15 import org.mockito.Mock;
16 import org.mockito.runners.MockitoJUnitRunner;
17
18 import javax.inject.Inject;
19
20 import static junit.framework.Assert.assertNotNull;
21 import static junit.framework.Assert.assertTrue;
22 import static org.junit.Assert.assertEquals;
23 import static org.junit.Assert.assertThat;
24 import static org.mockito.Mockito.verify;
25 import static org.mockito.Mockito.when;
26
27
28
29
30 @SuppressWarnings("unchecked")
31 @RunWith(MockitoJUnitRunner.class)
32 public class TestInjectPageBinder
33 {
34 private MyTestedProduct product;
35
36 @Mock
37 private ProductInstance productInstance;
38
39 @Mock
40 private Tester tester;
41
42 @Before
43 public void setUp() throws Exception
44 {
45 product = new MyTestedProduct(new SetTester());
46 }
47
48 private InjectPageBinder createBinder()
49 {
50 return createBinder(null, null);
51 }
52 private InjectPageBinder createBinder(final Class<?> key, final Class impl)
53 {
54 return new InjectPageBinder(productInstance, tester, new StandardModule(product),
55 new Module()
56 {
57 public void configure(Binder binder)
58 {
59 if (key != null)
60 {
61 binder.bind(key).to(impl);
62 }
63 }
64 });
65 }
66
67 @Test
68 public void testInject()
69 {
70 PageBinder binder = createBinder(StringField.class, StringFieldImpl.class);
71 OneFieldPage page = binder.bind(OneFieldPage.class);
72 assertEquals("Bob", page.name.getValue());
73 }
74
75 @Test
76 public void testInjectDefaults()
77 {
78 PageBinder binder = createBinder();
79 DefaultsPage page = binder.bind(DefaultsPage.class);
80 assertNotNull(page.testedProduct);
81 assertNotNull(page.myTestedProduct);
82 assertNotNull(page.tester);
83 assertNotNull(page.setTester);
84 assertNotNull(page.pageBinder);
85 assertNotNull(page.productInstance);
86 }
87
88 @Test(expected = IllegalArgumentException.class)
89 public void testInjectMissing()
90 {
91 PageBinder binder = createBinder();
92 OneFieldPage page = binder.bind(OneFieldPage.class);
93 int x = 0;
94 }
95
96 @Test
97 public void testInjectWithArgument()
98 {
99 PageBinder binder = createBinder();
100 ConstructorArgumentPage page = binder.bind(ConstructorArgumentPage.class, "foo");
101 assertEquals("foo", page.name);
102 }
103
104 @Test
105 public void testInstantiateWithPrimitiveArguments()
106 {
107 PageBinder binder = createBinder();
108 ConstructorArgumentPrimitive object = binder.bind(ConstructorArgumentPrimitive.class, 5, true);
109 assertNotNull(object);
110 assertEquals(5, object.intField);
111 assertTrue(object.booleanField);
112 }
113
114 @Test
115 public void testInjectWithArgumentSubclass()
116 {
117 PageBinder binder = createBinder();
118 ConstructorArgumentPage page = binder.bind(ConstructorArgumentPage.class, 43);
119 assertEquals(43, page.age);
120 }
121
122 @Test
123 public void testInitAfterInject()
124 {
125 PageBinder binder = createBinder(StringField.class, StringFieldImpl.class);
126 OneFieldWithInitPage page = binder.bind(OneFieldWithInitPage.class);
127 assertEquals("Bob Jones", page.name);
128 }
129
130 @Test
131 public void testPrivateInitAfterInject()
132 {
133 PageBinder binder = createBinder(StringField.class, StringFieldImpl.class);
134 OneFieldWithPrivateInitPage page = binder.bind(OneFieldWithPrivateInitPage.class);
135 assertEquals("Bob Private", page.name);
136 }
137
138 @Test
139 public void testOneFieldWithSuperClassInit()
140 {
141 PageBinder binder = createBinder(StringField.class, StringFieldImpl.class);
142 OneFieldWithSuperClassInitPage page = binder.bind(OneFieldWithSuperClassInitPage.class);
143 assertEquals("Bob Private", page.getName());
144
145 }
146
147 @Test
148 public void testProtectedInitAfterInject()
149 {
150 PageBinder binder = createBinder(StringField.class, StringFieldImpl.class);
151 OneFieldWithProtectedInitPage page = binder.bind(OneFieldWithProtectedInitPage.class);
152 assertEquals("Bob Protected", page.name);
153 }
154
155 @Test
156 public void testParentInject()
157 {
158 PageBinder binder = createBinder(StringField.class, StringFieldImpl.class);
159 ChildNoNamePage page = binder.bind(ChildNoNamePage.class);
160 assertEquals("Bob", page.name.getValue());
161 }
162
163 @Test
164 public void shouldImplementConfigurableInjectionContext()
165 {
166 final PageBinder binder = createBinder(StringField.class, StringFieldImpl.class);
167 assertThat(binder, CoreMatchers.instanceOf(ConfigurableInjectionContext.class));
168 assertEquals("Bob", binder.bind(OneFieldPage.class).name.getValue());
169 ConfigurableInjectionContext.class.cast(binder)
170 .configure()
171 .addImplementation(StringField.class, AnotherStringFieldImpl.class)
172 .finish();
173 assertEquals("Rob", binder.bind(OneFieldPage.class).name.getValue());
174 }
175
176 @Test
177 public void shouldAllowConfiguringNewSingletonInstanceThatIsSubclassOfInterfaceType()
178 {
179 final PageBinder binder = createBinder();
180 ConfigurableInjectionContext.class.cast(binder)
181 .configure()
182 .addSingleton(StringField.class, new StringFieldImpl())
183 .finish();
184 assertEquals("Bob", binder.bind(OneFieldPage.class).name.getValue());
185 }
186
187 @Test
188 public void shouldAllowConfiguringNewImplementationInstance()
189 {
190 final PageBinder binder = createBinder(StringField.class, StringFieldImpl.class);
191 assertEquals("Bob", binder.bind(OneFieldPage.class).name.getValue());
192 ConfigurableInjectionContext.class.cast(binder)
193 .configure()
194 .addSingleton(StringField.class, new StringField()
195 {
196 @Override
197 public String getValue()
198 {
199 return "Boom!";
200 }
201 })
202 .finish();
203 assertEquals("Boom!", binder.bind(OneFieldPage.class).name.getValue());
204 }
205
206 @Test
207 public void visitUrlShouldRemoveExtraSlashAfterHostname() throws Exception
208 {
209 when(productInstance.getBaseUrl()).thenReturn("http://localhost/");
210
211 final PageBinder binder = createBinder(StringField.class, StringFieldImpl.class);
212 binder.navigateToAndBind(OneFieldPage.class);
213
214 verify(tester).gotoUrl("http://localhost/path");
215 }
216
217 @Test
218 public void visitUrlShouldAddMissingSlashAfterHostname() throws Exception
219 {
220 when(productInstance.getBaseUrl()).thenReturn("http://localhost");
221
222 final PageBinder binder = createBinder(StringField.class, StringFieldImpl.class);
223 binder.navigateToAndBind(PageWithNoLeadingSlash.class);
224
225 verify(tester).gotoUrl("http://localhost/path");
226 }
227
228 static class AbstractPage implements Page
229 {
230 public String getUrl()
231 {
232 return "/path";
233 }
234 }
235
236 static class OneFieldPage extends AbstractPage
237 {
238 @Inject
239 private StringField name;
240 }
241
242 static class PageWithNoLeadingSlash extends AbstractPage
243 {
244 @Override
245 public String getUrl()
246 {
247 return "path";
248 }
249 }
250
251 static class ConstructorArgumentPrimitive
252 {
253 private final int intField;
254 private final boolean booleanField;
255
256 public ConstructorArgumentPrimitive(int intArg, boolean booleanArg)
257 {
258 this.intField = intArg;
259 this.booleanField = booleanArg;
260 }
261 }
262
263
264 static class ConstructorArgumentPage extends AbstractPage
265 {
266 private final String name;
267 private final Number age;
268
269 public ConstructorArgumentPage(String name)
270 {
271 this.name = name;
272 this.age = null;
273 }
274
275 public ConstructorArgumentPage(Number age)
276 {
277 this.age = age;
278 this.name = null;
279 }
280 }
281
282 static class ParentNamePage extends AbstractPage
283 {
284 @Inject
285 protected StringField name;
286 }
287
288 static class ChildNoNamePage extends ParentNamePage
289 {
290 }
291
292 static class DefaultsPage extends AbstractPage
293 {
294 @Inject
295 private ProductInstance productInstance;
296
297 @Inject
298 private TestedProduct testedProduct;
299
300 @Inject
301 private MyTestedProduct myTestedProduct;
302
303 @Inject
304 private Tester tester;
305
306 @Inject
307 private SetTester setTester;
308
309 @Inject
310 private PageBinder pageBinder;
311 }
312
313 static class OneFieldWithInitPage extends AbstractPage
314 {
315 @Inject
316 private StringField field;
317
318 private String name;
319 @Init
320 public void init()
321 {
322 name = field.getValue() + " Jones";
323 }
324 }
325
326 static interface StringField
327 {
328 String getValue();
329 }
330
331 static class StringFieldImpl implements StringField
332 {
333 public String getValue()
334 {
335 return "Bob";
336 }
337 }
338
339 static class AnotherStringFieldImpl implements StringField
340 {
341 public String getValue()
342 {
343 return "Rob";
344 }
345 }
346
347 static class OneFieldWithPrivateInitPage extends AbstractPage
348 {
349 @Inject
350 private StringField field;
351
352 private String name;
353
354 @Init
355 private void init()
356 {
357 name = field.getValue() + " Private";
358 }
359
360 public String getName()
361 {
362 return name;
363 }
364 }
365
366 static class OneFieldWithProtectedInitPage extends AbstractPage
367 {
368 @Inject
369 private StringField field;
370
371 private String name;
372
373 @Init
374 protected void init()
375 {
376 name = field.getValue() + " Protected";
377 }
378 }
379
380 static class OneFieldWithSuperClassInitPage extends OneFieldWithPrivateInitPage
381 {
382 }
383
384 }