单击指向当前页面的链接时,如何测试页面是否已重新加载?

时间:2014-01-03 12:19:19

标签: selenium functional-testing spock geb

我有一个奇怪的错误,我试图通过测试重新创建。我知道是什么导致了这个bug以及如何修复它,但我无法弄清楚如何正确测试它。

情景:

  • 我的浏览器位于http://example.com/foo
  • 我点击该页面上的链接,其中包含href =“/ foo”(同一页面)
  • 浏览器应重新加载同一页面

我试过了:

class SamePageHyperlinkSpec extends StatelessUserWebGebSpec {

    def 'users is on Foo page and clicks foo link'() {

        when:
            to FooPage

        then:
            // navigation.foo is a property in a super class that references
            // a particular navigation item
            navigation.foo.click()

        and:
            at FooPage
    }
}

...但这给出了误报,因为虽然浏览器没有重新加载页面,但它已经在该页面上。所以,我想我会看一下PageChangeListener,它应该允许我在页面更改时通过/失败:

class SamePageHyperlinkSpec extends StatelessUserWebGebSpec {

    def 'users is on Foo page and clicks foo link'() {

        given:
            def listener = new MyPageChangeListener()
            browser.registerPageChangeListener(listener)

        when:
            to FooPage
        and:
            listener.changeCount = 0

        then:
            // navigation.foo is a property in a super class that references
            // a particular navigation item
            navigation.foo.click()

        and:
            at FooPage

        and:
            listener.changeCount == 1
    }
}

class MyPageChangeListener implements PageChangeListener {

    int changeCount = 0

    void pageWillChange(Browser browser, Page oldPage, Page newPage) {
        println "browser '$browser' changing page from '$oldPage' to '$newPage'"
        changeCount++
    }
}

...当没有页面重新加载时失败(因为它应该),但是当页面重新加载时它也会失败,因为它最终的页面是相同的,因此没有页面更改< / em>发生了。

我也尝试复制Page类(并且它是“at”闭包),但无论是否有页面重新加载,它总是会通过。

那么,当我点击指向当前页面的链接时,如何测试页面是否已重新加载?

3 个答案:

答案 0 :(得分:1)

以@PaulHarris为首,JS方法似乎可以解决问题:

class SamePageHyperlinkSpec extends StatelessUserWebGebSpec {

    def 'users is on Foo page and clicks foo link'() {

        when:
            to FooPage

        and:
            browser.js.exec '$(document.body).attr("data-not-reloaded",true);'

        then:
            // navigation.foo is a property in a super class that references
            // a particular navigation item
            navigation.foo.click()

        and:
            at FooPage

        and:
            browser.js.exec 'return $(document.body).attr("data-not-reloaded") === undefined';
    }
}

答案 1 :(得分:0)

Here是C#.Net中WaitForPageLoad实现的更好且经过测试的版本

public void WaitForPageLoad(int maxWaitTimeInSeconds) {
string state = string.Empty;
try {
    WebDriverWait wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(maxWaitTimeInSeconds));

    //Checks every 500 ms whether predicate returns true if returns exit otherwise keep trying till it returns ture
    wait.Until(d = > {

        try {
            state = ((IJavaScriptExecutor) _driver).ExecuteScript(@"return document.readyState").ToString();
        } catch (InvalidOperationException) {
            //Ignore
        } catch (NoSuchWindowException) {
            //when popup is closed, switch to last windows
            _driver.SwitchTo().Window(_driver.WindowHandles.Last());
        }
        //In IE7 there are chances we may get state as loaded instead of complete
        return (state.Equals("complete", StringComparison.InvariantCultureIgnoreCase) || state.Equals("loaded", StringComparison.InvariantCultureIgnoreCase));

    });
} catch (TimeoutException) {
    //sometimes Page remains in Interactive mode and never becomes Complete, then we can still try to access the controls
    if (!state.Equals("interactive", StringComparison.InvariantCultureIgnoreCase))
        throw;
} catch (NullReferenceException) {
    //sometimes Page remains in Interactive mode and never becomes Complete, then we can still try to access the controls
    if (!state.Equals("interactive", StringComparison.InvariantCultureIgnoreCase))
        throw;
} catch (WebDriverException) {
    if (_driver.WindowHandles.Count == 1) {
        _driver.SwitchTo().Window(_driver.WindowHandles[0]);
    }
    state = ((IJavaScriptExecutor) _driver).ExecuteScript(@"return document.readyState").ToString();
    if (!(state.Equals("complete", StringComparison.InvariantCultureIgnoreCase) || state.Equals("loaded", StringComparison.InvariantCultureIgnoreCase)))
        throw;
}
}

答案 2 :(得分:0)

如果你在页面的文本字段中写下一些值,那么等待该文本字段的等待例程不会包含在页面中,之后你点击链接呢? 所以程序就是这样:

1.-在文本字段中写一些新值或使用js添加新的html标记或其他内容。

2.-制定例行程序,等待页面中未包含您添加到页面的元素/值。

3.-点击链接。

4.-拨打等待代码。

请告诉我这是否适合您。