18 changed files with 432 additions and 127 deletions
@ -0,0 +1,77 @@
@@ -0,0 +1,77 @@
|
||||
import { describe, expect, it } from 'vitest' |
||||
import { kinds } from 'nostr-tools' |
||||
import { eventMatchesTopicOrContentHashtag, formatTopicMapBubbleLabel, isValidNormalizedTopicKey, normalizedKeyMatchesHashtagPattern, normalizeTopic, relayTopicTagFilterValues } from '@/lib/discussion-topics' |
||||
|
||||
describe('eventMatchesTopicOrContentHashtag', () => { |
||||
it('matches normalized t tags', () => { |
||||
const ev = { |
||||
kind: kinds.ShortTextNote, |
||||
tags: [['t', 'catholic']], |
||||
content: 'hello', |
||||
id: 'a'.repeat(64), |
||||
pubkey: 'b'.repeat(64), |
||||
sig: 'c'.repeat(128), |
||||
created_at: 1 |
||||
} |
||||
expect(eventMatchesTopicOrContentHashtag(ev, 'catholic')).toBe(true) |
||||
}) |
||||
|
||||
it('matches #hashtag in content', () => { |
||||
const ev = { |
||||
kind: kinds.ShortTextNote, |
||||
tags: [], |
||||
content: 'Prayers for the #catholic church today', |
||||
id: 'a'.repeat(64), |
||||
pubkey: 'b'.repeat(64), |
||||
sig: 'c'.repeat(128), |
||||
created_at: 1 |
||||
} |
||||
expect(eventMatchesTopicOrContentHashtag(ev, 'catholic')).toBe(true) |
||||
}) |
||||
|
||||
it('rejects plain text without t tag or #hashtag', () => { |
||||
const ev = { |
||||
kind: kinds.ShortTextNote, |
||||
tags: [], |
||||
content: 'That catholic school is weird', |
||||
id: 'a'.repeat(64), |
||||
pubkey: 'b'.repeat(64), |
||||
sig: 'c'.repeat(128), |
||||
created_at: 1 |
||||
} |
||||
expect(eventMatchesTopicOrContentHashtag(ev, 'catholic')).toBe(false) |
||||
}) |
||||
}) |
||||
|
||||
describe('isValidNormalizedTopicKey', () => { |
||||
it('accepts normalized topic keys', () => { |
||||
expect(isValidNormalizedTopicKey('nostr')).toBe(true) |
||||
expect(isValidNormalizedTopicKey('grownostr')).toBe(true) |
||||
}) |
||||
|
||||
it('rejects empty, numeric-only, and invalid characters', () => { |
||||
expect(isValidNormalizedTopicKey('')).toBe(false) |
||||
expect(isValidNormalizedTopicKey('123')).toBe(false) |
||||
expect(isValidNormalizedTopicKey('-bad')).toBe(false) |
||||
}) |
||||
}) |
||||
|
||||
describe('formatTopicMapBubbleLabel', () => { |
||||
it('shows readable text without a hash prefix', () => { |
||||
expect(formatTopicMapBubbleLabel('decent-newsroom')).toBe('decent newsroom') |
||||
expect(formatTopicMapBubbleLabel('nostr')).toBe('nostr') |
||||
}) |
||||
}) |
||||
|
||||
describe('relayTopicTagFilterValues', () => { |
||||
it('includes plural t-tag variants for singularized map keys', () => { |
||||
expect(relayTopicTagFilterValues('jesu')).toEqual(expect.arrayContaining(['jesu', 'jesus'])) |
||||
}) |
||||
}) |
||||
|
||||
describe('normalizedKeyMatchesHashtagPattern', () => { |
||||
it('matches valid ascii hashtag bodies', () => { |
||||
expect(normalizedKeyMatchesHashtagPattern('imwald')).toBe(true) |
||||
expect(normalizedKeyMatchesHashtagPattern('')).toBe(false) |
||||
}) |
||||
}) |
||||
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
import { describe, expect, it } from 'vitest' |
||||
import { kinds } from 'nostr-tools' |
||||
import { DEFAULT_FEED_SHOW_KINDS } from '@/constants' |
||||
import { buildTopicKeywordBubbles } from './TopicKeywordHeatMap' |
||||
|
||||
function note(pubkey: string, tags: string[][], content = '') { |
||||
return { |
||||
kind: kinds.ShortTextNote, |
||||
pubkey, |
||||
content, |
||||
tags, |
||||
id: `${pubkey.slice(0, 8)}${'a'.repeat(56)}`, |
||||
sig: 'b'.repeat(128), |
||||
created_at: 1_700_000_000 |
||||
} |
||||
} |
||||
|
||||
describe('buildTopicKeywordBubbles', () => { |
||||
it('ranks pubkeys by how often they used the topic', () => { |
||||
const pkA = 'a'.repeat(64) |
||||
const pkB = 'b'.repeat(64) |
||||
const pkC = 'c'.repeat(64) |
||||
const bubbles = buildTopicKeywordBubbles( |
||||
[ |
||||
note(pkA, [['t', 'nostr']]), |
||||
note(pkA, [['t', 'nostr']]), |
||||
note(pkB, [['t', 'nostr']]), |
||||
note(pkC, [], 'hello #nostr'), |
||||
note(pkC, [], 'again #nostr') |
||||
], |
||||
DEFAULT_FEED_SHOW_KINDS, |
||||
true, |
||||
true, |
||||
true |
||||
) |
||||
const nostr = bubbles.find((b) => b.key === 'nostr') |
||||
expect(nostr?.pubkeys[0]).toBe(pkA) |
||||
expect(nostr?.pubkeys).toContain(pkC) |
||||
expect(nostr?.pubkeys).toContain(pkB) |
||||
}) |
||||
}) |
||||
Loading…
Reference in new issue