| @@ -148,3 +148,86 @@ struct CommitDetailTests { |
| 148 | 148 | } |
| 149 | 149 | } |
| 150 | 150 | } |
| 151 | |
| 152 | private func postArgv(_ stub: StubProtocol.Box) throws -> [([String], String?)] { |
| 153 | try stub.seen.filter { $0.method == "POST" }.map { seen in |
| 154 | let body = try #require(try JSONSerialization.jsonObject(with: seen.body) as? [String: Any]) |
| 155 | return (try #require(body["argv"] as? [String]), body["stdin"] as? String) |
| 156 | } |
| 157 | } |
| 158 | |
| 159 | private let okCmdJSON = #"{"protocol_version":1,"exit_code":0}"# |
| 160 | |
| 161 | @MainActor |
| 162 | struct AboutFileTests { |
| 163 | |
| 164 | /// The web's "profile-repo" form: create <owner>/.gitbay, commit a |
| 165 | /// starter README, show the result. |
| 166 | @Test func createsTheRepositoryAndAStarterFile() async throws { |
| 167 | let (client, stub) = try makeClient() |
| 168 | stub.enqueue(.init(status: 404, json: |
| 169 | #"{"protocol_version":1,"error":"no repository cmc/.gitbay","exit_code":3}"#, |
| 170 | match: "argv=repo&argv=show")) |
| 171 | stub.enqueue(.init(status: 200, json: okCmdJSON, match: "cmd")) |
| 172 | stub.enqueue(.init(status: 200, json: okCmdJSON, match: "cmd")) |
| 173 | stub.enqueue(.init(status: 200, json: userProfileJSON, match: "argv=profile&argv=show")) |
| 174 | let model = ProfileViewModel(client: client, name: "cmc") |
| 175 | |
| 176 | let created = await model.createAboutFile() |
| 177 | |
| 178 | #expect(created) |
| 179 | #expect(model.actionError == nil) |
| 180 | let writes = try postArgv(stub) |
| 181 | #expect(writes.map(\.0) == [ |
| 182 | ["repo", "create", "cmc/.gitbay"], |
| 183 | ["repo", "commit-file", "cmc/.gitbay", "profile/README.md", "--ref", "main", |
| 184 | "--message", "add profile about", "--file", "-"], |
| 185 | ]) |
| 186 | #expect(writes[1].1 == "# cmc\n\nThis is the about text on your profile.\n") |
| 187 | #expect(model.state.value?.aboutPath == "profile/README.org") |
| 188 | } |
| 189 | |
| 190 | /// A .gitbay repository can exist without an about file in it — it |
| 191 | /// holds other per-owner configuration too. Creating it again would |
| 192 | /// fail, so only the file is written. |
| 193 | @Test func skipsCreateWhenTheRepositoryExists() async throws { |
| 194 | let (client, stub) = try makeClient() |
| 195 | stub.enqueue(.init(status: 200, json: |
| 196 | #"{"protocol_version":1,"data":{"path":"krz/.gitbay"},"exit_code":0}"#, |
| 197 | match: "argv=repo&argv=show")) |
| 198 | stub.enqueue(.init(status: 200, json: okCmdJSON, match: "cmd")) |
| 199 | stub.enqueue(.init(status: 200, json: orgProfileJSON, match: "argv=profile&argv=show")) |
| 200 | let model = ProfileViewModel(client: client, name: "krz") |
| 201 | |
| 202 | let created = await model.createAboutFile() |
| 203 | |
| 204 | #expect(created) |
| 205 | let writes = try postArgv(stub) |
| 206 | #expect(writes.count == 1) |
| 207 | #expect(Array(writes[0].0.prefix(4)) == ["repo", "commit-file", "krz/.gitbay", "profile/README.md"]) |
| 208 | #expect(writes[0].1 == "# krz\n\nThis is the about text on your profile.\n") |
| 209 | } |
| 210 | |
| 211 | /// A refused create must not go on to write a file into nothing. |
| 212 | @Test func aRefusedCreateStopsAndSurfaces() async throws { |
| 213 | let (client, stub) = try makeClient() |
| 214 | stub.enqueue(.init(status: 404, json: |
| 215 | #"{"protocol_version":1,"error":"no repository krz/.gitbay","exit_code":3}"#, |
| 216 | match: "argv=repo&argv=show")) |
| 217 | stub.enqueue(.init(status: 200, json: |
| 218 | #"{"protocol_version":1,"error":"only admins of krz can create repositories there","exit_code":4}"#, |
| 219 | match: "cmd")) |
| 220 | let model = ProfileViewModel(client: client, name: "krz") |
| 221 | |
| 222 | let created = await model.createAboutFile() |
| 223 | |
| 224 | #expect(created == false) |
| 225 | #expect(model.actionError?.isEmpty == false) |
| 226 | #expect(try postArgv(stub).count == 1) |
| 227 | } |
| 228 | |
| 229 | @Test func theAboutRepositoryIsTheOwnersDotGitbay() throws { |
| 230 | let (client, _) = try makeClient() |
| 231 | #expect(ProfileViewModel(client: client, name: "cmc").aboutRepo == "cmc/.gitbay") |
| 232 | } |
| 233 | } |