0
votes

I have a common api class that i use for handling api calls in React Native. It will make the call and get the json/ error and return it. See the code below.

// General api to acces data from web
import ApiConstants from './ApiConstants';
export default function api(path,params,method, sssid){

    let options;
        options = Object.assign({headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        }},{ method: method }, params ? { body: JSON.stringify(params) } : null );


    return fetch(ApiConstants.BASE_URL+path, options).then( resp => {
        let json = resp.json();
        if (resp.ok) {
            return json;
        }
        return json.then(err => {
            throw err;
        }).then( json => json );
    });
}

But when i write the jest test to mock the api as folllows in tests folder.

test('Should login',() => {
    global.fetch = jest.fn(() => new Promise((resolve) => {
        resolve( { status: 201, json: () => (mock_data_login) });
    }));

    return Api(ApiConstants.LOGIN,{'un':'test1','pwd':'1234'},'post', null).then((data1)=>{

        expect(data1).toBeDefined();
        expect(data1.success).toEqual(true);
        expect(data1.message).toEqual('Login Success');
    });

});

it fails with:

TypeError: json.then is not a function

When I change the fetch return to this, the test passes:

 return fetch(ApiConstants.BASE_URL+path, options).then( resp => {
            let json = resp.json();
            return json
        });
    }

Why is this type error error popping up? I can't change the API module, because that will my redux saga code to change. What should I do?

3

3 Answers

1
votes

In your code, json is just an Object and not a Promise, so then is undefined. That's the complain you are getting because you are trying to use undefined as a function. The problem is not in the test but in your code that ha san error. Try the following instead.

return fetch(ApiConstants.BASE_URL+path, options)
        .then(resp => resp.json())
        .then( json => json)
        .catch((error) => error);
    });
1
votes

Edit: oh, just read you can't make changes to the component where the error occurs?

Try converting your fetch like this:

return fetch(ApiConstants.BASE_URL+path, options)
.then(resp => {
  let json = resp.json();
  if (resp.ok) {
    return json;
  } else {
    throw Error(resp.error) // assuming you have some kind of error from endpoint?
  }
})
.then(/*handle your ok response*/)
.catch(/*handle your error response*/);
1
votes

I faced the same issue, The problem is that you are mocking only response.json as function but it should be a Promise, Like this,

 global.fetch = jest.fn(() => new Promise((resolve) => {
    resolve( { status: 201, json: () => {
         return Promise.resolve(mock_data_login);
       } 
    });
}));

This will return a Promise for you json function.

Hope this fix your problem.