NoteContent.test.tsx
1 import { describe, it, expect } from 'vitest'; 2 import { render, screen } from '@testing-library/react'; 3 import { TestApp } from '@/test/TestApp'; 4 import { NoteContent } from './NoteContent'; 5 import type { NostrEvent } from '@nostrify/nostrify'; 6 7 describe('NoteContent', () => { 8 it('linkifies URLs in kind 1 events', () => { 9 const event: NostrEvent = { 10 id: 'test-id', 11 pubkey: 'test-pubkey', 12 created_at: Math.floor(Date.now() / 1000), 13 kind: 1, 14 tags: [], 15 content: 'Check out this link: https://example.com', 16 sig: 'test-sig', 17 }; 18 19 render( 20 <TestApp> 21 <NoteContent event={event} /> 22 </TestApp> 23 ); 24 25 const link = screen.getByRole('link', { name: 'https://example.com' }); 26 expect(link).toBeInTheDocument(); 27 expect(link).toHaveAttribute('href', 'https://example.com'); 28 expect(link).toHaveAttribute('target', '_blank'); 29 }); 30 31 it('linkifies URLs in kind 1111 events (comments)', () => { 32 const event: NostrEvent = { 33 id: 'test-comment-id', 34 pubkey: 'test-pubkey', 35 created_at: Math.floor(Date.now() / 1000), 36 kind: 1111, 37 tags: [ 38 ['a', '30040:pubkey:identifier'], 39 ['k', '30040'], 40 ['p', 'pubkey'], 41 ], 42 content: 'I think the log events should be different kind numbers instead of having a `log-type` tag. That way you can use normal Nostr filters to filter the log types. Also, the `note` type should just b a kind 1111: https://nostrbook.dev/kinds/1111', 43 sig: 'test-sig', 44 }; 45 46 render( 47 <TestApp> 48 <NoteContent event={event} /> 49 </TestApp> 50 ); 51 52 const link = screen.getByRole('link', { name: 'https://nostrbook.dev/kinds/1111' }); 53 expect(link).toBeInTheDocument(); 54 expect(link).toHaveAttribute('href', 'https://nostrbook.dev/kinds/1111'); 55 expect(link).toHaveAttribute('target', '_blank'); 56 }); 57 58 it('handles text without URLs correctly', () => { 59 const event: NostrEvent = { 60 id: 'test-id', 61 pubkey: 'test-pubkey', 62 created_at: Math.floor(Date.now() / 1000), 63 kind: 1111, 64 tags: [], 65 content: 'This is just plain text without any links.', 66 sig: 'test-sig', 67 }; 68 69 render( 70 <TestApp> 71 <NoteContent event={event} /> 72 </TestApp> 73 ); 74 75 expect(screen.getByText('This is just plain text without any links.')).toBeInTheDocument(); 76 expect(screen.queryByRole('link')).not.toBeInTheDocument(); 77 }); 78 79 it('renders hashtags as links', () => { 80 const event: NostrEvent = { 81 id: 'test-id', 82 pubkey: 'test-pubkey', 83 created_at: Math.floor(Date.now() / 1000), 84 kind: 1, 85 tags: [], 86 content: 'This is a post about #nostr and #bitcoin development.', 87 sig: 'test-sig', 88 }; 89 90 render( 91 <TestApp> 92 <NoteContent event={event} /> 93 </TestApp> 94 ); 95 96 const nostrHashtag = screen.getByRole('link', { name: '#nostr' }); 97 const bitcoinHashtag = screen.getByRole('link', { name: '#bitcoin' }); 98 99 expect(nostrHashtag).toBeInTheDocument(); 100 expect(bitcoinHashtag).toBeInTheDocument(); 101 expect(nostrHashtag).toHaveAttribute('href', '/t/nostr'); 102 expect(bitcoinHashtag).toHaveAttribute('href', '/t/bitcoin'); 103 }); 104 105 it('generates deterministic names for users without metadata and styles them differently', () => { 106 // Use a valid npub for testing 107 const event: NostrEvent = { 108 id: 'test-id', 109 pubkey: 'test-pubkey', 110 created_at: Math.floor(Date.now() / 1000), 111 kind: 1, 112 tags: [], 113 content: `Mentioning nostr:npub1zg69v7ys40x77y352eufp27daufrg4ncjz4ummcjx3t83y9tehhsqepuh0`, 114 sig: 'test-sig', 115 }; 116 117 render( 118 <TestApp> 119 <NoteContent event={event} /> 120 </TestApp> 121 ); 122 123 // The mention should be rendered with a deterministic name 124 const mention = screen.getByRole('link'); 125 expect(mention).toBeInTheDocument(); 126 127 // Should have muted styling for generated names (gray instead of blue) 128 expect(mention).toHaveClass('text-gray-500'); 129 expect(mention).not.toHaveClass('text-blue-500'); 130 131 // The text should start with @ and contain a generated name (not a truncated npub) 132 const linkText = mention.textContent; 133 expect(linkText).not.toMatch(/^@npub1/); // Should not be a truncated npub 134 expect(linkText).toEqual("@Swift Falcon"); 135 }); 136 });