You've already forked AstralRinth
forked from didirus/AstralRinth
Tests 3 restructure (#754)
* moved files * moved files * initial v3 additions * moves req data * tests passing, restructuring, remove v2 * fmt; clippy; prepare * merge conflicts + issues * merge conflict, fmt, clippy, prepare * revs * fixed failing test * fixed tests
This commit is contained in:
@@ -4,8 +4,8 @@ use super::environment::LocalService;
|
||||
use actix_web::dev::ServiceResponse;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub mod organization;
|
||||
pub mod project;
|
||||
pub mod request_data;
|
||||
pub mod tags;
|
||||
pub mod team;
|
||||
pub mod version;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::common::api_v2::request_data::ProjectCreationRequestData;
|
||||
use actix_http::StatusCode;
|
||||
use actix_web::{
|
||||
dev::ServiceResponse,
|
||||
@@ -14,14 +13,11 @@ use labrinth::{
|
||||
};
|
||||
use rust_decimal::Decimal;
|
||||
use serde_json::json;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::common::{
|
||||
asserts::assert_status,
|
||||
database::MOD_USER_PAT,
|
||||
request_data::{ImageData, ProjectCreationRequestData},
|
||||
};
|
||||
use crate::common::{asserts::assert_status, database::MOD_USER_PAT};
|
||||
|
||||
use super::ApiV2;
|
||||
use super::{request_data::ImageData, ApiV2};
|
||||
|
||||
impl ApiV2 {
|
||||
pub async fn add_public_project(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#![allow(dead_code)]
|
||||
use serde_json::json;
|
||||
|
||||
use super::dummy_data::{DummyImage, TestFile};
|
||||
use crate::common::dummy_data::{DummyImage, TestFile};
|
||||
use labrinth::{
|
||||
models::projects::ProjectId,
|
||||
util::actix::{MultipartSegment, MultipartSegmentData},
|
||||
@@ -12,9 +12,9 @@ use labrinth::{
|
||||
};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::common::{asserts::assert_status, request_data::VersionCreationRequestData};
|
||||
use crate::common::asserts::assert_status;
|
||||
|
||||
use super::ApiV2;
|
||||
use super::{request_data::VersionCreationRequestData, ApiV2};
|
||||
|
||||
pub fn url_encode_json_serialized_vec(elements: &[String]) -> String {
|
||||
let serialized = serde_json::to_string(&elements).unwrap();
|
||||
@@ -327,8 +327,7 @@ impl ApiV2 {
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
// TODO: remove redundancy in these functions
|
||||
|
||||
// TODO: remove redundancy in these functions- some are essentially repeats
|
||||
pub async fn create_default_version(
|
||||
&self,
|
||||
project_id: &str,
|
||||
|
||||
@@ -6,7 +6,12 @@ use std::rc::Rc;
|
||||
|
||||
pub mod oauth;
|
||||
pub mod oauth_clients;
|
||||
pub mod organization;
|
||||
pub mod project;
|
||||
pub mod request_data;
|
||||
pub mod tags;
|
||||
pub mod team;
|
||||
pub mod version;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ApiV3 {
|
||||
@@ -17,4 +22,15 @@ impl ApiV3 {
|
||||
pub async fn call(&self, req: actix_http::Request) -> ServiceResponse {
|
||||
self.test_app.call(req).await.unwrap()
|
||||
}
|
||||
|
||||
pub async fn reset_search_index(&self) -> ServiceResponse {
|
||||
let req = actix_web::test::TestRequest::post()
|
||||
.uri("/v3/admin/_force_reindex")
|
||||
.append_header((
|
||||
"Modrinth-Admin",
|
||||
dotenvy::var("LABRINTH_ADMIN_KEY").unwrap(),
|
||||
))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ impl ApiV3 {
|
||||
pub async fn oauth_accept(&self, flow: &str, pat: &str) -> ServiceResponse {
|
||||
self.call(
|
||||
TestRequest::post()
|
||||
.uri("/v3/auth/oauth/accept")
|
||||
.uri("/v3/oauth/accept")
|
||||
.append_header((AUTHORIZATION, pat))
|
||||
.set_json(RespondToOAuthClientScopes {
|
||||
flow: flow.to_string(),
|
||||
@@ -68,7 +68,7 @@ impl ApiV3 {
|
||||
pub async fn oauth_reject(&self, flow: &str, pat: &str) -> ServiceResponse {
|
||||
self.call(
|
||||
TestRequest::post()
|
||||
.uri("/v3/auth/oauth/reject")
|
||||
.uri("/v3/oauth/reject")
|
||||
.append_header((AUTHORIZATION, pat))
|
||||
.set_json(RespondToOAuthClientScopes {
|
||||
flow: flow.to_string(),
|
||||
@@ -87,7 +87,7 @@ impl ApiV3 {
|
||||
) -> ServiceResponse {
|
||||
self.call(
|
||||
TestRequest::post()
|
||||
.uri("/v3/auth/oauth/token")
|
||||
.uri("/v3/oauth/token")
|
||||
.append_header((AUTHORIZATION, client_secret))
|
||||
.set_form(TokenRequest {
|
||||
grant_type: "authorization_code".to_string(),
|
||||
@@ -108,7 +108,7 @@ pub fn generate_authorize_uri(
|
||||
state: Option<&str>,
|
||||
) -> String {
|
||||
format!(
|
||||
"/v3/auth/oauth/authorize?client_id={}{}{}{}",
|
||||
"/v3/oauth/authorize?client_id={}{}{}{}",
|
||||
urlencoding::encode(client_id),
|
||||
optional_query_param("redirect_uri", redirect_uri),
|
||||
optional_query_param("scope", scope),
|
||||
|
||||
@@ -3,14 +3,12 @@ use actix_web::{
|
||||
test::{self, TestRequest},
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use labrinth::models::{organizations::Organization, v2::projects::LegacyProject};
|
||||
use labrinth::models::{organizations::Organization, v3::projects::Project};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::common::request_data::ImageData;
|
||||
use super::{request_data::ImageData, ApiV3};
|
||||
|
||||
use super::ApiV2;
|
||||
|
||||
impl ApiV2 {
|
||||
impl ApiV3 {
|
||||
pub async fn create_organization(
|
||||
&self,
|
||||
organization_title: &str,
|
||||
@@ -18,7 +16,7 @@ impl ApiV2 {
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::post()
|
||||
.uri("/v2/organization")
|
||||
.uri("/v3/organization")
|
||||
.append_header(("Authorization", pat))
|
||||
.set_json(json!({
|
||||
"title": organization_title,
|
||||
@@ -30,7 +28,7 @@ impl ApiV2 {
|
||||
|
||||
pub async fn get_organization(&self, id_or_title: &str, pat: &str) -> ServiceResponse {
|
||||
let req = TestRequest::get()
|
||||
.uri(&format!("/v2/organization/{id_or_title}"))
|
||||
.uri(&format!("/v3/organization/{id_or_title}"))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
@@ -48,7 +46,7 @@ impl ApiV2 {
|
||||
|
||||
pub async fn get_organization_projects(&self, id_or_title: &str, pat: &str) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v2/organization/{id_or_title}/projects"))
|
||||
.uri(&format!("/v3/organization/{id_or_title}/projects"))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
@@ -58,7 +56,7 @@ impl ApiV2 {
|
||||
&self,
|
||||
id_or_title: &str,
|
||||
pat: &str,
|
||||
) -> Vec<LegacyProject> {
|
||||
) -> Vec<Project> {
|
||||
let resp = self.get_organization_projects(id_or_title, pat).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
test::read_body_json(resp).await
|
||||
@@ -71,7 +69,7 @@ impl ApiV2 {
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!("/v2/organization/{id_or_title}"))
|
||||
.uri(&format!("/v3/organization/{id_or_title}"))
|
||||
.append_header(("Authorization", pat))
|
||||
.set_json(patch)
|
||||
.to_request();
|
||||
@@ -89,7 +87,7 @@ impl ApiV2 {
|
||||
// If an icon is provided, upload it
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!(
|
||||
"/v2/organization/{id_or_title}/icon?ext={ext}",
|
||||
"/v3/organization/{id_or_title}/icon?ext={ext}",
|
||||
ext = icon.extension
|
||||
))
|
||||
.append_header(("Authorization", pat))
|
||||
@@ -100,7 +98,7 @@ impl ApiV2 {
|
||||
} else {
|
||||
// If no icon is provided, delete the icon
|
||||
let req = test::TestRequest::delete()
|
||||
.uri(&format!("/v2/organization/{id_or_title}/icon"))
|
||||
.uri(&format!("/v3/organization/{id_or_title}/icon"))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
|
||||
@@ -110,7 +108,7 @@ impl ApiV2 {
|
||||
|
||||
pub async fn delete_organization(&self, id_or_title: &str, pat: &str) -> ServiceResponse {
|
||||
let req = test::TestRequest::delete()
|
||||
.uri(&format!("/v2/organization/{id_or_title}"))
|
||||
.uri(&format!("/v3/organization/{id_or_title}"))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
|
||||
@@ -124,7 +122,7 @@ impl ApiV2 {
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::post()
|
||||
.uri(&format!("/v2/organization/{id_or_title}/projects"))
|
||||
.uri(&format!("/v3/organization/{id_or_title}/projects"))
|
||||
.append_header(("Authorization", pat))
|
||||
.set_json(json!({
|
||||
"project_id": project_id_or_slug,
|
||||
@@ -142,7 +140,7 @@ impl ApiV2 {
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::delete()
|
||||
.uri(&format!(
|
||||
"/v2/organization/{id_or_title}/projects/{project_id_or_slug}"
|
||||
"/v3/organization/{id_or_title}/projects/{project_id_or_slug}"
|
||||
))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
256
tests/common/api_v3/project.rs
Normal file
256
tests/common/api_v3/project.rs
Normal file
@@ -0,0 +1,256 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use actix_http::StatusCode;
|
||||
use actix_web::{
|
||||
dev::ServiceResponse,
|
||||
test::{self, TestRequest},
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use chrono::{DateTime, Utc};
|
||||
use labrinth::{
|
||||
models::v3::projects::{Project, Version},
|
||||
search::SearchResults,
|
||||
util::actix::AppendsMultipart,
|
||||
};
|
||||
use rust_decimal::Decimal;
|
||||
use serde_json::json;
|
||||
|
||||
use crate::common::{asserts::assert_status, database::MOD_USER_PAT};
|
||||
|
||||
use super::{
|
||||
request_data::{ImageData, ProjectCreationRequestData},
|
||||
ApiV3,
|
||||
};
|
||||
|
||||
impl ApiV3 {
|
||||
pub async fn add_public_project(
|
||||
&self,
|
||||
creation_data: ProjectCreationRequestData,
|
||||
pat: &str,
|
||||
) -> (Project, Vec<Version>) {
|
||||
// Add a project.
|
||||
let req = TestRequest::post()
|
||||
.uri("/v3/project")
|
||||
.append_header(("Authorization", pat))
|
||||
.set_multipart(creation_data.segment_data)
|
||||
.to_request();
|
||||
let resp = self.call(req).await;
|
||||
assert_status(&resp, StatusCode::OK);
|
||||
|
||||
// Approve as a moderator.
|
||||
let req = TestRequest::patch()
|
||||
.uri(&format!("/v3/project/{}", creation_data.slug))
|
||||
.append_header(("Authorization", MOD_USER_PAT))
|
||||
.set_json(json!(
|
||||
{
|
||||
"status": "approved"
|
||||
}
|
||||
))
|
||||
.to_request();
|
||||
let resp = self.call(req).await;
|
||||
assert_status(&resp, StatusCode::NO_CONTENT);
|
||||
|
||||
let project = self
|
||||
.get_project_deserialized(&creation_data.slug, pat)
|
||||
.await;
|
||||
|
||||
// Get project's versions
|
||||
let req = TestRequest::get()
|
||||
.uri(&format!("/v3/project/{}/version", creation_data.slug))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
let resp = self.call(req).await;
|
||||
let versions: Vec<Version> = test::read_body_json(resp).await;
|
||||
|
||||
(project, versions)
|
||||
}
|
||||
|
||||
pub async fn remove_project(&self, project_slug_or_id: &str, pat: &str) -> ServiceResponse {
|
||||
let req = test::TestRequest::delete()
|
||||
.uri(&format!("/v3/project/{project_slug_or_id}"))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
let resp = self.call(req).await;
|
||||
assert_eq!(resp.status(), 204);
|
||||
resp
|
||||
}
|
||||
|
||||
pub async fn get_project(&self, id_or_slug: &str, pat: &str) -> ServiceResponse {
|
||||
let req = TestRequest::get()
|
||||
.uri(&format!("/v3/project/{id_or_slug}"))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
pub async fn get_project_deserialized(&self, id_or_slug: &str, pat: &str) -> Project {
|
||||
let resp = self.get_project(id_or_slug, pat).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
pub async fn get_user_projects(&self, user_id_or_username: &str, pat: &str) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/user/{}/projects", user_id_or_username))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_user_projects_deserialized(
|
||||
&self,
|
||||
user_id_or_username: &str,
|
||||
pat: &str,
|
||||
) -> Vec<Project> {
|
||||
let resp = self.get_user_projects(user_id_or_username, pat).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
pub async fn edit_project(
|
||||
&self,
|
||||
id_or_slug: &str,
|
||||
patch: serde_json::Value,
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!("/v3/project/{id_or_slug}"))
|
||||
.append_header(("Authorization", pat))
|
||||
.set_json(patch)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn edit_project_bulk(
|
||||
&self,
|
||||
ids_or_slugs: impl IntoIterator<Item = &str>,
|
||||
patch: serde_json::Value,
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
let projects_str = ids_or_slugs
|
||||
.into_iter()
|
||||
.map(|s| format!("\"{}\"", s))
|
||||
.collect::<Vec<_>>()
|
||||
.join(",");
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!(
|
||||
"/v3/projects?ids={encoded}",
|
||||
encoded = urlencoding::encode(&format!("[{projects_str}]"))
|
||||
))
|
||||
.append_header(("Authorization", pat))
|
||||
.set_json(patch)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn edit_project_icon(
|
||||
&self,
|
||||
id_or_slug: &str,
|
||||
icon: Option<ImageData>,
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
if let Some(icon) = icon {
|
||||
// If an icon is provided, upload it
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!(
|
||||
"/v3/project/{id_or_slug}/icon?ext={ext}",
|
||||
ext = icon.extension
|
||||
))
|
||||
.append_header(("Authorization", pat))
|
||||
.set_payload(Bytes::from(icon.icon))
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
} else {
|
||||
// If no icon is provided, delete the icon
|
||||
let req = test::TestRequest::delete()
|
||||
.uri(&format!("/v3/project/{id_or_slug}/icon"))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn search_deserialized(
|
||||
&self,
|
||||
query: Option<&str>,
|
||||
facets: Option<serde_json::Value>,
|
||||
pat: &str,
|
||||
) -> SearchResults {
|
||||
let query_field = if let Some(query) = query {
|
||||
format!("&query={}", urlencoding::encode(query))
|
||||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
|
||||
let facets_field = if let Some(facets) = facets {
|
||||
format!("&facets={}", urlencoding::encode(&facets.to_string()))
|
||||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/search?{}{}", query_field, facets_field))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
let resp = self.call(req).await;
|
||||
let status = resp.status();
|
||||
assert_eq!(status, 200);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
pub async fn get_analytics_revenue(
|
||||
&self,
|
||||
id_or_slugs: Vec<&str>,
|
||||
start_date: Option<DateTime<Utc>>,
|
||||
end_date: Option<DateTime<Utc>>,
|
||||
resolution_minutes: Option<u32>,
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
let projects_string = serde_json::to_string(&id_or_slugs).unwrap();
|
||||
let projects_string = urlencoding::encode(&projects_string);
|
||||
|
||||
let mut extra_args = String::new();
|
||||
if let Some(start_date) = start_date {
|
||||
let start_date = start_date.to_rfc3339();
|
||||
// let start_date = serde_json::to_string(&start_date).unwrap();
|
||||
let start_date = urlencoding::encode(&start_date);
|
||||
extra_args.push_str(&format!("&start_date={start_date}"));
|
||||
}
|
||||
if let Some(end_date) = end_date {
|
||||
let end_date = end_date.to_rfc3339();
|
||||
// let end_date = serde_json::to_string(&end_date).unwrap();
|
||||
let end_date = urlencoding::encode(&end_date);
|
||||
extra_args.push_str(&format!("&end_date={end_date}"));
|
||||
}
|
||||
if let Some(resolution_minutes) = resolution_minutes {
|
||||
extra_args.push_str(&format!("&resolution_minutes={}", resolution_minutes));
|
||||
}
|
||||
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!(
|
||||
"/v3/analytics/revenue?{projects_string}{extra_args}",
|
||||
))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_analytics_revenue_deserialized(
|
||||
&self,
|
||||
id_or_slugs: Vec<&str>,
|
||||
start_date: Option<DateTime<Utc>>,
|
||||
end_date: Option<DateTime<Utc>>,
|
||||
resolution_minutes: Option<u32>,
|
||||
pat: &str,
|
||||
) -> HashMap<String, HashMap<i64, Decimal>> {
|
||||
let resp = self
|
||||
.get_analytics_revenue(id_or_slugs, start_date, end_date, resolution_minutes, pat)
|
||||
.await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
}
|
||||
146
tests/common/api_v3/request_data.rs
Normal file
146
tests/common/api_v3/request_data.rs
Normal file
@@ -0,0 +1,146 @@
|
||||
#![allow(dead_code)]
|
||||
use serde_json::json;
|
||||
|
||||
use crate::common::dummy_data::{DummyImage, TestFile};
|
||||
use labrinth::{
|
||||
models::projects::ProjectId,
|
||||
util::actix::{MultipartSegment, MultipartSegmentData},
|
||||
};
|
||||
|
||||
pub struct ProjectCreationRequestData {
|
||||
pub slug: String,
|
||||
pub jar: Option<TestFile>,
|
||||
pub segment_data: Vec<MultipartSegment>,
|
||||
}
|
||||
|
||||
pub struct VersionCreationRequestData {
|
||||
pub version: String,
|
||||
pub jar: Option<TestFile>,
|
||||
pub segment_data: Vec<MultipartSegment>,
|
||||
}
|
||||
|
||||
pub struct ImageData {
|
||||
pub filename: String,
|
||||
pub extension: String,
|
||||
pub icon: Vec<u8>,
|
||||
}
|
||||
|
||||
pub fn get_public_project_creation_data(
|
||||
slug: &str,
|
||||
version_jar: Option<TestFile>,
|
||||
) -> ProjectCreationRequestData {
|
||||
let json_data = get_public_project_creation_data_json(slug, version_jar.as_ref());
|
||||
let multipart_data = get_public_creation_data_multipart(&json_data, version_jar.as_ref());
|
||||
ProjectCreationRequestData {
|
||||
slug: slug.to_string(),
|
||||
jar: version_jar,
|
||||
segment_data: multipart_data,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_public_version_creation_data(
|
||||
project_id: ProjectId,
|
||||
version_number: &str,
|
||||
version_jar: TestFile,
|
||||
// closure that takes in a &mut serde_json::Value
|
||||
// and modifies it before it is serialized and sent
|
||||
modify_json: Option<impl FnOnce(&mut serde_json::Value)>,
|
||||
) -> VersionCreationRequestData {
|
||||
let mut json_data = get_public_version_creation_data_json(version_number, &version_jar);
|
||||
json_data["project_id"] = json!(project_id);
|
||||
if let Some(modify_json) = modify_json {
|
||||
modify_json(&mut json_data);
|
||||
}
|
||||
|
||||
let multipart_data = get_public_creation_data_multipart(&json_data, Some(&version_jar));
|
||||
VersionCreationRequestData {
|
||||
version: version_number.to_string(),
|
||||
jar: Some(version_jar),
|
||||
segment_data: multipart_data,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_public_version_creation_data_json(
|
||||
version_number: &str,
|
||||
version_jar: &TestFile,
|
||||
) -> serde_json::Value {
|
||||
let is_modpack = version_jar.project_type() == "modpack";
|
||||
let mut j = json!({
|
||||
"file_parts": [version_jar.filename()],
|
||||
"version_number": version_number,
|
||||
"version_title": "start",
|
||||
"dependencies": [],
|
||||
"release_channel": "release",
|
||||
"loaders": [if is_modpack { "mrpack" } else { "fabric" }],
|
||||
"featured": true,
|
||||
|
||||
// Loader fields
|
||||
"game_versions": ["1.20.1"],
|
||||
"client_side": "required",
|
||||
"server_side": "optional"
|
||||
});
|
||||
if is_modpack {
|
||||
j["mrpack_loaders"] = json!(["fabric"]);
|
||||
}
|
||||
j
|
||||
}
|
||||
|
||||
pub fn get_public_project_creation_data_json(
|
||||
slug: &str,
|
||||
version_jar: Option<&TestFile>,
|
||||
) -> serde_json::Value {
|
||||
let initial_versions = if let Some(jar) = version_jar {
|
||||
json!([get_public_version_creation_data_json("1.2.3", jar)])
|
||||
} else {
|
||||
json!([])
|
||||
};
|
||||
|
||||
let is_draft = version_jar.is_none();
|
||||
json!(
|
||||
{
|
||||
"title": format!("Test Project {slug}"),
|
||||
"slug": slug,
|
||||
"description": "A dummy project for testing with.",
|
||||
"body": "This project is approved, and versions are listed.",
|
||||
"initial_versions": initial_versions,
|
||||
"is_draft": is_draft,
|
||||
"categories": [],
|
||||
"license_id": "MIT",
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_public_creation_data_multipart(
|
||||
json_data: &serde_json::Value,
|
||||
version_jar: Option<&TestFile>,
|
||||
) -> Vec<MultipartSegment> {
|
||||
// Basic json
|
||||
let json_segment = MultipartSegment {
|
||||
name: "data".to_string(),
|
||||
filename: None,
|
||||
content_type: Some("application/json".to_string()),
|
||||
data: MultipartSegmentData::Text(serde_json::to_string(json_data).unwrap()),
|
||||
};
|
||||
|
||||
if let Some(jar) = version_jar {
|
||||
// Basic file
|
||||
let file_segment = MultipartSegment {
|
||||
name: jar.filename(),
|
||||
filename: Some(jar.filename()),
|
||||
content_type: Some("application/java-archive".to_string()),
|
||||
data: MultipartSegmentData::Binary(jar.bytes()),
|
||||
};
|
||||
|
||||
vec![json_segment, file_segment]
|
||||
} else {
|
||||
vec![json_segment]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_icon_data(dummy_icon: DummyImage) -> ImageData {
|
||||
ImageData {
|
||||
filename: dummy_icon.filename(),
|
||||
extension: dummy_icon.extension(),
|
||||
icon: dummy_icon.bytes(),
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,61 @@ use actix_web::{
|
||||
test::{self, TestRequest},
|
||||
};
|
||||
use labrinth::routes::v3::tags::GameData;
|
||||
use labrinth::{
|
||||
database::models::loader_fields::LoaderFieldEnumValue,
|
||||
routes::v3::tags::{CategoryData, LoaderData},
|
||||
};
|
||||
|
||||
use crate::common::database::ADMIN_USER_PAT;
|
||||
|
||||
use super::ApiV3;
|
||||
|
||||
impl ApiV3 {
|
||||
pub async fn get_loaders(&self) -> ServiceResponse {
|
||||
let req = TestRequest::get()
|
||||
.uri("/v3/tag/loader")
|
||||
.append_header(("Authorization", ADMIN_USER_PAT))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_loaders_deserialized(&self) -> Vec<LoaderData> {
|
||||
let resp = self.get_loaders().await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
pub async fn get_categories(&self) -> ServiceResponse {
|
||||
let req = TestRequest::get()
|
||||
.uri("/v3/tag/category")
|
||||
.append_header(("Authorization", ADMIN_USER_PAT))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_categories_deserialized(&self) -> Vec<CategoryData> {
|
||||
let resp = self.get_categories().await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
pub async fn get_loader_field_variants(&self, loader_field: &str) -> ServiceResponse {
|
||||
let req = TestRequest::get()
|
||||
.uri(&format!("/v3/loader_field?loader_field={}", loader_field))
|
||||
.append_header(("Authorization", ADMIN_USER_PAT))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_loader_field_variants_deserialized(
|
||||
&self,
|
||||
loader_field: &str,
|
||||
) -> Vec<LoaderFieldEnumValue> {
|
||||
let resp = self.get_loader_field_variants(loader_field).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
// TODO: fold this into v3 API of other v3 testing PR
|
||||
pub async fn get_games(&self) -> ServiceResponse {
|
||||
let req = TestRequest::get()
|
||||
|
||||
176
tests/common/api_v3/team.rs
Normal file
176
tests/common/api_v3/team.rs
Normal file
@@ -0,0 +1,176 @@
|
||||
use actix_http::StatusCode;
|
||||
use actix_web::{dev::ServiceResponse, test};
|
||||
use labrinth::models::{
|
||||
notifications::Notification,
|
||||
teams::{OrganizationPermissions, ProjectPermissions, TeamMember},
|
||||
};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::common::asserts::assert_status;
|
||||
|
||||
use super::ApiV3;
|
||||
|
||||
impl ApiV3 {
|
||||
pub async fn get_team_members(&self, id_or_title: &str, pat: &str) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/team/{id_or_title}/members"))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_team_members_deserialized(
|
||||
&self,
|
||||
id_or_title: &str,
|
||||
pat: &str,
|
||||
) -> Vec<TeamMember> {
|
||||
let resp = self.get_team_members(id_or_title, pat).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
pub async fn get_project_members(&self, id_or_title: &str, pat: &str) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/project/{id_or_title}/members"))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_project_members_deserialized(
|
||||
&self,
|
||||
id_or_title: &str,
|
||||
pat: &str,
|
||||
) -> Vec<TeamMember> {
|
||||
let resp = self.get_project_members(id_or_title, pat).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
pub async fn get_organization_members(&self, id_or_title: &str, pat: &str) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/organization/{id_or_title}/members"))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_organization_members_deserialized(
|
||||
&self,
|
||||
id_or_title: &str,
|
||||
pat: &str,
|
||||
) -> Vec<TeamMember> {
|
||||
let resp = self.get_organization_members(id_or_title, pat).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
pub async fn join_team(&self, team_id: &str, pat: &str) -> ServiceResponse {
|
||||
let req = test::TestRequest::post()
|
||||
.uri(&format!("/v3/team/{team_id}/join"))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn remove_from_team(
|
||||
&self,
|
||||
team_id: &str,
|
||||
user_id: &str,
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::delete()
|
||||
.uri(&format!("/v3/team/{team_id}/members/{user_id}"))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn edit_team_member(
|
||||
&self,
|
||||
team_id: &str,
|
||||
user_id: &str,
|
||||
patch: serde_json::Value,
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!("/v3/team/{team_id}/members/{user_id}"))
|
||||
.append_header(("Authorization", pat))
|
||||
.set_json(patch)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn transfer_team_ownership(
|
||||
&self,
|
||||
team_id: &str,
|
||||
user_id: &str,
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!("/v3/team/{team_id}/owner"))
|
||||
.append_header(("Authorization", pat))
|
||||
.set_json(json!({
|
||||
"user_id": user_id,
|
||||
}))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_user_notifications(&self, user_id: &str, pat: &str) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/user/{user_id}/notifications"))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_user_notifications_deserialized(
|
||||
&self,
|
||||
user_id: &str,
|
||||
pat: &str,
|
||||
) -> Vec<Notification> {
|
||||
let resp = self.get_user_notifications(user_id, pat).await;
|
||||
assert_status(&resp, StatusCode::OK);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
pub async fn mark_notification_read(
|
||||
&self,
|
||||
notification_id: &str,
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!("/v3/notification/{notification_id}"))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
pub async fn add_user_to_team(
|
||||
&self,
|
||||
team_id: &str,
|
||||
user_id: &str,
|
||||
project_permissions: Option<ProjectPermissions>,
|
||||
organization_permissions: Option<OrganizationPermissions>,
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::post()
|
||||
.uri(&format!("/v3/team/{team_id}/members"))
|
||||
.append_header(("Authorization", pat))
|
||||
.set_json(json!( {
|
||||
"user_id": user_id,
|
||||
"permissions" : project_permissions.map(|p| p.bits()).unwrap_or_default(),
|
||||
"organization_permissions" : organization_permissions.map(|p| p.bits()),
|
||||
}))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn delete_notification(&self, notification_id: &str, pat: &str) -> ServiceResponse {
|
||||
let req = test::TestRequest::delete()
|
||||
.uri(&format!("/v3/notification/{notification_id}"))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
}
|
||||
422
tests/common/api_v3/version.rs
Normal file
422
tests/common/api_v3/version.rs
Normal file
@@ -0,0 +1,422 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use actix_http::{header::AUTHORIZATION, StatusCode};
|
||||
use actix_web::{
|
||||
dev::ServiceResponse,
|
||||
test::{self, TestRequest},
|
||||
};
|
||||
use labrinth::{
|
||||
models::{projects::VersionType, v3::projects::Version},
|
||||
routes::v3::version_file::FileUpdateData,
|
||||
util::actix::AppendsMultipart,
|
||||
};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::common::asserts::assert_status;
|
||||
|
||||
use super::{request_data::VersionCreationRequestData, ApiV3};
|
||||
|
||||
pub fn url_encode_json_serialized_vec(elements: &[String]) -> String {
|
||||
let serialized = serde_json::to_string(&elements).unwrap();
|
||||
urlencoding::encode(&serialized).to_string()
|
||||
}
|
||||
|
||||
impl ApiV3 {
|
||||
pub async fn add_public_version(
|
||||
&self,
|
||||
creation_data: VersionCreationRequestData,
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
// Add a project.
|
||||
let req = TestRequest::post()
|
||||
.uri("/v3/version")
|
||||
.append_header(("Authorization", pat))
|
||||
.set_multipart(creation_data.segment_data)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn add_public_version_deserialized(
|
||||
&self,
|
||||
creation_data: VersionCreationRequestData,
|
||||
pat: &str,
|
||||
) -> Version {
|
||||
let resp = self.add_public_version(creation_data, pat).await;
|
||||
assert_status(&resp, StatusCode::OK);
|
||||
let value: serde_json::Value = test::read_body_json(resp).await;
|
||||
let version_id = value["id"].as_str().unwrap();
|
||||
self.get_version_deserialized(version_id, pat).await
|
||||
}
|
||||
|
||||
pub async fn get_version(&self, id: &str, pat: &str) -> ServiceResponse {
|
||||
let req = TestRequest::get()
|
||||
.uri(&format!("/v3/version/{id}"))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_version_deserialized(&self, id: &str, pat: &str) -> Version {
|
||||
let resp = self.get_version(id, pat).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
pub async fn edit_version(
|
||||
&self,
|
||||
version_id: &str,
|
||||
patch: serde_json::Value,
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::patch()
|
||||
.uri(&format!("/v3/version/{version_id}"))
|
||||
.append_header(("Authorization", pat))
|
||||
.set_json(patch)
|
||||
.to_request();
|
||||
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_version_from_hash(
|
||||
&self,
|
||||
hash: &str,
|
||||
algorithm: &str,
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!("/v3/version_file/{hash}?algorithm={algorithm}"))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_version_from_hash_deserialized(
|
||||
&self,
|
||||
hash: &str,
|
||||
algorithm: &str,
|
||||
pat: &str,
|
||||
) -> Version {
|
||||
let resp = self.get_version_from_hash(hash, algorithm, pat).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
pub async fn get_versions_from_hashes(
|
||||
&self,
|
||||
hashes: &[&str],
|
||||
algorithm: &str,
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
let req = TestRequest::post()
|
||||
.uri("/v3/version_files")
|
||||
.append_header(("Authorization", pat))
|
||||
.set_json(json!({
|
||||
"hashes": hashes,
|
||||
"algorithm": algorithm,
|
||||
}))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_versions_from_hashes_deserialized(
|
||||
&self,
|
||||
hashes: &[&str],
|
||||
algorithm: &str,
|
||||
pat: &str,
|
||||
) -> HashMap<String, Version> {
|
||||
let resp = self.get_versions_from_hashes(hashes, algorithm, pat).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
pub async fn get_update_from_hash(
|
||||
&self,
|
||||
hash: &str,
|
||||
algorithm: &str,
|
||||
loaders: Option<Vec<String>>,
|
||||
game_versions: Option<Vec<String>>,
|
||||
version_types: Option<Vec<String>>,
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
let mut json = json!({});
|
||||
if let Some(loaders) = loaders {
|
||||
json["loaders"] = serde_json::to_value(loaders).unwrap();
|
||||
}
|
||||
if let Some(game_versions) = game_versions {
|
||||
json["loader_fields"] = json!({
|
||||
"game_versions": game_versions,
|
||||
});
|
||||
}
|
||||
if let Some(version_types) = version_types {
|
||||
json["version_types"] = serde_json::to_value(version_types).unwrap();
|
||||
}
|
||||
|
||||
let req = test::TestRequest::post()
|
||||
.uri(&format!(
|
||||
"/v3/version_file/{hash}/update?algorithm={algorithm}"
|
||||
))
|
||||
.append_header(("Authorization", pat))
|
||||
.set_json(json)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn get_update_from_hash_deserialized(
|
||||
&self,
|
||||
hash: &str,
|
||||
algorithm: &str,
|
||||
loaders: Option<Vec<String>>,
|
||||
game_versions: Option<Vec<String>>,
|
||||
version_types: Option<Vec<String>>,
|
||||
pat: &str,
|
||||
) -> Version {
|
||||
let resp = self
|
||||
.get_update_from_hash(hash, algorithm, loaders, game_versions, version_types, pat)
|
||||
.await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
pub async fn update_files(
|
||||
&self,
|
||||
algorithm: &str,
|
||||
hashes: Vec<String>,
|
||||
loaders: Option<Vec<String>>,
|
||||
game_versions: Option<Vec<String>>,
|
||||
version_types: Option<Vec<String>>,
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
let mut json = json!({
|
||||
"algorithm": algorithm,
|
||||
"hashes": hashes,
|
||||
});
|
||||
if let Some(loaders) = loaders {
|
||||
json["loaders"] = serde_json::to_value(loaders).unwrap();
|
||||
}
|
||||
if let Some(game_versions) = game_versions {
|
||||
json["loader_fields"] = json!({
|
||||
"game_versions": game_versions,
|
||||
});
|
||||
}
|
||||
if let Some(version_types) = version_types {
|
||||
json["version_types"] = serde_json::to_value(version_types).unwrap();
|
||||
}
|
||||
|
||||
let req = test::TestRequest::post()
|
||||
.uri("/v3/version_files/update")
|
||||
.append_header(("Authorization", pat))
|
||||
.set_json(json)
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn update_files_deserialized(
|
||||
&self,
|
||||
algorithm: &str,
|
||||
hashes: Vec<String>,
|
||||
loaders: Option<Vec<String>>,
|
||||
game_versions: Option<Vec<String>>,
|
||||
version_types: Option<Vec<String>>,
|
||||
pat: &str,
|
||||
) -> HashMap<String, Version> {
|
||||
let resp = self
|
||||
.update_files(
|
||||
algorithm,
|
||||
hashes,
|
||||
loaders,
|
||||
game_versions,
|
||||
version_types,
|
||||
pat,
|
||||
)
|
||||
.await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
pub async fn update_individual_files(
|
||||
&self,
|
||||
algorithm: &str,
|
||||
hashes: Vec<FileUpdateData>,
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
let req = test::TestRequest::post()
|
||||
.uri("/v3/version_files/update_individual")
|
||||
.append_header(("Authorization", pat))
|
||||
.set_json(json!({
|
||||
"algorithm": algorithm,
|
||||
"hashes": hashes
|
||||
}))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
pub async fn update_individual_files_deserialized(
|
||||
&self,
|
||||
algorithm: &str,
|
||||
hashes: Vec<FileUpdateData>,
|
||||
pat: &str,
|
||||
) -> HashMap<String, Version> {
|
||||
let resp = self.update_individual_files(algorithm, hashes, pat).await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
// TODO: Not all fields are tested currently in the v3 tests, only the v2-v3 relevant ones are
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn get_project_versions(
|
||||
&self,
|
||||
project_id_slug: &str,
|
||||
game_versions: Option<Vec<String>>,
|
||||
loaders: Option<Vec<String>>,
|
||||
featured: Option<bool>,
|
||||
version_type: Option<VersionType>,
|
||||
limit: Option<usize>,
|
||||
offset: Option<usize>,
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
let mut query_string = String::new();
|
||||
if let Some(game_versions) = game_versions {
|
||||
query_string.push_str(&format!(
|
||||
"&game_versions={}",
|
||||
urlencoding::encode(&serde_json::to_string(&game_versions).unwrap())
|
||||
));
|
||||
}
|
||||
if let Some(loaders) = loaders {
|
||||
query_string.push_str(&format!(
|
||||
"&loaders={}",
|
||||
urlencoding::encode(&serde_json::to_string(&loaders).unwrap())
|
||||
));
|
||||
}
|
||||
if let Some(featured) = featured {
|
||||
query_string.push_str(&format!("&featured={}", featured));
|
||||
}
|
||||
if let Some(version_type) = version_type {
|
||||
query_string.push_str(&format!("&version_type={}", version_type));
|
||||
}
|
||||
if let Some(limit) = limit {
|
||||
let limit = limit.to_string();
|
||||
query_string.push_str(&format!("&limit={}", limit));
|
||||
}
|
||||
if let Some(offset) = offset {
|
||||
let offset = offset.to_string();
|
||||
query_string.push_str(&format!("&offset={}", offset));
|
||||
}
|
||||
|
||||
let req = test::TestRequest::get()
|
||||
.uri(&format!(
|
||||
"/v3/project/{project_id_slug}/version?{}",
|
||||
query_string.trim_start_matches('&')
|
||||
))
|
||||
.append_header(("Authorization", pat))
|
||||
.to_request();
|
||||
self.call(req).await
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn get_project_versions_deserialized(
|
||||
&self,
|
||||
slug: &str,
|
||||
game_versions: Option<Vec<String>>,
|
||||
loaders: Option<Vec<String>>,
|
||||
featured: Option<bool>,
|
||||
version_type: Option<VersionType>,
|
||||
limit: Option<usize>,
|
||||
offset: Option<usize>,
|
||||
pat: &str,
|
||||
) -> Vec<Version> {
|
||||
let resp = self
|
||||
.get_project_versions(
|
||||
slug,
|
||||
game_versions,
|
||||
loaders,
|
||||
featured,
|
||||
version_type,
|
||||
limit,
|
||||
offset,
|
||||
pat,
|
||||
)
|
||||
.await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
// TODO: remove redundancy in these functions
|
||||
|
||||
pub async fn create_default_version(
|
||||
&self,
|
||||
project_id: &str,
|
||||
ordering: Option<i32>,
|
||||
pat: &str,
|
||||
) -> Version {
|
||||
let json_data = json!(
|
||||
{
|
||||
"project_id": project_id,
|
||||
"file_parts": ["basic-mod-different.jar"],
|
||||
"version_number": "1.2.3.4",
|
||||
"version_title": "start",
|
||||
"dependencies": [],
|
||||
"game_versions": ["1.20.1"] ,
|
||||
"client_side": "required",
|
||||
"server_side": "optional",
|
||||
"release_channel": "release",
|
||||
"loaders": ["fabric"],
|
||||
"featured": true,
|
||||
"ordering": ordering,
|
||||
}
|
||||
);
|
||||
let json_segment = labrinth::util::actix::MultipartSegment {
|
||||
name: "data".to_string(),
|
||||
filename: None,
|
||||
content_type: Some("application/json".to_string()),
|
||||
data: labrinth::util::actix::MultipartSegmentData::Text(
|
||||
serde_json::to_string(&json_data).unwrap(),
|
||||
),
|
||||
};
|
||||
let file_segment = labrinth::util::actix::MultipartSegment {
|
||||
name: "basic-mod-different.jar".to_string(),
|
||||
filename: Some("basic-mod.jar".to_string()),
|
||||
content_type: Some("application/java-archive".to_string()),
|
||||
data: labrinth::util::actix::MultipartSegmentData::Binary(
|
||||
include_bytes!("../../../tests/files/basic-mod-different.jar").to_vec(),
|
||||
),
|
||||
};
|
||||
|
||||
let request = test::TestRequest::post()
|
||||
.uri("/v3/version")
|
||||
.set_multipart(vec![json_segment.clone(), file_segment.clone()])
|
||||
.append_header((AUTHORIZATION, pat))
|
||||
.to_request();
|
||||
let resp = self.call(request).await;
|
||||
assert_status(&resp, StatusCode::OK);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
pub async fn get_versions(&self, version_ids: Vec<String>, pat: &str) -> Vec<Version> {
|
||||
let ids = url_encode_json_serialized_vec(&version_ids);
|
||||
let request = test::TestRequest::get()
|
||||
.uri(&format!("/v3/versions?ids={}", ids))
|
||||
.append_header((AUTHORIZATION, pat))
|
||||
.to_request();
|
||||
let resp = self.call(request).await;
|
||||
assert_status(&resp, StatusCode::OK);
|
||||
test::read_body_json(resp).await
|
||||
}
|
||||
|
||||
pub async fn edit_version_ordering(
|
||||
&self,
|
||||
version_id: &str,
|
||||
ordering: Option<i32>,
|
||||
pat: &str,
|
||||
) -> ServiceResponse {
|
||||
let request = test::TestRequest::patch()
|
||||
.uri(&format!("/v3/version/{version_id}"))
|
||||
.set_json(json!(
|
||||
{
|
||||
"ordering": ordering
|
||||
}
|
||||
))
|
||||
.append_header((AUTHORIZATION, pat))
|
||||
.to_request();
|
||||
self.call(request).await
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
use crate::common::get_json_val_str;
|
||||
use itertools::Itertools;
|
||||
use labrinth::models::v2::projects::LegacyVersion;
|
||||
use labrinth::models::v3::projects::Version;
|
||||
|
||||
pub fn assert_status(response: &actix_web::dev::ServiceResponse, status: actix_http::StatusCode) {
|
||||
assert_eq!(response.status(), status, "{:#?}", response.response());
|
||||
}
|
||||
|
||||
pub fn assert_version_ids(versions: &[LegacyVersion], expected_ids: Vec<String>) {
|
||||
pub fn assert_version_ids(versions: &[Version], expected_ids: Vec<String>) {
|
||||
let version_ids = versions
|
||||
.iter()
|
||||
.map(|v| get_json_val_str(v.id))
|
||||
|
||||
@@ -7,7 +7,7 @@ use labrinth::models::{
|
||||
oauth_clients::OAuthClient,
|
||||
organizations::Organization,
|
||||
pats::Scopes,
|
||||
v2::projects::{LegacyProject, LegacyVersion},
|
||||
v3::projects::{Project, Version},
|
||||
};
|
||||
use serde_json::json;
|
||||
use sqlx::Executor;
|
||||
@@ -16,7 +16,7 @@ use zip::{write::FileOptions, CompressionMethod, ZipWriter};
|
||||
use crate::common::database::USER_USER_PAT;
|
||||
use labrinth::util::actix::{AppendsMultipart, MultipartSegment, MultipartSegmentData};
|
||||
|
||||
use super::{environment::TestEnvironment, request_data::get_public_project_creation_data};
|
||||
use super::{api_v3::request_data::get_public_project_creation_data, environment::TestEnvironment};
|
||||
|
||||
use super::{asserts::assert_status, database::USER_USER_ID, get_json_val_str};
|
||||
|
||||
@@ -170,10 +170,10 @@ pub struct DummyData {
|
||||
|
||||
impl DummyData {
|
||||
pub fn new(
|
||||
project_alpha: LegacyProject,
|
||||
project_alpha_version: LegacyVersion,
|
||||
project_beta: LegacyProject,
|
||||
project_beta_version: LegacyVersion,
|
||||
project_alpha: Project,
|
||||
project_alpha_version: Version,
|
||||
project_beta: Project,
|
||||
project_beta_version: Version,
|
||||
organization_zeta: Organization,
|
||||
oauth_client_alpha: OAuthClient,
|
||||
) -> Self {
|
||||
@@ -303,9 +303,9 @@ pub async fn get_dummy_data(test_env: &TestEnvironment) -> DummyData {
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn add_project_alpha(test_env: &TestEnvironment) -> (LegacyProject, LegacyVersion) {
|
||||
pub async fn add_project_alpha(test_env: &TestEnvironment) -> (Project, Version) {
|
||||
let (project, versions) = test_env
|
||||
.v2
|
||||
.v3
|
||||
.add_public_project(
|
||||
get_public_project_creation_data("alpha", Some(TestFile::DummyProjectAlpha)),
|
||||
USER_USER_PAT,
|
||||
@@ -314,25 +314,25 @@ pub async fn add_project_alpha(test_env: &TestEnvironment) -> (LegacyProject, Le
|
||||
(project, versions.into_iter().next().unwrap())
|
||||
}
|
||||
|
||||
pub async fn add_project_beta(test_env: &TestEnvironment) -> (LegacyProject, LegacyVersion) {
|
||||
pub async fn add_project_beta(test_env: &TestEnvironment) -> (Project, Version) {
|
||||
// Adds dummy data to the database with sqlx (projects, versions, threads)
|
||||
// Generate test project data.
|
||||
let jar = TestFile::DummyProjectBeta;
|
||||
// TODO: this shouldnt be hardcoded (nor should other similar ones be)
|
||||
let json_data = json!(
|
||||
{
|
||||
"title": "Test Project Beta",
|
||||
"slug": "beta",
|
||||
"description": "A dummy project for testing with.",
|
||||
"body": "This project is not-yet-approved, and versions are draft.",
|
||||
"client_side": "required",
|
||||
"server_side": "optional",
|
||||
"initial_versions": [{
|
||||
"file_parts": [jar.filename()],
|
||||
"version_number": "1.2.3",
|
||||
"version_title": "start",
|
||||
"status": "unlisted",
|
||||
"requested_status": "unlisted",
|
||||
"dependencies": [],
|
||||
"client_side": "required",
|
||||
"server_side": "optional",
|
||||
"game_versions": ["1.20.1"] ,
|
||||
"release_channel": "release",
|
||||
"loaders": ["fabric"],
|
||||
@@ -363,12 +363,11 @@ pub async fn add_project_beta(test_env: &TestEnvironment) -> (LegacyProject, Leg
|
||||
|
||||
// Add a project.
|
||||
let req = TestRequest::post()
|
||||
.uri("/v2/project")
|
||||
.uri("/v3/project")
|
||||
.append_header(("Authorization", USER_USER_PAT))
|
||||
.set_multipart(vec![json_segment.clone(), file_segment.clone()])
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
|
||||
assert_eq!(resp.status(), 200);
|
||||
|
||||
get_project_beta(test_env).await
|
||||
@@ -377,7 +376,7 @@ pub async fn add_project_beta(test_env: &TestEnvironment) -> (LegacyProject, Leg
|
||||
pub async fn add_organization_zeta(test_env: &TestEnvironment) -> Organization {
|
||||
// Add an organzation.
|
||||
let req = TestRequest::post()
|
||||
.uri("/v2/organization")
|
||||
.uri("/v3/organization")
|
||||
.append_header(("Authorization", USER_USER_PAT))
|
||||
.set_json(json!({
|
||||
"title": "zeta",
|
||||
@@ -391,46 +390,46 @@ pub async fn add_organization_zeta(test_env: &TestEnvironment) -> Organization {
|
||||
get_organization_zeta(test_env).await
|
||||
}
|
||||
|
||||
pub async fn get_project_alpha(test_env: &TestEnvironment) -> (LegacyProject, LegacyVersion) {
|
||||
pub async fn get_project_alpha(test_env: &TestEnvironment) -> (Project, Version) {
|
||||
// Get project
|
||||
let req = TestRequest::get()
|
||||
.uri("/v2/project/alpha")
|
||||
.uri("/v3/project/alpha")
|
||||
.append_header(("Authorization", USER_USER_PAT))
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
let project: LegacyProject = test::read_body_json(resp).await;
|
||||
let project: Project = test::read_body_json(resp).await;
|
||||
|
||||
// Get project's versions
|
||||
let req = TestRequest::get()
|
||||
.uri("/v2/project/alpha/version")
|
||||
.uri("/v3/project/alpha/version")
|
||||
.append_header(("Authorization", USER_USER_PAT))
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
let versions: Vec<LegacyVersion> = test::read_body_json(resp).await;
|
||||
let versions: Vec<Version> = test::read_body_json(resp).await;
|
||||
let version = versions.into_iter().next().unwrap();
|
||||
|
||||
(project, version)
|
||||
}
|
||||
|
||||
pub async fn get_project_beta(test_env: &TestEnvironment) -> (LegacyProject, LegacyVersion) {
|
||||
pub async fn get_project_beta(test_env: &TestEnvironment) -> (Project, Version) {
|
||||
// Get project
|
||||
let req = TestRequest::get()
|
||||
.uri("/v2/project/beta")
|
||||
.uri("/v3/project/beta")
|
||||
.append_header(("Authorization", USER_USER_PAT))
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
assert_status(&resp, StatusCode::OK);
|
||||
let project: serde_json::Value = test::read_body_json(resp).await;
|
||||
let project: LegacyProject = serde_json::from_value(project).unwrap();
|
||||
let project: Project = serde_json::from_value(project).unwrap();
|
||||
|
||||
// Get project's versions
|
||||
let req = TestRequest::get()
|
||||
.uri("/v2/project/beta/version")
|
||||
.uri("/v3/project/beta/version")
|
||||
.append_header(("Authorization", USER_USER_PAT))
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
assert_status(&resp, StatusCode::OK);
|
||||
let versions: Vec<LegacyVersion> = test::read_body_json(resp).await;
|
||||
let versions: Vec<Version> = test::read_body_json(resp).await;
|
||||
let version = versions.into_iter().next().unwrap();
|
||||
|
||||
(project, version)
|
||||
@@ -439,7 +438,7 @@ pub async fn get_project_beta(test_env: &TestEnvironment) -> (LegacyProject, Leg
|
||||
pub async fn get_organization_zeta(test_env: &TestEnvironment) -> Organization {
|
||||
// Get organization
|
||||
let req = TestRequest::get()
|
||||
.uri("/v2/organization/zeta")
|
||||
.uri("/v3/organization/zeta")
|
||||
.append_header(("Authorization", USER_USER_PAT))
|
||||
.to_request();
|
||||
let resp = test_env.call(req).await;
|
||||
|
||||
@@ -25,6 +25,9 @@ where
|
||||
|
||||
db.cleanup().await;
|
||||
}
|
||||
// TODO: This needs to be slightly redesigned in order to do both V2 and v3 tests.
|
||||
// TODO: Most tests, since they use API functions, can be applied to both. The ones that weren't are in v2/, but
|
||||
// all tests that can be applied to both should use both v2 and v3 (extract api to a trait with all the API functions and call both).
|
||||
|
||||
// A complete test environment, with a test actix app and a database.
|
||||
// Must be called in an #[actix_rt::test] context. It also simulates a
|
||||
@@ -77,7 +80,7 @@ impl TestEnvironment {
|
||||
|
||||
pub async fn generate_friend_user_notification(&self) {
|
||||
let resp = self
|
||||
.v2
|
||||
.v3
|
||||
.add_user_to_team(
|
||||
&self.dummy.as_ref().unwrap().project_alpha.team_id,
|
||||
FRIEND_USER_ID,
|
||||
@@ -95,7 +98,7 @@ impl TestEnvironment {
|
||||
pat: &str,
|
||||
status_code: StatusCode,
|
||||
) {
|
||||
let resp = self.v2.get_user_notifications(user_id, pat).await;
|
||||
let resp = self.v3.get_user_notifications(user_id, pat).await;
|
||||
assert_status(&resp, status_code);
|
||||
}
|
||||
|
||||
@@ -105,7 +108,7 @@ impl TestEnvironment {
|
||||
pat: &str,
|
||||
status_code: StatusCode,
|
||||
) {
|
||||
let resp = self.v2.get_user_projects(user_id, pat).await;
|
||||
let resp = self.v3.get_user_projects(user_id, pat).await;
|
||||
assert_status(&resp, status_code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ pub mod dummy_data;
|
||||
pub mod environment;
|
||||
pub mod pats;
|
||||
pub mod permissions;
|
||||
pub mod request_data;
|
||||
pub mod scopes;
|
||||
|
||||
// Testing equivalent to 'setup' function, producing a LabrinthConfig
|
||||
|
||||
@@ -4,13 +4,11 @@ use itertools::Itertools;
|
||||
use labrinth::models::teams::{OrganizationPermissions, ProjectPermissions};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::common::{
|
||||
database::{generate_random_name, ADMIN_USER_PAT},
|
||||
request_data,
|
||||
};
|
||||
use crate::common::database::{generate_random_name, ADMIN_USER_PAT};
|
||||
|
||||
use super::{
|
||||
database::{USER_USER_ID, USER_USER_PAT},
|
||||
api_v3::request_data,
|
||||
database::{ENEMY_USER_PAT, USER_USER_ID, USER_USER_PAT},
|
||||
environment::TestEnvironment,
|
||||
};
|
||||
|
||||
@@ -164,7 +162,48 @@ impl<'a> PermissionsTest<'a> {
|
||||
)
|
||||
.await;
|
||||
|
||||
// Failure test
|
||||
// Failure test- not logged in
|
||||
let request = req_gen(&PermissionsTestContext {
|
||||
project_id: Some(&project_id),
|
||||
team_id: Some(&team_id),
|
||||
..test_context
|
||||
})
|
||||
.to_request();
|
||||
|
||||
let resp = test_env.call(request).await;
|
||||
if !self.allowed_failure_codes.contains(&resp.status().as_u16()) {
|
||||
return Err(format!(
|
||||
"Failure permissions test failed. Expected failure codes {} got {}",
|
||||
self.allowed_failure_codes
|
||||
.iter()
|
||||
.map(|code| code.to_string())
|
||||
.join(","),
|
||||
resp.status().as_u16()
|
||||
));
|
||||
}
|
||||
|
||||
// Failure test- logged in on a non-team user
|
||||
let request = req_gen(&PermissionsTestContext {
|
||||
project_id: Some(&project_id),
|
||||
team_id: Some(&team_id),
|
||||
..test_context
|
||||
})
|
||||
.append_header(("Authorization", ENEMY_USER_PAT))
|
||||
.to_request();
|
||||
|
||||
let resp = test_env.call(request).await;
|
||||
if !self.allowed_failure_codes.contains(&resp.status().as_u16()) {
|
||||
return Err(format!(
|
||||
"Failure permissions test failed. Expected failure codes {} got {}",
|
||||
self.allowed_failure_codes
|
||||
.iter()
|
||||
.map(|code| code.to_string())
|
||||
.join(","),
|
||||
resp.status().as_u16()
|
||||
));
|
||||
}
|
||||
|
||||
// Failure test- logged in with EVERY non-relevant permission
|
||||
let request = req_gen(&PermissionsTestContext {
|
||||
project_id: Some(&project_id),
|
||||
team_id: Some(&team_id),
|
||||
@@ -175,7 +214,6 @@ impl<'a> PermissionsTest<'a> {
|
||||
|
||||
let resp = test_env.call(request).await;
|
||||
if !self.allowed_failure_codes.contains(&resp.status().as_u16()) {
|
||||
println!("Body: {:?}", resp.response().body());
|
||||
return Err(format!(
|
||||
"Failure permissions test failed. Expected failure codes {} got {}",
|
||||
self.allowed_failure_codes
|
||||
@@ -207,7 +245,6 @@ impl<'a> PermissionsTest<'a> {
|
||||
|
||||
let resp = test_env.call(request).await;
|
||||
if !resp.status().is_success() {
|
||||
println!("Body: {:?}", resp.response().body());
|
||||
return Err(format!(
|
||||
"Success permissions test failed. Expected success, got {}",
|
||||
resp.status().as_u16()
|
||||
@@ -342,8 +379,9 @@ impl<'a> PermissionsTest<'a> {
|
||||
organization_team_id: None,
|
||||
};
|
||||
|
||||
// TEST 1: Failure
|
||||
// Random user, unaffiliated with the project, with no permissions
|
||||
// TEST 1: User not logged in - no PAT.
|
||||
// This should always fail, regardless of permissions
|
||||
// (As we are testing permissions-based failures)
|
||||
let test_1 = async {
|
||||
let (project_id, team_id) = create_dummy_project(test_env).await;
|
||||
|
||||
@@ -379,18 +417,9 @@ impl<'a> PermissionsTest<'a> {
|
||||
};
|
||||
|
||||
// TEST 2: Failure
|
||||
// User affiliated with the project, with failure permissions
|
||||
// Random user, unaffiliated with the project, with no permissions
|
||||
let test_2 = async {
|
||||
let (project_id, team_id) = create_dummy_project(test_env).await;
|
||||
add_user_to_team(
|
||||
self.user_id,
|
||||
self.user_pat,
|
||||
&team_id,
|
||||
Some(failure_project_permissions),
|
||||
None,
|
||||
test_env,
|
||||
)
|
||||
.await;
|
||||
|
||||
let request = req_gen(&PermissionsTestContext {
|
||||
project_id: Some(&project_id),
|
||||
@@ -399,7 +428,6 @@ impl<'a> PermissionsTest<'a> {
|
||||
})
|
||||
.append_header(("Authorization", self.user_pat))
|
||||
.to_request();
|
||||
|
||||
let resp = test_env.call(request).await;
|
||||
if !self.allowed_failure_codes.contains(&resp.status().as_u16()) {
|
||||
return Err(format!(
|
||||
@@ -412,11 +440,57 @@ impl<'a> PermissionsTest<'a> {
|
||||
));
|
||||
}
|
||||
|
||||
let p =
|
||||
get_project_permissions(self.user_id, self.user_pat, &project_id, test_env).await;
|
||||
if p != ProjectPermissions::empty() {
|
||||
return Err(format!(
|
||||
"Test 2 failed. Expected no permissions, got {:?}",
|
||||
p
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
};
|
||||
|
||||
// TEST 3: Failure
|
||||
// User affiliated with the project, with failure permissions
|
||||
let test_3 = async {
|
||||
let (project_id, team_id) = create_dummy_project(test_env).await;
|
||||
add_user_to_team(
|
||||
self.user_id,
|
||||
self.user_pat,
|
||||
&team_id,
|
||||
Some(failure_project_permissions),
|
||||
None,
|
||||
test_env,
|
||||
)
|
||||
.await;
|
||||
|
||||
let request = req_gen(&PermissionsTestContext {
|
||||
project_id: Some(&project_id),
|
||||
team_id: Some(&team_id),
|
||||
..test_context
|
||||
})
|
||||
.append_header(("Authorization", self.user_pat))
|
||||
.to_request();
|
||||
|
||||
let resp = test_env.call(request).await;
|
||||
if !self.allowed_failure_codes.contains(&resp.status().as_u16()) {
|
||||
return Err(format!(
|
||||
"Test 3 failed. Expected failure codes {} got {}",
|
||||
self.allowed_failure_codes
|
||||
.iter()
|
||||
.map(|code| code.to_string())
|
||||
.join(","),
|
||||
resp.status().as_u16()
|
||||
));
|
||||
}
|
||||
|
||||
let p =
|
||||
get_project_permissions(self.user_id, self.user_pat, &project_id, test_env).await;
|
||||
if p != failure_project_permissions {
|
||||
return Err(format!(
|
||||
"Test 2 failed. Expected {:?}, got {:?}",
|
||||
"Test 3 failed. Expected {:?}, got {:?}",
|
||||
failure_project_permissions, p
|
||||
));
|
||||
}
|
||||
@@ -424,9 +498,9 @@ impl<'a> PermissionsTest<'a> {
|
||||
Ok(())
|
||||
};
|
||||
|
||||
// TEST 3: Success
|
||||
// TEST 4: Success
|
||||
// User affiliated with the project, with the given permissions
|
||||
let test_3 = async {
|
||||
let test_4 = async {
|
||||
let (project_id, team_id) = create_dummy_project(test_env).await;
|
||||
add_user_to_team(
|
||||
self.user_id,
|
||||
@@ -449,7 +523,7 @@ impl<'a> PermissionsTest<'a> {
|
||||
let resp = test_env.call(request).await;
|
||||
if !resp.status().is_success() {
|
||||
return Err(format!(
|
||||
"Test 3 failed. Expected success, got {}",
|
||||
"Test 4 failed. Expected success, got {}",
|
||||
resp.status().as_u16()
|
||||
));
|
||||
}
|
||||
@@ -458,7 +532,7 @@ impl<'a> PermissionsTest<'a> {
|
||||
get_project_permissions(self.user_id, self.user_pat, &project_id, test_env).await;
|
||||
if p != success_permissions {
|
||||
return Err(format!(
|
||||
"Test 3 failed. Expected {:?}, got {:?}",
|
||||
"Test 4 failed. Expected {:?}, got {:?}",
|
||||
success_permissions, p
|
||||
));
|
||||
}
|
||||
@@ -466,10 +540,10 @@ impl<'a> PermissionsTest<'a> {
|
||||
Ok(())
|
||||
};
|
||||
|
||||
// TEST 4: Failure
|
||||
// TEST 5: Failure
|
||||
// Project has an organization
|
||||
// User affiliated with the project's org, with default failure permissions
|
||||
let test_4 = async {
|
||||
let test_5 = async {
|
||||
let (project_id, team_id) = create_dummy_project(test_env).await;
|
||||
let (organization_id, organization_team_id) = create_dummy_org(test_env).await;
|
||||
add_project_to_org(test_env, &project_id, &organization_id).await;
|
||||
@@ -494,7 +568,7 @@ impl<'a> PermissionsTest<'a> {
|
||||
let resp = test_env.call(request).await;
|
||||
if !self.allowed_failure_codes.contains(&resp.status().as_u16()) {
|
||||
return Err(format!(
|
||||
"Test 4 failed. Expected failure codes {} got {}",
|
||||
"Test 5 failed. Expected failure codes {} got {}",
|
||||
self.allowed_failure_codes
|
||||
.iter()
|
||||
.map(|code| code.to_string())
|
||||
@@ -507,7 +581,7 @@ impl<'a> PermissionsTest<'a> {
|
||||
get_project_permissions(self.user_id, self.user_pat, &project_id, test_env).await;
|
||||
if p != failure_project_permissions {
|
||||
return Err(format!(
|
||||
"Test 4 failed. Expected {:?}, got {:?}",
|
||||
"Test 5 failed. Expected {:?}, got {:?}",
|
||||
failure_project_permissions, p
|
||||
));
|
||||
}
|
||||
@@ -515,55 +589,9 @@ impl<'a> PermissionsTest<'a> {
|
||||
Ok(())
|
||||
};
|
||||
|
||||
// TEST 5: Success
|
||||
// TEST 6: Success
|
||||
// Project has an organization
|
||||
// User affiliated with the project's org, with the default success
|
||||
let test_5 = async {
|
||||
let (project_id, team_id) = create_dummy_project(test_env).await;
|
||||
let (organization_id, organization_team_id) = create_dummy_org(test_env).await;
|
||||
add_project_to_org(test_env, &project_id, &organization_id).await;
|
||||
add_user_to_team(
|
||||
self.user_id,
|
||||
self.user_pat,
|
||||
&organization_team_id,
|
||||
Some(success_permissions),
|
||||
None,
|
||||
test_env,
|
||||
)
|
||||
.await;
|
||||
|
||||
let request = req_gen(&PermissionsTestContext {
|
||||
project_id: Some(&project_id),
|
||||
team_id: Some(&team_id),
|
||||
..test_context
|
||||
})
|
||||
.append_header(("Authorization", self.user_pat))
|
||||
.to_request();
|
||||
|
||||
let resp = test_env.call(request).await;
|
||||
if !resp.status().is_success() {
|
||||
return Err(format!(
|
||||
"Test 5 failed. Expected success, got {}",
|
||||
resp.status().as_u16()
|
||||
));
|
||||
}
|
||||
|
||||
let p =
|
||||
get_project_permissions(self.user_id, self.user_pat, &project_id, test_env).await;
|
||||
if p != success_permissions {
|
||||
return Err(format!(
|
||||
"Test 5 failed. Expected {:?}, got {:?}",
|
||||
success_permissions, p
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
};
|
||||
|
||||
// TEST 6: Failure
|
||||
// Project has an organization
|
||||
// User affiliated with the project's org (even can have successful permissions!)
|
||||
// User overwritten on the project team with failure permissions
|
||||
let test_6 = async {
|
||||
let (project_id, team_id) = create_dummy_project(test_env).await;
|
||||
let (organization_id, organization_team_id) = create_dummy_org(test_env).await;
|
||||
@@ -577,6 +605,52 @@ impl<'a> PermissionsTest<'a> {
|
||||
test_env,
|
||||
)
|
||||
.await;
|
||||
|
||||
let request = req_gen(&PermissionsTestContext {
|
||||
project_id: Some(&project_id),
|
||||
team_id: Some(&team_id),
|
||||
..test_context
|
||||
})
|
||||
.append_header(("Authorization", self.user_pat))
|
||||
.to_request();
|
||||
|
||||
let resp = test_env.call(request).await;
|
||||
if !resp.status().is_success() {
|
||||
return Err(format!(
|
||||
"Test 6 failed. Expected success, got {}",
|
||||
resp.status().as_u16()
|
||||
));
|
||||
}
|
||||
|
||||
let p =
|
||||
get_project_permissions(self.user_id, self.user_pat, &project_id, test_env).await;
|
||||
if p != success_permissions {
|
||||
return Err(format!(
|
||||
"Test 6 failed. Expected {:?}, got {:?}",
|
||||
success_permissions, p
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
};
|
||||
|
||||
// TEST 7: Failure
|
||||
// Project has an organization
|
||||
// User affiliated with the project's org (even can have successful permissions!)
|
||||
// User overwritten on the project team with failure permissions
|
||||
let test_7 = async {
|
||||
let (project_id, team_id) = create_dummy_project(test_env).await;
|
||||
let (organization_id, organization_team_id) = create_dummy_org(test_env).await;
|
||||
add_project_to_org(test_env, &project_id, &organization_id).await;
|
||||
add_user_to_team(
|
||||
self.user_id,
|
||||
self.user_pat,
|
||||
&organization_team_id,
|
||||
Some(success_permissions),
|
||||
None,
|
||||
test_env,
|
||||
)
|
||||
.await;
|
||||
add_user_to_team(
|
||||
self.user_id,
|
||||
self.user_pat,
|
||||
@@ -598,7 +672,7 @@ impl<'a> PermissionsTest<'a> {
|
||||
let resp = test_env.call(request).await;
|
||||
if !self.allowed_failure_codes.contains(&resp.status().as_u16()) {
|
||||
return Err(format!(
|
||||
"Test 6 failed. Expected failure codes {} got {}",
|
||||
"Test 7 failed. Expected failure codes {} got {}",
|
||||
self.allowed_failure_codes
|
||||
.iter()
|
||||
.map(|code| code.to_string())
|
||||
@@ -611,7 +685,7 @@ impl<'a> PermissionsTest<'a> {
|
||||
get_project_permissions(self.user_id, self.user_pat, &project_id, test_env).await;
|
||||
if p != failure_project_permissions {
|
||||
return Err(format!(
|
||||
"Test 6 failed. Expected {:?}, got {:?}",
|
||||
"Test 7 failed. Expected {:?}, got {:?}",
|
||||
failure_project_permissions, p
|
||||
));
|
||||
}
|
||||
@@ -619,11 +693,11 @@ impl<'a> PermissionsTest<'a> {
|
||||
Ok(())
|
||||
};
|
||||
|
||||
// TEST 7: Success
|
||||
// TEST 8: Success
|
||||
// Project has an organization
|
||||
// User affiliated with the project's org with default failure permissions
|
||||
// User overwritten to the project with the success permissions
|
||||
let test_7 = async {
|
||||
let test_8 = async {
|
||||
let (project_id, team_id) = create_dummy_project(test_env).await;
|
||||
let (organization_id, organization_team_id) = create_dummy_org(test_env).await;
|
||||
add_project_to_org(test_env, &project_id, &organization_id).await;
|
||||
@@ -658,7 +732,7 @@ impl<'a> PermissionsTest<'a> {
|
||||
|
||||
if !resp.status().is_success() {
|
||||
return Err(format!(
|
||||
"Test 7 failed. Expected success, got {}",
|
||||
"Test 8 failed. Expected success, got {}",
|
||||
resp.status().as_u16()
|
||||
));
|
||||
}
|
||||
@@ -667,7 +741,7 @@ impl<'a> PermissionsTest<'a> {
|
||||
get_project_permissions(self.user_id, self.user_pat, &project_id, test_env).await;
|
||||
if p != success_permissions {
|
||||
return Err(format!(
|
||||
"Test 7 failed. Expected {:?}, got {:?}",
|
||||
"Test 8 failed. Expected {:?}, got {:?}",
|
||||
success_permissions, p
|
||||
));
|
||||
}
|
||||
@@ -675,7 +749,8 @@ impl<'a> PermissionsTest<'a> {
|
||||
Ok(())
|
||||
};
|
||||
|
||||
tokio::try_join!(test_1, test_2, test_3, test_4, test_5, test_6, test_7,).map_err(|e| e)?;
|
||||
tokio::try_join!(test_1, test_2, test_3, test_4, test_5, test_6, test_7, test_8)
|
||||
.map_err(|e| e)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -845,7 +920,7 @@ impl<'a> PermissionsTest<'a> {
|
||||
}
|
||||
|
||||
async fn create_dummy_project(test_env: &TestEnvironment) -> (String, String) {
|
||||
let api = &test_env.v2;
|
||||
let api = &test_env.v3;
|
||||
|
||||
// Create a very simple project
|
||||
let slug = generate_random_name("test_project");
|
||||
@@ -861,7 +936,7 @@ async fn create_dummy_project(test_env: &TestEnvironment) -> (String, String) {
|
||||
async fn create_dummy_org(test_env: &TestEnvironment) -> (String, String) {
|
||||
// Create a very simple organization
|
||||
let name = generate_random_name("test_org");
|
||||
let api = &test_env.v2;
|
||||
let api = &test_env.v3;
|
||||
|
||||
let resp = api
|
||||
.create_organization(&name, "Example description.", ADMIN_USER_PAT)
|
||||
@@ -878,7 +953,7 @@ async fn create_dummy_org(test_env: &TestEnvironment) -> (String, String) {
|
||||
}
|
||||
|
||||
async fn add_project_to_org(test_env: &TestEnvironment, project_id: &str, organization_id: &str) {
|
||||
let api = &test_env.v2;
|
||||
let api = &test_env.v3;
|
||||
let resp = api
|
||||
.organization_add_project(organization_id, project_id, ADMIN_USER_PAT)
|
||||
.await;
|
||||
@@ -893,7 +968,7 @@ async fn add_user_to_team(
|
||||
organization_permissions: Option<OrganizationPermissions>,
|
||||
test_env: &TestEnvironment,
|
||||
) {
|
||||
let api = &test_env.v2;
|
||||
let api = &test_env.v3;
|
||||
|
||||
// Invite user
|
||||
let resp = api
|
||||
@@ -919,7 +994,7 @@ async fn modify_user_team_permissions(
|
||||
organization_permissions: Option<OrganizationPermissions>,
|
||||
test_env: &TestEnvironment,
|
||||
) {
|
||||
let api = &test_env.v2;
|
||||
let api = &test_env.v3;
|
||||
|
||||
// Send invitation to user
|
||||
let resp = api
|
||||
@@ -938,7 +1013,7 @@ async fn modify_user_team_permissions(
|
||||
|
||||
async fn remove_user_from_team(user_id: &str, team_id: &str, test_env: &TestEnvironment) {
|
||||
// Send invitation to user
|
||||
let api = &test_env.v2;
|
||||
let api = &test_env.v3;
|
||||
let resp = api.remove_from_team(team_id, user_id, ADMIN_USER_PAT).await;
|
||||
assert!(resp.status().is_success());
|
||||
}
|
||||
@@ -949,7 +1024,7 @@ async fn get_project_permissions(
|
||||
project_id: &str,
|
||||
test_env: &TestEnvironment,
|
||||
) -> ProjectPermissions {
|
||||
let resp = test_env.v2.get_project_members(project_id, user_pat).await;
|
||||
let resp = test_env.v3.get_project_members(project_id, user_pat).await;
|
||||
let permissions = if resp.status().as_u16() == 200 {
|
||||
let value: serde_json::Value = test::read_body_json(resp).await;
|
||||
value
|
||||
@@ -972,7 +1047,7 @@ async fn get_organization_permissions(
|
||||
organization_id: &str,
|
||||
test_env: &TestEnvironment,
|
||||
) -> OrganizationPermissions {
|
||||
let api = &test_env.v2;
|
||||
let api = &test_env.v3;
|
||||
let resp = api
|
||||
.get_organization_members(organization_id, user_pat)
|
||||
.await;
|
||||
|
||||
Reference in New Issue
Block a user