diff --git a/test/common/ops/sell.js b/test/common/ops/sell.js index 11c9676c03..9631fb9650 100644 --- a/test/common/ops/sell.js +++ b/test/common/ops/sell.js @@ -75,6 +75,16 @@ describe('shared.ops.sell', () => { } }); + it('returns an error when the requested amount is negative', (done) => { + try { + sell(user, {params: { type, key }, query: {amount: -42} }); + } catch (err) { + expect(err).to.be.an.instanceof(BadRequest); + expect(err.message).to.equal(i18n.t('positiveAmountRequired', {type})); + done(); + } + }); + it('reduces item count from user', () => { sell(user, {params: { type, key } }); diff --git a/website/client/components/shops/market/sellModal.vue b/website/client/components/shops/market/sellModal.vue index cfeaef7b48..b22bd3fb74 100644 --- a/website/client/components/shops/market/sellModal.vue +++ b/website/client/components/shops/market/sellModal.vue @@ -26,7 +26,7 @@ b.how-many-to-sell {{ $t('howManyToSell') }} div - b-input.itemsToSell(type="number", v-model="selectedAmountToSell", :max="itemCount", min="1") + b-input.itemsToSell(type="number", v-model="selectedAmountToSell", :max="itemCount", min="1", @keyup.native="preventNegative($event)") span.svg-icon.inline.icon-32(aria-hidden="true", v-html="icons.gold") span.value {{ item.value }} @@ -141,6 +141,13 @@ this.selectedAmountToSell = 1; }, + preventNegative ($event) { + let value = $event.target.value; + + if (isNaN($event.target.valueAsNumber) || Number(value) < 0) { + this.selectedAmountToSell = 0; + } + }, sellItems () { this.$store.dispatch('shops:sellItems', { type: this.itemType, diff --git a/website/common/locales/en/npc.json b/website/common/locales/en/npc.json index 4b49e2ab65..033513630b 100644 --- a/website/common/locales/en/npc.json +++ b/website/common/locales/en/npc.json @@ -92,6 +92,7 @@ "invalidTypeEquip": "\"type\" must be one of 'equipped', 'pet', 'mount', 'costume'.", "mustPurchaseToSet": "Must purchase <%= val %> to set it on <%= key %>.", "typeRequired": "Type is required", + "positiveAmountRequired": "Positive amount is required", "keyRequired": "Key is required", "notAccteptedType": "Type must be in [eggs, hatchingPotions, premiumHatchingPotions, food, quests, gear]", "contentKeyNotFound": "Key not found for Content <%= type %>", diff --git a/website/common/script/ops/sell.js b/website/common/script/ops/sell.js index 226bb3f114..a36f2c5fb6 100644 --- a/website/common/script/ops/sell.js +++ b/website/common/script/ops/sell.js @@ -17,6 +17,10 @@ module.exports = function sell (user, req = {}) { let type = get(req.params, 'type'); let amount = get(req.query, 'amount', 1); + if (amount < 0) { + throw new BadRequest(i18n.t('positiveAmountRequired', req.language)); + } + if (!type) { throw new BadRequest(i18n.t('typeRequired', req.language)); }