* added common project information; setup for v2 test change * all tests now use with_test_environment * progress, failing * finished re-adding tests * prepare * cargo sqlx prepare -- --tests * fmt; clippy; prepare * sqlx prepare * adds version_create fix and corresponding test * merge fixes; rev * fmt, clippy, prepare * test cargo sqlx prepare
130 lines
4.9 KiB
Rust
130 lines
4.9 KiB
Rust
#![allow(dead_code)]
|
|
use actix_web::test::{self, TestRequest};
|
|
use labrinth::models::pats::Scopes;
|
|
|
|
use super::{
|
|
api_common::Api, database::USER_USER_ID_PARSED, environment::TestEnvironment,
|
|
pats::create_test_pat,
|
|
};
|
|
|
|
// A reusable test type that works for any scope test testing an endpoint that:
|
|
// - returns a known 'expected_failure_code' if the scope is not present (defaults to 401)
|
|
// - returns a 200-299 if the scope is present
|
|
// - returns failure and success JSON bodies for requests that are 200 (for performing non-simple follow-up tests on)
|
|
// This uses a builder format, so you can chain methods to set the parameters to non-defaults (most will probably be not need to be set).
|
|
pub struct ScopeTest<'a, A> {
|
|
test_env: &'a TestEnvironment<A>,
|
|
// Scopes expected to fail on this test. By default, this is all scopes except the success scopes.
|
|
// (To ensure we have isolated the scope we are testing)
|
|
failure_scopes: Option<Scopes>,
|
|
// User ID to use for the PATs. By default, this is the USER_USER_ID_PARSED constant.
|
|
user_id: i64,
|
|
// The code that is expected to be returned if the scope is not present. By default, this is 401 (Unauthorized)
|
|
expected_failure_code: u16,
|
|
}
|
|
|
|
impl<'a, A: Api> ScopeTest<'a, A> {
|
|
pub fn new(test_env: &'a TestEnvironment<A>) -> Self {
|
|
Self {
|
|
test_env,
|
|
failure_scopes: None,
|
|
user_id: USER_USER_ID_PARSED,
|
|
expected_failure_code: 401,
|
|
}
|
|
}
|
|
|
|
// Set non-standard failure scopes
|
|
// If not set, it will be set to all scopes except the success scopes
|
|
// (eg: if a combination of scopes is needed, but you want to make sure that the endpoint does not work with all-but-one of them)
|
|
pub fn with_failure_scopes(mut self, scopes: Scopes) -> Self {
|
|
self.failure_scopes = Some(scopes);
|
|
self
|
|
}
|
|
|
|
// Set the user ID to use
|
|
// (eg: a moderator, or friend)
|
|
pub fn with_user_id(mut self, user_id: i64) -> Self {
|
|
self.user_id = user_id;
|
|
self
|
|
}
|
|
|
|
// If a non-401 code is expected.
|
|
// (eg: a 404 for a hidden resource, or 200 for a resource with hidden values deeper in)
|
|
pub fn with_failure_code(mut self, code: u16) -> Self {
|
|
self.expected_failure_code = code;
|
|
self
|
|
}
|
|
|
|
// Call the endpoint generated by req_gen twice, once with a PAT with the failure scopes, and once with the success scopes.
|
|
// success_scopes : the scopes that we are testing that should succeed
|
|
// returns a tuple of (failure_body, success_body)
|
|
// Should return a String error if on unexpected status code, allowing unwrapping in tests.
|
|
pub async fn test<T>(
|
|
&self,
|
|
req_gen: T,
|
|
success_scopes: Scopes,
|
|
) -> Result<(serde_json::Value, serde_json::Value), String>
|
|
where
|
|
T: Fn() -> TestRequest,
|
|
{
|
|
// First, create a PAT with failure scopes
|
|
let failure_scopes = self
|
|
.failure_scopes
|
|
.unwrap_or(Scopes::all() ^ success_scopes);
|
|
let access_token_all_others =
|
|
create_test_pat(failure_scopes, self.user_id, &self.test_env.db).await;
|
|
|
|
// Create a PAT with the success scopes
|
|
let access_token = create_test_pat(success_scopes, self.user_id, &self.test_env.db).await;
|
|
|
|
// Perform test twice, once with each PAT
|
|
// the first time, we expect a 401 (or known failure code)
|
|
let req = req_gen()
|
|
.append_header(("Authorization", access_token_all_others.as_str()))
|
|
.to_request();
|
|
let resp = self.test_env.call(req).await;
|
|
|
|
if resp.status().as_u16() != self.expected_failure_code {
|
|
return Err(format!(
|
|
"Expected failure code {}, got {} ({:#?})",
|
|
self.expected_failure_code,
|
|
resp.status().as_u16(),
|
|
resp.response()
|
|
));
|
|
}
|
|
|
|
let failure_body = if resp.status() == 200
|
|
&& resp.headers().contains_key("Content-Type")
|
|
&& resp.headers().get("Content-Type").unwrap() == "application/json"
|
|
{
|
|
test::read_body_json(resp).await
|
|
} else {
|
|
serde_json::Value::Null
|
|
};
|
|
|
|
// The second time, we expect a success code
|
|
let req = req_gen()
|
|
.append_header(("Authorization", access_token.as_str()))
|
|
.to_request();
|
|
let resp = self.test_env.call(req).await;
|
|
|
|
if !(resp.status().is_success() || resp.status().is_redirection()) {
|
|
return Err(format!(
|
|
"Expected success code, got {} ({:#?})",
|
|
resp.status().as_u16(),
|
|
resp.response()
|
|
));
|
|
}
|
|
|
|
let success_body = if resp.status() == 200
|
|
&& resp.headers().contains_key("Content-Type")
|
|
&& resp.headers().get("Content-Type").unwrap() == "application/json"
|
|
{
|
|
test::read_body_json(resp).await
|
|
} else {
|
|
serde_json::Value::Null
|
|
};
|
|
Ok((failure_body, success_body))
|
|
}
|
|
}
|