title: Testing AJAX in vanilla js with Jest
body: <p>I'm trying to test a XMLHttpRequesting function in vanilla JavaScript with Jest. It's a unit test on one of model functions. The function is making a XMLHttpRequest towards the mashape.com randsom-famous-quote API.</p>
  
  <p>This is my model:</p>
  
  <pre><code>const QuoteModel = function(quote) {
      this.quote = quote;
      this.savedQuotes = [];
      this.quoteChanged = new Observer();
      this.quoteSaved = new Observer();
      this.quoteDeleted = new Observer();
  };
  
  QuoteModel.prototype.changeQuote = function(quote) {
      this.quote = quote;
      this.quoteChanged.notify(this.quote);
  };
  
  QuoteModel.prototype.fetchQuote = function(url, apiKey = null) {
      const xhr = new XMLHttpRequest();
      let data;
  
      // QuoteModel
      const self = this;
  
      xhr.onload = function() {
  
          if (xhr.status &gt;= 200 &amp;&amp; xhr.status &lt; 300) {
              data = JSON.parse(this.response)[0];
              self.changeQuote(data);
  
          } else {
              data = 'Bad response';
          }
  
      };
  
      xhr.onerror = function() {
          data = 'Error fetching quote';
      };
  
      xhr.open('GET', url, true);
  
      if (apiKey != null) xhr.setRequestHeader('X-Mashape-Key', apiKey);
  
      xhr.send();
  
  };
  
  QuoteModel.prototype.getQuote = function() {
      return this.quote;
  };
  
  QuoteModel.prototype.tweet = function() {
      // Opens a tweet window..
  };
  
  QuoteModel.prototype.loadSavedQuotes = function() {
      // Load quotes from localStorage..
  };
  
  QuoteModel.prototype.saveQuote = function(quote) {
      // Saves quotes to localStorage..
  };
  </code></pre>
  
  <p>So the fetchQuote function is making an AJAX request, and the calling changQuote with the received quote.</p>
  
  <p>In my unit test for the model, I've got this:</p>
  
  <pre><code>import QuoteModel from '../js/QuoteModel';
  import config from '../config.js';
  
  const model = new QuoteModel({
      quote: 'I will never be quoted!',
      author: 'Michael Krøyserth-Simsø'
  });
  
  // https://stackoverflow.com/questions/28584773/xhr-testing-in-jest
  const xhrMockClass = () =&gt; ({
      open: jest.fn(),
      send: jest.fn(),
      setRequestHeader: jest.fn(),
      status: 200,
      response: JSON.stringify([{
          quote: 'A fetched quote is as good as any quote.',
          author: 'Pelle the Cat'
      }])
  });
  
  window.XMLHttpRequest = jest.fn().mockImplementation(xhrMockClass);
  
  // fetchQuote - ajax call to get quote is successfull
  test('should make XMLHttpRequest to get new quote', () =&gt; {
      model.fetchQuote('https://andruxnet-random-famous-quotes.p.mashape.com/?cat=famous&amp;count=10', config.API_KEY);
      expect(model.quote).toEqual({
          quote: 'A fetched quote is as good as any quote.',
          author: 'Pelle the Cat'
      });
  });
  </code></pre>
  
  <p>When I run the test I get this:</p>
  
  <pre><code> FAIL  test/QuoteModel.test.js
    ✕ should make XMLHttpRequest to get new quote (16ms)
    ✓ should have quote set (1ms)
    ✓ should change quote on request
  
    ● should make XMLHttpRequest to get new quote
  
      expect(received).toEqual(expected)
  
      Expected value to equal:
        {"author": "Pelle the Cat", "quote": "A fetched quote is as good as any quote."}
      Received:
        {"author": "Michael Krøyserth-Simsø", "quote": "I will never be quoted!"}
  
      Difference:
  
      - Expected
      + Received
  
        Object {
      -   "author": "Pelle the Cat",
      -   "quote": "A fetched quote is as good as any quote.",
      +   "author": "Michael Krøyserth-Simsø",
      +   "quote": "I will never be quoted!",
        }
  
        23 | test('should make XMLHttpRequest to get new quote', () =&gt; {
        24 |     model.fetchQuote('https://andruxnet-random-famous-quotes.p.mashape.com/?cat=famous&amp;count=10', config.API_KEY);
      &gt; 25 |     expect(model.quote).toEqual({
           |                         ^
        26 |         quote: 'A fetched quote is as good as any quote.',
        27 |         author: 'Pelle the Cat'
        28 |     });
  
        at Object.&lt;anonymous&gt; (test/QuoteModel.test.js:25:25)
  
  Test Suites: 1 failed, 1 total
  Tests:       1 failed, 2 passed, 3 total
  Snapshots:   0 total
  Time:        1.985s
  Ran all test suites matching /test\/QuoteModel.test.js/i.
  npm ERR! Test failed.  See above for more details.
  </code></pre>
  
  <p>In my mind the call to model.fetchQuote should change this.quote with the new quote in the mock function.
  I got that idea from <a href="https://stackoverflow.com/questions/28584773/xhr-testing-in-jest">this quiestion - XHR testing in Jest
  </a>. </p>
  
  <ul>
  <li>What am I missing here? </li>
  <li>Am I at least on the right track?</li>
  <li>Is this the right way to test AJAX?</li>
  </ul>
  
  <p>(This is the "Random Quote Machine" project in <a href="https://www.freecodecamp.org/" rel="nofollow noreferrer">FreeCodeCamp</a>. I know it's overkill but I just really wanted to make a front end app with MVC.)
  <a href="https://github.com/michaelsimsoe/fcc_rqm" rel="nofollow noreferrer">The repository</a></p>