marmelab / FakeRest

Patch fetch/XMLHttpRequest to fake a REST API server in the browser, based on JSON data.
MIT License
439 stars 48 forks source link

Problem to intercept jQuery ajax requests (and also Angular $http requests) #20

Closed blocknotes closed 7 years ago

blocknotes commented 8 years ago

Here is how I init (data is a simple hash):

          var restServer = new FakeRest.Server();
          restServer.init(data);
          var server = sinon.fakeServer.create();
          server.respondWith(restServer.getHandler());

Using pure JS works as expected:

          var req = new XMLHttpRequest();
          req.onreadystatechange = function() {
            console.log(req.responseText);
          };
          req.open("GET", "/authors", false);
          req.setRequestHeader( 'Accept', '*/*' );
          req.setRequestHeader( 'X-Requested-With', 'XMLHttpRequest');
          req.send(null);

If I try with jQuery the request seems to be caught but I get no response:

          var jqxhr = jQuery.ajax( { url: "/authors", accepts: { all: '*/*' } } )
          .done(function() {
            console.log( "success" );
          })
          .fail(function() {
            console.log( "error" );
          })
          .always(function() {
            console.log( "complete" );
          });

No console output.

The same with angularJS:

            $http({
              method: 'GET',
              url: '/authors'
            }).then(function successCallback(response) {
              console.log( 'ok' );
            }, function errorCallback(response) {
              console.log( 'err' );
            });

Any idea?

fzaninotto commented 8 years ago

Did you load and register FakeRest before jQuery is loaded?

blocknotes commented 8 years ago

How could I do it?

I tried also to inject jQuery later on (for testing):

  <script>
    setTimeout( function() {
(function() {
    var script = document.createElement("SCRIPT");
    script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js';
    script.type = 'text/javascript';
    document.getElementsByTagName("head")[0].appendChild(script);
})();
    }, 1000 );
  </script>
fzaninotto commented 8 years ago

Insert all the script tags mentioned in the Readme Usage section before loading jQuery.

blocknotes commented 8 years ago

That's what I tried.

Here are my script tags:

  <script src="FakeRest/dist/FakeRest.min.js"></script>
  <script src="sinon/sinon-1.17.3.js"></script>
  <script src="jquery/jquery-1.12.4.min.js"></script>

I tried in head or in the end of the body, same result.

If I inspect the ajax requests they are the same (headers are equals)

I put my code on plnkr if you want to take a look: https://plnkr.co/edit/unEDpD8mMMhUUqwhfAQQ?p=preview

airtonix commented 7 years ago

@fzaninotto @blocknotes problem is demonstrated here: http://codepen.io/airtonix/pen/BQKMjp

airtonix commented 7 years ago

@fzaninotto @blocknotes Ok so it looks like when you set async: false on the jQuery.ajax call, it succeeds and fakerest can intercept.

But change it back to the default of async: true, then fakerest can't intercept.

fzaninotto commented 7 years ago

I think the problem lies in sinon fake server

https://github.com/sinonjs/sinon/issues/510

blocknotes commented 7 years ago

@airtonix using async: false works for me too, probably it is caused by Sinon as pointed by @fzaninotto