manageable-users/Tests/SampleAppTests/AuthorizationTests.swift

210 lines
10 KiB
Swift

@testable import SampleApp
import ManageableUsers
import VaporTesting
import SQLKit
import Testing
@Suite("App Tests", .serialized)
struct AuthorizationTests {
private func withApp(_ test: (Application) async throws -> ()) async throws {
let app = try await Application.make (.testing)
do {
setenv ("BASE_URL", "http://localhost", 0)
setenv ("EMAIL_SENDER", "nobody@example.com", 0)
try await SampleApp.configure (app)
let mockDatabase = MockDatabase (eventLoop: app.eventLoopGroup.next())
app.storage[Application.MockDatabaseKey.self] = mockDatabase
try await test (app)
} catch {
try await app.asyncShutdown()
throw error
}
try await app.asyncShutdown()
}
@Test("Test login redirect")
func loginRedirect() async throws {
try await withApp { app in
try await app.testing().test(.GET, "", afterResponse: { res async in
#expect(res.status == .seeOther)
#expect(res.headers["Location"] == ["auth/login"])
})
}
}
@Test("Test login form")
func loginForm() async throws {
try await withApp { app in
try await app.testing().test(.GET, "auth/login", afterResponse: { res async in
#expect(res.status == .ok)
})
}
}
@Test("Invalid login")
func invalidLogin() async throws {
try await withApp { app in
app.storage[Application.MockDatabaseKey.self]?.results.append ([MockDatabase.Row (values: ["id": UUID(), "email": "gamma", "full_name": "delta", "password": "$2b$12$4bg4BftSpYAHiQsWjjqj2uZlw.LHbSWUsXA4gBL7njnvONYelCNFC", "active": true, "roles": ["admin"]])])
try await app.testing().test(
.POST,
"api/auth/login",
beforeRequest: { request async in
request.headers.contentType = .json
request.body = ByteBuffer (string: #"{"email": "foo", "password": "bar"}"#)
},
afterResponse: { res async in
#expect(res.status == .unauthorized)
#expect(res.headers["Location"].isEmpty)
})
#expect(app.storage[Application.MockDatabaseKey.self]?.queries.count == 1)
}
}
@Test("Valid login")
func validLogin() async throws {
try await withApp { app in
var session: String?
app.storage[Application.MockDatabaseKey.self]?.results.append ([MockDatabase.Row (values: ["id": UUID(), "email": "gamma", "full_name": "delta", "password": "$2b$12$4bg4BftSpYAHiQsWjjqj2uZlw.LHbSWUsXA4gBL7njnvONYelCNFC", "active": true, "roles": Array<String>()])])
app.storage[Application.MockDatabaseKey.self]?.results.append ([MockDatabase.Row (values: ["id": UUID(), "email": "gamma", "full_name": "delta", "password": "$2b$12$4bg4BftSpYAHiQsWjjqj2uZlw.LHbSWUsXA4gBL7njnvONYelCNFC", "active": true, "roles": Array<String>()])])
try await app.testing().test(
.POST,
"api/auth/login",
beforeRequest: { request async in
request.headers.contentType = .json
request.body = ByteBuffer (string: #"{"email": "gamma", "password": ""}"#)
},
afterResponse: { res async in
#expect(res.status == .ok)
#expect(res.headers["Location"].isEmpty)
#expect(res.headers.setCookie?["vapor-session"] != nil)
session = res.headers.setCookie?["vapor-session"]?.string
})
try await app.testing().test(.GET, "",
beforeRequest: { request async in
request.headers.cookie = ["vapor-session": HTTPCookies.Value (string: session ?? "")]
},
afterResponse: { res async in
#expect(res.status == .ok)
#expect(res.headers.setCookie?["vapor-session"]?.string == session)
})
#expect(app.storage[Application.MockDatabaseKey.self]?.queries.count == 2)
}
}
@Test("Restricted route")
func restrictedRoute() async throws {
try await withApp { app in
var session: String?
app.storage[Application.MockDatabaseKey.self]?.results.append ([MockDatabase.Row (values: ["id": UUID(), "email": "gamma", "full_name": "delta", "password": "$2b$12$4bg4BftSpYAHiQsWjjqj2uZlw.LHbSWUsXA4gBL7njnvONYelCNFC", "active": true, "roles": Array<String>()])])
app.storage[Application.MockDatabaseKey.self]?.results.append ([MockDatabase.Row (values: ["id": UUID(), "email": "gamma", "full_name": "delta", "password": "$2b$12$4bg4BftSpYAHiQsWjjqj2uZlw.LHbSWUsXA4gBL7njnvONYelCNFC", "active": true, "roles": Array<String>()])])
try await app.testing().test(
.POST,
"api/auth/login",
beforeRequest: { request async in
request.headers.contentType = .json
request.body = ByteBuffer (string: #"{"email": "gamma", "password": ""}"#)
},
afterResponse: { res async in
#expect(res.status == .ok)
#expect(res.headers.setCookie?["vapor-session"] != nil)
session = res.headers.setCookie?["vapor-session"]?.string
})
try await app.testing().test(.GET, "admin",
beforeRequest: { request async in
request.headers.cookie = ["vapor-session": HTTPCookies.Value (string: session ?? "")]
},
afterResponse: { res async in
#expect(res.status == .seeOther)
#expect(res.headers.setCookie?["vapor-session"]?.string == session)
#expect(res.headers["Location"] == ["http://localhost:8080"])
})
#expect(app.storage[Application.MockDatabaseKey.self]?.queries.count == 2)
}
}
@Test("Restricted authorized route")
func restrictedAuthorizedRoute() async throws {
try await withApp { app in
var session: String?
app.storage[Application.MockDatabaseKey.self]?.results.append ([MockDatabase.Row (values: ["id": UUID(), "email": "gamma", "full_name": "delta", "password": "$2b$12$4bg4BftSpYAHiQsWjjqj2uZlw.LHbSWUsXA4gBL7njnvONYelCNFC", "active": true, "roles": ["admin"]])])
app.storage[Application.MockDatabaseKey.self]?.results.append ([MockDatabase.Row (values: ["id": UUID(), "email": "gamma", "full_name": "delta", "password": "$2b$12$4bg4BftSpYAHiQsWjjqj2uZlw.LHbSWUsXA4gBL7njnvONYelCNFC", "active": true, "roles": ["admin"]])])
app.storage[Application.MockDatabaseKey.self]?.results.append ([MockDatabase.Row (values: ["name": "admin"])])
try await app.testing().test(
.POST,
"api/auth/login",
beforeRequest: { request async in
request.headers.contentType = .json
request.body = ByteBuffer (string: #"{"email": "gamma", "password": ""}"#)
},
afterResponse: { res async in
#expect(res.status == .ok)
#expect(res.headers.setCookie?["vapor-session"] != nil)
session = res.headers.setCookie?["vapor-session"]?.string
})
try await app.testing().test(.GET, "admin",
beforeRequest: { request async in
request.headers.cookie = ["vapor-session": HTTPCookies.Value (string: session ?? "")]
},
afterResponse: { res async in
#expect(res.status == .ok)
#expect(res.headers.setCookie?["vapor-session"]?.string == session)
})
#expect(app.storage[Application.MockDatabaseKey.self]?.queries.count == 3)
}
}
@Test("Forgot password route")
func forgotPasswordRoute() async throws {
try await withApp { app in
app.storage[Application.MockDatabaseKey.self]?.results.append ([MockDatabase.Row (values: [:])])
app.storage[Application.MockDatabaseKey.self]?.results.append ([MockDatabase.Row (values: ["id": UUID(), "email": "a@b", "full_name": "Somebody", "password": "", "active": true, "roles": [""]])])
app.storage[Application.MockDatabaseKey.self]?.results.append ([MockDatabase.Row (values: ["token": "füffe"])])
app.storage[Application.MockDatabaseKey.self]?.results.append ([MockDatabase.Row (values: [:])])
app.storage[Application.MockDatabaseKey.self]?.results.append ([MockDatabase.Row (values: [:])])
try await app.testing().test(.POST, "api/auth/forgot",
beforeRequest: { request async throws in
try request.content.encode (["email": "gamma"])
},
afterResponse: { res async in
#expect(res.status == .ok)
})
#expect(app.storage[Application.MockDatabaseKey.self]?.queries.count == 5)
}
}
@Test("Forgot password route without account")
func forgotPasswordRouteWithoutAccount() async throws {
try await withApp { app in
app.storage[Application.MockDatabaseKey.self]?.results.append ([MockDatabase.Row (values: [:])])
app.storage[Application.MockDatabaseKey.self]?.results.append ([])
app.storage[Application.MockDatabaseKey.self]?.results.append ([MockDatabase.Row (values: ["token": "füffe"])])
try await app.testing().test(.POST, "api/auth/forgot",
beforeRequest: { request async throws in
try request.content.encode (["email": "gamma"])
},
afterResponse: { res async in
#expect(res.status == .ok)
})
#expect(app.storage[Application.MockDatabaseKey.self]?.queries.count == 3)
}
}
}