1   /*
2    * Copyright 2007 united internet (unitedinternet.com) Robert Zimmermann
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   *
16   */
17  package com.unitedinternet.portal.selenium.utils.logging;
18  
19  import static org.easymock.EasyMock.aryEq;
20  import static org.easymock.EasyMock.createMock;
21  import static org.easymock.EasyMock.createNiceMock;
22  import static org.easymock.EasyMock.eq;
23  import static org.easymock.EasyMock.expect;
24  import static org.easymock.EasyMock.replay;
25  import static org.easymock.EasyMock.verify;
26  import static org.fest.assertions.Assertions.assertThat;
27  import static org.junit.Assert.assertEquals;
28  import static org.junit.Assert.fail;
29  
30  import org.junit.After;
31  import org.junit.Before;
32  import org.junit.Ignore;
33  import org.junit.Test;
34  
35  import com.thoughtworks.selenium.CommandProcessor;
36  import com.thoughtworks.selenium.Wait;
37  
38  @SuppressWarnings("PMD.TooManyStaticImports")
39  public class WaitUseCases {
40      CommandProcessor mockCommandProcessor;
41      LoggingResultsFormatter mockFormatter;
42      LoggingCommandProcessor testProcessor;
43  
44      @Before
45      public void setUp() {
46          mockCommandProcessor = createMock(CommandProcessor.class);
47          mockFormatter = createNiceMock(LoggingResultsFormatter.class);
48  
49          testProcessor = new LoggingCommandProcessor(mockCommandProcessor, mockFormatter);
50          doSetupLogExecutionEnvironment();
51      }
52  
53      @After
54      public void tearDown() {
55          verify(mockCommandProcessor);
56          verify(mockFormatter);
57      }
58  
59      void doReplayMocks() {
60          replay(mockCommandProcessor);
61          replay(mockFormatter);
62      }
63  
64      void doSetupLogExecutionEnvironment() {
65          mockCommandProcessor.start();
66          // TODO: duplication - same setup as in LoggingCommandProcessorTest.logExecutionEnvironment()
67          expect(mockCommandProcessor.getString(eq("getEval"), aryEq(new String[] {"navigator.userAgent"}))).andReturn(
68                  (String) "testUserAgent");
69          expect(mockCommandProcessor.getString(eq("getEval"), aryEq(new String[] {"window.top.Selenium.coreVersion"}))).andReturn(
70                  (String) "testCoreVersion");
71          expect(mockCommandProcessor.getString(eq("getEval"), aryEq(new String[] {"window.top.Selenium.coreRevision"})))
72                  .andReturn((String) "testCoreRevision");
73          expect(mockCommandProcessor.getString(eq("getEval"), aryEq(new String[] {"window.top.Selenium.rcVersion"}))).andReturn(
74                  (String) "testRcVersion");
75          expect(mockCommandProcessor.getString(eq("getEval"), aryEq(new String[] {"window.top.Selenium.rcRevision"}))).andReturn(
76                  (String) "testRcRevision");
77          mockCommandProcessor.stop();
78      }
79  
80      /**
81       * Attention: Timing is important for this test to succeed. So in case of debugging or very slow processing this test could
82       * wrongly fail.
83       */
84      @Test
85      public void correctTimeDelta_WaitTimedOut() {
86          expect(mockCommandProcessor.getBoolean(eq("isTextPresent"), aryEq(new String[] {"TestTextBeforeWait"}))).andReturn(
87                  (boolean) false);
88          expect(mockCommandProcessor.getBoolean(eq("isTextPresent"), aryEq(new String[] {"WaitTestText"}))).andReturn(
89                  (boolean) false).times(3);
90          expect(mockFormatter.generateFilenameForAutomaticScreenshot("WaitTimeout")).andReturn("MockFilename");
91          expect(mockCommandProcessor.doCommand(eq("captureScreenshot"), aryEq(new String[] {"MockFilename"}))).andReturn(
92                  (String) "OK");
93  
94          doReplayMocks();
95  
96          final LoggingSelenium selenium = new LoggingDefaultSelenium(testProcessor);
97          selenium.start();
98          selenium.isTextPresent("TestTextBeforeWait");
99          long startMillis = System.currentTimeMillis();
100         try {
101             new Wait() {
102                 public boolean until() {
103                     return selenium.isTextPresent("WaitTestText");
104                 }
105             }.wait("Wait Timeout Message", 300, 110);
106             fail("Expected WaitTimedOutException not occured.");
107         } catch (Exception timedOutException) {
108             assertEquals("Wait Timeout Message", timedOutException.getMessage());
109         }
110         selenium.stop();
111         long absoluteDeltaMillis = System.currentTimeMillis() - startMillis;
112 
113         assertEquals(5, testProcessor.loggingEventsQueue.size());
114         LoggingBean preWaitLoggingBean = testProcessor.loggingEventsQueue.get(0);
115         LoggingBean waitFalseLoggingBean1 = testProcessor.loggingEventsQueue.get(1);
116         // testProcessor.loggingEventsQueue.get(2) does not matter here
117         LoggingBean waitFalseLoggingBean3 = testProcessor.loggingEventsQueue.get(3);
118         LoggingBean screenshotLoggingBean = testProcessor.loggingEventsQueue.get(4);
119         assertEquals("isTextPresent", preWaitLoggingBean.getCommandName());
120         assertEquals("TestTextBeforeWait", preWaitLoggingBean.getArgs()[0]);
121 
122         assertEquals("isTextPresent", waitFalseLoggingBean1.getCommandName());
123         assertEquals("WaitTestText", waitFalseLoggingBean1.getArgs()[0]);
124         assertEquals("OK,false", waitFalseLoggingBean1.getResult());
125 
126         assertEquals("(Wait)isTextPresent", waitFalseLoggingBean3.getCommandName());
127         assertEquals("WaitTestText", waitFalseLoggingBean3.getArgs()[0]);
128         assertEquals("ERROR,wait timed out", waitFalseLoggingBean3.getResult());
129 
130         assertEquals("captureScreenshot", screenshotLoggingBean.getCommandName());
131         // These small timings can easily be broken on slow build-hardware
132         // so be careful with limits especially if cobertura instrumented code is run
133         assertThat(absoluteDeltaMillis).isGreaterThanOrEqualTo(300L);
134         assertThat(waitFalseLoggingBean3.getDeltaMillis()).isGreaterThanOrEqualTo(300L).isLessThanOrEqualTo(absoluteDeltaMillis);
135     }
136 
137     /**
138      * Attention: Timing is important for this test to succeed. So in case of debugging or very slow processing this test could
139      * wrongly fail.
140      */
141     @Test
142     public void correctTimeDelta_WaitSucceeded() {
143         expect(mockCommandProcessor.getBoolean(eq("isTextPresent"), aryEq(new String[] {"TestTextBeforeWait"}))).andReturn(
144                 (boolean) false);
145         expect(mockCommandProcessor.getBoolean(eq("isTextPresent"), aryEq(new String[] {"WaitTestText"}))).andReturn(
146                 (boolean) false).times(2);
147         expect(mockCommandProcessor.getBoolean(eq("isTextPresent"), aryEq(new String[] {"WaitTestText"}))).andReturn(
148                 (boolean) true);
149         expect(mockCommandProcessor.getBoolean(eq("isTextPresent"), aryEq(new String[] {"TestTextAfterWait"}))).andReturn(
150                 (boolean) false);
151 
152         doReplayMocks();
153 
154         final LoggingSelenium selenium = new LoggingDefaultSelenium(testProcessor);
155         selenium.start();
156         selenium.isTextPresent("TestTextBeforeWait");
157         long startMillis = System.currentTimeMillis();
158         new Wait() {
159             public boolean until() {
160                 return selenium.isTextPresent("WaitTestText");
161             }
162         }.wait("Wait Timeout Message", 1000, 100);
163         long absoluteDeltaMillis = System.currentTimeMillis() - startMillis;
164         selenium.isTextPresent("TestTextAfterWait");
165         selenium.stop();
166 
167         assertEquals(5, testProcessor.loggingEventsQueue.size());
168         LoggingBean preWaitLoggingBean = testProcessor.loggingEventsQueue.get(0);
169         LoggingBean waitFalseLoggingBean1 = testProcessor.loggingEventsQueue.get(1);
170         // testProcessor.loggingEventsQueue.get(2) does not matter here
171         LoggingBean waitTrueLoggingBean = testProcessor.loggingEventsQueue.get(3);
172         LoggingBean afterWaitloggingBean = testProcessor.loggingEventsQueue.get(4);
173 
174         assertEquals("isTextPresent", preWaitLoggingBean.getCommandName());
175         assertEquals("TestTextBeforeWait", preWaitLoggingBean.getArgs()[0]);
176 
177         assertEquals("isTextPresent", waitFalseLoggingBean1.getCommandName());
178         assertEquals("WaitTestText", waitFalseLoggingBean1.getArgs()[0]);
179         assertEquals("OK,false", waitFalseLoggingBean1.getResult());
180 
181         assertEquals("(Wait)isTextPresent", waitTrueLoggingBean.getCommandName());
182         assertEquals("WaitTestText", waitTrueLoggingBean.getArgs()[0]);
183         assertEquals("OK,true", waitTrueLoggingBean.getResult());
184 
185         assertEquals("isTextPresent", afterWaitloggingBean.getCommandName());
186         assertEquals("TestTextAfterWait", afterWaitloggingBean.getArgs()[0]);
187         assertEquals("OK,false", afterWaitloggingBean.getResult());
188         // These small timings can easily be broken on slow build-hardware
189         // so be careful with limits especially if cobertura instrumented code is run
190         assertThat(absoluteDeltaMillis).isGreaterThanOrEqualTo(200L);
191         assertThat(waitTrueLoggingBean.getDeltaMillis()).isGreaterThanOrEqualTo(200L).isLessThanOrEqualTo(absoluteDeltaMillis);
192     }
193 
194     /**
195      * Attention: Timing is important for this test to succeed. So in case of debugging or very slow processing this test could
196      * wrongly fail.
197      */
198     @Ignore("Broken by design. Use AOP to get this issue working")
199     @Test
200     public void noSeleniumCommandAfterWaitAndWaitSucceeded() {
201         expect(mockCommandProcessor.getBoolean(eq("isTextPresent"), aryEq(new String[] {"TestText"}))).andReturn((boolean) false);
202         expect(mockCommandProcessor.getBoolean(eq("isTextPresent"), aryEq(new String[] {"WaitTestText"}))).andReturn(
203                 (boolean) false).times(7);
204         expect(mockCommandProcessor.getBoolean(eq("isTextPresent"), aryEq(new String[] {"WaitTestText"}))).andReturn(
205                 (boolean) true);
206 
207         doReplayMocks();
208 
209         final LoggingSelenium selenium = new LoggingDefaultSelenium(testProcessor);
210         selenium.start();
211         boolean resultDoesNotMatter = selenium.isTextPresent("TestText"); // NOPMD it is an explaining variable
212         long startMillis = System.currentTimeMillis();
213         new Wait() {
214             public boolean until() {
215                 return selenium.isTextPresent("WaitTestText");
216             }
217         }.wait("Wait Timeout Message", 1000, 100);
218         long absoluteDeltaMillis = System.currentTimeMillis() - startMillis;
219         // call seleniumTestFinished directly to get to the metrics before they get flushed to the formatter
220         testProcessor.seleniumTestFinished();
221 
222         assertEquals(3, testProcessor.loggingEventsQueue.size());
223         LoggingBean loggingBean0 = testProcessor.loggingEventsQueue.get(0);
224 
225         LoggingBean loggingBean1 = testProcessor.loggingEventsQueue.get(1);
226         LoggingBean loggingBean2 = testProcessor.loggingEventsQueue.get(2);
227 
228         assertEquals("X-1and1-logComment", loggingBean0.getCommandName());
229         assertEquals("executing noSeleniumCommandAfterWaitAndWaitSucceeded()", loggingBean0.getArgs()[0]);
230         assertEquals("isTextPresent", loggingBean1.getCommandName());
231         assertEquals("(Wait)isTextPresent", loggingBean2.getCommandName());
232         // These small timings can easily be broken on slow build-hardware so do not set an upper limit
233         // especially if cobertura instrumented code is run
234         assertThat(absoluteDeltaMillis).isGreaterThanOrEqualTo(700L);
235         assertThat(loggingBean2.getDeltaMillis()).isGreaterThanOrEqualTo(700L);
236     }
237 }