Commit 311bd03689
Verified · cmc
Layout: unified · split
gitbay/Views/Repos/RepoSettingsView.swift +14 −12
| @@ -29,7 +29,7 @@ struct RepoSettingsView: View { | |||
| 29 | branchesSection(loaded) | 29 | branchesSection(loaded) |
| 30 | mergeRulesSection(loaded) | 30 | mergeRulesSection(loaded) |
| 31 | daemonSection(loaded) | 31 | daemonSection(loaded) |
| 32 | depsSection(loaded) | 32 | depsSection() |
| 33 | } | 33 | } |
| 34 | } | 34 | } |
| 35 | .overlay { LoadStateOverlay(state: model.state) } | 35 | .overlay { LoadStateOverlay(state: model.state) } |
| @@ -44,7 +44,10 @@ struct RepoSettingsView: View { | |||
| 44 | } | 44 | } |
| 45 | } | 45 | } |
| 46 | .task { await model.loadDeps() } | 46 | .task { await model.loadDeps() } |
| 47 | .refreshable { await model.load() } | 47 | .refreshable { |
| 48 | await model.load() | ||
| 49 | await model.loadDeps() | ||
| 50 | } | ||
| 48 | } | 51 | } |
| 49 | 52 | ||
| 50 | // MARK: - Sections | 53 | // MARK: - Sections |
| @@ -208,20 +211,17 @@ struct RepoSettingsView: View { | |||
| 208 | } | 211 | } |
| 209 | } | 212 | } |
| 210 | 213 | ||
| 211 | private func depsSection(_ loaded: RepoSettingsViewModel.Loaded) -> some View { | 214 | private func depsSection() -> some View { |
| 212 | Section { | 215 | Section { |
| 213 | SettingToggle(title: "Dependency checks", serverValue: model.deps?.enabled ?? false) { | ||
| 214 | await model.setDepsEnabled($0) | ||
| 215 | } | ||
| 216 | .disabled(model.deps == nil || model.working) | ||
| 217 | Text("Checks tell a public registry what this repository depends on.") | ||
| 218 | .font(.gbSans(.caption)) | ||
| 219 | .foregroundStyle(.secondary) | ||
| 220 | |||
| 221 | if let deps = model.deps { | 216 | if let deps = model.deps { |
| 217 | SettingToggle(title: "Dependency checks", serverValue: deps.enabled) { | ||
| 218 | await model.setDepsEnabled($0) | ||
| 219 | } | ||
| 220 | .disabled(model.working) | ||
| 221 | |||
| 222 | if deps.enabled { | 222 | if deps.enabled { |
| 223 | if let lastCheck = deps.lastCheck { | 223 | if let lastCheck = deps.lastCheck { |
| 224 | Text(lastCheck, format: .relative(presentation: .named)) | 224 | (Text("Last checked ") + Text(lastCheck, format: .relative(presentation: .named))) |
| 225 | .font(.gbSans(.caption)) | 225 | .font(.gbSans(.caption)) |
| 226 | .foregroundStyle(.secondary) | 226 | .foregroundStyle(.secondary) |
| 227 | } else { | 227 | } else { |
| @@ -266,6 +266,8 @@ struct RepoSettingsView: View { | |||
| 266 | } | 266 | } |
| 267 | } header: { | 267 | } header: { |
| 268 | Text("Dependencies") | 268 | Text("Dependencies") |
| 269 | } footer: { | ||
| 270 | Text("Checks tell a public registry what this repository depends on.") | ||
| 269 | } | 271 | } |
| 270 | } | 272 | } |
| 271 | 273 | ||
gitbayTests/DepsTests.swift +22
| @@ -112,6 +112,9 @@ struct DepsActionTests { | |||
| 112 | await model.setDepsEnabled(true) | 112 | await model.setDepsEnabled(true) |
| 113 | var write = try #require(stub.seen.first { $0.method == "POST" }) | 113 | var write = try #require(stub.seen.first { $0.method == "POST" }) |
| 114 | #expect(try argvOf(write) == ["repo", "deps", "enable", "krz/gitbay"]) | 114 | #expect(try argvOf(write) == ["repo", "deps", "enable", "krz/gitbay"]) |
| 115 | // The write must reload deps specifically, not the whole settings | ||
| 116 | // screen — otherwise this enqueued status stub goes unconsumed. | ||
| 117 | #expect(model.deps?.enabled == true) | ||
| 115 | 118 | ||
| 116 | let (client2, stub2) = try makeClient() | 119 | let (client2, stub2) = try makeClient() |
| 117 | let model2 = RepoSettingsViewModel(client: client2, repoPath: "krz/gitbay") | 120 | let model2 = RepoSettingsViewModel(client: client2, repoPath: "krz/gitbay") |
| @@ -122,6 +125,7 @@ struct DepsActionTests { | |||
| 122 | await model2.setDepsEnabled(false) | 125 | await model2.setDepsEnabled(false) |
| 123 | write = try #require(stub2.seen.first { $0.method == "POST" }) | 126 | write = try #require(stub2.seen.first { $0.method == "POST" }) |
| 124 | #expect(try argvOf(write) == ["repo", "deps", "disable", "krz/gitbay"]) | 127 | #expect(try argvOf(write) == ["repo", "deps", "disable", "krz/gitbay"]) |
| 128 | #expect(model2.deps?.enabled == true) | ||
| 125 | } | 129 | } |
| 126 | 130 | ||
| 127 | /// "Could not ask" must not render as "checks are off". | 131 | /// "Could not ask" must not render as "checks are off". |
| @@ -170,4 +174,22 @@ struct DepsActionTests { | |||
| 170 | #expect(model.depsError == nil) | 174 | #expect(model.depsError == nil) |
| 171 | #expect(model.deps?.enabled == true) | 175 | #expect(model.deps?.enabled == true) |
| 172 | } | 176 | } |
| 177 | |||
| 178 | /// The converse of the above: a later failure must drop the stale | ||
| 179 | /// status, not leave it sitting alongside the new error. | ||
| 180 | @Test func depsClearsOnALaterFailureAfterASuccess() async throws { | ||
| 181 | let (client, stub) = try makeClient() | ||
| 182 | stub.enqueue(.init(status: 200, json: fullStatus)) | ||
| 183 | let model = RepoSettingsViewModel(client: client, repoPath: "krz/gitbay") | ||
| 184 | await model.loadDeps() | ||
| 185 | #expect(model.deps?.enabled == true) | ||
| 186 | |||
| 187 | stub.enqueue(.init(status: 200, json: """ | ||
| 188 | {"protocol_version":1,"error":"denied","exit_code":4} | ||
| 189 | """)) | ||
| 190 | await model.loadDeps() | ||
| 191 | |||
| 192 | #expect(model.deps == nil) | ||
| 193 | #expect(model.depsError?.isEmpty == false) | ||
| 194 | } | ||
| 173 | } | 195 | } |