mirror of
https://github.com/sudoxnym/habitica.git
synced 2026-05-21 13:18:53 +00:00
Merge pull request #1 from crookedneighbor/vIiRuS-iOS-IAP
Viirus iOS iap - add tests
This commit is contained in:
commit
6467dd8fc0
2 changed files with 288 additions and 31 deletions
274
test/api/inAppPurchases.coffee
Normal file
274
test/api/inAppPurchases.coffee
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
'use strict'
|
||||
|
||||
app = require('../../website/src/server')
|
||||
rewire = require('rewire')
|
||||
sinon = require('sinon')
|
||||
inApp = rewire('../../website/src/controllers/payments/iap')
|
||||
iapMock = { }
|
||||
inApp.__set__('iap', iapMock)
|
||||
|
||||
describe 'In-App Purchases', ->
|
||||
describe 'Android', ->
|
||||
req = {
|
||||
body: {
|
||||
transaction: {
|
||||
reciept: 'foo'
|
||||
signature: 'sig'
|
||||
}
|
||||
}
|
||||
}
|
||||
res = {
|
||||
locals: { user: { _id: 'user' } }
|
||||
json: sinon.spy()
|
||||
}
|
||||
next = -> true
|
||||
paymentSpy = sinon.spy()
|
||||
|
||||
before ->
|
||||
inApp.__set__('payments.buyGems', paymentSpy)
|
||||
|
||||
afterEach ->
|
||||
paymentSpy.reset()
|
||||
res.json.reset()
|
||||
|
||||
context 'successful app purchase', ->
|
||||
before ->
|
||||
iapMock.setup = (cb)-> return cb(null)
|
||||
iapMock.validate = (iapGoogle, iapBodyReciept, cb)-> return cb(null, true)
|
||||
iapMock.isValidated = (googleRes)-> return googleRes
|
||||
iapMock.GOOGLE = 'google'
|
||||
|
||||
it 'calls res.json with succesful result object', ->
|
||||
expectedResObj = {
|
||||
ok: true
|
||||
data: true
|
||||
}
|
||||
|
||||
inApp.androidVerify(req, res, next)
|
||||
|
||||
expect(res.json).to.be.calledOnce
|
||||
expect(res.json).to.be.calledWith(expectedResObj)
|
||||
|
||||
it 'calls payments.buyGems function', ->
|
||||
inApp.androidVerify(req, res, next)
|
||||
|
||||
expect(paymentSpy).to.be.calledOnce
|
||||
expect(paymentSpy).to.be.calledWith({user: res.locals.user, paymentMethod:'IAP GooglePlay'})
|
||||
|
||||
context 'error in setup', ->
|
||||
before ->
|
||||
iapMock.setup = (cb)-> return cb("error in setup")
|
||||
|
||||
it 'calls res.json with setup error object', ->
|
||||
expectedResObj = {
|
||||
ok: false
|
||||
data: 'IAP Error'
|
||||
}
|
||||
|
||||
inApp.androidVerify(req, res, next)
|
||||
|
||||
expect(res.json).to.be.calledOnce
|
||||
expect(res.json).to.be.calledWith(expectedResObj)
|
||||
|
||||
it 'does not calls payments.buyGems function', ->
|
||||
inApp.androidVerify(req, res, next)
|
||||
|
||||
expect(paymentSpy).to.not.be.called
|
||||
|
||||
context 'error in validation', ->
|
||||
before ->
|
||||
iapMock.setup = (cb)-> return cb(null)
|
||||
iapMock.validate = (iapGoogle, iapBodyReciept, cb)-> return cb('error in validation', true)
|
||||
|
||||
it 'calls res.json with validation error object', ->
|
||||
expectedResObj = {
|
||||
ok: false
|
||||
data: {
|
||||
code: 6778001
|
||||
message: 'error in validation'
|
||||
}
|
||||
}
|
||||
|
||||
inApp.androidVerify(req, res, next)
|
||||
|
||||
expect(res.json).to.be.calledOnce
|
||||
expect(res.json).to.be.calledWith(expectedResObj)
|
||||
|
||||
it 'does not calls payments.buyGems function', ->
|
||||
inApp.androidVerify(req, res, next)
|
||||
|
||||
expect(paymentSpy).to.not.be.called
|
||||
|
||||
context 'iap is not valid', ->
|
||||
before ->
|
||||
iapMock.setup = (cb)-> return cb(null)
|
||||
iapMock.validate = (iapGoogle, iapBodyReciept, cb)-> return cb(null, false)
|
||||
iapMock.isValidated = (googleRes)-> return googleRes
|
||||
|
||||
it 'does not call res.json', ->
|
||||
inApp.androidVerify(req, res, next)
|
||||
|
||||
expect(res.json).to.not.be.called
|
||||
|
||||
it 'does not calls payments.buyGems function', ->
|
||||
inApp.androidVerify(req, res, next)
|
||||
|
||||
expect(paymentSpy).to.not.be.called
|
||||
|
||||
describe 'iOS', ->
|
||||
req = { body: { transaction: { reciept: 'foo' } } }
|
||||
res = {
|
||||
locals: { user: { _id: 'user' } }
|
||||
json: sinon.spy()
|
||||
}
|
||||
next = -> true
|
||||
paymentSpy = sinon.spy()
|
||||
|
||||
before ->
|
||||
inApp.__set__('payments.buyGems', paymentSpy)
|
||||
|
||||
afterEach ->
|
||||
paymentSpy.reset()
|
||||
res.json.reset()
|
||||
|
||||
context 'successful app purchase', ->
|
||||
before ->
|
||||
iapMock.setup = (cb)-> return cb(null)
|
||||
iapMock.validate = (iapApple, iapBodyReciept, cb)-> return cb(null, true)
|
||||
iapMock.isValidated = (appleRes)-> return appleRes
|
||||
iapMock.getPurchaseData = (appleRes)->
|
||||
return [{ productId: 'com.habitrpg.ios.Habitica.20gems' }]
|
||||
iapMock.APPLE = 'apple'
|
||||
|
||||
it 'calls res.json with succesful result object', ->
|
||||
expectedResObj = {
|
||||
ok: true
|
||||
data: true
|
||||
}
|
||||
|
||||
inApp.iosVerify(req, res, next)
|
||||
|
||||
expect(res.json).to.be.calledOnce
|
||||
expect(res.json).to.be.calledWith(expectedResObj)
|
||||
|
||||
it 'calls payments.buyGems function', ->
|
||||
inApp.iosVerify(req, res, next)
|
||||
|
||||
expect(paymentSpy).to.be.calledOnce
|
||||
expect(paymentSpy).to.be.calledWith({user: res.locals.user, paymentMethod:'IAP AppleStore'})
|
||||
|
||||
context 'error in setup', ->
|
||||
before ->
|
||||
iapMock.setup = (cb)-> return cb("error in setup")
|
||||
|
||||
it 'calls res.json with setup error object', ->
|
||||
expectedResObj = {
|
||||
ok: false
|
||||
data: 'IAP Error'
|
||||
}
|
||||
|
||||
inApp.iosVerify(req, res, next)
|
||||
|
||||
expect(res.json).to.be.calledOnce
|
||||
expect(res.json).to.be.calledWith(expectedResObj)
|
||||
|
||||
it 'does not calls payments.buyGems function', ->
|
||||
inApp.iosVerify(req, res, next)
|
||||
|
||||
expect(paymentSpy).to.not.be.called
|
||||
|
||||
context 'error in validation', ->
|
||||
before ->
|
||||
iapMock.setup = (cb)-> return cb(null)
|
||||
iapMock.validate = (iapApple, iapBodyReciept, cb)-> return cb('error in validation', true)
|
||||
|
||||
it 'calls res.json with validation error object', ->
|
||||
expectedResObj = {
|
||||
ok: false
|
||||
data: {
|
||||
code: 6778001
|
||||
message: 'error in validation'
|
||||
}
|
||||
}
|
||||
|
||||
inApp.iosVerify(req, res, next)
|
||||
|
||||
expect(res.json).to.be.calledOnce
|
||||
expect(res.json).to.be.calledWith(expectedResObj)
|
||||
|
||||
it 'does not calls payments.buyGems function', ->
|
||||
inApp.iosVerify(req, res, next)
|
||||
|
||||
expect(paymentSpy).to.not.be.called
|
||||
|
||||
context 'iap is not valid', ->
|
||||
before ->
|
||||
iapMock.setup = (cb)-> return cb(null)
|
||||
iapMock.validate = (iapApple, iapBodyReciept, cb)-> return cb(null, false)
|
||||
iapMock.isValidated = (appleRes)-> return appleRes
|
||||
|
||||
it 'does not call res.json', ->
|
||||
inApp.iosVerify(req, res, next)
|
||||
|
||||
expect(res.json).to.not.be.called
|
||||
|
||||
it 'does not calls payments.buyGems function', ->
|
||||
inApp.iosVerify(req, res, next)
|
||||
|
||||
expect(paymentSpy).to.not.be.called
|
||||
|
||||
context 'iap is valid but has no purchaseDataList', ->
|
||||
before ->
|
||||
iapMock.setup = (cb)-> return cb(null)
|
||||
iapMock.validate = (iapApple, iapBodyReciept, cb)-> return cb(null, true)
|
||||
iapMock.isValidated = (appleRes)-> return appleRes
|
||||
iapMock.getPurchaseData = (appleRes)->
|
||||
return []
|
||||
iapMock.APPLE = 'apple'
|
||||
|
||||
it 'calls res.json with succesful result object', ->
|
||||
expectedResObj = {
|
||||
ok: false
|
||||
data: {
|
||||
code: 6778001
|
||||
message: 'Incorrect receipt'
|
||||
}
|
||||
}
|
||||
|
||||
inApp.iosVerify(req, res, next)
|
||||
|
||||
expect(res.json).to.be.calledOnce
|
||||
expect(res.json).to.be.calledWith(expectedResObj)
|
||||
|
||||
it 'does not calls payments.buyGems function', ->
|
||||
inApp.iosVerify(req, res, next)
|
||||
|
||||
expect(paymentSpy).to.not.be.called
|
||||
|
||||
context 'iap is valid, has purchaseDataList, but productId does not match', ->
|
||||
before ->
|
||||
iapMock.setup = (cb)-> return cb(null)
|
||||
iapMock.validate = (iapApple, iapBodyReciept, cb)-> return cb(null, true)
|
||||
iapMock.isValidated = (appleRes)-> return appleRes
|
||||
iapMock.getPurchaseData = (appleRes)->
|
||||
return [{ productId: 'com.another.company' }]
|
||||
iapMock.APPLE = 'apple'
|
||||
|
||||
it 'calls res.json with incorrect reciept obj', ->
|
||||
expectedResObj = {
|
||||
ok: false
|
||||
data: {
|
||||
code: 6778001
|
||||
message: 'Incorrect receipt'
|
||||
}
|
||||
}
|
||||
|
||||
inApp.iosVerify(req, res, next)
|
||||
|
||||
expect(res.json).to.be.calledOnce
|
||||
expect(res.json).to.be.calledWith(expectedResObj)
|
||||
|
||||
it 'does not calls payments.buyGems function', ->
|
||||
inApp.iosVerify(req, res, next)
|
||||
|
||||
expect(paymentSpy).to.not.be.called
|
||||
|
|
@ -6,7 +6,7 @@ var nconf = require('nconf');
|
|||
var inAppPurchase = require('in-app-purchase');
|
||||
inAppPurchase.config({
|
||||
// this is the path to the directory containing iap-sanbox/iap-live files
|
||||
googlePublicKeyPath: nconf.get("IAP_GOOGLE_KEYDIR")
|
||||
googlePublicKeyPath: nconf.get("IAP_GOOGLE_KEYDIR")
|
||||
});
|
||||
|
||||
// Validation ERROR Codes
|
||||
|
|
@ -24,15 +24,11 @@ exports.androidVerify = function(req, res, next) {
|
|||
ok: false,
|
||||
data: 'IAP Error'
|
||||
};
|
||||
|
||||
console.error('IAP Setup ERROR');
|
||||
console.error(error);
|
||||
|
||||
res.json(resObj);
|
||||
|
||||
return;
|
||||
|
||||
return res.json(resObj);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
google receipt must be provided as an object
|
||||
{
|
||||
|
|
@ -44,7 +40,7 @@ exports.androidVerify = function(req, res, next) {
|
|||
data: iapBody.transaction.receipt,
|
||||
signature: iapBody.transaction.signature
|
||||
};
|
||||
|
||||
|
||||
// iap is ready
|
||||
iap.validate(iap.GOOGLE, testObj, function (err, googleRes) {
|
||||
if (err) {
|
||||
|
|
@ -56,9 +52,7 @@ exports.androidVerify = function(req, res, next) {
|
|||
}
|
||||
};
|
||||
|
||||
res.json(resObj);
|
||||
console.error(err);
|
||||
return;
|
||||
return res.json(resObj);
|
||||
}
|
||||
|
||||
if (iap.isValidated(googleRes)) {
|
||||
|
|
@ -69,16 +63,13 @@ exports.androidVerify = function(req, res, next) {
|
|||
|
||||
payments.buyGems({user:user, paymentMethod:'IAP GooglePlay'});
|
||||
|
||||
// yay good!
|
||||
res.json(resObj);
|
||||
return res.json(resObj);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.iosVerify = function(req, res, next) {
|
||||
console.info(req.body);
|
||||
|
||||
var iapBody = req.body;
|
||||
var user = res.locals.user;
|
||||
|
||||
|
|
@ -89,14 +80,10 @@ exports.iosVerify = function(req, res, next) {
|
|||
data: 'IAP Error'
|
||||
};
|
||||
|
||||
console.error('IAP Setup ERROR');
|
||||
console.error(error);
|
||||
return res.json(resObj);
|
||||
|
||||
res.json(resObj);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// iap is ready
|
||||
iap.validate(iap.APPLE, iapBody.transaction.receipt, function (err, appleRes) {
|
||||
if (err) {
|
||||
|
|
@ -108,9 +95,7 @@ exports.iosVerify = function(req, res, next) {
|
|||
}
|
||||
};
|
||||
|
||||
res.json(resObj);
|
||||
console.error(err);
|
||||
return;
|
||||
return res.json(resObj);
|
||||
}
|
||||
|
||||
if (iap.isValidated(appleRes)) {
|
||||
|
|
@ -123,8 +108,7 @@ exports.iosVerify = function(req, res, next) {
|
|||
data: appleRes
|
||||
};
|
||||
// yay good!
|
||||
res.json(resObj);
|
||||
return;
|
||||
return res.json(resObj);
|
||||
}
|
||||
}
|
||||
var resObj = {
|
||||
|
|
@ -135,9 +119,8 @@ exports.iosVerify = function(req, res, next) {
|
|||
}
|
||||
};
|
||||
|
||||
res.json(resObj);
|
||||
return;
|
||||
return res.json(resObj);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue