OpChan/src/lib/forum/relevance.test.ts
2025-08-11 12:23:08 +05:30

214 lines
6.6 KiB
TypeScript

import { RelevanceCalculator } from './relevance';
import { Post, Comment, Cell, User } from '@/types';
import { VoteMessage, MessageType } from '@/lib/waku/types';
import { expect, describe, beforeEach, it } from 'vitest';
import { UserVerificationStatus } from './types';
describe('RelevanceCalculator', () => {
let calculator: RelevanceCalculator;
let mockUserVerificationStatus: any;
beforeEach(() => {
calculator = new RelevanceCalculator();
mockUserVerificationStatus = {
'user1': { isVerified: true, hasENS: true, hasOrdinal: false },
'user2': { isVerified: false, hasENS: false, hasOrdinal: false },
'user3': { isVerified: true, hasENS: false, hasOrdinal: true }
};
});
describe('calculatePostScore', () => {
it('should calculate base score for a new post', () => {
const post: Post = {
id: '1',
cellId: 'cell1',
authorAddress: 'user2',
title: 'Test Post',
content: 'Test content',
timestamp: Date.now(),
upvotes: [],
downvotes: []
};
const result = calculator.calculatePostScore(post, [], [], mockUserVerificationStatus);
expect(result.score).toBeGreaterThan(0);
expect(result.details.baseScore).toBe(10);
expect(result.details.isVerified).toBe(false);
});
it('should apply verification bonus for verified author', () => {
const post: Post = {
id: '1',
cellId: 'cell1',
authorAddress: 'user1',
title: 'Test Post',
content: 'Test content',
timestamp: Date.now(),
upvotes: [],
downvotes: []
};
const result = calculator.calculatePostScore(post, [], [], mockUserVerificationStatus);
expect(result.details.isVerified).toBe(true);
expect(result.details.authorVerificationBonus).toBeGreaterThan(0);
});
it('should correctly identify verified users with ENS ownership', () => {
const verifiedUser: User = {
address: 'user1',
walletType: 'ethereum',
verificationStatus: 'verified-owner',
ensOwnership: true,
ensName: 'test.eth',
lastChecked: Date.now()
};
const isVerified = calculator.isUserVerified(verifiedUser);
expect(isVerified).toBe(true);
});
it('should correctly identify verified users with Ordinal ownership', () => {
const verifiedUser: User = {
address: 'user3',
walletType: 'bitcoin',
verificationStatus: 'verified-owner',
ordinalOwnership: true,
lastChecked: Date.now()
};
const isVerified = calculator.isUserVerified(verifiedUser);
expect(isVerified).toBe(true);
});
it('should correctly identify unverified users', () => {
const unverifiedUser: User = {
address: 'user2',
walletType: 'ethereum',
verificationStatus: 'unverified',
ensOwnership: false,
lastChecked: Date.now()
};
const isVerified = calculator.isUserVerified(unverifiedUser);
expect(isVerified).toBe(false);
});
it('should apply moderation penalty', () => {
const post: Post = {
id: '1',
cellId: 'cell1',
authorAddress: 'user2',
title: 'Test Post',
content: 'Test content',
timestamp: Date.now(),
upvotes: [],
downvotes: [],
moderated: true
};
const result = calculator.calculatePostScore(post, [], [], mockUserVerificationStatus);
expect(result.details.isModerated).toBe(true);
expect(result.details.moderationPenalty).toBe(0.5);
});
it('should calculate engagement bonuses', () => {
const post: Post = {
id: '1',
cellId: 'cell1',
authorAddress: 'user2',
title: 'Test Post',
content: 'Test content',
timestamp: Date.now(),
upvotes: [],
downvotes: []
};
const votes: VoteMessage[] = [
{ id: 'vote1', targetId: '1', value: 1, author: 'user1', timestamp: Date.now(), type: MessageType.VOTE },
{ id: 'vote2', targetId: '1', value: 1, author: 'user3', timestamp: Date.now(), type: MessageType.VOTE }
];
const comments: Comment[] = [
{ id: 'comment1', postId: '1', authorAddress: 'user1', content: 'Test comment', timestamp: Date.now(), upvotes: [], downvotes: [] }
];
const result = calculator.calculatePostScore(post, votes, comments, mockUserVerificationStatus);
expect(result.details.upvotes).toBe(2);
expect(result.details.comments).toBe(1);
expect(result.details.verifiedUpvotes).toBe(2);
expect(result.details.verifiedCommenters).toBe(1);
});
});
describe('timeDecay', () => {
it('should apply time decay to older posts', () => {
const now = Date.now();
const oneDayAgo = now - (24 * 60 * 60 * 1000);
const oneWeekAgo = now - (7 * 24 * 60 * 60 * 1000);
const recentPost: Post = {
id: '1',
cellId: 'cell1',
authorAddress: 'user2',
title: 'Recent Post',
content: 'Recent content',
timestamp: now,
upvotes: [],
downvotes: []
};
const oldPost: Post = {
id: '2',
cellId: 'cell1',
authorAddress: 'user2',
title: 'Old Post',
content: 'Old content',
timestamp: oneWeekAgo,
upvotes: [],
downvotes: []
};
const recentResult = calculator.calculatePostScore(recentPost, [], [], mockUserVerificationStatus);
const oldResult = calculator.calculatePostScore(oldPost, [], [], mockUserVerificationStatus);
expect(recentResult.score).toBeGreaterThan(oldResult.score);
});
});
describe('buildUserVerificationStatus', () => {
it('should correctly build verification status map from users array', () => {
const users: User[] = [
{
address: 'user1',
walletType: 'ethereum',
verificationStatus: 'verified-owner',
ensOwnership: true,
ensName: 'test.eth',
lastChecked: Date.now()
},
{
address: 'user2',
walletType: 'bitcoin',
verificationStatus: 'unverified',
ordinalOwnership: false,
lastChecked: Date.now()
}
];
const status = calculator.buildUserVerificationStatus(users);
expect(status['user1'].isVerified).toBe(true);
expect(status['user1'].hasENS).toBe(true);
expect(status['user1'].hasOrdinal).toBe(false);
expect(status['user2'].isVerified).toBe(false);
expect(status['user2'].hasENS).toBe(false);
expect(status['user2'].hasOrdinal).toBe(false);
});
});
});