0

I am binding the beforeunload event of a page to make a quick synchronous ajax call (not best practice but it is essentially a ping so we are trying it as an idea).

$(window).bind('beforeunload', function(){
    makeAjaxPUTcall();

    //return 'Send a message!';
});

This works fine when built, deployed to a test environment and tested manually.

I was then trying to add some selenium tests (ChromeDriver) to automate the testing. The Ajax call does not seem to get made. Setting a breakpoint on the browser seems to show the code running through the Ajax call and if I uncomment the return I will get an (unwanted) alert before the page unloads. I have, for sake of argument, bound the javascript function to the blur event of the page controls

$(':input').on('blur', function() { makeAjaxPUTcall(); });

and it works without problem in selenium (as well as manual testing).

When run in the beforeunload event logging seems to show that the call never hits server.

The javascript function is like this

function makeAjaxPUTcall(){
    $.ajax({
        type : 'PUT',
        async: false,
        url: urlVal,
        data: null,
        processData: false,
        dataType: 'json',
        contentType: 'application/json',
        success: function() {}
        });
}

So in summary from where I'm standing I've proved, in various ways, that the code to make the REST call is working client side and server side. I have also 'proved' by manual dev testing that these calls are triggered when a page navigation takes place manually. I have also proved that the beforeunload event is being triggered in the selenium tests (by adding a return string and seeing an alert pop up).

I have also converted the PUT to a GET and after putting a breakpoint in the test code navigated a different tab to the url provided and proved that it is triggered and does hit a breakpoint in the (java) controller code.

It SEEMS to me that the issue must be something to do with the way Selenium is handling the navigation ? Can anyone point me in the next direction ?!

CEH
  • 5,701
  • 2
  • 16
  • 40
gringogordo
  • 1,990
  • 6
  • 24
  • 60
  • Can you include your Selenium code and explain what your automation is supposed to be doing? Including the HTML for the items you are automating (or, preferably, the entire page) will be another necessary component for this. There's no solid "yes" or "no" answer as to why an AJAX call isn't getting triggered, so seeing your Selenium code & HTML may give us the clues to develop a workaround for the issue. – CEH Dec 09 '19 at 15:14
  • see if this help you https://stackoverflow.com/questions/6162188/javascript-browsers-window-close-send-an-ajax-request-or-run-a-script-on-win – Benilson Dec 09 '19 at 16:24
  • If there are any unhandled prompts showing at the time, then Selenium will automatically dismiss them on unload... (including the prompt for navigating away) Just noting this in case you have an alert in there somewhere. You should also see section "7.8.11 Unloading documents" of the HTML spec: https://html.spec.whatwg.org/ This explains what the browser will do when unloading which includes the prompt behavior you described. (I know this doesn't answer your question, but it should help explain some of the quirks of beforeunload calls) – pcalkins Dec 09 '19 at 20:24
  • Maybe the answer is this... since this is an asynchronous call there is no guarantee that the call will ever reach the server. The only time it will happen is if the user is prompted BEFORE unload which Selenium will dismiss immediately. (I believe this is true even for the browser-launched prompt.) You can see that the browser launched prompt only occurs when return for the event is not empty... and that's returning more or less at the same time as the async call. – pcalkins Dec 09 '19 at 21:02

1 Answers1

1

Try it with fetch:

window.onbeforeunload = () => {
  fetch(url, {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({foo: "bar"})
  })
}

Why? Fetch creates a promise and I believe chrome will try to let that resolve first

pguardiario
  • 53,827
  • 19
  • 119
  • 159