View Javadoc
1   /*
2    * Copyright 2024 Adrian Herscu
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 dev.aherscu.qa.testing.example.scenarios.attic;
18  
19  import static dev.aherscu.qa.jgiven.commons.utils.ConfigurableScenarioTest.*;
20  import static dev.aherscu.qa.testing.example.scenarios.attic.TestingRemoteWebApplication.*;
21  import static dev.aherscu.qa.testing.utils.StreamMatchers.*;
22  import static java.util.concurrent.TimeUnit.*;
23  import static org.hamcrest.MatcherAssert.*;
24  import static org.hamcrest.Matchers.*;
25  import static org.openqa.selenium.remote.CapabilityType.*;
26  
27  import java.net.*;
28  import java.util.function.*;
29  
30  import org.jooq.lambda.*;
31  import org.openqa.selenium.*;
32  import org.openqa.selenium.chrome.*;
33  import org.openqa.selenium.remote.*;
34  import org.testng.annotations.*;
35  
36  import dev.aherscu.qa.jgiven.commons.utils.*;
37  import edu.umd.cs.findbugs.annotations.*;
38  import io.github.bonigarcia.wdm.*;
39  import lombok.*;
40  import lombok.extern.slf4j.*;
41  
42  @Slf4j
43  public class TestingWebApplication {
44      private final WebDriver webDriver;
45  
46      @Factory(dataProvider = INTERNAL_DATA_PROVIDER)
47      public TestingWebApplication(final Supplier<WebDriver> webDriver) {
48          this.webDriver = webDriver.get();
49          log.trace("testing with {}", webDriver);
50      }
51  
52      // NOTE: parallel with @Factory requires parallel=instances
53      // see https://github.com/testng-team/testng/issues/1951
54      @DataProvider(parallel = true)
55      private static Object[][] data() {
56          // NOTE we use suppliers in order to lazily create drivers;
57          // thus, only when the test is constructed by TestNG
58          return new Object[][] {
59              // ISSUE Firefox cannot be installed on certain systems
60              // { Unchecked.supplier(() -> {
61              // log.trace("setting up firefox driver");
62              // WebDriverManager.firefoxdriver().setup();
63              // return new FirefoxDriver();
64              // }) },
65              { Unchecked.supplier(() -> {
66                  log.trace("setting up chrome driver");
67                  WebDriverManager.chromedriver().setup();
68                  return new ChromeDriver();
69              }) },
70              { Unchecked.supplier(() -> {
71                  log.trace("setting up remote driver");
72                  return new RemoteWebDriver(
73                      new URL(SAUCELABS_URL),
74                      new DesiredCapabilitiesEx()
75                          .with(BROWSER_NAME, "firefox"));
76              }) }
77          };
78      }
79  
80      @Test
81      public void shouldFind() {
82          // NOTE the search keyword must be unique such that it is not
83          // translated to other languages or written differently
84          val SEARCH_KEYWORD = "testng";
85          log.debug("searching for {} on Google", SEARCH_KEYWORD);
86          webDriver.findElement(By.name("q"))
87              .sendKeys(SEARCH_KEYWORD + Keys.ENTER);
88          assertThat(
89              webDriver.findElements(By.xpath("//a/h3"))
90                  .stream()
91                  .map(webElement -> webElement.getAttribute("textContent"))
92                  .peek(resultTitle -> log.debug("found {}", resultTitle)),
93              allMatch(either(containsStringIgnoringCase("testng"))
94                  .or(containsStringIgnoringCase("Try again"))
95                  .or(containsStringIgnoringCase("More results"))));
96      }
97  
98      @Test
99      public void shouldOpenWeb() {
100         log.debug("window title must contain Google");
101         assertThat(webDriver.getTitle(), containsString("Google"));
102     }
103 
104     @SuppressFBWarnings(
105         value = "UPM_UNCALLED_PRIVATE_METHOD",
106         justification = "called by testng framework")
107     @AfterClass(alwaysRun = true) // important, otherwise we may leak resources
108     private void afterClassCloseWebDriver() {
109         webDriver.quit();
110     }
111 
112     @SuppressFBWarnings(
113         value = "UPM_UNCALLED_PRIVATE_METHOD",
114         justification = "called by testng framework")
115     @BeforeClass
116     @SneakyThrows
117     private void beforeClassOpenWebDriver() {
118         log.trace("before connecting selenium");
119         webDriver.manage().window().maximize();
120         webDriver.manage().timeouts().implicitlyWait(10, SECONDS);
121         webDriver.get("https://google.com?hl=en"); // ensure English
122     }
123 }