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

Consider Supporting Selenium Grid WebDriver #378

Open
dpassen opened this issue Mar 3, 2022 · 10 comments
Open

Consider Supporting Selenium Grid WebDriver #378

dpassen opened this issue Mar 3, 2022 · 10 comments
Labels

Comments

@dpassen
Copy link

dpassen commented Mar 3, 2022

Using [etaoin "0.4.6"] and seleniarm/standalone-chromium:4.1.2-20220227 docker image,

(let [q {:tag :input :id "email"}]
    (etaoin/wait-exists driver q)
    [(etaoin/query driver q)
     (etaoin/query-all driver q)])

yields

[nil ["427cdc53-73a7-4a55-a98a-a6a05a650805"]]

This default multimethod does not find the value correctly, but the Safari and Firefox multimethods do.

@dpassen
Copy link
Author

dpassen commented Mar 7, 2022

When issuing a raw execute:

(let [q {:tag :input :id "email"}
        [loc term] (etaoin.query/expand driver q)]
    (-> (etaoin.api/execute
         {:driver driver
          :method :post
          :path   [:session (:session driver) :element]
          :data   {:using loc :value term}})))

the return is:

{:state "success",
 :sessionId nil,
 :class "org.openqa.selenium.remote.Response",
 :value
 {:element-6066-11e4-a52e-4f735466cecf
  "a3b83ecf-961e-41a9-9fb4-2f8e8213b362"},
 :status 0}

That's why the (-> ... first second) works. Any ideas?

@lread
Copy link
Collaborator

lread commented Jun 22, 2022

Hiya @dpassen, thanks for raising this issue.

I've not tried Selenium Grid docker images yet, but to get started, I'll do a sanity test on macOS hitting regular old Chrome.

(require '[etaoin.api :as e])

(def driver (e/chrome))

;; status gives us some idea of what I'm running here:
(e/get-status driver)
;; => {:build
;;     {:version
;;      "103.0.5060.53 (a1711811edd74ff1cf2150f36ffa3b0dae40b17f-refs/branch-heads/5060@{#853})"},
;;     :message "ChromeDriver ready for new sessions.",
;;     :os {:arch "x86_64", :name "Mac OS X", :version "10.15.7"},
;;     :ready true}

;; I'll navigate to a random page a test page on the InterWebs (so we can be on the page, :-))
(e/go driver "https://testpages.herokuapp.com/styled/basic-html-form-test.html")

;; And I'll adapt your query so it will find a single input on that page:
(let [q {:tag :input :name "username"}]
  (e/wait-exists driver q)
  [(e/query driver q)
   (e/query-all driver q)])

;; I'll also try your raw execute:
(require '[etaoin.query :as eq])

(let [q {:tag :input :name "username"}
      [loc term] (eq/expand driver q)]
    (-> (etaoin.api/execute
         {:driver driver
          :method :post
          :path   [:session (:session driver) :element]
          :data   {:using loc :value term}})))
;; => {:sessionId "3c9c305bfe7b6fa595bacada3d3cfedc",
;;     :status 0,
;;     :value {:ELEMENT "0.7985155027546353-1"}}

So does Selenium Grid translate/normalize W3C WebDriver requests?
The :class "org.openqa.selenium.remote.Response" in your example raw response seems to suggest it is does at least add some data.

@lread
Copy link
Collaborator

lread commented Jun 22, 2022

I'll learn-as-I-go with docker images.

Here's me launching a current seleniarm/standalone-chrome image:

docker run -d -p 4444:4444 -p 7900:7900 --shm-size="2g" seleniarm/standalone-chromium:4.2.2-20220620

And from the REPL

(require '[etaoin.api :as e])

;; fake out a driver to check the status
(e/get-status {:webdriver-url "http://localhost:4444"})
;; => {:ready true,
;;     :message "Selenium Grid ready.",
;;     :nodes
;;     [{:id "cb4a51db-715b-49f8-8cb4-9a72859526ab",
;;       :uri "http://172.17.0.2:4444",
;;       :maxSessions 1,
;;       :osInfo {:arch "amd64", :name "Linux", :version "5.10.104-linuxkit"},
;;       :heartbeatPeriod 60000,
;;       :availability "UP",
;;       :version "4.2.2 (revision 683ccb65d6)",
;;       :slots
;;       [{:id
;;         {:hostId "cb4a51db-715b-49f8-8cb4-9a72859526ab",
;;          :id "9a395f09-e0e6-402b-9dbc-4d587c871d36"},
;;         :lastStarted "1970-01-01T00:00:00Z",
;;         :session nil,
;;         :stereotype
;;         {:browserName "chrome",
;;          :browserVersion "102.0",
;;          :platformName "LINUX"}}]}]}

;; Ok that's certainly a selenium grid generated response

;; Now I'll try to create a session on the grid.
;; I was getting timeouts until I added in the :capabilities you see 
;; (a selenium grid docs example made me think this might help)
(def driver (e/chrome {:webdriver-url "http://localhost:4444"
                       :capabilities {:browserName "chrome"
                                      :browserVersion "102.0"
                                      :platformName "LINUX"}}))

;; let's see what status returns now
(e/get-status driver)
;; => {:ready false,
;;     :message "Selenium Grid not ready.",
;;     :nodes
;;     [{:id "85df67b0-e738-4c4b-b07a-1c5587ce1934",
;;       :uri "http://172.17.0.2:4444",
;;       :maxSessions 1,
;;       :osInfo {:arch "amd64", :name "Linux", :version "5.10.104-linuxkit"},
;;       :heartbeatPeriod 60000,
;;       :availability "UP",
;;       :version "4.2.2 (revision 683ccb65d6)",
;;       :slots
;;       [{:id
;;         {:hostId "85df67b0-e738-4c4b-b07a-1c5587ce1934",
;;          :id "e22d24ce-6e0b-4bd7-99b1-b9853fca0bea"},
;;         :lastStarted "2022-06-22T20:08:44.408660Z",
;;         :session
;;         {:capabilities
;;          {:browserName "chrome",
;;           :acceptInsecureCerts false,
;;           :goog:chromeOptions {:debuggerAddress "localhost:38761"},
;;           :se:cdpVersion "102.0.5005.115",
;;           :networkConnectionEnabled false,
;;           :webauthn:extension:largeBlob true,
;;           :unhandledPromptBehavior "dismiss and notify",
;;           :pageLoadStrategy "normal",
;;           :setWindowRect true,
;;           :se:cdp
;;           "ws://172.17.0.2:4444/session/693254bf31e96a52e2d77fb5d48396d2/se/cdp",
;;           :webauthn:virtualAuthenticators true,
;;           :proxy {},
;;           :chrome
;;           {:chromedriverVersion
;;            "102.0.5005.115 (174dbe6e33bc81994fceb71d751be201d0b4803d-refs/branch-heads/5005_109@{#3})",
;;            :userDataDir "/tmp/.org.chromium.Chromium.f0C2DS"},
;;           :browserVersion "102.0.5005.115",
;;           :timeouts {:implicit 0, :pageLoad 300000, :script 30000},
;;           :platformName "LINUX",
;;           :webauthn:extension:credBlob true,
;;           :strictFileInteractability false},
;;          :sessionId "693254bf31e96a52e2d77fb5d48396d2",
;;          :start "2022-06-22T20:08:44.408660Z",
;;          :stereotype
;;          {:browserName "chrome", :browserVersion "102.0", :platformName "LINUX"},
;;          :uri "http://172.17.0.2:4444"},
;;         :stereotype
;;         {:browserName "chrome",
;;          :browserVersion "102.0",
;;          :platformName "LINUX"}}]}]}

;; interesting!

;; Ok let's repeat our experiments
(e/go driver "https://testpages.herokuapp.com/styled/basic-html-form-test.html")
;; When I open http://localhost:7900 in my browser I can see that the go worked

(let [q {:tag :input :name "username"}]
  (e/wait-exists driver q)
  [(e/query driver q)
   (e/query-all driver q)])
;; => [nil ["258562f2-4ef4-4484-b364-baa137ff3906"]]
;; ^ matches your experience

(require '[etaoin.query :as eq])

(let [q {:tag :input :name "username"}
      [loc term] (eq/expand driver q)]
    (-> (etaoin.api/execute
         {:driver driver
          :method :post
          :path   [:session (:session driver) :element]
          :data   {:using loc :value term}})))
;; => {:state "success",
;;     :sessionId nil,
;;     :class "org.openqa.selenium.remote.Response",
;;     :value
;;     {:element-6066-11e4-a52e-4f735466cecf "258562f2-4ef4-4484-b364-baa137ff3906"},
;;     :status 0}

;; ^ also matches your experience

So to me, without understanding more, it seems that Selenium Grid is not a simple pass-through to chromedriver. It does stuff.

Etaoin currently assumes a connection to chromedriver (or any other driver) is not abstracted in any way. I'm guessing that to support Selenium Grid, we'd have to add in a feature to understand that Etaoin is talking to a Selenium Grid W3C WebDriver HTTP server.

Which seems reasonable if there is enough interest from the community in doing so.

@dpassen
Copy link
Author

dpassen commented Jun 22, 2022

Thanks for the research! Above and beyond

@lread
Copy link
Collaborator

lread commented Jun 22, 2022

Thanks for the issue, I might not have learned about Selenium Grid otherwise!

@lread lread changed the title query vs. query-all in Chromium Consider Supporting Selenium Grid WebDriver Jun 22, 2022
@lread lread added the feature label Jun 22, 2022
@ekochetkov
Copy link

ekochetkov commented Aug 11, 2022

I realised this feature for me, but did not tested all functions of Etaion. Result success, but need some modifies. My fork with this feature is and example

@lread
Copy link
Collaborator

lread commented Aug 11, 2022

Cool @ekochetkov, thanks for sharing. (Note your example is giving me a 404).

So does Selenium Grid WebDriver abstract specific WebDriver implementations to the W3C spec?

@ekochetkov
Copy link

Cool @ekochetkov, thanks for sharing. (Note your example is giving me a 404).

Fix

So does Selenium Grid WebDriver abstract specific WebDriver implementations to the W3C spec?

On the Webdriver page of selenium development documentation exists reference to W3C Recommendation

@lread
Copy link
Collaborator

lread commented Feb 3, 2023

Sooo... my understanding is as Etaoin was developed it adapted to the various WebDriver implementations which did not always follow the W3C spec correctly.

(Some of the adaptations might no longer be necessary with current WebDriver implementations that might be more conformant. Dunno.)

I assume the Selenium Grid abstraction, since it is written by the Selenium team who drive the WebDriver spec, probably abstracts the WebDriver implementations to conform to the spec.

@lread
Copy link
Collaborator

lread commented Feb 4, 2023

Of interest perhaps: api to get status of grid

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

No branches or pull requests

3 participants