From 8179b440004ef289cbcd09fc9614f32041a3bba5 Mon Sep 17 00:00:00 2001 From: ibrahim Hamzat Date: Tue, 4 Jun 2024 02:31:25 +0100 Subject: [PATCH 1/7] modify cli and add yam dsl for browser e2e --- Cargo.toml | 2 ++ browser-test.tk.yaml | 35 +++++++++++++++++++++++++++++++++++ src/base_cli.rs | 9 ++++++++- 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 browser-test.tk.yaml diff --git a/Cargo.toml b/Cargo.toml index f6d9a61..224eff1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,3 +37,5 @@ walkdir = "2.3.3" [dev-dependencies] httpmock = "0.7" testing_logger = "0.1.1" + +[workspace] \ No newline at end of file diff --git a/browser-test.tk.yaml b/browser-test.tk.yaml new file mode 100644 index 0000000..9f7f320 --- /dev/null +++ b/browser-test.tk.yaml @@ -0,0 +1,35 @@ +- name: "Login To Talstack" + description: "test login" + steps: + - visit: "http://localhost:8080" + - find: ".social-button_SocialButton__C6hcE" + click: true + - wait: 2000 + - find_xpath: "//*[@id ="identifierId"]" + type_text: "bjhfh@talsatck.com" + - wait: 2000 + - find_xpath: "//*[@id ="identifierNext"]" + click: true + - wait: 2000 + - find_xpath: "//*[@id ="password"]/div[1]/div / div[1]/input" + type_text: "drgddg" + - find_xpath: "//*[@id ="passwordNext"]" + click: true + - wait: 10000 + +# - name: "Google Search" +# description: "test google search" +# steps: +# - visit: "https://www.google.com/" +# - find: ".gLFyf" +# type_text: "hello world" +# - wait: 2000 +# - find: ".gNO89b" +# click : true +# - wait: 10000 + # - find: "#search" + # - assert: + # - array: ".g" + # - empty: ".non-existent-class" + # - string: "h3" + # - equal: "input[name='q'] == 'test query'" diff --git a/src/base_cli.rs b/src/base_cli.rs index 7ec53e9..e2060e1 100644 --- a/src/base_cli.rs +++ b/src/base_cli.rs @@ -5,7 +5,7 @@ use std::path::PathBuf; #[command(name = "testkit")] #[command(author = "APIToolkit. ")] #[command(version = "1.0")] -#[command(about = "Manually and Automated testing starting with APIs", long_about = None)] +#[command(about = "Manually and Automated testing starting with APIs and Browser", long_about = None)] pub struct Cli { #[command(subcommand)] pub command: Option, @@ -18,6 +18,13 @@ pub struct Cli { #[derive(Subcommand)] pub enum Commands { Test { + /// Run browser tests + #[arg(short = 'i', long)] + api: bool, + + #[arg(short = 'b', long)] + browser: bool, + /// Sets the YAML test configuration file #[arg(short, long)] file: Option, From 5da38bd6d8fea875960aba91d2aac2a09115ef1d Mon Sep 17 00:00:00 2001 From: ibrahim Hamzat Date: Tue, 4 Jun 2024 02:35:34 +0100 Subject: [PATCH 2/7] add base browser --- .DS_Store | Bin 6148 -> 6148 bytes .gitignore | 1 + src/base_browser.rs | 0 src/main.rs | 36 +++++++++++++++++++++++++++++++++--- 4 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 src/base_browser.rs diff --git a/.DS_Store b/.DS_Store index 1f0997236e4bc3dc5c68fb297744fd78c094a760..4bf558b8cbda996f9d455eb54b75c59e7d4c6e1b 100644 GIT binary patch delta 256 zcmZoMXfc@JFUrfnz`)4BAi%&-%#g}Z#GuPi!jQUIkYhQsCrC-`4<28PKzEZK@246Y0nV6_DdIY6t5 zQFSmoPtIU*hk)IsGsTq&0lrW?+6f=}ezQ8KM#^4ClKX3CpR!OFb4QDp9bNuB80Da*Wd;kCd diff --git a/.gitignore b/.gitignore index 7a83b9c..712b023 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ node_modules/ .vscode .env +.DS_Store \ No newline at end of file diff --git a/src/base_browser.rs b/src/base_browser.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/main.rs b/src/main.rs index f60a327..55d7849 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,9 @@ -#![feature(extend_one)] +pub mod base_browser; pub mod base_cli; pub mod base_request; + use anyhow::Ok; +use base_browser::TestCase; use base_cli::Commands; use base_request::{RequestResult, TestContext}; use clap::Parser; @@ -32,11 +34,18 @@ async fn main() { match cli_instance.command { None | Some(Commands::App {}) => {} - Some(Commands::Test { file }) => cli(file).await.unwrap(), + Some(Commands::Test { file, api, browser }) => { + if api { + cli_api(file.clone()).await.unwrap(); + } + if browser { + cli_browser(file).await.unwrap(); + } + } } } -async fn cli(file_op: Option) -> Result<(), anyhow::Error> { +async fn cli_api(file_op: Option) -> Result<(), anyhow::Error> { match file_op { Some(file) => { let content = fs::read_to_string(file.clone())?; @@ -64,6 +73,27 @@ async fn cli(file_op: Option) -> Result<(), anyhow::Error> { } } +async fn cli_browser(file_op: Option) -> Result<(), anyhow::Error> { + match file_op { + Some(file) => { + let content = fs::read_to_string(file.clone()).expect("Unable to read file"); + let test_cases: Vec = + serde_yaml::from_str(&content).expect("Unable to parse YAML"); + let _ = base_browser::run_browser_tests(&test_cases).await?; + } + None => { + let files = find_tk_yaml_files(Path::new(".")); + for file in files { + let content = fs::read_to_string(file.clone()).expect("Unable to read file"); + let test_cases: Vec = + serde_yaml::from_str(&content).expect("Unable to parse YAML"); + base_browser::run_browser_tests(&test_cases).await?; + } + } + } + Ok(()) +} + fn find_tk_yaml_files(dir: &Path) -> Vec { let mut result = Vec::new(); for entry in WalkDir::new(dir).into_iter().filter_map(|e| e.ok()) { From b76b6dcc807f30b4ff40179f54fdda98df78bdbf Mon Sep 17 00:00:00 2001 From: ibrahim Hamzat Date: Tue, 4 Jun 2024 02:36:04 +0100 Subject: [PATCH 3/7] add base browser --- src/base_browser.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/base_browser.rs b/src/base_browser.rs index e69de29..8b13789 100644 --- a/src/base_browser.rs +++ b/src/base_browser.rs @@ -0,0 +1 @@ + From d16dab286900957d9351056c6f61fceffe86cf6e Mon Sep 17 00:00:00 2001 From: ibrahim Hamzat Date: Tue, 4 Jun 2024 02:38:44 +0100 Subject: [PATCH 4/7] modify base browser --- Cargo.toml | 1 + src/base_browser.rs | 143 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 224eff1..55ca7b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ serde_with = "3.0.0" colored_json = "5" chrono = "0.4.26" walkdir = "2.3.3" +fantoccini = "0.19.3" # core-foundation = {git="https://github.com/servo/core-foundation-rs", rev="9effb788767458ad639ce36229cc07fd3b1dc7ba"} [dev-dependencies] diff --git a/src/base_browser.rs b/src/base_browser.rs index 8b13789..6892471 100644 --- a/src/base_browser.rs +++ b/src/base_browser.rs @@ -1 +1,144 @@ +use fantoccini::{Client, Locator}; +use serde::{Deserialize, Serialize}; +use std::{fs, time::Duration}; +use tokio; + +#[derive(Deserialize, Serialize, Debug)] +pub struct TestStep { + visit: Option, + find: Option, + find_xpath: Option, + #[serde(default)] + type_text: Option, + #[serde(default)] + click: Option, + #[serde(default)] + wait: Option, + assert: Option>, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +pub struct Assertion { + array: Option, + array_xpath: Option, + empty: Option, + empty_xpath: Option, + string: Option, + string_xpath: Option, + equal: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct TestCase { + name: String, + description: String, + steps: Vec, +} + +pub async fn run_browser_tests( + test_cases: &Vec, +) -> Result<(), fantoccini::error::CmdError> { + println!("Running browser tests..."); + + let mut client = Client::new("http://localhost:4444") + .await + .expect("Failed to connect to WebDriver"); + + for test_case in test_cases { + println!("Executing test case: {}", test_case.name); + for step in &test_case.steps { + if let Some(url) = &step.visit { + client.goto(url).await?; + } + + if let Some(selector) = &step.find { + let element = client.find(Locator::Css(selector)).await?; + if let Some(text) = &step.type_text { + element.send_keys(text).await?; + } + if step.click.unwrap_or(false) { + element.click().await?; + } + } + + if let Some(xpath) = &step.find_xpath { + let element = client.find(Locator::XPath(xpath)).await?; + if let Some(text) = &step.type_text { + element.send_keys(text).await?; + } + if step.click.unwrap_or(false) { + element.click().await?; + } + } + + if let Some(duration) = step.wait { + tokio::time::sleep(Duration::from_millis(duration)).await; + } + + if let Some(assertions) = &step.assert { + for assertion in assertions { + if let Some(selector) = &assertion.array { + let elements = client.find_all(Locator::Css(selector)).await?; + assert!(!elements.is_empty(), "Expected array but found none"); + } + + if let Some(xpath) = &assertion.array_xpath { + let elements = client.find_all(Locator::XPath(xpath)).await?; + assert!(!elements.is_empty(), "Expected array but found none"); + } + + if let Some(selector) = &assertion.empty { + let elements = client.find_all(Locator::Css(selector)).await?; + assert!(elements.is_empty(), "Expected no elements but found some"); + } + + if let Some(xpath) = &assertion.empty_xpath { + let elements = client.find_all(Locator::XPath(xpath)).await?; + assert!(elements.is_empty(), "Expected no elements but found some"); + } + + if let Some(selector) = &assertion.string { + let element = client.find(Locator::Css(selector)).await?; + let text = element.text().await?; + assert!( + text.parse::().is_ok(), + "Expected string but found something else" + ); + } + + if let Some(xpath) = &assertion.string_xpath { + let element = client.find(Locator::XPath(xpath)).await?; + let text = element.text().await?; + assert!( + text.parse::().is_ok(), + "Expected string but found something else" + ); + } + + if let Some(equal) = &assertion.equal { + let parts: Vec<&str> = equal.split("==").collect(); + if parts.len() == 2 { + let locator = parts[0].trim(); + let expected_value = parts[1].trim().trim_matches('"'); + let element = if locator.starts_with('/') { + client.find(Locator::XPath(locator)).await? + } else { + client.find(Locator::Css(locator)).await? + }; + let text = element.text().await?; + assert_eq!( + text, expected_value, + "Expected '{}' but found '{}'", + expected_value, text + ); + } + } + } + } + } + } + + client.close().await?; + Ok(()) +} From 33bc14375a936a703290af3b4d0fa4c2633a96ff Mon Sep 17 00:00:00 2001 From: ibrahim Hamzat Date: Tue, 4 Jun 2024 02:38:56 +0100 Subject: [PATCH 5/7] modify base browser --- src/base_browser.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/base_browser.rs b/src/base_browser.rs index 6892471..7b8905f 100644 --- a/src/base_browser.rs +++ b/src/base_browser.rs @@ -1,4 +1,3 @@ - use fantoccini::{Client, Locator}; use serde::{Deserialize, Serialize}; use std::{fs, time::Duration}; From 19b1d8e8600f53b306e5ece42adf764d5731aa28 Mon Sep 17 00:00:00 2001 From: ibrahim Hamzat Date: Wed, 26 Jun 2024 09:05:32 +0100 Subject: [PATCH 6/7] improve dsl and runner --- Cargo.toml | 2 +- browser-test.tk.yaml | 75 +++++++------- src/base_browser.rs | 226 +++++++++++++++++++++++++------------------ src/base_request.rs | 3 +- src/lib.rs | 2 +- src/main.rs | 10 +- 6 files changed, 181 insertions(+), 137 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 55ca7b5..bcf04e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ serde_with = "3.0.0" colored_json = "5" chrono = "0.4.26" walkdir = "2.3.3" -fantoccini = "0.19.3" +thirtyfour = "0.32.0" # core-foundation = {git="https://github.com/servo/core-foundation-rs", rev="9effb788767458ad639ce36229cc07fd3b1dc7ba"} [dev-dependencies] diff --git a/browser-test.tk.yaml b/browser-test.tk.yaml index 9f7f320..f84082a 100644 --- a/browser-test.tk.yaml +++ b/browser-test.tk.yaml @@ -1,35 +1,40 @@ -- name: "Login To Talstack" - description: "test login" - steps: - - visit: "http://localhost:8080" - - find: ".social-button_SocialButton__C6hcE" - click: true - - wait: 2000 - - find_xpath: "//*[@id ="identifierId"]" - type_text: "bjhfh@talsatck.com" - - wait: 2000 - - find_xpath: "//*[@id ="identifierNext"]" - click: true - - wait: 2000 - - find_xpath: "//*[@id ="password"]/div[1]/div / div[1]/input" - type_text: "drgddg" - - find_xpath: "//*[@id ="passwordNext"]" - click: true - - wait: 10000 - -# - name: "Google Search" -# description: "test google search" -# steps: -# - visit: "https://www.google.com/" -# - find: ".gLFyf" -# type_text: "hello world" -# - wait: 2000 -# - find: ".gNO89b" -# click : true -# - wait: 10000 - # - find: "#search" - # - assert: - # - array: ".g" - # - empty: ".non-existent-class" - # - string: "h3" - # - equal: "input[name='q'] == 'test query'" +- metadata: + name: Login To Talstack + description: test login + headless: false + browser: chrome + groups: + - group: Login to Talstack + steps: + - visit: 'app.talstack.com' + - find: .social-button_SocialButton__C6hcE + click: true + - wait: 2000 + - find_xpath: '//*[@id="identifierId"]' + type_text: bjhfh@talsatck.com + - wait: 2000 + - find_xpath: '//*[@id="identifierNext"]' + click: true + - wait: 2000 + - find_xpath: '//*[@id="password"]/div[1]/div/div[1]/input' + type_text: drgddg + - find_xpath: '//*[@id="passwordNext"]' + click: true + - wait: 10000 + - group: Register a user + steps: + - visit: 'http://localhost:8080' + - find: .social-button_SocialButton__C6hcE + click: true + - wait: 2000 + - find_xpath: '//*[@id="identifierId"]' + type_text: bjhfh@talsatck.com + - wait: 2000 + - find_xpath: '//*[@id="identifierNext"]' + click: true + - wait: 2000 + - find_xpath: '//*[@id="password"]/div[1]/div/div[1]/input' + type_text: drgddg + - find_xpath: '//*[@id="passwordNext"]' + click: true + - wait: 10000 diff --git a/src/base_browser.rs b/src/base_browser.rs index 7b8905f..83bf314 100644 --- a/src/base_browser.rs +++ b/src/base_browser.rs @@ -1,7 +1,10 @@ -use fantoccini::{Client, Locator}; +use std::time::Duration; + +use anyhow::Result; use serde::{Deserialize, Serialize}; -use std::{fs, time::Duration}; -use tokio; +use thirtyfour::prelude::*; +use thirtyfour::DesiredCapabilities; + #[derive(Deserialize, Serialize, Debug)] pub struct TestStep { @@ -16,8 +19,7 @@ pub struct TestStep { wait: Option, assert: Option>, } - -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +#[derive(Debug, Serialize, Deserialize)] pub struct Assertion { array: Option, array_xpath: Option, @@ -29,115 +31,153 @@ pub struct Assertion { } #[derive(Debug, Serialize, Deserialize)] -pub struct TestCase { - name: String, - description: String, +pub struct TestItem { + metadata: Option, + groups: Vec, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Metadata { + name: Option, + description: Option, + headless: Option, + browser: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Group { + group: String, steps: Vec, } -pub async fn run_browser_tests( - test_cases: &Vec, -) -> Result<(), fantoccini::error::CmdError> { - println!("Running browser tests..."); +#[derive(Debug, Default, Serialize)] +pub struct RequestResult { + pub step_name: Option, + pub step_index: u32, +} +pub async fn run_browser( + test_cases: &Vec, + should_log: bool, +) -> Result, Box> { + + let mut driver = None; + + // Find the metadata to configure the browser + for (i, item) in test_cases.iter().enumerate() { + if let Some(metadata) = &item.metadata { + log::debug!("running on : {:?}", metadata.browser); + + driver = match &metadata.browser { + Some(browser_str) => { + let caps = match browser_str.as_str() { + "firefox" => { + println!("Initializing Firefox"); + let mut caps = DesiredCapabilities::firefox(); + if metadata.headless.unwrap_or(false) { + caps.set_headless()?; + } + caps + }, + _ => { + println!("Unrecognized browser '{}', defaulting to Firefox", browser_str); + let mut caps = DesiredCapabilities::firefox(); + if metadata.headless.unwrap_or(false) { + caps.set_headless()?; + } + caps + } + }; + + Some(WebDriver::new("http://localhost:4444", caps).await?) + }, + None => { + println!("No browser specified, defaulting to Firefox"); + let mut caps = DesiredCapabilities::firefox(); + if metadata.headless.unwrap_or(false) { + caps.set_headless()?; + } + Some(WebDriver::new("http://localhost:4444", caps).await?) + } + }; + + break; + } + } + + if driver.is_none() { + log::debug!("No driver configuration found in metadata"); + } + + let driver = driver.unwrap(); + - let mut client = Client::new("http://localhost:4444") - .await - .expect("Failed to connect to WebDriver"); + let mut all_results = Vec::new(); for test_case in test_cases { - println!("Executing test case: {}", test_case.name); - for step in &test_case.steps { - if let Some(url) = &step.visit { - client.goto(url).await?; + + let result = base_browser(test_case, driver.clone()).await; + match result { + Ok(mut res) => { + if should_log { + log::debug!("Test passed: {:?}", res); + } + all_results.append(&mut res); + } + Err(err) => { + if should_log { + log::error!(target: "testkit", "{}", err); + } + return Err(err); } + } + } + + Ok(all_results) +} + +pub async fn base_browser( + test_item: &TestItem, + client: WebDriver, +) -> Result, Box> { + let mut results: Vec = Vec::new(); + for (i, group) in test_item.groups.iter().enumerate() { + println!("Running group: {:?}", group.group); + + for (j, step) in group.steps.iter().enumerate() { + if let Some(url) = &step.visit { + client.get(url).await?; + } if let Some(selector) = &step.find { - let element = client.find(Locator::Css(selector)).await?; - if let Some(text) = &step.type_text { - element.send_keys(text).await?; - } + let element = client.find(By::Css(selector)).await?; if step.click.unwrap_or(false) { element.click().await?; } - } - - if let Some(xpath) = &step.find_xpath { - let element = client.find(Locator::XPath(xpath)).await?; if let Some(text) = &step.type_text { element.send_keys(text).await?; } + + } + if let Some(xpath) = &step.find_xpath { + let element = client.find(By::XPath(xpath)).await?; if step.click.unwrap_or(false) { element.click().await?; } + if let Some(text) = &step.type_text { + element.send_keys(text).await?; + } } - - if let Some(duration) = step.wait { - tokio::time::sleep(Duration::from_millis(duration)).await; + if let Some(wait_time) = step.wait { + tokio::time::sleep(Duration::from_millis(wait_time)).await; } - if let Some(assertions) = &step.assert { - for assertion in assertions { - if let Some(selector) = &assertion.array { - let elements = client.find_all(Locator::Css(selector)).await?; - assert!(!elements.is_empty(), "Expected array but found none"); - } - - if let Some(xpath) = &assertion.array_xpath { - let elements = client.find_all(Locator::XPath(xpath)).await?; - assert!(!elements.is_empty(), "Expected array but found none"); - } - - if let Some(selector) = &assertion.empty { - let elements = client.find_all(Locator::Css(selector)).await?; - assert!(elements.is_empty(), "Expected no elements but found some"); - } - - if let Some(xpath) = &assertion.empty_xpath { - let elements = client.find_all(Locator::XPath(xpath)).await?; - assert!(elements.is_empty(), "Expected no elements but found some"); - } - - if let Some(selector) = &assertion.string { - let element = client.find(Locator::Css(selector)).await?; - let text = element.text().await?; - assert!( - text.parse::().is_ok(), - "Expected string but found something else" - ); - } - - if let Some(xpath) = &assertion.string_xpath { - let element = client.find(Locator::XPath(xpath)).await?; - let text = element.text().await?; - assert!( - text.parse::().is_ok(), - "Expected string but found something else" - ); - } - - if let Some(equal) = &assertion.equal { - let parts: Vec<&str> = equal.split("==").collect(); - if parts.len() == 2 { - let locator = parts[0].trim(); - let expected_value = parts[1].trim().trim_matches('"'); - let element = if locator.starts_with('/') { - client.find(Locator::XPath(locator)).await? - } else { - client.find(Locator::Css(locator)).await? - }; - let text = element.text().await?; - assert_eq!( - text, expected_value, - "Expected '{}' but found '{}'", - expected_value, text - ); - } - } - } - } + results.push(RequestResult { + step_name: Some(format!("{} - step {}", group.group, j)), + step_index: i as u32, + }); } } - client.close().await?; - Ok(()) -} + client.quit().await?; + Ok(results) +} \ No newline at end of file diff --git a/src/base_request.rs b/src/base_request.rs index 14fb5f1..ce05894 100644 --- a/src/base_request.rs +++ b/src/base_request.rs @@ -6,8 +6,7 @@ use reqwest::header::{HeaderMap, HeaderValue}; use rhai::Engine; use serde::{Deserialize, Serialize}; use serde_json::Value; -use serde_with::{serde_as, DisplayFromStr}; -use serde_yaml::with; +use serde_with::{serde_as}; use std::{collections::HashMap, env, env::VarError}; use thiserror::Error; diff --git a/src/lib.rs b/src/lib.rs index 2f83334..fb182c3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ use base_request::{RequestResult, TestContext}; use libc::c_char; -use std::ffi::{CStr, CString}; +use std::ffi::{CStr}; pub mod base_cli; pub mod base_request; diff --git a/src/main.rs b/src/main.rs index 55d7849..1470443 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ pub mod base_cli; pub mod base_request; use anyhow::Ok; -use base_browser::TestCase; +use base_browser::TestItem; use base_cli::Commands; use base_request::{RequestResult, TestContext}; use clap::Parser; @@ -77,17 +77,17 @@ async fn cli_browser(file_op: Option) -> Result<(), anyhow::Error> { match file_op { Some(file) => { let content = fs::read_to_string(file.clone()).expect("Unable to read file"); - let test_cases: Vec = + let test_cases: Vec = serde_yaml::from_str(&content).expect("Unable to parse YAML"); - let _ = base_browser::run_browser_tests(&test_cases).await?; + let _ = base_browser::run_browser(&test_cases, true).await; } None => { let files = find_tk_yaml_files(Path::new(".")); for file in files { let content = fs::read_to_string(file.clone()).expect("Unable to read file"); - let test_cases: Vec = + let test_cases: Vec = serde_yaml::from_str(&content).expect("Unable to parse YAML"); - base_browser::run_browser_tests(&test_cases).await?; + base_browser::run_browser(&test_cases, true).await; } } } From 46c7ef46dc36734c284d7f847067784d06bf85c6 Mon Sep 17 00:00:00 2001 From: ibrahim Hamzat Date: Wed, 26 Jun 2024 09:11:47 +0100 Subject: [PATCH 7/7] improve dsl and runner --- browser-test.tk.yaml | 23 +++++------------------ src/base_browser.rs | 26 ++++++++++++-------------- src/base_request.rs | 2 +- src/lib.rs | 2 +- 4 files changed, 19 insertions(+), 34 deletions(-) diff --git a/browser-test.tk.yaml b/browser-test.tk.yaml index f84082a..af8fa36 100644 --- a/browser-test.tk.yaml +++ b/browser-test.tk.yaml @@ -2,7 +2,7 @@ name: Login To Talstack description: test login headless: false - browser: chrome + browser: firefox groups: - group: Login to Talstack steps: @@ -11,30 +11,17 @@ click: true - wait: 2000 - find_xpath: '//*[@id="identifierId"]' - type_text: bjhfh@talsatck.com + type_text: random@tjs.com - wait: 2000 - find_xpath: '//*[@id="identifierNext"]' click: true - wait: 2000 - find_xpath: '//*[@id="password"]/div[1]/div/div[1]/input' - type_text: drgddg + type_text: "loleremm" - find_xpath: '//*[@id="passwordNext"]' click: true - wait: 10000 - group: Register a user steps: - - visit: 'http://localhost:8080' - - find: .social-button_SocialButton__C6hcE - click: true - - wait: 2000 - - find_xpath: '//*[@id="identifierId"]' - type_text: bjhfh@talsatck.com - - wait: 2000 - - find_xpath: '//*[@id="identifierNext"]' - click: true - - wait: 2000 - - find_xpath: '//*[@id="password"]/div[1]/div/div[1]/input' - type_text: drgddg - - find_xpath: '//*[@id="passwordNext"]' - click: true - - wait: 10000 + - visit: 'app.talstack.com/' + diff --git a/src/base_browser.rs b/src/base_browser.rs index 83bf314..8fe802a 100644 --- a/src/base_browser.rs +++ b/src/base_browser.rs @@ -5,7 +5,6 @@ use serde::{Deserialize, Serialize}; use thirtyfour::prelude::*; use thirtyfour::DesiredCapabilities; - #[derive(Deserialize, Serialize, Debug)] pub struct TestStep { visit: Option, @@ -59,14 +58,13 @@ pub async fn run_browser( test_cases: &Vec, should_log: bool, ) -> Result, Box> { - let mut driver = None; // Find the metadata to configure the browser for (i, item) in test_cases.iter().enumerate() { if let Some(metadata) = &item.metadata { log::debug!("running on : {:?}", metadata.browser); - + driver = match &metadata.browser { Some(browser_str) => { let caps = match browser_str.as_str() { @@ -77,9 +75,12 @@ pub async fn run_browser( caps.set_headless()?; } caps - }, + } _ => { - println!("Unrecognized browser '{}', defaulting to Firefox", browser_str); + println!( + "Unrecognized browser '{}', defaulting to Firefox", + browser_str + ); let mut caps = DesiredCapabilities::firefox(); if metadata.headless.unwrap_or(false) { caps.set_headless()?; @@ -87,9 +88,9 @@ pub async fn run_browser( caps } }; - + Some(WebDriver::new("http://localhost:4444", caps).await?) - }, + } None => { println!("No browser specified, defaulting to Firefox"); let mut caps = DesiredCapabilities::firefox(); @@ -99,22 +100,20 @@ pub async fn run_browser( Some(WebDriver::new("http://localhost:4444", caps).await?) } }; - + break; } } - + if driver.is_none() { log::debug!("No driver configuration found in metadata"); } - - let driver = driver.unwrap(); + let driver = driver.unwrap(); let mut all_results = Vec::new(); for test_case in test_cases { - let result = base_browser(test_case, driver.clone()).await; match result { Ok(mut res) => { @@ -156,7 +155,6 @@ pub async fn base_browser( if let Some(text) = &step.type_text { element.send_keys(text).await?; } - } if let Some(xpath) = &step.find_xpath { let element = client.find(By::XPath(xpath)).await?; @@ -180,4 +178,4 @@ pub async fn base_browser( client.quit().await?; Ok(results) -} \ No newline at end of file +} diff --git a/src/base_request.rs b/src/base_request.rs index ce05894..472658e 100644 --- a/src/base_request.rs +++ b/src/base_request.rs @@ -6,7 +6,7 @@ use reqwest::header::{HeaderMap, HeaderValue}; use rhai::Engine; use serde::{Deserialize, Serialize}; use serde_json::Value; -use serde_with::{serde_as}; +use serde_with::serde_as; use std::{collections::HashMap, env, env::VarError}; use thiserror::Error; diff --git a/src/lib.rs b/src/lib.rs index fb182c3..9f1c4a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ use base_request::{RequestResult, TestContext}; use libc::c_char; -use std::ffi::{CStr}; +use std::ffi::CStr; pub mod base_cli; pub mod base_request;