Jest to mock Stripe - node.js

I want to test my nodejs code using Jest.
In my code I use stripe.
When requiring stripe you have to use this line
const stripe=require('stripe')("apikey");
in order to be able to access the stripe methods.
Obviously that's the library I want to mock, but if I do
jest.mock('stripe');
I cannot mock the stripe methods I need as it's like doing a require without passing the key in the higher order function.
I could not find any correlation around.
Is there a way to achieve that?

I figure you'll need to build your entire Stripe SDK mock. This is what's working for me atm:
// Stripe SDK mock
jest.mock('stripe', () => {
return jest.fn().mockImplementation(() => {
return {
skus: {
retrieve: (sku, callback) => {
callback({}, {});
}
}
};
});
});
The above mock will return empty sku object when calling stripe.skus.retrieve(req.query.sku, function(err, sku) { ... })
Same should go for the rest. If you want this mock to return different kinds of data depending on input, you'll need to implement that logic in the mock.
Hope this helps,

Related

Can we access request header on Firebase Auth triggers i.e onCreate?

How can one access the IP and country in firebase auth onCreate trigger? Is there any other way to get this info?
For the front end, I'm using firebase-ui and for user register using the following method.
app.auth().createUserWithEmailAndPassword(email,password)
Cloud Functions code:
exports.processSignUp = functions.auth.user().onCreate(async user => {
return admin.auth().setCustomUserClaims(user.uid, {
clientIp: 'xxx.xxx.xx.xx', // required here headers['x-forwarded-for']
country: 'countryName' // required here headers['x-appengine-country']
})
.then(() => {
})
.catch(error => {
console.log(error);
});
});
The Cloud Function is triggered by the Google/Firebase infrastructure, and thus the headers are the values from that infrastructure. No information about the user/device that called createUserWithEmailAndPassword is available beyond what is passed in the user object.
If you need more information, consider implementing a callable function that you call directly from your code passing both the credentials (that you now pass to createUserWithEmailAndPassword) and the additional information you need, and then creating the user in the Cloud Functions code itself.

Unit testing firebase admin SDK authentication on node.JS

Is there any way I can write unit tests for firebase authentication to store locally? I want to do something like mongodb-memory-server, so all the data saved doesn't persists when the tests are over. I want to create some tests to those two functions specifically:
async function createResearcherOnFirebase(email, password) {
return admin.auth().createUser({
email,
password,
}).then((researcherRecord) => researcherRecord.uid).catch(() => false);
}
async function grantResearcherRole(uid) {
return admin.auth().setCustomUserClaims(uid, { researcher: true })
.then(() => true).catch(() => false);
}
While for some Firebase products there is now an emulator suite that you can run locally for precisely such use-cases, Firebase Authentication is currently not in there.
If you don't want to hit the real project, you will have to mock the service and inject it.

Return Stripe Response within Firebase Function to Swift Application

I’m trying to make an iOS that connects to Stripe and can show user information and data and things.
I’m doing this by using Firebase Functions, so I don’t have to maintain a server, and also because I’m a newb to the extreme.
But when I try to say, get a customer by using the Firebase callable functions, ex.
exports.getCustomer = functions.callableFunctions((data, context) => {
stripe.customers.retrieve(
data.customerID, function (err, customer) {
console.log(‘customer’)
});
});
I’m not sure where to place the “return” in order to actually use that ‘customer’ object in my app. I tried to stick a “return customer” under the console.log, but it’s never....... returning. I’ve also tried creating an empty string variable that I set after the console log and return, but that is always coming up as an empty string on the app.
Sorry for the typesetting issues, and this question is very theoretical - I’m typing on my phone because I don’t want to forget it and I’ll be away from my computer for a while.
Can anyone provide any guidance on how I’d return the ‘customer’ object to my iOS app?
As detailed here, since the release of the Stripe node.js API version 2, they added support for promises: "Every resource method now returns a Promises/A+ compliant promise in addition to supporting the conventional callback".
So you could do as follows:
exports.getCustomer = functions.callableFunctions((data, context) => {
const stripeCustomerID = data.customerID;
return stripe.customers.retrieve(stripeCustomerID)
.then(customer => {
return { customer: customer };
})
.catch(err => {
throw new functions.https.HttpsError('<status error code>', 'xxxxxxx');
});
});
As indicated in the doc, have a look here for the possible values of

How to generate API html documentation from mocha BDD tests?

I worked on a project with Spring Boot java framework where guys automated API docs generation. Every time you run BDD/Integration style tests, there was api blue print file created out from mocha tests. Then it ran generate-html-from-api blueprint. I liked this approach as it has two advantages:
1) API docs are always correct and up-to-date
2) saves time, because no need to write another documentation file (like apidoc).
Has anyone tried and has working example for node projects? I found api-doc-test plugin, however its documentation is limited. ? Ideally, I would like just to run:
mocha --recursive
Which would generate api-doc.html and place under test/tmp/.
I have looked at swagger but I really don't want to specify endpoint information twice and it would really be awesome just write once in BDD tests and have double result (tests + docs) at the same time.
https://github.com/stackia/test2doc.js
I'm working on this project, which enables generating documents (currently only API blueprint) from BDD tests, just exactly what you need.
Test code example:
const doc = require('test2doc')
const request = require('supertest') // We use supertest as the HTTP request library
require('should') // and use should as the assertion library
// For Koa, you should exports app.listen() or app.callback() in your app entry
const app = require('./my-express-app.js')
after(function () {
doc.emit('api-documentation.apib')
})
doc.group('Products').is(doc => {
describe('#Products', function () {
doc.action('Get all products').is(doc => {
it('should get all products', function () {
// Write specs towards your API endpoint as you would normally do
// Just decorate with some utility methods
return request(app)
.get(doc.get('/products'))
.query(doc.query({
minPrice: doc.val(10, 'Only products of which price >= this value should be returned')
}))
.expect(200)
.then(res => {
body = doc.resBody(res.body)
body.desc('List of all products')
.should.not.be.empty()
body[0].should.have.properties('id', 'name', 'price')
body[0].price.desc('Price of this product').should.be.a.Number
})
})
})
})
})

How to mock external service when testing a NodeJS API

I have JSON API built with koa which I am trying to cover with integration tests.
A simple test would look like this:
describe("GET: /users", function() {
it ("should respond", function (done) {
request(server)
.get('/api/users')
.expect(200, done);
});
});
Now the issue comes when the actions behind a controller - lets say saveUser at POST /users - use external resources. For instance I need to validate the users phone number.
My controller looks like this:
save: async function(ctx, next) {
const userFromRequest = await parse(ctx);
try {
// validate data
await ctx.repo.validate(userFromRequest);
// validate mobile code
await ctx.repo.validateSMSCode(
userFromRequest.mobile_number_verification_token,
userFromRequest.mobile_number.prefix + userFromRequest.mobile_number.number
);
const user = await ctx.repo.create(userFromRequest);
return ctx.data(201, { user });
} catch (e) {
return ctx.error(422, e.message, e.meta);
}
}
I was hoping to be able to mock the ctx.repo on the request object but I can't seem to able to get a hold on it from test, which means that my tests are actually hitting the phone number verification service.
Are there any ways I could go around hitting that verification service ?
Have you considered using a mockup library like https://github.com/mfncooper/mockery?
Typically, when writing tests requiring external services, I mock the service client library module. For example, using mocha:
mockery = require('mockery');
repo = require('your-repo-module');
before(function() {
mockery.enable();
repo.validateSMSCode = function() {...};
mockery.registerMock('your-repo-module', repo);
}
This way, every time you require your-repo-module, the mocked module will be loaded rather than the original one. Until you disable the mock, obviously...
app.context is the prototype from which ctx is created from. You may
add additional properties to ctx by editing app.context. This is
useful for adding properties or methods to ctx to be used across your
entire app, which may be more performant (no middleware) and/or easier
(fewer require()s) at the expense of relying more on ctx, which could
be considered an anti-pattern.
app.context.someProp = "Some Value";
app.use(async (ctx) => {
console.log(ctx.someProp);
});
For your sample your re-define app.context.repo.validateSMSCode like this, assuming that you have following setup lines in your test:
import app from '../app'
import supertest from 'supertest'
app.context.repo.validateSMSCode = async function(ctx, next) {
// Your logic here.
};
const request = supertest.agent(app.listen())
After re-defining app.context.repo.validateSMSCode method that your will define in your test, will work, instead of original method.
https://github.com/koajs/koa/blob/v2.x/docs/api/index.md#appcontext
https://github.com/koajs/koa/issues/652

Resources