| @@ -6,11 +6,9 @@ struct ProfileEditFlagTests { |
| 6 | |
6 | |
| 7 | private func edit( |
7 | private func edit( |
| 8 | description: String = "", website: String = "", |
8 | description: String = "", website: String = "", |
| 9 | about: String = "", aboutFormat: String = "md", |
| |
| 10 | links: [ProfileEdit.Link] = [] |
9 | links: [ProfileEdit.Link] = [] |
| 11 | ) -> ProfileEdit { |
10 | ) -> ProfileEdit { |
| 12 | ProfileEdit(description: description, website: website, |
11 | ProfileEdit(description: description, website: website, links: links) |
| 13 | about: about, aboutFormat: aboutFormat, links: links) |
| |
| 14 | } |
12 | } |
| 15 | |
13 | |
| 16 | @Test func everyFieldSendsItsFlag() { |
14 | @Test func everyFieldSendsItsFlag() { |
| @@ -59,19 +57,14 @@ struct ProfileEditFlagTests { |
| 59 | #expect(flags.contains("|https://a.test") == false) |
57 | #expect(flags.contains("|https://a.test") == false) |
| 60 | } |
58 | } |
| 61 | |
59 | |
| 62 | /// Long-form text with newlines belongs in stdin, not argv. |
60 | /// Since gitbay v1.31.0 the about text is a file in <owner>/.gitbay, |
| 63 | @Test func theAboutTextGoesToStdinNotArgv() { |
61 | /// and `profile set` refuses any of these as an unknown flag (exit 2). |
| 64 | let e = edit(about: "line one\n\nline two", aboutFormat: "org") |
62 | @Test func noAboutFlagIsSent() { |
| 65 | #expect(e.flags().contains { $0.contains("line one") } == false) |
63 | let flags = edit(description: "hi", website: "https://x.test", |
| 66 | #expect(e.flags().contains("--file")) |
64 | links: [.init(label: "a", url: "https://a.test")]).flags() |
| 67 | #expect(e.flags().contains("-")) |
65 | #expect(!flags.contains("--about")) |
| 68 | #expect(e.aboutStdin == "line one\n\nline two") |
66 | #expect(!flags.contains("--about-format")) |
| 69 | } |
67 | #expect(!flags.contains("--file")) |
| 70 | |
| |
| 71 | @Test func theAboutFormatAccompaniesTheText() { |
| |
| 72 | let flags = edit(about: "x", aboutFormat: "org").flags() |
| |
| 73 | let i = try! #require(flags.firstIndex(of: "--about-format")) |
| |
| 74 | #expect(flags[i + 1] == "org") |
| |
| 75 | } |
68 | } |
| 76 | |
69 | |
| 77 | @Test func moreThanFiveLinksIsInvalid() { |
70 | @Test func moreThanFiveLinksIsInvalid() { |
| @@ -103,36 +96,17 @@ struct ProfileEditFromProfileTests { |
| 103 | "repos":[],"activity_total":0} |
96 | "repos":[],"activity_total":0} |
| 104 | """ |
97 | """ |
| 105 | |
98 | |
| 106 | /// The real profile on gitbay.org is org, with tables and links that |
99 | @Test func seedsFromTheProfile() throws { |
| 107 | /// render as flat text under markdown — the stored format must round |
| |
| 108 | /// trip, not default away from what the server holds. |
| |
| 109 | @Test func seedsFromAnOrgProfile() throws { |
| |
| 110 | let data = try #require(orgProfileJSON.data(using: .utf8)) |
100 | let data = try #require(orgProfileJSON.data(using: .utf8)) |
| 111 | let profile = try JSONDecoder().decode(ProfileViewModel.Profile.self, from: data) |
101 | let profile = try JSONDecoder().decode(ProfileViewModel.Profile.self, from: data) |
| 112 | |
102 | |
| 113 | let edit = ProfileEdit(from: profile) |
103 | let edit = ProfileEdit(from: profile) |
| 114 | |
104 | |
| 115 | #expect(edit.aboutFormat == "org") |
| |
| 116 | #expect(edit.description == "about me") |
105 | #expect(edit.description == "about me") |
| 117 | #expect(edit.website == "https://cleberg.net") |
106 | #expect(edit.website == "https://cleberg.net") |
| 118 | #expect(edit.about == "* heading\n\n| a | b |") |
| |
| 119 | #expect(edit.links.map(\.url) == ["https://a.test", "https://b.test"]) |
107 | #expect(edit.links.map(\.url) == ["https://a.test", "https://b.test"]) |
| 120 | #expect(edit.links.map(\.label) == ["", "blog"]) |
108 | #expect(edit.links.map(\.label) == ["", "blog"]) |
| 121 | } |
109 | } |
| 122 | |
| |
| 123 | /// Absent `about_format`, seeding falls back to markdown. |
| |
| 124 | @Test func seedingFallsBackToMarkdownWhenFormatIsAbsent() throws { |
| |
| 125 | let json = """ |
| |
| 126 | {"name":"cmc","kind":"user",\ |
| |
| 127 | "description":"hi","repos":[],"activity_total":0} |
| |
| 128 | """ |
| |
| 129 | let data = try #require(json.data(using: .utf8)) |
| |
| 130 | let profile = try JSONDecoder().decode(ProfileViewModel.Profile.self, from: data) |
| |
| 131 | |
| |
| 132 | let edit = ProfileEdit(from: profile) |
| |
| 133 | |
| |
| 134 | #expect(edit.aboutFormat == "md") |
| |
| 135 | } |
| |
| 136 | } |
110 | } |
| 137 | |
111 | |
| 138 | private func makeClient() throws -> (GitbayClient, StubProtocol.Box) { |
112 | private func makeClient() throws -> (GitbayClient, StubProtocol.Box) { |
| @@ -170,14 +144,13 @@ struct ProfileSaveTests { |
| 170 | /// The write, then the reload `profile set` triggers — one POST, one |
144 | /// The write, then the reload `profile set` triggers — one POST, one |
| 171 | /// GET. Both need a stub or the flow ends up looking like a refusal |
145 | /// GET. Both need a stub or the flow ends up looking like a refusal |
| 172 | /// even when the write itself succeeded. |
146 | /// even when the write itself succeeded. |
| 173 | @Test func savesTheFullArgvWithAboutOnlyInStdin() async throws { |
147 | @Test func savesScalarsAndLinksWithNoStdin() async throws { |
| 174 | let (client, stub) = try makeClient() |
148 | let (client, stub) = try makeClient() |
| 175 | stub.enqueue(.init(status: 200, json: okJSON, match: "cmd")) |
149 | stub.enqueue(.init(status: 200, json: okJSON, match: "cmd")) |
| 176 | stub.enqueue(.init(status: 200, json: profileJSON, match: "argv=show")) |
150 | stub.enqueue(.init(status: 200, json: profileJSON, match: "argv=show")) |
| 177 | let model = ProfileViewModel(client: client, name: "cmc") |
151 | let model = ProfileViewModel(client: client, name: "cmc") |
| 178 | let edit = ProfileEdit( |
152 | let edit = ProfileEdit( |
| 179 | description: "hi", website: "https://cleberg.net", |
153 | description: "hi", website: "https://cleberg.net", |
| 180 | about: "long form\n\nprose", aboutFormat: "org", |
| |
| 181 | links: [.init(label: "blog", url: "https://b.test")] |
154 | links: [.init(label: "blog", url: "https://b.test")] |
| 182 | ) |
155 | ) |
| 183 | |
156 | |
| @@ -190,10 +163,8 @@ struct ProfileSaveTests { |
| 190 | "profile", "set", |
163 | "profile", "set", |
| 191 | "--description", "hi", "--website", "https://cleberg.net", |
164 | "--description", "hi", "--website", "https://cleberg.net", |
| 192 | "--link", "blog|https://b.test", |
165 | "--link", "blog|https://b.test", |
| 193 | "--about-format", "org", "--file", "-", |
| |
| 194 | ]) |
166 | ]) |
| 195 | #expect(stdin == "long form\n\nprose") |
167 | #expect(stdin == nil) |
| 196 | #expect(argv.contains { $0.contains("long form") } == false) |
| |
| 197 | } |
168 | } |
| 198 | |
169 | |
| 199 | /// An org's profile is written by `org profile <org>`, with the same |
170 | /// An org's profile is written by `org profile <org>`, with the same |