//! These tests check how single migration via http server run works use super::utils::{M0, M1, M2}; use bson::Bson; use futures::stream::StreamExt; use hyper::{Body, Client, Request, StatusCode}; use mongodb::{options::FindOptions, Database}; use mongodb_migrator::{ migration::Migration, migration_record::MigrationRecord, server::{self, DbParams, MigratorParams, ServiceParams}, }; use testcontainers::Docker; #[tokio::test] pub async fn server_runs_migrations_by_id() { let migrations: Vec> = vec![Box::new(M0 {}), Box::new(M1 {}), Box::new(M2 {})]; let r = tokio::spawn(async move { let docker = testcontainers::clients::Cli::default(); let node = docker.run(testcontainers::images::mongo::Mongo::default()); let host_port = node.get_host_port(27017).unwrap(); let url = format!("mongodb://localhost:{}/", host_port); let client = mongodb::Client::with_uri_str(url).await.unwrap(); let db = client.database("test"); tokio::spawn(async move { let params = ServiceParams { migrator: MigratorParams { db: DbParams { connection_string: format!("mongodb://localhost:{}/", host_port), log_into_db_name: "test".to_string(), }, migrations, }, ..Default::default() }; server::server(params).await; }); check_ups(&db).await; db.drop(None).await.expect("test db deleted"); check_downs(&db).await; }) .await; assert!(r.is_ok()); } async fn check_ups(db: &Database) { let migrations: Vec> = vec![Box::new(M0 {}), Box::new(M1 {}), Box::new(M2 {})]; let migrations_ids = migrations .iter() .map(|m| m.get_id().to_string()) .collect::>(); let client = Client::new(); let response = client .request( Request::builder() .uri(format!("http://{}/up/M0", "localhost:3000")) .method("POST") .body(Body::empty()) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::OK); let response = client .request( Request::builder() .uri(format!("http://{}/up/M1", "localhost:3000")) .method("POST") .body(Body::empty()) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::OK); let response = client .request( Request::builder() .uri(format!("http://{}/up/M2", "localhost:3000")) .method("POST") .body(Body::empty()) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::OK); let mut f_o: FindOptions = Default::default(); f_o.sort = Some(bson::doc! {"end_date": 1}); let all_records = db .collection("migrations") .find(bson::doc! {}, f_o) .await .unwrap() .collect::>() .await .into_iter() .map(|v| bson::from_bson(Bson::Document(v.unwrap())).unwrap()) .map(|v: MigrationRecord| v._id.to_string()) .collect::>(); assert_eq!(all_records, migrations_ids); } async fn check_downs(db: &Database) { let migrations: Vec> = vec![Box::new(M0 {}), Box::new(M1 {}), Box::new(M2 {})]; let migrations_ids = migrations .iter() .map(|m| m.get_id().to_string()) .collect::>(); let client = Client::new(); let response = client .request( Request::builder() .uri(format!("http://{}/down/M2", "localhost:3000")) .method("POST") .body(Body::empty()) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::OK); let response = client .request( Request::builder() .uri(format!("http://{}/down/M1", "localhost:3000")) .method("POST") .body(Body::empty()) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::OK); let response = client .request( Request::builder() .uri(format!("http://{}/down/M0", "localhost:3000")) .method("POST") .body(Body::empty()) .unwrap(), ) .await .unwrap(); assert_eq!(response.status(), StatusCode::OK); let mut f_o: FindOptions = Default::default(); f_o.sort = Some(bson::doc! {"end_date": 1}); let all_records = db .collection("migrations") .find(bson::doc! {}, f_o) .await .unwrap() .collect::>() .await .into_iter() .map(|v| bson::from_bson(Bson::Document(v.unwrap())).unwrap()) .map(|v: MigrationRecord| v._id.to_string()) .collect::>(); assert_eq!( all_records, migrations_ids.into_iter().rev().collect::>() ); }