0

I am trying to take a black box approach and use sagaTester to test my sagas.

This is the saga.js from react-boilerplate:

export function* getRepos() {
  // Select username from store
  const username = yield select(makeSelectUsername());
  const requestURL = `https://api.github.com/users/${username}/repos?type=all&sort=updated`;

  try {
    // Call our request helper (see 'utils/request')
    const repos = yield call(request, requestURL);
    yield put(reposLoaded(repos, username));
  } catch (err) {
    yield put(repoLoadingError(err));
  }
}

export default function* githubData() {
  // Watches for LOAD_REPOS actions and calls getRepos when one comes in.
  // By using `takeLatest` only the result of the latest API call is applied.
  // It returns task descriptor (just like fork) so we can continue execution
  // It will be cancelled automatically on component unmount
  yield takeLatest(LOAD_REPOS, getRepos);
}

This is my saga.test.js:

it('black box testing using sagaTester', async () => {
    const initialState = fromJS({
      home: {
        username: 'john',
      },
    });
    const sagaTester = new SagaTester({ initialState });
    sagaTester.start(githubData);

    sagaTester.dispatch(loadRepos());

    nock('https://api.github.com/repos?type=all&sort=updated')
      .get('/users/john')
      .reply(200, 'hello world');

    await sagaTester.waitFor(reposLoaded.type);
  });

This is the error that I've got:

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

All I am trying to do is to mock the response from this line:

const repos = yield call(request, requestURL);

What am I doing wrong????

Any help is appreciated!!!

johnwick0831
  • 918
  • 1
  • 12
  • 24

2 Answers2

0

The main 2 problems with yout code are:

  • missing CORS header
  • wrong waitFor call

Working example:

nock('https://api.github.com')
  .get('/users/john/repos')
  .query({ type: "all", sort: "updated" })
  .reply(200, [{ name: 'First repo', }, { name: 'Second repo', }], {'Access-Control-Allow-Origin': '*'});


await sagaTester.waitFor(reposLoaded().type);
Gm0t
  • 703
  • 7
  • 13
  • Thanks, but that didn't work. I was hoping that nock would be able to mock the call and response so that 'yield put(reposLoaded(repos, username));' reposLoaded action would be dispatched. But that never happened. If anyone picks up what's wrong please let me know!!! Still stuck.. – johnwick0831 Feb 10 '18 at 13:52
  • @calpang yeah, I missed 2 more errors... I've updated my answer. I hope it will help you! – Gm0t Feb 10 '18 at 15:12
0

I hope this will help others who stumble across this problem. The problem here was whatwg-fetch which is the baked in library in react-boiler-plate.

I looked at the example here and I noticed that node-fetch was being used.

So I replaced this line:

const repos = yield call(request, requestURL);

with:

const repos = yield call(() => fetch(requestURL));

and my test worked.

Another thing, if you want to use axios instead of whatwg, then you better use axios-mock-adapter to mock the request. Finally got this working after hours of fiddling. Thanks for your help!

johnwick0831
  • 918
  • 1
  • 12
  • 24