damus

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

commit 3b76fcb743f1e9bb4049228a302b4254bccc9921
parent edb23e4e7016465ad7e9238673fe7d039e2b2b2a
Author: Daniel D’Aquino <daniel@daquino.me>
Date:   Fri, 13 Oct 2023 12:28:41 -0700

test: Add basic snapshot test coverage for EventView

This commit adds a basic snapshot test for EventView, and also adds some testing infrastructure to help with mocking NostrDB behavior.

Test
----

PASS

Device: iOS 17.0 Simulator
iOS: 17.0
Damus: This commit
Steps: Run `EventViewTests`
Results: Snapshot matches baseline reference added

Diffstat:
Mdamus.xcodeproj/project.pbxproj | 18+++++++++++++++---
AdamusTests/EventViewTests.swift | 46++++++++++++++++++++++++++++++++++++++++++++++
AdamusTests/Mocking/MockDamusState.swift | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AdamusTests/Mocking/MockProfiles.swift | 28++++++++++++++++++++++++++++
AdamusTests/__Snapshots__/EventViewTests/testBasicEventViewLayout.1.png | 0
5 files changed, 155 insertions(+), 3 deletions(-)

diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj @@ -430,6 +430,9 @@ BAB68BED29543FA3007BA466 /* SelectWalletView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAB68BEC29543FA3007BA466 /* SelectWalletView.swift */; }; D2277EEA2A089BD5006C3807 /* Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2277EE92A089BD5006C3807 /* Router.swift */; }; D71DC1EC2A9129C3006E207C /* PostViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D71DC1EB2A9129C3006E207C /* PostViewTests.swift */; }; + D72A2D022AD9C136002AFF62 /* EventViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72A2CFF2AD9B66B002AFF62 /* EventViewTests.swift */; }; + D72A2D052AD9C1B5002AFF62 /* MockDamusState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72A2D042AD9C1B5002AFF62 /* MockDamusState.swift */; }; + D72A2D072AD9C1FB002AFF62 /* MockProfiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72A2D062AD9C1FB002AFF62 /* MockProfiles.swift */; }; D7315A2A2ACDF3B70036E30A /* DamusCacheManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7315A292ACDF3B70036E30A /* DamusCacheManager.swift */; }; D7315A2C2ACDF4DA0036E30A /* DamusCacheManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7315A2B2ACDF4DA0036E30A /* DamusCacheManagerTests.swift */; }; D723C38E2AB8D83400065664 /* ContentFilters.swift in Sources */ = {isa = PBXBuildFile; fileRef = D723C38D2AB8D83400065664 /* ContentFilters.swift */; }; @@ -1128,6 +1131,9 @@ D2277EE92A089BD5006C3807 /* Router.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Router.swift; sourceTree = "<group>"; }; D71DC1EB2A9129C3006E207C /* PostViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostViewTests.swift; sourceTree = "<group>"; }; D723C38D2AB8D83400065664 /* ContentFilters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentFilters.swift; sourceTree = "<group>"; }; + D72A2CFF2AD9B66B002AFF62 /* EventViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventViewTests.swift; sourceTree = "<group>"; }; + D72A2D042AD9C1B5002AFF62 /* MockDamusState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockDamusState.swift; sourceTree = "<group>"; }; + D72A2D062AD9C1FB002AFF62 /* MockProfiles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockProfiles.swift; sourceTree = "<group>"; }; D78525242A7B2EA4002FA637 /* NoteContentViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoteContentViewTests.swift; sourceTree = "<group>"; }; D7870BC02AC4750B0080BA88 /* MentionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MentionView.swift; sourceTree = "<group>"; }; D7870BC22AC47EBC0080BA88 /* EventLoaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventLoaderView.swift; sourceTree = "<group>"; }; @@ -2155,6 +2161,7 @@ 4CE6DEF627F7A08200C66700 /* damusTests */ = { isa = PBXGroup; children = ( + D72A2D032AD9C165002AFF62 /* Mocking */, 4C9B0DEC2A65A74000CBDA21 /* Util */, 4C0C03962A61E2670098B3B8 /* Fixtures */, 4C7D097D2A0C58B900943473 /* WalletConnectTests.swift */, @@ -2185,6 +2192,7 @@ 4C684A562A7FFAE6005E6031 /* UrlTests.swift */, D7DEEF2E2A8C021E00E0C99F /* NostrEventTests.swift */, D71DC1EB2A9129C3006E207C /* PostViewTests.swift */, + D72A2CFF2AD9B66B002AFF62 /* EventViewTests.swift */, D7315A2B2ACDF4DA0036E30A /* DamusCacheManagerTests.swift */, ); path = damusTests; @@ -2313,12 +2321,13 @@ path = Camera; sourceTree = "<group>"; }; - BA3759952ABCCF360018D73B /* Camera */ = { + D72A2D032AD9C165002AFF62 /* Mocking */ = { isa = PBXGroup; children = ( - BA3759962ABCCF360018D73B /* CameraPreview.swift */, + D72A2D042AD9C1B5002AFF62 /* MockDamusState.swift */, + D72A2D062AD9C1FB002AFF62 /* MockProfiles.swift */, ); - path = Camera; + path = Mocking; sourceTree = "<group>"; }; F71694E82A66221E001F4053 /* Onboarding */ = { @@ -2975,12 +2984,14 @@ 3A30410129AB12AA008A0F29 /* EventGroupViewTests.swift in Sources */, 501F8C822A0224EB001AFC1D /* KeychainStorageTests.swift in Sources */, 3ACBCB78295FE5C70037388A /* TimeAgoTests.swift in Sources */, + D72A2D072AD9C1FB002AFF62 /* MockProfiles.swift in Sources */, 4C4F14A72A2A61A30045A0B9 /* NostrScriptTests.swift in Sources */, D78525252A7B2EA4002FA637 /* NoteContentViewTests.swift in Sources */, 4C3EA67B28FF7B3900C48A62 /* InvoiceTests.swift in Sources */, 4C363A9E2828A822006E126D /* ReplyTests.swift in Sources */, 4C7D097E2A0C58B900943473 /* WalletConnectTests.swift in Sources */, 4CB883AA297612FF00DC99E7 /* ZapTests.swift in Sources */, + D72A2D022AD9C136002AFF62 /* EventViewTests.swift in Sources */, 4CB8839A297322D200DC99E7 /* DMTests.swift in Sources */, D7315A2C2ACDF4DA0036E30A /* DamusCacheManagerTests.swift in Sources */, 4C9054852A6AEAA000811EEC /* NdbTests.swift in Sources */, @@ -2988,6 +2999,7 @@ F944F56E29EA9CCC0067B3BF /* DamusParseContentTests.swift in Sources */, 3A5E47C72A4A76C800C0D090 /* TrieTests.swift in Sources */, 4CB883AE2976FA9300DC99E7 /* FormatTests.swift in Sources */, + D72A2D052AD9C1B5002AFF62 /* MockDamusState.swift in Sources */, 4C363AA02828A8DD006E126D /* LikeTests.swift in Sources */, 4C90BD1C283AC38E008EE7EF /* Bech32Tests.swift in Sources */, 50A50A8D29A09E1C00C01BE7 /* RequestTests.swift in Sources */, diff --git a/damusTests/EventViewTests.swift b/damusTests/EventViewTests.swift @@ -0,0 +1,46 @@ +// +// EventViewTests.swift +// damusTests +// +// Created by Daniel D’Aquino on 2023-10-13. +// + +import Foundation +import XCTest +import SnapshotTesting +import SwiftUI +@testable import damus + +final class EventViewTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testBasicEventViewLayout() { + let test_mock_damus_state = generate_test_damus_state( + mock_profile_info: [ + // Manually mock some profile info so that we have a more realistic-looking note + jack_keypair.pubkey: Profile( + name: "jack", + display_name: "Jack Dorsey" + ) + ] + ) + let test_note = NostrEvent( + content: "Nostr is the super app. Because it’s actually an ecosystem of apps, all of which make each other better. People haven’t grasped that yet. They will when it’s more accessible and onboarding is more straightforward and intuitive.", + keypair: jack_keypair, + createdAt: UInt32(Date.init(timeIntervalSinceNow: -60).timeIntervalSince1970) + )! + + let eventViewTest = EventView(damus: test_mock_damus_state, event: test_note).padding() + let hostView = UIHostingController(rootView: eventViewTest) + + // Run snapshot check + assertSnapshot(matching: hostView, as: .image(on: .iPhone13(.portrait))) + } +} diff --git a/damusTests/Mocking/MockDamusState.swift b/damusTests/Mocking/MockDamusState.swift @@ -0,0 +1,66 @@ +// +// MockDamusState.swift +// damusTests +// +// Created by Daniel D’Aquino on 2023-10-13. +// + +import Foundation +@testable import damus + +// Generates a test damus state with configurable mock parameters +func generate_test_damus_state( + mock_profile_info: [Pubkey: Profile]? +) -> DamusState { + // Create a unique temporary directory + var tempDir: String! + do { + let fileManager = FileManager.default + let temp = fileManager.temporaryDirectory.appendingPathComponent(UUID().uuidString) + try fileManager.createDirectory(at: temp, withIntermediateDirectories: true, attributes: nil) + tempDir = temp.absoluteString + } catch { + tempDir = "." + } + + print("opening \(tempDir!)") + let ndb = Ndb(path: tempDir)! + let our_pubkey = test_pubkey + let pool = RelayPool(ndb: ndb) + let settings = UserSettingsStore() + + let profiles: Profiles = { + guard let mock_profile_info, let profiles: Profiles = MockProfiles(mocked_profiles: mock_profile_info, ndb: ndb) else { + return Profiles.init(ndb: ndb) + } + return profiles + }() + + let damus = DamusState(pool: pool, + keypair: test_keypair, + likes: .init(our_pubkey: our_pubkey), + boosts: .init(our_pubkey: our_pubkey), + contacts: .init(our_pubkey: our_pubkey), + profiles: profiles, + dms: .init(our_pubkey: our_pubkey), + previews: .init(), + zaps: .init(our_pubkey: our_pubkey), + lnurls: .init(), + settings: settings, + relay_filters: .init(our_pubkey: our_pubkey), + relay_model_cache: .init(), + drafts: .init(), + events: .init(ndb: ndb), + bookmarks: .init(pubkey: our_pubkey), + postbox: .init(pool: pool), + bootstrap_relays: .init(), + replies: .init(our_pubkey: our_pubkey), + muted_threads: .init(keypair: test_keypair), + wallet: .init(settings: settings), + nav: .init(), + music: .init(onChange: {_ in }), + video: .init(), + ndb: ndb) + + return damus +} diff --git a/damusTests/Mocking/MockProfiles.swift b/damusTests/Mocking/MockProfiles.swift @@ -0,0 +1,28 @@ +// +// MockProfiles.swift +// damusTests +// +// Created by Daniel D’Aquino on 2023-10-13. +// + +import Foundation +@testable import damus + +// A Mockable `Profiles` class that can be used for testing. +// Note: Not all methods are mocked. You might need to implement a method depending on the test you are writing. +class MockProfiles: Profiles { + var mocked_profiles: [Pubkey: Profile] = [:] + var ndb: Ndb + + init?(mocked_profiles: [Pubkey : Profile], ndb: Ndb) { + self.mocked_profiles = mocked_profiles + self.ndb = ndb + super.init(ndb: ndb) + } + + override func lookup(id: Pubkey) -> NdbTxn<Profile?> { + return NdbTxn(ndb: self.ndb) { txn in + return self.mocked_profiles[id] + } + } +} diff --git a/damusTests/__Snapshots__/EventViewTests/testBasicEventViewLayout.1.png b/damusTests/__Snapshots__/EventViewTests/testBasicEventViewLayout.1.png Binary files differ.