Implemented phase 2 for the POC prototype in the Website service.
This commit is contained in:
1 parent
09c7b8a1a7
commit
43dcc03da6
28 files changed
+1468
-65
No files matched your search
@@ -33,6 +33,8 @@ struct SiteHeaderTests {
|
||||
#expect(html.contains(#"aria-label="Messages, 3 unread""#))
|
||||
#expect(html.contains(#"href="/sell""#))
|
||||
#expect(html.contains(">MV<"))
|
||||
#expect(html.contains(">Mara<"))
|
||||
#expect(html.contains(#"action="/sign-out" method="post""#))
|
||||
#expect(!html.contains(#"href="/sign-in""#))
|
||||
}
|
||||
|
||||
|
||||
@@ -74,6 +74,30 @@ struct ListingDisplayTests {
|
||||
#expect(cents.euros == price)
|
||||
}
|
||||
|
||||
@Test(arguments: zip(
|
||||
["/listing/a?x=1", "/", "//evil.example", "https://evil.example", "/\\evil.example", "listing/a", "", "/a\nb"],
|
||||
["/listing/a?x=1", "/", "/", "/", "/", "/", "/", "/"]
|
||||
))
|
||||
func `follows a return path only within the site`(
|
||||
_ path: String,
|
||||
expects safe: String
|
||||
) {
|
||||
#expect(String.Route.safeReturn(path) == safe)
|
||||
}
|
||||
|
||||
@Test
|
||||
func `returns home without a return path`() {
|
||||
#expect(String.Route.safeReturn(nil) == "/")
|
||||
}
|
||||
|
||||
@Test
|
||||
func `leads a gated action to itself signed in, and to the sign-in signed out`() {
|
||||
let offer = String.Route.offer("a")
|
||||
|
||||
#expect(String.Route.gated(offer, from: "/listing/a", viewer: .init(displayName: "Mara")) == "/listing/a/offer")
|
||||
#expect(String.Route.gated(offer, from: "/listing/a", viewer: nil) == "/sign-in?return=/listing/a")
|
||||
}
|
||||
|
||||
@Test
|
||||
func `returns to the gated action's path after sign-in`() {
|
||||
#expect(String.Route.signIn(returningTo: "/shop/a?keys=1&page=2") == "/sign-in?return=/shop/a%3Fkeys%3D1%26page%3D2")
|
||||
|
||||
@@ -121,8 +121,71 @@ struct CataloguePagesTests {
|
||||
#expect(html.contains("<dt>Condition</dt>"))
|
||||
}
|
||||
|
||||
@Test
|
||||
func `listing page opens its actions to a signed-in viewer`() {
|
||||
let html = ListingPage(
|
||||
listing: .stub(),
|
||||
related: [],
|
||||
viewer: .init(displayName: "Mara Visser")
|
||||
).render()
|
||||
|
||||
#expect(html.contains(#"href="/listing/nightward-1/buy""#))
|
||||
#expect(html.contains(#"href="/listing/nightward-1/offer""#))
|
||||
#expect(html.contains(#"href="/messages/new?listing=nightward-1""#))
|
||||
#expect(html.contains(#"aria-label="Account of Mara Visser""#))
|
||||
#expect(!html.contains("gate-note"))
|
||||
#expect(html.contains(#"disabled title="Not part of the prototype">Save"#))
|
||||
}
|
||||
|
||||
// MARK: ShopPage tests
|
||||
|
||||
@Test
|
||||
func `shop page opens its actions to a signed-in viewer`() {
|
||||
let html = ShopPage(
|
||||
shop: .stub(),
|
||||
inventory: [],
|
||||
matches: [],
|
||||
parameters: .init(),
|
||||
viewer: .init(displayName: "Mara Visser")
|
||||
).render()
|
||||
|
||||
#expect(html.contains(#"href="/messages/new?shop=kestrel-row-comics""#))
|
||||
#expect(!html.contains("Both need a passkey sign-in"))
|
||||
#expect(!html.contains("/sign-in?return="))
|
||||
}
|
||||
|
||||
// MARK: SignInPage tests
|
||||
|
||||
@Test
|
||||
func `sign-in page is bare, states the intent, and carries the return path`() {
|
||||
let html = SignInPage(
|
||||
returnPath: "/listing/nightward-1",
|
||||
intent: "To buy Nightward #1"
|
||||
).render()
|
||||
|
||||
#expect(html.contains("To buy Nightward #1"))
|
||||
#expect(html.contains(#"action="/sign-in" method="post""#))
|
||||
#expect(html.contains(#"name="return" value="/listing/nightward-1""#))
|
||||
#expect(html.contains(#"href="/listing/nightward-1" aria-label="Close and go back""#))
|
||||
#expect(html.contains(#"content="noindex""#))
|
||||
#expect(html.contains("/css/sign-in.css"))
|
||||
#expect(!html.contains("site-header"))
|
||||
#expect(!html.contains("site-footer"))
|
||||
#expect(!html.contains("aria-invalid"))
|
||||
#expect(!html.contains("style="))
|
||||
}
|
||||
|
||||
@Test
|
||||
func `sign-in page ties an error to the email field`() {
|
||||
let html = SignInPage(
|
||||
returnPath: "/",
|
||||
error: "That doesn't look like an email address."
|
||||
).render()
|
||||
|
||||
#expect(html.contains(#"aria-invalid="true" aria-describedby="email-error""#))
|
||||
#expect(html.contains(#"id="email-error">That doesn't look like an email address.</p>"#))
|
||||
}
|
||||
|
||||
@Test
|
||||
func `shop page counts its tabs from the whole inventory and lists the matches`() {
|
||||
let inventory = [
|
||||
|
||||
@@ -108,6 +108,7 @@ private extension StaticFileTests {
|
||||
(.search, ["css/search.css"]),
|
||||
(.shared, ["css/shared.css", "js/shared.js"]),
|
||||
(.shop, ["css/shop.css"]),
|
||||
(.signIn, ["css/sign-in.css"]),
|
||||
(.site, ["site.webmanifest"]),
|
||||
(.sitemap, ["sitemap.xml"]),
|
||||
]
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Persistence
|
||||
import Testing
|
||||
|
||||
@testable import WebsiteLibrary
|
||||
@@ -8,6 +9,17 @@ import Testing
|
||||
)
|
||||
struct ViewerTests {
|
||||
|
||||
// MARK: Initializers tests
|
||||
|
||||
@Test
|
||||
func `signs in as the account's display name`() {
|
||||
let viewer = Viewer(User(id: .init(), email: "mara.v@example.com", displayName: "Mara Visser"))
|
||||
|
||||
#expect(viewer.displayName == "Mara Visser")
|
||||
#expect(viewer.newWantMatches == 0)
|
||||
#expect(viewer.unreadMessages == 0)
|
||||
}
|
||||
|
||||
// MARK: Computed tests
|
||||
|
||||
@Test(arguments: zip(
|
||||
@@ -21,4 +33,15 @@ struct ViewerTests {
|
||||
#expect(Viewer(displayName: displayName).initials == initials)
|
||||
}
|
||||
|
||||
@Test(arguments: zip(
|
||||
["Mara Visser", "Mara", ""],
|
||||
["Mara", "Mara", ""]
|
||||
))
|
||||
func `first name`(
|
||||
of displayName: String,
|
||||
expects firstName: String
|
||||
) {
|
||||
#expect(Viewer(displayName: displayName).firstName == firstName)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user