Purchase API Refactoring: Mounts [Hourglass] (#10482)

* AbstractGemItemOperation - BuyQuestWithGemOperation

* fix purchase
This commit is contained in:
negue
2019-09-20 16:52:15 +02:00
committed by Matteo Pagliazzi
parent 4690431384
commit 3aa2e30815
4 changed files with 102 additions and 5 deletions

View File

@@ -9,11 +9,18 @@ import {
generateUser,
} from '../../../helpers/common.helper';
import errorMessage from '../../../../website/common/script/libs/errorMessage';
import {BuyHourglassMountOperation} from '../../../../website/common/script/ops/buy/buyMount';
describe('common.ops.hourglassPurchase', () => {
let user;
let analytics = {track () {}};
function buyMount (_user, _req, _analytics) {
const buyOp = new BuyHourglassMountOperation(_user, _req, _analytics);
return buyOp.purchase();
}
beforeEach(() => {
user = generateUser();
sinon.stub(analytics, 'track');
@@ -66,7 +73,7 @@ describe('common.ops.hourglassPurchase', () => {
it('does not grant to mounts without Mystic Hourglasses', (done) => {
try {
hourglassPurchase(user, {params: {type: 'mounts', key: 'MantisShrimp-Base'}});
buyMount(user, {params: {key: 'MantisShrimp-Base'}});
} catch (err) {
expect(err).to.be.an.instanceof(NotAuthorized);
expect(err.message).to.eql(i18n.t('notEnoughHourglasses'));
@@ -90,7 +97,7 @@ describe('common.ops.hourglassPurchase', () => {
user.purchased.plan.consecutive.trinkets = 1;
try {
hourglassPurchase(user, {params: {type: 'mounts', key: 'Orca-Base'}});
buyMount(user, {params: {key: 'Orca-Base'}});
} catch (err) {
expect(err).to.be.an.instanceof(NotAuthorized);
expect(err.message).to.eql(i18n.t('notAllowedHourglass'));
@@ -120,7 +127,7 @@ describe('common.ops.hourglassPurchase', () => {
};
try {
hourglassPurchase(user, {params: {type: 'mounts', key: 'MantisShrimp-Base'}});
buyMount(user, {params: {key: 'MantisShrimp-Base'}});
} catch (err) {
expect(err).to.be.an.instanceof(NotAuthorized);
expect(err.message).to.eql(i18n.t('mountsAlreadyOwned'));
@@ -144,7 +151,7 @@ describe('common.ops.hourglassPurchase', () => {
it('buys a mount', () => {
user.purchased.plan.consecutive.trinkets = 2;
let [, message] = hourglassPurchase(user, {params: {type: 'mounts', key: 'MantisShrimp-Base'}});
let [, message] = buyMount(user, {params: {key: 'MantisShrimp-Base'}});
expect(message).to.eql(i18n.t('hourglassPurchase'));
expect(user.purchased.plan.consecutive.trinkets).to.eql(1);
expect(user.items.mounts).to.eql({'MantisShrimp-Base': true});

View File

@@ -194,3 +194,28 @@ export class AbstractGemItemOperation extends AbstractBuyOperation {
};
}
}
export class AbstractHourglassItemOperation extends AbstractBuyOperation {
constructor (user, req, analytics) {
super(user, req, analytics);
}
canUserPurchase (user, item) {
this.item = item;
if (user.purchased.plan.consecutive.trinkets <= 0) {
throw new NotAuthorized(this.i18n('notEnoughHourglasses'));
}
}
subtractCurrency (user) {
user.purchased.plan.consecutive.trinkets--;
}
analyticsData () {
return {
itemKey: this.item.key,
acquireMethod: 'Hourglass',
};
}
}

View File

@@ -13,6 +13,7 @@ import hourglassPurchase from './hourglassPurchase';
import errorMessage from '../../libs/errorMessage';
import {BuyGemOperation} from './buyGem';
import {BuyQuestWithGemOperation} from './buyQuestGem';
import {BuyHourglassMountOperation} from './buyMount';
// @TODO: remove the req option style. Dependency on express structure is an anti-pattern
// We should either have more params or a set structure validated by a Type checker
@@ -72,8 +73,13 @@ module.exports = function buy (user, req = {}, analytics, options = {quantity: 1
case 'bundles':
buyRes = purchaseOp(user, req, analytics);
break;
case 'mounts': {
const buyOp = new BuyHourglassMountOperation(user, req, analytics);
buyRes = buyOp.purchase();
break;
}
case 'pets':
case 'mounts':
buyRes = hourglassPurchase(user, req, analytics);
break;
case 'quest': {

View File

@@ -0,0 +1,59 @@
import content from '../../content/index';
import {
BadRequest,
NotAuthorized,
} from '../../libs/errors';
import {AbstractHourglassItemOperation} from './abstractBuyOperation';
import get from 'lodash/get';
import includes from 'lodash/includes';
import keys from 'lodash/keys';
export class BuyHourglassMountOperation extends AbstractHourglassItemOperation {
constructor (user, req, analytics) {
super(user, req, analytics);
}
multiplePurchaseAllowed () {
return false;
}
extractAndValidateParams (user, req) {
let key = this.key = get(req, 'params.key');
if (!key) throw new BadRequest(this.i18n('missingKeyParam'));
if (!includes(keys(content.timeTravelStable.mounts), key)) {
throw new NotAuthorized(this.i18n('notAllowedHourglass'));
}
if (user.items.mounts[key]) {
throw new NotAuthorized(this.i18n('mountsAlreadyOwned'));
}
this.canUserPurchase(user, {
key,
});
}
executeChanges (user) {
user.items.mounts[this.key] = true;
if (user.markModified) user.markModified('items.mounts');
this.subtractCurrency(user);
let message = this.i18n('hourglassPurchase');
return [
{ items: user.items, purchasedPlanConsecutive: user.purchased.plan.consecutive },
message,
];
}
analyticsData () {
let data = super.analyticsData();
data.itemType = 'mounts';
return data;
}
}