Testcafe+Nightmare: Why is element not in DOM?

时间:2017-04-10 00:03:52

标签: javascript testing acceptance-testing nightmare testcafe

I have the following test:

fixture('Minimal reproduction')
  .page('http://www.sport-conrad.com/');


test('Navigate to item-details', async t => {
  await t
    .click('.dropdown-toggle')
    .click('.productData:first-of-type a')
  });

When I run this with testcafe chrome test.js it works as expect.

If I do testcafe nightmare test.js I get the error The element that matches the specified selector is not visible..

I tracked this one down to the fact that apparently the Electron-browser nightmare uses opens up the page with a viewport that causes the desktop-nav to disappear and so .dropdown-toggle is not visible anymore. So I worked around this by adding a manual resize:

fixture('Minimal reproduction')
  .page('http://www.sport-conrad.com/');


test('Navigate to item-details', async t => {
  await t
    .resizeWindow(1024, 900)
    .click('.dropdown-toggle')
    .click('.productData:first-of-type a')
  });

So my first question: While this works, is there another way to provide the dimension that testcafe opens up the browser in nightmare-mode?

...but: Now that .dropdown-toggle is back, I expected the test to pass again, just like before.

Unfortunately now I get another error: The specified selector does not match any element in the DOM tree. ...which seems to relate to the second selector. I'm not sure why though.

So my second question: What is the nightmare browser here doing differently? I tried a similar test-case on another page and it seemed to load the page fine just as chrome did.

I also tried a couple of workaround like forcing the browser to wait for some time but nothing worked.

Maybe someone can point me in the right direction here? :)

2 个答案:

答案 0 :(得分:3)

1)现在,在您的情况下设置浏览器大小的唯一方法是使用t.resizeWindow命令。为避免代码重复,您可以在fixture.beforeEach挂钩中执行此操作(请参阅testcafe documentation)。

同时,Nightmare允许通过constructor options设置浏览器大小。但是在testcafe-browser-provider-nightmare插件中为此添加API是必要的。

2)我已在nightmare以可视模式(没有TestCafe)打开了您的网站,并尝试点击.dropdown-toggle链接。但是,重定向到新页面并不会发生。经过一些调试后,我发现在单击事件的脚本中调用了event.preventDefault()。 (在chrome中,这不会被调用,并且会发生重定向)。脚本被缩小,因此很难确定调用preventDefault的真正原因。我认为它是电子浏览器特有的东西,有必要调查它为什么会发生。 以下是我运行它的脚本:

var Nightmare = require('nightmare');       
var nightmare = Nightmare({
    show: true,
    width: 1024,
    height: 600,
    webPreferences: { devTools: true },
    executionTimeout: 1000000,
    waitTimeout: 1000000
});

nightmare
  .goto('http://www.sport-conrad.com/')
  .wait(1000000)
  .end();

答案 1 :(得分:1)

所以,在Alexander的帮助下(非常感谢!)我能够将这个错误的根源追溯到jQuery。

以下行似乎会导致此行为:

    // Determine handlers
    handlerQueue = jQuery.event.handlers.call( this, event, handlers );

    // Run delegates first; they may want to stop propagation beneath us
    i = 0;
    while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
        event.currentTarget = matched.elem;

        j = 0;
        while ( ( handleObj = matched.handlers[ j++ ] ) &&
            !event.isImmediatePropagationStopped() ) {

            // Triggered event must either 1) have no namespace, or 2) have namespace(s)
            // a subset or equal to those in the bound event (both can have no namespace).
            if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {

                event.handleObj = handleObj;
                event.data = handleObj.data;

                ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
                    handleObj.handler ).apply( matched.elem, args );

                if ( ret !== undefined ) {
                    if ( ( event.result = ret ) === false ) {
                        event.preventDefault();
                        event.stopPropagation();
                    }
                }
            }
        }
    }

    // Call the postDispatch hook for the mapped type
    if ( special.postDispatch ) {
        special.postDispatch.call( this, event );
    }

我不确定为什么会这样。特别是为什么只有当测试以噩梦运行时才发生,而其他浏览器似乎做得很好......