| @@ -135,6 +135,21 @@ struct RepoActionsTests { |
| 135 | 135 | == ["repo", "fork", "krz/gitbay", "--name", "mine"]) |
| 136 | 136 | } |
| 137 | 137 | |
| 138 | /// Surrounding whitespace must not reach the server — the name is |
| 139 | /// trimmed, not just tested for blankness. |
| 140 | @Test func forkingWithSurroundingWhitespaceTrimsTheName() async throws { |
| 141 | let (client, stub) = try makeClient() |
| 142 | stub.enqueue(.init(status: 200, json: """ |
| 143 | {"protocol_version":1,"data":{"path":"cmc/mine","fork_of":"krz/gitbay"},\ |
| 144 | "exit_code":0} |
| 145 | """)) |
| 146 | let model = RepoActionsViewModel(client: client, repoPath: "krz/gitbay") |
| 147 | _ = await model.fork(named: " mine ") |
| 148 | |
| 149 | #expect(try argvOf(try #require(stub.seen.last)) |
| 150 | == ["repo", "fork", "krz/gitbay", "--name", "mine"]) |
| 151 | } |
| 152 | |
| 138 | 153 | /// A blank name must not send an empty flag value. |
| 139 | 154 | @Test func forkingWithABlankNameOmitsTheFlag() async throws { |
| 140 | 155 | let (client, stub) = try makeClient() |
| @@ -182,4 +197,39 @@ struct RepoActionsTests { |
| 182 | 197 | #expect(model.notice == nil) |
| 183 | 198 | #expect(model.actionError?.isEmpty == false) |
| 184 | 199 | } |
| 200 | |
| 201 | /// A 0-exit fork whose envelope carries no `data` must not fail |
| 202 | /// silently — the caller needs to know nothing came back. |
| 203 | @Test func aForkThatReportsNothingBackSetsAnError() async throws { |
| 204 | let (client, stub) = try makeClient() |
| 205 | stub.enqueue(.init(status: 200, json: """ |
| 206 | {"protocol_version":1,"exit_code":0} |
| 207 | """)) |
| 208 | let model = RepoActionsViewModel(client: client, repoPath: "krz/gitbay") |
| 209 | let result = await model.fork(named: nil) |
| 210 | |
| 211 | #expect(result == nil) |
| 212 | #expect(model.actionError?.isEmpty == false) |
| 213 | } |
| 214 | |
| 215 | /// A bookmark write must be followed by a re-read of `repo |
| 216 | /// bookmarks` — that re-read is what keeps `isBookmarked` honest |
| 217 | /// instead of an optimistic local guess. |
| 218 | @Test func bookmarkingRereadsTheListingAfterTheWrite() async throws { |
| 219 | let (client, stub) = try makeClient() |
| 220 | stub.enqueue(.init(status: 200, json: bookmarks)) |
| 221 | let model = RepoActionsViewModel(client: client, repoPath: "krz/other") |
| 222 | await model.loadBookmarkState() |
| 223 | #expect(model.isBookmarked == false) |
| 224 | |
| 225 | stub.enqueue(.init(status: 200, json: ok)) |
| 226 | stub.enqueue(.init(status: 200, json: bookmarks)) |
| 227 | await model.setBookmarked(true) |
| 228 | |
| 229 | let calls = stub.seen.suffix(2) |
| 230 | let write = try #require(calls.first) |
| 231 | let reread = try #require(calls.last) |
| 232 | #expect(try argvOf(write) == ["repo", "bookmark", "krz/other"]) |
| 233 | #expect(argvFrom(reread.url) == ["repo", "bookmarks"]) |
| 234 | } |
| 185 | 235 | } |