import Fluent import Testing import VaporTesting @testable import auth_service @Suite("App Tests with DB", .serialized) struct auth_serviceTests { private func withApp(_ test: (Application) async throws -> Void) async throws { let app = try await Application.make(.testing) do { try await configure(app) try await app.autoMigrate() try await test(app) try await app.autoRevert() } catch { try? await app.autoRevert() try await app.asyncShutdown() throw error } try await app.asyncShutdown() } @Test("Getting all the Users") func getAllUsers() async throws { try await withApp { app in let sampleUsers = [ User( username: "user1", email: "user1@example.com", password: "user1password", group: "users", isSuperuser: true), User( username: "user2", email: "user2@example.com", password: "user2password", group: "users", isSuperuser: false), ] try await sampleUsers.create(on: app.db) try await app.testing().test( .GET, "users", afterResponse: { res async throws in #expect(res.status == .ok) #expect( try res.content.decode([UserDTO].self).sorted(by: { ($0.username ?? "") < ($1.username ?? "") }) == sampleUsers.map { $0.toDTO() }.sorted(by: { ($0.username ?? "") < ($1.username ?? "") }) ) }) } } @Test("Creating a User") func createUser() async throws { let newDTO = UserDTO( id: nil, username: "test", email: "test@example.com", password: "testpassword") try await withApp { app in try await app.testing().test( .POST, "users", beforeRequest: { req in try req.content.encode(newDTO) }, afterResponse: { res async throws in #expect(res.status == .ok) let models = try await User.query(on: app.db).all() #expect(models.map({ $0.toDTO().username }) == [newDTO.username]) }) } } @Test("Deleting a User") func deleteUser() async throws { let testUsers = [ User( username: "user1", email: "user1@example.com", password: "user1password", group: "users", isSuperuser: true), User( username: "user2", email: "user2@example.com", password: "user2password", group: "users", isSuperuser: false), ] try await withApp { app in try await testUsers.create(on: app.db) try await app.testing().test( .DELETE, "users/\(testUsers[0].requireID())", afterResponse: { res async throws in #expect(res.status == .noContent) let model = try await User.find(testUsers[0].id, on: app.db) #expect(model == nil) }) } } @Test("Getting a User by ID") func showUser() async throws { let testUsers = [ User( username: "user1", email: "user1@example.com", password: "user1password", group: "users", isSuperuser: true), User( username: "user2", email: "user2@example.com", password: "user2password", group: "users", isSuperuser: false), ] try await withApp { app in try await testUsers.create(on: app.db) try await app.testing().test( .GET, "users/\(testUsers[0].requireID())", afterResponse: { res async throws in #expect(res.status == .ok) let user = try res.content.decode(UserDTO.self) #expect(user.id == testUsers[0].id) #expect(user.username == testUsers[0].username) }) } } @Test("Updating a User") func updateUser() async throws { let testUsersDTOs = [ UserDTO( username: "user1", email: "user1@example.com", password: "user1password", group: "users", isSuperuser: true), UserDTO( username: "user2", email: "user2@example.com", password: "user2password", group: "users", isSuperuser: false), ] let testUsers = [ User( username: "user1", email: "user1@example.com", password: "user1password", group: "users", isSuperuser: true), User( username: "user2", email: "user2@example.com", password: "user2password", group: "users", isSuperuser: false), ] try await withApp { app in try await testUsers.create(on: app.db) try await app.testing().test( .PUT, "users/\(testUsers[0].requireID())", beforeRequest: { req in try req.content.encode(testUsersDTOs[0]) }, afterResponse: { res async throws in #expect(res.status == .ok) let user = try res.content.decode(UserDTO.self) #expect(user.id == testUsers[0].id) #expect(user.username == testUsers[0].username) }) } } } extension UserDTO: Equatable { public static func == (lhs: Self, rhs: Self) -> Bool { lhs.id == rhs.id && lhs.username == rhs.username } }