View Javadoc

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   * Injections rules for test instances. Access via {@link com.atlassian.webdriver.testing.rule.InjectionRules}.
21   *
22   * @since 2.1
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          // we need to have this guy provided by the test due to https://github.com/KentBeck/junit/issues/351
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       * An injection rule requiring the class injection rule to be present in the context.
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 }