Implemented phase 6 for the POC prototype in the Website service.

This commit is contained in:
javier committed 2026-09-21 13:53:13 +02:00
1 parent 256d22df40
commit f2f445827b
40 files changed
+1906 -37

No files matched your search

@@ -140,7 +140,7 @@ struct AccountAndCollectingControllerTests {
_ = try await post(client, "/wants/\(id)/remove", "", as: mara)
try await client.execute(uri: "/wants", method: .get, headers: [.cookie: mara]) { response in
#expect(String(buffer: response.body).contains("Nothing on your list yet"))
#expect(String(buffer: response.body).contains("No wants yet"))
}
}
}
@@ -266,7 +266,7 @@ private extension AccountAndCollectingControllerTests {
let sessions = SessionStore(trade: .init(fluent: fluent), collecting: collecting)
let router = Router(context: WebsiteRequestContext.self)
router.addRoutes(CatalogueController<WebsiteRequestContext>(repository: catalogue, sessions: sessions).routes)
router.addRoutes(CatalogueController<WebsiteRequestContext>(repository: catalogue, sessions: sessions, collecting: collecting).routes)
router.addRoutes(SessionController<WebsiteRequestContext>(sessions: sessions, accounts: accounts, catalogue: catalogue).routes)
router.addRoutes(AccountController<WebsiteRequestContext>(accounts: accounts, catalogue: catalogue, sessions: sessions).routes)
router.addRoutes(CollectingController<WebsiteRequestContext>(collecting: collecting, catalogue: catalogue, sessions: sessions).routes)
@@ -282,3 +282,100 @@ private extension AccountAndCollectingControllerTests {
}
}
// MARK: - Collection, events, and recovery
extension AccountAndCollectingControllerTests {
@Test
func `keeps a collection through its form and the switches on a series`() async throws {
try await withApp { client in
let mara = try await signIn(client)
_ = try await post(client, "/collection", "series=echo-country&issues=1-3%2C+9", as: mara)
_ = try await post(client, "/series/echo-country/own", "issue=5", as: mara)
_ = try await post(client, "/series/echo-country/own", "issue=1", as: mara)
try await client.execute(uri: "/collection", method: .get, headers: [.cookie: mara]) { response in
let body = String(buffer: response.body)
// #2, #3 and #5: #9 is outside the six-issue run, and #1 was switched back off.
#expect(body.contains(">3/6<"))
#expect(body.contains("3 missing · 1 listed now"))
}
try await client.execute(uri: "/series/echo-country", method: .get, headers: [.cookie: mara]) { response in
#expect(String(buffer: response.body).contains("3 of 6 owned"))
}
}
}
@Test
func `serves the events, and narrows a search to the copies to pick up at one`() async throws {
try await withApp { client in
try await client.execute(uri: "/events", method: .get) { response in
let body = String(buffer: response.body)
#expect(response.status == .ok)
#expect(body.contains("Dutch Comic Con"))
#expect(body.contains("Comic Con Brussels"))
}
// Silverfish alone trades at Stripdagen.
try await client.execute(uri: "/search?pickup=stripdagen-haarlem&ships-from=anywhere", method: .get) { response in
let body = String(buffer: response.body)
#expect(body.contains("4 listings"))
#expect(body.contains("from 1 shop"))
}
try await client.execute(uri: "/search?pickup=no-such-event", method: .get) { response in
#expect(String(buffer: response.body).contains("No listings match"))
}
try await client.execute(uri: "/listing/nightward-1-cgc-9-8", method: .get) { response in
#expect(String(buffer: response.body).contains("or pick up at Dutch Comic Con"))
}
}
}
@Test
func `hands a recovery link to an account's email alone, good until it runs out`() async throws {
try await withApp { client in
let link = try await client.execute(
uri: "/recover",
method: .post,
headers: Self.form,
body: ByteBuffer(string: "email=Mara.V%40example.com")
) { response in
let body = String(buffer: response.body)
#expect(response.status == .ok)
#expect(response.headers[.cacheControl] == "no-store")
return String(try #require(body.firstMatch(of: /\/recover\/[0-9a-f]{64}/)).output)
}
try await client.execute(uri: link, method: .get) { response in
#expect(response.status == .ok)
#expect(String(buffer: response.body).contains("Set up a new passkey"))
}
try await client.execute(uri: "/recover/0000", method: .get) { response in
#expect(response.status == .gone)
}
try await client.execute(uri: "/recover", method: .post, headers: Self.form, body: ByteBuffer(string: "email=nobody%40example.com")) { response in
let body = String(buffer: response.body)
#expect(body.contains("No account has that email"))
#expect(body.firstMatch(of: /\/recover\/[0-9a-f]{64}/) == nil)
}
try await client.execute(uri: "/recover", method: .post, headers: Self.form, body: ByteBuffer(string: "email=nope")) { response in
#expect(response.status == .unprocessableContent)
}
}
}
}