Files
ccn/Packages/Persistence/Tests/Cases/Public/Methods/ServiceTests.swift
T
javierandClaude Opus 5.5 911424de24 Project updates from Template
This commit contains the latest updates from the generic Website template, which move the toolchain to Swift 6.4, gate analytics and structured data behind traits, and rework page routing:

- Updated the Swift toolchain for all the package dependencies and the Website service to version 6.4. (345b305)
- Adapted all the existing middlewares in the Infrastructure package to Swift 6.4. (26008df)
- Moved test resource teardown in the Persistence and the Website library into defer blocks. (27984a9)
- Gated analytics behind a trait and reworked structured data in the Infrastructure package. (c7d4769)
- Enabled the Analytics trait in the Website service. (f6a6bbd)
- Reworked page routing in the Website service. (d1cb2c1)
- Gated the structured data features in the Infrastructure package behind a trait. (f0a8791)
- Enabled the StructuredData trait of the Infrastructure package in the Website service. (bbfdeb3)
- Fixed the asset pin and a build warning in the Dockerfile of the Website service. (6ed0f9b)

The root README change in 345b305 was left out, as this project no longer carries that file. From d1cb2c1, the RootController rework was left out, as the prototype serves a session-aware landing page and routes its other pages through their own controllers; the view-event reporter was appended to the prototype's shared script instead.

The prototype code was adapted to the stricter Swift 6.4 settings: `String(format:)` was swapped for safe formatting, the NoIndex middleware takes a `@concurrent` next handler, and the tests flagged by warnings-as-errors were tightened.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 11:55:43 +01:00

165 lines
4.6 KiB
Swift

import Foundation
import Logging
import SQLKit
import Testing
@testable import Persistence
@Suite(
"Service method",
.tags(.method)
)
struct ServiceTests {
// MARK: Methods tests
@Test
func `registers an SQLite database as the default for the in-memory driver`() async throws {
let service = try Service(
driver: .inMemory,
logger: Logger(label: "test")
)
let fluent = service()
let database = fluent.db() as? any SQLDatabase
try await fluent.shutdown()
let dialect = try #require(database?.dialect)
#expect(dialect.name == "sqlite")
}
@Test
func `registers a PostgreSQL database as the default for the postgres driver`() async throws {
// Resolving the default database opens no connection — pooling is lazy — so no server
// needs to be listening on the configured host and port.
let service = try Service(
driver: .postgres(
.init(
host: "127.0.0.1",
port: 5432,
name: "site",
username: "site",
password: "site",
tls: .off,
maxConnectionsPerEventLoop: 1,
poolTimeout: .seconds(10)
)
),
logger: Logger(label: "test")
)
let fluent = service()
let database = fluent.db() as? any SQLDatabase
try await fluent.shutdown()
let dialect = try #require(database?.dialect)
#expect(dialect.name == "postgresql")
}
@Test
func `builds a usable in-memory database`() async throws {
let service = try Service(
driver: .inMemory,
logger: Logger(label: "test")
)
let fluent = service()
defer {
try? await fluent.shutdown()
}
let database = try #require(fluent.db() as? any SQLDatabase)
try await database.raw("SELECT 1").run()
}
@Test("in-memory: migrate, seed, read back")
func inMemoryRoundTrip() async throws {
try await roundTrip(driver: .inMemory)
}
@Test(
"postgres: migrate, seed, read back",
.enabled(if: postgresDriver != nil)
)
func postgresRoundTrip() async throws {
try await roundTrip(
driver: postgresDriver!,
revertAfter: true
)
}
}
// MARK: - Helpers
private extension ServiceTests {
/// Migrates, seeds, and reads the catalogue back against the given driver, shutting the pool down after.
///
/// The `Fluent` service normally owns pool shutdown via its `run()` in the service group; outside that,
/// the test must shut it down explicitly — even on failure — or the pool asserts on `deinit`.
/// - Parameters:
/// - driver: the persistence backend to exercise.
/// - revertAfter: whether to revert the migrations afterwards; set for a shared database (the
/// in-memory database is discarded on shutdown, so it needs no revert).
func roundTrip(
driver: Persistence.Driver,
revertAfter: Bool = false
) async throws {
let prepareDB = PrepareDB()
let service = try Service(
driver: driver,
logger: Logger(label: "test")
)
let fluent = service()
defer {
try? await fluent.shutdown()
}
await prepareDB(for: fluent)
try await fluent.migrate()
let repository = CatalogueRepository(fluent: fluent)
#expect(try await !repository.listings().isEmpty)
if revertAfter {
try await fluent.revert()
}
}
}
/// The PostgreSQL driver built from the `POSTGRES_TEST_*` environment variables, or `nil` when the gate
/// variable `POSTGRES_TEST_HOST` is unset — in which case the PostgreSQL integration test is skipped, so
/// the suite stays runnable with no database available.
private let postgresDriver: Persistence.Driver? = {
let environment = ProcessInfo.processInfo.environment
guard let host = environment["POSTGRES_TEST_HOST"] else {
return nil
}
return .postgres(
.init(
host: host,
port: environment["POSTGRES_TEST_PORT"].flatMap(Int.init) ?? 5432,
name: environment["POSTGRES_TEST_NAME"] ?? "site",
username: environment["POSTGRES_TEST_USERNAME"] ?? "site",
password: environment["POSTGRES_TEST_PASSWORD"] ?? "site",
tls: .off,
maxConnectionsPerEventLoop: 2,
poolTimeout: .seconds(10)
)
)
}()