implement replies collection for posts

This commit is contained in:
Hazelnoot 2025-02-22 20:33:45 -05:00
parent 62d35a56c1
commit 5182f17d32
4 changed files with 295 additions and 3 deletions

View file

@ -9,6 +9,7 @@ import { generateKeyPair } from 'crypto';
import { Test } from '@nestjs/testing';
import { jest } from '@jest/globals';
import type { Config } from '@/config.js';
import type { MiLocalUser, MiRemoteUser } from '@/models/User.js';
import { ApImageService } from '@/core/activitypub/models/ApImageService.js';
import { ApNoteService } from '@/core/activitypub/models/ApNoteService.js';
@ -99,6 +100,7 @@ describe('ActivityPub', () => {
let idService: IdService;
let userPublickeysRepository: UserPublickeysRepository;
let userKeypairService: UserKeypairService;
let config: Config;
const metaInitial = {
cacheRemoteFiles: true,
@ -149,6 +151,7 @@ describe('ActivityPub', () => {
idService = app.get<IdService>(IdService);
userPublickeysRepository = app.get<UserPublickeysRepository>(DI.userPublickeysRepository);
userKeypairService = app.get<UserKeypairService>(UserKeypairService);
config = app.get<Config>(DI.config);
// Prevent ApPersonService from fetching instance, as it causes Jest import-after-test error
const federatedInstanceService = app.get<FederatedInstanceService>(FederatedInstanceService);
@ -612,6 +615,40 @@ describe('ActivityPub', () => {
expect(result.summary).toBe('original and mandatory');
});
});
describe('replies', () => {
it('should be included when visibility=public', async () => {
note.visibility = 'public';
const rendered = await rendererService.renderNote(note, author, false);
expect(rendered.replies).toBeDefined();
});
it('should be included when visibility=home', async () => {
note.visibility = 'home';
const rendered = await rendererService.renderNote(note, author, false);
expect(rendered.replies).toBeDefined();
});
it('should be excluded when visibility=followers', async () => {
note.visibility = 'followers';
const rendered = await rendererService.renderNote(note, author, false);
expect(rendered.replies).not.toBeDefined();
});
it('should be excluded when visibility=specified', async () => {
note.visibility = 'specified';
const rendered = await rendererService.renderNote(note, author, false);
expect(rendered.replies).not.toBeDefined();
});
});
});
describe('renderUpnote', () => {
@ -695,6 +732,110 @@ describe('ActivityPub', () => {
expect(result.name).toBeUndefined();
});
});
describe('renderRepliesCollection', () => {
it('should include type', async () => {
const collection = await rendererService.renderRepliesCollection(note.id);
expect(collection.type).toBe('OrderedCollection');
});
it('should include id', async () => {
const collection = await rendererService.renderRepliesCollection(note.id);
expect(collection.id).toBe(`${config.url}/notes/${note.id}/replies`);
});
it('should include first', async () => {
const collection = await rendererService.renderRepliesCollection(note.id);
expect(collection.first).toBe(`${config.url}/notes/${note.id}/replies?page=true`);
});
it('should include totalItems', async () => {
const collection = await rendererService.renderRepliesCollection(note.id);
expect(collection.totalItems).toBe(0);
});
});
describe('renderRepliesCollectionPage', () => {
describe('with untilId', () => {
it('should include type', async () => {
const collection = await rendererService.renderRepliesCollectionPage(note.id, 'abc123');
expect(collection.type).toBe('OrderedCollectionPage');
});
it('should include id', async () => {
const collection = await rendererService.renderRepliesCollectionPage(note.id, 'abc123');
expect(collection.id).toBe(`${config.url}/notes/${note.id}/replies?page=true&until_id=abc123`);
});
it('should include partOf', async () => {
const collection = await rendererService.renderRepliesCollectionPage(note.id, 'abc123');
expect(collection.partOf).toBe(`${config.url}/notes/${note.id}/replies`);
});
it('should include first', async () => {
const collection = await rendererService.renderRepliesCollectionPage(note.id, 'abc123');
expect(collection.first).toBe(`${config.url}/notes/${note.id}/replies?page=true`);
});
it('should include totalItems', async () => {
const collection = await rendererService.renderRepliesCollectionPage(note.id, 'abc123');
expect(collection.totalItems).toBe(0);
});
it('should include orderedItems', async () => {
const collection = await rendererService.renderRepliesCollectionPage(note.id, 'abc123');
expect(collection.orderedItems).toBeDefined();
});
});
describe('without untilId', () => {
it('should include type', async () => {
const collection = await rendererService.renderRepliesCollectionPage(note.id, undefined);
expect(collection.type).toBe('OrderedCollectionPage');
});
it('should include id', async () => {
const collection = await rendererService.renderRepliesCollectionPage(note.id, undefined);
expect(collection.id).toBe(`${config.url}/notes/${note.id}/replies?page=true`);
});
it('should include partOf', async () => {
const collection = await rendererService.renderRepliesCollectionPage(note.id, undefined);
expect(collection.partOf).toBe(`${config.url}/notes/${note.id}/replies`);
});
it('should include first', async () => {
const collection = await rendererService.renderRepliesCollectionPage(note.id, undefined);
expect(collection.first).toBe(`${config.url}/notes/${note.id}/replies?page=true`);
});
it('should include totalItems', async () => {
const collection = await rendererService.renderRepliesCollectionPage(note.id, undefined);
expect(collection.totalItems).toBe(0);
});
it('should include orderedItems', async () => {
const collection = await rendererService.renderRepliesCollectionPage(note.id, undefined);
expect(collection.orderedItems).toBeDefined();
});
});
});
});
describe(ApPersonService, () => {