import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; const testState = vi.hoisted(() => ({ consoleErrorMock: vi.fn(), communities: {} as Record }>, })); 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; 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); }); });