mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-14 05:07:22 +01:00
* todo comment * add failures field to webhooks and sanitize * implement logic * use update instead of save * specify timeout and maximum number of retries * add tests
173 lines
4.9 KiB
JavaScript
173 lines
4.9 KiB
JavaScript
import { v4 as generateUUID } from 'uuid';
|
|
import {
|
|
generateUser,
|
|
translate as t,
|
|
} from '../../../../helpers/api-integration/v3';
|
|
import apiError from '../../../../../website/server/libs/apiError';
|
|
|
|
describe('PUT /user/webhook/:id', () => {
|
|
let user; let
|
|
webhookToUpdate;
|
|
|
|
beforeEach(async () => {
|
|
user = await generateUser();
|
|
|
|
webhookToUpdate = await user.post('/user/webhook', {
|
|
url: 'http://some-url.com',
|
|
label: 'Original Label',
|
|
enabled: true,
|
|
type: 'taskActivity',
|
|
options: { created: true, scored: true },
|
|
});
|
|
await user.post('/user/webhook', {
|
|
url: 'http://some-other-url.com',
|
|
enabled: false,
|
|
});
|
|
|
|
await user.sync();
|
|
});
|
|
|
|
it('returns an error if webhook with id does not exist', async () => {
|
|
await expect(user.put('/user/webhook/id-that-does-not-exist')).to.eventually.be.rejected.and.eql({
|
|
code: 404,
|
|
error: 'NotFound',
|
|
message: t('noWebhookWithId', { id: 'id-that-does-not-exist' }),
|
|
});
|
|
});
|
|
|
|
it('returns an error if validation fails', async () => {
|
|
await expect(user.put(`/user/webhook/${webhookToUpdate.id}`, { url: 'foo_invalid', enabled: true })).to.eventually.be.rejected.and.eql({
|
|
code: 400,
|
|
error: 'BadRequest',
|
|
message: 'User validation failed',
|
|
});
|
|
});
|
|
|
|
it('updates a webhook', async () => {
|
|
const url = 'http://a-new-url.com';
|
|
const type = 'groupChatReceived';
|
|
const label = 'New Label';
|
|
const options = { groupId: generateUUID() };
|
|
|
|
await user.put(`/user/webhook/${webhookToUpdate.id}`, {
|
|
url, type, options, label,
|
|
});
|
|
|
|
await user.sync();
|
|
|
|
const webhook = user.webhooks.find(hook => webhookToUpdate.id === hook.id);
|
|
|
|
expect(webhook.url).to.equal(url);
|
|
expect(webhook.label).to.equal(label);
|
|
expect(webhook.type).to.equal(type);
|
|
expect(webhook.options).to.eql(options);
|
|
});
|
|
|
|
it('ignores protected fields', async () => {
|
|
const failures = 3;
|
|
const lastFailureAt = new Date();
|
|
|
|
await user.put(`/user/webhook/${webhookToUpdate.id}`, {
|
|
failures, lastFailureAt,
|
|
});
|
|
|
|
await user.sync();
|
|
const webhook = user.webhooks.find(hook => webhookToUpdate.id === hook.id);
|
|
|
|
expect(webhook.failures).to.eql(0);
|
|
expect(webhook.lastFailureAt).to.eql(undefined);
|
|
});
|
|
|
|
it('updates a webhook with empty label', async () => {
|
|
const url = 'http://a-new-url.com';
|
|
const type = 'groupChatReceived';
|
|
const label = '';
|
|
const options = { groupId: generateUUID() };
|
|
|
|
await user.put(`/user/webhook/${webhookToUpdate.id}`, {
|
|
url, type, options, label,
|
|
});
|
|
|
|
await user.sync();
|
|
|
|
const webhook = user.webhooks.find(hook => webhookToUpdate.id === hook.id);
|
|
|
|
expect(webhook.url).to.equal(url);
|
|
expect(webhook.label).to.equal(label);
|
|
expect(webhook.type).to.equal(type);
|
|
expect(webhook.options).to.eql(options);
|
|
});
|
|
|
|
it('returns the updated webhook', async () => {
|
|
const url = 'http://a-new-url.com';
|
|
const type = 'groupChatReceived';
|
|
const options = { groupId: generateUUID() };
|
|
|
|
const response = await user.put(`/user/webhook/${webhookToUpdate.id}`, { url, type, options });
|
|
|
|
expect(response.url).to.eql(url);
|
|
expect(response.type).to.eql(type);
|
|
expect(response.options).to.eql(options);
|
|
});
|
|
|
|
it('cannot update the id', async () => {
|
|
const id = generateUUID();
|
|
const url = 'http://a-new-url.com';
|
|
|
|
await user.put(`/user/webhook/${webhookToUpdate.id}`, { url, id });
|
|
|
|
await user.sync();
|
|
|
|
const webhook = user.webhooks.find(hook => webhookToUpdate.id === hook.id);
|
|
|
|
expect(webhook.id).to.eql(webhookToUpdate.id);
|
|
expect(webhook.url).to.eql(url);
|
|
});
|
|
|
|
it('can update taskActivity options', async () => {
|
|
const type = 'taskActivity';
|
|
const options = {
|
|
updated: false,
|
|
deleted: true,
|
|
};
|
|
|
|
const webhook = await user.put(`/user/webhook/${webhookToUpdate.id}`, { type, options });
|
|
|
|
expect(webhook.options).to.eql({
|
|
checklistScored: false, // starting value
|
|
created: true, // starting value
|
|
updated: false,
|
|
deleted: true,
|
|
scored: true, // default value
|
|
});
|
|
});
|
|
|
|
it('errors if taskActivity option is not a boolean', async () => {
|
|
const type = 'taskActivity';
|
|
const options = {
|
|
created: 'not a boolean',
|
|
updated: false,
|
|
deleted: true,
|
|
};
|
|
|
|
await expect(user.put(`/user/webhook/${webhookToUpdate.id}`, { type, options })).to.eventually.be.rejected.and.eql({
|
|
code: 400,
|
|
error: 'BadRequest',
|
|
message: t('webhookBooleanOption', { option: 'created' }),
|
|
});
|
|
});
|
|
|
|
it('errors if groupChatRecieved groupId option is not a uuid', async () => {
|
|
const type = 'groupChatReceived';
|
|
const options = {
|
|
groupId: 'not-a-uuid',
|
|
};
|
|
|
|
await expect(user.put(`/user/webhook/${webhookToUpdate.id}`, { type, options })).to.eventually.be.rejected.and.eql({
|
|
code: 400,
|
|
error: 'BadRequest',
|
|
message: apiError('groupIdRequired'),
|
|
});
|
|
});
|
|
});
|