### Starting Chrome Driver Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Basic example of starting a Chrome WebDriver instance. This can sometimes lead to 'DevToolsActivePort file doesn't exist' errors. ```clojure (def driver (e/chrome)) ``` -------------------------------- ### Starting Firefox Driver with Logging Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Example of starting a Firefox WebDriver instance with specific log file paths and trace log level for debugging. ```clojure (def driver (firefox {:log-stdout "ffout.log" :log-stderr "fferr.log" :driver-log-level "trace"})) ``` -------------------------------- ### Automate Wikipedia Session with Etaoin Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc This example demonstrates automating a browser session using Etaoin, including starting a Firefox WebDriver, navigating to Wikipedia, searching, and verifying content. The driver is quit at the end. ```clojure (require '[etaoin.api :as e] '[etaoin.keys :as k] '[clojure.string :as str]) ;; Start WebDriver for Firefox (def driver (e/firefox)) ;; a Firefox window should appear (e/driver-type driver) ;; => :firefox ;; let's perform a quick Wiki session ;; navigate to Wikipedia (e/go driver "https://en.wikipedia.org/") ;; make sure we aren't using a large screen layout (e/set-window-size driver {:width 1280 :height 800}) ;; wait for the search input to load (e/wait-visible driver [{:tag :input :name :search}]) ;; search for something interesting (e/fill driver {:tag :input :name :search} "Clojure programming language") (e/wait driver 1) ;; select first match presented in drop down (e/fill driver {:tag :input :name :search} k/arrow-down) (e/fill driver {:tag :input :name :search} k/enter) (e/wait-visible driver {:id :firstHeading}) ;; check our new url location ;; (wikipedia can tack on a querystring, for result consistency we'll ignore it) (-> (e/get-url driver) (str/split #"\?") first) ;; => "https://en.wikipedia.org/wiki/Clojure" ;; and our new title (e/get-title driver) ;; => "Clojure - Wikipedia" ;; does the page have Clojure in it? (e/has-text? driver "Clojure") ;; => true ;; navigate through history (e/back driver) (e/forward driver) (e/refresh driver) (e/get-title driver) ;; => "Clojure - Wikipedia" ;; let's explore the info box ;; What's header? Let's select it with a css query: (e/get-element-text driver {:css "table.infobox tr th"}) ;; => "Clojure" ;; Ok, now let's try something trickier ;; Maybe we are interested in what value the infobox holds for the Family row: (let [wikitable (e/query driver {:css "table.infobox.vevent tbody"}) row-els (e/query-all-from driver wikitable {:tag :tr})] (for [row row-els :let [header-col-text (e/with-http-error (e/get-element-text-el driver (e/query-from driver row {:tag :th})))] :when (= "Family" header-col-text)] (e/get-element-text-el driver (e/query-from driver row {:tag :td})))) ;; => ("Lisp") ;; Etaoin gives you many options; we can do the same-ish in one swoop in XPath: (e/get-element-text driver "//table[@class='infobox vevent']/tbody/tr/th[text()='Family']/../td") ;; => "Lisp" ;; When we are done, we quit, which stops the Firefox WebDriver (e/quit driver) ;; the Firefox Window should close ``` -------------------------------- ### Setup for Etaoin Doc Blocks Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc This setup code is used for better test-doc-block reporting and to create a directory for saving screenshots when running generated tests. ```clojure (require '[babashka.fs :as fs]) ;; for better test-doc-block reporting when running generated tests (require '[etaoin.test-report]) ;; for screenshots save dir (dir must currently exist) (fs/create-dirs "target/etaoin-play") ``` -------------------------------- ### Start Cljdoc Preview Docker Image Source: https://github.com/clj-commons/etaoin/blob/master/doc/02-developer-guide.adoc Downloads and starts the cljdoc Docker image for previewing documentation. This is an experimental task. ```shell bb cljdoc-preview start ``` -------------------------------- ### Start Browser Driver Servers Source: https://github.com/clj-commons/etaoin/wiki/Installing-drivers Launch these commands to start local HTTP servers for each respective browser driver. An endless process indicates successful startup. ```bash chromedriver ``` ```bash geckodriver ``` ```bash phantomjs --wd ``` ```bash safaridriver -p 0 ``` -------------------------------- ### Verify WebDriver Installations Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Launch these commands to check if your WebDriver installations are running correctly. Each command starts a local HTTP server. Use Ctrl-C to terminate. ```bash chromedriver geckodriver safaridriver -p 0 msedgedriver ``` -------------------------------- ### Run Docker Image Interactively Source: https://github.com/clj-commons/etaoin/blob/master/doc/02-developer-guide.adoc Start the Etaoin Docker image for interactive use. After starting, you can run commands within the prompt. ```shell bb docker-run ``` -------------------------------- ### Run User Guide Code Block Tests Source: https://github.com/clj-commons/etaoin/blob/master/doc/02-developer-guide.adoc Executes tests against code examples found in the user guide to ensure they are functional. ```shell bb test-doc ``` -------------------------------- ### Starting Headless Firefox Driver Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Example of starting a headless Firefox WebDriver instance. This can sometimes result in 'invalid argument: can't kill an exited process' errors. ```clojure (def driver (e/firefox {:headless true})) ``` -------------------------------- ### Launch Clojure REPL Source: https://github.com/clj-commons/etaoin/blob/master/doc/02-developer-guide.adoc Starts a Clojure REPL session for development. ```shell bb dev:jvm ``` -------------------------------- ### Creating a Virtual Keyboard Input Device Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc This example shows how to initialize a virtual keyboard input device using `make-key-input`. This device can then be configured with specific key actions. ```clojure (def keyboard (e/make-key-input)) ``` -------------------------------- ### Initial Setup and Driver Bootstrapping Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc This code block shows the necessary require statements and how to initialize a WebDriver instance for use with Etaoin. It also demonstrates navigating to a local HTML file. ```clojure (require '[etaoin.api :as e] '[etaoin.keys :as k] '[clojure.java.io :as io]) (def sample-page (-> "doc/user-guide-sample.html" io/file .toURI str)) (def driver (e/chrome)) ;; or replace chrome with your preference (e/go driver sample-page) ``` -------------------------------- ### Basic Browser Interaction Example Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc This snippet demonstrates a sequence of actions: navigating to a URL, setting window size, waiting for an element, filling input fields, and clicking elements. ```clojure (doto driver (e/go "https://en.wikipedia.org/") (e/set-window-size {:width 1280 :height 800}) (e/wait-visible [{:tag :input :name :search}]) (e/fill {:tag :input :name :search} "Clojure programming language") (e/wait 1) (e/fill {:tag :input :name :search} k/enter) (e/wait-visible {:class :mw-search-results}) (e/click [{:class :mw-search-results} {:class :mw-search-result-heading} {:tag :a}]) (e/wait-visible {:id :firstHeading}) (e/quit)) ``` -------------------------------- ### Configure Chrome with HTTP/SSL Proxy Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Example of creating a Chrome driver with specific HTTP and SSL proxy settings. ```clojure (e/chrome {:proxy {:http "some.proxy.com:8080" :ssl "some.proxy.com:8080"}}) ``` -------------------------------- ### Launch Babashka REPL Source: https://github.com/clj-commons/etaoin/blob/master/doc/02-developer-guide.adoc Starts a Babashka REPL session for development. ```shell bb dev:bb ``` -------------------------------- ### Install PhantomJS via Homebrew Source: https://github.com/clj-commons/etaoin/wiki/Installing-drivers Use this command for Mac users to install Phantom.js. ```bash brew install phantomjs ``` -------------------------------- ### Get Help for JVM Tests Source: https://github.com/clj-commons/etaoin/blob/master/doc/02-developer-guide.adoc Displays help information for the `test:jvm` task, showing available options and usage. ```shell bb test:jvm --help ``` -------------------------------- ### Run Headless Chrome Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Starts a headless Chrome browser instance. The driver is automatically quit. ```clojure (require '[etaoin.api :as e]) (def driver (e/chrome {:headless true})) ;; runs headless Chrome ;; do some stuff (e/quit driver) ``` -------------------------------- ### Raw Keyboard and Pointer Actions Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc These examples show the raw map structures for defining keyboard and pointer actions. They illustrate the detailed commands like key presses, releases, and mouse movements. ```clojure ;; a keyboard input {:type "key" :id "some name" :actions [{:type "keyDown" :value "a"} {:type "keyUp" :value "a"} {:type "pause" :duration 100}]} ;; some pointer input {:type "pointer" :id "UUID or some name" :parameters {:pointerType "mouse"} :actions [{:type "pointerMove" :origin "pointer" :x 396 :y 323} ;; double click {:type "pointerDown" :duration 0 :button 0} {:type "pointerUp" :duration 0 :button 0} {:type "pointerDown" :duration 0 :button 0} {:type "pointerUp" :duration 0 :button 0}]} ``` -------------------------------- ### Start Chrome with DevTools Support Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Initiate a Chrome browser instance with DevTools support enabled. This is necessary for tracking network requests and other DevTools events. ```clojure (require '[etaoin.api :as e]) (e/with-chrome driver {:dev {}}) ;; do some stuff ) ``` -------------------------------- ### Install Chromedriver via Homebrew Source: https://github.com/clj-commons/etaoin/wiki/Installing-drivers Use this command for Mac users to install the Google Chrome driver. ```bash brew install chromedriver ``` -------------------------------- ### Install Chromedriver via Scoop Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc On Windows, you can install the Chromedriver using the Scoop package manager. ```shell scoop install chromedriver ``` -------------------------------- ### Install Xvfb and Fluxbox for Headless Testing Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Installs necessary packages for headless browser testing on Linux environments. Xvfb provides a virtual display, and fluxbox is a window manager required by geckodriver. ```shell sudo apt get install -y xvfb fluxbox ``` -------------------------------- ### Install Geckodriver via Homebrew Source: https://github.com/clj-commons/etaoin/wiki/Installing-drivers Use this command for Mac users to install the Geckodriver for Firefox. ```bash brew install geckodriver ``` -------------------------------- ### HTTP Proxy Configuration Map Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Example of a map for configuring HTTP, FTP, SSL, SOCKS proxies, and bypass URLs. ```clojure {:proxy {:http "some.proxy.com:8080" :ftp "some.proxy.com:8080" :ssl "some.proxy.com:8080" :socks {:host "myproxy:1080" :version 5} :bypass ["http://this.url" "http://that.url"] :pac-url "localhost:8888"}} ``` -------------------------------- ### Ingest Etaoin into Cljdoc Source: https://github.com/clj-commons/etaoin/blob/master/doc/02-developer-guide.adoc Installs etaoin to the local maven repo and imports it into a locally running cljdoc instance. Requires the cljdoc preview Docker image to be running. ```shell bb cljdoc-preview ingest ``` -------------------------------- ### Launch Virtual Display and Fluxbox Window Manager Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Starts an X virtual display server and the fluxbox window manager. These are essential components for running headless browser tests in a virtualized environment. ```shell Xvfb :99 -screen 0 1024x768x24 & fluxbox -display :99 & ``` -------------------------------- ### Default Page Load Strategy (:normal) Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc This example illustrates the default `:normal` load strategy, where the driver waits for the entire page, including images, to fully load before proceeding. This ensures all resources are available. ```clojure (e/with-chrome driver (e/go driver sample-page) ;; by default you'll hang on this line until the page loads ;; (do-something) ) ``` -------------------------------- ### Configure Browser Proxy Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Configure proxy settings for the web browser. See <> for an example. ```clojure See <> ``` -------------------------------- ### Run Interactive Command in Docker Source: https://github.com/clj-commons/etaoin/blob/master/doc/02-developer-guide.adoc Execute a command from within an interactive Etaoin Docker session. This example runs IDE suites with Firefox. ```shell bb test:jvm --suites ide --browsers firefox ``` -------------------------------- ### Set Browser Preferences Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Provide a map of web browser specific preferences. See <> for an example usage. ```clojure see one usage in <>. ``` -------------------------------- ### Get Help for Babashka Tests Source: https://github.com/clj-commons/etaoin/blob/master/doc/02-developer-guide.adoc Displays help information for the `test:bb` task, showing available options and usage. ```shell bb test:bb --help ``` -------------------------------- ### Automate Wikipedia with Doto Macro Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc This example shows a portion of the previous Wikipedia automation rewritten using the `doto` macro for a more DSL-like feel. It requires Etaoin API and keys to be required. ```clojure (require '[etaoin.api :as e] '[etaoin.keys :as k]) (def driver (e/firefox)) ``` -------------------------------- ### Run Headless Firefox and Check Headless Status Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Starts a headless Firefox browser instance and demonstrates checking if a driver is in headless mode. ```clojure (def driver (e/firefox {:headless true})) ;; runs headless Firefox ;; you can also check if a driver is in headless mode: (e/headless? driver) ;; => true (e/wait 1) ;; seems to appease Firefox on Linux (e/quit driver) ``` -------------------------------- ### Configuring Wait Timeout and Interval Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc This example demonstrates how to set a custom wait timeout and interval using `with-wait-timeout`. It's useful when default wait times are insufficient for specific operations. ```clojure (e/with-wait-timeout 15 ;; time in seconds (doto driver (e/refresh) (e/wait-visible {:id :last-section}) (e/click {:tag :a}) (e/wait-has-text :clicked "link 1"))) ``` -------------------------------- ### Print Page to PDF Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Prints the current browser page to a PDF file. This example demonstrates usage within a headless Firefox context. ```clojure (e/with-firefox-headless driver (e/go driver sample-page) (e/print-page driver "target/etaoin-play/printed.pdf")) ``` -------------------------------- ### Maximize Window with Chrome Driver Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Example of maximizing a Chrome driver window. This was a workaround for an older chromedriver bug. ```clojure (e/with-chrome driver (e/maximize driver)) ``` -------------------------------- ### Configure Chrome with WebDriver Capabilities for Proxy Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Example of setting proxy details using WebDriver capabilities, including proxy type, URL, and bypass list. ```clojure (e/chrome {:capabilities {:proxy {:proxyType "manual" :proxyAutoconfigUrl "some.proxy.com:8080" :ftpProxy "some.proxy.com:8080" :httpProxy "some.proxy.com:8080" :noProxy ["http://this.url" "http://that.url"] :sslProxy "some.proxy.com:8080" :socksProxy "some.proxy.com:1080" :socksVersion 5}}}) ``` -------------------------------- ### Run Specific Etaoin API Tests Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Perform a smaller sanity test by running only API tests against specified browsers. This example runs API tests against Chrome. ```bash bb test:bb --suites api --browsers chrome ``` -------------------------------- ### Multi-Driver Fixture Setup Source: https://github.com/clj-commons/etaoin/wiki/Test-fixtures Configures tests to run against multiple specified driver types (e.g., Firefox and Chrome). Each test is executed once per driver type, with the `testing` macro used to identify the browser in reports. ```clojure (def driver-type [:firefox :chrome]) (defn fixture-drivers [f] (doseq [type driver-types] (with-driver type {} driver (binding [*driver* driver] (testing (format "Testing in %s browser" (name type)) (f)))))) ``` -------------------------------- ### Eager Page Load Strategy (:eager) Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc This example uses the `:eager` load strategy, which waits only for the DOM content to load. Note that this strategy is currently only supported by Firefox. ```clojure (e/with-chrome {:load-strategy :eager} driver (e/go driver sample-page) ;; waits for DOMContentLoaded ;; (do-something) ) ``` -------------------------------- ### Postmortem Artifacts Directory Structure Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Example of the directory structure created by `with-postmortem` for storing captured artifacts like HTML, JSON, and PNG files. ```shell tree target └── etaoin-postmortem ├── chrome-127.0.0.1-49766-2022-06-04-12-26-31.html ├── chrome-127.0.0.1-49766-2022-06-04-12-26-31.json └── chrome-127.0.0.1-49766-2022-06-04-12-26-31.png ``` -------------------------------- ### Fill Text into Input Elements Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Enter text into input fields found by Etaoin queries. Use `fill-el` with the element ID and the desired text. This example shows filling with a specific string and a random selection. ```clojure (e/refresh driver) (def elements (e/query-all driver {:tag :input :type :text :fn/disabled false})) (e/fill-el driver (first elements) "This is a test") (e/fill-el driver (rand-nth elements) "I like tests!") ``` -------------------------------- ### Basic REPL Usage with Etaoin Source: https://github.com/clj-commons/etaoin/wiki/Basic-Usage Demonstrates automating a browser directly from the REPL, including navigation, searching, and basic assertions. ```clojure (use 'etaoin.api) (require '[etaoin.keys :as k]) (def driver (firefox)) ;; here, a Firefox window should appear ;; let's perform a quick Wiki session (go driver "https://en.wikipedia.org/") (wait-visible driver [{:id :simpleSearch} {:tag :input :name :search}]) ;; search for something (fill driver {:tag :input :name :search} "Clojure programming language") (fill driver {:tag :input :name :search} k/enter) (wait-visible driver {:class :mw-search-results}) ;; I'm sure the first link is what I was looking for (click driver [{:class :mw-search-results} {:class :mw-search-result-heading} {:tag :a}]) (wait-visible driver {:id :firstHeading}) ;; let's ensure (get-url driver) ;; "https://en.wikipedia.org/wiki/Clojure" (get-title driver) ;; "Clojure - Wikipedia" (has-text? driver "Clojure") ;; true ;; navigate on history (back driver) (forward driver) (refresh driver) (get-title driver) ;; "Clojure - Wikipedia" ;; stops Firefox and HTTP server (quit driver) ``` -------------------------------- ### Run All Etaoin Tests Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Execute the full Etaoin test suite using this command. ```bash bb test:bb ``` -------------------------------- ### Configure Postmortem Options Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Demonstrates various options for `with-postmortem`, including specifying directories for screenshots, HTML sources, and console logs, as well as custom date formatting. ```clojure {;; directory to save artifacts ;; will be created if it does not already exist, defaults to the current working directory :dir "/home/ivan/UI-tests" ;; directory to save screenshots; defaults to :dir :dir-img "/home/ivan/UI-tests/screenshots" ;; the same but for HTML sources :dir-src "/home/ivan/UI-tests/HTML" ;; the same but for console logs :dir-log "/home/ivan/UI-tests/console" ;; a string template to format a timestamp; See SimpleDateFormat Java class :date-format "yyyy-MM-dd-HH-mm-ss"} ``` -------------------------------- ### Run Etaoin Library Tests Source: https://github.com/clj-commons/etaoin/wiki/Installing-drivers Execute this command to run the library's tests, which will open and close browser windows to validate functionality. ```bash lein test ``` -------------------------------- ### Set WebDriver Capabilities Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Specify vendor-specific capabilities for the WebDriver. See <> for an example. ```clojure See <> for an example usage. ``` -------------------------------- ### Stop Cljdoc Preview Docker Image Source: https://github.com/clj-commons/etaoin/blob/master/doc/02-developer-guide.adoc Stops the cljdoc Docker image that was started for documentation preview. ```shell bb cljdoc-preview stop ``` -------------------------------- ### Creating Chrome Headless Driver Instances Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Shows various methods for creating a headless Chrome WebDriver instance, including direct boot, using `e/chrome`, and the dedicated `e/chrome-headless` function. ```clojure (require '[etaoin.api :as e]) ;; at the base we have: (def driver (e/boot-driver :chrome {:headless true})) ;; do stuff (e/quit driver) ;; This can also be expressed as: (def driver (e/chrome {:headless true})) ;; do stuff (e/quit driver) ;; Or... (def driver (e/chrome-headless)) ;; do stuff (e/quit driver) ``` -------------------------------- ### XPath Search from Root Node Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Example of searching for an element containing specific text from the root of the page using XPath. ```clojure (e/get-element-text driver [{:id :mishmash} "//*[contains(text(),'some')] MISHMASH"]) ;; => "A little sample page to illustrate some concepts described in the Etaoin user guide." ;; but we've found the first element with text 'some' ``` -------------------------------- ### Use Headless Driver Shortcuts Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Provides shortcuts for launching Chrome and Firefox in headless mode, with options for extra settings. ```clojure (def driver (e/chrome-headless)) ;; do some stuff (e/quit driver) ;; or (def driver (e/firefox-headless {:log-level :all})) ;; with extra settings ;; do some stuff (e/quit driver) ;; or (require '[etaoin.api :as e]) (e/with-chrome-headless driver (e/go driver "https://clojure.org")) (e/with-firefox-headless {:log-level :all} driver ;; notice extra settings (e/go driver "https://clojure.org")) ``` -------------------------------- ### View Cljdoc Preview Source: https://github.com/clj-commons/etaoin/blob/master/doc/02-developer-guide.adoc Opens the locally imported cljdoc documentation in your default web browser. Requires the cljdoc preview Docker image to be running and etaoin to be ingested. ```shell bb cljdoc-preview view ``` -------------------------------- ### Click Button and Get Text Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Clicks a button specified by a list of selectors and retrieves the text of an element to verify the action. ```clojure (e/click driver [{:tag :html} {:tag :body} {:tag :button}]) ;; our sample page shows form submits; did it work? (e/get-element-text driver :submit-count) ;; => "1" ``` -------------------------------- ### Using `with-` for Driver Management Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Demonstrates the convenience of `with-chrome` and `with-chrome-headless` for managing WebDriver instances, ensuring proper cleanup after operations. ```clojure (e/with-chrome {:headless true} driver (e/go driver "https://clojure.org")) (e/with-chrome-headless driver (e/go driver "https://clojure.org")) ``` -------------------------------- ### List Available Babashka Tasks Source: https://github.com/clj-commons/etaoin/blob/master/doc/02-developer-guide.adoc Run this command to see all available tasks in the project. ```shell bb tasks ``` -------------------------------- ### Execute JavaScript and Get Logs Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Execute JavaScript in the browser and retrieve console logs. Note that logs are only available in Chrome and are cleared after reading. ```clojure (e/js-execute driver "console.log('foo')") (e/get-logs driver) ;; [{:level :info, ;; :message "console-api 2:32 \"foo\"", ;; :source :console-api, ;; :timestamp 1654358994253, ;; :datetime #inst "2022-06-04T16:09:54.253-00:00"}] ;; on the 2nd call, for chrome, we'll find the logs empty (e/get-logs driver) ;; => [] ``` -------------------------------- ### Run Selenium IDE Script via CLI (Uberjar) Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Execute a .side file from the command line when packaged in an uberjar. Ensure Etaoin is a primary dependency. Specify the driver, parameters, and the file path. ```shell java -cp .../poject.jar -m etaoin.ide.main -d firefox -p '{:port 8888}' -f ide/test.side ``` -------------------------------- ### Adding Key Actions to a Virtual Input Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc This snippet demonstrates how to add key down, key up, and pause actions to a virtual keyboard input device using Etaoin's helper functions. It shows building a sequence of keyboard events. ```clojure (-> keyboard (e/add-key-down k/shift-left) (e/add-key-down "a") (e/add-key-up "a") (e/add-key-up k/shift-left)) ``` -------------------------------- ### XPath Search from Current Node Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Example of searching for an element containing specific text relative to the current node using XPath with a leading dot. ```clojure (e/get-element-text driver [{:id :mishmash} ".//*[contains(text(),'some')] MISHMASH"]) ;; => "some other paragraph" ;; that's what we were looking for! ``` -------------------------------- ### Query Shadow Root Host and Get Property Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Find an element with a specific ID and retrieve its 'shadowRoot' property. This is useful for inspecting the structure of a Shadow DOM. ```clojure (e/query driver {:id "shadow-root-host"}) ;; an element ID similar to (but not the same as) ;; "78344155-7a53-46fb-a46e-e864210e501d" ``` ```clojure (e/get-element-property-el driver (e/query driver {:id "shadow-root-host"}) "shadowRoot") ;; something similar to ;; {:shadow-6066-11e4-a52e-4f735466cecf "ac5ab914-7f93-427f-a0bf-f7e91098fd37"} ``` ```clojure (e/get-element-property driver {:id "shadow-root-host"} "shadowRoot") ;; something similar to ;; {:shadow-6066-11e4-a52e-4f735466cecf "ac5ab914-7f93-427f-a0bf-f7e91098fd37"} ``` -------------------------------- ### Launch REPL with Host Access Source: https://github.com/clj-commons/etaoin/blob/master/doc/02-developer-guide.adoc Allows connecting to the REPL from any host, useful for remote debugging or specific network configurations. Use with caution. ```shell bb dev:jvm --host 0.0.0.0 ``` -------------------------------- ### Specify Browser Binary Path Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Use this option to specify the path to the web browser binary if it's not found in the system's PATH. Etaoin will attempt to locate it automatically if this is omitted. ```clojure :path-browser "/Users/ivan/Downloads/firefox/firefox" ``` -------------------------------- ### Query Tree for Descendant Elements Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Traverses a DOM tree structure starting from a root element to find all descendant anchor tags. Extracts and sorts their text content. ```clojure (->> (e/query-tree driver :query-tree-example {:tag :div} {:tag :a}) (map #(e/get-element-text-el driver %)) sort) ;; => ("a1" "a2" "a3" "a4" "a5" "a6" "a7" "a8" "a9") ``` -------------------------------- ### Performing Raw Keyboard Actions Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc This snippet demonstrates how to manually create a keyboard action map and execute it using `perform-actions`. It includes pressing and releasing keys and adding pauses. ```clojure (def keyboard-input {:type "key" :id "some name" :actions [{:type "keyDown" :value "e"} {:type "keyUp" :value "e"} {:type "keyDown" :value "t"} {:type "keyUp" :value "t"} ;; duration is in ms {:type "pause" :duration 100}]}) ;; refresh so that we'll be at the active input field (e/refresh driver) ;; perform our keyboard input action (e/perform-actions driver keyboard-input) ``` -------------------------------- ### Using doto for Cleaner REPL Workflow Source: https://github.com/clj-commons/etaoin/wiki/Basic-Usage Simplifies browser automation code by chaining function calls on the driver instance using the `doto` macro. ```clojure (def driver (firefox)) (doto driver (go "https://en.wikipedia.org/") (wait-visible [{:id :simpleSearch} {:tag :input :name :search}]) ... (fill {:tag :input :name :search} k/enter) (wait-visible {:class :mw-search-results}) ... (wait-visible {:id :firstHeading}) (get-url) "https://en.wikipedia.org/wiki/Clojure" ... (quit)) ``` -------------------------------- ### Build Docker Image for Testing Source: https://github.com/clj-commons/etaoin/blob/master/doc/02-developer-guide.adoc Builds a local Docker image that includes Chrome and Firefox support for testing on Linux environments. ```shell bb docker-build ``` -------------------------------- ### Configure Chrome Downloads Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Set a download directory for Chrome. Ensure the driver is quit after use. ```clojure (def driver (e/chrome {:download-dir "target/etaoin-play/chrome-downloads"})) ;; do some downloading (e/driver quit) ``` -------------------------------- ### Fill Element using XPath and CSS Selectors Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Demonstrates filling an input element using both XPath and CSS selectors. The driver's `:locator` setting determines interpretation, defaulting to XPath. Shows how to switch to CSS using `e/use-css`. ```clojure (e/refresh driver) (e/fill driver ".//input[@id='uname'][@name='username']" "XPath can be tricky") ;; let's check if that worked as expected: (e/get-element-value driver :uname) ;; => "XPath can be tricky" ;; let's modify the driver to use CSS rather than XPath ;; note that this returns a new, modified copy of the driver ;; the old driver is still valid, however (def driver-css (e/use-css driver)) (e/refresh driver-css) (e/fill driver-css "input#uname[name='username']" "CSS can be tricky, too") (e/get-element-value driver-css :uname) ;; => "CSS can be tricky, too" ``` -------------------------------- ### Complex Element Selection and Click Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Demonstrates clicking an element using a combination of HTML tag, CSS class, and XPath selectors. Verifies the click by getting element text. ```clojure ;; under the html tag (using map query syntax), ;; under a div tag with a class that includes some-links (using css query), ;; click on a tag that has ;; a class attribute equal to active (using xpath syntax): (e/click driver [{:tag :html} {:css "div.some-links"} ".//a[@class='active']"]) ;; our sample page shows link clicks, did it work? (e/get-element-text driver :clicked) ;; => "link 2 (active)" ``` -------------------------------- ### Get Element Text by Href Inclusion Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Retrieves the text of an `a` element whose `href` attribute contains 'clojure.org'. Uses `:fn/link`, equivalent to XPath `contains(@href, '...')`. ```clojure (e/get-element-text driver {:tag :a :fn/link "clojure.org"}) ;; => "link 3 (clojure.org)" ;; equivalent xpath: (e/get-element-text driver ".//a[contains(@href, \"clojure.org\")]") ;; => "link 3 (clojure.org)" ``` -------------------------------- ### Set Initial Browser Window Size Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Define the initial width and height in pixels for the web browser window. ```clojure size: [640 480] ``` -------------------------------- ### Get Element Text by Class Inclusion Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Retrieves the text of a `span` element that includes 'class1' in its class attribute. Uses `:fn/has-class`, equivalent to XPath `contains(@class, '...')`. ```clojure (e/get-element-text driver {:tag :span :fn/has-class "class1"}) ;; => "blarg in a span" ;; equivalent xpath: (e/get-element-text driver ".//span[contains(@class, 'class1')]") ;; => "blarg in a span" ``` -------------------------------- ### Run Selenium IDE Script via CLI (Clojure) Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Execute a .side file from the command line using the clojure CLI. Specify the driver, parameters, and the resource path to the IDE file. ```shell clojure -M -m etaoin.ide.main -d firefox -p '{:port 8888}' -r ide/test.side ``` -------------------------------- ### Configure Firefox Downloads with Custom MIME Types Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Set a download directory and custom MIME types for Firefox. Ensure the driver is quit after use. ```clojure (def driver (e/firefox {:download-dir "target/etaoin-play/firefox-downloads" :prefs {:browser.helperApps.neverAsk.saveToDisk "some-mime/type-1;other-mime/type-2"}})) ;; do some downloading (e/driver quit) ``` -------------------------------- ### Get Shadow Root Element ID from Host Element Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Obtain the shadow root element ID when you already have the host element. This function is useful when the host element has already been queried. ```clojure (def host (e/query driver {:id "shadow-root-host"})) (e/get-element-shadow-root-el driver host) ;; something similar to ;; "ac5ab914-7f93-427f-a0bf-f7e91098fd37" ``` -------------------------------- ### Get Shadow Root Element ID Directly Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Retrieve the element ID of a shadow root directly using its host element's selector. This is a more direct approach than querying for the host and then its property. ```clojure (e/get-element-shadow-root driver {:id "shadow-root-host"}) ;; something similar to ;; "ac5ab914-7f93-427f-a0bf-f7e91098fd37" ``` -------------------------------- ### Run Test Coverage Report Source: https://github.com/clj-commons/etaoin/blob/master/doc/02-developer-guide.adoc Generate a test coverage report for Etaoin's unit and doc tests. This helps identify areas not covered by tests. The results are saved in `./target/clofidence/index.html`. ```shell bb test-coverage ``` -------------------------------- ### Getting Element Text Directly and via Query Result Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Illustrates two ways to retrieve the text content of an element: directly passing a query to `get-element-text` and passing the result of a query to `get-element-text-el`. ```clojure ;; specifying query directly (e/get-element-text driver {:tag :button}) ;; => "Submit Form" ;; specifying the result of a query (notice the `-el` fn variant here) (e/get-element-text-el driver (e/query driver {:tag :button})) ;; => "Submit Form" ``` -------------------------------- ### Run Firefox WebDriver in Docker Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Launch a Firefox WebDriver instance using a pre-built Docker image. Expose the WebDriver port. ```shell docker run --name geckodriver -p 4444:4444 -d instrumentisto/geckodriver ``` -------------------------------- ### Ensuring Driver Cleanup with `with-` Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Illustrates using `with-firefox` to manage the WebDriver lifecycle, ensuring the process is closed even if exceptions occur. ```clojure (e/with-firefox driver (doto driver (e/go "https://google.com") ;; ... your code here )) ``` -------------------------------- ### Get Element Text by Partial Text and Index Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Retrieves the text of an element that contains 'blarg' and is the 3rd such element. Uses `:fn/has-text` and `:fn/index`, equivalent to XPath `//*[contains(text(), 'blarg')][n]`. ```clojure (e/get-element-text driver {:fn/has-text "blarg" :fn/index 3}) ;; => "blarg in a p" ;; equivalent in xpath: (e/get-element-text driver ".//*[contains(text(), 'blarg')][3]") ;; => "blarg in a p" ``` -------------------------------- ### Run Chrome with --no-sandbox Argument Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Use this snippet to launch Chrome with the '--no-sandbox' argument, which can prevent crashes when running as root. This configuration is unsupported and discouraged. ```clojure (e/with-chrome {:args ["--no-sandbox"]} driver (e/go driver "https://clojure.org")) ``` -------------------------------- ### Manual Screenshot After Each Form Field Fill Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Illustrates the manual process equivalent to `with-screenshots`, showing individual screenshot calls after each fill operation. ```clojure (e/refresh driver) (e/fill driver :uname "et") (e/screenshot driver "target/etaoin-play/saved-screenshots/chrome-1.png") (e/fill driver :uname "ao") (e/screenshot driver "target/etaoin-play/saved-screenshots/chrome-2.png") (e/fill driver :uname "in") (e/screenshot driver "target/etaoin-play/saved-screenshots/chrome-3.png") ``` -------------------------------- ### Get Element Text by Multiple Class Inclusions Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Retrieves the text of an element that includes all specified classes ('class2', 'class3', 'class5'). Uses `:fn/has-classes`, equivalent to multiple XPath `contains(@class, '...')` clauses. ```clojure (e/get-element-text driver {:fn/has-classes [:class2 :class3 :class5]}) ;; => "blarg in a div" ;; equivalent in xpath: (e/get-element-text driver ".//*[contains(@class, 'class2')][contains(@class, 'class3')][contains(@class, 'class5')]") ;; => "blarg in a div" ``` -------------------------------- ### Faster Testing with Headless Chrome Driver Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc A simplified test fixture that initializes a headless Chrome WebDriver instance once and binds it to the dynamic `*driver*` var. This setup is suitable for faster test execution when per-test browser resets are not strictly necessary. ```clojure (defn fixture-browser [f] (e/with-chrome-headless driver (binding [*driver* driver] (f)))) ``` -------------------------------- ### Run Chrome Driver with a Specific Profile Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Launch a Chrome WebDriver instance using a pre-configured user profile. Ensure the profile path is correctly specified. ```clojure ;; Chrome (def chrome-profile "/Users/ivan/Library/Application Support/Google/Chrome/Profile 2/Default") (def chrome-driver (e/chrome {:profile chrome-profile})) ``` -------------------------------- ### Set Download Directory for Browser Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Specify the directory where the web browser should download files. See <> for usage. ```clojure :download-dir "target/chrome-downloads" ``` -------------------------------- ### Run Single Docker Command Source: https://github.com/clj-commons/etaoin/blob/master/doc/02-developer-guide.adoc Execute a specific command within the Etaoin Docker image and then exit. Useful for running unit tests. ```shell bb docker-run bb test:bb --suites unit ``` -------------------------------- ### Connect to Remote WebDriver URL Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc When specified, Etaoin connects to a pre-existing WebDriver process at the given URL. If omitted, a new local process is created. ```clojure :web-driver-url "https://chrome.browserless.io/webdriver" ``` -------------------------------- ### Publish New Release Source: https://github.com/clj-commons/etaoin/blob/master/doc/03-maintainer-guide.adoc Invoke the publish task from the command line. This task performs local validations and automates version bumping, git operations, and CI triggering. ```shell bb publish ``` -------------------------------- ### Select Dropdown Option with Click (Safari Quirk) Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Demonstrates selecting a dropdown option using `e/click` while accounting for the Safari quirk, which may require an initial click on the select element before clicking the option. ```clojure (e/click driver :dropdown) ;; needed for Safari quirk only (e/click driver [{:id :dropdown} {:fn/has-text "bar"}]) (e/get-element-value driver :dropdown) ``` -------------------------------- ### Run Firefox Driver with a Specific Profile Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Launch a Firefox WebDriver instance using a pre-configured user profile. Ensure the profile path is correctly specified. ```clojure ;; Firefox (def ff-profile "/Users/ivan/Library/Application Support/Firefox/Profiles/iy4iitbg.Test") (def firefox-driver (e/firefox {:profile ff-profile})) ``` -------------------------------- ### Enter Text with Shift Key Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Demonstrates entering text with the Shift key held down to simulate typing in uppercase. ```clojure (e/refresh driver) (e/wait 1) ;; maybe we need a sec for active element to focus (e/fill-active driver (k/with-shift "caps is great")) (e/get-element-value-el driver (e/get-active-element driver)) ``` -------------------------------- ### Set URL to Open in Browser Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Specify a URL to open in the web browser. This option currently only works with Firefox. ```clojure :url "https://clojure.org" ``` -------------------------------- ### Basic Test Fixture with Per-Test Driver Lifecycle Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Sets up a test fixture that creates and tears down a Chrome WebDriver instance for each test. The driver is bound to a dynamic var `*driver*` for use within tests. ```clojure (ns project.test.integration "A module for integration tests" (:require [clojure.test :refer [deftest is use-fixtures]] [etaoin.api :as e])) (def ^:dynamic *driver*) (defn fixture-driver "Executes a test running a driver. Bounds a driver with the global *driver* variable." [f] (e/with-chrome [driver] (binding [*driver* driver] (f)))) (use-fixtures :each ;; start and stop driver for each test fixture-driver) ;; now declare your tests (deftest ^:integration test-some-case (doto *driver* (e/go url-project) (e/click :some-button) (e/refresh) ... )) ``` -------------------------------- ### Basic Element Selection and Interaction Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc This snippet shows how to refresh the page, select an element by its ID and fill it with text, and click an element by its tag. ```clojure ;; let's start anew by refreshing the page: (e/refresh driver) ;; select the element with an html attribute id of 'uname' and fill it with text: (e/fill driver {:id "uname"} "Etaoin") ;; select the first element with an html button tag and click on it: (e/click driver {:tag :button}) ``` -------------------------------- ### Enable Headless Browser Mode Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Run the web browser without a user interface. This is useful for running tests on servers without graphical output. ```clojure :headless true ``` -------------------------------- ### Check Tools Versions Source: https://github.com/clj-commons/etaoin/blob/master/doc/02-developer-guide.adoc Verifies the versions of development tools, useful for checking prerequisites and for CI environments. ```shell bb tools-versions ``` -------------------------------- ### Check for Outdated Dependencies Source: https://github.com/clj-commons/etaoin/blob/master/doc/02-developer-guide.adoc Check Etaoin dependencies for any outdated versions. This helps in keeping the project's dependencies up-to-date. ```shell bb outdated ``` -------------------------------- ### Run Chrome WebDriver in Docker Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Launch a Chrome WebDriver instance using a pre-built Docker image. Expose the WebDriver port and configure IP whitelisting. ```shell docker run --name chromedriver -p 9515:4444 -d -e CHROMEDRIVER_WHITELISTED_IPS='' robcherry/docker-chromedriver:latest ``` -------------------------------- ### Lint Etaoin Source Code Source: https://github.com/clj-commons/etaoin/blob/master/doc/02-developer-guide.adoc Run clj-kondo to lint the Etaoin source code. This command checks for lint warnings and is used to maintain code quality. ```shell bb lint ``` -------------------------------- ### Navigate and Wait for AJAX Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Navigate to a URL and wait for AJAX requests to complete. This is useful for ensuring dynamic content has loaded. ```clojure ;; refresh to fill the logs again (e/go driver "https://google.com") (e/wait 2) ;; give ajax requests a chance to finish ``` -------------------------------- ### Run Selenium IDE Script Programmatically in Clojure Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Execute a .side file using Etaoin's flow API. Configure options like base URL and specific test selection. Ensure the ide/test.side file is accessible as a resource. ```clojure (require '[clojure.java.io :as io] '[etaoin.api :as e] '[etaoin.ide.flow :as flow]) (def driver (e/chrome)) (def ide-file (io/resource "ide/test.side")) (def opt {;; The base URL redefines the one from the file. ;; For example, the file was written on the local machine ;; (http://localhost:8080), and we want to perform the scenario ;; on staging (https://preprod-001.company.com) :base-url "https://preprod-001.company.com" ;; keywords :test-.. and :suite-.. (id, ids, name, names) ;; are used to select specific tests. When not passed, ;; all tests get run. For example: :test-id "xxxx-xxxx..." ;; a single test by its UUID :test-name "some-test" ;; a single test by its name :test-ids ["xxxx-xxxx...", ...] ;; multiple tests by their ids :test-names ["some-test1", ...] ;; multiple tests by their names ;; the same for suites: :suite-id ... :suite-name ... :suite-ids [...] :suite-names [...]}) (flow/run-ide-script driver ide-file opt) ``` -------------------------------- ### Connect to Dockerized WebDriver in Clojure Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Instantiate headless Chrome or Firefox drivers in Clojure, connecting to a WebDriver process running in Docker. Specify host and port, and optionally provide driver arguments. ```clojure (def driver (e/chrome-headless {:host "localhost" :port 9515 :args ["--no-sandbox"]})) (def driver (e/firefox-headless {:host "localhost"})) ;; will try to connect to port 4444 ``` -------------------------------- ### Upload File using Path String Source: https://github.com/clj-commons/etaoin/blob/master/doc/01-user-guide.adoc Uploads a file to a file input element using its local system path. An exception is thrown if the file is not found. ```clojure (e/go driver "http://nervgh.github.io/pages/angular-file-upload/examples/simple/") ;; bind element selector to variable; you may also specify an id, class, etc (def file-input {:tag :input :type :file}) ;; upload a file from your system to the first file input (def my-file "env/test/resources/static/drag-n-drop/images/document.png") (e/upload-file driver file-input my-file) ```