Add tests for 1.1.0 features

This commit is contained in:
alexandrev-tibco
2026-02-01 14:40:10 +01:00
parent d55b999bef
commit 2437dd647f
11 changed files with 297 additions and 29 deletions
@@ -0,0 +1,65 @@
import XCTest
@testable import PortfolioJournal
final class BackupServiceTests: XCTestCase {
private var tempRoot: URL!
override func setUp() {
super.setUp()
tempRoot = FileManager.default.temporaryDirectory
.appendingPathComponent(UUID().uuidString, isDirectory: true)
try? FileManager.default.createDirectory(at: tempRoot, withIntermediateDirectories: true)
}
override func tearDown() {
if let tempRoot {
try? FileManager.default.removeItem(at: tempRoot)
}
super.tearDown()
}
func testCreateBackupPrunesToRetentionCount() {
let localBase = tempRoot.appendingPathComponent("Local", isDirectory: true)
try? FileManager.default.createDirectory(at: localBase, withIntermediateDirectories: true)
var dates = [
Date(timeIntervalSince1970: 100),
Date(timeIntervalSince1970: 200)
]
let service = BackupService(
fileManager: .default,
dateProvider: { dates.removeFirst() },
localBaseDirectoryProvider: { localBase },
iCloudBaseDirectoryProvider: { nil },
exportProvider: { "{}" }
)
_ = service.createBackup(retentionCount: 1, includeICloud: false)
let records = service.createBackup(retentionCount: 1, includeICloud: false)
XCTAssertEqual(records.count, 1)
XCTAssertEqual(records.first?.location, .local)
}
func testCreateBackupIncludesICloudWhenEnabled() {
let localBase = tempRoot.appendingPathComponent("Local", isDirectory: true)
let iCloudBase = tempRoot.appendingPathComponent("iCloud", isDirectory: true)
try? FileManager.default.createDirectory(at: localBase, withIntermediateDirectories: true)
try? FileManager.default.createDirectory(at: iCloudBase, withIntermediateDirectories: true)
let service = BackupService(
fileManager: .default,
dateProvider: { Date(timeIntervalSince1970: 300) },
localBaseDirectoryProvider: { localBase },
iCloudBaseDirectoryProvider: { iCloudBase },
exportProvider: { "{}" }
)
let records = service.createBackup(retentionCount: 5, includeICloud: true)
let locations = Set(records.map { $0.location })
XCTAssertTrue(locations.contains(.local))
XCTAssertTrue(locations.contains(.iCloud))
}
}
@@ -0,0 +1,54 @@
import XCTest
@testable import PortfolioJournal
final class ReviewPromptServiceTests: XCTestCase {
private var defaults: UserDefaults!
private var suiteName: String!
override func setUp() {
super.setUp()
suiteName = UUID().uuidString
defaults = UserDefaults(suiteName: suiteName)
}
override func tearDown() {
if let suiteName {
defaults.removePersistentDomain(forName: suiteName)
}
super.tearDown()
}
func testTriggersAfterMinimumCheckIns() {
var didRequest = false
let service = ReviewPromptService(
userDefaults: defaults,
dateProvider: { Date(timeIntervalSince1970: 1_000) },
reviewRequestHandler: { didRequest = true }
)
service.recordMonthlyCheckInCompleted()
service.recordMonthlyCheckInCompleted()
XCTAssertFalse(didRequest)
service.recordMonthlyCheckInCompleted()
XCTAssertTrue(didRequest)
}
func testDoesNotTriggerIfPromptedRecently() {
var didRequest = false
let now = Date(timeIntervalSince1970: 10_000)
defaults.set(now, forKey: "reviewPromptLastDate")
let service = ReviewPromptService(
userDefaults: defaults,
dateProvider: { now.addingTimeInterval(60 * 60 * 24 * 10) },
reviewRequestHandler: { didRequest = true }
)
service.recordMonthlyCheckInCompleted()
service.recordMonthlyCheckInCompleted()
service.recordMonthlyCheckInCompleted()
XCTAssertFalse(didRequest)
}
}
@@ -0,0 +1,28 @@
import XCTest
@testable import PortfolioJournal
final class ShareServiceTests: XCTestCase {
func testBuildMonthlyCheckInShareText() {
let summary = MonthlySummary(
periodLabel: "January 2026",
startDate: Date(timeIntervalSince1970: 0),
endDate: Date(timeIntervalSince1970: 0),
startingValue: 1000,
endingValue: 1200,
contributions: 150,
netPerformance: 50
)
let text = ShareService.buildMonthlyCheckInShareText(
summary: summary,
appName: "Portfolio Journal"
)
XCTAssertTrue(text.contains("January 2026 Check-in"))
XCTAssertTrue(text.contains("Starting:"))
XCTAssertTrue(text.contains("Ending:"))
XCTAssertTrue(text.contains("Contributions:"))
XCTAssertTrue(text.contains("Net performance:"))
XCTAssertTrue(text.contains("Shared from Portfolio Journal"))
}
}
@@ -0,0 +1,42 @@
import XCTest
@testable import PortfolioJournal
@MainActor
final class SettingsViewModelTests: XCTestCase {
override func tearDown() {
UserDefaults.standard.removeObject(forKey: "backupsEnabled")
UserDefaults.standard.removeObject(forKey: "backupRetentionCount")
UserDefaults.standard.removeObject(forKey: "debugPremiumOverride")
super.tearDown()
}
func testSetBackupsEnabledNonPremiumShowsPaywall() {
let iap = IAPService()
#if DEBUG
iap.setPremiumForTesting(false)
#endif
let viewModel = SettingsViewModel(iapService: iap)
viewModel.setBackupsEnabled(true)
XCTAssertFalse(viewModel.backupsEnabled)
XCTAssertTrue(viewModel.showingPaywall)
}
func testSetBackupsEnabledPremiumPersistsFlag() {
#if DEBUG
UserDefaults.standard.set(true, forKey: "debugPremiumOverride")
#endif
let iap = IAPService()
#if DEBUG
iap.setDebugPremiumOverride(true)
#endif
let viewModel = SettingsViewModel(iapService: iap)
viewModel.setBackupsEnabled(true)
XCTAssertTrue(viewModel.backupsEnabled)
XCTAssertFalse(viewModel.showingPaywall)
XCTAssertTrue(UserDefaults.standard.bool(forKey: "backupsEnabled"))
}
}
@@ -0,0 +1,10 @@
import XCTest
import UIKit
@testable import PortfolioJournal
final class OnboardingViewTests: XCTestCase {
func testAppSettingsURLMatchesSystemConstant() {
let expected = URL(string: UIApplication.openSettingsURLString)
XCTAssertEqual(OnboardingQuickStartView.appSettingsURL(), expected)
}
}