@testable import DatabaseClientLive import Dependencies import FluentSQLiteDriver import Foundation import Logging import NIO import SharedModels import Testing @Suite("DatabaseClientTests") struct DatabaseClientTests { let logger: Logger init() async throws { let logger = Logger(label: "database-client-tests") self.logger = logger } // @Test // func testPath() { // let path = ApiRoute.router.path(for: .employee(.index)) // #expect(path == "/api/v1/employees") // } @Test func users() async throws { try await withDatabase(migrations: User.Migrate()) { $0.database.users = .live(database: $1) } operation: { @Dependency(\.database.users) var users let user = try await users.create(.init( username: "blob", email: "blob@example.com", password: "super-secret", confirmPassword: "super-secret" )) #expect(user.username == "blob") #expect(user.email == "blob@example.com") #expect(user.createdAt != nil) #expect(user.updatedAt != nil) let allUsers = try await users.fetchAll() #expect(allUsers.count == 1) #expect(allUsers.first == user) let fetched = try await users.get(user.id) #expect(fetched != nil) #expect(fetched == user) try await users.delete(user.id) let allUsers2 = try await users.fetchAll() #expect(allUsers2.count == 0) } } @Test func employees() async throws { try await withDatabase(migrations: Employee.Migrate()) { $0.database.employees = .live(database: $1) } operation: { @Dependency(\.database.employees) var employees let employee = try await employees.create(.init( firstName: "Blob", lastName: "Esquire" )) #expect(employee.firstName == "Blob") #expect(employee.lastName == "Esquire") #expect(employee.active) let allEmployees = try await employees.fetchAll() #expect(allEmployees.count == 1) #expect(allEmployees.first == employee) let inActiveEmployees = try await employees.fetchAll(.inactive) #expect(inActiveEmployees.count == 0) let activeEmployees = try await employees.fetchAll(.active) #expect(activeEmployees == allEmployees) let fetched = try await employees.get(employee.id) #expect(fetched == employee) let updated = try await employees.update(employee.id, Employee.Update(active: false)) #expect(updated.active == false) let inActiveEmployees2 = try await employees.fetchAll(.inactive) #expect(inActiveEmployees2.count == 1) try await employees.delete(employee.id) let shouldBeNone = try await employees.fetchAll() #expect(shouldBeNone.count == 0) } } @Test func vendors() async throws { try await withDatabase(migrations: Vendor.Migrate(), VendorBranch.Migrate()) { $0.database.vendorBranches = .live(database: $1) $0.database.vendors = .live(database: $1) } operation: { @Dependency(\.database.vendorBranches) var branches @Dependency(\.database.vendors) var vendors let vendor = try await vendors.create(.init(name: "Corken")) #expect(vendor.name == "Corken") let branch = try await branches.create(.init(name: "Monroe", vendorID: vendor.id)) #expect(branch.name == "Monroe") let all = try await vendors.fetchAll() #expect(all.count == 1) #expect(all.first == vendor) let allWithBranches = try await vendors.fetchAll(.withBranches) #expect(allWithBranches.count == 1) #expect(allWithBranches.first!.branches!.first == branch) let fetched = try await vendors.get(vendor.id) #expect(fetched == vendor) let fetchedWithBranches = try await vendors.get(vendor.id, .withBranches) #expect(fetchedWithBranches!.branches!.first == branch) let updated = try await vendors.update(vendor.id, with: .init(name: "Johnstone")) #expect(updated.name == "Johnstone") try await vendors.delete(vendor.id) let shouldBeNone = try await vendors.fetchAll() #expect(shouldBeNone.count == 0) } } @Test func vendorBranches() async throws { try await withDatabase(migrations: Vendor.Migrate(), VendorBranch.Migrate()) { $0.database.vendorBranches = .live(database: $1) $0.database.vendors = .live(database: $1) } operation: { @Dependency(\.database.vendorBranches) var branches @Dependency(\.database.vendors) var vendors let vendor = try await vendors.create(.init(name: "Corken")) #expect(vendor.name == "Corken") let branch = try await branches.create(.init(name: "Monroe", vendorID: vendor.id)) #expect(branch.name == "Monroe") let all = try await branches.fetchAll() #expect(all.count == 1) let fetched = try await branches.get(branch.id) #expect(fetched == branch) let updated = try await branches.update(branch.id, .init(name: "Covington")) #expect(updated.name == "Covington") try await branches.delete(branch.id) let shouldBeNone = try await branches.fetchAll() #expect(shouldBeNone.count == 0) } } // Helper to create an in-memory database for testing. func withDatabase( migrations: (any AsyncMigration)..., setupDependencies: (inout DependencyValues, any Database) -> Void, operation: () async throws -> Void ) async throws { let dbs = Databases(threadPool: NIOThreadPool.singleton, on: MultiThreadedEventLoopGroup.singleton) dbs.use(.sqlite(.memory), as: .sqlite) let database = dbs.database( .sqlite, logger: .init(label: "test.sqlite"), on: MultiThreadedEventLoopGroup.singleton.any() )! for migration in migrations { try await migration.prepare(on: database) } try await withDependencies { $0.uuid = .incrementing $0.date = .init { Date() } setupDependencies(&$0, database) } operation: { try await operation() } for migration in migrations { try await migration.revert(on: database) } await dbs.shutdownAsync() } }