feat: Adds script to generate database seeded values and removes old mock storage.

This commit is contained in:
2025-01-16 21:00:27 -05:00
parent 09b46f672a
commit e1d07008a1
16 changed files with 399 additions and 535 deletions

View File

@@ -0,0 +1,49 @@
#if DEBUG
import DatabaseClientLive
import Dependencies
import FluentSQLiteDriver
import SharedModels
import Vapor
struct SeedCommand: AsyncCommand {
struct Signature: CommandSignature {}
var help: String {
"Generate random seed database."
}
func run(using context: CommandContext, signature: Signature) async throws {
let database = DatabaseClient.live(database: context.application.db(.sqlite))
var users: [User] = []
var employees: [Employee] = []
var vendors: [Vendor] = []
var vendorBranches: [VendorBranch] = []
for user in User.Create.generateMocks() {
let created = try await database.users.create(user)
users.append(created)
}
for employee in Employee.Create.generateMocks() {
let created = try await database.employees.create(employee)
employees.append(created)
}
for vendor in Vendor.Create.generateMocks() {
let created = try await database.vendors.create(vendor)
vendors.append(created)
}
for branch in VendorBranch.Create.generateMocks(vendors: vendors) {
let created = try await database.vendorBranches.create(branch)
vendorBranches.append(created)
}
for purchaseOrder in PurchaseOrder.Create.generateMocks(employees: employees, vendorBranches: vendorBranches) {
_ = try await database.purchaseOrders.create(purchaseOrder, users.randomElement()!.id)
}
}
}
#endif

View File

@@ -30,7 +30,8 @@ public func configure(_ app: Application) async throws {
switch app.environment {
case .production, .development:
app.databases.use(DatabaseConfigurationFactory.sqlite(.file("db.sqlite")), as: .sqlite)
let dbFileName = Environment.get("SQLITE_FILENAME") ?? "db.sqlite"
app.databases.use(DatabaseConfigurationFactory.sqlite(.file(dbFileName)), as: .sqlite)
default:
app.databases.use(DatabaseConfigurationFactory.sqlite(.memory), as: .sqlite)
}
@@ -48,5 +49,6 @@ public func configure(_ app: Application) async throws {
if app.environment != .production {
try await app.autoMigrate()
app.asyncCommands.use(SeedCommand(), as: "seed")
}
}

View File

@@ -32,70 +32,3 @@ extension Employee.Update: Content {}
extension DatabaseClient.Employees: TestDependencyKey {
public static let testValue = Self()
}
#if DEBUG
typealias EmployeeMockStorage = MockStorage<
Employee,
Employee.Create,
DatabaseClient.Employees.FetchRequest,
Void,
Employee.Update
>
private extension EmployeeMockStorage {
init(_ mocks: [Employee]) {
@Dependency(\.date.now) var now
@Dependency(\.uuid) var uuid
self.init(
mocks,
create: { employee in
Employee(
id: uuid(),
active: employee.active ?? true,
createdAt: now,
firstName: employee.firstName,
lastName: employee.lastName,
updatedAt: now
)
},
fetch: { request in
switch request {
case .all:
return { _ in true }
case .active:
return { $0.active == true }
case .inactive:
return { $0.active == false }
}
},
update: { employee, updates in
let model = Employee(
id: employee.id,
active: updates.active ?? employee.active,
createdAt: employee.createdAt,
firstName: updates.firstName ?? employee.firstName,
lastName: updates.lastName ?? employee.lastName,
updatedAt: now
)
employee = model
}
)
}
}
public extension DatabaseClient.Employees {
static func mock(_ mocks: [Employee] = []) -> Self {
let storage = EmployeeMockStorage(mocks)
return .init(
create: { try await storage.create($0) },
delete: { try await storage.delete($0) },
fetchAll: { try await storage.fetchAll($0) },
get: { try await storage.get($0) },
update: { try await storage.update($0, $1) }
)
}
}
#endif

View File

@@ -1,142 +0,0 @@
#if DEBUG
import Dependencies
import Vapor
actor MockStorage<
Model: Identifiable,
Create: Sendable,
Fetch: Sendable,
Get: Sendable,
Update: Sendable
> where Model: Sendable {
@Dependency(\.date.now) var now
@Dependency(\.uuid) var uuid
private var storage: [Model.ID: Model]
private let modelFromCreate: @Sendable (Create) async throws -> Model
private let fetchToPredicate: @Sendable (Fetch) -> ((Model) -> Bool)
private let fetchExtras: @Sendable (Fetch, [Model]) async throws -> [Model]
private let applyUpdates: @Sendable (inout Model, Update, Get?) async throws -> Void
private let getExtras: @Sendable (Get?, Model) async throws -> Model
init(
_ mocks: [Model] = [],
create modelFromCreate: @Sendable @escaping (Create) async throws -> Model,
fetch fetchToPredicate: @Sendable @escaping (Fetch) -> ((Model) -> Bool),
fetchExtras: @Sendable @escaping (Fetch, [Model]) async throws -> [Model] = { $1 },
get getExtras: @Sendable @escaping (Get?, Model) async throws -> Model,
update applyUpdates: @Sendable @escaping (inout Model, Update, Get?) async throws -> Void
) {
self.storage = mocks.reduce(into: [Model.ID: Model]()) { $0[$1.id] = $1 }
self.modelFromCreate = modelFromCreate
self.fetchToPredicate = fetchToPredicate
self.fetchExtras = fetchExtras
self.applyUpdates = applyUpdates
self.getExtras = getExtras
}
func count() async throws -> Int {
storage.count
}
func create(_ create: Create) async throws -> Model {
let model = try await modelFromCreate(create)
storage[model.id] = model
return model
}
func delete(_ id: Model.ID) async throws {
storage[id] = nil
}
func fetchAll(_ request: Fetch) async throws -> [Model] {
let predicate = fetchToPredicate(request)
return try await fetchExtras(request, Array(storage.values.filter { predicate($0) }))
}
func get(_ id: Model.ID, _ request: Get?) async throws -> Model? {
if let model = storage[id] {
return try await getExtras(request, model)
}
return nil
}
func update(_ id: Model.ID, _ updates: Update, _ get: Get?) async throws -> Model {
guard var model = storage[id] else {
throw Abort(.badRequest, reason: "Model not found.")
}
try await applyUpdates(&model, updates, get)
storage[id] = model
return model
}
}
extension MockStorage where Get == Void {
init(
_ mocks: [Model] = [],
create modelFromCreate: @Sendable @escaping (Create) async throws -> Model,
fetch fetchToPredicate: @Sendable @escaping (Fetch) -> ((Model) -> Bool),
fetchExtras: @Sendable @escaping (Fetch, [Model]) async throws -> [Model] = { $1 },
update applyUpdates: @Sendable @escaping (inout Model, Update) async throws -> Void
) {
self.init(
mocks,
create: modelFromCreate,
fetch: fetchToPredicate,
fetchExtras: fetchExtras,
get: { _, model in model },
update: { model, updates, _ in try await applyUpdates(&model, updates) }
)
}
func get(_ id: Model.ID) async throws -> Model? {
storage[id]
}
func update(_ id: Model.ID, _ updates: Update) async throws -> Model {
try await update(id, updates, ())
}
}
extension MockStorage where Fetch == Void {
init(
_ mocks: [Model] = [],
create modelFromCreate: @Sendable @escaping (Create) async throws -> Model,
fetchExtras: @Sendable @escaping (Fetch, [Model]) async throws -> [Model] = { $1 },
get getExtras: @Sendable @escaping (Get?, Model) async throws -> Model,
update applyUpdates: @Sendable @escaping (inout Model, Update, Get?) async throws -> Void
) {
self.init(
mocks,
create: modelFromCreate,
fetch: { _ in { _ in true } },
fetchExtras: fetchExtras,
get: getExtras,
update: applyUpdates
)
}
func fetchAll() async throws -> [Model] {
try await fetchAll(())
}
}
extension MockStorage where Fetch == Void, Get == Void {
init(
_ mocks: [Model] = [],
create modelFromCreate: @Sendable @escaping (Create) async throws -> Model,
fetchExtras: @Sendable @escaping (Fetch, [Model]) async throws -> [Model] = { $1 },
update applyUpdates: @Sendable @escaping (inout Model, Update) async throws -> Void
) {
self.init(
mocks,
create: modelFromCreate,
fetchExtras: fetchExtras,
get: { _, model in model },
update: { model, updates, _ in try await applyUpdates(&model, updates) }
)
}
}
#endif

View File

@@ -22,74 +22,3 @@ extension PurchaseOrder.Create: Content {}
extension DatabaseClient.PurchaseOrders: TestDependencyKey {
public static let testValue: DatabaseClient.PurchaseOrders = Self()
}
#if DEBUG
typealias PurchaseOrderMockStorage = MockStorage<
PurchaseOrder,
PurchaseOrder.Create,
Void,
Void,
Void
>
public extension DependencyValues {
var purchaseOrderID: PurchaseOrderIDGenerator {
get { self[PurchaseOrderIDGenerator.self] }
set { self[PurchaseOrderIDGenerator.self] = newValue }
}
}
@DependencyClient
public struct PurchaseOrderIDGenerator: Sendable {
var nextID: @Sendable () async throws -> Int
}
extension PurchaseOrderIDGenerator: DependencyKey {
public static let testValue: PurchaseOrderIDGenerator = .liveValue
public static var liveValue: Self {
let counter = Counter()
return .init(nextID: { await counter.nextID() })
}
actor Counter {
private var count: Int
init(starting: Int = 1) {
self.count = starting
}
func nextID() async -> Int {
count += 1
return count
}
}
}
// private extension PurchaseOrderMockStorage {
// static func make(_ mocks: [PurchaseOrder]) -> Self {
// @Dependency(\.date.now) var now
// @Dependency(\.purchaseOrderID) var purchaseOrderID
//
// return .init(
// mocks,
// create: { model in
// try await PurchaseOrder(
// id: purchaseOrderID.nextID(),
// workOrder: model.workOrder,
// materials: model.materials,
// customer: model.customer,
// truckStock: model.truckStock,
// createdBy: model.createdForID,
// createdFor: model.createdForID,
// vendorBranch: .i
//
// )
// },
// update: { _, _ in
// fatalError()
// }
// )
// }
// }
#endif

View File

@@ -28,66 +28,3 @@ extension User.Update: Content {}
extension DatabaseClient.Users: TestDependencyKey {
public static let testValue: DatabaseClient.Users = Self()
}
#if DEBUG
typealias UserMockStorage = MockStorage<
User,
User.Create,
Void,
Void,
User.Update
>
private extension UserMockStorage {
static func make(_ mocks: [User]) -> Self {
@Dependency(\.date.now) var now
@Dependency(\.uuid) var uuid
return .init(
create: { model in
User(
id: uuid(),
email: model.email,
username: model.username,
createdAt: now,
updatedAt: now
)
},
update: { model, updates in
let user = User(
id: model.id,
email: updates.email ?? model.email,
username: updates.username ?? model.username,
createdAt: model.createdAt,
updatedAt: now
)
model = user
}
)
}
}
public extension User.Token {
static func mock(id: User.ID) -> Self {
.init(id: UUID(0), userID: id, value: "test")
}
}
public extension DatabaseClient.Users {
static func mock(_ mocks: [User]) -> Self {
let storage = UserMockStorage.make(mocks)
return .init(
count: { try await storage.count() },
create: { try await storage.create($0) },
delete: { try await storage.delete($0) },
fetchAll: { try await storage.fetchAll() },
get: { try await storage.get($0) },
login: { _ in .mock(id: UUID(0)) },
logout: { _ in },
token: { .mock(id: $0) },
update: { try await storage.update($0, $1) }
)
}
}
#endif

View File

@@ -31,61 +31,3 @@ extension DatabaseClient.VendorBranches.FetchRequest: Content {}
extension DatabaseClient.VendorBranches: TestDependencyKey {
public static let testValue: DatabaseClient.VendorBranches = Self()
}
#if DEBUG
typealias VendorBranchMockStorage = MockStorage<
VendorBranch,
VendorBranch.Create,
DatabaseClient.VendorBranches.FetchRequest,
Void,
VendorBranch.Update
>
private extension VendorBranchMockStorage {
init(_ mocks: [VendorBranch]) {
@Dependency(\.date.now) var now
@Dependency(\.uuid) var uuid
self.init(
mocks,
create: {
VendorBranch(id: uuid(), name: $0.name, vendorID: $0.vendorID, createdAt: now, updatedAt: now)
},
fetch: { request in
switch request {
case .all:
return { _ in true }
case let .for(vendorID):
return { $0.vendorID == vendorID }
}
},
update: { branch, updates in
let model = VendorBranch(
id: branch.id,
name: updates.name ?? branch.name,
vendorID: branch.vendorID,
createdAt: branch.createdAt,
updatedAt: now
)
branch = model
}
)
}
}
public extension DatabaseClient.VendorBranches {
static func mock(_ mocks: [VendorBranch] = []) -> Self {
let storage = VendorBranchMockStorage(mocks)
return .init(
create: { try await storage.create($0) },
delete: { try await storage.delete($0) },
fetchAll: { try await storage.fetchAll($0) },
get: { try await storage.get($0) },
update: { try await storage.update($0, $1) }
)
}
}
#endif

View File

@@ -51,94 +51,3 @@ extension DatabaseClient.Vendors.GetRequest: Content {}
extension DatabaseClient.Vendors: TestDependencyKey {
public static let testValue: DatabaseClient.Vendors = Self()
}
#if DEBUG
typealias VendorMockStorage = MockStorage<
Vendor,
Vendor.Create,
DatabaseClient.Vendors.FetchRequest,
DatabaseClient.Vendors.GetRequest,
Vendor.Update
>
private extension VendorMockStorage {
// swiftlint:disable function_body_length
static func vendors(_ mocks: [Vendor]) -> Self {
@Dependency(\.date.now) var now
@Dependency(\.uuid) var uuid
@Dependency(\.database.vendorBranches) var vendorBranches
return .init(
mocks,
create: {
Vendor(
id: uuid(),
name: $0.name,
createdAt: now,
updatedAt: now
)
},
fetch: { _ in
{ _ in true }
},
fetchExtras: { request, models in
guard request == .withBranches else { return models }
let branches = try await vendorBranches.fetchAll()
return models.map { model in
Vendor(
id: model.id,
name: model.name,
branches: Array(branches.filter { $0.vendorID == model.id }),
createdAt: model.createdAt,
updatedAt: model.updatedAt
)
}
},
get: { req, model in
guard req == .withBranches else { return model }
let branches = try await vendorBranches.fetchAll(.for(vendorID: model.id))
return Vendor(
id: model.id,
name: model.name,
branches: branches,
createdAt: model.createdAt,
updatedAt: model.updatedAt
)
},
update: { model, updates, get in
var branches: [VendorBranch]?
if get == .withBranches {
branches = try await vendorBranches.fetchAll(.for(vendorID: model.id))
}
let vendor = Vendor(
id: model.id,
name: updates.name ?? model.name,
branches: branches ?? model.branches,
createdAt: model.createdAt,
updatedAt: now
)
model = vendor
}
)
}
// swiftlint:enable function_body_length
}
public extension DatabaseClient.Vendors {
static func mock(_ mocks: [Vendor]) -> Self {
let storage = VendorMockStorage.vendors(mocks)
return .init(
create: { try await storage.create($0) },
delete: { try await storage.delete($0) },
fetchAll: { try await storage.fetchAll($0) },
get: { try await storage.get($0, $1) },
update: { req, updates, get in try await storage.update(req, updates, get) }
)
}
}
#endif

View File

@@ -9,7 +9,8 @@ public extension DatabaseClient.PurchaseOrders {
.init { create, createdById in
let model = try create.toModel(createdByID: createdById)
try await model.save(on: database)
return try model.toDTO()
let fetched = try await PurchaseOrderModel.allQuery(on: database).filter(\.$id == model.id!).first()!
return try fetched.toDTO()
} fetchAll: {
try await PurchaseOrderModel.allQuery(on: database)
.all()

View File

@@ -60,6 +60,46 @@ public extension Employee {
}
}
#if DEBUG
//
// public extension Employee {
//
// static func generateMocks(count: Int = 10) -> [Self] {
// @Dependency(\.date.now) var now
// @Dependency(\.uuid) var uuid
//
// var output = [Self]()
//
// for _ in 0 ... count {
// output.append(.init(
// id: uuid(),
// active: Bool.random(),
// createdAt: now,
// firstName: RandomNames.firstNames.randomElement()!,
// lastName: RandomNames.lastNames.randomElement()!,
// updatedAt: now
// ))
// }
//
// return output
// }
// }
public extension Employee.Create {
static func generateMocks(count: Int = 5) -> [Self] {
(0 ... count).reduce(into: [Self]()) { array, _ in
array.append(.init(
firstName: RandomNames.firstNames.randomElement()! + String(RandomNames.characterString.randomElement()!),
lastName: RandomNames.lastNames.randomElement()! + String(RandomNames.characterString.randomElement()!),
active: Bool.random()
))
}
}
}
#endif
// public extension Employee {
// static var mocks: [Self] {
// [

View File

@@ -0,0 +1,150 @@
#if DEBUG
enum RandomNames {
static let characterString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
// Static variables for first names
static let firstNames: [String] = [
"Oliver",
"Emma",
"Liam",
"Ava",
"Noah",
"Sophia",
"Elijah",
"Isabella",
"James",
"Mia",
"Benjamin",
"Charlotte",
"Lucas",
"Amelia",
"Henry",
"Harper",
"Alexander",
"Evelyn",
"William",
"Abigail"
]
// Static variables for last names
static let lastNames: [String] = [
"Smith",
"Johnson",
"Brown",
"Williams",
"Jones",
"Garcia",
"Martinez",
"Davis",
"Rodriguez",
"Martins",
"Hernandez",
"Lopez",
"Gonzalez",
"Wilson",
"Anderson",
"Thomas",
"Taylor",
"Moore",
"Jackson",
"Martin"
]
// Static variables for user names
static let userNames: [String] = [
"CoolCat123",
"FastFrog99",
"SunnySky",
"RocketRider",
"PixelPanda",
"ShadowNinja",
"ThunderWolf",
"GoldenEagle",
"SilverFox",
"MightyBear",
"IronLion",
"BlueTiger",
"FirePhoenix",
"CrystalDragon",
"NeonKnight",
"ElectricZebra",
"MagicUnicorn",
"StealthShark",
"GalaxyRanger",
"CosmicTurtle"
]
// Static variables for city names
static let cityNames: [String] = [
"Springfield",
"Rivertown",
"Sunnyvale",
"Lakeside",
"Hillcrest",
"Oakwood",
"Mapleton",
"Pinehill",
"Brookfield",
"Riverbend",
"Clearwater",
"Greystone",
"Westhaven",
"Eastwood",
"Silverlake",
"Goldenfield",
"Highland",
"Cedarville",
"Willowbrook",
"Fairview"
]
// Static variables for company names
static let companyNames: [String] = [
"TechNova",
"GreenLeaf Co.",
"Skyline Ventures",
"Pioneer Systems",
"Quantum Dynamics",
"Blue Horizon",
"NextGen Solutions",
"Summit Enterprises",
"FutureWorks",
"BrightPath",
"Eclipse Innovations",
"Golden Gate Technologies",
"Silverline Corp.",
"Vertex Industries",
"DynamicEdge",
"CrestPoint",
"EcoSphere",
"PrimeSource",
"InfinityTech",
"TrueNorth Inc."
]
// Static variables for fake emails
static let emails: [String] = [
"oliver.smith@example.com",
"emma.johnson@example.org",
"liam.brown@example.net",
"ava.williams@example.com",
"noah.jones@example.org",
"sophia.garcia@example.net",
"elijah.martinez@example.com",
"isabella.davis@example.org",
"james.rodriguez@example.net",
"mia.martins@example.com",
"benjamin.hernandez@example.org",
"charlotte.lopez@example.net",
"lucas.gonzalez@example.com",
"amelia.wilson@example.org",
"henry.anderson@example.net",
"harper.thomas@example.com",
"alexander.taylor@example.org",
"evelyn.moore@example.net",
"william.jackson@example.com",
"abigail.martin@example.org"
]
}
#endif

View File

@@ -72,3 +72,57 @@ public extension PurchaseOrder {
}
}
#if DEBUG
// public extension PurchaseOrder {
// static func generateMocks(
// count: Int = 50,
// employees: [Employee],
// users: [User],
// vendorBranches: [VendorBranch]
// ) -> [Self] {
// @Dependency(\.date.now) var now
// @Dependency(\.uuid) var uuid
//
// var output = [Self]()
//
// for id in 0 ... count {
// output.append(.init(
// id: id,
// workOrder: Int.random(in: 0 ... 100),
// materials: "Some thing",
// customer: "\(RandomNames.firstNames.randomElement()!) \(RandomNames.lastNames.randomElement()!)",
// truckStock: Bool.random(),
// createdBy: users.randomElement()!,
// createdFor: employees.randomElement()!,
// vendorBranch: vendorBranches.randomElement()!,
// createdAt: now,
// updatedAt: now
// ))
// }
//
// return output
// }
// }
public extension PurchaseOrder.Create {
static func generateMocks(
count: Int = 50,
employees: [Employee],
vendorBranches: [VendorBranch]
) -> [Self] {
precondition(employees.count > 0)
precondition(vendorBranches.count > 0)
return (0 ... count).reduce(into: [Self]()) { array, _ in
array.append(.init(
materials: "Some materials",
customer: "\(RandomNames.firstNames.randomElement()!) \(RandomNames.lastNames.randomElement()!)",
createdForID: employees.randomElement()!.id,
vendorBranchID: vendorBranches.randomElement()!.id
))
}
}
}
#endif

View File

@@ -84,12 +84,18 @@ public extension User {
}
// public extension User {
// static var mocks: [Self] {
// [
// .init(email: "blob@test.com", username: "blob"),
// .init(email: "blob-jr@test.com", username: "blob-jr"),
// .init(email: "blob-sr@test.com", username: "blob-sr")
// ]
// }
// }
#if DEBUG
public extension User.Create {
static func generateMocks(count: Int = 5) -> [Self] {
(0 ... count).reduce(into: [Self]()) { array, _ in
array.append(.init(
username: RandomNames.userNames.randomElement()! + String(RandomNames.characterString.randomElement()!),
email: String(RandomNames.characterString.randomElement()!) + RandomNames.emails.randomElement()!,
password: "super-secret",
confirmPassword: "super-secret"
))
}
}
}
#endif

View File

@@ -41,3 +41,40 @@ public extension Vendor {
}
}
}
#if DEBUG
//
// public extension Vendor {
//
// static func generateMocks(count: Int = 20) -> [Self] {
// @Dependency(\.date.now) var now
// @Dependency(\.uuid) var uuid
//
// var output = [Self]()
//
// for _ in 0 ... count {
// output.append(.init(
// id: uuid(),
// name: RandomNames.companyNames.randomElement()!,
// branches: nil,
// createdAt: now,
// updatedAt: now
// ))
// }
//
// return output
// }
// }
public extension Vendor.Create {
static func generateMocks(count: Int = 5) -> [Self] {
(0 ... count).reduce(into: [Self]()) { array, _ in
array.append(.init(
name: RandomNames.companyNames.randomElement()! + String(RandomNames.characterString.randomElement()!)
))
}
}
}
#endif

View File

@@ -42,3 +42,41 @@ public extension VendorBranch {
}
}
}
#if DEBUG
// public extension VendorBranch {
//
// static func generateMocks(countPerVendor: Int = 3, vendors: [Vendor]) -> [Self] {
// @Dependency(\.date.now) var now
// @Dependency(\.uuid) var uuid
//
// var output = [Self]()
//
// for vendor in vendors {
// for _ in 0 ... countPerVendor {
// output.append(.init(
// id: uuid(),
// name: RandomNames.cityNames.randomElement()!,
// vendorID: vendor.id,
// createdAt: now,
// updatedAt: now
// ))
// }
// }
//
// return output
// }
// }
public extension VendorBranch.Create {
static func generateMocks(countPerVendor: Int = 3, vendors: [Vendor]) -> [Self] {
return vendors.reduce(into: [Self]()) { output, vendor in
output = (0 ... countPerVendor).reduce(into: output) { array, _ in
array.append(.init(name: RandomNames.cityNames.randomElement()!, vendorID: vendor.id))
}
}
}
}
#endif

View File

@@ -49,12 +49,10 @@ struct DatabaseClientTests {
}
}
@Test(arguments: EmployeeTestFactory.testCases)
func employees(factory: EmployeeTestFactory) async throws {
@Test
func employees() async throws {
try await withDatabase(migrations: Employee.Migrate()) {
$0.uuid = .incrementing
$0.date = .init { Date() }
$0.database.employees = factory.handler($1)
$0.database.employees = .live(database: $1)
} operation: {
@Dependency(\.database.employees) var employees
@@ -93,11 +91,11 @@ struct DatabaseClientTests {
}
}
@Test(arguments: VendorTestFactory.testCases)
func vendors(factory: VendorTestFactory) async throws {
@Test
func vendors() async throws {
try await withDatabase(migrations: Vendor.Migrate(), VendorBranch.Migrate()) {
$0.database.vendorBranches = factory.handler($1).0
$0.database.vendors = factory.handler($1).1
$0.database.vendorBranches = .live(database: $1)
$0.database.vendors = .live(database: $1)
} operation: {
@Dependency(\.database.vendorBranches) var branches
@Dependency(\.database.vendors) var vendors
@@ -132,11 +130,11 @@ struct DatabaseClientTests {
}
}
@Test(arguments: VendorTestFactory.testCases)
func vendorBranches(factory: VendorTestFactory) async throws {
@Test
func vendorBranches() async throws {
try await withDatabase(migrations: Vendor.Migrate(), VendorBranch.Migrate()) {
$0.database.vendorBranches = factory.handler($1).0
$0.database.vendors = factory.handler($1).1
$0.database.vendorBranches = .live(database: $1)
$0.database.vendors = .live(database: $1)
} operation: {
@Dependency(\.database.vendorBranches) var branches
@Dependency(\.database.vendors) var vendors
@@ -197,22 +195,3 @@ struct DatabaseClientTests {
await dbs.shutdownAsync()
}
}
struct EmployeeTestFactory {
let handler: (any Database) -> DatabaseClient.Employees
static var testCases: [Self] { [
.init(handler: { .live(database: $0) }),
.init(handler: { _ in .mock([]) })
] }
}
struct VendorTestFactory {
let handler: (any Database) -> (DatabaseClient.VendorBranches, DatabaseClient.Vendors)
static var testCases: [Self] { [
.init(handler: { (.live(database: $0), .live(database: $0)) }),
.init(handler: { _ in (.mock([]), .mock([])) })
] }
}