import Configuration import Infrastructure import Persistence import Testing @testable import Website @testable import WebsiteLibrary @Suite("ConfigReader properties") struct ConfigReaderPropertiesTests { // MARK: Functional tests @Test func `analytics to be omitted by default`() { // The template ships no website identifier, so an unconfigured deployment embeds no tracker at all. #expect(.Analytics.websiteID == "") #expect(reader().analytics == nil) } @Test func `analytics to be enabled by setting the website id alone`() throws { let analytics = try #require(reader(values: [ .Analytics.websiteID: "0000-website-id" ]).analytics) #expect(analytics.scriptURL == .Analytics.scriptURL) #expect(analytics.websiteID == "0000-website-id") #expect(analytics.domains.isEmpty) #expect(analytics.excludeHash) #expect(analytics.doNotTrack) #expect(analytics.performance) #expect(!analytics.recorder) } @Test func `analytics to switch recorder mode on when configured`() throws { // Session recording is the most invasive thing the tracker does, so it is opted into rather than out of. let analytics = try #require(reader(values: [ .Analytics.websiteID: "0000-website-id", .Analytics.recorder: true ]).analytics) #expect(analytics.recorder) } @Test func `analytics to override the website id and domains when configured`() throws { let analytics = try #require(reader(values: [ .Analytics.websiteID: "custom-website-id", .Analytics.domains: "staging.example.com" ]).analytics) #expect(analytics.websiteID == "custom-website-id") #expect(analytics.domains == "staging.example.com") #expect(analytics.scriptURL == .Analytics.scriptURL) } @Test func `analytics to be omitted when the website id is cleared`() { #expect(reader(values: [.Analytics.websiteID: ""]).analytics == nil) } @Test(arguments: [ "shared.css", "shared.js", "milker-400.woff2", "booth.mp4", "portrait.jpg", "portrait.webp" ]) func `cache control to mark the fingerprinted media immutable`( file: String ) throws { let header = try #require(reader().cacheControl.getCacheControlHeader(for: file)) #expect(header.contains("immutable")) } @Test(arguments: [ // The icons are exempt: a browser fetches `/favicon.ico` unversioned whatever the markup says, and the manifest names the PNGs. "favicon.ico", "icon-192.png", "icon.svg" ]) func `cache control to leave the unversioned images mutable`( file: String ) throws { let header = try #require(reader().cacheControl.getCacheControlHeader(for: file)) #expect(!header.contains("immutable")) } @Test func `cache control to have the unversioned text revalidate`() throws { let header = try #require(reader().cacheControl.getCacheControlHeader(for: "robots.txt")) #expect(header.contains("must-revalidate")) #expect(!header.contains("immutable")) } } // MARK: - Helpers private extension ConfigReaderPropertiesTests { // MARK: Methods /// Builds a configuration reader over the given in-memory values alone. func reader( values: [AbsoluteConfigKey: ConfigValue] = [:] ) -> ConfigReader { ConfigReader(providers: [ InMemoryProvider(values: values) ]) } }