XMLHttpRequest is not defined when testing react-native app with jest - react-native

i am trying to test a apiwrapper in a react-native based app using jest (integration testing).
When i run it in the iOs simulator everything runs fine however it wont run my jest tests correctly - i always get:
ReferenceError: XMLHttpRequest is not defined
when i try to run tests using my api wrapper, eg.:
it('Login successful with correct data', () => {
let api = Api.getInstance();
return api.login("test", "testpass")
.then(result => expect(result).toEqual('login_successful'));
});
the api class i am trying to test here does use the fetch api (not vanilla xhr). I assume its something related to jest trying to mock something but have not found a way to make it work yet.
Thanks in advance.

In my case, I'm not testing the search code but only importing it somewhere in my code path, so I decided to just mock it at the global level in a setup.js file (loaded using --require at test run). The following works for me:
// needed in react-instantsearch
class XMLHttpRequest {}
global.XMLHttpRequest = XMLHttpRequest;

I had a similar problem with lokka using XMLHttpRequest. I made a mock for lokka, which my api wrapper class depends on. You could try mocking your api wrapper.
This is what my lokka mock looks like for now. I'll add more to it when I start testing error handling.
export default class {
query() {
return new Promise(resolve => {
resolve(200);
});
}
}
You might be able to mock your api wrapper with something similar:
export default class Api {
getInstance() {
\\ However you implemented getInstance
}
login(user, password) {
return new Promise(resolve => {
resolve('login_successful');
});
}
}

Related

How to test global middlware in expressJS?

This seems like a simple question, but I'm stumped. How do I test my expressjs middleware is setting up the user session properly?
app.use((req:Req, res:Response, next:NextFunction) => {
req.userSessionId = uuid();
next();
});
I am not sure how to test that an incoming request is being captured and setting the userSessionId correctly. I want something like
describe('setting up middleware', ()=> {
//instantiate the app
expect(app.use).tobeCalled();
expect(mockReq).toBeSetWith(userSessionId)
});
You can refactor your middleware code into a function, and write unit-tests that test this function logic.
Your unit tests, in my opinion (and others), should only test your code and avoid testing Express logic (calling your middleware). For this you should have integration tests which test your app is working properly as a whole
// This middleware code needs to be tested
const userSessionMiddleare = (req: Request, res:Response, next: NextFunction) => {
req.userSessionId = uuid();
next();
};
// This Express logic should not be unit-tested but rather tested in your integration testing
app.use(userSessionMiddleare);

Expo secure-store unavailable in jest tests

This question is specifically about expo-secure-store and jest.
Currently, I am using expo-secure-store to store my JWT when logging in. It works fine when running on emulator however, it doesn't work at all in Jest tests; token comes back as undefined. I am able to call the functions like normal.
Excuse any typos I might have made refactoring this.
Calling from tests:
test('when logging in, given correct credentials, gets response token.', async () => {
try {
var token = await SecureStore.getItemAsync("token");
await SecureStore.setItemAsync('token', 'test');
token = await SecureStore.getItemAsync('token');
console.log(token);
expect(token).toBeDefined();
expect(token).toBe("test");
} catch (err) {
console.log(err);
throw err;
}
}
Question: Does expo-secure-store not load/work without an actual device/emulator?
There are no documentation at all about testing with secure-store and from what I can tell I might have to mock this module.
you have to mock any native module that you use because their implementations live primarily in native code that is intended to be run on ios and android devices. so the same applies here - you should mock expo-secure-store.

More than one test fails due to import after jest is torn down - Supertest Typescript and Express API

I am running into an issue where I am running multiple tests using supertest and jest. When there is only one test running then it works just fine but the second one throws the following error:
ReferenceError: You are trying to `import` a file after the Jest environment has been torn down.
I tested this with two very simple tests:
describe("Default API", () => {
describe("Default:", () => {
it("should create a user in the DB", (done) => {
request(app).get("/").expect(200, done);
});
it("should create a user in the DB", (done) => {
request(app).get("/").expect(200, done);
});
});
});
They are the same but the second one throws the error. If I run only the first one there is no issue. This must be a setup issue Does anyone have advice. In my index.ts where I have the main express code I export app as follows:
export default app;
This is at the bottom of the index.ts file.
I had the simular problem and toggle down the issue, in my case I want to use mysql2 to access mariadb. That Module try to autodetect the charset and do to try to lacy loading that encoding.
But I have not found a solution for that for now.

Compatibility between cypress and react-apollo

I am using react-apollo to make GraphQL queries, and I am using Cypress for testing.
The problem is that these 2 dont seem to play well along. Apollo seems to be making all its requests through the Fetch API.
But Cypress seems like it is not able to capture anything, except XHR requests.
So what could I do to solve this problem? Is there a way for Cypress to capture "fetch" requests? Is there a way for react-apollo to use "xhr" instead of "fetch"?
Try out cypress-graphql-mock
You just pass it your schema:
const schema = fs.readFileSync('../../app-schema.graphql', 'utf8');
// alternatively, using a dumped introspection query:
// const schema = require('../../dumped-schema.json')
beforeEach(() => {
cy.server();
cy.mockGraphql({ schema });
});
An easy workaround is to use whatwg-fetch, which you'd add as a dependency via npm and then...
cypress/support/fetch_to_xhr.js
function fetchToXhr() {
let polyfill
before(() => {
cy.readFile('node_modules/whatwg-fetch/dist/fetch.umd.js')
.then((contents) => polyfill = contents)
Cypress.on('window:before:load', (win) => {
delete win.fetch
win.eval(polyfill)
})
})
}
fetchToXhr()
cypress/support/index.js
import "./fetch_to_xhr";
After that cypress will capture the graphql requests
Cypress now officially supports working with GQL: Working with GraphQL.
I recommend reading their documentation in detail, but at your own risk here is a VERY crude TLDR:
cy.intercept('your-url-here/graphql', (req) => {
const { body } = req;
if (body.hasOwnProperty('your-operationName-here')) {
// do something with the request, like:
req.reply('your-mock-here');
}
});

Meteorjs test Meteor methods

I have the following simple Meteor Method that I want to test.
It inserts a given Object into my collection
Meteor.methods({
insertHelper(profile){
HelperCollection.insert(profile);
return true;
},
}
For Testing i use "dispatch:mocha-phantomjs"
My Test so far is the following:
describe('methods', () => {
it('can delete owned task', () => {
Meteor.call('insertHelper',{a: 1});
});
});
When running my tests I get the message " Error: Method 'insertHelper' not found [404]"
So how can I access my Meteor methods from my Test suite?
As discussed in the comments, we have to include the files where the Meteor methods are defined in order to test them :
import '/path/to/method/file.js';
or with require :
require('/path/to/methos/file.js');
EDIT
Meteor advises to use import instead of using require, if you can.