Files
vapor-po/Tests/ViewControllerTests/ViewControllerTests.swift

410 lines
11 KiB
Swift

import DatabaseClient
import Dependencies
import Foundation
import HtmlSnapshotTesting
import SharedModels
import SnapshotTesting
import Testing
import ViewControllerLive
// NOTE: Passing routes as arguments doesn't work bc they are sometimes not in the same order.
@Suite("ViewControllerTests")
struct ViewControllerTests {
let record: SnapshotTestingConfiguration.Record = .missing
@Test
func sanity() {
#expect(Bool(true))
}
@Test
func employeeViews() async throws {
try await withSnapshotTesting(record: record) {
try await withDependencies {
$0.viewController = .liveValue
$0.database.employees = .mock
$0.dateFormatter = .mock
} operation: {
@Dependency(\.viewController) var viewController
@Dependency(\.database) var database
var htmlString = try await viewController.render(.employee(.index))
assertSnapshot(of: htmlString, as: .html)
htmlString = try await viewController.render(.employee(.form))
assertSnapshot(of: htmlString, as: .html)
htmlString = try await viewController.render(.employee(.get(id: UUID(0))))
assertSnapshot(of: htmlString, as: .html)
htmlString = try await viewController.render(.employee(.select(context: .purchaseOrderForm)))
assertSnapshot(of: htmlString, as: .html)
htmlString = try await viewController.render(.employee(.select(context: .purchaseOrderSearch)))
assertSnapshot(of: htmlString, as: .html)
htmlString = try await viewController.render(.employee(.update(id: UUID(0), updates: .mock)))
assertSnapshot(of: htmlString, as: .html)
}
}
}
@Test
func loginViews() async throws {
try await withSnapshotTesting(record: record) {
try await withDependencies {
$0.viewController = .liveValue
$0.dateFormatter = .mock
} operation: {
@Dependency(\.viewController) var viewController
let htmlString = try await viewController.render(.login(.index(next: "/purchase-orders")))
assertSnapshot(of: htmlString, as: .html)
}
}
}
@Test
func purchaseOrderViews() async throws {
try await withSnapshotTesting(record: record) {
try await withDependencies {
$0.dateFormatter = .mock
$0.database.purchaseOrders = .mock
$0.viewController = .liveValue
} operation: {
@Dependency(\.viewController) var viewController
var htmlString = try await viewController.render(.purchaseOrder(.index))
assertSnapshot(of: htmlString, as: .html)
htmlString = try await viewController.render(.purchaseOrder(.form))
assertSnapshot(of: htmlString, as: .html)
htmlString = try await viewController.render(.purchaseOrder(.create(.mock)))
assertSnapshot(of: htmlString, as: .html)
htmlString = try await viewController.render(.purchaseOrder(.get(id: 1)))
assertSnapshot(of: htmlString, as: .html)
htmlString = try await viewController.render(.purchaseOrder(.page(page: 1, limit: 25)))
assertSnapshot(of: htmlString, as: .html)
for context in ViewRoute.PurchaseOrderRoute.Search.Context.allCases {
htmlString = try await viewController.render(.purchaseOrder(.search(.index(
context: context,
table: true
))))
assertSnapshot(of: htmlString, as: .html)
}
}
}
}
@Test
func userViews() async throws {
try await withSnapshotTesting(record: record) {
try await withDependencies {
$0.dateFormatter = .mock
$0.database.users = .mock
$0.viewController = .liveValue
} operation: {
@Dependency(\.database) var database
@Dependency(\.viewController) var viewController
var htmlString = try await viewController.render(.user(.index))
assertSnapshot(of: htmlString, as: .html)
htmlString = try await viewController.render(.user(.form))
assertSnapshot(of: htmlString, as: .html)
htmlString = try await viewController.render(.user(.create(.mock)))
assertSnapshot(of: htmlString, as: .html)
htmlString = try await viewController.render(.user(.get(id: UUID(0))))
assertSnapshot(of: htmlString, as: .html)
htmlString = try await viewController.render(.user(.update(id: UUID(0), updates: .mock)))
assertSnapshot(of: htmlString, as: .html)
}
}
}
@Test
func vendorViews() async throws {
try await withSnapshotTesting(record: record) {
try await withDependencies {
$0.dateFormatter = .mock
$0.database.vendors = .mock
$0.viewController = .liveValue
} operation: {
@Dependency(\.database) var database
@Dependency(\.viewController) var viewController
var htmlString = try await viewController.render(.vendor(.index))
assertSnapshot(of: htmlString, as: .html)
htmlString = try await viewController.render(.vendor(.form))
assertSnapshot(of: htmlString, as: .html)
htmlString = try await viewController.render(.vendor(.create(.mock)))
assertSnapshot(of: htmlString, as: .html)
htmlString = try await viewController.render(.vendor(.get(id: UUID(0))))
assertSnapshot(of: htmlString, as: .html)
htmlString = try await viewController.render(.vendor(.update(id: UUID(0), updates: .mock)))
assertSnapshot(of: htmlString, as: .html)
}
}
}
@Test
func vendorBranchViews() async throws {
try await withSnapshotTesting(record: record) {
try await withDependencies {
$0.dateFormatter = .mock
$0.database.vendors = .mock
$0.database.vendorBranches = .mock
$0.viewController = .liveValue
} operation: {
@Dependency(\.database) var database
@Dependency(\.viewController) var viewController
var htmlString = try await viewController.render(.vendorBranch(.index(for: UUID(0))))
assertSnapshot(of: htmlString, as: .html)
htmlString = try await viewController.render(.vendorBranch(.select(context: .purchaseOrderSearch)))
assertSnapshot(of: htmlString, as: .html)
htmlString = try await viewController.render(.vendorBranch(.select(context: .purchaseOrderForm)))
assertSnapshot(of: htmlString, as: .html)
htmlString = try await viewController.render(.vendorBranch(.create(.mock)))
assertSnapshot(of: htmlString, as: .html)
}
}
}
}
extension ViewController {
func render(_ route: ViewRoute) async throws -> String {
let html = try await view(
for: route,
isHtmxRequest: true,
logger: .init(label: "tests"),
authenticate: { _ in }
)
return html.renderFormatted()
}
}
struct TestError: Error {}
extension DatabaseClient.Employees {
static var mock: Self {
.init(
create: { _ in .mock },
delete: { _ in },
fetchAll: { _ in [Employee.mock] },
get: { _ in Employee.mock },
update: { _, _ in Employee.mock }
)
}
}
extension DatabaseClient.PurchaseOrders {
static var mock: Self {
.init(
create: { _ in .mock },
fetchAll: { [.mock] },
fetchPage: { _ in .init(items: [.mock], metadata: .init(page: 1, per: 1, total: 1)) },
get: { _ in .mock },
delete: { _ in },
search: { _, _ in .init(items: [.mock], metadata: .init(page: 1, per: 1, total: 1)) }
)
}
}
extension DatabaseClient.Users {
static var mock: Self {
.init(
count: { 1 },
create: { _ in User.mock },
delete: { _ in },
fetchAll: { [User.mock] },
get: { _ in User.mock },
login: { _ in User.Token.mock },
logout: { _ in },
token: { _ in User.Token.mock },
update: { _, _ in User.mock }
)
}
}
extension DatabaseClient.Vendors {
static var mock: Self {
.init(
create: { _ in Vendor.mock },
delete: { _ in },
fetchAll: { _ in [Vendor.mock] },
get: { _, _ in Vendor.mock },
update: { _, _, _ in Vendor.mock }
)
}
}
extension DatabaseClient.VendorBranches {
static var mock: Self {
.init(
create: { _ in VendorBranch.mock },
delete: { _ in },
fetchAll: { _ in [VendorBranch.mock] },
fetchAllWithDetail: { [VendorBranch.Detail.mock] },
get: { _ in VendorBranch.mock },
update: { _, _ in VendorBranch.mock }
)
}
}
extension Date {
static var mock: Self {
let formatter = ISO8601DateFormatter()
return formatter.date(from: "2025-01-31T02:22:40Z")!
}
}
extension DateFormatterKey {
static var mock: Self {
.init(string: { _ in "01/31/2025" })
}
}
extension Employee {
static var mock: Self {
Employee(
id: UUID(0),
createdAt: .mock,
firstName: "Testy",
lastName: "McTestface",
updatedAt: .mock
)
}
}
extension Employee.Create {
static var mock: Self {
.init(firstName: "Testy", lastName: "McTestface")
}
func employeeMock() -> Employee {
@Dependency(\.date.now) var now
return .init(
id: UUID(0),
createdAt: .mock,
firstName: firstName,
lastName: lastName,
updatedAt: .mock
)
}
}
extension Employee.Update {
static var mock: Self {
.init(firstName: "Testy", lastName: "McTestface", active: false)
}
}
extension User {
static var mock: Self {
.init(id: UUID(0), email: "test@example.com", username: "test")
}
}
extension User.Create {
static var mock: Self {
.init(username: "test", email: "test@example.com", password: "super-secret", confirmPassword: "super-secret")
}
}
extension User.Token {
static var mock: Self {
.init(id: UUID(1), userID: UUID(0), value: "test-token")
}
}
extension User.Update {
static var mock: Self {
User.Update(username: "test", email: "test@test.com")
}
}
extension Vendor {
static var mock: Self {
.init(id: UUID(0), name: "Test", branches: nil, createdAt: .mock, updatedAt: .mock)
}
}
extension Vendor.Create {
static var mock: Self {
.init(name: "Test")
}
}
extension Vendor.Update {
static var mock: Self {
.init(name: "Test")
}
}
extension VendorBranch {
static var mock: Self {
.init(id: UUID(1), name: "Mock", vendorID: UUID(0), createdAt: .mock, updatedAt: .mock)
}
}
extension VendorBranch.Create {
static var mock: Self {
.init(name: "Mock", vendorID: UUID(0))
}
}
extension VendorBranch.Detail {
static var mock: Self {
.init(id: UUID(1), name: "Mock", vendor: .mock, createdAt: .mock, updatedAt: .mock)
}
}
extension PurchaseOrder {
static var mock: Self {
.init(
id: 1,
workOrder: 12245,
materials: "foo",
customer: "Testy McTestface",
truckStock: true,
createdBy: .mock,
createdFor: .mock,
vendorBranch: .mock,
createdAt: .mock,
updatedAt: .mock
)
}
}
extension PurchaseOrder.Create {
static var mock: Self {
.init(
materials: "bar",
customer: "Testy McTestface",
createdByID: UUID(0),
createdForID: UUID(0),
vendorBranchID: UUID(0)
)
}
}