diff --git a/src/repositories/powerBoostingRepository.test.ts b/src/repositories/powerBoostingRepository.test.ts index 0689a4c73..04c80b5a6 100644 --- a/src/repositories/powerBoostingRepository.test.ts +++ b/src/repositories/powerBoostingRepository.test.ts @@ -1,16 +1,19 @@ import { + assertThrowsAsync, createProjectData, generateRandomEtheriumAddress, saveProjectDirectlyToDb, saveUserDirectlyToDb, } from '../../test/testUtils'; import { + cancelProjectBoosting, findPowerBoostings, findUserPowerBoosting, findUsersWhoBoostedProject, getPowerBoostingSnapshotRound, insertSinglePowerBoosting, setMultipleBoosting, + setSingleBoosting, takePowerBoostingSnapshot, } from './powerBoostingRepository'; import { assert, use } from 'chai'; @@ -20,10 +23,12 @@ import { PowerBoostingSnapshot } from '../entities/powerBoostingSnapshot'; import { getConnection } from 'typeorm'; import { Reaction } from '../entities/reaction'; import { findUsersWhoLikedProject } from './reactionRepository'; +import { errorMessages } from '../utils/errorMessages'; describe('findUserPowerBoosting() testCases', findUserPowerBoostingTestCases); describe('findPowerBoostings() testCases', findPowerBoostingsTestCases); describe('setMultipleBoosting() testCases', setMultipleBoostingTestCases); +describe('setSingleBoosting() testCases', setSingleBoostingTestCases); describe('power boosting snapshot testCases', powerBoostingSnapshotTests); describe( 'findUsersWhoBoostedProject() testCases', @@ -726,6 +731,134 @@ function setMultipleBoostingTestCases() { }); } +function setSingleBoostingTestCases() { + it('should set single boosting with 100%, when boosted multi project', async () => { + const user = await saveUserDirectlyToDb(generateRandomEtheriumAddress()); + const firstProject = await saveProjectDirectlyToDb(createProjectData()); + const secondProject = await saveProjectDirectlyToDb(createProjectData()); + const thirdProject = await saveProjectDirectlyToDb(createProjectData()); + await setMultipleBoosting({ + userId: user.id, + projectIds: [firstProject.id, secondProject.id, thirdProject.id], + percentages: [40, 20, 40], + }); + await setSingleBoosting({ + userId: user.id, + projectId: firstProject.id, + percentage: 100, + }); + const [userPowerBoostings] = await findPowerBoostings({ + userId: user.id, + orderBy: { + field: 'updatedAt', + direction: 'ASC', + }, + }); + assert.equal(userPowerBoostings.length, 1); + assert.equal(userPowerBoostings[0].percentage, 100); + assert.equal(userPowerBoostings[0].projectId, firstProject.id); + }); + it('should set single boosting with 100%', async () => { + const user = await saveUserDirectlyToDb(generateRandomEtheriumAddress()); + const firstProject = await saveProjectDirectlyToDb(createProjectData()); + + await setSingleBoosting({ + userId: user.id, + projectId: firstProject.id, + percentage: 100, + }); + + const [userPowerBoostings] = await findPowerBoostings({ + userId: user.id, + orderBy: { + field: 'updatedAt', + direction: 'ASC', + }, + }); + + assert.equal(userPowerBoostings.length, 1); + assert.equal(userPowerBoostings[0].percentage, 100); + assert.equal(userPowerBoostings[0].projectId, firstProject.id); + }); + + it('should set single boosting with 0%, when boosted multi project', async () => { + const user = await saveUserDirectlyToDb(generateRandomEtheriumAddress()); + const firstProject = await saveProjectDirectlyToDb(createProjectData()); + const secondProject = await saveProjectDirectlyToDb(createProjectData()); + const thirdProject = await saveProjectDirectlyToDb(createProjectData()); + await setMultipleBoosting({ + userId: user.id, + projectIds: [firstProject.id, secondProject.id, thirdProject.id], + percentages: [20, 40, 40], + }); + + await setSingleBoosting({ + userId: user.id, + projectId: firstProject.id, + percentage: 0, + }); + const [userPowerBoostings] = await findPowerBoostings({ + userId: user.id, + orderBy: { + field: 'updatedAt', + direction: 'ASC', + }, + }); + + assert.equal(userPowerBoostings.length, 2); + + assert.isOk( + userPowerBoostings.find( + powerBoosting => + powerBoosting.project.id === secondProject.id && + powerBoosting.percentage === 50, + ), + ); + assert.isOk( + userPowerBoostings.find( + powerBoosting => + powerBoosting.project.id === thirdProject.id && + powerBoosting.percentage === 50, + ), + ); + }); + it('should set single boosting with 0%', async () => { + const user = await saveUserDirectlyToDb(generateRandomEtheriumAddress()); + const firstProject = await saveProjectDirectlyToDb(createProjectData()); + + await setSingleBoosting({ + userId: user.id, + projectId: firstProject.id, + percentage: 100, + }); + + await cancelProjectBoosting({ + userId: user.id, + projectId: firstProject.id, + }); + const [userPowerBoostings] = await findPowerBoostings({ + userId: user.id, + orderBy: { + field: 'updatedAt', + direction: 'ASC', + }, + }); + + assert.equal(userPowerBoostings.length, 0); + }); + it('should get error when set single boosting with something between 0-100', async () => { + const user = await saveUserDirectlyToDb(generateRandomEtheriumAddress()); + const firstProject = await saveProjectDirectlyToDb(createProjectData()); + await assertThrowsAsync(async () => { + await setSingleBoosting({ + userId: user.id, + projectId: firstProject.id, + percentage: 70, + }); + }, errorMessages.ERROR_GIVPOWER_BOOSTING_FIRST_PROJECT_100_PERCENT); + }); +} + function powerBoostingSnapshotTests() { it('should take snapshot of power boosting', async () => { await PowerBoosting.clear(); diff --git a/src/repositories/powerBoostingRepository.ts b/src/repositories/powerBoostingRepository.ts index fd379db74..cbda3ba29 100644 --- a/src/repositories/powerBoostingRepository.ts +++ b/src/repositories/powerBoostingRepository.ts @@ -11,7 +11,6 @@ import { import { PowerSnapshot } from '../entities/powerSnapshot'; import { getRoundNumberByDate } from '../utils/powerBoostingUtils'; import { getKeyByValue } from '../utils/utils'; -import { Reaction } from '../entities/reaction'; const MAX_PROJECT_BOOST_LIMIT = Number( process.env.GIVPOWER_BOOSTING_USER_PROJECTS_LIMIT || '20', @@ -125,12 +124,30 @@ export const insertSinglePowerBoosting = async (params: { }).save(); }; +export const cancelProjectBoosting = async (params: { + userId: number; + projectId: number; +}): Promise => + _setSingleBoosting({ + ...params, + percentage: 0, + projectIsCanceled: true, + }); + export const setSingleBoosting = async (params: { userId: number; projectId: number; percentage: number; +}): Promise => + _setSingleBoosting({ ...params, projectIsCanceled: false }); + +const _setSingleBoosting = async (params: { + userId: number; + projectId: number; + percentage: number; + projectIsCanceled: boolean; }): Promise => { - const { userId, projectId, percentage } = params; + const { userId, projectId, percentage, projectIsCanceled } = params; if (percentage < 0 || percentage > 100) { throw new Error( @@ -161,7 +178,7 @@ export const setSingleBoosting = async (params: { const commitData: PowerBoosting[] = []; if (otherProjectsPowerBoostings.length === 0) { - if (percentage !== 100) + if (percentage !== 100 && !projectIsCanceled) throw new Error( i18n.__( translationErrorMessagesKeys.ERROR_GIVPOWER_BOOSTING_FIRST_PROJECT_100_PERCENT, diff --git a/src/services/powerBoostingService.test.ts b/src/services/powerBoostingService.test.ts index 5aa4c0a01..358bf89d8 100644 --- a/src/services/powerBoostingService.test.ts +++ b/src/services/powerBoostingService.test.ts @@ -51,4 +51,25 @@ function changeUserBoostingsAfterProjectCancelledTestCases() { assert.equal(secondUserBoostings[0].percentage, 100); assert.equal(secondUserBoostings[0].projectId, firstProject.id); }); + it('should change user percentage to zero when project cancelled, even when just has 1 boositng', async () => { + const user1 = await saveUserDirectlyToDb(generateRandomEtheriumAddress()); + const projectThatWouldGetCancelled = await saveProjectDirectlyToDb( + createProjectData(), + ); + await setMultipleBoosting({ + userId: user1.id, + projectIds: [projectThatWouldGetCancelled.id], + percentages: [100], + }); + + await changeUserBoostingsAfterProjectCancelled({ + projectId: projectThatWouldGetCancelled.id, + }); + + // Changing percentages is async we sleep some milli seconds to make sure all updates has been done + await sleep(100); + const firstUserBoostings = await findUserPowerBoosting(user1.id); + + assert.equal(firstUserBoostings.length, 0); + }); } diff --git a/src/services/powerBoostingService.ts b/src/services/powerBoostingService.ts index a96a6e089..3b10a4145 100644 --- a/src/services/powerBoostingService.ts +++ b/src/services/powerBoostingService.ts @@ -1,6 +1,6 @@ import { + cancelProjectBoosting, findPowerBoostings, - setSingleBoosting, } from '../repositories/powerBoostingRepository'; export const changeUserBoostingsAfterProjectCancelled = async (params: { @@ -12,10 +12,9 @@ export const changeUserBoostingsAfterProjectCancelled = async (params: { projectId, }); powerBoostings.forEach(powerBoosting => - setSingleBoosting({ + cancelProjectBoosting({ userId: powerBoosting.userId, projectId, - percentage: 0, }), ); };