diff options
| author | Christian Cleberg <[email protected]> | 2026-07-15 22:41:33 -0500 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-07-15 22:41:33 -0500 |
| commit | 922502a2c74c66034f3ec2db6612f2a36d242042 (patch) | |
| tree | 0867730c955e308437b8c86dd37638c9bff6c9c5 /HutchTests | |
| parent | b9ec80716ea015de5b6b31395fdc5ff03191398c (diff) | |
| parent | 1d2769fc7a347939275e9130ee174d61d96ea401 (diff) | |
| download | hutch-922502a2c74c66034f3ec2db6612f2a36d242042.tar.gz hutch-922502a2c74c66034f3ec2db6612f2a36d242042.tar.bz2 hutch-922502a2c74c66034f3ec2db6612f2a36d242042.zip | |
Merge pull request #4 from zerolabsco/phase-2-patchsets
Phase 2: patchset review
Diffstat (limited to 'HutchTests')
| -rw-r--r-- | HutchTests/InboxViewModelTests.swift | 2 | ||||
| -rw-r--r-- | HutchTests/PatchsetTests.swift | 141 |
2 files changed, 142 insertions, 1 deletions
diff --git a/HutchTests/InboxViewModelTests.swift b/HutchTests/InboxViewModelTests.swift index 7bfc199..e67d317 100644 --- a/HutchTests/InboxViewModelTests.swift +++ b/HutchTests/InboxViewModelTests.swift @@ -186,7 +186,7 @@ struct InboxViewModelTests { 2.50.1 (Apple Git-155) """ - let segments = ThreadViewModel.segmentMessageBodyForTesting(body, isPatch: true) + let segments = InboxThreadUtilities.segmentMessageBody(body, isPatch: true) #expect(segments.count == 3) diff --git a/HutchTests/PatchsetTests.swift b/HutchTests/PatchsetTests.swift new file mode 100644 index 0000000..945131f --- /dev/null +++ b/HutchTests/PatchsetTests.swift @@ -0,0 +1,141 @@ +import Foundation +import Testing +@testable import Hutch + +struct PatchsetStatusTests { + + @Test + func statusRawValuesMatchTheGraphQLEnum() { + // lists.sr.ht's PatchsetStatus enum values, which are sent verbatim to + // updatePatchset. + #expect(PatchsetStatus.unknown.rawValue == "UNKNOWN") + #expect(PatchsetStatus.proposed.rawValue == "PROPOSED") + #expect(PatchsetStatus.needsRevision.rawValue == "NEEDS_REVISION") + #expect(PatchsetStatus.superseded.rawValue == "SUPERSEDED") + #expect(PatchsetStatus.approved.rawValue == "APPROVED") + #expect(PatchsetStatus.rejected.rawValue == "REJECTED") + #expect(PatchsetStatus.applied.rawValue == "APPLIED") + } + + @Test + func assignableStatusesExcludeServerManagedOnes() { + // UNKNOWN is a sentinel and SUPERSEDED is set by the server when a newer + // version lands, so neither should be offered as a reviewer choice. + #expect(!PatchsetStatus.assignable.contains(.unknown)) + #expect(!PatchsetStatus.assignable.contains(.superseded)) + #expect(PatchsetStatus.assignable.contains(.approved)) + #expect(PatchsetStatus.assignable.contains(.rejected)) + #expect(PatchsetStatus.assignable.contains(.applied)) + #expect(PatchsetStatus.assignable.contains(.needsRevision)) + #expect(PatchsetStatus.assignable.contains(.proposed)) + } + + @Test + func openStatusesAreThoseAwaitingADecision() { + #expect(PatchsetStatus.proposed.isOpen) + #expect(PatchsetStatus.needsRevision.isOpen) + #expect(!PatchsetStatus.applied.isOpen) + #expect(!PatchsetStatus.rejected.isOpen) + #expect(!PatchsetStatus.superseded.isOpen) + } + + @Test + func statusDecodesFromTheWireFormat() throws { + let decoded = try JSONDecoder().decode(PatchsetStatus.self, from: Data("\"NEEDS_REVISION\"".utf8)) + #expect(decoded == .needsRevision) + } +} + +struct PatchsetSummaryTests { + + @Test + func versionLabelIsHiddenForFirstVersion() { + let summary = PatchsetSummary( + id: 1, + subject: "[PATCH] fix the thing", + version: 1, + prefix: nil, + status: .proposed + ) + + #expect(summary.versionLabel == nil) + } + + @Test + func versionLabelIsShownForRevisions() { + let summary = PatchsetSummary( + id: 1, + subject: "[PATCH v3] fix the thing", + version: 3, + prefix: nil, + status: .proposed + ) + + #expect(summary.versionLabel == "v3") + } +} + +@MainActor +struct PatchsetOrderingTests { + + private func makePatch(id: Int, index: Int?, count: Int?) -> PatchsetEmail { + PatchsetEmail( + id: id, + subject: "patch \(id)", + date: nil, + sender: Entity(canonicalName: "~someone"), + contentBlocks: [], + index: index, + count: count + ) + } + + @Test + func patchesAreOrderedBySeriesIndexNotReceiptOrder() { + let patches = [ + makePatch(id: 30, index: 3, count: 3), + makePatch(id: 10, index: 1, count: 3), + makePatch(id: 20, index: 2, count: 3) + ] + + let ordered = PatchsetDetailViewModel.orderPatches(patches) + + #expect(ordered.map(\.index) == [1, 2, 3]) + } + + @Test + func unindexedPatchesAreKeptAtTheEndRatherThanDropped() { + let patches = [ + makePatch(id: 99, index: nil, count: nil), + makePatch(id: 20, index: 2, count: 2), + makePatch(id: 10, index: 1, count: 2) + ] + + let ordered = PatchsetDetailViewModel.orderPatches(patches) + + #expect(ordered.count == 3) + #expect(ordered.map(\.index) == [1, 2, nil]) + } + + @Test + func orderingIsStableForASingleUnindexedPatch() { + // A lone patch with no [PATCH n/m] prefix is the common one-off case. + let patches = [makePatch(id: 1, index: nil, count: nil)] + + let ordered = PatchsetDetailViewModel.orderPatches(patches) + + #expect(ordered.map(\.id) == [1]) + } + + @Test + func seriesLabelIsHiddenForSinglePatchSeries() { + let patch = makePatch(id: 1, index: 1, count: 1) + #expect(patch.seriesLabel == nil) + } + + @Test + func seriesLabelShowsPositionForMultiPatchSeries() { + let patch = makePatch(id: 1, index: 2, count: 5) + #expect(patch.seriesLabel == "2/5") + } +} |
