Files
talk/test/server/graph/mutations/editComment.js
T
2018-03-12 16:39:38 -06:00

289 lines
8.8 KiB
JavaScript

const { graphql } = require('graphql');
const timekeeper = require('timekeeper');
const AssetModel = require('../../../../models/asset');
const CommentModel = require('../../../../models/comment');
const CommentsService = require('../../../../services/comments');
const Context = require('../../../../graph/context');
const schema = require('../../../../graph/schema');
const SettingsService = require('../../../../services/settings');
const UsersService = require('../../../../services/users');
const { expect } = require('chai');
describe('graph.mutations.editComment', () => {
let asset, user;
beforeEach(async () => {
timekeeper.reset();
await SettingsService.init();
const ctx = Context.forSystem();
asset = await AssetModel.create({});
user = await UsersService.createLocalUser(
ctx,
'usernameA@example.com',
'password',
'usernameA'
);
});
const editCommentMutation = `
mutation EditComment ($id: ID!, $asset_id: ID!, $edit: EditCommentInput) {
editComment(id:$id, asset_id:$asset_id, edit:$edit) {
errors {
translation_key
}
}
}
`;
it('a user can edit their own comment', async () => {
const context = new Context({ user });
const testStartedAt = new Date();
const comment = await CommentsService.publicCreate({
asset_id: asset.id,
author_id: user.id,
body: `hello there! ${String(Math.random()).slice(2)}`,
});
// body_history should be there
expect(comment.body_history.length).to.equal(1);
expect(comment.body_history[0].body).to.equal(comment.body);
expect(comment.body_history[0].created_at).to.be.instanceOf(Date);
expect(comment.body_history[0].created_at).to.be.at.least(testStartedAt);
// now edit
const newBody = 'I have been edited.';
const response = await graphql(schema, editCommentMutation, {}, context, {
id: comment.id,
asset_id: asset.id,
edit: {
body: newBody,
},
});
if (response.errors && response.errors.length) {
console.error(response.errors);
}
expect(response.errors).to.be.empty;
if (
response.data.editComment.errors &&
response.data.editComment.errors.length > 0
) {
console.error(response.data.editComment.errors);
}
expect(response.data.editComment.errors).to.be.null;
// assert body has changed
const commentAfterEdit = await CommentModel.findOne({ id: comment.id });
expect(commentAfterEdit.body).to.equal(newBody);
expect(commentAfterEdit.body_history).to.be.instanceOf(Array);
expect(commentAfterEdit.body_history.length).to.equal(2);
expect(commentAfterEdit.body_history[1].body).to.equal(newBody);
expect(commentAfterEdit.body_history[1].created_at).to.be.instanceOf(Date);
expect(commentAfterEdit.body_history[1].created_at).to.be.at.least(
testStartedAt
);
expect(commentAfterEdit.status).to.equal('NONE');
});
it("A user can't edit their comment outside of the edit comment time window", async () => {
const comment = await CommentsService.publicCreate({
asset_id: asset.id,
author_id: user.id,
body: `hello there! ${String(Math.random()).slice(2)}`,
});
const now = new Date();
const oneHourFromNow = new Date(new Date(now).setHours(now.getHours() + 1));
timekeeper.travel(oneHourFromNow);
const newBody = 'This body should never be set';
const context = new Context({ user });
const response = await graphql(schema, editCommentMutation, {}, context, {
id: comment.id,
asset_id: asset.id,
edit: {
body: newBody,
},
});
if (response.errors && response.errors.length > 0) {
console.error(response.errors);
}
expect(response.errors).to.be.empty;
expect(response.data.editComment.errors).to.not.be.empty;
expect(response.data.editComment.errors[0].translation_key).to.equal(
'EDIT_WINDOW_ENDED'
);
const commentAfterEdit = await CommentModel.findOne({ id: comment.id });
// it *hasn't* changed from the original
expect(commentAfterEdit.body).to.equal(comment.body);
});
it("A user can't edit someone else's comment", async () => {
const comment = await CommentsService.publicCreate({
asset_id: asset.id,
author_id: user.id,
body: `hello there! ${String(Math.random()).slice(2)}`,
});
const ctx = Context.forSystem();
const userB = await UsersService.createLocalUser(
ctx,
'usernameB@example.com',
'password',
'usernameB'
);
const newBody = 'This body should never be set';
const context = new Context({ user: userB });
const response = await graphql(schema, editCommentMutation, {}, context, {
id: comment.id,
asset_id: asset.id,
edit: {
body: newBody,
},
});
expect(response.errors).to.be.empty;
expect(response.data.editComment.errors).to.not.be.empty;
expect(response.data.editComment.errors[0].translation_key).to.equal(
'NOT_AUTHORIZED'
);
const commentAfterEdit = await CommentModel.findOne({ id: comment.id });
// it *hasn't* changed from the original
expect(commentAfterEdit.body).to.equal(comment.body);
});
it("A user Can't edit a comment id that doesn't exist", async () => {
const fakeCommentId = 'nooooope';
const newBody = 'This body should never be set';
const context = new Context({ user });
const response = await graphql(schema, editCommentMutation, {}, context, {
id: fakeCommentId,
asset_id: asset.id,
edit: {
body: newBody,
},
});
if (response.errors && response.errors.length > 0) {
console.error(response.errors);
}
expect(response.errors).to.be.empty;
expect(response.data.editComment.errors[0].translation_key).to.equal(
'NOT_FOUND'
);
});
const bannedWord = 'BANNED_WORD';
[
{
description: 'premod: editing a REJECTED comment is rejected',
settings: {
moderation: 'PRE',
},
beforeEdit: {
body: 'I was offensive and thus REJECTED',
status: 'REJECTED',
},
edit: {
body: 'I have been edited to be less offensive',
},
error: true,
},
{
description:
'editing an ACCEPTED comment to add a bad word sets status to REJECTED',
settings: {
moderation: 'POST',
wordlist: {
banned: [bannedWord],
},
},
beforeEdit: {
body: "I'm a perfectly acceptable comment",
status: 'ACCEPTED',
},
edit: {
body: `I have been sneakily edited to add a banned word: ${bannedWord}`,
},
afterEdit: {
status: 'REJECTED',
},
},
{
description:
'postmod: editing a REJECTED comment with banned word be rejected',
settings: {
moderation: 'POST',
wordlist: {
banned: [bannedWord],
},
},
beforeEdit: {
body: `I'm a rejected comment with bad word ${bannedWord}`,
status: 'REJECTED',
},
edit: {
body: 'I have been edited to remove the bad word',
},
error: true,
},
{
description:
'postmod + premodLinksEnable: editing an ACCEPTED comment to add a link sets status to PREMOD',
settings: {
moderation: 'POST',
premodLinksEnable: true,
},
beforeEdit: {
body: "I'm a perfectly acceptable comment",
status: 'ACCEPTED',
},
edit: {
body: 'I have been edited to add a link: https://coralproject.net/',
},
afterEdit: {
status: 'SYSTEM_WITHHELD',
},
},
].forEach(({ description, settings, beforeEdit, edit, afterEdit, error }) => {
it(description, async () => {
await SettingsService.update(settings);
const context = new Context({ user });
const comment = await CommentsService.publicCreate(
Object.assign(
{
asset_id: asset.id,
author_id: user.id,
},
beforeEdit
)
);
// now edit
const newBody = edit.body;
const response = await graphql(schema, editCommentMutation, {}, context, {
id: comment.id,
asset_id: asset.id,
edit: {
body: newBody,
},
});
if (error) {
expect(response.data.editComment.errors).to.not.be.empty;
} else {
if (
response.data.editComment.errors &&
response.data.editComment.errors.length
) {
console.error(response.data.editComment.errors);
}
expect(response.data.editComment.errors).to.be.null;
const commentAfterEdit = await CommentModel.findOne({ id: comment.id });
expect(commentAfterEdit.body).to.equal(newBody);
expect(commentAfterEdit.status).to.equal(afterEdit.status);
}
});
});
});