Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CHROME] find_element() -> Error(Json (Error ("invalid type: null, expected a string", line: 3, column: 19)) #35

Open
l1444 opened this issue Nov 21, 2020 · 2 comments

Comments

@l1444
Copy link

l1444 commented Nov 21, 2020

hello, I'm using the code that is provided in the documentation so this one:

let mut driver = WebDriver::new(Browser::Chrome);

driver.start_session();
driver.navigate("http://google.com");
let search_bar = driver.find_element(Selector::CSS, "input[maxlength=\"2048\"]").unwrap();

search_bar.type_text("selenium-rs github");
let search_button = driver.find_element(Selector::CSS, "input[name=\"btnK\"]").unwrap();
search_button.click();

and it shows me this error:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error(Json(Error("invalid type: null, expected a string", line: 3, column: 19)))', src\main.rs:20:71
@l1444 l1444 changed the title [CHROME]find_element () -> Error(Json (Error ("invalid type: null, expected a string", line: 3, column: 19)) [CHROME] find_element() -> Error(Json (Error ("invalid type: null, expected a string", line: 3, column: 19)) Nov 21, 2020
@blesson3
Copy link

I'm seeing that the selenium-rs is not communicating well with the the local Selenium API. It's returning sessionId: null to selenium-rs when trying to find an element, which selenium-rs requires in the response (ElementResponse). I have a fix incoming, but it's relatively large and changes some semantics.

As an aside: does anyone have a reference to the standalone Selenium server REST API (for selenium-server-standalone-3.141.59.jar)? It would be incredibly useful for this fix. I seem to be unable to find it in ~10m of web searching.

@nixpulvis
Copy link

nixpulvis commented Feb 21, 2021

Here's a hacky workaround I whipped up (sorry for the whitespace changes). I only updated find_elements but the same hack can be applied to other functions I'm sure.

diff --git a/src/element.rs b/src/element.rs
index 743064b..8ff48ce 100644
--- a/src/element.rs
+++ b/src/element.rs
@@ -1,13 +1,13 @@
-/*! 
+/*!
 
     Element enables most of the site interaction, and wraps user interactions such as typing text and clicking
     on things. Note that each element is tied to the specific session (currently, we
     can't hold on to the same element across sessions).
 
 
-    # Example - Inspecting attributes of an element 
+    # Example - Inspecting attributes of an element
 
-    ```rust 
+    ```rust
         use selenium_rs::webdriver::{Selector, Browser, WebDriver};
         use selenium_rs::element::Element;
 
@@ -43,6 +43,11 @@ impl<'a> Element<'a> {
             client,
         }
     }
+
+    pub fn set_session_id(&mut self, session_id: String) {
+        self.session_id = session_id;
+    }
 }
 
 // Contains implementation for attribute interaction for the element
diff --git a/src/element_structs.rs b/src/element_structs.rs
index ff8cf36..e22a47e 100644
--- a/src/element_structs.rs
+++ b/src/element_structs.rs
@@ -1,3 +1,4 @@
+use std::collections::HashMap;
 use element::Element;
 use reqwest;
 
@@ -11,29 +12,24 @@ pub struct SelectedResponse {
 #[derive(Deserialize)]
 pub struct ElementResponse {
     #[serde(rename = "sessionId")]
-    session_id: String,
+    session_id: Option<String>,
     status: i32,
-    value: ElemValue,
+    value: HashMap<String, String>,
 }
 
 #[allow(dead_code)]
-#[derive(Deserialize)]
+#[derive(Deserialize, Debug)]
 pub struct ElementsResponse {
     #[serde(rename = "sessionId")]
-    session_id: String,
+    session_id: Option<String>,
     status: i32,
-    value: Vec<ElemValue>,
-}
-
-#[derive(Deserialize)]
-struct ElemValue {
-    #[serde(rename = "ELEMENT")]
-    element_id: String,
+    value: Vec<HashMap<String, String>>,
 }
 
 impl<'a> ElementResponse {
     pub fn parse_into_element(self, client: &'a reqwest::Client) -> Element<'a> {
-        Element::new(self.value.element_id, self.session_id, client)
+        let element_id = self.value.values().next().expect("one element");
+        Element::new(element_id.clone(), self.session_id.as_ref().map_or("null".to_string(), |id| id.clone()), client)
     }
 }
 
@@ -42,7 +38,10 @@ impl<'a> ElementsResponse {
         let session_id = self.session_id;
         self.value
             .into_iter()
-            .map(|value| Element::new(value.element_id, session_id.clone(), client))
+            .map(|value| {
+                let element_id = value.values().next().expect("one element");
+                Element::new(element_id.clone(), session_id.as_ref().map_or("null".to_string(), |id| id.clone()), client)
+            })
             .collect()
     }
 }
@@ -51,7 +50,7 @@ impl<'a> ElementsResponse {
 #[derive(Deserialize)]
 pub struct AttributeResponse {
     #[serde(rename = "sessionId")]
-    session_id: String,
+    session_id: Option<String>,
     pub value: String,
 }
 
diff --git a/src/webdriver.rs b/src/webdriver.rs
index ddc270e..47a0196 100644
--- a/src/webdriver.rs
+++ b/src/webdriver.rs
@@ -199,13 +199,17 @@ impl WebDriver {
         let sess_id = self.session_id.clone().unwrap();
         let url = construct_url(vec!["session/", &(sess_id + "/"), "elements"]);
         let payload = ElementRequest::new(str_for_selector(selector), query.to_string());
         let response: ElementsResponse = self.client
             .post(url)
             .json(&payload)
             .send()?
             .error_for_status()?
             .json()?;
-        let elements = response.parse_into_elements(&self.client);
+        let mut elements = response.parse_into_elements(&self.client);
+        for element in &mut elements {
+            element.set_session_id(self.session_id.clone().unwrap());
+        }
         Ok(elements)
     }
 }

As an aside: does anyone have a reference to the standalone Selenium server REST API [...]?

I'm struggling without this too! The fundamental issue I don't really understand is why the sessionId field is null, or why an element needs it's own session id at all. But I'm not really that knowledgeable of Selenium, I just use it occasionally.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants