diff --git a/crates/api_models/src/webhooks.rs b/crates/api_models/src/webhooks.rs index 15df7da9ee..a17fc86c31 100644 --- a/crates/api_models/src/webhooks.rs +++ b/crates/api_models/src/webhooks.rs @@ -15,7 +15,6 @@ pub enum IncomingWebhookEvent { EventNotSupported, SourceChargeable, SourceTransactionCreated, - ChargeSucceeded, RefundFailure, RefundSuccess, DisputeOpened, @@ -60,7 +59,6 @@ impl From for WebhookFlow { IncomingWebhookEvent::EndpointVerification => Self::ReturnResponse, IncomingWebhookEvent::SourceChargeable | IncomingWebhookEvent::SourceTransactionCreated => Self::BankTransfer, - IncomingWebhookEvent::ChargeSucceeded => Self::Payment, } } } diff --git a/crates/router/src/connector/nuvei/transformers.rs b/crates/router/src/connector/nuvei/transformers.rs index 73ce1eac4a..6fda774679 100644 --- a/crates/router/src/connector/nuvei/transformers.rs +++ b/crates/router/src/connector/nuvei/transformers.rs @@ -75,6 +75,15 @@ pub struct NuveiPaymentsRequest { pub checksum: String, pub billing_address: Option, pub related_transaction_id: Option, + pub url_details: Option, +} + +#[derive(Debug, Serialize, Default)] +#[serde(rename_all = "camelCase")] +pub struct UrlDetails { + pub success_url: String, + pub failure_url: String, + pub pending_url: String, } #[derive(Debug, Serialize, Default)] @@ -676,12 +685,18 @@ impl capture_method: item.request.capture_method, ..Default::default() })?; + let return_url = item.request.get_return_url()?; Ok(Self { is_rebilling: request_data.is_rebilling, user_token_id: request_data.user_token_id, related_transaction_id: request_data.related_transaction_id, payment_option: request_data.payment_option, billing_address: request_data.billing_address, + url_details: Some(UrlDetails { + success_url: return_url.clone(), + failure_url: return_url.clone(), + pending_url: return_url, + }), ..request }) } @@ -1017,6 +1032,7 @@ pub enum NuveiTransactionStatus { Declined, Error, Redirect, + Pending, #[default] Processing, } @@ -1100,7 +1116,9 @@ fn get_payment_status(response: &NuveiPaymentsResponse) -> enums::AttemptStatus _ => enums::AttemptStatus::Failure, } } - NuveiTransactionStatus::Processing => enums::AttemptStatus::Pending, + NuveiTransactionStatus::Processing | NuveiTransactionStatus::Pending => { + enums::AttemptStatus::Pending + } NuveiTransactionStatus::Redirect => enums::AttemptStatus::AuthenticationPending, }, None => match response.status { @@ -1253,7 +1271,9 @@ impl From for enums::RefundStatus { match item { NuveiTransactionStatus::Approved => Self::Success, NuveiTransactionStatus::Declined | NuveiTransactionStatus::Error => Self::Failure, - NuveiTransactionStatus::Processing | NuveiTransactionStatus::Redirect => Self::Pending, + NuveiTransactionStatus::Processing + | NuveiTransactionStatus::Pending + | NuveiTransactionStatus::Redirect => Self::Pending, } } } diff --git a/crates/router/src/connector/stripe.rs b/crates/router/src/connector/stripe.rs index fa56cc155f..ff0005088d 100644 --- a/crates/router/src/connector/stripe.rs +++ b/crates/router/src/connector/stripe.rs @@ -1645,14 +1645,8 @@ impl api::IncomingWebhook for Stripe { Ok(match details.event_data.event_object.object { stripe::WebhookEventObjectType::PaymentIntent - | stripe::WebhookEventObjectType::Charge => { - api_models::webhooks::ObjectReferenceId::PaymentId( - api_models::payments::PaymentIdType::ConnectorTransactionId( - details.event_data.event_object.id, - ), - ) - } - stripe::WebhookEventObjectType::Dispute => { + | stripe::WebhookEventObjectType::Charge + | stripe::WebhookEventObjectType::Dispute => { api_models::webhooks::ObjectReferenceId::PaymentId( api_models::payments::PaymentIdType::ConnectorTransactionId( details @@ -1692,7 +1686,9 @@ impl api::IncomingWebhook for Stripe { stripe::WebhookEventType::SourceChargeable => { api::IncomingWebhookEvent::SourceChargeable } - stripe::WebhookEventType::ChargeSucceeded => api::IncomingWebhookEvent::ChargeSucceeded, + stripe::WebhookEventType::ChargeSucceeded => { + api::IncomingWebhookEvent::PaymentIntentSuccess + } stripe::WebhookEventType::DisputeCreated => api::IncomingWebhookEvent::DisputeOpened, stripe::WebhookEventType::DisputeClosed => api::IncomingWebhookEvent::DisputeCancelled, stripe::WebhookEventType::DisputeUpdated => api::IncomingWebhookEvent::try_from( diff --git a/crates/router/src/connector/stripe/transformers.rs b/crates/router/src/connector/stripe/transformers.rs index 9064d725fe..645ca09f77 100644 --- a/crates/router/src/connector/stripe/transformers.rs +++ b/crates/router/src/connector/stripe/transformers.rs @@ -1399,11 +1399,11 @@ pub struct PaymentIntentResponse { pub id: String, pub object: String, pub amount: i64, - pub amount_received: i64, - pub amount_capturable: i64, + pub amount_received: Option, + pub amount_capturable: Option, pub currency: String, pub status: StripePaymentStatus, - pub client_secret: Secret, + pub client_secret: Option>, pub created: i32, pub customer: Option, pub payment_method: Option, @@ -1519,7 +1519,7 @@ impl From for PaymentIntentResponse { id: value.id, object: value.object, status: value.status, - client_secret: value.client_secret, + client_secret: Some(value.client_secret), customer: value.customer, description: None, statement_descriptor: value.statement_descriptor, @@ -1619,7 +1619,7 @@ impl connector_metadata, network_txn_id, }), - amount_captured: Some(item.response.amount_received), + amount_captured: item.response.amount_received, ..item.data }) } @@ -1707,7 +1707,7 @@ impl Ok(Self { status: enums::AttemptStatus::from(item.response.status.to_owned()), response, - amount_captured: Some(item.response.amount_received), + amount_captured: item.response.amount_received, ..item.data }) } diff --git a/crates/router/tests/connectors/adyen_ui.rs b/crates/router/tests/connectors/adyen_uk_ui.rs similarity index 69% rename from crates/router/tests/connectors/adyen_ui.rs rename to crates/router/tests/connectors/adyen_uk_ui.rs index 4a2b840f68..2ffbd99cbc 100644 --- a/crates/router/tests/connectors/adyen_ui.rs +++ b/crates/router/tests/connectors/adyen_uk_ui.rs @@ -5,29 +5,35 @@ use crate::{selenium::*, tester}; struct AdyenSeleniumTest; -impl SeleniumTest for AdyenSeleniumTest {} +impl SeleniumTest for AdyenSeleniumTest { + fn get_connector_name(&self) -> String { + "adyen_uk".to_string() + } +} async fn should_make_adyen_gpay_payment(c: WebDriver) -> Result<(), WebDriverError> { let conn = AdyenSeleniumTest {}; + let pub_key = conn.get_configs().adyen_uk.unwrap().key1; conn.make_gpay_payment(c, - &format!("{CHEKOUT_BASE_URL}/gpay?gatewayname=adyen&gatewaymerchantid=JuspayDEECOM&amount=70.00&country=US¤cy=USD"), + &format!("{CHEKOUT_BASE_URL}/gpay?gatewayname=adyen&gatewaymerchantid={pub_key}&amount=70.00&country=US¤cy=USD"), vec![ - Event::Assert(Assert::IsPresent("succeeded")), + Event::Assert(Assert::IsPresent("processing")), ]).await?; Ok(()) } async fn should_make_adyen_gpay_mandate_payment(c: WebDriver) -> Result<(), WebDriverError> { let conn = AdyenSeleniumTest {}; + let pub_key = conn.get_configs().adyen_uk.unwrap().key1; conn.make_gpay_payment(c, - &format!("{CHEKOUT_BASE_URL}/gpay?gatewayname=adyen&gatewaymerchantid=JuspayDEECOM&amount=70.00&country=US¤cy=USD&mandate_data[customer_acceptance][acceptance_type]=offline&mandate_data[customer_acceptance][accepted_at]=1963-05-03T04:07:52.723Z&mandate_data[customer_acceptance][online][ip_address]=127.0.0.1&mandate_data[customer_acceptance][online][user_agent]=amet%20irure%20esse&mandate_data[mandate_type][multi_use][amount]=7000&mandate_data[mandate_type][multi_use][currency]=USD"), + &format!("{CHEKOUT_BASE_URL}/gpay?gatewayname=adyen&gatewaymerchantid={pub_key}&amount=70.00&country=US¤cy=USD&mandate_data[customer_acceptance][acceptance_type]=offline&mandate_data[customer_acceptance][accepted_at]=1963-05-03T04:07:52.723Z&mandate_data[customer_acceptance][online][ip_address]=127.0.0.1&mandate_data[customer_acceptance][online][user_agent]=amet%20irure%20esse&mandate_data[mandate_type][multi_use][amount]=7000&mandate_data[mandate_type][multi_use][currency]=USD"), vec![ - Event::Assert(Assert::IsPresent("succeeded")), + Event::Assert(Assert::IsPresent("processing")), Event::Assert(Assert::IsPresent("Mandate ID")), Event::Assert(Assert::IsPresent("man_")),// mandate id starting with man_ - Event::Trigger(Trigger::Click(By::Id("pm-mandate-btn"))), + Event::Trigger(Trigger::Click(By::Css("#pm-mandate-btn a"))), Event::Trigger(Trigger::Click(By::Id("pay-with-mandate-btn"))), - Event::Assert(Assert::IsPresent("succeeded")), + Event::Assert(Assert::IsPresent("processing")), ]).await?; Ok(()) } @@ -36,15 +42,16 @@ async fn should_make_adyen_gpay_zero_dollar_mandate_payment( c: WebDriver, ) -> Result<(), WebDriverError> { let conn = AdyenSeleniumTest {}; + let pub_key = conn.get_configs().adyen_uk.unwrap().key1; conn.make_gpay_payment(c, - &format!("{CHEKOUT_BASE_URL}/gpay?gatewayname=adyen&gatewaymerchantid=JuspayDEECOM&amount=0.00&country=US¤cy=USD&mandate_data[customer_acceptance][acceptance_type]=offline&mandate_data[customer_acceptance][accepted_at]=1963-05-03T04:07:52.723Z&mandate_data[customer_acceptance][online][ip_address]=127.0.0.1&mandate_data[customer_acceptance][online][user_agent]=amet%20irure%20esse&mandate_data[mandate_type][multi_use][amount]=700&mandate_data[mandate_type][multi_use][currency]=USD"), + &format!("{CHEKOUT_BASE_URL}/gpay?gatewayname=adyen&gatewaymerchantid={pub_key}&amount=0.00&country=US¤cy=USD&mandate_data[customer_acceptance][acceptance_type]=offline&mandate_data[customer_acceptance][accepted_at]=1963-05-03T04:07:52.723Z&mandate_data[customer_acceptance][online][ip_address]=127.0.0.1&mandate_data[customer_acceptance][online][user_agent]=amet%20irure%20esse&mandate_data[mandate_type][multi_use][amount]=700&mandate_data[mandate_type][multi_use][currency]=USD"), vec![ - Event::Assert(Assert::IsPresent("succeeded")), + Event::Assert(Assert::IsPresent("processing")), Event::Assert(Assert::IsPresent("Mandate ID")), Event::Assert(Assert::IsPresent("man_")),// mandate id starting with man_ - Event::Trigger(Trigger::Click(By::Id("pm-mandate-btn"))), + Event::Trigger(Trigger::Click(By::Css("#pm-mandate-btn a"))), Event::Trigger(Trigger::Click(By::Id("pay-with-mandate-btn"))), - Event::Assert(Assert::IsPresent("succeeded")), + Event::Assert(Assert::IsPresent("processing")), ]).await?; Ok(()) } @@ -67,12 +74,12 @@ async fn should_make_adyen_klarna_mandate_payment(c: WebDriver) -> Result<(), We ] ), Event::Trigger(Trigger::SwitchTab(Position::Prev)), - Event::Assert(Assert::IsPresent("succeeded")), + Event::Assert(Assert::IsPresent("processing")), Event::Assert(Assert::IsPresent("Mandate ID")), Event::Assert(Assert::IsPresent("man_")),// mandate id starting with man_ - Event::Trigger(Trigger::Click(By::Id("pm-mandate-btn"))), + Event::Trigger(Trigger::Click(By::Css("#pm-mandate-btn a"))), Event::Trigger(Trigger::Click(By::Id("pay-with-mandate-btn"))), - Event::Assert(Assert::IsPresent("succeeded")), + Event::Assert(Assert::IsPresent("processing")), ]).await?; Ok(()) } diff --git a/crates/router/tests/connectors/connector_auth.rs b/crates/router/tests/connectors/connector_auth.rs index 8c2191ae67..ef31b20c3b 100644 --- a/crates/router/tests/connectors/connector_auth.rs +++ b/crates/router/tests/connectors/connector_auth.rs @@ -1,12 +1,13 @@ use std::env; use router::types::ConnectorAuthType; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; -#[derive(Debug, Deserialize, Clone)] -pub(crate) struct ConnectorAuthentication { +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct ConnectorAuthentication { pub aci: Option, pub adyen: Option, + pub adyen_uk: Option, pub airwallex: Option, pub authorizedotnet: Option, pub bambora: Option, @@ -35,10 +36,13 @@ pub(crate) struct ConnectorAuthentication { pub rapyd: Option, pub shift4: Option, pub stripe: Option, + pub stripe_au: Option, + pub stripe_uk: Option, pub trustpay: Option, pub worldpay: Option, pub worldline: Option, pub zen: Option, + pub automation_configs: Option, } impl ConnectorAuthentication { @@ -55,8 +59,8 @@ impl ConnectorAuthentication { } } -#[derive(Debug, Deserialize, Clone)] -pub(crate) struct HeaderKey { +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct HeaderKey { pub api_key: String, } @@ -68,8 +72,8 @@ impl From for ConnectorAuthType { } } -#[derive(Debug, Deserialize, Clone)] -pub(crate) struct BodyKey { +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct BodyKey { pub api_key: String, pub key1: String, } @@ -83,8 +87,8 @@ impl From for ConnectorAuthType { } } -#[derive(Debug, Deserialize, Clone)] -pub(crate) struct SignatureKey { +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct SignatureKey { pub api_key: String, pub key1: String, pub api_secret: String, @@ -100,8 +104,8 @@ impl From for ConnectorAuthType { } } -#[derive(Debug, Deserialize, Clone)] -pub(crate) struct MultiAuthKey { +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct MultiAuthKey { pub api_key: String, pub key1: String, pub api_secret: String, @@ -118,3 +122,20 @@ impl From for ConnectorAuthType { } } } + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct AutomationConfigs { + pub hs_base_url: Option, + pub hs_api_key: Option, + pub hs_test_browser: Option, + pub chrome_profile_path: Option, + pub firefox_profile_path: Option, + pub pypl_email: Option, + pub pypl_pass: Option, + pub gmail_email: Option, + pub gmail_pass: Option, + pub configs_url: Option, + pub stripe_pub_key: Option, + pub testcases_path: Option, + pub run_minimum_steps: Option, +} diff --git a/crates/router/tests/connectors/main.rs b/crates/router/tests/connectors/main.rs index 7925b1cb09..dd6342113c 100644 --- a/crates/router/tests/connectors/main.rs +++ b/crates/router/tests/connectors/main.rs @@ -7,7 +7,7 @@ mod aci; mod adyen; -mod adyen_ui; +mod adyen_uk_ui; mod airwallex; mod authorizedotnet; mod bambora; @@ -35,6 +35,7 @@ mod opennode; mod payeezy; mod paypal; mod payu; +mod payu_ui; mod rapyd; mod selenium; mod shift4; @@ -43,5 +44,6 @@ mod stripe_ui; mod trustpay; mod utils; mod worldline; +mod worldline_ui; mod worldpay; mod zen; diff --git a/crates/router/tests/connectors/nuvei_ui.rs b/crates/router/tests/connectors/nuvei_ui.rs index 5bb1fce88e..453c3ab1f0 100644 --- a/crates/router/tests/connectors/nuvei_ui.rs +++ b/crates/router/tests/connectors/nuvei_ui.rs @@ -5,7 +5,11 @@ use crate::{selenium::*, tester}; struct NuveiSeleniumTest; -impl SeleniumTest for NuveiSeleniumTest {} +impl SeleniumTest for NuveiSeleniumTest { + fn get_connector_name(&self) -> String { + "nuvei".to_string() + } +} async fn should_make_nuvei_3ds_payment(c: WebDriver) -> Result<(), WebDriverError> { let conn = NuveiSeleniumTest {}; @@ -27,14 +31,13 @@ async fn should_make_nuvei_3ds_payment(c: WebDriver) -> Result<(), WebDriverErro async fn should_make_nuvei_3ds_mandate_payment(c: WebDriver) -> Result<(), WebDriverError> { let conn = NuveiSeleniumTest {}; conn.make_redirection_payment(c, vec![ - Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/card?cname=CL-BRW1&ccnum=4000027891380961&expmonth=10&expyear=25&cvv=123&amount=200&country=US¤cy=USD&setup_future_usage=off_session&mandate_data[customer_acceptance][acceptance_type]=offline&mandate_data[customer_acceptance][accepted_at]=1963-05-03T04:07:52.723Z&mandate_data[customer_acceptance][online][ip_address]=in%20sit&mandate_data[customer_acceptance][online][user_agent]=amet%20irure%20esse&mandate_data[mandate_type][multi_use][amount]=7000&mandate_data[mandate_type][multi_use][currency]=USD&mandate_data[mandate_type][multi_use][start_date]=2022-09-10T00:00:00Z&mandate_data[mandate_type][multi_use][end_date]=2023-09-10T00:00:00Z&mandate_data[mandate_type][multi_use][metadata][frequency]=13"))), + Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/card?cname=CL-BRW1&ccnum=4000027891380961&expmonth=10&expyear=25&cvv=123&amount=200&country=US¤cy=USD&setup_future_usage=off_session&mandate_data[customer_acceptance][acceptance_type]=offline&mandate_data[customer_acceptance][accepted_at]=1963-05-03T04:07:52.723Z&mandate_data[customer_acceptance][online][ip_address]=in%20sit&mandate_data[customer_acceptance][online][user_agent]=amet%20irure%20esse&mandate_data[mandate_type][multi_use][amount]=7000&mandate_data[mandate_type][multi_use][currency]=USD&mandate_data[mandate_type][multi_use][start_date]=2022-09-10T00:00:00Z&mandate_data[mandate_type][multi_use][end_date]=2023-09-10T00:00:00Z&mandate_data[mandate_type][multi_use][metadata][frequency]=13&return_url={CHEKOUT_BASE_URL}/payments"))), Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), Event::Trigger(Trigger::Query(By::ClassName("title"))), Event::Assert(Assert::Eq(Selector::Title, "ThreeDS ACS Emulator - Challenge Page")), Event::Trigger(Trigger::Click(By::Id("btn1"))), Event::Trigger(Trigger::Click(By::Id("btn5"))), - Event::Assert(Assert::IsPresent("Google")), - Event::Assert(Assert::Contains(Selector::QueryParamStr, "status=succeeded")), + Event::Assert(Assert::IsPresent("succeeded")), Event::Assert(Assert::IsPresent("man_")),//mandate id prefix is present ]).await?; @@ -56,9 +59,13 @@ async fn should_make_nuvei_pypl_payment(c: WebDriver) -> Result<(), WebDriverErr conn.make_paypal_payment( c, &format!("{CHEKOUT_BASE_URL}/paypal-redirect?amount=12.00&country=US¤cy=USD"), - vec![Event::Assert(Assert::IsPresent( - "Your transaction has been successfully executed.", - ))], + vec![ + Event::Assert(Assert::IsPresent("Google")), + Event::Assert(Assert::ContainsAny( + Selector::QueryParamStr, + vec!["status=succeeded"], + )), + ], ) .await?; Ok(()) @@ -82,7 +89,8 @@ async fn should_make_nuvei_giropay_payment(c: WebDriver) -> Result<(), WebDriver Event::Trigger(Trigger::Sleep(5)), Event::Trigger(Trigger::SwitchTab(Position::Next)), Event::Assert(Assert::IsPresent("Sicher bezahlt!")), - Event::Assert(Assert::IsPresent("Your transaction")) // Transaction succeeds sometimes and pending sometimes + Event::Assert(Assert::IsPresent("Google")), + Event::Assert(Assert::ContainsAny(Selector::QueryParamStr, vec!["status=succeeded", "status=processing"])) ]).await?; Ok(()) } @@ -98,7 +106,8 @@ async fn should_make_nuvei_ideal_payment(c: WebDriver) -> Result<(), WebDriverEr Event::Assert(Assert::IsPresent("IDEALFORTIS")), Event::Trigger(Trigger::Sleep(5)), Event::Trigger(Trigger::Click(By::Id("ctl00_mainContent_btnGo"))), - Event::Assert(Assert::IsPresent("Your transaction")),// Transaction succeeds sometimes and pending sometimes + Event::Assert(Assert::IsPresent("Google")), + Event::Assert(Assert::ContainsAny(Selector::QueryParamStr, vec!["status=succeeded", "status=processing"])) ]).await?; Ok(()) } @@ -111,7 +120,8 @@ async fn should_make_nuvei_sofort_payment(c: WebDriver) -> Result<(), WebDriverE Event::Assert(Assert::IsPresent("SOFORT")), Event::Trigger(Trigger::ChangeQueryParam("sender_holder", "John Doe")), Event::Trigger(Trigger::Click(By::Id("ctl00_mainContent_btnGo"))), - Event::Assert(Assert::IsPresent("Your transaction")),// Transaction succeeds sometimes and pending sometimes + Event::Assert(Assert::IsPresent("Google")), + Event::Assert(Assert::ContainsAny(Selector::QueryParamStr, vec!["status=succeeded", "status=processing"])) ]).await?; Ok(()) } @@ -127,7 +137,8 @@ async fn should_make_nuvei_eps_payment(c: WebDriver) -> Result<(), WebDriverErro Event::Assert(Assert::IsPresent("Simulator")), Event::Trigger(Trigger::SelectOption(By::Css("select[name='result']"), "Succeeded")), Event::Trigger(Trigger::Click(By::Id("submitbutton"))), - Event::Assert(Assert::IsPresent("Your transaction")),// Transaction succeeds sometimes and pending sometimes + Event::Assert(Assert::IsPresent("Google")), + Event::Assert(Assert::ContainsAny(Selector::QueryParamStr, vec!["status=succeeded", "status=processing"])) ]).await?; Ok(()) } diff --git a/crates/router/tests/connectors/payu_ui.rs b/crates/router/tests/connectors/payu_ui.rs new file mode 100644 index 0000000000..11288281e0 --- /dev/null +++ b/crates/router/tests/connectors/payu_ui.rs @@ -0,0 +1,56 @@ +use serial_test::serial; +use thirtyfour::{prelude::*, WebDriver}; + +use crate::{selenium::*, tester}; + +struct PayUSeleniumTest; + +impl SeleniumTest for PayUSeleniumTest { + fn get_connector_name(&self) -> String { + "payu".to_string() + } +} + +async fn should_make_no_3ds_card_payment(c: WebDriver) -> Result<(), WebDriverError> { + let conn = PayUSeleniumTest {}; + conn.make_redirection_payment( + c, + vec![ + Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/72"))), + Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), + Event::Trigger(Trigger::Sleep(1)), + Event::Assert(Assert::IsPresent("status")), + Event::Assert(Assert::IsPresent("processing")), + ], + ) + .await?; + Ok(()) +} + +async fn should_make_gpay_payment(c: WebDriver) -> Result<(), WebDriverError> { + let conn = PayUSeleniumTest {}; + conn.make_redirection_payment( + c, + vec![ + Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/77"))), + Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), + Event::Trigger(Trigger::Sleep(1)), + Event::Assert(Assert::IsPresent("status")), + Event::Assert(Assert::IsPresent("processing")), + ], + ) + .await?; + Ok(()) +} + +#[test] +#[serial] +fn should_make_no_3ds_card_payment_test() { + tester!(should_make_no_3ds_card_payment); +} + +#[test] +#[serial] +fn should_make_gpay_payment_test() { + tester!(should_make_gpay_payment); +} diff --git a/crates/router/tests/connectors/sample_auth.toml b/crates/router/tests/connectors/sample_auth.toml index 77c5aefc77..02d78e1b80 100644 --- a/crates/router/tests/connectors/sample_auth.toml +++ b/crates/router/tests/connectors/sample_auth.toml @@ -115,3 +115,13 @@ api_key = "API Key" api_key = "Application API KEY" api_secret = "Application Identifier" key1 = "Business Identifier" + +[automation_configs] +hs_base_url="http://localhost:8080" +hs_test_browser="firefox" +chrome_profile_path="" +firefox_profile_path="" +pypl_email="" +pypl_pass="" +gmail_email="" +gmail_pass="" diff --git a/crates/router/tests/connectors/selenium.rs b/crates/router/tests/connectors/selenium.rs index fd71cc531f..cbf80299e7 100644 --- a/crates/router/tests/connectors/selenium.rs +++ b/crates/router/tests/connectors/selenium.rs @@ -4,6 +4,9 @@ use actix_web::cookie::SameSite; use async_trait::async_trait; use thirtyfour::{components::SelectElement, prelude::*, WebDriver}; +use crate::connector_auth; + +#[derive(Clone)] pub enum Event<'a> { RunIf(Assert<'a>, Vec>), EitherOr(Assert<'a>, Vec>, Vec>), @@ -11,6 +14,7 @@ pub enum Event<'a> { Trigger(Trigger<'a>), } +#[derive(Clone)] #[allow(dead_code)] pub enum Trigger<'a> { Goto(&'a str), @@ -26,18 +30,22 @@ pub enum Trigger<'a> { Sleep(u64), } +#[derive(Clone)] pub enum Position { Prev, Next, } +#[derive(Clone)] pub enum Selector { Title, QueryParamStr, } +#[derive(Clone)] pub enum Assert<'a> { Eq(Selector, &'a str), Contains(Selector, &'a str), + ContainsAny(Selector, Vec<&'a str>), IsPresent(&'a str), IsPresentNow(&'a str), } @@ -46,6 +54,15 @@ pub static CHEKOUT_BASE_URL: &str = "https://hs-payments-test.netlify.app"; pub static CHEKOUT_DOMAIN: &str = "hs-payments-test.netlify.app"; #[async_trait] pub trait SeleniumTest { + fn get_configs(&self) -> connector_auth::ConnectorAuthentication { + let path = env::var("CONNECTOR_AUTH_FILE_PATH") + .expect("connector authentication file path not set"); + toml::from_str( + &std::fs::read_to_string(path).expect("connector authentication config file not found"), + ) + .expect("Failed to read connector authentication config file") + } + fn get_connector_name(&self) -> String; async fn complete_actions( &self, driver: &WebDriver, @@ -61,6 +78,15 @@ pub trait SeleniumTest { } _ => assert!(driver.title().await?.contains(text)), }, + Assert::ContainsAny(selector, search_keys) => match selector { + Selector::QueryParamStr => { + let url = driver.current_url().await?; + assert!(search_keys + .iter() + .any(|key| url.query().unwrap().contains(key))) + } + _ => assert!(driver.title().await?.contains(search_keys.first().unwrap())), + }, Assert::Eq(_selector, text) => assert_eq!(driver.title().await?, text), Assert::IsPresent(text) => { assert!(is_text_present(driver, text).await?) @@ -79,6 +105,15 @@ pub trait SeleniumTest { } _ => assert!(driver.title().await?.contains(text)), }, + Assert::ContainsAny(selector, keys) => match selector { + Selector::QueryParamStr => { + let url = driver.current_url().await?; + if keys.iter().any(|key| url.query().unwrap().contains(key)) { + self.complete_actions(driver, events).await?; + } + } + _ => assert!(driver.title().await?.contains(keys.first().unwrap())), + }, Assert::Eq(_selector, text) => { if text == driver.title().await? { self.complete_actions(driver, events).await?; @@ -111,6 +146,21 @@ pub trait SeleniumTest { } _ => assert!(driver.title().await?.contains(text)), }, + Assert::ContainsAny(selector, keys) => match selector { + Selector::QueryParamStr => { + let url = driver.current_url().await?; + self.complete_actions( + driver, + if keys.iter().any(|key| url.query().unwrap().contains(key)) { + success + } else { + failure + }, + ) + .await?; + } + _ => assert!(driver.title().await?.contains(keys.first().unwrap())), + }, Assert::Eq(_selector, text) => { self.complete_actions( driver, @@ -148,16 +198,35 @@ pub trait SeleniumTest { Event::Trigger(trigger) => match trigger { Trigger::Goto(url) => { driver.goto(url).await?; - let hs_base_url = - env::var("HS_BASE_URL").unwrap_or("http://localhost:8080".to_string()); //Issue: #924 - let hs_api_key = - env::var("HS_API_KEY").expect("Hyperswitch user API key not present"); //Issue: #924 + let conf = serde_json::to_string(&self.get_configs()).unwrap(); + let hs_base_url = self + .get_configs() + .automation_configs + .unwrap() + .hs_base_url + .unwrap_or_else(|| "http://localhost:8080".to_string()); + let configs_url = self + .get_configs() + .automation_configs + .unwrap() + .configs_url + .unwrap(); + let script = &[ + format!("localStorage.configs='{configs_url}'").as_str(), + format!("localStorage.hs_api_configs='{conf}'").as_str(), + "localStorage.force_sync='true'", + format!( + "localStorage.current_connector=\"{}\";", + self.get_connector_name().clone() + ) + .as_str(), + ] + .join(";"); + + driver.execute(script, Vec::new()).await?; driver .add_cookie(new_cookie("hs_base_url", hs_base_url).clone()) .await?; - driver - .add_cookie(new_cookie("hs_api_key", hs_api_key).clone()) - .await?; } Trigger::Click(by) => { let ele = driver.query(by).first().await?; @@ -232,7 +301,12 @@ pub trait SeleniumTest { c: WebDriver, actions: Vec>, ) -> Result<(), WebDriverError> { - self.complete_actions(&c, actions).await + let config = self.get_configs().automation_configs.unwrap(); + if config.run_minimum_steps.unwrap() { + self.complete_actions(&c, actions[..3].to_vec()).await + } else { + self.complete_actions(&c, actions).await + } } async fn make_gpay_payment( &self, @@ -240,10 +314,8 @@ pub trait SeleniumTest { url: &str, actions: Vec>, ) -> Result<(), WebDriverError> { - let (email, pass) = ( - &get_env("GMAIL_EMAIL").clone(), - &get_env("GMAIL_PASS").clone(), - ); + let config = self.get_configs().automation_configs.unwrap(); + let (email, pass) = (&config.gmail_email.unwrap(), &config.gmail_pass.unwrap()); let default_actions = vec![ Event::Trigger(Trigger::Goto(url)), Event::Trigger(Trigger::Click(By::Css(".gpay-button"))), @@ -294,8 +366,18 @@ pub trait SeleniumTest { ) .await?; let (email, pass) = ( - &get_env("PYPL_EMAIL").clone(), - &get_env("PYPL_PASS").clone(), + &self + .get_configs() + .automation_configs + .unwrap() + .pypl_email + .unwrap(), + &self + .get_configs() + .automation_configs + .unwrap() + .pypl_pass + .unwrap(), ); let mut pypl_actions = vec![ Event::EitherOr( @@ -392,7 +474,7 @@ macro_rules! tester { } pub fn get_browser() -> String { - env::var("HS_TEST_BROWSER").unwrap_or("firefox".to_string()) //Issue: #924 + "firefox".to_string() } pub fn make_capabilities(s: &str) -> Capabilities { @@ -420,44 +502,32 @@ pub fn make_capabilities(s: &str) -> Capabilities { } } fn get_chrome_profile_path() -> Result { - env::var("CHROME_PROFILE_PATH").map_or_else( - //Issue: #924 - |_| -> Result { - let exe = env::current_exe()?; - let dir = exe.parent().expect("Executable must be in some directory"); - let mut base_path = dir - .to_str() - .map(|str| { - let mut fp = str.split(MAIN_SEPARATOR).collect::>(); - fp.truncate(3); - fp.join(&MAIN_SEPARATOR.to_string()) - }) - .unwrap(); - base_path.push_str(r#"/Library/Application\ Support/Google/Chrome/Default"#); - Ok(base_path) - }, - Ok, - ) + let exe = env::current_exe()?; + let dir = exe.parent().expect("Executable must be in some directory"); + let mut base_path = dir + .to_str() + .map(|str| { + let mut fp = str.split(MAIN_SEPARATOR).collect::>(); + fp.truncate(3); + fp.join(&MAIN_SEPARATOR.to_string()) + }) + .unwrap(); + base_path.push_str(r#"/Library/Application\ Support/Google/Chrome/Default"#); + Ok(base_path) } fn get_firefox_profile_path() -> Result { - env::var("FIREFOX_PROFILE_PATH").map_or_else( - //Issue: #924 - |_| -> Result { - let exe = env::current_exe()?; - let dir = exe.parent().expect("Executable must be in some directory"); - let mut base_path = dir - .to_str() - .map(|str| { - let mut fp = str.split(MAIN_SEPARATOR).collect::>(); - fp.truncate(3); - fp.join(&MAIN_SEPARATOR.to_string()) - }) - .unwrap(); - base_path.push_str(r#"/Library/Application Support/Firefox/Profiles/hs-test"#); - Ok(base_path) - }, - Ok, - ) + let exe = env::current_exe()?; + let dir = exe.parent().expect("Executable must be in some directory"); + let mut base_path = dir + .to_str() + .map(|str| { + let mut fp = str.split(MAIN_SEPARATOR).collect::>(); + fp.truncate(3); + fp.join(&MAIN_SEPARATOR.to_string()) + }) + .unwrap(); + base_path.push_str(r#"/Library/Application Support/Firefox/Profiles/hs-test"#); + Ok(base_path) } pub fn make_url(s: &str) -> &'static str { @@ -487,7 +557,3 @@ pub fn handle_test_error( } } } - -pub fn get_env(name: &str) -> String { - env::var(name).unwrap_or_else(|_| panic!("{name} not present")) //Issue: #924 -} diff --git a/crates/router/tests/connectors/stripe_ui.rs b/crates/router/tests/connectors/stripe_ui.rs index 019979d1ae..9fc19d9431 100644 --- a/crates/router/tests/connectors/stripe_ui.rs +++ b/crates/router/tests/connectors/stripe_ui.rs @@ -5,7 +5,11 @@ use crate::{selenium::*, tester}; struct StripeSeleniumTest; -impl SeleniumTest for StripeSeleniumTest {} +impl SeleniumTest for StripeSeleniumTest { + fn get_connector_name(&self) -> String { + "stripe".to_string() + } +} async fn should_make_3ds_payment(c: WebDriver) -> Result<(), WebDriverError> { let conn = StripeSeleniumTest {}; @@ -29,7 +33,7 @@ async fn should_make_3ds_mandate_payment(c: WebDriver) -> Result<(), WebDriverEr Event::Assert(Assert::IsPresent("succeeded")), Event::Assert(Assert::IsPresent("Mandate ID")), Event::Assert(Assert::IsPresent("man_")),// mandate id starting with man_ - Event::Trigger(Trigger::Click(By::Id("pm-mandate-btn"))), + Event::Trigger(Trigger::Click(By::Css("#pm-mandate-btn a"))), Event::Trigger(Trigger::Click(By::Id("pay-with-mandate-btn"))), Event::Assert(Assert::IsPresent("succeeded")), @@ -48,7 +52,7 @@ async fn should_fail_recurring_payment_due_to_authentication( Event::Assert(Assert::IsPresent("succeeded")), Event::Assert(Assert::IsPresent("Mandate ID")), Event::Assert(Assert::IsPresent("man_")),// mandate id starting with man_ - Event::Trigger(Trigger::Click(By::Id("pm-mandate-btn"))), + Event::Trigger(Trigger::Click(By::Css("#pm-mandate-btn a"))), Event::Trigger(Trigger::Click(By::Id("pay-with-mandate-btn"))), Event::Assert(Assert::IsPresent("authentication_required: Your card was declined. This transaction requires authentication.")), @@ -67,7 +71,7 @@ async fn should_make_3ds_mandate_with_zero_dollar_payment( Event::Assert(Assert::IsPresent("succeeded")), Event::Assert(Assert::IsPresent("Mandate ID")), Event::Assert(Assert::IsPresent("man_")),// mandate id starting with man_ - Event::Trigger(Trigger::Click(By::Id("pm-mandate-btn"))), + Event::Trigger(Trigger::Click(By::Css("#pm-mandate-btn a"))), Event::Trigger(Trigger::Click(By::Id("pay-with-mandate-btn"))), // Need to be handled as mentioned in https://stripe.com/docs/payments/save-and-reuse?platform=web#charge-saved-payment-method Event::Assert(Assert::IsPresent("succeeded")), @@ -78,8 +82,14 @@ async fn should_make_3ds_mandate_with_zero_dollar_payment( async fn should_make_gpay_payment(c: WebDriver) -> Result<(), WebDriverError> { let conn = StripeSeleniumTest {}; + let pub_key = conn + .get_configs() + .automation_configs + .unwrap() + .stripe_pub_key + .unwrap(); conn.make_gpay_payment(c, - &format!("{CHEKOUT_BASE_URL}/gpay?gatewayname=stripe&gpaycustomfields[stripe:version]=2018-10-31&gpaycustomfields[stripe:publishableKey]=pk_test_51Msk2GAGHc77EJXX78h549SX2uaOnEkUYqBfjcoD05PIpAnDkYxMn8nQ4d19im85NQuX4Z6WDyHaUw2fFTPBWsIY00Wa7oNerO&amount=70.00&country=US¤cy=USD"), + &format!("{CHEKOUT_BASE_URL}/gpay?gatewayname=stripe&gpaycustomfields[stripe:version]=2018-10-31&gpaycustomfields[stripe:publishableKey]={pub_key}&amount=70.00&country=US¤cy=USD"), vec![ Event::Assert(Assert::IsPresent("succeeded")), ]).await?; @@ -88,20 +98,288 @@ async fn should_make_gpay_payment(c: WebDriver) -> Result<(), WebDriverError> { async fn should_make_gpay_mandate_payment(c: WebDriver) -> Result<(), WebDriverError> { let conn = StripeSeleniumTest {}; + let pub_key = conn + .get_configs() + .automation_configs + .unwrap() + .stripe_pub_key + .unwrap(); conn.make_gpay_payment(c, - &format!("{CHEKOUT_BASE_URL}/gpay?gatewayname=stripe&gpaycustomfields[stripe:version]=2018-10-31&gpaycustomfields[stripe:publishableKey]=pk_test_51Msk2GAGHc77EJXX78h549SX2uaOnEkUYqBfjcoD05PIpAnDkYxMn8nQ4d19im85NQuX4Z6WDyHaUw2fFTPBWsIY00Wa7oNerO&amount=70.00&country=US¤cy=USD&mandate_data[customer_acceptance][acceptance_type]=offline&mandate_data[customer_acceptance][accepted_at]=1963-05-03T04:07:52.723Z&mandate_data[customer_acceptance][online][ip_address]=127.0.0.1&mandate_data[customer_acceptance][online][user_agent]=amet%20irure%20esse&mandate_data[mandate_type][multi_use][amount]=700&mandate_data[mandate_type][multi_use][currency]=USD"), + &format!("{CHEKOUT_BASE_URL}/gpay?gatewayname=stripe&gpaycustomfields[stripe:version]=2018-10-31&gpaycustomfields[stripe:publishableKey]={pub_key}&amount=70.00&country=US¤cy=USD&mandate_data[customer_acceptance][acceptance_type]=offline&mandate_data[customer_acceptance][accepted_at]=1963-05-03T04:07:52.723Z&mandate_data[customer_acceptance][online][ip_address]=127.0.0.1&mandate_data[customer_acceptance][online][user_agent]=amet%20irure%20esse&mandate_data[mandate_type][multi_use][amount]=700&mandate_data[mandate_type][multi_use][currency]=USD"), vec![ Event::Assert(Assert::IsPresent("succeeded")), Event::Assert(Assert::IsPresent("Mandate ID")), Event::Assert(Assert::IsPresent("man_")),// mandate id starting with man_ - Event::Trigger(Trigger::Click(By::Id("pm-mandate-btn"))), + Event::Trigger(Trigger::Click(By::Css("#pm-mandate-btn a"))), Event::Trigger(Trigger::Click(By::Id("pay-with-mandate-btn"))), Event::Assert(Assert::IsPresent("succeeded")), ]).await?; Ok(()) } +#[ignore = "Different flows"] //https://stripe.com/docs/testing#regulatory-cards +async fn should_make_stripe_klarna_payment(c: WebDriver) -> Result<(), WebDriverError> { + let conn = StripeSeleniumTest {}; + conn.make_redirection_payment( + c, + vec![ + Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/19"))), + Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), + Event::Trigger(Trigger::SwitchFrame(By::Id("klarna-apf-iframe"))), + Event::RunIf( + Assert::IsPresent("Let’s verify your phone"), + vec![ + Event::Trigger(Trigger::SendKeys(By::Id("phone"), "8056594427")), + Event::Trigger(Trigger::Click(By::Id("onContinue"))), + Event::Trigger(Trigger::SendKeys(By::Id("otp_field"), "123456")), + ], + ), + Event::RunIf( + Assert::IsPresent("Pick a plan"), + vec![Event::Trigger(Trigger::Click(By::Css( + "button[data-testid='pick-plan']", + )))], + ), + Event::Trigger(Trigger::Click(By::Css( + "button[data-testid='confirm-and-pay']", + ))), + Event::Trigger(Trigger::SwitchTab(Position::Prev)), + Event::Assert(Assert::IsPresent("Google")), + Event::Assert(Assert::Contains( + Selector::QueryParamStr, + "status=succeeded", + )), + ], + ) + .await?; + Ok(()) +} + +async fn should_make_afterpay_payment(c: WebDriver) -> Result<(), WebDriverError> { + let conn = StripeSeleniumTest {}; + conn.make_redirection_payment( + c, + vec![ + Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/22"))), + Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), + Event::Trigger(Trigger::Click(By::Css( + "a[class='common-Button common-Button--default']", + ))), + Event::Assert(Assert::IsPresent("Google")), + Event::Assert(Assert::Contains( + Selector::QueryParamStr, + "status=succeeded", + )), + ], + ) + .await?; + Ok(()) +} + +async fn should_make_stripe_alipay_payment(c: WebDriver) -> Result<(), WebDriverError> { + let conn = StripeSeleniumTest {}; + conn.make_redirection_payment( + c, + vec![ + Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/35"))), + Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), + Event::Trigger(Trigger::Click(By::Css( + "button[class='common-Button common-Button--default']", + ))), + Event::Trigger(Trigger::Sleep(5)), + Event::Assert(Assert::IsPresent("Google")), + Event::Assert(Assert::Contains( + Selector::QueryParamStr, + "status=succeeded", + )), + ], + ) + .await?; + Ok(()) +} + +async fn should_make_stripe_ideal_bank_redirect_payment( + c: WebDriver, +) -> Result<(), WebDriverError> { + let conn = StripeSeleniumTest {}; + conn.make_redirection_payment( + c, + vec![ + Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/2"))), + Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), + Event::Trigger(Trigger::Click(By::Css( + "a[class='common-Button common-Button--default']", + ))), + Event::Assert(Assert::IsPresent("Google")), + Event::Assert(Assert::Contains( + Selector::QueryParamStr, + "status=succeeded", + )), + ], + ) + .await?; + Ok(()) +} + +async fn should_make_stripe_giropay_bank_redirect_payment( + c: WebDriver, +) -> Result<(), WebDriverError> { + let conn = StripeSeleniumTest {}; + conn.make_redirection_payment( + c, + vec![ + Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/1"))), + Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), + Event::Trigger(Trigger::Click(By::Css( + "a[class='common-Button common-Button--default']", + ))), + Event::Assert(Assert::IsPresent("Google")), + Event::Assert(Assert::Contains( + Selector::QueryParamStr, + "status=succeeded", + )), + ], + ) + .await?; + Ok(()) +} + +async fn should_make_stripe_eps_bank_redirect_payment(c: WebDriver) -> Result<(), WebDriverError> { + let conn = StripeSeleniumTest {}; + conn.make_redirection_payment( + c, + vec![ + Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/26"))), + Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), + Event::Trigger(Trigger::Click(By::Css( + "a[class='common-Button common-Button--default']", + ))), + Event::Assert(Assert::IsPresent("Google")), + Event::Assert(Assert::Contains( + Selector::QueryParamStr, + "status=succeeded", + )), + ], + ) + .await?; + Ok(()) +} + +async fn should_make_stripe_bancontact_card_redirect_payment( + c: WebDriver, +) -> Result<(), WebDriverError> { + let conn = StripeSeleniumTest {}; + conn.make_redirection_payment( + c, + vec![ + Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/28"))), + Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), + Event::Trigger(Trigger::Click(By::Css( + "a[class='common-Button common-Button--default']", + ))), + Event::Assert(Assert::IsPresent("Google")), + Event::Assert(Assert::Contains( + Selector::QueryParamStr, + "status=succeeded", + )), + ], + ) + .await?; + Ok(()) +} + +async fn should_make_stripe_p24_redirect_payment(c: WebDriver) -> Result<(), WebDriverError> { + let conn = StripeSeleniumTest {}; + conn.make_redirection_payment( + c, + vec![ + Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/31"))), + Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), + Event::Trigger(Trigger::Click(By::Css( + "a[class='common-Button common-Button--default']", + ))), + Event::Assert(Assert::IsPresent("Google")), + Event::Assert(Assert::Contains( + Selector::QueryParamStr, + "status=succeeded", + )), + ], + ) + .await?; + Ok(()) +} + +async fn should_make_stripe_sofort_redirect_payment(c: WebDriver) -> Result<(), WebDriverError> { + let conn = StripeSeleniumTest {}; + conn.make_redirection_payment( + c, + vec![ + Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/34"))), + Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), + Event::Trigger(Trigger::Click(By::Css( + "a[class='common-Button common-Button--default']", + ))), + Event::Assert(Assert::IsPresent("Google")), + Event::Assert(Assert::ContainsAny( + Selector::QueryParamStr, + vec!["status=processing", "status=succeeded"], + )), + ], + ) + .await?; + Ok(()) +} + +async fn should_make_stripe_ach_bank_debit_payment(c: WebDriver) -> Result<(), WebDriverError> { + let conn = StripeSeleniumTest {}; + conn.make_redirection_payment( + c, + vec![ + Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/56"))), + Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), + Event::Trigger(Trigger::SendKeys( + By::Css("input[class='p-CodePuncher-controllingInput']"), + "11AA", + )), + Event::Trigger(Trigger::Click(By::Css( + "div[class='SubmitButton-IconContainer']", + ))), + Event::Assert(Assert::IsPresent("Thanks for your payment")), + Event::Assert(Assert::IsPresent("You completed a payment")), + ], + ) + .await?; + Ok(()) +} + +async fn should_make_stripe_becs_bank_debit_payment(c: WebDriver) -> Result<(), WebDriverError> { + let conn = StripeSeleniumTest {}; + conn.make_redirection_payment( + c, + vec![ + Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/56"))), + Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), + Event::Assert(Assert::IsPresent("processing")), + ], + ) + .await?; + Ok(()) +} + +async fn should_make_stripe_sepa_bank_debit_payment(c: WebDriver) -> Result<(), WebDriverError> { + let conn = StripeSeleniumTest {}; + conn.make_redirection_payment( + c, + vec![ + Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/67"))), + Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), + Event::Assert(Assert::IsPresent("processing")), + ], + ) + .await?; + Ok(()) +} #[test] #[serial] @@ -138,3 +416,75 @@ fn should_make_gpay_payment_test() { fn should_make_gpay_mandate_payment_test() { tester!(should_make_gpay_mandate_payment); } + +#[test] +#[serial] +fn should_make_stripe_klarna_payment_test() { + tester!(should_make_stripe_klarna_payment); +} + +#[test] +#[serial] +fn should_make_afterpay_payment_test() { + tester!(should_make_afterpay_payment); +} + +#[test] +#[serial] +fn should_make_stripe_alipay_payment_test() { + tester!(should_make_stripe_alipay_payment); +} + +#[test] +#[serial] +fn should_make_stripe_ideal_bank_redirect_payment_test() { + tester!(should_make_stripe_ideal_bank_redirect_payment); +} + +#[test] +#[serial] +fn should_make_stripe_giropay_bank_redirect_payment_test() { + tester!(should_make_stripe_giropay_bank_redirect_payment); +} + +#[test] +#[serial] +fn should_make_stripe_eps_bank_redirect_payment_test() { + tester!(should_make_stripe_eps_bank_redirect_payment); +} + +#[test] +#[serial] +fn should_make_stripe_bancontact_card_redirect_payment_test() { + tester!(should_make_stripe_bancontact_card_redirect_payment); +} + +#[test] +#[serial] +fn should_make_stripe_p24_redirect_payment_test() { + tester!(should_make_stripe_p24_redirect_payment); +} + +#[test] +#[serial] +fn should_make_stripe_sofort_redirect_payment_test() { + tester!(should_make_stripe_sofort_redirect_payment); +} + +#[test] +#[serial] +fn should_make_stripe_ach_bank_debit_payment_test() { + tester!(should_make_stripe_ach_bank_debit_payment); +} + +#[test] +#[serial] +fn should_make_stripe_becs_bank_debit_payment_test() { + tester!(should_make_stripe_becs_bank_debit_payment); +} + +#[test] +#[serial] +fn should_make_stripe_sepa_bank_debit_payment_test() { + tester!(should_make_stripe_sepa_bank_debit_payment); +} diff --git a/crates/router/tests/connectors/worldline_ui.rs b/crates/router/tests/connectors/worldline_ui.rs new file mode 100644 index 0000000000..b95285b67f --- /dev/null +++ b/crates/router/tests/connectors/worldline_ui.rs @@ -0,0 +1,83 @@ +use serial_test::serial; +use thirtyfour::{prelude::*, WebDriver}; + +use crate::{selenium::*, tester}; + +struct WorldlineSeleniumTest; + +impl SeleniumTest for WorldlineSeleniumTest { + fn get_connector_name(&self) -> String { + "worldline".to_string() + } +} + +async fn should_make_card_non_3ds_payment(c: WebDriver) -> Result<(), WebDriverError> { + let conn = WorldlineSeleniumTest {}; + conn.make_redirection_payment( + c, + vec![ + Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/71"))), + Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), + Event::Assert(Assert::IsPresent("status")), + Event::Assert(Assert::IsPresent("processing")), + ], + ) + .await?; + Ok(()) +} + +async fn should_make_worldline_ideal_redirect_payment(c: WebDriver) -> Result<(), WebDriverError> { + let conn = WorldlineSeleniumTest {}; + conn.make_redirection_payment( + c, + vec![ + Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/49"))), + Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), + Event::Assert(Assert::IsPresent("Google")), + Event::Assert(Assert::ContainsAny( + Selector::QueryParamStr, + vec!["status=requires_customer_action", "status=succeeded"], + )), + ], + ) + .await?; + Ok(()) +} + +async fn should_make_worldline_giropay_redirect_payment( + c: WebDriver, +) -> Result<(), WebDriverError> { + let conn = WorldlineSeleniumTest {}; + conn.make_redirection_payment( + c, + vec![ + Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/48"))), + Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), + Event::Assert(Assert::IsPresent("Google")), + Event::Assert(Assert::ContainsAny( + Selector::QueryParamStr, + vec!["status=requires_customer_action", "status=succeeded"], + )), + ], + ) + .await?; + Ok(()) +} + +#[test] +#[serial] +fn should_make_worldline_giropay_redirect_payment_test() { + tester!(should_make_worldline_giropay_redirect_payment); +} + +#[test] +#[serial] +fn should_make_worldline_ideal_redirect_payment_test() { + tester!(should_make_worldline_ideal_redirect_payment); +} + +#[test] +#[serial] +fn should_make_card_non_3ds_payment_test() { + tester!(should_make_card_non_3ds_payment); +}