Files
5chan/src/lib/utils/__tests__/pattern-utils.test.ts
T

124 lines
4.8 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
const testState = vi.hoisted(() => ({
consoleErrorMock: vi.fn(),
communities: {} as Record<string, { roles?: Record<string, { role?: string }> }>,
}));
vi.mock('@bitsocial/bitsocial-react-hooks/dist/stores/communities', () => ({
default: {
getState: () => ({
communities: testState.communities,
}),
},
}));
import { commentMatchesPattern, displayNameMatchesPattern, matchesPattern, parsePattern, userHasRole, userIdMatchesPattern } from '../pattern-utils';
describe('pattern-utils', () => {
let consoleErrorSpy: ReturnType<typeof vi.spyOn>;
beforeEach(() => {
vi.clearAllMocks();
testState.communities = {
'music-posting.eth': {
roles: {
'author-1': { role: 'moderator' },
'author-2': { role: 'owner' },
},
},
};
consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(testState.consoleErrorMock);
});
afterEach(() => {
consoleErrorSpy.mockRestore();
});
it('matches whole words, exact phrases, regexes, wildcards, and logical operators', () => {
expect(matchesPattern('That feel when the girlfriend texts back', 'feel')).toBe(true);
expect(matchesPattern('That feel when the girlfriend texts back', 'feels')).toBe(false);
expect(matchesPattern('That feel when the girlfriend texts back', 'feel girlfriend')).toBe(true);
expect(matchesPattern('That feel when the girlfriend texts back', 'girlfriend|boyfriend feel')).toBe(true);
expect(matchesPattern('That feel when the girlfriend texts back', '"feel when the girlfriend"')).toBe(true);
expect(matchesPattern('That feeling stays forever', 'feel*')).toBe(true);
expect(matchesPattern('MIXED Case Example', '/mixed case example/i')).toBe(true);
});
it('falls back to a simple include when pattern parsing throws', () => {
expect(matchesPattern('the broken marker foo(', 'foo(')).toBe(true);
expect(consoleErrorSpy).toHaveBeenCalled();
});
it('matches user ids through full and short addresses', () => {
const comment = {
author: {
address: '12D3KooWabcdef',
shortAddress: '12D3KooWabc',
},
};
expect(userIdMatchesPattern(comment as never, 'abcdef')).toBe(true);
expect(userIdMatchesPattern(comment as never, '12D3KooWabc')).toBe(true);
expect(userIdMatchesPattern(comment as never, 'missing')).toBe(false);
});
it('matches display names case-insensitively and treats anonymous as undefined display names', () => {
expect(displayNameMatchesPattern({ author: { displayName: 'Alice' } } as never, 'alice')).toBe(true);
expect(displayNameMatchesPattern({ author: {} } as never, 'anonymous')).toBe(true);
expect(displayNameMatchesPattern({ author: { displayName: 'Bob' } } as never, 'anonymous')).toBe(false);
});
it('matches roles with moderator aliases and rejects missing role metadata', () => {
const modComment = {
author: { address: 'author-1' },
communityAddress: 'music-posting.eth',
};
const ownerComment = {
author: { address: 'author-2' },
communityAddress: 'music-posting.eth',
};
expect(userHasRole(modComment as never, 'moderator')).toBe(true);
expect(userHasRole(modComment as never, 'mod')).toBe(true);
expect(userHasRole(ownerComment as never, 'owner')).toBe(true);
expect(userHasRole(ownerComment as never, 'admin')).toBe(false);
expect(userHasRole({ author: { address: 'missing' }, communityAddress: 'unknown.eth' } as never, 'moderator')).toBe(false);
});
it('parses mixed special filters and content filters', () => {
expect(parsePattern('#abc ##Alice #!#mod exact phrase')).toEqual({
contentFilter: 'exact phrase',
specialFilters: [
{ type: 'userId', value: 'abc' },
{ type: 'displayName', value: 'Alice' },
{ type: 'role', value: 'mod' },
],
});
expect(parsePattern('')).toEqual({
contentFilter: '',
specialFilters: [],
});
});
it('matches comments against combined special filters and content filters', () => {
const comment = {
author: {
address: 'author-1',
displayName: 'Alice',
shortAddress: 'auth1',
},
content: 'That feel when the girlfriend texts back',
communityAddress: 'music-posting.eth',
title: 'TFW',
};
expect(commentMatchesPattern(comment as never, '#auth1 ##Alice #!#moderator girlfriend')).toBe(true);
expect(commentMatchesPattern(comment as never, '#auth1 ##Bob #!#moderator girlfriend')).toBe(false);
expect(commentMatchesPattern(comment as never, '#auth1')).toBe(true);
expect(commentMatchesPattern(comment as never, '##Alice')).toBe(true);
expect(commentMatchesPattern(comment as never, '#!#mod')).toBe(true);
expect(commentMatchesPattern(comment as never, 'tfw girlfriend')).toBe(true);
});
});