| 
									
										
										
										
											2024-04-12 10:21:41 +02:00
										 |  |  | use std::fs::{create_dir_all, File, OpenOptions};
 | 
					
						
							| 
									
										
										
										
											2023-08-28 13:28:24 +08:00
										 |  |  | use std::io::copy;
 | 
					
						
							| 
									
										
										
										
											2023-07-05 20:57:09 +08:00
										 |  |  | use std::ops::Deref;
 | 
					
						
							| 
									
										
										
										
											2023-08-28 13:28:24 +08:00
										 |  |  | use std::path::{Path, PathBuf};
 | 
					
						
							| 
									
										
										
										
											2023-07-05 20:57:09 +08:00
										 |  |  | use std::time::Duration;
 | 
					
						
							| 
									
										
										
										
											2024-04-12 10:21:41 +02:00
										 |  |  | use std::{fs, io};
 | 
					
						
							| 
									
										
										
										
											2023-07-05 20:57:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-29 13:02:27 +08:00
										 |  |  | use nanoid::nanoid;
 | 
					
						
							| 
									
										
										
										
											2023-07-05 20:57:09 +08:00
										 |  |  | use tokio::sync::mpsc::Receiver;
 | 
					
						
							|  |  |  | use tokio::time::timeout;
 | 
					
						
							| 
									
										
										
										
											2023-10-02 17:22:22 +08:00
										 |  |  | use uuid::Uuid;
 | 
					
						
							| 
									
										
										
										
											2024-04-12 10:21:41 +02:00
										 |  |  | use walkdir::WalkDir;
 | 
					
						
							|  |  |  | use zip::write::FileOptions;
 | 
					
						
							|  |  |  | use zip::{CompressionMethod, ZipArchive, ZipWriter};
 | 
					
						
							| 
									
										
										
										
											2023-07-05 20:57:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-26 18:00:56 +08:00
										 |  |  | use event_integration_test::event_builder::EventBuilder;
 | 
					
						
							|  |  |  | use event_integration_test::Cleaner;
 | 
					
						
							|  |  |  | use event_integration_test::EventIntegrationTest;
 | 
					
						
							| 
									
										
										
										
											2024-08-18 05:16:42 +02:00
										 |  |  | use flowy_user::entities::UpdateUserProfilePayloadPB;
 | 
					
						
							| 
									
										
										
										
											2023-07-05 20:57:09 +08:00
										 |  |  | use flowy_user::errors::FlowyError;
 | 
					
						
							|  |  |  | use flowy_user::event_map::UserEvent::*;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | pub struct FlowySupabaseTest {
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:42:39 +08:00
										 |  |  |   event_test: EventIntegrationTest,
 | 
					
						
							| 
									
										
										
										
											2023-07-05 20:57:09 +08:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | impl FlowySupabaseTest {
 | 
					
						
							| 
									
										
										
										
											2023-10-30 12:35:06 +08:00
										 |  |  |   pub async fn new() -> Option<Self> {
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:42:39 +08:00
										 |  |  |     let event_test = EventIntegrationTest::new().await;
 | 
					
						
							|  |  |  |     Some(Self { event_test })
 | 
					
						
							| 
									
										
										
										
											2023-07-05 20:57:09 +08:00
										 |  |  |   }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-29 09:46:24 +08:00
										 |  |  |   pub async fn update_user_profile(
 | 
					
						
							|  |  |  |     &self,
 | 
					
						
							|  |  |  |     payload: UpdateUserProfilePayloadPB,
 | 
					
						
							|  |  |  |   ) -> Option<FlowyError> {
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:42:39 +08:00
										 |  |  |     EventBuilder::new(self.event_test.clone())
 | 
					
						
							| 
									
										
										
										
											2023-07-05 20:57:09 +08:00
										 |  |  |       .event(UpdateUserProfile)
 | 
					
						
							|  |  |  |       .payload(payload)
 | 
					
						
							|  |  |  |       .async_send()
 | 
					
						
							| 
									
										
										
										
											2023-07-29 09:46:24 +08:00
										 |  |  |       .await
 | 
					
						
							|  |  |  |       .error()
 | 
					
						
							| 
									
										
										
										
											2023-07-05 20:57:09 +08:00
										 |  |  |   }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | impl Deref for FlowySupabaseTest {
 | 
					
						
							| 
									
										
										
										
											2023-10-24 20:11:06 +08:00
										 |  |  |   type Target = EventIntegrationTest;
 | 
					
						
							| 
									
										
										
										
											2023-07-05 20:57:09 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   fn deref(&self) -> &Self::Target {
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:42:39 +08:00
										 |  |  |     &self.event_test
 | 
					
						
							| 
									
										
										
										
											2023-07-05 20:57:09 +08:00
										 |  |  |   }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:42:39 +08:00
										 |  |  | pub async fn receive_with_timeout<T>(mut receiver: Receiver<T>, duration: Duration) -> Option<T> {
 | 
					
						
							|  |  |  |   timeout(duration, receiver.recv()).await.ok()?
 | 
					
						
							| 
									
										
										
										
											2023-07-05 20:57:09 +08:00
										 |  |  | }
 | 
					
						
							| 
									
										
										
										
											2023-08-17 23:46:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-12 10:21:41 +02:00
										 |  |  | /// zip the asset to the destination
 | 
					
						
							|  |  |  | /// Zips the specified directory into a zip file.
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | /// # Arguments
 | 
					
						
							|  |  |  | /// - `src_dir`: Path to the directory to zip.
 | 
					
						
							|  |  |  | /// - `output_file`: Path to the output zip file.
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | /// # Errors
 | 
					
						
							|  |  |  | /// Returns `io::Result<()>` indicating the operation's success or failure.
 | 
					
						
							|  |  |  | pub fn zip(src_dir: PathBuf, output_file_path: PathBuf) -> io::Result<()> {
 | 
					
						
							|  |  |  |   // Ensure the output directory exists
 | 
					
						
							|  |  |  |   if let Some(parent) = output_file_path.parent() {
 | 
					
						
							|  |  |  |     if !parent.exists() {
 | 
					
						
							|  |  |  |       fs::create_dir_all(parent)?;
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |   }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Open or create the output file, truncating it if it exists
 | 
					
						
							|  |  |  |   let file = OpenOptions::new()
 | 
					
						
							|  |  |  |     .create(true)
 | 
					
						
							|  |  |  |     .write(true)
 | 
					
						
							|  |  |  |     .truncate(true)
 | 
					
						
							|  |  |  |     .open(&output_file_path)?;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-15 15:23:23 +08:00
										 |  |  |   let options = FileOptions::<()>::default().compression_method(CompressionMethod::Deflated);
 | 
					
						
							| 
									
										
										
										
											2024-04-12 10:21:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   let mut zip = ZipWriter::new(file);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Calculate the name of the new folder within the ZIP file based on the last component of the output path
 | 
					
						
							|  |  |  |   let new_folder_name = output_file_path
 | 
					
						
							|  |  |  |     .file_stem()
 | 
					
						
							|  |  |  |     .and_then(|name| name.to_str())
 | 
					
						
							|  |  |  |     .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Invalid output file name"))?;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   let src_dir_str = src_dir.to_str().expect("Invalid source directory path");
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for entry in WalkDir::new(&src_dir).into_iter().filter_map(|e| e.ok()) {
 | 
					
						
							|  |  |  |     let path = entry.path();
 | 
					
						
							|  |  |  |     let relative_path = path
 | 
					
						
							|  |  |  |       .strip_prefix(src_dir_str)
 | 
					
						
							|  |  |  |       .map_err(|_| io::Error::new(io::ErrorKind::Other, "Error calculating relative path"))?;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Construct the path within the ZIP, prefixing with the new folder's name
 | 
					
						
							|  |  |  |     let zip_path = Path::new(new_folder_name).join(relative_path);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if path.is_file() {
 | 
					
						
							|  |  |  |       zip.start_file(
 | 
					
						
							|  |  |  |         zip_path
 | 
					
						
							|  |  |  |           .to_str()
 | 
					
						
							|  |  |  |           .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Invalid file name"))?,
 | 
					
						
							|  |  |  |         options,
 | 
					
						
							|  |  |  |       )?;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       let mut f = File::open(path)?;
 | 
					
						
							|  |  |  |       io::copy(&mut f, &mut zip)?;
 | 
					
						
							|  |  |  |     } else if entry.file_type().is_dir() && !relative_path.as_os_str().is_empty() {
 | 
					
						
							|  |  |  |       zip.add_directory(
 | 
					
						
							|  |  |  |         zip_path
 | 
					
						
							|  |  |  |           .to_str()
 | 
					
						
							|  |  |  |           .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Invalid directory name"))?,
 | 
					
						
							|  |  |  |         options,
 | 
					
						
							|  |  |  |       )?;
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |   }
 | 
					
						
							|  |  |  |   zip.finish()?;
 | 
					
						
							|  |  |  |   Ok(())
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | pub fn unzip_test_asset(folder_name: &str) -> io::Result<(Cleaner, PathBuf)> {
 | 
					
						
							|  |  |  |   unzip("./tests/asset", folder_name)
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | pub fn unzip(root: &str, folder_name: &str) -> io::Result<(Cleaner, PathBuf)> {
 | 
					
						
							| 
									
										
										
										
											2023-08-28 13:28:24 +08:00
										 |  |  |   // Open the zip file
 | 
					
						
							|  |  |  |   let zip_file_path = format!("{}/{}.zip", root, folder_name);
 | 
					
						
							|  |  |  |   let reader = File::open(zip_file_path)?;
 | 
					
						
							| 
									
										
										
										
											2023-12-29 13:02:27 +08:00
										 |  |  |   let output_folder_path = format!("{}/unit_test_{}", root, nanoid!(6));
 | 
					
						
							| 
									
										
										
										
											2023-08-28 13:28:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Create a ZipArchive from the file
 | 
					
						
							|  |  |  |   let mut archive = ZipArchive::new(reader)?;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Iterate through each file in the zip
 | 
					
						
							|  |  |  |   for i in 0..archive.len() {
 | 
					
						
							|  |  |  |     let mut file = archive.by_index(i)?;
 | 
					
						
							|  |  |  |     let output_path = Path::new(&output_folder_path).join(file.mangled_name());
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if file.name().ends_with('/') {
 | 
					
						
							|  |  |  |       // Create directory
 | 
					
						
							|  |  |  |       create_dir_all(&output_path)?;
 | 
					
						
							|  |  |  |     } else {
 | 
					
						
							|  |  |  |       // Write file
 | 
					
						
							|  |  |  |       if let Some(p) = output_path.parent() {
 | 
					
						
							|  |  |  |         if !p.exists() {
 | 
					
						
							|  |  |  |           create_dir_all(p)?;
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |       }
 | 
					
						
							|  |  |  |       let mut outfile = File::create(&output_path)?;
 | 
					
						
							|  |  |  |       copy(&mut file, &mut outfile)?;
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |   }
 | 
					
						
							|  |  |  |   let path = format!("{}/{}", output_folder_path, folder_name);
 | 
					
						
							|  |  |  |   Ok((
 | 
					
						
							|  |  |  |     Cleaner::new(PathBuf::from(output_folder_path)),
 | 
					
						
							|  |  |  |     PathBuf::from(path),
 | 
					
						
							|  |  |  |   ))
 | 
					
						
							|  |  |  | }
 | 
					
						
							| 
									
										
										
										
											2023-10-02 17:22:22 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | pub fn generate_test_email() -> String {
 | 
					
						
							|  |  |  |   format!("{}@test.com", Uuid::new_v4())
 | 
					
						
							|  |  |  | }
 |