Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests for userCaps resolver #143

Merged
merged 10 commits into from
Nov 27, 2024
190 changes: 190 additions & 0 deletions src/resolvers/qAccResolver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,15 @@ import {
import {
projectUserDonationCap,
projectUserTotalDonationAmounts,
userCaps,
} from '../../test/graphqlQueries';
import { ProjectRoundRecord } from '../entities/projectRoundRecord';
import { EarlyAccessRound } from '../entities/earlyAccessRound';
import {
GITCOIN_PASSPORT_MIN_VALID_ANALYSIS_SCORE,
MAX_CONTRIBUTION_WITH_GITCOIN_PASSPORT_ONLY_USD,
} from '../constants/gitcoin';
import { PrivadoAdapter } from '../adapters/privado/privadoAdapter';

describe(
'projectUserTotalDonationAmount() test cases',
Expand All @@ -38,6 +44,8 @@ describe(
projectUserDonationCapTestCases,
);

describe('userCaps() test cases', userCapsTestCases);

function projectUserTotalDonationAmountTestCases() {
it('should return total donation amount of a user for a project', async () => {
it('should return total donation amount of a user for a project', async () => {
Expand Down Expand Up @@ -236,3 +244,185 @@ function projectUserDonationCapTestCases() {
);
});
}

function userCapsTestCases() {
let project;
let user;
let accessToken;
let qfRound1: QfRound;
beforeEach(async () => {
project = await saveProjectDirectlyToDb(createProjectData());

user = await saveUserDirectlyToDb(generateRandomEtheriumAddress());
accessToken = await generateTestAccessToken(user.id);

qfRound1 = await QfRound.create({
roundNumber: 1,
isActive: true,
name: new Date().toString() + ' - 1',
allocatedFund: 100,
minimumPassportScore: 12,
slug: new Date().getTime().toString() + ' - 1',
beginDate: new Date('2001-01-14'),
endDate: new Date('2001-01-16'),
roundUSDCapPerProject: 10000,
roundUSDCapPerUserPerProject: 2500,
tokenPrice: 0.5,
}).save();
sinon.useFakeTimers({
now: new Date('2001-01-15').getTime(),
});
});
afterEach(async () => {
// Clean up the database after each test
await ProjectRoundRecord.delete({});
await Donation.delete({ projectId: project.id });
await QfRound.delete(qfRound1.id);

sinon.restore();
});
it('should return correct caps for a user with GitcoinPassport', async () => {
// Save donations
const donationAmount = 100;
await saveDonationDirectlyToDb(
{
...createDonationData(),
amount: donationAmount,
status: DONATION_STATUS.VERIFIED,
qfRoundId: qfRound1.id,
},
user.id,
project.id,
);

// Simulate valid GitcoinPassport score
user.analysisScore = 80;
user.passportScoreUpdateTimestamp = new Date();
await user.save();

const response: ExecutionResult<{
data: {
userCaps: {
qAccCap: number;
gitcoinPassport?: {
unusedCap: number;
};
zkId?: {
unusedCap: number;
};
};
};
}> = await axios.post(
graphqlUrl,
{
query: userCaps,
variables: { projectId: project.id },
},
{
headers: {
Authorization: `Bearer ${accessToken}`,
},
},
);

assert.equal(
response.data?.data.userCaps?.qAccCap,
Number(qfRound1.roundUSDCapPerUserPerProject) /
Number(qfRound1.tokenPrice) -
donationAmount,
);
assert.equal(
response.data?.data.userCaps?.gitcoinPassport?.unusedCap,
MAX_CONTRIBUTION_WITH_GITCOIN_PASSPORT_ONLY_USD /
Number(qfRound1.tokenPrice) -
donationAmount,
);
assert.isNull(response.data?.data.userCaps?.zkId);
});

it('should return correct caps for a user with ZkId', async () => {
// Save donations
const donationAmount = 500;
await saveDonationDirectlyToDb(
{
...createDonationData(),
amount: donationAmount,
status: DONATION_STATUS.VERIFIED,
qfRoundId: qfRound1.id,
},
user.id,
project.id,
);

user.privadoVerifiedRequestIds = [PrivadoAdapter.privadoRequestId];
await user.save();

const response: ExecutionResult<{
data: {
userCaps: {
qAccCap: number;
gitcoinPassport?: {
unusedCap: number;
};
zkId?: {
unusedCap: number;
};
};
};
}> = await axios.post(
graphqlUrl,
{
query: userCaps,
variables: { projectId: project.id },
},
{
headers: {
Authorization: `Bearer ${accessToken}`,
},
},
);

// Assert: Verify the response matches expected values
assert.equal(
response.data?.data.userCaps?.qAccCap,
Number(qfRound1.roundUSDCapPerUserPerProject) /
Number(qfRound1.tokenPrice) -
donationAmount,
);
assert.equal(
response.data?.data.userCaps?.zkId?.unusedCap,
Number(qfRound1.roundUSDCapPerUserPerProject) /
Number(qfRound1.tokenPrice) -
donationAmount,
);
assert.isNull(response.data?.data.userCaps?.gitcoinPassport);
});

it('should throw an error if the user does not meet the minimum analysis score', async () => {
// Simulate invalid GitcoinPassport score
sinon.stub(user, 'analysisScore').value(40); // Below threshold
sinon.stub(user, 'hasEnoughGitcoinAnalysisScore').value(false);

// Act: Call the resolver through a GraphQL query and expect an error
try {
await axios.post(
graphqlUrl,
{
query: userCaps,
variables: { projectId: project.id },
},
{
headers: {
Authorization: `Bearer ${accessToken}`,
},
},
);
} catch (error: any) {
// Assert: Verify the error message
assert.equal(
error.response.data.errors[0].message,
`analysis score is less than ${GITCOIN_PASSPORT_MIN_VALID_ANALYSIS_SCORE}`,
);
}
});
}
4 changes: 2 additions & 2 deletions test/graphqlQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2165,10 +2165,10 @@ export const userCaps = `
userCaps(projectId: $projectId) {
qAccCap
gitcoinPassport {
unusedCapped
unusedCap
}
zkId {
unusedCapped
unusedCap
}
}
}
Expand Down