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.testing.utils.StreamMatchers.*;
20  import static java.util.Objects.*;
21  import static java.util.concurrent.TimeUnit.*;
22  import static org.hamcrest.MatcherAssert.*;
23  import static org.hamcrest.Matchers.*;
24  import static org.openqa.selenium.remote.CapabilityType.*;
25  
26  import java.net.*;
27  
28  import org.openqa.selenium.*;
29  import org.openqa.selenium.remote.*;
30  import org.testng.annotations.*;
31  
32  import dev.aherscu.qa.jgiven.commons.utils.*;
33  import edu.umd.cs.findbugs.annotations.*;
34  import lombok.*;
35  import lombok.extern.slf4j.*;
36  
37  @Slf4j
38  public class TestingRemoteWebApplication {
39      public final static String SAUCELABS_PASSWORD;
40      public final static String SAUCELABS_URL;
41      public final static String SAUCELABS_USER;
42  
43      static {
44          SAUCELABS_PASSWORD =
45              requireNonNull(System.getenv("SAUCELABS_PASSWORD"),
46                  "missing SauceLabs password");
47          SAUCELABS_USER =
48              requireNonNull(System.getenv("SAUCELABS_USER"),
49                  "missing SauceLabs username");
50          SAUCELABS_URL = String
51              .format("https://%s:%s@ondemand.saucelabs.com:443/wd/hub",
52                  SAUCELABS_USER, SAUCELABS_PASSWORD);
53      }
54  
55      private WebDriver webDriver;
56  
57      @Test
58      public void shouldFind() {
59          // NOTE the search keyword must be unique such that it is not
60          // translated to other languages or written differently
61          val SEARCH_KEYWORD = "testng";
62          webDriver.findElement(By.name("q"))
63              .sendKeys(SEARCH_KEYWORD + Keys.ENTER);
64          assertThat(
65              webDriver.findElements(By.xpath("//a/h3"))
66                  .stream()
67                  .map(webElement -> webElement.getAttribute("textContent"))
68                  .peek(resultTitle -> log.debug("found {}", resultTitle)),
69              allMatch(either(containsStringIgnoringCase("testng"))
70                  .or(containsStringIgnoringCase("Try again"))
71                  .or(containsStringIgnoringCase("More results"))));
72      }
73  
74      @Test
75      public void shouldOpenWeb() {
76          assertThat(webDriver.getTitle(), containsString("Google"));
77      }
78  
79      @SuppressFBWarnings(
80          value = "UPM_UNCALLED_PRIVATE_METHOD",
81          justification = "called by testng framework")
82      @AfterClass(alwaysRun = true) // important, otherwise we may leak resources
83      private void afterClassCloseWebDriver() {
84          webDriver.quit();
85      }
86  
87      @SuppressFBWarnings(
88          value = "UPM_UNCALLED_PRIVATE_METHOD",
89          justification = "called by testng framework")
90      @BeforeClass
91      @SneakyThrows
92      private void beforeClassOpenWebDriver() {
93          log.trace("connecting saucelabs with {}:{}",
94              SAUCELABS_USER, SAUCELABS_PASSWORD);
95          webDriver = new RemoteWebDriver(new URL(SAUCELABS_URL),
96              new DesiredCapabilitiesEx()
97                  .with(BROWSER_NAME, "firefox")
98                  .with("sauce:name", "selenium 4 test")
99          // NOTE since Selenium 4, non-standard capabilities must be prefixed;
100         // see https://www.w3.org/TR/webdriver1/#capabilities
101         // and https://docs.saucelabs.com/dev/test-configuration-options/
102         // and
103         // https://docs.saucelabs.com/dev/test-configuration-options/#desktop-and-mobile-capabilities-sauce-specific--optional
104         // and
105         // https://docs.saucelabs.com/mobile-apps/automated-testing/appium/appium-2-migration/
106         // For example,
107         // .with("my:capability", "kuku")
108         );
109 
110         webDriver.manage().window().maximize();
111         webDriver.manage().timeouts().implicitlyWait(10, SECONDS);
112         webDriver.get("https://google.com?hl=en");
113     }
114 }