var app, iapMock, inApp, rewire, sinon;

app = require('../../website/server/server');

rewire = require('rewire');

sinon = require('sinon');

inApp = rewire('../../website/server/controllers/payments/iap');

iapMock = {};

inApp.__set__('iap', iapMock);

describe('In-App Purchases', function() {
  describe('Android', function() {
    var next, paymentSpy, req, res;
    req = {
      body: {
        transaction: {
          reciept: 'foo',
          signature: 'sig'
        }
      }
    };
    res = {
      locals: {
        user: {
          _id: 'user'
        }
      },
      json: sinon.spy()
    };
    next = function() {
      return true;
    };
    paymentSpy = sinon.spy();
    before(function() {
      return inApp.__set__('payments.buyGems', paymentSpy);
    });
    afterEach(function() {
      paymentSpy.reset();
      return res.json.reset();
    });
    context('successful app purchase', function() {
      before(function() {
        iapMock.setup = function(cb) {
          return cb(null);
        };
        iapMock.validate = function(iapGoogle, iapBodyReciept, cb) {
          return cb(null, true);
        };
        iapMock.isValidated = function(googleRes) {
          return googleRes;
        };
        return iapMock.GOOGLE = 'google';
      });
      it('calls res.json with succesful result object', function() {
        var expectedResObj;
        expectedResObj = {
          ok: true,
          data: true
        };
        inApp.androidVerify(req, res, next);
        expect(res.json).to.be.calledOnce;
        return expect(res.json).to.be.calledWith(expectedResObj);
      });
      return it('calls payments.buyGems function', function() {
        inApp.androidVerify(req, res, next);
        expect(paymentSpy).to.be.calledOnce;
        return expect(paymentSpy).to.be.calledWith({
          user: res.locals.user,
          paymentMethod: 'IAP GooglePlay',
          amount: 5.25
        });
      });
    });
    context('error in setup', function() {
      before(function() {
        return iapMock.setup = function(cb) {
          return cb("error in setup");
        };
      });
      it('calls res.json with setup error object', function() {
        var expectedResObj;
        expectedResObj = {
          ok: false,
          data: 'IAP Error'
        };
        inApp.androidVerify(req, res, next);
        expect(res.json).to.be.calledOnce;
        return expect(res.json).to.be.calledWith(expectedResObj);
      });
      return it('does not calls payments.buyGems function', function() {
        inApp.androidVerify(req, res, next);
        return expect(paymentSpy).to.not.be.called;
      });
    });
    context('error in validation', function() {
      before(function() {
        iapMock.setup = function(cb) {
          return cb(null);
        };
        return iapMock.validate = function(iapGoogle, iapBodyReciept, cb) {
          return cb('error in validation', true);
        };
      });
      it('calls res.json with validation error object', function() {
        var expectedResObj;
        expectedResObj = {
          ok: false,
          data: {
            code: 6778001,
            message: 'error in validation'
          }
        };
        inApp.androidVerify(req, res, next);
        expect(res.json).to.be.calledOnce;
        return expect(res.json).to.be.calledWith(expectedResObj);
      });
      return it('does not calls payments.buyGems function', function() {
        inApp.androidVerify(req, res, next);
        return expect(paymentSpy).to.not.be.called;
      });
    });
    return context('iap is not valid', function() {
      before(function() {
        iapMock.setup = function(cb) {
          return cb(null);
        };
        iapMock.validate = function(iapGoogle, iapBodyReciept, cb) {
          return cb(null, false);
        };
        return iapMock.isValidated = function(googleRes) {
          return googleRes;
        };
      });
      it('does not call res.json', function() {
        inApp.androidVerify(req, res, next);
        return expect(res.json).to.not.be.called;
      });
      return it('does not calls payments.buyGems function', function() {
        inApp.androidVerify(req, res, next);
        return expect(paymentSpy).to.not.be.called;
      });
    });
  });
  return describe('iOS', function() {
    var next, paymentSpy, req, res;
    req = {
      body: {
        transaction: {
          reciept: 'foo'
        }
      }
    };
    res = {
      locals: {
        user: {
          _id: 'user'
        }
      },
      json: sinon.spy()
    };
    next = function() {
      return true;
    };
    paymentSpy = sinon.spy();
    before(function() {
      return inApp.__set__('payments.buyGems', paymentSpy);
    });
    afterEach(function() {
      paymentSpy.reset();
      return res.json.reset();
    });
    context('successful app purchase', function() {
      before(function() {
        iapMock.setup = function(cb) {
          return cb(null);
        };
        iapMock.validate = function(iapApple, iapBodyReciept, cb) {
          return cb(null, true);
        };
        iapMock.isValidated = function(appleRes) {
          return appleRes;
        };
        iapMock.getPurchaseData = function(appleRes) {
          return [
            {
              productId: 'com.habitrpg.ios.Habitica.20gems'
            }
          ];
        };
        return iapMock.APPLE = 'apple';
      });
      it('calls res.json with succesful result object', function() {
        var expectedResObj;
        expectedResObj = {
          ok: true,
          data: true
        };
        inApp.iosVerify(req, res, next);
        expect(res.json).to.be.calledOnce;
        return expect(res.json).to.be.calledWith(expectedResObj);
      });
      return it('calls payments.buyGems function', function() {
        inApp.iosVerify(req, res, next);
        expect(paymentSpy).to.be.calledOnce;
        return expect(paymentSpy).to.be.calledWith({
          user: res.locals.user,
          paymentMethod: 'IAP AppleStore',
          amount: 5.25
        });
      });
    });
    context('error in setup', function() {
      before(function() {
        return iapMock.setup = function(cb) {
          return cb("error in setup");
        };
      });
      it('calls res.json with setup error object', function() {
        var expectedResObj;
        expectedResObj = {
          ok: false,
          data: 'IAP Error'
        };
        inApp.iosVerify(req, res, next);
        expect(res.json).to.be.calledOnce;
        return expect(res.json).to.be.calledWith(expectedResObj);
      });
      return it('does not calls payments.buyGems function', function() {
        inApp.iosVerify(req, res, next);
        return expect(paymentSpy).to.not.be.called;
      });
    });
    context('error in validation', function() {
      before(function() {
        iapMock.setup = function(cb) {
          return cb(null);
        };
        return iapMock.validate = function(iapApple, iapBodyReciept, cb) {
          return cb('error in validation', true);
        };
      });
      it('calls res.json with validation error object', function() {
        var expectedResObj;
        expectedResObj = {
          ok: false,
          data: {
            code: 6778001,
            message: 'error in validation'
          }
        };
        inApp.iosVerify(req, res, next);
        expect(res.json).to.be.calledOnce;
        return expect(res.json).to.be.calledWith(expectedResObj);
      });
      return it('does not calls payments.buyGems function', function() {
        inApp.iosVerify(req, res, next);
        return expect(paymentSpy).to.not.be.called;
      });
    });
    context('iap is not valid', function() {
      before(function() {
        iapMock.setup = function(cb) {
          return cb(null);
        };
        iapMock.validate = function(iapApple, iapBodyReciept, cb) {
          return cb(null, false);
        };
        return iapMock.isValidated = function(appleRes) {
          return appleRes;
        };
      });
      it('does not call res.json', function() {
        var expectedResObj;
        inApp.iosVerify(req, res, next);
        expectedResObj = {
          ok: false,
          data: {
            code: 6778001,
            message: 'Invalid receipt'
          }
        };
        expect(res.json).to.be.calledOnce;
        return expect(res.json).to.be.calledWith(expectedResObj);
      });
      return it('does not calls payments.buyGems function', function() {
        inApp.iosVerify(req, res, next);
        return expect(paymentSpy).to.not.be.called;
      });
    });
    context('iap is valid but has no purchaseDataList', function() {
      before(function() {
        iapMock.setup = function(cb) {
          return cb(null);
        };
        iapMock.validate = function(iapApple, iapBodyReciept, cb) {
          return cb(null, true);
        };
        iapMock.isValidated = function(appleRes) {
          return appleRes;
        };
        iapMock.getPurchaseData = function(appleRes) {
          return [];
        };
        return iapMock.APPLE = 'apple';
      });
      it('calls res.json with succesful result object', function() {
        var expectedResObj;
        expectedResObj = {
          ok: false,
          data: {
            code: 6778001,
            message: 'Incorrect receipt content'
          }
        };
        inApp.iosVerify(req, res, next);
        expect(res.json).to.be.calledOnce;
        return expect(res.json).to.be.calledWith(expectedResObj);
      });
      return it('does not calls payments.buyGems function', function() {
        inApp.iosVerify(req, res, next);
        return expect(paymentSpy).to.not.be.called;
      });
    });
    return context('iap is valid, has purchaseDataList, but productId does not match', function() {
      before(function() {
        iapMock.setup = function(cb) {
          return cb(null);
        };
        iapMock.validate = function(iapApple, iapBodyReciept, cb) {
          return cb(null, true);
        };
        iapMock.isValidated = function(appleRes) {
          return appleRes;
        };
        iapMock.getPurchaseData = function(appleRes) {
          return [
            {
              productId: 'com.another.company'
            }
          ];
        };
        return iapMock.APPLE = 'apple';
      });
      it('calls res.json with incorrect reciept obj', function() {
        var expectedResObj;
        expectedResObj = {
          ok: false,
          data: {
            code: 6778001,
            message: 'Incorrect receipt content'
          }
        };
        inApp.iosVerify(req, res, next);
        expect(res.json).to.be.calledOnce;
        return expect(res.json).to.be.calledWith(expectedResObj);
      });
      return it('does not calls payments.buyGems function', function() {
        inApp.iosVerify(req, res, next);
        return expect(paymentSpy).to.not.be.called;
      });
    });
  });
});
