damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

ReplyTests.swift (14641B)


      1 //
      2 //  ReplyTests.swift
      3 //  damusTests
      4 //
      5 //  Created by William Casarin on 2022-05-08.
      6 //
      7 
      8 import XCTest
      9 @testable import damus
     10 
     11 class ReplyTests: XCTestCase {
     12 
     13     override func setUpWithError() throws {
     14         // Put setup code here. This method is called before the invocation of each test method in the class.
     15     }
     16 
     17     override func tearDownWithError() throws {
     18         // Put teardown code here. This method is called after the invocation of each test method in the class.
     19     }
     20     
     21     func testAtAtEnd() {
     22         let content = "what @"
     23         let blocks = parse_post_blocks(content: content)
     24         
     25         XCTAssertEqual(blocks.count, 1)
     26         XCTAssertEqual(blocks[0].asText, "what @")
     27     }
     28     
     29     func testHashtagsInQuote() {
     30         let content = "This is my \"#awesome post\""
     31         let blocks = parse_post_blocks(content: content)
     32         
     33         XCTAssertEqual(blocks.count, 3)
     34         XCTAssertEqual(blocks[0].asText, "This is my \"")
     35         XCTAssertEqual(blocks[1].asHashtag, "awesome")
     36         XCTAssertEqual(blocks[2].asText, " post\"")
     37     }
     38     
     39     func testHashtagAtStartWorks() {
     40         let content = "#hashtag"
     41         let blocks = parse_post_blocks(content: content)
     42         XCTAssertEqual(blocks.count, 1)
     43         XCTAssertEqual(blocks[0].asHashtag, "hashtag")
     44     }
     45     
     46     func testGroupOfHashtags() {
     47         let content = "#hashtag#what#nope"
     48         let blocks = parse_post_blocks(content: content)
     49         XCTAssertEqual(blocks.count, 3)
     50         XCTAssertEqual(blocks[0].asHashtag, "hashtag")
     51         XCTAssertEqual(blocks[1].asHashtag, "what")
     52         XCTAssertEqual(blocks[2].asHashtag, "nope")
     53     }
     54     
     55     func testEmptyMention() throws {
     56         let content = "this is some & content"
     57         let ev = NostrEvent(content: content, keypair: test_keypair, tags: [])!
     58         let blocks = parse_note_content(content: .init(note: ev, keypair: test_keypair)).blocks
     59         let post_blocks = parse_post_blocks(content: content)
     60         let post = NostrPost(content: content, kind: NostrKind.text, tags: [])
     61         let post_tags = post.make_post_tags(post_blocks: post_blocks, tags: [])
     62         let tr = interpret_event_refs(tags: ev.tags)
     63 
     64         XCTAssertNil(tr)
     65         XCTAssertEqual(post_tags.blocks.count, 1)
     66         XCTAssertEqual(post_tags.tags.count, 0)
     67         XCTAssertEqual(post_blocks.count, 1)
     68     }
     69 
     70     func testNewlineMentions() throws {
     71         let bech32_pk = "npub1xtscya34g58tk0z605fvr788k263gsu6cy9x0mhnm87echrgufzsevkk5s"
     72         let pk = bech32_pubkey_decode(bech32_pk)!
     73 
     74         let profile = Profile(name: "jb55")
     75         let post = user_tag_attr_string(profile: profile, pubkey: pk)
     76         post.append(.init(string: "\n"))
     77         post.append(user_tag_attr_string(profile: profile, pubkey: pk))
     78         post.append(.init(string: "\n"))
     79 
     80         let post_note = build_post(state: test_damus_state, post: post, action: .posting(.none), uploadedMedias: [], pubkeys: [pk])
     81 
     82         let expected_render = "nostr:\(pk.npub)\nnostr:\(pk.npub)"
     83         XCTAssertEqual(post_note.content, expected_render)
     84 
     85         let blocks = parse_note_content(content: .content(post_note.content,nil)).blocks
     86         let rendered = blocks.map { $0.asString }.joined(separator: "")
     87 
     88         XCTAssertEqual(rendered, expected_render)
     89 
     90         XCTAssertEqual(blocks.count, 3)
     91         XCTAssertEqual(blocks[0].asMention, Mention<MentionRef>.any(.pubkey(pk)))
     92         XCTAssertEqual(blocks[1].asText, "\n")
     93         XCTAssertEqual(blocks[2].asMention, Mention<MentionRef>.any(.pubkey(pk)))
     94     }
     95     
     96     func testThreadedReply() throws {
     97         let content = "this is some content"
     98         let thread_id = NoteId(hex: "da256fb52146dc565c6c6b9ef906117c665864dc02b14a7b853eca244729c2f2")!
     99         let reply_id = NoteId(hex: "80093e9bdb495728f54cda2bad4aed096877189552b3d41264e73b9a9595be22")!
    100         let tags = [thread_id.tag, reply_id.tag]
    101         let ev = NostrEvent(content: content, keypair: test_keypair, tags: tags)!
    102         let tr = interpret_event_refs(tags: ev.tags)
    103         XCTAssertNotNil(tr)
    104         guard let tr else { return }
    105 
    106         XCTAssertEqual(tr.root.note_id, thread_id)
    107         XCTAssertEqual(tr.reply.note_id, reply_id)
    108     }
    109     
    110     func testRootReply() throws {
    111         let content = "this is a reply"
    112         let thread_id = NoteId(hex: "53f60f5114c06f069ffe9da2bc033e533d09cae44d37a8462154a663771a4ce6")!
    113         let tags = [thread_id.tag]
    114         let ev = NostrEvent(content: content, keypair: test_keypair, tags: tags)!
    115         let tr = interpret_event_refs(tags: ev.tags)
    116 
    117         XCTAssertNotNil(tr)
    118         guard let tr else { return }
    119 
    120         XCTAssertEqual(tr.root.note_id, thread_id)
    121         XCTAssertEqual(tr.reply.note_id, thread_id)
    122         XCTAssertNil(tr.mention)
    123     }
    124 
    125     func testAdjacentComposedMention() throws {
    126         let content = "cc@jb55"
    127 
    128         let profile = Profile(name: "jb55")
    129         let tag = user_tag_attr_string(profile: profile, pubkey: test_pubkey)
    130         let appended = append_user_tag(tag: tag, post: .init(string: content), word_range: .init(2...6))
    131         let new_post = appended.post
    132 
    133         try new_post.testAttributes(conditions: [
    134             { let link = $0[.link] as? String; XCTAssertNil(link) },
    135             { let link = $0[.link] as! String; XCTAssertEqual(link, "damus:nostr:\(test_pubkey.npub)") },
    136             { let link = $0[.link] as? String; XCTAssertNil(link) }
    137         ])
    138 
    139         XCTAssertEqual(new_post.string, "cc @jb55 ")
    140     }
    141 
    142     func testAdjacentEmojiComposedMention() throws {
    143         let content = "😎@jb55"
    144 
    145         let profile = Profile(name: "jb55")
    146         let tag = user_tag_attr_string(profile: profile, pubkey: test_pubkey)
    147         let appended = append_user_tag(tag: tag, post: .init(string: content), word_range: .init(2...6))
    148         let new_post = appended.post
    149 
    150         try new_post.testAttributes(conditions: [
    151             { let link = $0[.link] as? String; XCTAssertNil(link) },
    152             { let link = $0[.link] as! String; XCTAssertEqual(link, "damus:nostr:\(test_pubkey.npub)") },
    153             { let link = $0[.link] as? String; XCTAssertNil(link) }
    154         ])
    155 
    156         XCTAssertEqual(new_post.string, "😎 @jb55 ")
    157     }
    158 
    159     func testComposedMentionNewline() throws {
    160         let content = """
    161         
    162         @jb55
    163         """
    164 
    165         let profile = Profile(name: "jb55")
    166         let tag = user_tag_attr_string(profile: profile, pubkey: test_pubkey)
    167         let appended = append_user_tag(tag: tag, post: .init(string: content), word_range: .init(1...5))
    168         let new_post = appended.post
    169 
    170         try new_post.testAttributes(conditions: [
    171             { let link = $0[.link] as? String; XCTAssertNil(link) },
    172             { let link = $0[.link] as! String; XCTAssertEqual(link, "damus:nostr:\(test_pubkey.npub)") },
    173             { let link = $0[.link] as? String; XCTAssertNil(link) },
    174         ])
    175 
    176         XCTAssertEqual(new_post.string, "\n@jb55 ")
    177     }
    178 
    179     func testComposedMention() throws {
    180         let content = "@jb55"
    181 
    182         let profile = Profile(name: "jb55")
    183         let tag = user_tag_attr_string(profile: profile, pubkey: test_pubkey)
    184         let appended = append_user_tag(tag: tag, post: .init(string: content), word_range: .init(0...4))
    185         let new_post = appended.post
    186 
    187         try new_post.testAttributes(conditions: [
    188             { let link = $0[.link] as! String; XCTAssertEqual(link, "damus:nostr:\(test_pubkey.npub)") },
    189             { let link = $0[.link] as? String; XCTAssertNil(link) },
    190         ])
    191 
    192         XCTAssertEqual(new_post.string, "@jb55 ")
    193     }
    194 
    195     func testAdjacentSpaceComposedMention() throws {
    196         let content = "cc @jb55"
    197 
    198         let profile = Profile(name: "jb55")
    199         let tag = user_tag_attr_string(profile: profile, pubkey: test_pubkey)
    200         let appended = append_user_tag(tag: tag, post: .init(string: content), word_range: .init(3...7))
    201         let new_post = appended.post
    202 
    203         try new_post.testAttributes(conditions: [
    204             { let link = $0[.link] as? String; XCTAssertNil(link) },
    205             { let link = $0[.link] as! String; XCTAssertEqual(link, "damus:nostr:\(test_pubkey.npub)") },
    206             { let link = $0[.link] as? String; XCTAssertNil(link) }
    207         ])
    208 
    209         XCTAssertEqual(new_post.string, "cc @jb55 ")
    210     }
    211 
    212     func testEmptyPostReference() throws {
    213         let parsed = parse_post_blocks(content: "")
    214         XCTAssertEqual(parsed.count, 0)
    215     }
    216     
    217     func testBech32MentionAtStart() throws {
    218         let pk = Pubkey(hex: "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245")!
    219         let content = "@\(pk.npub) hello there"
    220         let blocks = parse_post_blocks(content: content)
    221         
    222         XCTAssertEqual(blocks.count, 2)
    223         XCTAssertEqual(blocks[0].asMention, .any(.pubkey(pk)))
    224         XCTAssertEqual(blocks[1].asText, " hello there")
    225 
    226     }
    227     
    228     func testBech32MentionAtEnd() throws {
    229         let pk = Pubkey(hex: "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245")!
    230         let content = "this is a @\(pk.npub)"
    231         let blocks = parse_post_blocks(content: content)
    232         
    233         XCTAssertEqual(blocks.count, 2)
    234         XCTAssertEqual(blocks[1].asMention, .any(.pubkey(pk)))
    235         XCTAssertEqual(blocks[0].asText, "this is a ")
    236     }
    237     
    238     func testNpubMention() throws {
    239         let evid = NoteId(hex: "71ba3e5ddaf48103be294aa370e470fb60b6c8bca3fb01706eecd00054c2f588")!
    240         let pk = Pubkey(hex: "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245")!
    241         let content = "this is a @\(pk.npub) mention"
    242         let blocks = parse_post_blocks(content: content)
    243         let post = NostrPost(content: content, tags: [["e", evid.hex()]])
    244         let ev = post.to_event(keypair: test_keypair_full)!
    245 
    246         XCTAssertEqual(ev.tags.count, 2)
    247         XCTAssertEqual(blocks.count, 3)
    248         XCTAssertEqual(blocks[1].asMention, .any(.pubkey(pk)))
    249         XCTAssertEqual(ev.content, "this is a nostr:npub1xtscya34g58tk0z605fvr788k263gsu6cy9x0mhnm87echrgufzsevkk5s mention")
    250     }
    251     
    252     func testNsecMention() throws {
    253         let evid = NoteId(hex: "71ba3e5ddaf48103be294aa370e470fb60b6c8bca3fb01706eecd00054c2f588")!
    254         let pk = Pubkey(hex: "ccf95d668650178defca5ac503693b6668eb77895f610178ff8ed9fe5cf9482e")!
    255         let nsec = "nsec1jmzdz7d0ldqctdxwm5fzue277ttng2pk28n2u8wntc2r4a0w96ssnyukg7"
    256         let content = "this is a @\(nsec) mention"
    257         let blocks = parse_post_blocks(content: content)
    258         let post = NostrPost(content: content, tags: [["e", evid.hex()]])
    259         let ev = post.to_event(keypair: test_keypair_full)!
    260 
    261         XCTAssertEqual(ev.tags.count, 2)
    262         XCTAssertEqual(blocks.count, 3)
    263         XCTAssertEqual(blocks[1].asMention, .any(.pubkey(pk)))
    264         XCTAssertEqual(ev.content, "this is a nostr:npub1enu46e5x2qtcmm72ttzsx6fmve5wkauftassz78l3mvluh8efqhqejf3v4 mention")
    265     }
    266     
    267     func testReplyMentions() throws {
    268         let pubkey  = Pubkey(hex: "30c6d1dc7f7c156794fa15055e651b758a61b99f50fcf759de59386050bf6ae2")!
    269         let thread_id = NoteId(hex: "a250fc93570c3e87f9c9b08d6b3ef7b8e05d346df8a52c69e30ffecdb178fb9e")!
    270         let reply_id = NoteId(hex: "9a180a10f16dac9566543ad1fc29616aab272b0cf123ab5d58843e16f4ef03a3")!
    271 
    272         let tags = [
    273             ["e", thread_id.hex()],
    274             ["e", reply_id.hex()],
    275             ["p", pubkey.hex()]
    276         ]
    277 
    278         let post = NostrPost(content: "this is a (@\(pubkey.npub)) mention", tags: tags)
    279         let ev = post.to_event(keypair: test_keypair_full)!
    280         
    281         XCTAssertEqual(ev.content, "this is a (nostr:\(pubkey.npub)) mention")
    282         XCTAssertEqual(ev.tags[2][1].string(), pubkey.description)
    283     }
    284     
    285     func testInvalidPostReference() throws {
    286         let pk = "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e24"
    287         let content = "this is a @\(pk) mention"
    288         let parsed = parse_post_blocks(content: content)
    289         XCTAssertEqual(parsed.count, 1)
    290         guard case .text(let txt) = parsed[0] else {
    291             XCTAssert(false)
    292             return
    293         }
    294         XCTAssertEqual(txt, content)
    295     }
    296     
    297     func testInvalidPostReferenceEmptyAt() throws {
    298         let content = "this is a @ mention"
    299         let parsed = parse_post_blocks(content: content)
    300         XCTAssertEqual(parsed.count, 1)
    301         guard case .text(let txt) = parsed[0] else {
    302             XCTAssert(false)
    303             return
    304         }
    305         XCTAssertEqual(txt, content)
    306     }
    307     
    308     func testInvalidUriReference() throws {
    309         let id = "6fec2ee6cfff779fe8560976b3d9df782b74577f0caefa7a77c0ed4c3749b5de"
    310         let content = "this is a nostr:z:\(id) event mention"
    311         let parsed = parse_post_blocks(content: content)
    312         
    313         XCTAssertNotNil(parsed)
    314         XCTAssertEqual(parsed.count, 1)
    315         
    316         guard case .text(let txt) = parsed[0] else {
    317             XCTAssertTrue(false)
    318             return
    319         }
    320         
    321         XCTAssertEqual(txt, content)
    322     }
    323     
    324     func testParsePostUriPubkeyReference() throws {
    325         let id = Pubkey(hex: "6fec2ee6cfff779fe8560976b3d9df782b74577f0caefa7a77c0ed4c3749b5de")!
    326         let parsed = parse_post_blocks(content: "this is a nostr:\(id.npub) event mention")
    327 
    328         XCTAssertNotNil(parsed)
    329         XCTAssertEqual(parsed.count, 3)
    330         XCTAssertEqual(parsed[0].asText, "this is a ")
    331         XCTAssertEqual(parsed[1].asMention, .any(.pubkey(id)))
    332         XCTAssertEqual(parsed[2].asText, " event mention")
    333         
    334         guard case .text(let t1) = parsed[0] else {
    335             XCTAssertTrue(false)
    336             return
    337         }
    338         XCTAssertEqual(t1, "this is a ")
    339         
    340         guard case .text(let t2) = parsed[2] else {
    341             XCTAssertTrue(false)
    342             return
    343         }
    344         XCTAssertEqual(t2, " event mention")
    345     }
    346     
    347     func testParsePostUriReference() throws {
    348         let id = NoteId(hex: "6fec2ee6cfff779fe8560976b3d9df782b74577f0caefa7a77c0ed4c3749b5de")!
    349         let parsed = parse_post_blocks(content: "this is a nostr:\(id.bech32) event mention")
    350 
    351         XCTAssertNotNil(parsed)
    352         XCTAssertEqual(parsed.count, 3)
    353         XCTAssertEqual(parsed[0].asText, "this is a ")
    354         XCTAssertEqual(parsed[1].asMention, .any(.note(id)))
    355         XCTAssertEqual(parsed[2].asText, " event mention")
    356 
    357         guard case .text(let t1) = parsed[0] else {
    358             XCTAssertTrue(false)
    359             return
    360         }
    361         XCTAssertEqual(t1, "this is a ")
    362         
    363         guard case .text(let t2) = parsed[2] else {
    364             XCTAssertTrue(false)
    365             return
    366         }
    367         XCTAssertEqual(t2, " event mention")
    368     }
    369     
    370 }