diff options
| author | Mitchell Hashimoto <m@mitchellh.com> | 2025-10-10 08:34:42 -0700 |
|---|---|---|
| committer | Mitchell Hashimoto <m@mitchellh.com> | 2025-10-10 08:34:45 -0700 |
| commit | 47f3c946401529ec7b2c90405be46ab7a4123629 (patch) | |
| tree | 27a7f757a1bb2958743d718d70291a20b3f11ca5 | |
| parent | 6993947a3a8a8c92d849fa1fa23a9e9fa4016ea8 (diff) | |
macos: many more unit tests for update work
| -rw-r--r-- | AGENTS.md | 1 | ||||
| -rw-r--r-- | macos/Tests/Update/UpdateStateTests.swift | 116 | ||||
| -rw-r--r-- | macos/Tests/Update/UpdateViewModelTests.swift | 97 |
3 files changed, 214 insertions, 0 deletions
@@ -29,3 +29,4 @@ A file for [guiding coding agents](https://agents.md/). - Do not use `xcodebuild` - Use `zig build` to build the macOS app and any shared Zig code +- Run Xcode tests using `zig build test` diff --git a/macos/Tests/Update/UpdateStateTests.swift b/macos/Tests/Update/UpdateStateTests.swift new file mode 100644 index 000000000..5a0832a5a --- /dev/null +++ b/macos/Tests/Update/UpdateStateTests.swift @@ -0,0 +1,116 @@ +import Testing +import Foundation +import Sparkle +@testable import Ghostty + +struct UpdateStateTests { + // MARK: - Equatable Tests + + @Test func testIdleEquality() { + let state1: UpdateState = .idle + let state2: UpdateState = .idle + #expect(state1 == state2) + } + + @Test func testCheckingEquality() { + let state1: UpdateState = .checking(.init(cancel: {})) + let state2: UpdateState = .checking(.init(cancel: {})) + #expect(state1 == state2) + } + + @Test func testNotFoundEquality() { + let state1: UpdateState = .notFound + let state2: UpdateState = .notFound + #expect(state1 == state2) + } + + @Test func testInstallingEquality() { + let state1: UpdateState = .installing + let state2: UpdateState = .installing + #expect(state1 == state2) + } + + @Test func testPermissionRequestEquality() { + let request1 = SPUUpdatePermissionRequest(systemProfile: []) + let request2 = SPUUpdatePermissionRequest(systemProfile: []) + let state1: UpdateState = .permissionRequest(.init(request: request1, reply: { _ in })) + let state2: UpdateState = .permissionRequest(.init(request: request2, reply: { _ in })) + #expect(state1 == state2) + } + + @Test func testReadyToInstallEquality() { + let state1: UpdateState = .readyToInstall(.init(reply: { _ in })) + let state2: UpdateState = .readyToInstall(.init(reply: { _ in })) + #expect(state1 == state2) + } + + @Test func testDownloadingEqualityWithSameProgress() { + let state1: UpdateState = .downloading(.init(cancel: {}, expectedLength: 1000, progress: 500)) + let state2: UpdateState = .downloading(.init(cancel: {}, expectedLength: 1000, progress: 500)) + #expect(state1 == state2) + } + + @Test func testDownloadingInequalityWithDifferentProgress() { + let state1: UpdateState = .downloading(.init(cancel: {}, expectedLength: 1000, progress: 500)) + let state2: UpdateState = .downloading(.init(cancel: {}, expectedLength: 1000, progress: 600)) + #expect(state1 != state2) + } + + @Test func testDownloadingInequalityWithDifferentExpectedLength() { + let state1: UpdateState = .downloading(.init(cancel: {}, expectedLength: 1000, progress: 500)) + let state2: UpdateState = .downloading(.init(cancel: {}, expectedLength: 2000, progress: 500)) + #expect(state1 != state2) + } + + @Test func testDownloadingEqualityWithNilExpectedLength() { + let state1: UpdateState = .downloading(.init(cancel: {}, expectedLength: nil, progress: 500)) + let state2: UpdateState = .downloading(.init(cancel: {}, expectedLength: nil, progress: 500)) + #expect(state1 == state2) + } + + @Test func testExtractingEqualityWithSameProgress() { + let state1: UpdateState = .extracting(.init(progress: 0.5)) + let state2: UpdateState = .extracting(.init(progress: 0.5)) + #expect(state1 == state2) + } + + @Test func testExtractingInequalityWithDifferentProgress() { + let state1: UpdateState = .extracting(.init(progress: 0.5)) + let state2: UpdateState = .extracting(.init(progress: 0.6)) + #expect(state1 != state2) + } + + @Test func testErrorEqualityWithSameDescription() { + let error1 = NSError(domain: "Test", code: 1, userInfo: [NSLocalizedDescriptionKey: "Error message"]) + let error2 = NSError(domain: "Test", code: 2, userInfo: [NSLocalizedDescriptionKey: "Error message"]) + let state1: UpdateState = .error(.init(error: error1, retry: {}, dismiss: {})) + let state2: UpdateState = .error(.init(error: error2, retry: {}, dismiss: {})) + #expect(state1 == state2) + } + + @Test func testErrorInequalityWithDifferentDescription() { + let error1 = NSError(domain: "Test", code: 1, userInfo: [NSLocalizedDescriptionKey: "Error 1"]) + let error2 = NSError(domain: "Test", code: 1, userInfo: [NSLocalizedDescriptionKey: "Error 2"]) + let state1: UpdateState = .error(.init(error: error1, retry: {}, dismiss: {})) + let state2: UpdateState = .error(.init(error: error2, retry: {}, dismiss: {})) + #expect(state1 != state2) + } + + @Test func testDifferentStatesAreNotEqual() { + let state1: UpdateState = .idle + let state2: UpdateState = .checking(.init(cancel: {})) + #expect(state1 != state2) + } + + // MARK: - isIdle Tests + + @Test func testIsIdleTrue() { + let state: UpdateState = .idle + #expect(state.isIdle == true) + } + + @Test func testIsIdleFalse() { + let state: UpdateState = .checking(.init(cancel: {})) + #expect(state.isIdle == false) + } +} diff --git a/macos/Tests/Update/UpdateViewModelTests.swift b/macos/Tests/Update/UpdateViewModelTests.swift new file mode 100644 index 000000000..dd88cbe83 --- /dev/null +++ b/macos/Tests/Update/UpdateViewModelTests.swift @@ -0,0 +1,97 @@ +import Testing +import Foundation +import SwiftUI +import Sparkle +@testable import Ghostty + +struct UpdateViewModelTests { + // MARK: - Text Formatting Tests + + @Test func testIdleText() { + let viewModel = UpdateViewModel() + viewModel.state = .idle + #expect(viewModel.text == "") + } + + @Test func testPermissionRequestText() { + let viewModel = UpdateViewModel() + let request = SPUUpdatePermissionRequest(systemProfile: []) + viewModel.state = .permissionRequest(.init(request: request, reply: { _ in })) + #expect(viewModel.text == "Enable Automatic Updates?") + } + + @Test func testCheckingText() { + let viewModel = UpdateViewModel() + viewModel.state = .checking(.init(cancel: {})) + #expect(viewModel.text == "Checking for Updates…") + } + + @Test func testDownloadingTextWithKnownLength() { + let viewModel = UpdateViewModel() + viewModel.state = .downloading(.init(cancel: {}, expectedLength: 1000, progress: 500)) + #expect(viewModel.text == "Downloading: 50%") + } + + @Test func testDownloadingTextWithUnknownLength() { + let viewModel = UpdateViewModel() + viewModel.state = .downloading(.init(cancel: {}, expectedLength: nil, progress: 500)) + #expect(viewModel.text == "Downloading…") + } + + @Test func testDownloadingTextWithZeroExpectedLength() { + let viewModel = UpdateViewModel() + viewModel.state = .downloading(.init(cancel: {}, expectedLength: 0, progress: 500)) + #expect(viewModel.text == "Downloading…") + } + + @Test func testExtractingText() { + let viewModel = UpdateViewModel() + viewModel.state = .extracting(.init(progress: 0.75)) + #expect(viewModel.text == "Preparing: 75%") + } + + @Test func testReadyToInstallText() { + let viewModel = UpdateViewModel() + viewModel.state = .readyToInstall(.init(reply: { _ in })) + #expect(viewModel.text == "Install Update") + } + + @Test func testInstallingText() { + let viewModel = UpdateViewModel() + viewModel.state = .installing + #expect(viewModel.text == "Installing…") + } + + @Test func testNotFoundText() { + let viewModel = UpdateViewModel() + viewModel.state = .notFound + #expect(viewModel.text == "No Updates Available") + } + + @Test func testErrorText() { + let viewModel = UpdateViewModel() + let error = NSError(domain: "Test", code: 1, userInfo: [NSLocalizedDescriptionKey: "Network error"]) + viewModel.state = .error(.init(error: error, retry: {}, dismiss: {})) + #expect(viewModel.text == "Network error") + } + + // MARK: - Max Width Text Tests + + @Test func testMaxWidthTextForDownloading() { + let viewModel = UpdateViewModel() + viewModel.state = .downloading(.init(cancel: {}, expectedLength: 1000, progress: 50)) + #expect(viewModel.maxWidthText == "Downloading: 100%") + } + + @Test func testMaxWidthTextForExtracting() { + let viewModel = UpdateViewModel() + viewModel.state = .extracting(.init(progress: 0.5)) + #expect(viewModel.maxWidthText == "Preparing: 100%") + } + + @Test func testMaxWidthTextForNonProgressState() { + let viewModel = UpdateViewModel() + viewModel.state = .checking(.init(cancel: {})) + #expect(viewModel.maxWidthText == viewModel.text) + } +} |
