feat(test): Add support to run UI tests in CI pipeline (#1539)

This commit is contained in:
Jagan
2023-07-05 19:01:42 +05:30
committed by GitHub
parent 5628985c40
commit 21f5e20929
12 changed files with 1407 additions and 92 deletions

31
.github/scripts/run_ui_tests.sh vendored Normal file
View File

@ -0,0 +1,31 @@
#! /usr/bin/env bash
sudo apt update
apt install net-tools
mkdir tests
#download connector ui tests
while [ ! -f $HOME/target/test/connector_tests.json ]
do
if [ $SECONDS > 20 ]
then
exit 1
fi
sleep 2
wget $UI_TESTCASES_PATH && mv testcases $HOME/target/test/connector_tests.json
done
firefox --version
$GECKOWEBDRIVER/geckodriver > tests/geckodriver.log 2>&1 &
#start server and run ui tests
cargo run &
#Wait for the server to start in port 8080
while netstat -lnt | awk '$4 ~ /:8080$/ {exit 1}'; do
if [ $SECONDS > 900 ]
then
exit 1
else
sleep 10
fi
done

Binary file not shown.

1136
.github/testcases/ui_tests.json vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,133 @@
name: Connector UI Sanity Tests
on:
workflow_dispatch:
push:
branches:
- main
merge_group:
types:
- checks_requested
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
# Disable incremental compilation.
#
# Incremental compilation is useful as part of an edit-build-test-edit cycle,
# as it lets the compiler avoid recompiling code that hasn't changed. However,
# on CI, we're not making small edits; we're almost always building the entire
# project from scratch. Thus, incremental compilation on CI actually
# introduces *additional* overhead to support making future builds
# faster...but no future builds will ever occur in any given CI environment.
#
# See https://matklad.github.io/2021/09/04/fast-rust-builds.html#ci-workflow
# for details.
CARGO_INCREMENTAL: 1
# Allow more retries for network requests in cargo (downloading crates) and
# rustup (installing toolchains). This should help to reduce flaky CI failures
# from transient network timeouts or other issues.
CARGO_NET_RETRY: 10
RUSTUP_MAX_RETRIES: 10
# Don't emit giant backtraces in the CI logs.
RUST_BACKTRACE: short
# Use cargo's sparse index protocol
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
jobs:
test_connectors:
name: Run tests on stable toolchain for connectors
runs-on: ubuntu-latest
services:
redis:
image: redis
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379
postgres:
image: postgres:14.5
env:
POSTGRES_USER: db_user
POSTGRES_PASSWORD: db_pass
POSTGRES_DB: hyperswitch_db
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
strategy:
fail-fast: false
matrix:
connector:
# do not use more than 8 runners, try to group less time taking connectors together
- stripe
- adyen_uk|shift4|worldline
- airwallex|bluesnap|checkout
- paypal|mollie|payu
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Decrypt connector auth file
env:
CONNECTOR_AUTH_PASSPHRASE: ${{ secrets.CONNECTOR_AUTH_PASSPHRASE }}
shell: bash
run: ./scripts/decrypt_connector_auth.sh
- name: Set connector auth file path in env
shell: bash
run: echo "CONNECTOR_AUTH_FILE_PATH=$HOME/target/test/connector_auth.toml" >> $GITHUB_ENV
- name: Set connector tests file path in env
shell: bash
run: echo "CONNECTOR_TESTS_FILE_PATH=$HOME/target/test/connector_tests.json" >> $GITHUB_ENV
- name: Set ignore_browser_profile usage in env
shell: bash
run: echo "IGNORE_BROWSER_PROFILE=true" >> $GITHUB_ENV
- name: Install latest compiler
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- uses: Swatinem/rust-cache@v2.4.0
- uses: baptiste0928/cargo-install@v2.0.0
with:
crate: diesel_cli
features: postgres
args: "--no-default-features"
- name: diesel migration run
shell: bash
env:
DATABASE_URL: postgres://db_user:db_pass@localhost:5432/hyperswitch_db
run: diesel migration run
- name: Start server
env:
UI_TESTCASES_PATH: ${{ secrets.UI_TESTCASES_PATH }}
shell: bash
run: sh .github/scripts/run_ui_tests.sh
- name: Run tests
shell: bash
run: |
IN="${{ matrix.connector }}"
connectors=(${IN//|/ })
for i in "${connectors[@]}"; do
cargo test --package router --test connectors -- "${i}_ui::" --test-threads=1
done

View File

@ -17,15 +17,13 @@ async fn should_make_adyen_3ds_payment_failed(web_driver: WebDriver) -> Result<(
web_driver, web_driver,
vec![ vec![
Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/177"))), Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/177"))),
Event::Assert(Assert::IsPresent("Expiry Year")),
Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
Event::Trigger(Trigger::SwitchFrame(By::Name("threeDSIframe"))), Event::Trigger(Trigger::SwitchFrame(By::Name("threeDSIframe"))),
Event::Assert(Assert::Eq(Selector::Title, "Payment Authentication")), Event::Assert(Assert::Eq(Selector::Title, "Payment Authentication")),
Event::Trigger(Trigger::SendKeys(By::ClassName("input-field"), "password")), Event::Trigger(Trigger::SendKeys(By::ClassName("input-field"), "password")),
Event::Trigger(Trigger::Click(By::Id("buttonSubmit"))), Event::Trigger(Trigger::Click(By::Id("buttonSubmit"))),
Event::Trigger(Trigger::Sleep(5)), Event::Trigger(Trigger::Sleep(5)),
Event::Assert(Assert::IsPresent("Google")), Event::Assert(Assert::IsPresent("failed")),
Event::Assert(Assert::Contains(Selector::QueryParamStr, "status=failed")),
], ],
) )
.await?; .await?;
@ -40,7 +38,6 @@ async fn should_make_adyen_3ds_payment_success(
web_driver, web_driver,
vec![ vec![
Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/62"))), Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/62"))),
Event::Assert(Assert::IsPresent("Expiry Year")),
Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
Event::Trigger(Trigger::SwitchFrame(By::Name("threeDSIframe"))), Event::Trigger(Trigger::SwitchFrame(By::Name("threeDSIframe"))),
Event::Assert(Assert::Eq(Selector::Title, "Payment Authentication")), Event::Assert(Assert::Eq(Selector::Title, "Payment Authentication")),
@ -50,7 +47,7 @@ async fn should_make_adyen_3ds_payment_success(
Event::Assert(Assert::IsPresent("Google")), Event::Assert(Assert::IsPresent("Google")),
Event::Assert(Assert::Contains( Event::Assert(Assert::Contains(
Selector::QueryParamStr, Selector::QueryParamStr,
"status=processing", "status=succeeded",
)), )),
], ],
) )
@ -157,18 +154,21 @@ async fn should_make_adyen_alipay_hk_payment(c: WebDriver) -> Result<(), WebDriv
#[test] #[test]
#[serial] #[serial]
#[ignore]
fn should_make_adyen_gpay_payment_test() { fn should_make_adyen_gpay_payment_test() {
tester!(should_make_adyen_gpay_payment); tester!(should_make_adyen_gpay_payment);
} }
#[test] #[test]
#[serial] #[serial]
#[ignore]
fn should_make_adyen_gpay_mandate_payment_test() { fn should_make_adyen_gpay_mandate_payment_test() {
tester!(should_make_adyen_gpay_mandate_payment); tester!(should_make_adyen_gpay_mandate_payment);
} }
#[test] #[test]
#[serial] #[serial]
#[ignore]
fn should_make_adyen_gpay_zero_dollar_mandate_payment_test() { fn should_make_adyen_gpay_zero_dollar_mandate_payment_test() {
tester!(should_make_adyen_gpay_zero_dollar_mandate_payment); tester!(should_make_adyen_gpay_zero_dollar_mandate_payment);
} }
@ -193,6 +193,7 @@ fn should_make_adyen_3ds_payment_success_test() {
#[test] #[test]
#[serial] #[serial]
#[ignore]
fn should_make_adyen_alipay_hk_payment_test() { fn should_make_adyen_alipay_hk_payment_test() {
tester!(should_make_adyen_alipay_hk_payment); tester!(should_make_adyen_alipay_hk_payment);
} }

View File

@ -17,7 +17,6 @@ async fn should_make_airwallex_3ds_payment(web_driver: WebDriver) -> Result<(),
web_driver, web_driver,
vec![ vec![
Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/85"))), Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/85"))),
Event::Assert(Assert::IsPresent("Expiry Year")),
Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
Event::Trigger(Trigger::Query(By::ClassName("title"))), Event::Trigger(Trigger::Query(By::ClassName("title"))),
Event::Assert(Assert::Eq( Event::Assert(Assert::Eq(
@ -65,6 +64,7 @@ fn should_make_airwallex_3ds_payment_test() {
#[test] #[test]
#[serial] #[serial]
#[ignore]
fn should_make_airwallex_gpay_payment_test() { fn should_make_airwallex_gpay_payment_test() {
tester!(should_make_airwallex_gpay_payment); tester!(should_make_airwallex_gpay_payment);
} }

View File

@ -20,11 +20,7 @@ async fn should_make_3ds_payment(c: WebDriver) -> Result<(), WebDriverError> {
Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/33"))), Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/33"))),
Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
Event::Trigger(Trigger::Click(By::Id("continue-transaction"))), Event::Trigger(Trigger::Click(By::Id("continue-transaction"))),
Event::Assert(Assert::IsPresent("Google")), Event::Assert(Assert::IsPresent("succeeded")),
Event::Assert(Assert::Contains(
Selector::QueryParamStr,
"status=succeeded",
)),
], ],
) )
.await?; .await?;

View File

@ -18,11 +18,17 @@ async fn should_make_3ds_payment(driver: WebDriver) -> Result<(), WebDriverError
vec![ vec![
Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/10"))), Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/10"))),
Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
Event::RunIf(
Assert::IsElePresent(By::Id("Cardinal-CCA-IFrame")),
vec![
Event::Trigger(Trigger::SwitchFrame(By::Id("Cardinal-CCA-IFrame"))), Event::Trigger(Trigger::SwitchFrame(By::Id("Cardinal-CCA-IFrame"))),
Event::Assert(Assert::IsPresent("Enter your code below")), Event::Assert(Assert::IsPresent("Enter your code below")),
Event::Trigger(Trigger::SendKeys(By::Name("challengeDataEntry"), "1234")), Event::Trigger(Trigger::SendKeys(By::Name("challengeDataEntry"), "1234")),
Event::Trigger(Trigger::Click(By::ClassName("button.primary"))), Event::Trigger(Trigger::Click(By::ClassName("button.primary"))),
Event::Trigger(Trigger::Sleep(5)), ],
),
Event::Trigger(Trigger::Sleep(10)),
Event::Assert(Assert::IsPresent("Google")),
Event::Assert(Assert::Contains( Event::Assert(Assert::Contains(
Selector::QueryParamStr, Selector::QueryParamStr,
"status=succeeded", "status=succeeded",
@ -57,6 +63,7 @@ fn should_make_3ds_payment_test() {
#[test] #[test]
#[serial] #[serial]
#[ignore]
fn should_make_gpay_payment_test() { fn should_make_gpay_payment_test() {
tester!(should_make_gpay_payment); tester!(should_make_gpay_payment);
} }

View File

@ -31,7 +31,7 @@ async fn should_make_globalpay_paypal_payment(driver: WebDriver) -> Result<(), W
let conn = GlobalpaySeleniumTest {}; let conn = GlobalpaySeleniumTest {};
conn.make_paypal_payment( conn.make_paypal_payment(
driver, driver,
&format!("{CHEKOUT_BASE_URL}/paypal-redirect?amount=12.00&country=US&currency=EUR"), &format!("{CHEKOUT_BASE_URL}/saved/46"),
vec![ vec![
Event::Assert(Assert::IsPresent("Google")), Event::Assert(Assert::IsPresent("Google")),
Event::Assert(Assert::ContainsAny( Event::Assert(Assert::ContainsAny(
@ -50,7 +50,6 @@ async fn should_make_globalpay_ideal_payment(driver: WebDriver) -> Result<(), We
driver, driver,
vec![ vec![
Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/53"))), Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/53"))),
Event::Assert(Assert::IsPresent("Home")),
Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
Event::Assert(Assert::IsPresent("Choose your Bank")), Event::Assert(Assert::IsPresent("Choose your Bank")),
Event::Trigger(Trigger::Click(By::Css("button.btn.btn-primary"))), Event::Trigger(Trigger::Click(By::Css("button.btn.btn-primary"))),
@ -77,7 +76,6 @@ async fn should_make_globalpay_giropay_payment(driver: WebDriver) -> Result<(),
driver, driver,
vec![ vec![
Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/59"))), Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/59"))),
Event::Assert(Assert::IsPresent("Home")),
Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
Event::Assert(Assert::IsPresent("Choose your Bank")), Event::Assert(Assert::IsPresent("Choose your Bank")),
Event::Trigger(Trigger::Click(By::Css("button.btn.btn-primary"))), Event::Trigger(Trigger::Click(By::Css("button.btn.btn-primary"))),
@ -104,7 +102,6 @@ async fn should_make_globalpay_eps_payment(driver: WebDriver) -> Result<(), WebD
driver, driver,
vec![ vec![
Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/50"))), Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/50"))),
Event::Assert(Assert::IsPresent("Home")),
Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
Event::Assert(Assert::IsPresent("Choose your Bank")), Event::Assert(Assert::IsPresent("Choose your Bank")),
Event::Trigger(Trigger::Click(By::Css("button.btn.btn-primary"))), Event::Trigger(Trigger::Click(By::Css("button.btn.btn-primary"))),
@ -131,7 +128,6 @@ async fn should_make_globalpay_sofort_payment(driver: WebDriver) -> Result<(), W
driver, driver,
vec![ vec![
Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/63"))), Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/63"))),
Event::Assert(Assert::IsPresent("Home")),
Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))), Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
Event::RunIf( Event::RunIf(
Assert::IsPresent("Wählen"), Assert::IsPresent("Wählen"),

View File

@ -58,7 +58,7 @@ async fn should_make_nuvei_pypl_payment(c: WebDriver) -> Result<(), WebDriverErr
let conn = NuveiSeleniumTest {}; let conn = NuveiSeleniumTest {};
conn.make_paypal_payment( conn.make_paypal_payment(
c, c,
&format!("{CHEKOUT_BASE_URL}/paypal-redirect?amount=12.00&country=US&currency=USD"), &format!("{CHEKOUT_BASE_URL}/saved/5"),
vec![ vec![
Event::Assert(Assert::IsPresent("Google")), Event::Assert(Assert::IsPresent("Google")),
Event::Assert(Assert::ContainsAny( Event::Assert(Assert::ContainsAny(

View File

@ -1,6 +1,5 @@
use std::{collections::HashMap, env, path::MAIN_SEPARATOR, time::Duration}; use std::{collections::HashMap, env, io::Read, path::MAIN_SEPARATOR, time::Duration};
use actix_web::cookie::SameSite;
use async_trait::async_trait; use async_trait::async_trait;
use thirtyfour::{components::SelectElement, prelude::*, WebDriver}; use thirtyfour::{components::SelectElement, prelude::*, WebDriver};
@ -47,13 +46,27 @@ pub enum Assert<'a> {
Contains(Selector, &'a str), Contains(Selector, &'a str),
ContainsAny(Selector, Vec<&'a str>), ContainsAny(Selector, Vec<&'a str>),
IsPresent(&'a str), IsPresent(&'a str),
IsElePresent(By),
IsPresentNow(&'a str), IsPresentNow(&'a str),
} }
pub static CHEKOUT_BASE_URL: &str = "https://hs-payments-test.netlify.app"; pub static CHEKOUT_BASE_URL: &str = "https://hs-payments-test.netlify.app";
pub static CHEKOUT_DOMAIN: &str = "hs-payments-test.netlify.app";
#[async_trait] #[async_trait]
pub trait SeleniumTest { pub trait SeleniumTest {
fn get_saved_testcases(&self) -> serde_json::Value {
let env_value = env::var("CONNECTOR_TESTS_FILE_PATH").ok();
if env_value.is_none() {
return serde_json::json!("");
}
let path = env_value.unwrap();
let mut file = &std::fs::File::open(path).expect("Failed to open file");
let mut contents = String::new();
file.read_to_string(&mut contents)
.expect("Failed to read file");
// Parse the JSON data
serde_json::from_str(&contents).expect("Failed to parse JSON")
}
fn get_configs(&self) -> connector_auth::ConnectorAuthentication { fn get_configs(&self) -> connector_auth::ConnectorAuthentication {
let path = env::var("CONNECTOR_AUTH_FILE_PATH") let path = env::var("CONNECTOR_AUTH_FILE_PATH")
.expect("connector authentication file path not set"); .expect("connector authentication file path not set");
@ -91,6 +104,9 @@ pub trait SeleniumTest {
Assert::IsPresent(text) => { Assert::IsPresent(text) => {
assert!(is_text_present(driver, text).await?) assert!(is_text_present(driver, text).await?)
} }
Assert::IsElePresent(selector) => {
assert!(is_element_present(driver, selector).await?)
}
Assert::IsPresentNow(text) => { Assert::IsPresentNow(text) => {
assert!(is_text_present_now(driver, text).await?) assert!(is_text_present_now(driver, text).await?)
} }
@ -124,6 +140,11 @@ pub trait SeleniumTest {
self.complete_actions(driver, events).await?; self.complete_actions(driver, events).await?;
} }
} }
Assert::IsElePresent(text) => {
if is_element_present(driver, text).await.is_ok() {
self.complete_actions(driver, events).await?;
}
}
Assert::IsPresentNow(text) => { Assert::IsPresentNow(text) => {
if is_text_present_now(driver, text).await.is_ok() { if is_text_present_now(driver, text).await.is_ok() {
self.complete_actions(driver, events).await?; self.complete_actions(driver, events).await?;
@ -183,6 +204,17 @@ pub trait SeleniumTest {
) )
.await?; .await?;
} }
Assert::IsElePresent(by) => {
self.complete_actions(
driver,
if is_element_present(driver, by).await.is_ok() {
success
} else {
failure
},
)
.await?;
}
Assert::IsPresentNow(text) => { Assert::IsPresentNow(text) => {
self.complete_actions( self.complete_actions(
driver, driver,
@ -197,7 +229,8 @@ pub trait SeleniumTest {
}, },
Event::Trigger(trigger) => match trigger { Event::Trigger(trigger) => match trigger {
Trigger::Goto(url) => { Trigger::Goto(url) => {
driver.goto(url).await?; let saved_tests =
serde_json::to_string(&self.get_saved_testcases()).unwrap();
let conf = serde_json::to_string(&self.get_configs()).unwrap(); let conf = serde_json::to_string(&self.get_configs()).unwrap();
let hs_base_url = self let hs_base_url = self
.get_configs() .get_configs()
@ -218,6 +251,8 @@ pub trait SeleniumTest {
"localStorage.hs_api_keys=''", "localStorage.hs_api_keys=''",
format!("localStorage.base_url='{hs_base_url}'").as_str(), format!("localStorage.base_url='{hs_base_url}'").as_str(),
format!("localStorage.hs_api_configs='{conf}'").as_str(), format!("localStorage.hs_api_configs='{conf}'").as_str(),
format!("localStorage.saved_payments=JSON.stringify({saved_tests})")
.as_str(),
"localStorage.force_sync='true'", "localStorage.force_sync='true'",
format!( format!(
"localStorage.current_connector=\"{}\";", "localStorage.current_connector=\"{}\";",
@ -226,11 +261,8 @@ pub trait SeleniumTest {
.as_str(), .as_str(),
] ]
.join(";"); .join(";");
driver.goto(url).await?;
driver.execute(script, Vec::new()).await?; driver.execute(script, Vec::new()).await?;
driver
.add_cookie(new_cookie("hs_base_url", hs_base_url).clone())
.await?;
} }
Trigger::Click(by) => { Trigger::Click(by) => {
let ele = driver.query(by).first().await?; let ele = driver.query(by).first().await?;
@ -339,6 +371,7 @@ pub trait SeleniumTest {
Event::Trigger(Trigger::SendKeys(By::Name("Passwd"), pass)), Event::Trigger(Trigger::SendKeys(By::Name("Passwd"), pass)),
Event::Trigger(Trigger::Sleep(2)), Event::Trigger(Trigger::Sleep(2)),
Event::Trigger(Trigger::Click(By::Id("passwordNext"))), Event::Trigger(Trigger::Click(By::Id("passwordNext"))),
Event::Trigger(Trigger::Sleep(10)),
], ],
vec![ vec![
Event::Trigger(Trigger::SendKeys(By::Id("identifierId"), email)), Event::Trigger(Trigger::SendKeys(By::Id("identifierId"), email)),
@ -346,6 +379,7 @@ pub trait SeleniumTest {
Event::Trigger(Trigger::SendKeys(By::Name("Passwd"), pass)), Event::Trigger(Trigger::SendKeys(By::Name("Passwd"), pass)),
Event::Trigger(Trigger::Sleep(2)), Event::Trigger(Trigger::Sleep(2)),
Event::Trigger(Trigger::Click(By::Id("passwordNext"))), Event::Trigger(Trigger::Click(By::Id("passwordNext"))),
Event::Trigger(Trigger::Sleep(10)),
], ],
), ),
], ],
@ -368,7 +402,7 @@ pub trait SeleniumTest {
&c, &c,
vec![ vec![
Event::Trigger(Trigger::Goto(url)), Event::Trigger(Trigger::Goto(url)),
Event::Trigger(Trigger::Click(By::Id("pypl-redirect-btn"))), Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
], ],
) )
.await?; .await?;
@ -387,6 +421,13 @@ pub trait SeleniumTest {
.unwrap(), .unwrap(),
); );
let mut pypl_actions = vec![ let mut pypl_actions = vec![
Event::RunIf(
Assert::IsPresent("Enter your email address to get started."),
vec![
Event::Trigger(Trigger::SendKeys(By::Id("email"), email)),
Event::Trigger(Trigger::Click(By::Id("btnNext"))),
],
),
Event::EitherOr( Event::EitherOr(
Assert::IsPresent("Password"), Assert::IsPresent("Password"),
vec![ vec![
@ -420,12 +461,9 @@ async fn is_text_present(driver: &WebDriver, key: &str) -> WebDriverResult<bool>
let result = driver.query(By::XPath(&xpath)).first().await?; let result = driver.query(By::XPath(&xpath)).first().await?;
result.is_present().await result.is_present().await
} }
fn new_cookie(name: &str, value: String) -> Cookie<'_> { async fn is_element_present(driver: &WebDriver, by: By) -> WebDriverResult<bool> {
let mut base_url_cookie = Cookie::new(name, value); let element = driver.query(by).first().await?;
base_url_cookie.set_same_site(Some(SameSite::Lax)); element.is_present().await
base_url_cookie.set_domain(CHEKOUT_DOMAIN);
base_url_cookie.set_path("/");
base_url_cookie
} }
#[macro_export] #[macro_export]
@ -488,29 +526,25 @@ pub fn make_capabilities(s: &str) -> Capabilities {
match s { match s {
"firefox" => { "firefox" => {
let mut caps = DesiredCapabilities::firefox(); let mut caps = DesiredCapabilities::firefox();
let ignore_profile = env::var("IGNORE_BROWSER_PROFILE").ok();
if ignore_profile.is_none() {
let profile_path = &format!("-profile={}", get_firefox_profile_path().unwrap()); let profile_path = &format!("-profile={}", get_firefox_profile_path().unwrap());
caps.add_firefox_arg(profile_path).unwrap(); caps.add_firefox_arg(profile_path).unwrap();
// let mut prefs = FirefoxPreferences::new(); } else {
// prefs.set("-browser.link.open_newwindow", 3).unwrap(); caps.add_firefox_arg("--headless").ok();
// caps.set_preferences(prefs).unwrap(); }
caps.into() caps.into()
} }
"chrome" => { "chrome" => {
let mut caps = DesiredCapabilities::chrome(); let mut caps = DesiredCapabilities::chrome();
let profile_path = &format!("user-data-dir={}", get_chrome_profile_path().unwrap()); let profile_path = &format!("user-data-dir={}", get_chrome_profile_path().unwrap());
caps.add_chrome_arg(profile_path).unwrap(); caps.add_chrome_arg(profile_path).unwrap();
// caps.set_headless().unwrap();
// caps.set_no_sandbox().unwrap();
// caps.set_disable_gpu().unwrap();
// caps.set_disable_dev_shm_usage().unwrap();
caps.into() caps.into()
} }
&_ => DesiredCapabilities::safari().into(), &_ => DesiredCapabilities::safari().into(),
} }
} }
fn get_chrome_profile_path() -> Result<String, WebDriverError> { fn get_chrome_profile_path() -> Result<String, WebDriverError> {
env::var("CHROME_PROFILE_PATH").map_or_else(
|_| -> Result<String, WebDriverError> {
let exe = env::current_exe()?; let exe = env::current_exe()?;
let dir = exe.parent().expect("Executable must be in some directory"); let dir = exe.parent().expect("Executable must be in some directory");
let mut base_path = dir let mut base_path = dir
@ -521,11 +555,8 @@ fn get_chrome_profile_path() -> Result<String, WebDriverError> {
fp.join(&MAIN_SEPARATOR.to_string()) fp.join(&MAIN_SEPARATOR.to_string())
}) })
.unwrap(); .unwrap();
base_path.push_str(r#"/Library/Application\ Support/Google/Chrome/Default"#); base_path.push_str(r#"/Library/Application\ Support/Google/Chrome/Default"#); //Issue: 1573
Ok(base_path) Ok(base_path)
},
Ok,
)
} }
fn get_firefox_profile_path() -> Result<String, WebDriverError> { fn get_firefox_profile_path() -> Result<String, WebDriverError> {
let exe = env::current_exe()?; let exe = env::current_exe()?;
@ -538,7 +569,7 @@ fn get_firefox_profile_path() -> Result<String, WebDriverError> {
fp.join(&MAIN_SEPARATOR.to_string()) fp.join(&MAIN_SEPARATOR.to_string())
}) })
.unwrap(); .unwrap();
base_path.push_str(r#"/Library/Application Support/Firefox/Profiles/hs-test"#); base_path.push_str(r#"/Library/Application Support/Firefox/Profiles/hs-test"#); //Issue: 1573
Ok(base_path) Ok(base_path)
} }

View File

@ -34,8 +34,7 @@ async fn should_make_3ds_mandate_payment(c: WebDriver) -> Result<(), WebDriverEr
Event::Assert(Assert::IsPresent("Mandate ID")), Event::Assert(Assert::IsPresent("Mandate ID")),
Event::Assert(Assert::IsPresent("man_")),// mandate id starting with man_ Event::Assert(Assert::IsPresent("man_")),// mandate id starting with man_
Event::Trigger(Trigger::Click(By::Css("#pm-mandate-btn a"))), Event::Trigger(Trigger::Click(By::Css("#pm-mandate-btn a"))),
Event::Trigger(Trigger::Click(By::Css("#pm-mandate-btn a"))), Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
Event::Trigger(Trigger::Click(By::Id("pay-with-mandate-btn"))),
Event::Assert(Assert::IsPresent("succeeded")), Event::Assert(Assert::IsPresent("succeeded")),
]).await?; ]).await?;
@ -54,8 +53,7 @@ async fn should_fail_recurring_payment_due_to_authentication(
Event::Assert(Assert::IsPresent("Mandate ID")), Event::Assert(Assert::IsPresent("Mandate ID")),
Event::Assert(Assert::IsPresent("man_")),// mandate id starting with man_ Event::Assert(Assert::IsPresent("man_")),// mandate id starting with man_
Event::Trigger(Trigger::Click(By::Css("#pm-mandate-btn a"))), Event::Trigger(Trigger::Click(By::Css("#pm-mandate-btn a"))),
Event::Trigger(Trigger::Click(By::Css("#pm-mandate-btn a"))), Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
Event::Trigger(Trigger::Click(By::Id("pay-with-mandate-btn"))),
Event::Assert(Assert::IsPresent("authentication_required: Your card was declined. This transaction requires authentication.")), Event::Assert(Assert::IsPresent("authentication_required: Your card was declined. This transaction requires authentication.")),
]).await?; ]).await?;
@ -74,8 +72,7 @@ async fn should_make_3ds_mandate_with_zero_dollar_payment(
Event::Assert(Assert::IsPresent("Mandate ID")), Event::Assert(Assert::IsPresent("Mandate ID")),
Event::Assert(Assert::IsPresent("man_")),// mandate id starting with man_ Event::Assert(Assert::IsPresent("man_")),// mandate id starting with man_
Event::Trigger(Trigger::Click(By::Css("#pm-mandate-btn a"))), Event::Trigger(Trigger::Click(By::Css("#pm-mandate-btn a"))),
Event::Trigger(Trigger::Click(By::Css("#pm-mandate-btn a"))), Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
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 // 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")), Event::Assert(Assert::IsPresent("succeeded")),
@ -114,7 +111,7 @@ async fn should_make_gpay_mandate_payment(c: WebDriver) -> Result<(), WebDriverE
Event::Assert(Assert::IsPresent("Mandate ID")), Event::Assert(Assert::IsPresent("Mandate ID")),
Event::Assert(Assert::IsPresent("man_")),// mandate id starting with man_ Event::Assert(Assert::IsPresent("man_")),// mandate id starting with man_
Event::Trigger(Trigger::Click(By::Css("#pm-mandate-btn a"))), Event::Trigger(Trigger::Click(By::Css("#pm-mandate-btn a"))),
Event::Trigger(Trigger::Click(By::Id("pay-with-mandate-btn"))), Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
Event::Assert(Assert::IsPresent("succeeded")), Event::Assert(Assert::IsPresent("succeeded")),
]).await?; ]).await?;
Ok(()) Ok(())
@ -147,6 +144,12 @@ async fn should_make_stripe_klarna_payment(c: WebDriver) -> Result<(), WebDriver
Event::Trigger(Trigger::Click(By::Css( Event::Trigger(Trigger::Click(By::Css(
"button[data-testid='confirm-and-pay']", "button[data-testid='confirm-and-pay']",
))), ))),
Event::RunIf(
Assert::IsPresent("Fewer clicks"),
vec![Event::Trigger(Trigger::Click(By::Css(
"button[data-testid='SmoothCheckoutPopUp:skip']",
)))],
),
Event::Trigger(Trigger::SwitchTab(Position::Prev)), Event::Trigger(Trigger::SwitchTab(Position::Prev)),
Event::Assert(Assert::IsPresent("Google")), Event::Assert(Assert::IsPresent("Google")),
Event::Assert(Assert::Contains( Event::Assert(Assert::Contains(
@ -356,21 +359,6 @@ async fn should_make_stripe_ach_bank_debit_payment(c: WebDriver) -> Result<(), W
Ok(()) 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("Status")),
Event::Assert(Assert::IsPresent("processing")),
],
)
.await?;
Ok(())
}
async fn should_make_stripe_sepa_bank_debit_payment(c: WebDriver) -> Result<(), WebDriverError> { async fn should_make_stripe_sepa_bank_debit_payment(c: WebDriver) -> Result<(), WebDriverError> {
let conn = StripeSeleniumTest {}; let conn = StripeSeleniumTest {};
conn.make_redirection_payment( conn.make_redirection_payment(
@ -412,12 +400,14 @@ fn should_make_3ds_mandate_with_zero_dollar_payment_test() {
#[test] #[test]
#[serial] #[serial]
#[ignore]
fn should_make_gpay_payment_test() { fn should_make_gpay_payment_test() {
tester!(should_make_gpay_payment); tester!(should_make_gpay_payment);
} }
#[test] #[test]
#[serial] #[serial]
#[ignore]
fn should_make_gpay_mandate_payment_test() { fn should_make_gpay_mandate_payment_test() {
tester!(should_make_gpay_mandate_payment); tester!(should_make_gpay_mandate_payment);
} }
@ -482,12 +472,6 @@ fn should_make_stripe_ach_bank_debit_payment_test() {
tester!(should_make_stripe_ach_bank_debit_payment); 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] #[test]
#[serial] #[serial]
fn should_make_stripe_sepa_bank_debit_payment_test() { fn should_make_stripe_sepa_bank_debit_payment_test() {