Skip to content

Commit

Permalink
Add clj-kondo export config
Browse files Browse the repository at this point in the history
Export config uses call hooks for better error reporting for users of our
public API. Still using macro expand hooks for internal only macros.

Using the brand spanking new `.clj_kondo` extension for hook source.
This is nice to keep tooling less confused, but also keeps my brain less
confused.

Etaoin has a relatively large number of macros. I think I hit the
important ones. But some macros are not under test and not verified
by me as clj-kondo friendly. We'll add in support for any uncovered
macros as needed.

Ran a lint and turfed an unused var.
Also added a sanity test for an etaoin.api2 macro.

Added the lint task as a job to our CI build matrix.
This helps to verify our clj-kondo config.

Closes clj-commons#413
  • Loading branch information
lread committed May 29, 2022
1 parent cfef813 commit 944ca90
Show file tree
Hide file tree
Showing 14 changed files with 138 additions and 71 deletions.
17 changes: 6 additions & 11 deletions .clj-kondo/config.edn
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
{:config-paths ^:replace [] ;; don't adopt any user preferences
:cljc {:features [:clj]}
{:config-paths ^:replace ;; don't adopt any user preferences
["../resources/clj-kondo.exports/etaoin/etaoin"] ;; include our exported public config
:cljc {:features [:clj]} ;; our bb reader conditionals might make some tools also assume cljs, state otherwise
:hooks
;; for now we'll use the simple macroexpand, can move to hooks for finer grained errors later
;; for internal stuff, I'm fine with using macroexpand, our external config uses analyze-call for
;; finer grained error reporting
{:macroexpand
{etaoin.impl.util/defmethods etaoin.impl.util/defmethods
etaoin.impl.util/with-tmp-file etaoin.impl.util/with-tmp-file

etaoin.api/with-key-down etaoin.api/with-key-down
etaoin.api/with-pointer-btn-down etaoin.api/with-pointer-btn-down
etaoin.api/with-pointer-left-btn-down etaoin.api/with-pointer-left-btn-down
etaoin.api/with-driver etaoin.api/with-driver
etaoin.api/with-chrome etaoin.api/with-chrome
etaoin.api/with-firefox etaoin.api/with-firefox}}
etaoin.impl.util/with-tmp-file etaoin.impl.util/with-tmp-file}}

:linters
;; etaoin is dsl-ish and does make use of :refer :all, can decide if we like that at some later date
Expand Down
41 changes: 0 additions & 41 deletions .clj-kondo/etaoin/api.clj

This file was deleted.

File renamed without changes.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,8 @@ build.xml
/.calva
# Clojure tools cli classpath cache
/.cpcache
# clj-kondo will copy our own exported config under resources to ./clj-kondo,
# we don't need this duplicate.
# note that we do not ignore /.clj-kondo/etaoin because it does include some macro hooks
# that are not part of our export config
/.clj-kondo/etaoin/etaoin
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ If we got this wrong your code will fail, you will tell us, and we can discuss.
Other Changes

* https://github.com/clj-commons/etaoin/issues/380[#380]: Etaoin is now Babashka compatible!
* https://github.com/clj-commons/etaoin/issues/413[#413]: Etaoin now exports a clj-kondo config to help with the linting of its many handy macros
* https://github.com/clj-commons/etaoin/issues/383[#383]: Drop testing for Safari on Windows, Apple no longer releases Safari for Windows
* https://github.com/clj-commons/etaoin/issues/388[#388]: Drop testing for PhantomJS, development has long ago stopped for PhantomJS
* https://github.com/clj-commons/etaoin/issues/387[#387]: No longer testing multiple key modifiers for a single webdriver send keys request
Expand Down
4 changes: 2 additions & 2 deletions deps.edn
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{:paths ["src"]
{:paths ["src" "resources"]
:deps {org.clojure/clojure {:mvn/version "1.9.0"} ;; min clojure version
babashka/fs {:mvn/version "0.1.6"}
clj-http/clj-http {:mvn/version "3.12.3"} ;; for jvm use
Expand All @@ -23,7 +23,7 @@
:bb-test {:extra-deps {org.clojure/tools.namespace {:git/url "https://github.com/babashka/tools.namespace"
:git/sha "a13b037215e21a2e71aa34b27e1dd52c801a2a7b"}}}
;; for consistent linting we use a specific version of clj-kondo through the jvm
:clj-kondo {:extra-deps {clj-kondo/clj-kondo {:mvn/version "2022.04.25"}}
:clj-kondo {:extra-deps {clj-kondo/clj-kondo {:mvn/version "2022.05.28"}}
:main-opts ["-m" "clj-kondo.main"]}

:build {:deps {io.github.clojure/tools.build {:git/tag "v0.8.2" :git/sha "ba1a2bf"}
Expand Down
4 changes: 3 additions & 1 deletion doc/02-developer-guide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,11 @@ See `script/bb_test_runner.clj` and tweak if necessary.
Sometimes tools like WireShark can also be helpful.
@lread personally used a combination of RawCap and WireShark on Windows to successfully diagnose an issue.

=== Clj-kondo Export Config [COMING SOON]
=== Clj-kondo Export Config

Users of Etaoin and clj-kondo benefit from our clj-kondo export configuration.
As is the convention, you'll find it under `./resources/clj-kondo.exports/`.
We keep any clj-kondo config containing our local linting preferences, and pertinent to only our internal code, in `.clj-kondo/config.edn`.

This configuration is included in the Etaoin release jar and available when folks reference Etaoin from their `deps.edn` form a `git` dependency.

Expand Down
25 changes: 25 additions & 0 deletions resources/clj-kondo.exports/etaoin/etaoin/config.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{:hooks
{:analyze-call
{etaoin.api/with-chrome etaoin.api/with-browser
etaoin.api/with-firefox etaoin.api/with-browser
etaoin.api/with-chrome-headless etaoin.api/with-browser
etaoin.api/with-edge etaoin.api/with-browser
etaoin.api/with-edge-headless etaoin.api/with-browser
etaoin.api/with-phantom etaoin.api/with-browser
etaoin.api/with-safari etaoin.api/with-browser

etaoin.api/with-driver etaoin.api/with-driver
etaoin.api/with-key-down etaoin.api/with-key-down
etaoin.api/with-pointer-btn-down etaoin.api/with-pointer-btn-down

;; api2 moves to a more conventional let-ish vector syntax
etaoin.api2/with-chrome etaoin.api2/with-browser
etaoin.api2/with-chrome-headless etaoin.api2/with-browser
etaoin.api2/with-edge etaoin.api2/with-browser
etaoin.api2/with-edge-headless etaoin.api2/with-browser
etaoin.api2/with-firefox etaoin.api2/with-browser
etaoin.api2/with-firefox-headless etaoin.api2/with-browser
etaoin.api2/with-phantom etaoin.api2/with-browser
etaoin.api2/with-safari etaoin.api2/with-browser}}
:lint-as
{etaoin.api/with-pointer-left-btn-down clojure.core/->}}
53 changes: 53 additions & 0 deletions resources/clj-kondo.exports/etaoin/etaoin/etaoin/api.clj_kondo
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
(ns etaoin.api
(:require [clj-kondo.hooks-api :as api]
[etaoin.hooks-util :as h]))

(defn- with-bound-arg [node bound-arg-ndx]
(let [macro-args (rest (:children node))
binding-sym (nth macro-args bound-arg-ndx nil)]
(if-not (h/symbol-node? binding-sym)
;; could use clj-kondo findings, but I think this is good for now
(throw (ex-info (format "Expected binding symbol as %s arg"
;; use words instead of numbers to avoid ambiguity
(case 1 "second"
2 "third")) {}))
(let [leading-args (take bound-arg-ndx macro-args)
body (drop (inc bound-arg-ndx) macro-args)]
{:node (api/list-node
(list*
(api/token-node 'let)
;; simulate the effect, macro is creating a new thing (driver for example)
;; via binding it. I don't think the bound value matters for the linting process
(api/vector-node [binding-sym (api/map-node [])])
;; reference the other args so that they are not linted as unused
(api/vector-node leading-args)
body))}))))

(defn- with-x-down [node]
(let [macro-args (rest (:children node))
[leading-args body] (split-at 2 macro-args)]
{:node (api/list-node
(list*
(api/token-node 'do)
;; dump the body
(api/list-node (list* body))
;; reference the other args so that they are not linted as unused (if they happen to be symbols)
(api/vector-node leading-args)))}))

(defn with-browser
"Covers etaoin.api/with-chrome and all its variants
[opt bind & body]"
[{:keys [node]}]
(with-bound-arg node 1))

(defn with-driver
"Very similar to with-browser but bound arg is 1 deeper
[type opt bind & body]"
[{:keys [node]}]
(with-bound-arg node 2))

(defn with-key-down [{:keys [node]}]
(with-x-down node))

(defn with-pointer-btn-down [{:keys [node]}]
(with-x-down node))
27 changes: 27 additions & 0 deletions resources/clj-kondo.exports/etaoin/etaoin/etaoin/api2.clj_kondo
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
(ns etaoin.api2
(:require [clj-kondo.hooks-api :as api]
[etaoin.hooks-util :as h]))

(defn with-browser
"Newer variants for api2
[[bind & [options]] & body]"
[{:keys [node]}]
(let [macro-args (rest (:children node))
binding-like-vector (first macro-args)]
(if-not (api/vector-node? binding-like-vector)
;; could use clj-kondo findings, but I think this is good for now
(throw (ex-info "Expected vector for first arg" {}))
(let [binding-sym (-> binding-like-vector :children first)]
(if-not (h/symbol-node? binding-sym)
(throw (ex-info "Expected binding symbol for first arg in vector" {}))
(let [other-args (rest binding-like-vector)
body (rest macro-args)]
{:node (api/list-node
(list*
(api/token-node 'let)
;; simulate the effect, macro is creating a new thing (driver for example)
;; via binding it. I don't think the bound value matters for the linting process
(api/vector-node [binding-sym (api/map-node [])])
;; reference the other args so that they are not linted as unused
(api/vector-node other-args)
body))}))))))
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
(ns etaoin.hooks-util
(:require [clj-kondo.hooks-api :as api]))

(defn symbol-node? [node]
(and (api/token-node? node)
(symbol? (api/sexpr node))))
2 changes: 1 addition & 1 deletion script/test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
(and (= "windows" os) (= "safari" browser))))]
(test-def os "api" platform browser)))
(sort-by :desc)
(into []))))
(into [{:os "ubuntu" :cmd "bb lint" :desc "lint"}]))))

(defn- launch-xvfb []
(if (fs/which "Xvfb")
Expand Down
14 changes: 0 additions & 14 deletions src/etaoin/api.clj
Original file line number Diff line number Diff line change
Expand Up @@ -2132,20 +2132,6 @@
(def ^{:doc "Opposite of `exists?`."}
absent? (complement exists?))

;; NOTE: This doesn't appear to be as reliable as checking the `visibility` and
;; `display` attributes. See this issue, for example:
;; https://github.com/clj-commons/etaoin/issues/444
(defn- displayed-impl-value
"Returns the browser native `displayed` attribute for an element.
Reference:
https://www.w3.org/TR/webdriver/#element-displayedness"
[driver el]
{:pre [(some? el)]}
(:value (execute {:driver driver
:method :get
:path [:session (:session driver) :element el :displayed]})))

(defn- effectively-displayed?
[driver el]
{:pre [(some? el)]}
Expand Down
10 changes: 9 additions & 1 deletion test/etaoin/unit/unit_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
[clojure.spec.alpha :as s]
[clojure.test :refer :all]
[etaoin.api :refer :all]
[etaoin.api2 :as e2]
[etaoin.ide.flow :as ide]
[etaoin.ide.impl.spec :as spec]
[etaoin.test-report]
Expand Down Expand Up @@ -42,13 +43,20 @@
(is profile-path
(get-element-text driver :profile_path))))))

(deftest test-chrome-profile-using-v2-api
(fs/with-temp-dir [chrome-dir {:prefix "chrome-dir"}]
(let [profile-path (str (fs/file chrome-dir "chrome-profile"))]
(e2/with-chrome [driver {:profile profile-path :args ["--no-sandbox"]} ]
(go driver "chrome://version")
(is profile-path
(get-element-text driver :profile_path))))))

(deftest test-fail-run-driver
(is (thrown-with-msg?
clojure.lang.ExceptionInfo
#"wrong-driver-path"
(chrome {:path-driver "wrong-driver-path"}))))


(deftest test-actions
(let [keyboard (-> (make-key-input)
(with-key-down "H")
Expand Down

0 comments on commit 944ca90

Please sign in to comment.