comments implement

This commit is contained in:
vadim committed 2026-10-01 12:02:03 +03:00
1 parent 9e0bef2527
commit 4b6ecfbf5d
41 files changed
+1350 -13

No files matched your search

@@ -0,0 +1,76 @@
import { describe, expect, it } from 'vitest';
import { Comment } from './comment.entity.js';
import { CommentForbiddenException } from '../exceptions/comment-forbidden.exception.js';
const buildComment = (overrides: Partial<{ authorId: string | null; deletedAt: Date | null }> = {}) =>
Comment.reconstitute({
id: 'comment-1',
content: 'Original',
issueId: 1,
authorId: overrides.authorId === undefined ? 'user-1' : overrides.authorId,
editedAt: null,
deletedAt: overrides.deletedAt ?? null,
createdAt: new Date('2026-01-01T00:00:00.000Z'),
updatedAt: new Date('2026-01-01T00:00:00.000Z'),
});
describe('Comment', () => {
describe('create', () => {
it('creates a new comment without id and edit/delete marks', () => {
const comment = Comment.create({ issueId: 1, authorId: 'user-1', content: ' Hello ' });
expect(comment.id).toBeNull();
expect(comment.content).toBe('Hello');
expect(comment.editedAt).toBeNull();
expect(comment.isDeleted).toBe(false);
});
it('rejects empty content', () => {
expect(() => Comment.create({ issueId: 1, authorId: 'user-1', content: '' })).toThrow();
});
});
describe('edit', () => {
it('changes content and sets editedAt', () => {
const comment = buildComment();
expect(comment.edit('Changed', 'user-1')).toBe(true);
expect(comment.content).toBe('Changed');
expect(comment.editedAt).toBeInstanceOf(Date);
});
it('is a no-op when content is the same', () => {
const comment = buildComment();
expect(comment.edit(' Original ', 'user-1')).toBe(false);
expect(comment.editedAt).toBeNull();
});
it('forbids editing by someone other than the author', () => {
expect(() => buildComment().edit('Changed', 'user-2')).toThrow(CommentForbiddenException);
});
it('forbids editing when the author account is deleted', () => {
expect(() => buildComment({ authorId: null }).edit('Changed', 'user-1')).toThrow(CommentForbiddenException);
});
it('forbids editing a deleted comment', () => {
expect(() => buildComment({ deletedAt: new Date() }).edit('Changed', 'user-1')).toThrow();
});
});
describe('delete', () => {
it('soft-deletes the comment', () => {
const comment = buildComment();
comment.delete('user-1');
expect(comment.isDeleted).toBe(true);
expect(comment.deletedAt).toBeInstanceOf(Date);
});
it('forbids deletion by someone other than the author', () => {
expect(() => buildComment().delete('user-2')).toThrow(CommentForbiddenException);
});
});
});