View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
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    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.libraries.jquery;
16  
17  import java.io.IOException;
18  import java.nio.charset.StandardCharsets;
19  import java.util.ArrayList;
20  import java.util.List;
21  
22  import org.eclipse.jetty.server.Server;
23  import org.htmlunit.WebClient;
24  import org.htmlunit.WebDriverTestCase;
25  import org.htmlunit.WebRequest;
26  import org.htmlunit.WebResponse;
27  import org.htmlunit.WebResponseData;
28  import org.htmlunit.WebServerTestCase;
29  import org.htmlunit.http.HttpStatus;
30  import org.htmlunit.junit.SetExpectedAlertsBeforeTestExecutionCallback;
31  import org.htmlunit.util.WebConnectionWrapper;
32  import org.junit.jupiter.api.AfterAll;
33  import org.junit.jupiter.api.Assertions;
34  import org.junit.jupiter.api.BeforeEach;
35  import org.openqa.selenium.By;
36  import org.openqa.selenium.NoSuchElementException;
37  import org.openqa.selenium.StaleElementReferenceException;
38  import org.openqa.selenium.WebDriver;
39  import org.openqa.selenium.WebElement;
40  import org.openqa.selenium.htmlunit.HtmlUnitDriver;
41  
42  /**
43   * Base class for jQuery Tests.
44   *
45   * @author Ronald Brill
46   */
47  public abstract class JQueryTestBase extends WebDriverTestCase {
48  
49      protected static final class OnlyLocalConnectionWrapper extends WebConnectionWrapper {
50          private static final WebResponseData RESPONSE_DATA =
51                  new WebResponseData("not found".getBytes(StandardCharsets.US_ASCII),
52                          HttpStatus.NOT_FOUND_404, HttpStatus.NOT_FOUND_404_MSG,
53                          new ArrayList<>());
54  
55  
56          protected OnlyLocalConnectionWrapper(final WebClient webClient) {
57              super(webClient);
58          }
59  
60          @Override
61          public WebResponse getResponse(final WebRequest request) throws IOException {
62              final String url = request.getUrl().toExternalForm();
63  
64              if (url.contains("localhost")) {
65                  return super.getResponse(request);
66              }
67  
68  
69              return new WebResponse(RESPONSE_DATA, request, 0);
70          }
71      }
72  
73      private static Server SERVER_;
74  
75      /**
76       * Returns the jQuery version being tested.
77       * @return the jQuery version being tested
78       */
79      abstract String getVersion();
80  
81      /**
82       * Runs the specified test.
83       * @param testName the test name
84       * @throws Exception if an error occurs
85       */
86      protected void runTest(final String testName) throws Exception {
87          final String testNumber = readTestNumber(testName);
88          if (testNumber == null) {
89              assertEquals("Test number not found for: " + testName,
90                      SetExpectedAlertsBeforeTestExecutionCallback.NO_ALERTS_DEFINED, getExpectedAlerts());
91              return;
92          }
93          final long runTime = 60 * DEFAULT_WAIT_TIME.toMillis();
94          final long endTime = System.currentTimeMillis() + runTime;
95  
96          try {
97              final WebDriver webDriver = getWebDriver();
98  
99              if (webDriver instanceof HtmlUnitDriver) {
100                 final WebClient webClient = ((HtmlUnitDriver) webDriver).getWebClient();
101                 new OnlyLocalConnectionWrapper(webClient);
102             }
103 
104             final String url = buildUrl(testNumber);
105             webDriver.get(url);
106 
107             while (!getResultElementText(webDriver).startsWith("Tests completed")) {
108                 Thread.sleep(42);
109 
110                 if (System.currentTimeMillis() > endTime) {
111                     final String result = "Test #" + testNumber
112                                             + " runs too long (longer than " + runTime / 1000 + "s)";
113                     assertEquals(getExpectedAlerts()[0], result);
114                     return;
115                 }
116             }
117 
118             final String result = getResultDetailElementText(webDriver, testNumber);
119             final String expected = testName + " (" + getExpectedAlerts()[0] + ")";
120             if (!expected.contains(result)) {
121                 System.out.println("--------------------------------------------");
122                 System.out.println("URL:      " + url);
123                 System.out.println("Test:     " + webDriver.findElement(By.id("qunit-tests")).getText());
124                 System.out.println("Result:   " + result);
125                 System.out.println("Failures: ");
126                 final List<WebElement> failures = webDriver.findElements(By.cssSelector(".qunit-assert-list li.fail"));
127                 for (final WebElement webElement : failures) {
128                     System.out.println("  " + webElement.getText());
129                 }
130                 System.out.println("--------------------------------------------");
131 
132                 Assertions.fail("'" + expected + "' does not contain teh current result '" + result);
133             }
134         }
135         catch (final Exception e) {
136             e.printStackTrace();
137             Throwable t = e;
138             while ((t = t.getCause()) != null) {
139                 t.printStackTrace();
140             }
141             throw e;
142         }
143     }
144 
145     private static String getResultElementText(final WebDriver webdriver) {
146         // if the elem is not available or stale we return an empty string
147         // this will force a second try
148         try {
149             final WebElement elem = webdriver.findElement(By.id("qunit-testresult"));
150             try {
151                 return elem.getText();
152             }
153             catch (final StaleElementReferenceException e) {
154                 return "";
155             }
156         }
157         catch (final NoSuchElementException e) {
158             return "";
159         }
160     }
161 
162     /**
163      * Determine test number for test name.
164      * @param testName the name
165      * @return the test number
166      * @throws Exception in case of problems
167      */
168     protected String readTestNumber(final String testName) throws Exception {
169         final String testResults = loadExpectation("/libraries/jQuery/"
170                                         + getVersion() + "/expectations/results", ".txt");
171         final String[] lines = testResults.split("\n");
172         for (int i = 0; i < lines.length; i++) {
173             final String line = lines[i];
174             final int pos = line.indexOf(testName);
175             if (pos != -1
176                     && line.indexOf('(', pos + testName.length() + 3) == -1) {
177                 return Integer.toString(i + 1);
178             }
179         }
180 
181         return null;
182     }
183 
184     /**
185      * @param testNumber the number of the test to run
186      * @return the test url
187      */
188     protected String buildUrl(final String testNumber) {
189         return URL_FIRST + "jquery/test/index.html?dev&testNumber=" + testNumber;
190     }
191 
192     /**
193      * @param webdriver the web driver
194      * @param testNumber the number of the test to run
195      * @return the test result details
196      */
197     protected String getResultDetailElementText(final WebDriver webdriver, final String testNumber) {
198         final WebElement output = webdriver.findElement(By.id("qunit-test-output0"));
199         String result = output.getText();
200         result = result.substring(0, result.indexOf("Rerun")).trim();
201         return result;
202     }
203 
204     /**
205      * @throws Exception if an error occurs
206      */
207     @BeforeEach
208     public void aaa_startSesrver() throws Exception {
209         if (SERVER_ == null) {
210             SERVER_ = WebServerTestCase.createWebServer("src/test/resources/libraries/jQuery/" + getVersion(), null);
211         }
212     }
213 
214     /**
215      * @throws Exception if an error occurs
216      */
217     @AfterAll
218     public static void zzz_stopServer() throws Exception {
219         if (SERVER_ != null) {
220             SERVER_.stop();
221             SERVER_.destroy();
222             SERVER_ = null;
223         }
224     }
225 }