2020 */
2121package eu .tsystems .mms .tic .testframework .pageobjects .internal ;
2222
23+ import com .google .common .eventbus .EventBus ;
24+ import com .google .common .eventbus .Subscribe ;
25+ import eu .tsystems .mms .tic .testframework .common .Testerra ;
2326import eu .tsystems .mms .tic .testframework .enums .CheckRule ;
27+ import eu .tsystems .mms .tic .testframework .events .MethodEndEvent ;
2428import eu .tsystems .mms .tic .testframework .exceptions .PageFactoryException ;
2529import eu .tsystems .mms .tic .testframework .logging .Loggable ;
2630import eu .tsystems .mms .tic .testframework .pageobjects .Component ;
2731import eu .tsystems .mms .tic .testframework .pageobjects .Page ;
2832import eu .tsystems .mms .tic .testframework .pageobjects .UiElement ;
29- import eu . tsystems . mms . tic . testframework . utils . StringUtils ;
30- import java . lang . reflect . Constructor ;
33+ import org . apache . commons . collections . buffer . CircularFifoBuffer ;
34+ import org . apache . commons . lang3 . StringUtils ;
3135import org .openqa .selenium .WebDriver ;
3236
33- public class DefaultPageFactory implements PageFactory , Loggable {
37+ import java .lang .reflect .Constructor ;
38+ import java .util .List ;
39+ import java .util .stream .Collectors ;
40+
41+ public class DefaultPageFactory implements PageFactory , MethodEndEvent .Listener , Loggable {
3442
3543 @ Deprecated
3644 private String GLOBAL_PAGES_PREFIX = null ;
3745 @ Deprecated
3846 private final ThreadLocal <String > THREAD_LOCAL_PAGES_PREFIX = new ThreadLocal <>();
3947
48+ private static final ThreadLocal <CircularFifoBuffer > LOOP_DETECTION_LOGGER = new ThreadLocal <>();
49+ private static final int NR_OF_LOOPS = Properties .PAGE_FACTORY_LOOPS .asLong ().intValue ();
50+
4051 @ Override
4152 public PageFactory setGlobalPagesPrefix (String pagePrefix ) {
4253 GLOBAL_PAGES_PREFIX = pagePrefix ;
@@ -55,25 +66,31 @@ public PageFactory clearThreadLocalPagesPrefix() {
5566 return this ;
5667 }
5768
69+ public DefaultPageFactory () {
70+ // For clear PageFactory loop detection buffer
71+ EventBus eventBus = Testerra .getEventBus ();
72+ eventBus .register (this );
73+ }
74+
5875 @ Override
5976 public <T extends Page > T createPage (Class <T > pageClass , WebDriver webDriver ) {
6077 return createPageWithCheckRule (pageClass , webDriver , CheckRule .DEFAULT );
6178 }
6279
6380 private String getConfiguredPrefix () {
6481 String pagesPrefix = GLOBAL_PAGES_PREFIX ;
65- if (! StringUtils .isStringEmpty (THREAD_LOCAL_PAGES_PREFIX .get ())) {
82+ if (StringUtils .isNotEmpty (THREAD_LOCAL_PAGES_PREFIX .get ())) {
6683 pagesPrefix = THREAD_LOCAL_PAGES_PREFIX .get ();
6784 }
68- return (pagesPrefix != null ? pagesPrefix : "" );
85+ return (pagesPrefix != null ? pagesPrefix : "" );
6986 }
7087
7188 @ Override
7289 public <T extends Component > T createComponent (Class <T > componentClass , UiElement rootElement ) {
7390 try {
7491 Constructor <T > constructor = componentClass .getConstructor (UiElement .class );
7592 T component = constructor .newInstance (rootElement );
76- ((AbstractPage )component ).checkUiElements ();
93+ ((AbstractPage ) component ).checkUiElements ();
7794 return component ;
7895 } catch (Throwable throwable ) {
7996 throw new PageFactoryException (componentClass , rootElement .getWebDriver (), throwable );
@@ -83,16 +100,50 @@ public <T extends Component> T createComponent(Class<T> componentClass, UiElemen
83100 @ Override
84101 @ Deprecated
85102 public <T extends Page > T createPageWithCheckRule (Class <T > pageClass , WebDriver webDriver , CheckRule checkRule ) {
103+ T page ;
86104 try {
87- String pageClassString = String .format ("%s.%s%s" ,pageClass .getPackage ().getName (), getConfiguredPrefix (), pageClass .getSimpleName ());
105+ String pageClassString = String .format ("%s.%s%s" , pageClass .getPackage ().getName (), getConfiguredPrefix (), pageClass .getSimpleName ());
88106 pageClass = (Class <T >) Class .forName (pageClassString );
89107
90108 Constructor <T > constructor = pageClass .getConstructor (WebDriver .class );
91- T page = constructor .newInstance (webDriver );
92- ((AbstractPage )page ).checkUiElements (checkRule );
93- return page ;
109+ page = constructor .newInstance (webDriver );
110+ ((AbstractPage ) page ).checkUiElements (checkRule );
94111 } catch (Throwable throwable ) {
95112 throw new PageFactoryException (pageClass , webDriver , throwable );
96113 }
114+ this .runLoopDetection (pageClass );
115+ return page ;
116+ }
117+
118+ private void runLoopDetection (Class pageClass ) {
119+ CircularFifoBuffer buffer = LOOP_DETECTION_LOGGER .get ();
120+ if (buffer == null ) {
121+ CircularFifoBuffer fifoBuffer = new CircularFifoBuffer (NR_OF_LOOPS );
122+ LOOP_DETECTION_LOGGER .set (fifoBuffer );
123+ buffer = LOOP_DETECTION_LOGGER .get ();
124+ }
125+
126+ buffer .add (pageClass );
127+
128+ // Check if complete buffer contains only one class
129+ if (buffer .size () == NR_OF_LOOPS ) {
130+ List <Class > list = (List <Class >) buffer .stream ().distinct ().collect (Collectors .toList ());
131+
132+ // if this list is size 1, then there is only 1 page type loaded in NR_OF_LOOPS load actions (recorded by the buffer)
133+ if (list .size () == 1 ) {
134+ // NR_OF_LOOPS times this one class has been loaded in this thread
135+ throw new RuntimeException ("PageFactory create loop detected loading: " + list .get (0 ));
136+ }
137+ }
138+ }
139+
140+ @ Override
141+ @ Subscribe
142+ public void onMethodEnd (MethodEndEvent event ) {
143+ this .clearLoopDetectionBuffer ();
144+ }
145+
146+ private void clearLoopDetectionBuffer () {
147+ LOOP_DETECTION_LOGGER .get ().clear ();
97148 }
98149}
0 commit comments