1 package com.atlassian.webdriver.testing.rule;
2
3 import com.atlassian.pageobjects.TestedProduct;
4 import com.atlassian.pageobjects.inject.InjectionContext;
5 import com.atlassian.pageobjects.util.InjectingTestedProducts;
6 import com.google.common.base.Supplier;
7 import org.junit.ClassRule;
8 import org.junit.rules.TestRule;
9 import org.junit.runner.Description;
10 import org.junit.runners.model.Statement;
11 import org.junit.runners.model.TestClass;
12 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory;
14
15 import java.util.List;
16
17 import static com.google.common.base.Preconditions.checkNotNull;
18
19
20
21
22
23
24 final class InstanceInjectionRules
25 {
26 private static final Logger logger = LoggerFactory.getLogger(InstanceInjectionRules.class);
27
28 static abstract class AbstractInstanceInjectionRule implements TestRule
29 {
30
31 private final Object target;
32
33 public AbstractInstanceInjectionRule(Object target)
34 {
35 this.target = checkNotNull(target, "target");
36 }
37
38 @Override
39 public final Statement apply(final Statement base, final Description description)
40 {
41 return new Statement() {
42 @Override
43 public void evaluate() throws Throwable
44 {
45 if (supportsInjection(base, description))
46 {
47 injectionContext(base, description).injectMembers(target);
48 }
49 base.evaluate();
50 }
51 };
52 }
53
54 protected abstract boolean supportsInjection(Statement base, Description description);
55
56 protected abstract InjectionContext injectionContext(Statement base, Description description);
57
58 }
59
60 static final class InstanceStandaloneInjectionRule<T extends TestedProduct<?>> extends AbstractInstanceInjectionRule
61 {
62 private final Supplier<T> product;
63
64 InstanceStandaloneInjectionRule(Object target, Supplier<T> productSupplier)
65 {
66 super(target);
67 this.product = checkNotNull(productSupplier, "productSupplier");
68 }
69
70 @Override
71 protected boolean supportsInjection(Statement base, Description description)
72 {
73 return InjectingTestedProducts.supportsInjection(product.get());
74 }
75
76 @Override
77 protected InjectionContext injectionContext(Statement base, Description description)
78 {
79 return InjectingTestedProducts.asInjectionContext(product.get());
80 }
81 }
82
83
84
85
86 static final class InstanceCollaboratingInjectionRule extends AbstractInstanceInjectionRule
87 {
88 InstanceCollaboratingInjectionRule(Object target)
89 {
90 super(target);
91 }
92
93 @Override
94 protected boolean supportsInjection(Statement base, Description description)
95 {
96 return findClassInjectionRule(description).supportsInjection();
97 }
98
99 @Override
100 protected InjectionContext injectionContext(Statement base, Description description)
101 {
102 return findClassInjectionRule(description).injectionContext();
103 }
104
105 private ClassInjectionRule<?> findClassInjectionRule(Description description)
106 {
107 final List<ClassInjectionRule> rules = getClassInjectionRules(description);
108 if (rules.isEmpty())
109 {
110 throw new IllegalStateException("Test class configuration invalid: to use context-aware members injection " +
111 "rule you must declare a class rule as well. See JavaDoc of the " +
112 "com.atlassian.webdriver.testing.rule.InjectionRules class");
113 }
114 if (rules.size() > 1)
115 {
116 logger.warn("More than one field of type " + ClassInjectionRule.class.getName() + " annotated with " +
117 "@ClassRule. Using the first one to retrieve injection context");
118 }
119 return rules.get(0);
120 }
121
122 private List<ClassInjectionRule> getClassInjectionRules(Description description)
123 {
124 return new TestClass(description.getTestClass())
125 .getAnnotatedFieldValues(null, ClassRule.class, ClassInjectionRule.class);
126 }
127 }
128
129 }