diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj index 84ecdfc8..c1ec36ec 100644 --- a/damus.xcodeproj/project.pbxproj +++ b/damus.xcodeproj/project.pbxproj @@ -1756,6 +1756,7 @@ D7EB00B12CD59C8D00660C07 /* PresentFullScreenItemNotify.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7EB00AF2CD59C8300660C07 /* PresentFullScreenItemNotify.swift */; }; D7EBF8BB2E59022A004EAE29 /* NostrNetworkManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7EBF8BA2E5901F7004EAE29 /* NostrNetworkManagerTests.swift */; }; D7EBF8BE2E59470D004EAE29 /* test_notes.jsonl in Resources */ = {isa = PBXBuildFile; fileRef = D7EBF8BD2E594708004EAE29 /* test_notes.jsonl */; }; + D7EBF8C02E5D39DC004EAE29 /* ThreadModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7EBF8BF2E5D39D1004EAE29 /* ThreadModelTests.swift */; }; D7EDED152B11776B0018B19C /* LibreTranslateServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE45AF5297BB2E700C1D842 /* LibreTranslateServer.swift */; }; D7EDED162B1177840018B19C /* LNUrls.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB883B5297730E400DC99E7 /* LNUrls.swift */; }; D7EDED172B1177960018B19C /* TranslationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AAA95C9298DF87B00F3D526 /* TranslationService.swift */; }; @@ -2692,6 +2693,7 @@ D7EB00AF2CD59C8300660C07 /* PresentFullScreenItemNotify.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PresentFullScreenItemNotify.swift; sourceTree = ""; }; D7EBF8BA2E5901F7004EAE29 /* NostrNetworkManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NostrNetworkManagerTests.swift; sourceTree = ""; }; D7EBF8BD2E594708004EAE29 /* test_notes.jsonl */ = {isa = PBXFileReference; lastKnownFileType = text; path = test_notes.jsonl; sourceTree = ""; }; + D7EBF8BF2E5D39D1004EAE29 /* ThreadModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadModelTests.swift; sourceTree = ""; }; D7EDED1B2B1178FE0018B19C /* NoteContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoteContent.swift; sourceTree = ""; }; D7EDED1D2B11797D0018B19C /* LongformEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LongformEvent.swift; sourceTree = ""; }; D7EDED202B117DCA0018B19C /* SequenceUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SequenceUtils.swift; sourceTree = ""; }; @@ -5001,6 +5003,7 @@ children = ( D7EBF8BD2E594708004EAE29 /* test_notes.jsonl */, D7EBF8BA2E5901F7004EAE29 /* NostrNetworkManagerTests.swift */, + D7EBF8BF2E5D39D1004EAE29 /* ThreadModelTests.swift */, ); path = NostrNetworkManagerTests; sourceTree = ""; @@ -5934,6 +5937,7 @@ 4C9B0DEE2A65A75F00CBDA21 /* AttrStringTestExtensions.swift in Sources */, 4C19AE552A5D977400C90DB7 /* HashtagTests.swift in Sources */, D72927AD2BAB515C00F93E90 /* RelayURLTests.swift in Sources */, + D7EBF8C02E5D39DC004EAE29 /* ThreadModelTests.swift in Sources */, 4C0ED07F2D7A1E260020D8A2 /* Benchmarking.swift in Sources */, 3A3040ED29A5CB86008A0F29 /* ReplyDescriptionTests.swift in Sources */, D71DC1EC2A9129C3006E207C /* PostViewTests.swift in Sources */, diff --git a/damus/Features/Chat/Models/ThreadModel.swift b/damus/Features/Chat/Models/ThreadModel.swift index 332b11de..e9df2130 100644 --- a/damus/Features/Chat/Models/ThreadModel.swift +++ b/damus/Features/Chat/Models/ThreadModel.swift @@ -190,6 +190,12 @@ class ThreadModel: ObservableObject { self.add_event(ev, keypair: damus_state.keypair) } } + else if ev.known_kind == .boost { + damus_state.boosts.add_event(ev, target: original_event.id) + } + else if ev.known_kind == .like { + damus_state.likes.add_event(ev, target: original_event.id) + } } // MARK: External control interface diff --git a/damusTests/NostrNetworkManagerTests/ThreadModelTests.swift b/damusTests/NostrNetworkManagerTests/ThreadModelTests.swift new file mode 100644 index 00000000..ee6b582c --- /dev/null +++ b/damusTests/NostrNetworkManagerTests/ThreadModelTests.swift @@ -0,0 +1,63 @@ +// +// ThreadModelTests.swift +// damus +// +// Created by Daniel D’Aquino on 2025-08-25. +// + + +import XCTest +@testable import damus + +final class ThreadModelTests: XCTestCase { + var damusState: DamusState? = nil + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + damusState = generate_test_damus_state(mock_profile_info: nil) + + let notesJSONL = getTestNotesJSONL() + + for noteText in notesJSONL.split(separator: "\n") { + let _ = damusState!.ndb.process_event("[\"EVENT\",\"subid\",\(String(noteText))]") + } + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + damusState = nil + } + + func getTestNotesJSONL() -> String { + // Get the path for the test_notes.jsonl file in the same folder as this test file + let testBundle = Bundle(for: type(of: self)) + let fileURL = testBundle.url(forResource: "test_notes", withExtension: "jsonl")! + + // Load the contents of the file + return try! String(contentsOf: fileURL, encoding: .utf8) + } + + /// Tests loading up a thread and checking if the repost count loads as expected. + func testActionBarModel() throws { + let testNoteJson = """ +{"content":"https://smartflowsocial.s3.us-east-1.amazonaws.com/clients/cm7kdrwdk0000qyu6fwtd96ui/0cab65a9-0142-48e3-abd7-94d20e30d3b2.jpg\n\n","pubkey":"71ecabd8b6b33548e075ff01b31568ffda19d0ac2788067d99328c6de4885975","tags":[["t","meme"],["t","memes"],["t","memestr"],["t","plebchain"]],"created_at":1755694800,"id":"64b26d0a587f5f894470e1e4783756b4d8ba971226de975ee30ac1b69970d5a1","kind":1,"sig":"c000794da8c4f7549b546630b16ed17f6edc0af0269b8c46ce14f5b1937431e7575b78351bc152007ebab5720028e5fe4b738f99e8887f273d35dd2217d1cc3d"} +""" + let testShouldComplete = XCTestExpectation(description: "Test should complete") + Task { + let note = NostrEvent.owned_from_json(json: testNoteJson)! + let threadModel = await ThreadModel(event: note, damus_state: damusState!) + await threadModel.subscribe() + let actionBarModel = make_actionbar_model(ev: note.id, damus: damusState!) + while true { + try await Task.sleep(nanoseconds: 500_000_000) + actionBarModel.update(damus: damusState!, evid: note.id) + if actionBarModel.boosts >= 5 { + break + } + } + XCTAssertEqual(actionBarModel.boosts, 5) + testShouldComplete.fulfill() + } + wait(for: [testShouldComplete], timeout: 10.0) + } +}