Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/target
/webdrivers
/webdrivers
/docs
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions webdriver-downloader-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
[package]
name = "webdriver-downloader-cli"
version = "0.5.18"
version = "0.5.20"
edition = "2021"
authors = ["ik1ne <[email protected]>"]
description = "Cli for webdriver download."
repository = "https://github.com/ik1ne/webdriver-downloader"
homepage = "https://github.com/ik1ne/webdriver-downloader"
license = "MIT"
readme = "README.md"
keywords = ["webdriver-downloader", "webdriver", "chromedriver", "geckodriver"]
keywords = ["webdriver-downloader", "webdriver", "chromedriver", "geckodriver", "edgedriver"]
categories = ["command-line-utilities", "web-programming"]

[[bin]]
Expand All @@ -21,7 +21,7 @@ clap = { version = "4", features = ["cargo", "string"] }
tokio = "1"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
webdriver-downloader = { version = "0.16", path = "../webdriver-downloader", default-features = false }
webdriver-downloader = { version = "0.16.2", path = "../webdriver-downloader", default-features = false }

[dev-dependencies]
assert_cmd = "2"
Expand Down
5 changes: 3 additions & 2 deletions webdriver-downloader-cli/src/cli/build_arg.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::path::{Path, PathBuf};

use anyhow::Result;
use clap::{arg, command, value_parser, ArgMatches, Arg, ArgAction};
use clap::{arg, command, value_parser, Arg, ArgAction, ArgMatches};

use super::{Args, DriverType};

Expand All @@ -10,7 +10,7 @@ pub(super) fn get_args() -> Result<Args> {
.arg(
arg!(--type <TYPE> "driver type")
.default_value("chrome")
.value_parser(["chrome", "gecko"]),
.value_parser(["chrome", "edge", "gecko"]),
)
.arg(
arg!(--driver <PATH> "driver path")
Expand Down Expand Up @@ -69,6 +69,7 @@ fn get_driver_type(matches: &ArgMatches) -> DriverType {

match browser_type.as_str() {
"chrome" => DriverType::Chrome,
"edge" => DriverType::Edge,
"gecko" => DriverType::Gecko,
_ => panic!("Unexpected argument value of \"type\". {:?}", browser_type),
}
Expand Down
3 changes: 3 additions & 0 deletions webdriver-downloader-cli/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ pub(crate) struct Args {
#[derive(Debug, Copy, Clone)]
pub(crate) enum DriverType {
Chrome,
Edge,
Gecko,
}

impl DriverType {
fn default_driver_install_path(&self) -> Result<PathBuf, os_specific::DefaultPathError> {
match self {
DriverType::Chrome => os_specific::chromedriver::default_driver_path(),
DriverType::Edge => os_specific::edgedriver::default_driver_path(),
DriverType::Gecko => os_specific::geckodriver::default_driver_path(),
}
}
Expand All @@ -43,6 +45,7 @@ impl DriverType {
os_specific::chromedriver_old::default_browser_path()
}
}
DriverType::Edge => os_specific::edgedriver::default_browser_path(),
DriverType::Gecko => os_specific::geckodriver::default_browser_path(),
}
}
Expand Down
12 changes: 12 additions & 0 deletions webdriver-downloader-cli/src/cli/run.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use webdriver_downloader::driver_impls::chromedriver_info::ChromedriverInfo;
use webdriver_downloader::driver_impls::edgedriver_info::EdgedriverInfo;

use super::build_arg::*;
use super::check_arg::*;
Expand All @@ -23,6 +24,17 @@ pub async fn run() -> anyhow::Result<String> {
)
.await
}
DriverType::Edge => {
let driver_info = EdgedriverInfo::new(args.driver_install_path, args.browser_path);

install(
&driver_info,
args.reinstall,
args.skip_verification,
args.num_tries,
)
.await
}
DriverType::Gecko => {
let driver_info = GeckodriverInfo::new(args.driver_install_path, args.browser_path);

Expand Down
4 changes: 2 additions & 2 deletions webdriver-downloader/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
[package]
name = "webdriver-downloader"
version = "0.16.0"
version = "0.16.4"
edition = "2021"
authors = ["ik1ne <[email protected]>"]
description = "Library for webdriver download."
repository = "https://github.com/ik1ne/webdriver-downloader"
homepage = "https://github.com/ik1ne/webdriver-downloader"
license = "MIT"
readme = "README.md"
keywords = ["webdriver-downloader", "webdriver", "chromedriver", "geckodriver"]
keywords = ["webdriver-downloader", "webdriver", "chromedriver", "geckodriver", "edgedriver"]
categories = ["web-programming"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
29 changes: 29 additions & 0 deletions webdriver-downloader/src/driver_impls/edgedriver_info/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use std::path::PathBuf;

use crate::os_specific;
use crate::os_specific::DefaultPathError;

mod trait_impls;

/// Information required to implement [WebdriverDownloadInfo](crate::prelude::WebdriverDownloadInfo) for Microsoft EdgeDriver.
#[derive(Debug)]
pub struct EdgedriverInfo {
pub driver_install_path: PathBuf,
pub browser_path: PathBuf,
}

impl EdgedriverInfo {
#[tracing::instrument]
pub fn new(driver_install_path: PathBuf, browser_path: PathBuf) -> Self {
EdgedriverInfo {
driver_install_path,
browser_path,
}
}

pub fn new_default() -> Result<Self, DefaultPathError> {
let driver_install_path = os_specific::edgedriver::default_driver_path()?;
let browser_path = os_specific::edgedriver::default_browser_path()?;
Ok(EdgedriverInfo::new(driver_install_path, browser_path))
}
}
164 changes: 164 additions & 0 deletions webdriver-downloader/src/driver_impls/edgedriver_info/trait_impls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
use std::path::Path;

use async_trait::async_trait;
use fantoccini::wd::Capabilities;
use semver::Version;
use serde_json::{json, Map};

use crate::os_specific;
use crate::traits::installation_info::WebdriverInstallationInfo;
use crate::traits::url_info::{UrlError, WebdriverVersionUrl};
use crate::traits::verification_info::WebdriverVerificationInfo;
use crate::traits::version_req_url_info::{VersionReqError, VersionReqUrlInfo};

use super::EdgedriverInfo;

#[async_trait]
impl VersionReqUrlInfo for EdgedriverInfo {
fn binary_version(&self) -> Result<Version, VersionReqError> {
os_specific::edgedriver::binary_version(&self.browser_path)
}

async fn driver_version_urls(&self) -> Result<Vec<WebdriverVersionUrl>, UrlError> {
// For EdgeDriver, we need to match the browser version exactly
// EdgeDriver follows the same version as the Edge browser
let browser_version = self
.binary_version()
.map_err(|e| UrlError::Other(e.into()))?;

// Get the original full version string for the URL (with 4 components)
let original_version = os_specific::edgedriver::binary_version_string(&self.browser_path)
.map_err(|e| UrlError::Other(e.into()))?;

let url = os_specific::edgedriver::build_url(&original_version);

// EdgeDriver version must match browser version exactly
let version_req = format!("={}", browser_version)
.parse()
.map_err(|e: semver::Error| UrlError::Other(e.into()))?;

Ok(vec![WebdriverVersionUrl {
version_req,
webdriver_version: browser_version,
url,
}])
}
}

impl WebdriverInstallationInfo for EdgedriverInfo {
fn driver_install_path(&self) -> &Path {
&self.driver_install_path
}

fn driver_executable_name(&self) -> &'static str {
os_specific::edgedriver::DRIVER_EXECUTABLE_NAME
}
}

impl WebdriverVerificationInfo for EdgedriverInfo {
fn driver_capabilities(&self) -> Option<Capabilities> {
let capabilities_value = json!({
"binary": self.browser_path,
"args": ["--headless"],
"useAutomationExtension": false,
"excludeSwitches": ["enable-automation"],
});

let mut capabilities = Map::new();

// Use Microsoft Edge-specific capability key
capabilities.insert("ms:edgeOptions".to_string(), capabilities_value);

Some(capabilities)
}
}

#[cfg(test)]
mod tests {
use anyhow::Result;
use std::path::PathBuf;
use test_log::test;

use crate::prelude::EdgedriverInfo;
use crate::prelude::*;

#[test]
fn test_get_binary_version() -> Result<()> {
let browser_path = os_specific::edgedriver::default_browser_path()
.expect("Failed to get default browser path");

let edgedriver_info = EdgedriverInfo {
driver_install_path: "".into(),
browser_path,
};

// This test will only pass if Microsoft Edge is installed
if edgedriver_info.browser_path.exists() {
edgedriver_info.binary_version()?;
}

Ok(())
}

#[test]
fn test_driver_executable_name() {
let edgedriver_info = EdgedriverInfo {
driver_install_path: PathBuf::from("/tmp/test"),
browser_path: PathBuf::from("/tmp/edge"),
};

#[cfg(target_os = "windows")]
assert_eq!(edgedriver_info.driver_executable_name(), "msedgedriver.exe");

#[cfg(not(target_os = "windows"))]
assert_eq!(edgedriver_info.driver_executable_name(), "msedgedriver");
}

#[test]
fn test_driver_capabilities() {
let browser_path =
PathBuf::from("/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge");
let edgedriver_info = EdgedriverInfo {
driver_install_path: PathBuf::from("/tmp/test"),
browser_path: browser_path.clone(),
};

let capabilities = edgedriver_info.driver_capabilities();
assert!(capabilities.is_some());

let caps = capabilities.unwrap();
assert!(caps.contains_key("ms:edgeOptions"));

let edge_options = &caps["ms:edgeOptions"];
assert_eq!(
edge_options["binary"],
serde_json::Value::String(browser_path.to_string_lossy().to_string())
);
}

#[test]
fn test_build_url_format() {
let version = "141.0.3537.57";
let url = os_specific::edgedriver::build_url(version);

assert!(url.starts_with("https://msedgedriver.microsoft.com/"));
assert!(url.contains(version));
assert!(url.ends_with(".zip"));

// Check platform-specific URL suffix
#[cfg(all(target_os = "windows", target_arch = "x86"))]
assert!(url.contains("edgedriver_win32.zip"));

#[cfg(all(target_os = "windows", target_arch = "x86_64"))]
assert!(url.contains("edgedriver_win64.zip"));

#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
assert!(url.contains("edgedriver_mac64.zip"));

#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
assert!(url.contains("edgedriver_mac64_m1.zip"));

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
assert!(url.contains("edgedriver_linux64.zip"));
}
}
1 change: 1 addition & 0 deletions webdriver-downloader/src/driver_impls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
pub mod chromedriver_for_testing_info;
pub mod chromedriver_info;
pub mod chromedriver_old_info;
pub mod edgedriver_info;
pub mod geckodriver_info;
3 changes: 2 additions & 1 deletion webdriver-downloader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ pub mod traits;
/// necessary imports for using library provided driver implementations.
pub mod prelude {
pub use crate::driver_impls::{
chromedriver_info::ChromedriverInfo, geckodriver_info::GeckodriverInfo,
chromedriver_info::ChromedriverInfo, edgedriver_info::EdgedriverInfo,
geckodriver_info::GeckodriverInfo,
};
pub use crate::os_specific;
pub use crate::traits::installation_info::{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@ use which::{which, Error};

use crate::os_specific::DefaultPathError;

#[cfg(target_arch = "x86_64")]
pub const PLATFORM: &str = "linux64";

// Chrome for Testing does not support ARM64 on Linux yet
// ARM64 users should use EdgeDriver instead
#[cfg(target_arch = "aarch64")]
pub const PLATFORM: &str = "linux64"; // Will result in 404, but allows compilation

pub const DRIVER_EXECUTABLE_NAME: &str = "chromedriver";

pub const BROWSER_EXECUTABLE_NAMES: &[&str] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ use crate::os_specific::DefaultPathError;
#[cfg(target_arch = "x86")]
pub const PLATFORM: &str = "win32";

pub const DRIVER_EXECUTABLE_NAME: &str = "chromedriver";

#[cfg(target_arch = "x86_64")]
pub const PLATFORM: &str = "win64";

pub const DRIVER_EXECUTABLE_NAME: &str = "chromedriver";
#[cfg(target_arch = "aarch64")]
pub const PLATFORM: &str = "arm64";

pub fn default_browser_path() -> Result<PathBuf, DefaultPathError> {
let program_files = std::env::var("ProgramFiles")?;
Expand Down
Loading
Loading