feat(server): add comment-attachment model (#12909)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Introduced support for comment attachments, allowing users to add,
view, and manage attachments linked to comments within documents.
* **Tests**
* Added comprehensive tests to ensure correct behavior for adding,
updating, deleting, listing, and retrieving comment attachments.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


#### PR Dependency Tree


* **PR #12909** 👈
  * **PR #12911**
    * **PR #12761**
      * **PR #12924**
        * **PR #12925**

This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
This commit is contained in:
fengmk2
2025-06-28 16:45:24 +08:00
committed by GitHub
parent 1c1dade2d5
commit e773930256
5 changed files with 243 additions and 0 deletions
@@ -0,0 +1,125 @@
import test from 'ava';
import { createModule } from '../../__tests__/create-module';
import { Mockers } from '../../__tests__/mocks';
import { Models } from '..';
const module = await createModule();
const models = module.get(Models);
test.after.always(async () => {
await module.close();
});
test('should upsert comment attachment', async t => {
const workspace = await module.create(Mockers.Workspace);
// add
const item = await models.commentAttachment.upsert({
workspaceId: workspace.id,
docId: 'test-doc-id',
key: 'test-key',
name: 'test-name',
mime: 'text/plain',
size: 100,
});
t.is(item.workspaceId, workspace.id);
t.is(item.docId, 'test-doc-id');
t.is(item.key, 'test-key');
t.is(item.mime, 'text/plain');
t.is(item.size, 100);
t.truthy(item.createdAt);
// update
const item2 = await models.commentAttachment.upsert({
workspaceId: workspace.id,
docId: 'test-doc-id',
name: 'test-name',
key: 'test-key',
mime: 'text/html',
size: 200,
});
t.is(item2.workspaceId, workspace.id);
t.is(item2.docId, 'test-doc-id');
t.is(item2.key, 'test-key');
t.is(item2.mime, 'text/html');
t.is(item2.size, 200);
// make sure only one blob is created
const items = await models.commentAttachment.list(workspace.id);
t.is(items.length, 1);
t.deepEqual(items[0], item2);
});
test('should delete comment attachment', async t => {
const workspace = await module.create(Mockers.Workspace);
const item = await models.commentAttachment.upsert({
workspaceId: workspace.id,
docId: 'test-doc-id',
key: 'test-key',
name: 'test-name',
mime: 'text/plain',
size: 100,
});
await models.commentAttachment.delete(workspace.id, item.docId, item.key);
const item2 = await models.commentAttachment.get(
workspace.id,
item.docId,
item.key
);
t.is(item2, null);
});
test('should list comment attachments', async t => {
const workspace = await module.create(Mockers.Workspace);
const item1 = await models.commentAttachment.upsert({
workspaceId: workspace.id,
docId: 'test-doc-id',
name: 'test-name',
key: 'test-key',
mime: 'text/plain',
size: 100,
});
const item2 = await models.commentAttachment.upsert({
workspaceId: workspace.id,
docId: 'test-doc-id2',
name: 'test-name2',
key: 'test-key2',
mime: 'text/plain',
size: 200,
});
const items = await models.commentAttachment.list(workspace.id);
t.is(items.length, 2);
items.sort((a, b) => a.key.localeCompare(b.key));
t.is(items[0].key, item1.key);
t.is(items[1].key, item2.key);
});
test('should get comment attachment', async t => {
const workspace = await module.create(Mockers.Workspace);
const item = await models.commentAttachment.upsert({
workspaceId: workspace.id,
docId: 'test-doc-id',
name: 'test-name',
key: 'test-key',
mime: 'text/plain',
size: 100,
});
const item2 = await models.commentAttachment.get(
workspace.id,
item.docId,
item.key
);
t.truthy(item2);
t.is(item2?.key, item.key);
});