3

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? :)

AvantiC
  • 367
  • 3
  • 17

2 Answers2

3

1) For now the only way to set the browser size in your case is using the t.resizeWindow command. To avoid code duplication you can do it in the fixture.beforeEach hook (see testcafe documentation).

Meanwhile, Nightmare allows to set the browser size via its constructor options. But it's necessary to add API for this in the testcafe-browser-provider-nightmare plugin.

2) I've opened your site in nightmare in visual mode (without TestCafe) and have tried to click on the .dropdown-toggle link. But redirect to a new page doesn't occur. After some debug I see that the event.preventDefault() is called in the script for the click event. (In chrome this is not called and redirect occurs). Scripts are minified so it's hard to determine the real reason why preventDefault is called. I think it's something specific for electron browser, and it's necessary to investigate why it happens. Here is the script how I run it:

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();
Alexander Moskovkin
  • 1,861
  • 12
  • 13
  • Hi, thanks for your answer. So I tried to reproduce using the script you provided, but when the window opens and I visually click on the first entry of the nav-bar (which has the class `.dropdown-toggle`) the redirect still happens as expected?! I also searched through the code and couldn't find any `preventDefault()` related to this class. Can you maybe tell me, where you saw this being called so I can investigate further? – AvantiC Apr 10 '17 at 10:49
  • Here are screencasts where you can see how I've found it: [link1](https://www.screencast.com/t/n00w2NRVEvi), [advanced debug](https://www.screencast.com/t/T5WUlB11p) – Alexander Moskovkin Apr 10 '17 at 12:45
  • I tracked down the root of the error (see other comment) but it's a little out of my depth right now to see, why that would be failing for nightmare (or rather electron). I can work around it by just hovering over the element and clicking on another one. At least that keeps my tests going for now. ;) Thanks alot for your help in providing the screencasts. ;) – AvantiC Apr 10 '17 at 15:43
1

So, with Alexander's help (thank you very much!) I was able to track down the root of this error to jQuery.

The following lines seem to cause this behaviour:

    // 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 );
    }

I'm not really sure why this happens though. And especially why it only happens when the test is run with nightmare while other browsers seem to do just fine...

AvantiC
  • 367
  • 3
  • 17