diff --git a/tests/e2e/asserts.rs b/tests/common/asserts.rs similarity index 95% rename from tests/e2e/asserts.rs rename to tests/common/asserts.rs index f2968904..60df0956 100644 --- a/tests/e2e/asserts.rs +++ b/tests/common/asserts.rs @@ -1,7 +1,7 @@ -use crate::e2e::responses::TextResponse; - // Text responses +use super::responses::TextResponse; + pub fn assert_response_title(response: &TextResponse, title: &str) { let title_element = format!("{title}"); diff --git a/tests/e2e/client.rs b/tests/common/client.rs similarity index 94% rename from tests/e2e/client.rs rename to tests/common/client.rs index 727299aa..cf35cdab 100644 --- a/tests/e2e/client.rs +++ b/tests/common/client.rs @@ -1,14 +1,14 @@ use reqwest::multipart; use serde::Serialize; -use super::contexts::category::{AddCategoryForm, DeleteCategoryForm}; -use super::contexts::settings::UpdateSettingsForm; -use super::contexts::torrent::requests::{TorrentId, UpdateTorrentFrom}; -use super::contexts::user::{LoginForm, RegistrationForm, TokenRenewalForm, TokenVerificationForm, Username}; -use super::responses::{self, BinaryResponse}; -use crate::e2e::connection_info::ConnectionInfo; -use crate::e2e::http::{Query, ReqwestQuery}; -use crate::e2e::responses::TextResponse; +use super::connection_info::ConnectionInfo; +use super::contexts::category::forms::{AddCategoryForm, DeleteCategoryForm}; +use super::contexts::settings::form::UpdateSettingsForm; +use super::contexts::torrent::forms::UpdateTorrentFrom; +use super::contexts::torrent::requests::TorrentId; +use super::contexts::user::forms::{LoginForm, RegistrationForm, TokenRenewalForm, TokenVerificationForm, Username}; +use super::http::{Query, ReqwestQuery}; +use super::responses::{self, BinaryResponse, TextResponse}; /// API Client pub struct Client { diff --git a/tests/e2e/connection_info.rs b/tests/common/connection_info.rs similarity index 100% rename from tests/e2e/connection_info.rs rename to tests/common/connection_info.rs diff --git a/tests/common/contexts/about/mod.rs b/tests/common/contexts/about/mod.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/tests/common/contexts/about/mod.rs @@ -0,0 +1 @@ + diff --git a/tests/common/contexts/category/fixtures.rs b/tests/common/contexts/category/fixtures.rs new file mode 100644 index 00000000..18e62288 --- /dev/null +++ b/tests/common/contexts/category/fixtures.rs @@ -0,0 +1,18 @@ +use rand::Rng; + +pub fn software_predefined_category_name() -> String { + "software".to_string() +} + +pub fn software_predefined_category_id() -> i64 { + 5 +} + +pub fn random_category_name() -> String { + format!("category name {}", random_id()) +} + +fn random_id() -> u64 { + let mut rng = rand::thread_rng(); + rng.gen_range(0..1_000_000) +} diff --git a/tests/common/contexts/category/forms.rs b/tests/common/contexts/category/forms.rs new file mode 100644 index 00000000..ea9cf429 --- /dev/null +++ b/tests/common/contexts/category/forms.rs @@ -0,0 +1,9 @@ +use serde::Serialize; + +#[derive(Serialize)] +pub struct AddCategoryForm { + pub name: String, + pub icon: Option, +} + +pub type DeleteCategoryForm = AddCategoryForm; diff --git a/tests/common/contexts/category/mod.rs b/tests/common/contexts/category/mod.rs new file mode 100644 index 00000000..6f27f51d --- /dev/null +++ b/tests/common/contexts/category/mod.rs @@ -0,0 +1,3 @@ +pub mod fixtures; +pub mod forms; +pub mod responses; diff --git a/tests/common/contexts/category/responses.rs b/tests/common/contexts/category/responses.rs new file mode 100644 index 00000000..a345d523 --- /dev/null +++ b/tests/common/contexts/category/responses.rs @@ -0,0 +1,18 @@ +use serde::Deserialize; + +#[derive(Deserialize)] +pub struct AddedCategoryResponse { + pub data: String, +} + +#[derive(Deserialize, Debug)] +pub struct ListResponse { + pub data: Vec, +} + +#[derive(Deserialize, Debug, PartialEq)] +pub struct ListItem { + pub category_id: i64, + pub name: String, + pub num_torrents: i64, +} diff --git a/tests/common/contexts/mod.rs b/tests/common/contexts/mod.rs new file mode 100644 index 00000000..a6f14141 --- /dev/null +++ b/tests/common/contexts/mod.rs @@ -0,0 +1,6 @@ +pub mod about; +pub mod category; +pub mod root; +pub mod settings; +pub mod torrent; +pub mod user; diff --git a/tests/common/contexts/root/mod.rs b/tests/common/contexts/root/mod.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/tests/common/contexts/root/mod.rs @@ -0,0 +1 @@ + diff --git a/tests/common/contexts/settings/form.rs b/tests/common/contexts/settings/form.rs new file mode 100644 index 00000000..f2f21086 --- /dev/null +++ b/tests/common/contexts/settings/form.rs @@ -0,0 +1,3 @@ +use super::Settings; + +pub type UpdateSettingsForm = Settings; diff --git a/tests/common/contexts/settings/mod.rs b/tests/common/contexts/settings/mod.rs new file mode 100644 index 00000000..a046c859 --- /dev/null +++ b/tests/common/contexts/settings/mod.rs @@ -0,0 +1,59 @@ +pub mod form; +pub mod responses; + +use serde::{Deserialize, Serialize}; + +#[derive(Deserialize, Serialize, PartialEq, Debug)] +pub struct Settings { + pub website: Website, + pub tracker: Tracker, + pub net: Net, + pub auth: Auth, + pub database: Database, + pub mail: Mail, +} + +#[derive(Deserialize, Serialize, PartialEq, Debug)] +pub struct Website { + pub name: String, +} + +#[derive(Deserialize, Serialize, PartialEq, Debug)] +pub struct Tracker { + pub url: String, + pub mode: String, + pub api_url: String, + pub token: String, + pub token_valid_seconds: u64, +} + +#[derive(Deserialize, Serialize, PartialEq, Debug)] +pub struct Net { + pub port: u64, + pub base_url: Option, +} + +#[derive(Deserialize, Serialize, PartialEq, Debug)] +pub struct Auth { + pub email_on_signup: String, + pub min_password_length: u64, + pub max_password_length: u64, + pub secret_key: String, +} + +#[derive(Deserialize, Serialize, PartialEq, Debug)] +pub struct Database { + pub connect_url: String, + pub torrent_info_update_interval: u64, +} + +#[derive(Deserialize, Serialize, PartialEq, Debug)] +pub struct Mail { + pub email_verification_enabled: bool, + pub from: String, + pub reply_to: String, + pub username: String, + pub password: String, + pub server: String, + pub port: u64, +} diff --git a/tests/common/contexts/settings/responses.rs b/tests/common/contexts/settings/responses.rs new file mode 100644 index 00000000..096ef1f4 --- /dev/null +++ b/tests/common/contexts/settings/responses.rs @@ -0,0 +1,26 @@ +use serde::Deserialize; + +use super::Settings; + +#[derive(Deserialize)] +pub struct AllSettingsResponse { + pub data: Settings, +} + +#[derive(Deserialize)] +pub struct PublicSettingsResponse { + pub data: Public, +} + +#[derive(Deserialize, PartialEq, Debug)] +pub struct Public { + pub website_name: String, + pub tracker_url: String, + pub tracker_mode: String, + pub email_on_signup: String, +} + +#[derive(Deserialize)] +pub struct SiteNameResponse { + pub data: String, +} diff --git a/tests/e2e/contexts/torrent/asserts.rs b/tests/common/contexts/torrent/asserts.rs similarity index 100% rename from tests/e2e/contexts/torrent/asserts.rs rename to tests/common/contexts/torrent/asserts.rs diff --git a/tests/e2e/contexts/torrent/file.rs b/tests/common/contexts/torrent/file.rs similarity index 100% rename from tests/e2e/contexts/torrent/file.rs rename to tests/common/contexts/torrent/file.rs diff --git a/tests/e2e/contexts/torrent/fixtures.rs b/tests/common/contexts/torrent/fixtures.rs similarity index 74% rename from tests/e2e/contexts/torrent/fixtures.rs rename to tests/common/contexts/torrent/fixtures.rs index 96d69d9a..f2a46748 100644 --- a/tests/e2e/contexts/torrent/fixtures.rs +++ b/tests/common/contexts/torrent/fixtures.rs @@ -6,11 +6,9 @@ use tempfile::{tempdir, TempDir}; use uuid::Uuid; use super::file::{create_torrent, parse_torrent, TorrentFileInfo}; -use super::requests::{BinaryFile, UploadTorrentMultipartForm}; -use super::responses::{Id, UploadedTorrentResponse}; -use crate::e2e::contexts::category::fixtures::software_predefined_category_name; -use crate::e2e::contexts::user::LoggedInUserData; -use crate::e2e::environment::TestEnv; +use super::forms::{BinaryFile, UploadTorrentMultipartForm}; +use super::responses::Id; +use crate::common::contexts::category::fixtures::software_predefined_category_name; /// Information about a torrent that is going to added to the index. #[derive(Clone)] @@ -53,26 +51,6 @@ impl TorrentListedInIndex { } } -/// Add a new random torrent to the index -pub async fn upload_random_torrent_to_index(uploader: &LoggedInUserData) -> (TestTorrent, TorrentListedInIndex) { - let random_torrent = random_torrent(); - let indexed_torrent = upload_torrent(uploader, &random_torrent.index_info).await; - (random_torrent, indexed_torrent) -} - -/// Upload a torrent to the index -pub async fn upload_torrent(uploader: &LoggedInUserData, torrent: &TorrentIndexInfo) -> TorrentListedInIndex { - let client = TestEnv::default().authenticated_client(&uploader.token); - - let form: UploadTorrentMultipartForm = torrent.clone().into(); - - let response = client.upload_torrent(form.into()).await; - - let res: UploadedTorrentResponse = serde_json::from_str(&response.body).unwrap(); - - TorrentListedInIndex::from(torrent.clone(), res.data.torrent_id) -} - #[derive(Clone)] pub struct TestTorrent { /// Parsed info from torrent file. diff --git a/tests/e2e/contexts/torrent/requests.rs b/tests/common/contexts/torrent/forms.rs similarity index 97% rename from tests/e2e/contexts/torrent/requests.rs rename to tests/common/contexts/torrent/forms.rs index fb1ec578..0c4499f1 100644 --- a/tests/e2e/contexts/torrent/requests.rs +++ b/tests/common/contexts/torrent/forms.rs @@ -1,10 +1,15 @@ use std::fs; use std::path::Path; -use reqwest::multipart::Form; use serde::{Deserialize, Serialize}; -pub type TorrentId = i64; +#[derive(Deserialize, Serialize)] +pub struct UpdateTorrentFrom { + pub title: Option, + pub description: Option, +} + +use reqwest::multipart::Form; pub struct UploadTorrentMultipartForm { pub title: String, @@ -43,9 +48,3 @@ impl From for Form { ) } } - -#[derive(Deserialize, Serialize)] -pub struct UpdateTorrentFrom { - pub title: Option, - pub description: Option, -} diff --git a/tests/common/contexts/torrent/mod.rs b/tests/common/contexts/torrent/mod.rs new file mode 100644 index 00000000..efe732e6 --- /dev/null +++ b/tests/common/contexts/torrent/mod.rs @@ -0,0 +1,6 @@ +pub mod asserts; +pub mod file; +pub mod fixtures; +pub mod forms; +pub mod requests; +pub mod responses; diff --git a/tests/common/contexts/torrent/requests.rs b/tests/common/contexts/torrent/requests.rs new file mode 100644 index 00000000..259a2dae --- /dev/null +++ b/tests/common/contexts/torrent/requests.rs @@ -0,0 +1 @@ +pub type TorrentId = i64; diff --git a/tests/e2e/contexts/torrent/responses.rs b/tests/common/contexts/torrent/responses.rs similarity index 100% rename from tests/e2e/contexts/torrent/responses.rs rename to tests/common/contexts/torrent/responses.rs diff --git a/tests/common/contexts/user/fixtures.rs b/tests/common/contexts/user/fixtures.rs new file mode 100644 index 00000000..3eda8502 --- /dev/null +++ b/tests/common/contexts/user/fixtures.rs @@ -0,0 +1,18 @@ +use rand::Rng; + +use crate::common::contexts::user::forms::RegistrationForm; + +pub fn random_user_registration() -> RegistrationForm { + let user_id = random_user_id(); + RegistrationForm { + username: format!("username_{user_id}"), + email: Some(format!("email_{user_id}@email.com")), + password: "password".to_string(), + confirm_password: "password".to_string(), + } +} + +fn random_user_id() -> u64 { + let mut rng = rand::thread_rng(); + rng.gen_range(0..1_000_000) +} diff --git a/tests/common/contexts/user/forms.rs b/tests/common/contexts/user/forms.rs new file mode 100644 index 00000000..359252a8 --- /dev/null +++ b/tests/common/contexts/user/forms.rs @@ -0,0 +1,37 @@ +use serde::Serialize; + +#[derive(Clone, Serialize)] +pub struct RegistrationForm { + pub username: String, + pub email: Option, + pub password: String, + pub confirm_password: String, +} + +pub type RegisteredUser = RegistrationForm; + +#[derive(Serialize)] +pub struct LoginForm { + pub login: String, + pub password: String, +} + +#[derive(Serialize)] +pub struct TokenVerificationForm { + pub token: String, +} + +#[derive(Serialize)] +pub struct TokenRenewalForm { + pub token: String, +} + +pub struct Username { + pub value: String, +} + +impl Username { + pub fn new(value: String) -> Self { + Self { value } + } +} diff --git a/tests/common/contexts/user/mod.rs b/tests/common/contexts/user/mod.rs new file mode 100644 index 00000000..6f27f51d --- /dev/null +++ b/tests/common/contexts/user/mod.rs @@ -0,0 +1,3 @@ +pub mod fixtures; +pub mod forms; +pub mod responses; diff --git a/tests/common/contexts/user/responses.rs b/tests/common/contexts/user/responses.rs new file mode 100644 index 00000000..428b0b96 --- /dev/null +++ b/tests/common/contexts/user/responses.rs @@ -0,0 +1,35 @@ +use serde::Deserialize; + +#[derive(Deserialize)] +pub struct SuccessfulLoginResponse { + pub data: LoggedInUserData, +} + +#[derive(Deserialize, Debug)] +pub struct LoggedInUserData { + pub token: String, + pub username: String, + pub admin: bool, +} + +#[derive(Deserialize)] +pub struct TokenVerifiedResponse { + pub data: String, +} + +#[derive(Deserialize)] +pub struct BannedUserResponse { + pub data: String, +} + +#[derive(Deserialize)] +pub struct TokenRenewalResponse { + pub data: TokenRenewalData, +} + +#[derive(Deserialize, PartialEq, Debug)] +pub struct TokenRenewalData { + pub token: String, + pub username: String, + pub admin: bool, +} diff --git a/tests/e2e/http.rs b/tests/common/http.rs similarity index 100% rename from tests/e2e/http.rs rename to tests/common/http.rs diff --git a/tests/common/mod.rs b/tests/common/mod.rs new file mode 100644 index 00000000..33956c17 --- /dev/null +++ b/tests/common/mod.rs @@ -0,0 +1,6 @@ +pub mod asserts; +pub mod client; +pub mod connection_info; +pub mod contexts; +pub mod http; +pub mod responses; diff --git a/tests/e2e/responses.rs b/tests/common/responses.rs similarity index 100% rename from tests/e2e/responses.rs rename to tests/common/responses.rs diff --git a/tests/e2e/contexts/about.rs b/tests/e2e/contexts/about/contract.rs similarity index 86% rename from tests/e2e/contexts/about.rs rename to tests/e2e/contexts/about/contract.rs index 49bf6c41..8c97831a 100644 --- a/tests/e2e/contexts/about.rs +++ b/tests/e2e/contexts/about/contract.rs @@ -1,4 +1,5 @@ -use crate::e2e::asserts::{assert_response_title, assert_text_ok}; +//! API contract for `about` context. +use crate::common::asserts::{assert_response_title, assert_text_ok}; use crate::e2e::environment::TestEnv; #[tokio::test] diff --git a/tests/e2e/contexts/about/mod.rs b/tests/e2e/contexts/about/mod.rs new file mode 100644 index 00000000..2943dbb5 --- /dev/null +++ b/tests/e2e/contexts/about/mod.rs @@ -0,0 +1 @@ +pub mod contract; diff --git a/tests/e2e/contexts/category.rs b/tests/e2e/contexts/category/contract.rs similarity index 75% rename from tests/e2e/contexts/category.rs rename to tests/e2e/contexts/category/contract.rs index ca6ed51a..75df92ef 100644 --- a/tests/e2e/contexts/category.rs +++ b/tests/e2e/contexts/category/contract.rs @@ -1,38 +1,18 @@ -use serde::{Deserialize, Serialize}; - -use crate::e2e::asserts::assert_json_ok; -use crate::e2e::contexts::category::fixtures::{add_category, random_category_name}; -use crate::e2e::contexts::user::fixtures::{logged_in_admin, logged_in_user}; +//! API contract for `category` context. +use crate::common::asserts::assert_json_ok; +use crate::common::contexts::category::fixtures::random_category_name; +use crate::common::contexts::category::forms::{AddCategoryForm, DeleteCategoryForm}; +use crate::common::contexts::category::responses::{AddedCategoryResponse, ListResponse}; +use crate::e2e::contexts::category::steps::add_category; +use crate::e2e::contexts::user::steps::{logged_in_admin, logged_in_user}; use crate::e2e::environment::TestEnv; -// Request data - -#[derive(Serialize)] -pub struct AddCategoryForm { - pub name: String, - pub icon: Option, -} - -pub type DeleteCategoryForm = AddCategoryForm; - -// Response data - -#[derive(Deserialize)] -pub struct AddedCategoryResponse { - pub data: String, -} - -#[derive(Deserialize, Debug)] -pub struct ListResponse { - pub data: Vec, -} - -#[derive(Deserialize, Debug, PartialEq)] -pub struct ListItem { - pub category_id: i64, - pub name: String, - pub num_torrents: i64, -} +/* todo: + - it should allow adding a new category to authenticated clients + - it should not allow adding a new category with an empty name + - it should allow adding a new category with an optional icon + - ... +*/ #[tokio::test] #[cfg_attr(not(feature = "e2e-tests"), ignore)] @@ -202,49 +182,3 @@ async fn it_should_not_allow_guests_to_delete_categories() { assert_eq!(response.status, 401); } - -/* todo: - - it should allow adding a new category to authenticated clients - - it should not allow adding a new category with an empty name - - it should allow adding a new category with an optional icon - - ... -*/ - -pub mod fixtures { - - use rand::Rng; - - use super::AddCategoryForm; - use crate::e2e::contexts::user::fixtures::logged_in_admin; - use crate::e2e::environment::TestEnv; - use crate::e2e::responses::TextResponse; - - pub fn software_predefined_category_name() -> String { - "software".to_string() - } - - pub fn software_predefined_category_id() -> i64 { - 5 - } - - pub async fn add_category(category_name: &str) -> TextResponse { - let logged_in_admin = logged_in_admin().await; - let client = TestEnv::default().authenticated_client(&logged_in_admin.token); - - client - .add_category(AddCategoryForm { - name: category_name.to_string(), - icon: None, - }) - .await - } - - pub fn random_category_name() -> String { - format!("category name {}", random_id()) - } - - fn random_id() -> u64 { - let mut rng = rand::thread_rng(); - rng.gen_range(0..1_000_000) - } -} diff --git a/tests/e2e/contexts/category/mod.rs b/tests/e2e/contexts/category/mod.rs new file mode 100644 index 00000000..2001efb8 --- /dev/null +++ b/tests/e2e/contexts/category/mod.rs @@ -0,0 +1,2 @@ +pub mod contract; +pub mod steps; diff --git a/tests/e2e/contexts/category/steps.rs b/tests/e2e/contexts/category/steps.rs new file mode 100644 index 00000000..58794a96 --- /dev/null +++ b/tests/e2e/contexts/category/steps.rs @@ -0,0 +1,16 @@ +use crate::common::contexts::category::forms::AddCategoryForm; +use crate::common::responses::TextResponse; +use crate::e2e::contexts::user::steps::logged_in_admin; +use crate::e2e::environment::TestEnv; + +pub async fn add_category(category_name: &str) -> TextResponse { + let logged_in_admin = logged_in_admin().await; + let client = TestEnv::default().authenticated_client(&logged_in_admin.token); + + client + .add_category(AddCategoryForm { + name: category_name.to_string(), + icon: None, + }) + .await +} diff --git a/tests/e2e/contexts/root.rs b/tests/e2e/contexts/root/contract.rs similarity index 76% rename from tests/e2e/contexts/root.rs rename to tests/e2e/contexts/root/contract.rs index d7ea0e03..c82d8a8d 100644 --- a/tests/e2e/contexts/root.rs +++ b/tests/e2e/contexts/root/contract.rs @@ -1,4 +1,5 @@ -use crate::e2e::asserts::{assert_response_title, assert_text_ok}; +//! API contract for `root` context. +use crate::common::asserts::{assert_response_title, assert_text_ok}; use crate::e2e::environment::TestEnv; #[tokio::test] diff --git a/tests/e2e/contexts/root/mod.rs b/tests/e2e/contexts/root/mod.rs new file mode 100644 index 00000000..2943dbb5 --- /dev/null +++ b/tests/e2e/contexts/root/mod.rs @@ -0,0 +1 @@ +pub mod contract; diff --git a/tests/e2e/contexts/settings.rs b/tests/e2e/contexts/settings/contract.rs similarity index 78% rename from tests/e2e/contexts/settings.rs rename to tests/e2e/contexts/settings/contract.rs index 08eb0a10..11dd88ad 100644 --- a/tests/e2e/contexts/settings.rs +++ b/tests/e2e/contexts/settings/contract.rs @@ -1,92 +1,9 @@ -use serde::{Deserialize, Serialize}; - -use crate::e2e::contexts::user::fixtures::logged_in_admin; +use crate::common::contexts::settings::form::UpdateSettingsForm; +use crate::common::contexts::settings::responses::{AllSettingsResponse, Public, PublicSettingsResponse, SiteNameResponse}; +use crate::common::contexts::settings::{Auth, Database, Mail, Net, Settings, Tracker, Website}; +use crate::e2e::contexts::user::steps::logged_in_admin; use crate::e2e::environment::TestEnv; -// Request data - -pub type UpdateSettingsForm = Settings; - -// Response data - -#[derive(Deserialize)] -pub struct AllSettingsResponse { - pub data: Settings, -} - -#[derive(Deserialize, Serialize, PartialEq, Debug)] -pub struct Settings { - pub website: Website, - pub tracker: Tracker, - pub net: Net, - pub auth: Auth, - pub database: Database, - pub mail: Mail, -} - -#[derive(Deserialize, Serialize, PartialEq, Debug)] -pub struct Website { - pub name: String, -} - -#[derive(Deserialize, Serialize, PartialEq, Debug)] -pub struct Tracker { - pub url: String, - pub mode: String, - pub api_url: String, - pub token: String, - pub token_valid_seconds: u64, -} - -#[derive(Deserialize, Serialize, PartialEq, Debug)] -pub struct Net { - pub port: u64, - pub base_url: Option, -} - -#[derive(Deserialize, Serialize, PartialEq, Debug)] -pub struct Auth { - pub email_on_signup: String, - pub min_password_length: u64, - pub max_password_length: u64, - pub secret_key: String, -} - -#[derive(Deserialize, Serialize, PartialEq, Debug)] -pub struct Database { - pub connect_url: String, - pub torrent_info_update_interval: u64, -} - -#[derive(Deserialize, Serialize, PartialEq, Debug)] -pub struct Mail { - pub email_verification_enabled: bool, - pub from: String, - pub reply_to: String, - pub username: String, - pub password: String, - pub server: String, - pub port: u64, -} - -#[derive(Deserialize)] -pub struct PublicSettingsResponse { - pub data: Public, -} - -#[derive(Deserialize, PartialEq, Debug)] -pub struct Public { - pub website_name: String, - pub tracker_url: String, - pub tracker_mode: String, - pub email_on_signup: String, -} - -#[derive(Deserialize)] -pub struct SiteNameResponse { - pub data: String, -} - #[tokio::test] #[cfg_attr(not(feature = "e2e-tests"), ignore)] async fn it_should_allow_guests_to_get_the_public_settings() { diff --git a/tests/e2e/contexts/settings/mod.rs b/tests/e2e/contexts/settings/mod.rs new file mode 100644 index 00000000..2943dbb5 --- /dev/null +++ b/tests/e2e/contexts/settings/mod.rs @@ -0,0 +1 @@ +pub mod contract; diff --git a/tests/e2e/contexts/torrent/contract.rs b/tests/e2e/contexts/torrent/contract.rs index e7521de8..591396b1 100644 --- a/tests/e2e/contexts/torrent/contract.rs +++ b/tests/e2e/contexts/torrent/contract.rs @@ -24,11 +24,13 @@ Get torrent info: mod for_guests { use torrust_index_backend::utils::parse_torrent::decode_torrent; - use crate::e2e::contexts::category::fixtures::software_predefined_category_id; - use crate::e2e::contexts::torrent::asserts::assert_expected_torrent_details; - use crate::e2e::contexts::torrent::fixtures::upload_random_torrent_to_index; - use crate::e2e::contexts::torrent::responses::{Category, File, TorrentDetails, TorrentDetailsResponse, TorrentListResponse}; - use crate::e2e::contexts::user::fixtures::logged_in_user; + use crate::common::contexts::category::fixtures::software_predefined_category_id; + use crate::common::contexts::torrent::asserts::assert_expected_torrent_details; + use crate::common::contexts::torrent::responses::{ + Category, File, TorrentDetails, TorrentDetailsResponse, TorrentListResponse, + }; + use crate::e2e::contexts::torrent::steps::upload_random_torrent_to_index; + use crate::e2e::contexts::user::steps::logged_in_user; use crate::e2e::environment::TestEnv; #[tokio::test] @@ -140,10 +142,10 @@ mod for_guests { mod for_authenticated_users { - use crate::e2e::contexts::torrent::fixtures::random_torrent; - use crate::e2e::contexts::torrent::requests::UploadTorrentMultipartForm; - use crate::e2e::contexts::torrent::responses::UploadedTorrentResponse; - use crate::e2e::contexts::user::fixtures::logged_in_user; + use crate::common::contexts::torrent::fixtures::random_torrent; + use crate::common::contexts::torrent::forms::UploadTorrentMultipartForm; + use crate::common::contexts::torrent::responses::UploadedTorrentResponse; + use crate::e2e::contexts::user::steps::logged_in_user; use crate::e2e::environment::TestEnv; #[tokio::test] @@ -231,8 +233,8 @@ mod for_authenticated_users { } mod and_non_admins { - use crate::e2e::contexts::torrent::fixtures::upload_random_torrent_to_index; - use crate::e2e::contexts::user::fixtures::logged_in_user; + use crate::e2e::contexts::torrent::steps::upload_random_torrent_to_index; + use crate::e2e::contexts::user::steps::logged_in_user; use crate::e2e::environment::TestEnv; #[tokio::test] @@ -250,10 +252,10 @@ mod for_authenticated_users { } mod and_torrent_owners { - use crate::e2e::contexts::torrent::fixtures::upload_random_torrent_to_index; - use crate::e2e::contexts::torrent::requests::UpdateTorrentFrom; - use crate::e2e::contexts::torrent::responses::UpdatedTorrentResponse; - use crate::e2e::contexts::user::fixtures::logged_in_user; + use crate::common::contexts::torrent::forms::UpdateTorrentFrom; + use crate::common::contexts::torrent::responses::UpdatedTorrentResponse; + use crate::e2e::contexts::torrent::steps::upload_random_torrent_to_index; + use crate::e2e::contexts::user::steps::logged_in_user; use crate::e2e::environment::TestEnv; #[tokio::test] @@ -288,10 +290,10 @@ mod for_authenticated_users { } mod and_admins { - use crate::e2e::contexts::torrent::fixtures::upload_random_torrent_to_index; - use crate::e2e::contexts::torrent::requests::UpdateTorrentFrom; - use crate::e2e::contexts::torrent::responses::{DeletedTorrentResponse, UpdatedTorrentResponse}; - use crate::e2e::contexts::user::fixtures::{logged_in_admin, logged_in_user}; + use crate::common::contexts::torrent::forms::UpdateTorrentFrom; + use crate::common::contexts::torrent::responses::{DeletedTorrentResponse, UpdatedTorrentResponse}; + use crate::e2e::contexts::torrent::steps::upload_random_torrent_to_index; + use crate::e2e::contexts::user::steps::{logged_in_admin, logged_in_user}; use crate::e2e::environment::TestEnv; #[tokio::test] diff --git a/tests/e2e/contexts/torrent/mod.rs b/tests/e2e/contexts/torrent/mod.rs index 4f3882e6..2001efb8 100644 --- a/tests/e2e/contexts/torrent/mod.rs +++ b/tests/e2e/contexts/torrent/mod.rs @@ -1,6 +1,2 @@ -pub mod asserts; pub mod contract; -pub mod file; -pub mod fixtures; -pub mod requests; -pub mod responses; +pub mod steps; diff --git a/tests/e2e/contexts/torrent/steps.rs b/tests/e2e/contexts/torrent/steps.rs new file mode 100644 index 00000000..1d34e493 --- /dev/null +++ b/tests/e2e/contexts/torrent/steps.rs @@ -0,0 +1,25 @@ +use crate::common::contexts::torrent::fixtures::{random_torrent, TestTorrent, TorrentIndexInfo, TorrentListedInIndex}; +use crate::common::contexts::torrent::forms::UploadTorrentMultipartForm; +use crate::common::contexts::torrent::responses::UploadedTorrentResponse; +use crate::common::contexts::user::responses::LoggedInUserData; +use crate::e2e::environment::TestEnv; + +/// Add a new random torrent to the index +pub async fn upload_random_torrent_to_index(uploader: &LoggedInUserData) -> (TestTorrent, TorrentListedInIndex) { + let random_torrent = random_torrent(); + let indexed_torrent = upload_torrent(uploader, &random_torrent.index_info).await; + (random_torrent, indexed_torrent) +} + +/// Upload a torrent to the index +pub async fn upload_torrent(uploader: &LoggedInUserData, torrent: &TorrentIndexInfo) -> TorrentListedInIndex { + let client = TestEnv::default().authenticated_client(&uploader.token); + + let form: UploadTorrentMultipartForm = torrent.clone().into(); + + let response = client.upload_torrent(form.into()).await; + + let res: UploadedTorrentResponse = serde_json::from_str(&response.body).unwrap(); + + TorrentListedInIndex::from(torrent.clone(), res.data.torrent_id) +} diff --git a/tests/e2e/contexts/user.rs b/tests/e2e/contexts/user/contract.rs similarity index 60% rename from tests/e2e/contexts/user.rs rename to tests/e2e/contexts/user/contract.rs index 1d0c456f..dd3c333e 100644 --- a/tests/e2e/contexts/user.rs +++ b/tests/e2e/contexts/user/contract.rs @@ -1,12 +1,16 @@ -use serde::{Deserialize, Serialize}; - -use crate::e2e::contexts::user::fixtures::{logged_in_user, random_user_registration, registered_user}; +//! API contract for `user` context. +use crate::common::contexts::user::fixtures::random_user_registration; +use crate::common::contexts::user::forms::{LoginForm, TokenRenewalForm, TokenVerificationForm}; +use crate::common::contexts::user::responses::{ + SuccessfulLoginResponse, TokenRenewalData, TokenRenewalResponse, TokenVerifiedResponse, +}; +use crate::e2e::contexts::user::steps::{logged_in_user, registered_user}; use crate::e2e::environment::TestEnv; /* This test suite is not complete. It's just a starting point to show how to -write E2E tests. ANyway, the goal is not to fully cover all the app features +write E2E tests. Anyway, the goal is not to fully cover all the app features with E2E tests. The goal is to cover the most important features and to demonstrate how to write E2E tests. Some important pending tests could be: @@ -29,80 +33,8 @@ the mailcatcher API. */ -// Request data - -#[derive(Clone, Serialize)] -pub struct RegistrationForm { - pub username: String, - pub email: Option, - pub password: String, - pub confirm_password: String, -} - -type RegisteredUser = RegistrationForm; - -#[derive(Serialize)] -pub struct LoginForm { - pub login: String, - pub password: String, -} - -#[derive(Serialize)] -pub struct TokenVerificationForm { - pub token: String, -} - -#[derive(Serialize)] -pub struct TokenRenewalForm { - pub token: String, -} - -pub struct Username { - pub value: String, -} - -impl Username { - pub fn new(value: String) -> Self { - Self { value } - } -} - // Responses data -#[derive(Deserialize)] -pub struct SuccessfulLoginResponse { - pub data: LoggedInUserData, -} - -#[derive(Deserialize, Debug)] -pub struct LoggedInUserData { - pub token: String, - pub username: String, - pub admin: bool, -} - -#[derive(Deserialize)] -pub struct TokenVerifiedResponse { - pub data: String, -} - -#[derive(Deserialize)] -pub struct BannedUserResponse { - pub data: String, -} - -#[derive(Deserialize)] -pub struct TokenRenewalResponse { - pub data: TokenRenewalData, -} - -#[derive(Deserialize, PartialEq, Debug)] -pub struct TokenRenewalData { - pub token: String, - pub username: String, - pub admin: bool, -} - #[tokio::test] #[cfg_attr(not(feature = "e2e-tests"), ignore)] async fn it_should_allow_a_guess_user_to_register() { @@ -194,8 +126,9 @@ async fn it_should_not_allow_a_logged_in_user_to_renew_an_authentication_token_w } mod banned_user_list { - use crate::e2e::contexts::user::fixtures::{logged_in_admin, logged_in_user, registered_user}; - use crate::e2e::contexts::user::{BannedUserResponse, Username}; + use crate::common::contexts::user::forms::Username; + use crate::common::contexts::user::responses::BannedUserResponse; + use crate::e2e::contexts::user::steps::{logged_in_admin, logged_in_user, registered_user}; use crate::e2e::environment::TestEnv; #[tokio::test] @@ -242,71 +175,3 @@ mod banned_user_list { assert_eq!(response.status, 401); } } - -pub mod fixtures { - use std::sync::Arc; - - use rand::Rng; - use torrust_index_backend::databases::database::connect_database; - - use super::{LoggedInUserData, LoginForm, RegisteredUser, RegistrationForm, SuccessfulLoginResponse}; - use crate::e2e::environment::TestEnv; - - pub async fn logged_in_admin() -> LoggedInUserData { - let user = logged_in_user().await; - - // todo: get from E2E config file `config-idx-back.toml.local` - let connect_url = "sqlite://storage/database/torrust_index_backend_e2e_testing.db?mode=rwc"; - - let database = Arc::new(connect_database(connect_url).await.expect("Database error.")); - - let user_profile = database.get_user_profile_from_username(&user.username).await.unwrap(); - - database.grant_admin_role(user_profile.user_id).await.unwrap(); - - user - } - - pub async fn logged_in_user() -> LoggedInUserData { - let client = TestEnv::default().unauthenticated_client(); - - let registered_user = registered_user().await; - - let response = client - .login_user(LoginForm { - login: registered_user.username.clone(), - password: registered_user.password.clone(), - }) - .await; - - let res: SuccessfulLoginResponse = serde_json::from_str(&response.body).unwrap(); - res.data - } - - pub async fn registered_user() -> RegisteredUser { - let client = TestEnv::default().unauthenticated_client(); - - let form = random_user_registration(); - - let registered_user = form.clone(); - - let _response = client.register_user(form).await; - - registered_user - } - - pub fn random_user_registration() -> RegistrationForm { - let user_id = random_user_id(); - RegistrationForm { - username: format!("username_{user_id}"), - email: Some(format!("email_{user_id}@email.com")), - password: "password".to_string(), - confirm_password: "password".to_string(), - } - } - - fn random_user_id() -> u64 { - let mut rng = rand::thread_rng(); - rng.gen_range(0..1_000_000) - } -} diff --git a/tests/e2e/contexts/user/mod.rs b/tests/e2e/contexts/user/mod.rs new file mode 100644 index 00000000..2001efb8 --- /dev/null +++ b/tests/e2e/contexts/user/mod.rs @@ -0,0 +1,2 @@ +pub mod contract; +pub mod steps; diff --git a/tests/e2e/contexts/user/steps.rs b/tests/e2e/contexts/user/steps.rs new file mode 100644 index 00000000..a94a6e49 --- /dev/null +++ b/tests/e2e/contexts/user/steps.rs @@ -0,0 +1,51 @@ +use std::sync::Arc; + +use torrust_index_backend::databases::database::connect_database; + +use crate::common::contexts::user::fixtures::random_user_registration; +use crate::common::contexts::user::forms::{LoginForm, RegisteredUser}; +use crate::common::contexts::user::responses::{LoggedInUserData, SuccessfulLoginResponse}; +use crate::e2e::environment::TestEnv; + +pub async fn logged_in_admin() -> LoggedInUserData { + let user = logged_in_user().await; + + // todo: get from E2E config file `config-idx-back.toml.local` + let connect_url = "sqlite://storage/database/torrust_index_backend_e2e_testing.db?mode=rwc"; + + let database = Arc::new(connect_database(connect_url).await.expect("Database error.")); + + let user_profile = database.get_user_profile_from_username(&user.username).await.unwrap(); + + database.grant_admin_role(user_profile.user_id).await.unwrap(); + + user +} + +pub async fn logged_in_user() -> LoggedInUserData { + let client = TestEnv::default().unauthenticated_client(); + + let registered_user = registered_user().await; + + let response = client + .login_user(LoginForm { + login: registered_user.username.clone(), + password: registered_user.password.clone(), + }) + .await; + + let res: SuccessfulLoginResponse = serde_json::from_str(&response.body).unwrap(); + res.data +} + +pub async fn registered_user() -> RegisteredUser { + let client = TestEnv::default().unauthenticated_client(); + + let form = random_user_registration(); + + let registered_user = form.clone(); + + let _response = client.register_user(form).await; + + registered_user +} diff --git a/tests/e2e/environment.rs b/tests/e2e/environment.rs index f69e2024..186c5d2d 100644 --- a/tests/e2e/environment.rs +++ b/tests/e2e/environment.rs @@ -1,5 +1,5 @@ -use super::connection_info::{anonymous_connection, authenticated_connection}; -use crate::e2e::client::Client; +use crate::common::client::Client; +use crate::common::connection_info::{anonymous_connection, authenticated_connection}; pub struct TestEnv { pub authority: String, diff --git a/tests/e2e/mod.rs b/tests/e2e/mod.rs index ce9ef1d1..d80b0505 100644 --- a/tests/e2e/mod.rs +++ b/tests/e2e/mod.rs @@ -29,10 +29,5 @@ //! clean database, delete the files before running the tests. //! //! See the [docker documentation](https://github.com/torrust/torrust-index-backend/tree/develop/docker) for more information on how to run the API. -mod asserts; -mod client; -mod connection_info; mod contexts; -mod environment; -mod http; -mod responses; +pub mod environment; diff --git a/tests/integration/contexts/about.rs b/tests/integration/contexts/about.rs new file mode 100644 index 00000000..a22b8538 --- /dev/null +++ b/tests/integration/contexts/about.rs @@ -0,0 +1,5 @@ +#[tokio::test] +#[ignore] +async fn it_should_load_the_about_page_with_information_about_the_api() { + // todo: launch isolated API server for this test +} diff --git a/tests/integration/contexts/mod.rs b/tests/integration/contexts/mod.rs new file mode 100644 index 00000000..0fc29088 --- /dev/null +++ b/tests/integration/contexts/mod.rs @@ -0,0 +1 @@ +mod about; diff --git a/tests/integration/mod.rs b/tests/integration/mod.rs new file mode 100644 index 00000000..22207461 --- /dev/null +++ b/tests/integration/mod.rs @@ -0,0 +1 @@ +mod contexts; diff --git a/tests/mod.rs b/tests/mod.rs index f90fa4f2..d99c2c97 100644 --- a/tests/mod.rs +++ b/tests/mod.rs @@ -1,3 +1,5 @@ +mod common; mod databases; mod e2e; -pub mod upgrades; +mod integration; +mod upgrades;