Skip to content

Commit

Permalink
Merge pull request #4026 from LiskHQ/4017-vote-amount-decrease
Browse files Browse the repository at this point in the history
Fixed vote amount decrease bug - Closes #4017
  • Loading branch information
reyraa authored Dec 31, 2021
2 parents c25b227 + d7c7289 commit 44b29e8
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 13 deletions.
1 change: 1 addition & 0 deletions i18n/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@
"Vote": "Vote",
"Vote amount": "Vote amount",
"Vote amount (LSK)": "Vote amount (LSK)",
"Vote amount can't be zero or negative.": "Vote amount can't be zero or negative.",
"Vote for delegate": "Vote for delegate",
"Voted delegates": "Voted delegates",
"Voter": "Voter",
Expand Down
22 changes: 21 additions & 1 deletion src/components/screens/editVote/editVotes.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ describe('EditVote', () => {
expect(wrapper.find('.amount Feedback')).toHaveText('Provided amount will result in a wallet with less than the minimum balance.');
});

it('should display error when voting for self if called with amount greater than balance and locked votes for delegate', () => {
it('should display error when voting if called with amount greater than balance and locked votes for delegate', () => {
const wrapper = mountWithRouterAndStore(
EditVote, propsWithoutSearch, {}, { ...state, voting: withVotes },
);
Expand All @@ -152,6 +152,26 @@ describe('EditVote', () => {
expect(wrapper.find('.amount Feedback')).toHaveText('Provided amount is higher than your current balance.');
});

it('should display error when voting if called with amount that is zero or negative', () => {
const wrapper = mountWithRouterAndStore(
EditVote, propsWithoutSearch, {}, { ...state, voting: withVotes },
);
let amountField = wrapper.find('input[name="vote"]').at(0);
amountField.simulate('change', {
target: {
value: '-0',
name: 'vote',
},
});
wrapper.update();
act(() => { jest.advanceTimersByTime(300); });
wrapper.update();
amountField = wrapper.find('input[name="vote"]').at(0);

expect(amountField.find('.error')).toHaveClassName('error');
expect(wrapper.find('.amount Feedback')).toHaveText('Vote amount can\'t be zero or negative.');
});

it('should dispatch remove vote for host if called with address search param', () => {
const wrapper = mountWithRouterAndStore(
EditVote, propsWithSearch, {}, { ...state, voting: withVotes },
Expand Down
12 changes: 9 additions & 3 deletions src/components/screens/editVote/useVoteAmountField.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,20 @@ let loaderTimeout = null;
/**
* Returns error and feedback of vote amount field.
*
* @param {String} value - The vote amount value in Beddows
* @param {String} value - The vote amount value difference in Beddows
* @param {String} balance - The account balance value in Beddows
* @param {String} minValue - The minimum value checker in Beddows
* @param {String} inputValue - The input vote amount value in Beddows
* @returns {Object} The boolean error flag and a human readable message.
*/
const getAmountFeedbackAndError = (value, balance) => {
const getAmountFeedbackAndError = (value, balance, minValue, inputValue) => {
const { message: feedback } = validateAmountFormat({
value,
token: tokenMap.LSK.key,
funds: parseInt(balance, 10),
checklist: ['FORMAT', 'ZERO', 'VOTE_10X', 'INSUFFICIENT_FUNDS', 'MIN_BALANCE'],
checklist: ['FORMAT', 'NEGATIVE_VOTE', 'ZERO', 'VOTE_10X', 'INSUFFICIENT_FUNDS', 'MIN_BALANCE'],
minValue,
inputValue,
});

return { error: !!feedback, feedback };
Expand Down Expand Up @@ -80,6 +84,8 @@ const useVoteAmountField = (initialValue) => {
const feedback = getAmountFeedbackAndError(
value - fromRawLsk(previouslyConfirmedVotes - totalUnconfirmedVotes),
balance,
-1 * fromRawLsk(previouslyConfirmedVotes),
value,
);
loaderTimeout = setTimeout(() => {
setAmountField({
Expand Down
16 changes: 13 additions & 3 deletions src/utils/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ export const validateLSKPublicKey = (publicKey) => {
* @param {string?} [data.funds] Maximum funds users are allowed to input
* @param {Array?} [data.checklist] The list of errors to be tested. A choice of
* ZERO, MAX_ACCURACY, FORMAT, VOTE_10X, INSUFFICIENT_FUNDS
* @param {string} [data.initialVote] The amount of the user's previous votes
* @param {string} [data.minValue] The minimum value which is the previously confirmed votes
* @param {string} [data.inputValue] The user's input for votes
* @returns {Object.<string, string|boolean>}
* data - Object containing the message and if has an error
* data.message - Message of the error or empty string
Expand All @@ -79,16 +80,25 @@ export const validateAmountFormat = ({
locale = i18n.language,
funds,
checklist = ['ZERO', 'MAX_ACCURACY', 'FORMAT'],
minValue,
inputValue,
}) => {
const { format, maxFloating } = reg.amount[locale];
const errors = {
NEGATIVE_VOTE: {
message: i18n.t('Vote amount can\'t be zero or negative.'),
fn: () =>
numeral(value).value() < minValue
|| numeral(inputValue).value() < 0
|| Object.is(numeral(inputValue).value(), -0),
},
ZERO: {
message: i18n.t('Amount can\'t be zero.'),
fn: () => numeral(value).value() === 0,
fn: () => numeral(Math.abs(value)).value() === 0,
},
FORMAT: {
message: i18n.t('Provide a correct amount of {{token}}', { token }),
fn: () => format.test(value),
fn: () => (typeof value === 'string' && value.slice(-1) === '.') || format.test(Math.abs(value)),
},
MAX_ACCURACY: {
message: i18n.t('Maximum floating point is 8.'),
Expand Down
11 changes: 5 additions & 6 deletions src/utils/validators.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,15 @@ describe('Validate Amount Format', () => {
FLOATING_POINT: i18n.t('Maximum floating point is 8.'),
};
it('Should return errors.ZERO if amount is zero', () => {
[0.0, '0,', '0,0'].forEach((value) => {
expect(validateAmountFormat({ value })).toEqual({
error: true,
message: errors.ZERO,
});
const zeroValue = 0.0;
expect(validateAmountFormat({ value: zeroValue })).toEqual({
error: true,
message: errors.ZERO,
});
});

it('Should return errors.INVALID if format is invalid', () => {
['0.1.2', '1..', '1a,1', '2.d2'].forEach((value) => {
['0,', '0,0', '0.1.2', '1..', '1a,1', '2.d2'].forEach((value) => {
expect(validateAmountFormat({ value })).toEqual({
error: true,
message: errors.INVALID,
Expand Down

0 comments on commit 44b29e8

Please sign in to comment.