use go_true_redux::{Client, EmailOrPhone, UserAttributes}; use rand::{distributions::Alphanumeric, Rng}; use serde_json::json; use std::error::Error; fn get_client() -> Client { Client::new("http://localhost:9998") } fn get_random_email() -> String { let random_string: String = rand::thread_rng() .sample_iter(&Alphanumeric) .take(7) .map(|c| c.to_ascii_lowercase()) .map(char::from) .collect(); format!("{random_string}@example.com") } #[tokio::test] async fn it_signs_up_with_email() -> Result<(), Box> { let email = get_random_email(); let password = "Abcd1234!"; let mut client = get_client(); let res = client .sign_up(EmailOrPhone::Email(email.clone()), password) .await?; assert_eq!(email, res.user.email); Ok(()) } #[tokio::test] async fn it_should_throw_email_already_taken_error() -> Result<(), Box> { let email = get_random_email(); let password = "Abcd1234!"; let mut client = get_client(); let _throw_away_signup_result = client .sign_up(EmailOrPhone::Email(email.clone()), password) .await?; // Sign up with email to invalidate second signup. let result = client.sign_up(EmailOrPhone::Email(email), password).await; match result { Ok(_) => panic!("Should throw error"), Err(e) => assert!(matches!(e, go_true_redux::Error::AlreadySignedUp)), } Ok(()) } #[tokio::test] async fn it_signs_in_with_email() -> Result<(), Box> { let email = get_random_email(); let password = "Abcd1234!"; let mut client = get_client(); let _throw_away_signup_result = client .sign_up(EmailOrPhone::Email(email.clone()), password) .await?; let res = client .sign_in(EmailOrPhone::Email(email.clone()), password) .await?; assert_eq!(res.user.email, email); Ok(()) } #[tokio::test] async fn it_should_return_error_when_credentials_are_wrong_on_signin() -> Result<(), Box> { let email = get_random_email(); let password = "Abcd1234!"; let mut client = get_client(); let _throw_away_signup_result = client.sign_up(EmailOrPhone::Email(email), password).await?; let wrong_email = get_random_email(); let result = client .sign_in(EmailOrPhone::Email(wrong_email), password) .await; match result { Ok(_) => panic!("Should throw error"), Err(e) => assert!(matches!(e, go_true_redux::Error::WrongCredentials)), } Ok(()) } #[tokio::test] async fn it_should_return_error_if_no_session_when_refreshing() -> Result<(), Box> { let mut client = get_client(); let result = client.refresh_session().await; match result { Ok(_) => panic!("Should throw error"), Err(e) => assert!(matches!(e, go_true_redux::Error::NotAuthenticated)), } Ok(()) } #[tokio::test] async fn it_should_refresh_session() -> Result<(), Box> { let email = get_random_email(); let password = "Abcd1234!"; let mut client = get_client(); let _throw_away_signup_result = client .sign_up(EmailOrPhone::Email(email.clone()), password) .await?; let old_session = client .sign_in(EmailOrPhone::Email(email.clone()), password) .await?; let session = client.refresh_session().await?; assert_eq!(session.user.email, email); assert_ne!(old_session.refresh_token, session.refresh_token); Ok(()) } #[tokio::test] async fn it_send_magic_link_with_valid_email() -> Result<(), Box> { let email = get_random_email(); let password = "Abcd1234!"; let mut client = get_client(); let _throw_away_signup_result = client .sign_up(EmailOrPhone::Email(email.clone()), password) .await?; let res = client.send_otp(EmailOrPhone::Email(email), None).await?; assert!(res); Ok(()) } #[tokio::test] async fn it_does_not_send_magic_link_with_invalid_email() -> Result<(), Box> { let email = "i-do-not-exist"; let client = get_client(); let result = client .send_otp(EmailOrPhone::Email(email.to_owned()), None) .await; match result { Ok(_) => panic!("Should throw error"), Err(e) => assert!(matches!(e, go_true_redux::Error::UserNotFound)), } Ok(()) } #[tokio::test] async fn it_should_log_out() -> Result<(), Box> { let email = get_random_email(); let password = "Abcd1234!"; let mut client = get_client(); let _throw_away_signup_result = client .sign_up(EmailOrPhone::Email(email.clone()), password) .await?; let _throw_away_signin_result = client.sign_in(EmailOrPhone::Email(email), password).await?; let success = client.sign_out().await?; assert!(success); Ok(()) } #[tokio::test] async fn it_should_return_error_in_log_out_if_no_session() -> Result<(), Box> { let client = get_client(); let result = client.sign_out().await; match result { Ok(_) => panic!("Should throw error"), Err(e) => assert!(matches!(e, go_true_redux::Error::NotAuthenticated)), } Ok(()) } #[tokio::test] async fn it_should_send_password_recovery_email() -> Result<(), Box> { let email = get_random_email(); let password = "Abcd1234!"; let mut client = get_client(); let _throw_away_signup_result = client .sign_up(EmailOrPhone::Email(email.clone()), password) .await?; let res = client.reset_password_for_email(&email).await?; assert!(res); Ok(()) } #[tokio::test] async fn it_should_update_user() -> Result<(), Box> { let email = get_random_email(); let password = "Abcd1234!"; let mut client = get_client(); let _throw_away_signup_result = client .sign_up(EmailOrPhone::Email(email.clone()), password) .await?; let _throw_away_signin_result = client.sign_in(EmailOrPhone::Email(email), password).await?; let new_email = get_random_email(); let attributes = UserAttributes { email: new_email.clone(), password: "Abcd12345!".to_string(), data: json!({ "test": "test" }), }; let update = client.update_user(attributes).await?; assert_eq!(update.new_email, new_email); Ok(()) } #[tokio::test] async fn it_should_set_session_by_refresh_token() -> Result<(), Box> { let email = get_random_email(); let password = "Abcd1234!"; let mut client = get_client(); let old_session = client .sign_up(EmailOrPhone::Email(email.clone()), password) .await?; let session = client.set_session(&old_session.refresh_token).await?; assert_eq!(old_session.user.email, session.user.email); Ok(()) }