web-dev-qa-db-ja.com

Selenium Webdriverのポップアップ

だから私はC#winformでSelenium firefox webdriversを使って作業しており、「webtraffic_popup_start_button」をクリックするとポップアップのハンドルを取得するポップアップのハンドルを取得するためにこのコードを持っていますが、ポップアップのハンドルは同じです現在のものとして。

string current = driver.CurrentWindowHandle;
driver.FindElement(By.XPath("//*[@id='webtraffic_popup_start_button']")).Click();
Thread.Sleep(Sleep_Seconds);
popup = driver.CurrentWindowHandle;
Thread.Sleep(3000);
driver.SwitchTo().Window(current);
Thread.Sleep(1000);

これに関するヘルプは大歓迎です

これがポップアップの表示です。

Popup_Image

12
Coderz

WebDriverは、OSで実際にどのウィンドウがフォアグラウンドにあるかを検出するための追跡を一切行わず、新しいブラウザーウィンドウが開かれたときに自動切り替えを行いません。つまり、新しく開いたポップアップウィンドウのハンドルを取得する適切な方法は、複数ステップのプロセスです。そのためには、次のことを行います。

  1. 現在フォーカスされているウィンドウハンドルを変数に保存して、後で切り替えられるようにします。
  2. 現在開いているウィンドウハンドルのリストを取得します。
  3. 新しいウィンドウが表示される原因となるアクションを実行します。
  4. ウィンドウハンドルの数が1増えるまで待ちます。
  5. ウィンドウハンドルの新しいリストを取得します。
  6. ハンドルのリストで新しいハンドルを見つけます。
  7. その新しいウィンドウに切り替えます。

.NET言語バインディングを使用するコードでは、次のようになります。

string currentHandle = driver.CurrentWindowHandle;
ReadOnlyCollection<string> originalHandles = driver.WindowHandles;

// Cause the popup to appear
driver.FindElement(By.XPath("//*[@id='webtraffic_popup_start_button']")).Click();

// WebDriverWait.Until<T> waits until the delegate returns
// a non-null value for object types. We can leverage this
// behavior to return the popup window handle.
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5));
string popupWindowHandle = wait.Until<string>((d) =>
{
    string foundHandle = null;

    // Subtract out the list of known handles. In the case of a single
    // popup, the newHandles list will only have one value.
    List<string> newHandles = driver.WindowHandles.Except(originalHandles).ToList();
    if (newHandles.Count > 0)
    {
        foundHandle = newHandles[0];
    }

    return foundHandle;
});

driver.SwitchTo().Window(popupWindowHandle);

// Do whatever you need to on the popup browser, then...
driver.Close();
driver.SwitchToWindow(currentHandle);

または、.NETバインディングを使用している場合、これらの操作を行うために特別に設計されたWebDriver.SupportアセンブリにPopupWindowFinderクラスがあります。そのクラスの使用ははるかに簡単です。

// Get the current window handle so you can switch back later.
string currentHandle = driver.CurrentWindowHandle;

// Find the element that triggers the popup when clicked on.
IWebElement element = driver.FindElement(By.XPath("//*[@id='webtraffic_popup_start_button']"));

// The Click method of the PopupWindowFinder class will click
// the desired element, wait for the popup to appear, and return
// the window handle to the popped-up browser window. Note that
// you still need to switch to the window to manipulate the page
// displayed by the popup window.
PopupWindowFinder Finder = new PopupWindowFinder(driver);
string popupWindowHandle = Finder.Click(element);

driver.SwitchTo().Window(popupWindowHandle);

// Do whatever you need to on the popup browser, then...
driver.Close();
driver.SwitchToWindow(currentHandle);
27
JimEvans

最後に開いたウィンドウがターゲットの場合、クリック後に次の操作を行うだけです

driver.SwitchTo().Window(driver.WindowHandles.ToList().Last());

[〜#〜] edit [〜#〜]

//You may need to go back to parent window to perform additional actions;

// to the new window
driver.SwitchTo().Window(driver.WindowHandles.ToList().Last());

 // to the new window
driver.SwitchTo().Window(driver.WindowHandles.ToList().First());
//or
driver.SwitchTo().DefaultContent();
4
Saifur

あなたが好きかもしれないいくつかのコードを持っています。最も簡単な解決策はPopup Finderを使用することですが、私も独自の方法を作成しました。適切なウィンドウを選択するために、ウィンドウハンドルの順序に依存することはありません。ポップアップウィンドウファインダー:

PopupWindowFinder Finder = new PopupWindowFinder(driver);
driver.SwitchTo().Window(newWin); 

私のカスタムメソッド。基本的には、クリックする要素、Webドライバー、およびオプションで要素をクリックしてから検索するまでの待機時間を渡します。

現在のすべてのハンドルを取り、リストを作成します。このリストを使用して、既存のウィンドウが誤って切り替えられるのを防ぎます。次に、新しいウィンドウを起動する要素をクリックします。すぐには何も起こらないため、クリック後は常に何らかの遅延が発生するはずです。そして、新しいリストを作成し、新しいウィンドウを見つけるかループが期限切れになるまで、古いリストと比較します。新しいウィンドウが見つからない場合はnullが返されるため、常に機能しないiffy Web要素がある場合は、nullチェックを実行してスイッチが機能しているかどうかを確認できます。

public static string ClickAndSwitchWindow(IWebElement elementToBeClicked,
IWebDriver driver, int timer = 2000)
        {
            System.Collections.Generic.List<string> previousHandles = new 
System.Collections.Generic.List<string>();
            System.Collections.Generic.List<string> currentHandles = new 
System.Collections.Generic.List<string>();
        previousHandles.AddRange(driver.WindowHandles);
        elementToBeClicked.Click();

        Thread.Sleep(timer);
        for (int i = 0; i < 20; i++)
        {
            currentHandles.Clear();
            currentHandles.AddRange(driver.WindowHandles);
            foreach (string s in previousHandles)
            {
                currentHandles.RemoveAll(p => p == s);
            }
            if (currentHandles.Count == 1)
             {
                driver.SwitchTo().Window(currentHandles[0]);
                Thread.Sleep(100);
                return currentHandles[0];
            }
            else
            {
                Thread.Sleep(500);
            }
        }
        return null;
    }