freeCodeCamp/api-server/server/utils/donation.test.js

167 lines
4.7 KiB
JavaScript
Raw Normal View History

2020-03-13 09:25:57 +00:00
/* eslint-disable camelcase */
/* global describe it expect */
/* global jest*/
import axios from 'axios';
import keys from '../../../config/secrets';
import {
getAsyncPaypalToken,
verifyWebHook,
updateUser,
capitalizeKeys,
createDonationObj
} from './donation';
import { mockActivationHook, mockCancellationHook } from './__mocks__/donation';
import {
mockApp,
createDonationMockFn,
createUserMockFn,
updateDonationAttr,
updateUserAttr
} from '../boot_tests/fixtures';
jest.mock('axios');
const verificationUrl = `https://api.sandbox.paypal.com/v1/notifications/verify-webhook-signature`;
const tokenUrl = `https://api.sandbox.paypal.com/v1/oauth2/token`;
2020-03-13 09:25:57 +00:00
const {
body: activationHookBody,
headers: activationHookHeaders
} = mockActivationHook;
describe('donation', () => {
describe('getAsyncPaypalToken', () => {
it('call paypal api for token ', async () => {
const res = {
data: {
access_token: 'token'
}
};
axios.post.mockImplementationOnce(() => Promise.resolve(res));
await expect(getAsyncPaypalToken()).resolves.toEqual(
res.data.access_token
);
expect(axios.post).toHaveBeenCalledTimes(1);
expect(axios.post).toHaveBeenCalledWith(tokenUrl, null, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
auth: {
username: keys.paypal.client,
password: keys.paypal.secret
},
params: {
grant_type: 'client_credentials'
}
});
});
});
describe('verifyWebHook', () => {
// normalize headers
capitalizeKeys(activationHookHeaders);
const mockWebhookId = 'qwdfq;3w12341dfa4';
const mockAccessToken = '241231223$!@$#1243';
const mockPayLoad = {
auth_algo: activationHookHeaders['PAYPAL-AUTH-ALGO'],
cert_url: activationHookHeaders['PAYPAL-CERT-URL'],
transmission_id: activationHookHeaders['PAYPAL-TRANSMISSION-ID'],
transmission_sig: activationHookHeaders['PAYPAL-TRANSMISSION-SIG'],
transmission_time: activationHookHeaders['PAYPAL-TRANSMISSION-TIME'],
webhook_id: mockWebhookId,
webhook_event: activationHookBody
};
const failedVerificationErr = {
message: `Failed token verification.`,
type: 'FailedPaypalTokenVerificationError'
};
const axiosOptions = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${mockAccessToken}`
}
};
const successVerificationResponce = {
data: {
verification_status: 'SUCCESS'
}
};
const failedVerificationResponce = {
data: {
verification_status: 'FAILED'
}
};
it('calls paypal for Webhook verification', async () => {
axios.post.mockImplementationOnce(() =>
Promise.resolve(successVerificationResponce)
);
await expect(
verifyWebHook(
activationHookHeaders,
activationHookBody,
mockAccessToken,
mockWebhookId
)
).resolves.toEqual(activationHookBody);
expect(axios.post).toHaveBeenCalledWith(
verificationUrl,
mockPayLoad,
axiosOptions
);
});
it('throws error if verification not successful', async () => {
axios.post.mockImplementationOnce(() =>
Promise.resolve(failedVerificationResponce)
);
await expect(
verifyWebHook(
activationHookHeaders,
activationHookBody,
mockAccessToken,
mockWebhookId
)
).rejects.toEqual(failedVerificationErr);
});
});
describe('updateUser', () => {
it('created a donation when a machting user found', () => {
updateUser(activationHookBody, mockApp);
expect(createDonationMockFn).toHaveBeenCalledTimes(1);
expect(createDonationMockFn).toHaveBeenCalledWith(
createDonationObj(activationHookBody)
);
});
it('create a user and donation when no machting user found', () => {
let newActivationHookBody = activationHookBody;
newActivationHookBody.resource.subscriber.email_address =
'new@freecodecamp.org';
updateUser(newActivationHookBody, mockApp);
expect(createUserMockFn).toHaveBeenCalledTimes(1);
});
it('modify user and donation records on cancellation', () => {
const { body: cancellationHookBody } = mockCancellationHook;
const {
resource: { status_update_time = new Date(Date.now()).toISOString() }
} = cancellationHookBody;
updateUser(cancellationHookBody, mockApp);
expect(updateDonationAttr).toHaveBeenCalledWith({
endDate: new Date(status_update_time).toISOString()
});
expect(updateUserAttr).toHaveBeenCalledWith({
isDonating: false
});
});
});
});