IE でポップアップ ウィンドウを扱うときにほとんどの人が見逃しているのは、要素のクリックが非同期であることです。つまり.WindowHandles
、クリックした直後にプロパティをチェックすると、競合状態が失われる可能性があります。これは、IE が新しいウィンドウを作成する機会を得る前に新しいウィンドウの存在をチェックしているためであり、ドライバーが登録するチャンスが存在します。
同じ操作を実行するために使用する C# コードを次に示します。
string foundHandle = null;
string originalWindowHandle = driver.CurrentWindowHandle;
// Get the list of existing window handles.
IList<string> existingHandles = driver.WindowHandles;
IWebElement addtoList = driver.FindElement(By.XPath(_pageName));
addtoList.Click();
// Use a timeout. Alternatively, you could use a WebDriverWait
// for this operation.
DateTime timeout = DateTime.Now.Add(TimeSpan.FromSeconds(5));
while(DateTime.Now < timeout)
{
// This method uses LINQ, so it presupposes you are running on
// .NET 3.5 or above. Alternatively, it's possible to do this
// without LINQ, but the code is more verbose.
IList<string> currentHandles = driver.WindowHandles;
IList<string> differentHandles = currentHandles.Except(existingHandles).ToList();
if (differentHandles.Count > 0)
{
// There will ordinarily only be one handle in this list,
// so it should be safe to return the first one here.
foundHandle = differentHandles[0];
break;
}
// Sleep for a very short period of time to prevent starving the driver thread.
System.Threading.Thread.Sleep(250);
}
if (string.IsNullOrEmpty(foundHandle))
{
throw new Exception("didn't find popup window within timeout");
}
driver.SwitchToWindow(foundHandle);
// Do whatever verification on the popup window you need to, then...
driver.Close();
// And switch back to the original window handle.
driver.SwitchToWindow(originalWindowHandle);
ちなみに、.NET バインディングを使用している場合はPopupWindowFinder
、WebDriver.Support.dll アセンブリ内のクラスにアクセスできます。これは、ポップアップ ウィンドウを見つけるのと非常によく似た方法を使用します。クラスがニーズを正確に満たし、変更せずに使用できることがわかる場合があります。