Initial commit.
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
import Elementary
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@testable import Infrastructure
|
||||
|
||||
@Suite(
|
||||
"Page protocol",
|
||||
.tags(.`protocol`)
|
||||
)
|
||||
struct PageTests {
|
||||
|
||||
// MARK: Functional tests
|
||||
|
||||
@Test
|
||||
func `assembles the document around the page's parts`() {
|
||||
let html = StubPage().render()
|
||||
|
||||
#expect(html.contains("<title>Stub Page</title>"))
|
||||
#expect(html.contains(#"lang="en""#))
|
||||
#expect(html.contains(#"name="viewport""#))
|
||||
#expect(html.contains(#"<meta name="stub" content="marker">"#))
|
||||
#expect(html.contains(#"<link rel="stylesheet" href="/css/stub.css">"#))
|
||||
#expect(html.contains(#"<script defer src="/js/stub.js"></script>"#))
|
||||
#expect(html.contains("Stub content"))
|
||||
}
|
||||
|
||||
@Test
|
||||
func `places the metadata between the viewport and the stylesheets`() throws {
|
||||
let html = StubPage().render()
|
||||
|
||||
let viewport = try #require(html.range(of: #"name="viewport""#))
|
||||
let metadata = try #require(html.range(of: #"name="stub""#))
|
||||
let stylesheet = try #require(html.range(of: "/css/stub.css"))
|
||||
|
||||
#expect(viewport.lowerBound < metadata.lowerBound)
|
||||
#expect(metadata.lowerBound < stylesheet.lowerBound)
|
||||
}
|
||||
|
||||
@Test
|
||||
func `renders the scripts deferred in the head, after the stylesheets`() throws {
|
||||
let html = StubPage().render()
|
||||
|
||||
let stylesheet = try #require(html.range(of: "/css/stub.css"))
|
||||
let script = try #require(html.range(of: "/js/stub.js"))
|
||||
let content = try #require(html.range(of: "Stub content"))
|
||||
|
||||
// Deferred head scripts start downloading during head parsing but still execute, in order, only after the
|
||||
// document is parsed — the semantics end-of-body tags gave, minus the late download start.
|
||||
#expect(stylesheet.lowerBound < script.lowerBound)
|
||||
#expect(script.lowerBound < content.lowerBound)
|
||||
}
|
||||
|
||||
@Test
|
||||
func `omits the summary and canonical tags by default`() {
|
||||
let html = StubPage().render()
|
||||
|
||||
#expect(!html.contains(#"name="description""#))
|
||||
#expect(!html.contains(#"rel="canonical""#))
|
||||
}
|
||||
|
||||
@Test
|
||||
func `renders the summary and canonical tags when provided`() {
|
||||
let html = StubPage(
|
||||
canonicalURL: "https://stub.example/",
|
||||
summary: "A stub page."
|
||||
).render()
|
||||
|
||||
#expect(html.contains(#"<meta name="description" content="A stub page.">"#))
|
||||
#expect(html.contains(#"<link rel="canonical" href="https://stub.example/">"#))
|
||||
}
|
||||
|
||||
@Test
|
||||
func `omits the social card tags by default`() {
|
||||
let html = StubPage().render()
|
||||
|
||||
#expect(!html.contains(#"property="og:"#))
|
||||
#expect(!html.contains(#"name="twitter:card""#))
|
||||
}
|
||||
|
||||
@Test
|
||||
func `renders the social card tags when provided`() {
|
||||
let html = StubPage(socialCard: .init(
|
||||
title: "Stub Page",
|
||||
summary: "A stub page.",
|
||||
url: "https://stub.example/",
|
||||
image: .init(
|
||||
url: "https://stub.example/img/card.png",
|
||||
width: 2400,
|
||||
height: 1260
|
||||
)
|
||||
)).render()
|
||||
|
||||
#expect(html.contains(#"<meta property="og:type" content="website">"#))
|
||||
#expect(html.contains(#"<meta property="og:title" content="Stub Page">"#))
|
||||
#expect(html.contains(#"<meta property="og:description" content="A stub page.">"#))
|
||||
#expect(html.contains(#"<meta property="og:url" content="https://stub.example/">"#))
|
||||
#expect(html.contains(#"<meta property="og:image" content="https://stub.example/img/card.png">"#))
|
||||
#expect(html.contains(#"<meta property="og:image:width" content="2400">"#))
|
||||
#expect(html.contains(#"<meta property="og:image:height" content="1260">"#))
|
||||
#expect(html.contains(#"<meta name="twitter:card" content="summary_large_image">"#))
|
||||
}
|
||||
|
||||
@Test
|
||||
func `omits the structured data script by default`() {
|
||||
let html = StubPage().render()
|
||||
|
||||
#expect(!html.contains("application/ld+json"))
|
||||
}
|
||||
|
||||
@Test
|
||||
func `renders the structured data script when provided`() {
|
||||
let html = StubPage(structuredData: .init(
|
||||
name: "Stub Site",
|
||||
url: "https://stub.example/",
|
||||
logo: "https://stub.example/logo.png",
|
||||
profiles: ["https://social.example/stub"]
|
||||
)).render()
|
||||
|
||||
#expect(html.contains(
|
||||
#"<script type="application/ld+json">"# +
|
||||
#"{"@context":"https://schema.org","@graph":["# +
|
||||
#"{"@type":"Organization","@id":"https://stub.example/#organization","name":"Stub Site","url":"https://stub.example/","logo":"https://stub.example/logo.png","sameAs":["https://social.example/stub"]},"# +
|
||||
#"{"@type":"WebSite","name":"Stub Site","url":"https://stub.example/","publisher":{"@id":"https://stub.example/#organization"}}]}"# +
|
||||
#"</script>"#
|
||||
))
|
||||
}
|
||||
|
||||
@Test
|
||||
func `omits the analytics tracker by default`() {
|
||||
let html = StubPage().render()
|
||||
|
||||
#expect(!html.contains("data-website-id"))
|
||||
#expect(!html.contains(#"rel="preconnect""#))
|
||||
}
|
||||
|
||||
@Test
|
||||
func `renders the analytics tracker when provided`() throws {
|
||||
let html = StubPage(analytics: .init(
|
||||
scriptURL: "https://analytics.example.com/script",
|
||||
websiteID: "0000-website-id",
|
||||
domains: "example.com"
|
||||
)).render()
|
||||
|
||||
#expect(html.contains(#"<script defer src="https://analytics.example.com/script" data-website-id="0000-website-id" data-domains="example.com" data-exclude-hash="true" data-do-not-track="true" data-performance="true"></script>"#))
|
||||
|
||||
// The preconnect hint warms the tracker origin's connection before the parser reaches the script tag.
|
||||
let preconnect = try #require(html.range(of: #"<link rel="preconnect" href="https://analytics.example.com">"#))
|
||||
let script = try #require(html.range(of: #"<script defer src="https://analytics.example.com/script""#))
|
||||
|
||||
#expect(preconnect.lowerBound < script.lowerBound)
|
||||
}
|
||||
|
||||
@Test
|
||||
func `omits the session recorder script by default`() {
|
||||
let html = StubPage(analytics: .init(
|
||||
scriptURL: "https://analytics.example.com/script",
|
||||
websiteID: "0000-website-id",
|
||||
domains: "example.com"
|
||||
)).render()
|
||||
|
||||
#expect(!html.contains("recorder.js"))
|
||||
}
|
||||
|
||||
@Test
|
||||
func `renders the session recorder script when recorder mode is on`() throws {
|
||||
let html = StubPage(analytics: .init(
|
||||
scriptURL: "https://analytics.example.com/script",
|
||||
websiteID: "0000-website-id",
|
||||
domains: "example.com",
|
||||
recorder: true
|
||||
)).render()
|
||||
|
||||
#expect(html.contains(#"<script defer src="https://analytics.example.com/recorder.js" data-website-id="0000-website-id"></script>"#))
|
||||
|
||||
let tracker = try #require(html.range(of: #"<script defer src="https://analytics.example.com/script""#))
|
||||
let recorder = try #require(html.range(of: #"<script defer src="https://analytics.example.com/recorder.js""#))
|
||||
|
||||
#expect(tracker.lowerBound < recorder.lowerBound)
|
||||
}
|
||||
|
||||
@Test
|
||||
func `omits the analytics behavior flags that are disabled`() {
|
||||
let html = StubPage(analytics: .init(
|
||||
scriptURL: "https://analytics.example.com/script",
|
||||
websiteID: "0000-website-id",
|
||||
domains: "example.com",
|
||||
excludeHash: true,
|
||||
doNotTrack: false,
|
||||
performance: false
|
||||
)).render()
|
||||
|
||||
#expect(html.contains(#"<script defer src="https://analytics.example.com/script" data-website-id="0000-website-id" data-domains="example.com" data-exclude-hash="true"></script>"#))
|
||||
#expect(!html.contains("data-do-not-track"))
|
||||
#expect(!html.contains("data-performance"))
|
||||
}
|
||||
|
||||
@Test
|
||||
func `appends the version token to the asset URLs`() {
|
||||
let html = StubPage(assetVersion: "0123456789abcdef").render()
|
||||
|
||||
#expect(html.contains("/css/stub.css?v=0123456789abcdef"))
|
||||
#expect(html.contains("/js/stub.js?v=0123456789abcdef"))
|
||||
}
|
||||
|
||||
@Test
|
||||
func `derives the document language from the locale`() {
|
||||
let html = StubPage(locale: .init(identifier: "de-DE")).render()
|
||||
|
||||
#expect(html.contains(#"lang="de""#))
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user