helper.rs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. use backend::{
  2. application::{get_connection_pool, Application},
  3. config::{get_configuration, DatabaseSettings},
  4. };
  5. use flowy_user::{errors::UserError, prelude::*};
  6. use flowy_workspace::prelude::{server::*, *};
  7. use sqlx::{Connection, Executor, PgConnection, PgPool};
  8. use uuid::Uuid;
  9. pub struct TestApp {
  10. pub address: String,
  11. pub port: u16,
  12. pub pg_pool: PgPool,
  13. }
  14. impl TestApp {
  15. pub async fn register_user(&self, params: SignUpParams) -> SignUpResponse {
  16. let url = format!("{}/api/register", self.address);
  17. let resp = user_sign_up_request(params, &url).await.unwrap();
  18. resp
  19. }
  20. pub async fn sign_in(&self, params: SignInParams) -> Result<SignInResponse, UserError> {
  21. let url = format!("{}/api/auth", self.address);
  22. user_sign_in_request(params, &url).await
  23. }
  24. pub async fn sign_out(&self, token: &str) {
  25. let url = format!("{}/api/auth", self.address);
  26. let _ = user_sign_out_request(token, &url).await.unwrap();
  27. }
  28. pub async fn get_user_profile(&self, token: &str) -> UserProfile {
  29. let url = format!("{}/api/user", self.address);
  30. let user_profile = get_user_profile_request(token, &url).await.unwrap();
  31. user_profile
  32. }
  33. pub async fn update_user_profile(
  34. &self,
  35. token: &str,
  36. params: UpdateUserParams,
  37. ) -> Result<(), UserError> {
  38. let url = format!("{}/api/user", self.address);
  39. update_user_profile_request(token, params, &url).await
  40. }
  41. pub async fn create_workspace(&self, params: CreateWorkspaceParams, token: &str) -> Workspace {
  42. let url = format!("{}/api/workspace", self.address);
  43. let workspace = create_workspace_request(token, params, &url).await.unwrap();
  44. workspace
  45. }
  46. pub async fn read_workspaces(
  47. &self,
  48. params: QueryWorkspaceParams,
  49. token: &str,
  50. ) -> RepeatedWorkspace {
  51. let url = format!("{}/api/workspace", self.address);
  52. let workspaces = read_workspaces_request(token, params, &url).await.unwrap();
  53. workspaces
  54. }
  55. pub async fn update_workspace(&self, params: UpdateWorkspaceParams, token: &str) {
  56. let url = format!("{}/api/workspace", self.address);
  57. update_workspace_request(token, params, &url).await.unwrap();
  58. }
  59. pub async fn delete_workspace(&self, params: DeleteWorkspaceParams, token: &str) {
  60. let url = format!("{}/api/workspace", self.address);
  61. delete_workspace_request(token, params, &url).await.unwrap();
  62. }
  63. pub async fn create_app(&self, params: CreateAppParams, token: &str) -> App {
  64. let url = format!("{}/api/app", self.address);
  65. let app = create_app_request(token, params, &url).await.unwrap();
  66. app
  67. }
  68. pub async fn read_app(&self, params: QueryAppParams, token: &str) -> Option<App> {
  69. let url = format!("{}/api/app", self.address);
  70. let app = read_app_request(token, params, &url).await.unwrap();
  71. app
  72. }
  73. pub async fn update_app(&self, params: UpdateAppParams, token: &str) {
  74. let url = format!("{}/api/app", self.address);
  75. update_app_request(token, params, &url).await.unwrap();
  76. }
  77. pub async fn delete_app(&self, params: DeleteAppParams, token: &str) {
  78. let url = format!("{}/api/app", self.address);
  79. delete_app_request(token, params, &url).await.unwrap();
  80. }
  81. pub async fn create_view(&self, params: CreateViewParams, token: &str) -> View {
  82. let url = format!("{}/api/view", self.address);
  83. let view = create_view_request(token, params, &url).await.unwrap();
  84. view
  85. }
  86. pub async fn read_view(&self, params: QueryViewParams, token: &str) -> Option<View> {
  87. let url = format!("{}/api/view", self.address);
  88. let view = read_view_request(token, params, &url).await.unwrap();
  89. view
  90. }
  91. pub async fn update_view(&self, params: UpdateViewParams, token: &str) {
  92. let url = format!("{}/api/view", self.address);
  93. update_view_request(token, params, &url).await.unwrap();
  94. }
  95. pub async fn delete_view(&self, params: DeleteViewParams, token: &str) {
  96. let url = format!("{}/api/view", self.address);
  97. delete_view_request(token, params, &url).await.unwrap();
  98. }
  99. pub(crate) async fn register_test_user(&self) -> SignUpResponse {
  100. let params = SignUpParams {
  101. email: "[email protected]".to_string(),
  102. name: "annie".to_string(),
  103. password: "HelloAppFlowy123!".to_string(),
  104. };
  105. let response = self.register_user(params).await;
  106. response
  107. }
  108. }
  109. pub async fn spawn_app() -> TestApp {
  110. let database_name = format!("{}", Uuid::new_v4().to_string());
  111. let configuration = {
  112. let mut c = get_configuration().expect("Failed to read configuration.");
  113. c.database.database_name = database_name.clone();
  114. // Use a random OS port
  115. c.application.port = 0;
  116. c
  117. };
  118. let _ = configure_database(&configuration.database).await;
  119. let application = Application::build(configuration.clone())
  120. .await
  121. .expect("Failed to build application.");
  122. let application_port = application.port();
  123. let _ = tokio::spawn(async {
  124. let _ = application.run_until_stopped();
  125. // drop_test_database(database_name).await;
  126. });
  127. TestApp {
  128. address: format!("http://localhost:{}", application_port),
  129. port: application_port,
  130. pg_pool: get_connection_pool(&configuration.database)
  131. .await
  132. .expect("Failed to connect to the database"),
  133. }
  134. }
  135. async fn configure_database(config: &DatabaseSettings) -> PgPool {
  136. // Create database
  137. let mut connection = PgConnection::connect_with(&config.without_db())
  138. .await
  139. .expect("Failed to connect to Postgres");
  140. connection
  141. .execute(&*format!(r#"CREATE DATABASE "{}";"#, config.database_name))
  142. .await
  143. .expect("Failed to create database.");
  144. // Migrate database
  145. let connection_pool = PgPool::connect_with(config.with_db())
  146. .await
  147. .expect("Failed to connect to Postgres.");
  148. sqlx::migrate!("./migrations")
  149. .run(&connection_pool)
  150. .await
  151. .expect("Failed to migrate the database");
  152. connection_pool
  153. }
  154. #[allow(dead_code)]
  155. async fn drop_test_database(database_name: String) {
  156. // https://stackoverflow.com/questions/36502401/postgres-drop-database-error-pq-cannot-drop-the-currently-open-database?rq=1
  157. let configuration = {
  158. let mut c = get_configuration().expect("Failed to read configuration.");
  159. c.database.database_name = "flowy".to_owned();
  160. c.application.port = 0;
  161. c
  162. };
  163. let mut connection = PgConnection::connect_with(&configuration.database.without_db())
  164. .await
  165. .expect("Failed to connect to Postgres");
  166. connection
  167. .execute(&*format!(r#"Drop DATABASE "{}";"#, database_name))
  168. .await
  169. .expect("Failed to drop database.");
  170. }