一次向下滚动一个下拉列表(igCombo)元素,直到它到达列表末尾

时间:2017-05-15 19:41:39

标签: c# selenium

我有一个igCombo下拉控件,它使用虚拟化将项目从javascript加载到HTML中。在初始扩展下拉列表时,完整的项目列表不在列表/ HTML中,只有前10个项目。当用户向下滚动时,新项目将加载到HTML中。所以我不能简单地使用SelecElement.SelectByText,或者我不能使用一个简单的函数来存储来自HTML的for循环中的所有li元素,因为如果我要点击的项目是索引11或更远,它不会在还没有HTML。

我认为攻击它的唯一方法是使用for循环将初始项存储在HTML中。然后,如果用户传递的itemToClick变量值与此for循环中的任何项匹配,请单击该项,否则向下滚动一整页以加载下一个10项。重复循环,直到itemToClick值与滚动后的任何项目匹配,或者直到滚动到达下拉列表的底部,然后在那时,告诉用户该项目不存在。

所以我的方法调用就在这里。请注意,我想点击" MTV",它位于下拉列表的底部:

ClickListItemByNameVirtualization(driver, dropDownElem, scrollBarElem, "MTV");

这是方法。请参阅 NOT CODED YET 评论。这就是我需要帮助的地方。我尝试了几件事,但我不能提出适用于我需要的代码:

public void ClickListItemByNameVirtualization(IWebDriver browser, IWebElement divElemOfScrollBar, IWebElement ulElemOfDropDown, string itemName)
{
    bool topOfList = true;

    do
    {
        if (topOfList == false)
        {
            // NOT CODED YET: I need a method that scrolls down page by page within a dropdown frame. For reference of how I scroll statically inside a
            // frame, see my ScrollToWithinFrame method that I referenced at the bottom of this post
            ScrollDownPageWithinDropdown();
        }

        topOfList = false;

        // Store all li elements within the unordered list
        var liElems = ulElemOfDropDown.FindElements(By.TagName("li")).ToList();

        // Loop through all list items
        foreach (var liElem in liElems)
        {
            // if the current list item's text value in the for loop equals the users passed parameter itemName
            if (liElem.Text == itemName)
            {
                liElem.Click();
                Thread.Sleep(0200);
                return;
            }
        }
        // NOT CODED YET: I need code to add to ScrollBarEnd that returns true or false. Only do the above code if ScrollBarEnd is false
    } while (!ScrollBarEnd());
}

最后,作为参考,这是我在框架内滚动的代码:

public void ScrollToWithinFrame(IWebDriver browser, IWebElement divElemOfScrollBar, int xOrYCoordinate, string HorizontalOrVertical)
{
    IJavaScriptExecutor js = (IJavaScriptExecutor)browser;

    if (HorizontalOrVertical == "Vertical")
    {
        js.ExecuteScript("arguments[0].scrollTop = arguments[1];", divElemOfScrollBar, xOrYCoordinate);
    }

    if (HorizontalOrVertical == "Horizontal")
    {
        // Scroll inside the popup frame element vertically. See the following...
        // http://stackoverflow.com/questions/22709200/selenium-webdriver-scrolling-inside-a-div-popup
        js.ExecuteScript("arguments[0].scrollLeft = arguments[1];", divElemOfScrollBar, xOrYCoordinate);
    }
}

2 个答案:

答案 0 :(得分:0)

您可以使用无限循环与服务员等待列表末尾的新<li>元素:

public void ClickListItemByNameVirtualization(IWebDriver browser, IWebElement divElemOfScrollBar, IWebElement ulElemOfDropDown, string itemName)
{
    var wait = new WebDriverWait(browser, TimeSpan.FromSeconds(5));
    IWebElement lastLi = null;

    while (true) {

        // wait for a new li element at the end and store all li elements
        var liElems = wait.Until<ReadOnlyCollection<IWebElement>>(drv => {

            var elems = ulElemOfDropDown.FindElements(By.TagName("li"));

            return (elems.Count > 0 && elems[elems.Count - 1] != lastLi) ? elems : null;
        });

        // store the last element
        lastLi = liElems[liElems.Count - 1];

        // Loop through all list items
        foreach (var liElem in liElems) {
            // if the current list item's text value in the for loop equals the users passed parameter itemName
            if (liElem.Text == itemName) {
                liElem.Click();
                return;
            }
        }

        // scroll the container to the end
        ((IJavaScriptExecutor)browser).js.ExecuteScript(
          "arguments[0].scrollTop = (-1 >>> 1);", divElemOfScrollBar);
    }
}

答案 1 :(得分:0)

我想出了一个丑陋的方法。因为我知道滚动条在展开时的可见高度,其中包含可见项目(每个滚动10个加载到HTML中的项目),我使用可见高度(387像素)滚动我的for循环的每一步直到我达到最大高度。这里是。直到2天我都不会将此标记为答案,可能会给别人一个更直观的尝试。

public static void ClickListItemByNameVirtualization(IWebDriver browser, IWebElement ulElem, IWebElement divElem, string itemName)
        int scrollAmount = 0;
        IJavaScriptExecutor js = (IJavaScriptExecutor)browser;

        ProgramLibraryPage PL = new ProgramLibraryPage(browser);
        PL.ChangeProgFormSelectProgDrpDnBtn.Click();

        // Scroll to the top of the list
        js.ExecuteScript("return arguments[0].scrollTop = 0;", divElem);


        for (var i = 0; i < 1000; i++)
        {
            List<IWebElement> liElems = ulElem.FindElements(By.TagName("li")).ToList();

            foreach (var liElem in liElems)
            {
                // if the current list item's text value in the for loop equals the users passed parameter itemName
                if (liElem.Text == itemName)
                {
                    liElem.Click();
                    Thread.Sleep(0200);
                    return;
                }
            }

            scrollAmount = scrollAmount + 387;

            object scrollMaxHeight = js.ExecuteScript("return arguments[0].scrollHeight;", divElem);

            var scrollMaxHeightInt = Convert.ToInt32(scrollMaxHeight);

            if (scrollMaxHeightInt > scrollAmount)
            {
                ElemSet.ScrollToWithinFrame(browser, divElem, scrollAmount, "Vertical");
            }
        }
}