krz/octosentry
macOS menu bar app to monitor GitHub security alerts
clone: git clone https://gitbay.org/krz/octosentry.git
main: octosentryTests/UpdateStoreTests.swift · raw
1//
2// UpdateStoreTests.swift
3// octosentryTests
4//
5// isNewer decides whether anyone ever hears about a release: too strict and
6// updates go unnoticed, too loose and every user is nagged to install what
7// they already have.
8//
9
10import Foundation
11import Testing
12@testable import octosentry
13
14// isNewer is a pure function but inherits the target's MainActor isolation.
15@MainActor
16struct UpdateStoreTests {
17
18 // MARK: - Ordering
19
20 @Test func aNewerPatchMinorOrMajorIsOffered() {
21 #expect(UpdateStore.isNewer("1.1.1", than: "1.1.0"))
22 #expect(UpdateStore.isNewer("1.2.0", than: "1.1.9"))
23 #expect(UpdateStore.isNewer("2.0.0", than: "1.9.9"))
24 }
25
26 @Test func theSameVersionIsNotOffered() {
27 #expect(!UpdateStore.isNewer("1.1.1", than: "1.1.1"))
28 #expect(!UpdateStore.isNewer("1.0.0", than: "1.0.0"))
29 }
30
31 @Test func anOlderReleaseIsNotOffered() {
32 #expect(!UpdateStore.isNewer("1.1.0", than: "1.1.1"))
33 #expect(!UpdateStore.isNewer("1.0.1", than: "1.1.0"))
34 #expect(!UpdateStore.isNewer("0.7.0", than: "1.0.0"))
35 }
36
37 // A local build ahead of the latest release must not prompt for the
38 // release it already contains.
39 @Test func aBundleAheadOfTheLatestReleaseIsNotPrompted() {
40 #expect(!UpdateStore.isNewer("1.1", than: "1.1.1"))
41 }
42
43 // MARK: - Numeric, not lexical
44
45 // The comparison that a string compare gets wrong: "1.10" sorts before
46 // "1.9" as text, and after it as versions.
47 @Test func componentsCompareNumericallyNotAsText() {
48 #expect(UpdateStore.isNewer("1.10.0", than: "1.9.0"))
49 #expect(!UpdateStore.isNewer("1.9.0", than: "1.10.0"))
50 #expect(UpdateStore.isNewer("1.1.10", than: "1.1.9"))
51 }
52
53 // MARK: - Shapes the tag names actually take
54
55 @Test func missingTrailingComponentsCountAsZero() {
56 #expect(!UpdateStore.isNewer("1.1", than: "1.1.0"))
57 #expect(!UpdateStore.isNewer("1.1.0", than: "1.1"))
58 #expect(UpdateStore.isNewer("1.1.1", than: "1.1"))
59 }
60
61 @Test func aLeadingVIsIgnored() {
62 #expect(UpdateStore.isNewer("v1.1.1", than: "1.1.0"))
63 #expect(!UpdateStore.isNewer("v1.1.1", than: "1.1.1"))
64 #expect(UpdateStore.isNewer("v2.0.0", than: "v1.9.9"))
65 }
66
67 // Rather than crash or throw on a tag that isn't a version.
68 @Test func unparseableComponentsCountAsZero() {
69 #expect(!UpdateStore.isNewer("nightly", than: "1.1.1"))
70 #expect(UpdateStore.isNewer("1.1.1", than: "nightly"))
71 }
72
73 // MARK: - This repo's real tags
74
75 @Test func everyShippedTagIsNewerThanTheOneBefore() {
76 let shipped = ["0.1.0", "0.3.0", "0.4.0", "0.5.0", "0.6.0", "0.7.0", "1.0.0", "1.0.1", "1.1", "1.1.1"]
77
78 for (earlier, later) in zip(shipped, shipped.dropFirst()) {
79 #expect(UpdateStore.isNewer(later, than: earlier), "\(later) should be newer than \(earlier)")
80 #expect(!UpdateStore.isNewer(earlier, than: later), "\(earlier) should not be newer than \(later)")
81 }
82 }
83}