3

I am using Jest with JS and trying to write a test around the X-ray JS library, a web scraping toolkit. The following is the test. This is using Jest 18.x and the latest x-ray js as of 02/20/2017.

const htmlResponse = require('../__mocks__/html_response'); // just contains {listingsPage: '<html>....</html>';}

describe('scraper', () => {
    it("should get David Nichols' latest study from valid HTML", (done) => {
        var listingsHtml = htmlResponse.listingsPage;
        const Xray = require('x-ray');
        const x = Xray();
        expect(x).not.toEqual(null);
        var parseHtml = x('#Repo tbody tr', { link: 'td:nth-child(1) a@href' })
        parseHtml(listingsHtml, (err, result) => {
            console.log(Object.keys(result));
            expect(result.link).toEqual('le test'); // commenting this out causes test to pass.
            done();
        });
});

If I remove the expect().toEqual call inside the callback above the done() the test runs:

 PASS  src/__tests__/scraper-test.js

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.315s, estimated 6s
Ran all test suites related to changed files.

with that line as-is, it times out. result is a simple object {link: 'string'} The test is making no network calls. I attempted updating the timeout value to 30 seconds with no luck.

 FAIL  src/__tests__/scraper-test.js (5.787s)

  ● scraper › should get David Nichols' latest study from valid HTML

    Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.

      at Timeout.callback [as _onTimeout] (node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/browser/Window.js:480:19)
      at ontimeout (timers.js:365:14)
      at tryOnTimeout (timers.js:237:5)
      at Timer.listOnTimeout (timers.js:207:5)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        6.641s
Ran all test suites related to changed files.
Andreas Köberle
  • 106,652
  • 57
  • 273
  • 297
3-MeO-PCE
  • 31
  • 1
  • 2

1 Answers1

3

The problem is that you cant predict how long it takes to get the result. What you can do is to create promises that resolve in the callback and return this promise from your test

    const htmlResponse = require('../__mocks__/html_response'); // just contains {listingsPage: '<html>....</html>';}
describe('scraper', () = > {
    it("should get David Nichols' latest study from valid HTML", (done) = > {
      const Xray = require('x-ray');
      const x = Xray();
      expect(x)
        .not.toEqual(null);
      var parseHtml = x('#Repo tbody tr', {
        link: 'td:nth-child(1) a@href'
      })
      return  new Promise((resolve) = > {
        var listingsHtml = htmlResponse.listingsPage;
        parseHtml(listingsHtml, (err, result) = > {
          resolve(result);
        });
      })
      .then((result = > {
        expect(result.link)
          .toEqual('le test'); // commenting this out causes test to pass.
      }))
    });
Andreas Köberle
  • 106,652
  • 57
  • 273
  • 297