mcdcorp / opentest

Open source test automation tool for web applications, mobile apps and APIs
https://getopentest.org
MIT License
455 stars 110 forks source link

org.getopentest.selenium.HandleModal doesn't work #604

Open TripleG opened 1 year ago

TripleG commented 1 year ago
  - actor: WEB
    segments:
      - segment: 1
        actions:
          - description: Navigate to DemoQA
            action: org.getopentest.selenium.NavigateTo
            args:
              url: https://demoqa.com/alerts

          - description: Trigger Alert Box
            action: org.getopentest.selenium.Click
            args:
              locator: { css: "#alertButton" }

          - description: Read the text displayed in the dialog box
            action: org.getopentest.selenium.HandleModal
            args:
              perform: getText
              $localData:
                dialogText: $output.text

          - description: Log the text that we just read
            script: |
              $log("The dialog box said: " + $localData.dialogText);

Action getText seems to close the Alert Box without reading the text and then it throws: java.lang.RuntimeException: org.openqa.selenium.TimeoutException: Expected condition failed: waiting for alert to be present (tried for 10 second(s) with 500 milliseconds interval)

Action accept does the same - the alert box is closed and then the same exception thrown.

adrianth commented 1 year ago

I'm not surprised you're seeing problems with this, as modals handling is notoriously tricky in web testing. This topic doesn't receive much attention anymore, since basic authentication is a bad practice and not used in modern applications. The causes for the error could be either the Selenium Java client library or the WebDriver executable for the browser you are testing with. The most likely culprit is the WebDriver - please check that you are using the right WebDriver executable for your browser version.

The way OpenTest uses Selenium is pretty straightforward and it is unlikely to be the cause of the error. You can take a look for yourself here. If you notice any problem, I'd be happy to help with providing a fix, but the code is very simple and unlikely to be the cause of the issue you're seeing.

One other thing people suggest is to try and avoid the modal dialog altogether by providing the authentication details in the URL. See here for more information, if this is a viable option for you.

TripleG commented 1 year ago

Hi @adrianth ,

This is not HTTP Authentication modal, but a simple alert box.

I tried the same site with pure Selenium and it works fine:

@Test
public void modal() {
  var driver = new ChromeDriver();
  driver.manage().timeouts().implicitlyWait(20L, TimeUnit.SECONDS);
  try {
      driver.get("https://demoqa.com/alerts");
      driver.findElement(By.cssSelector("#alertButton")).click();

      (new WebDriverWait(driver, 5L)).until(ExpectedConditions.alertIsPresent());
      var alert = driver.switchTo().alert();
      var text = alert.getText();
      System.out.println("Alert box text is: " + text);
  } finally {
      driver.quit();
  }
}

The problem is definitely in OpenTest. The alert box is closed before the wait.until(ExpectedConditions.alertIsPresent()); gets executed. Seems that somewhere here the closing of the alert box happens:

super.run();

String perform = this.readStringArgument("perform");

this.waitForAsyncCallsToFinish();

Did you run the test by yourself?

adrianth commented 1 year ago

If the code that you included above works fine, then the Selenium Java client library used in OpenTest is the source of the problem. Can you please let me know what version of the Selenium Java client library you used for your test?

TripleG commented 1 year ago

I am using Selenium API version 3.14.0 What version does OpenTest use?

adrianth commented 1 year ago

OpenTest is using 3.141.59. I was pretty sure you were using version 4. Now I am really confused as to what the root cause may be. :-(

ewmartinez commented 1 year ago

Hi any advance on this, I am with the same problem This is a common scenario Thank you very much

Keonik1 commented 1 year ago

I also came across the fact that HandleModal does not work. In my situation, just replace with http://user:pass@url it is impossible due to the peculiarities of the site, so processing the browser request is the only solution (from what I know)

UPD: maybe it will be useful to someone:

The problem in my case was that when authenticating in this way (http://user:pass@url ) the page did not load. But I found out that if I then go to the same link without authentication (http://url ), then the page will load completely, moreover, you will be under the user entered earlier. However, this is all a crutch due to the fact that it does not work org.getopentest.selenium.HandleModal

Config:

description: Open my url
actors:
  - actor: WEB
    segments:
      - segment: 1
        actions:
          - description: auth on my site
            action: org.getopentest.selenium.NavigateTo
            args:
              url: http://user:password@mysite.test/

          - description: Navigate to my site homepage
            action: org.getopentest.selenium.NavigateTo
            args:
              url: http://mysite.test/
Keonik1 commented 1 year ago

OK, I found one crutch, but it works. If all you need is to click "OK" (return true) or maybe "Cancel" (return false), you can overwrite the "window.confirm" function (possibly an alert and more). Just add this code before you expect the warning window to appear:

          - description: Auto click "OK" for allert
            action: org.getopentest.selenium.ExecuteScript
            args:
              script: |
                window.confirm = function() {return true}

          - description: Click - Save
            macro: ClickSaveButton #Showing allert window

UPD

I have updated the macro for pressing the save button so that the optional confirmAllert argument can be used if necessary.

description: Click save button
actions:
  - description: Other - Check whether the autoclicker needs to be set up 
    script: |
      $localData.isNeedSetupHandlerClicker = false
      if(typeof($macroArgs.confirmAllert) === 'boolean')
        $localData.isNeedSetupHandlerClicker = true

  - description: Other - Build the browser script to set allert auto answer
    action: org.getopentest.actions.Format
    args:
      template: |
        window.confirm = function() {return ${$macroArgs.confirmAllert}}
      $if: $localData.isNeedSetupHandlerClicker

  - description: Other - Set allert auto answer
    action: org.getopentest.selenium.ExecuteScript
    args:
      script: $output.text
      $if: $localData.isNeedSetupHandlerClicker

  - description: Click - Save
    action: org.getopentest.selenium.Click
    args:
      locator: { xpath: "//input[@value='Save']" }

Inside test: