View Javadoc
1   /*
2    * Copyright 2023 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.tutorial4;
18  
19  import static io.appium.java_client.remote.MobilePlatform.*;
20  import static io.appium.java_client.remote.options.SupportsAppOption.*;
21  import static io.appium.java_client.remote.options.SupportsAutoWebViewOption.*;
22  import static io.appium.java_client.remote.options.SupportsDeviceNameOption.*;
23  import static io.appium.java_client.remote.options.SupportsPlatformVersionOption.*;
24  import static java.util.concurrent.TimeUnit.*;
25  import static org.hamcrest.MatcherAssert.*;
26  import static org.hamcrest.Matchers.*;
27  import static org.openqa.selenium.remote.CapabilityType.*;
28  
29  import java.net.*;
30  import java.time.*;
31  import java.time.format.*;
32  
33  import org.openqa.selenium.*;
34  import org.openqa.selenium.remote.*;
35  import org.testng.annotations.*;
36  
37  import edu.umd.cs.findbugs.annotations.*;
38  import io.appium.java_client.android.*;
39  import lombok.*;
40  
41  /**
42   * TODO should run against one of the Android applications, e.g. Calculator
43   */
44  public class TestingAndroidOnSauceLabs {
45  
46      private WebDriver webDriver;
47  
48      @java.lang.SuppressWarnings("serial")
49      @SneakyThrows
50      static AndroidDriver saucelabsApp(
51          final String name) {
52          return new AndroidDriver(new URL(
53              // FIXME should get these credentials from system enviroment
54              // SAUCELABS_USERNAME and SAUCELABS_PASSWORD
55              "https://TBD:TBD@ondemand.saucelabs.com:443/wd/hub"),
56              new DesiredCapabilities() {
57                  {
58                      setCapability(PLATFORM_NAME, ANDROID);
59                      setCapability(PLATFORM_VERSION_OPTION, "8");
60                      setCapability(DEVICE_NAME_OPTION,
61                          "Samsung Galaxy S9 Plus WQHD GoogleAPI Emulator");
62                      setCapability(AUTO_WEB_VIEW_OPTION, true);
63                      setCapability(APP_OPTION, "sauce-storage:app.apk");
64                      setCapability("name", name);
65                      setCapability("build", "local-"
66                          + DateTimeFormatter.ofPattern("yyyyMMddHHmmss")
67                              .withZone(ZoneOffset.UTC)
68                              .format(Instant.now()));
69                  }
70              });
71      }
72  
73      @Test
74      public void shouldRequireEmail() {
75          assertThat(webDriver
76              .findElements(By.xpath("//*[text()='Please enter valid email']")),
77              not(empty()));
78      }
79  
80      @SuppressFBWarnings(
81          value = "UPM_UNCALLED_PRIVATE_METHOD",
82          justification = "called by testng framework")
83      @AfterClass(alwaysRun = true) // important, otherwise we may leak resources
84      private void afterClassCloseWebDriver() {
85          webDriver.quit();
86      }
87  
88      @SuppressFBWarnings(
89          value = "UPM_UNCALLED_PRIVATE_METHOD",
90          justification = "called by testng framework")
91      @BeforeClass
92      @SneakyThrows
93      private void beforeClassOpenWebDriver() {
94          // NOTE: ensure you have TBD.apk uploaded to SauceLabs
95          // curl -u "TBD:TBD" -X POST
96          // https://saucelabs.com/rest/v1/storage/TBD --data-binary
97          // @TBD.apk
98          webDriver = saucelabsApp(getClass().getSimpleName());
99          webDriver.manage().timeouts().implicitlyWait(5, SECONDS);
100     }
101 }