From 5beefe3e39493f9ec88039b2fcecfed8cea1789b Mon Sep 17 00:00:00 2001 From: Dave Roberts Date: Mon, 16 Sep 2024 10:41:14 -0500 Subject: [PATCH] Throw exception for unknown :fn/* function keywords (#670) --- CHANGELOG.adoc | 1 + src/etaoin/impl/xpath.clj | 14 ++++++++++++-- test/etaoin/api_test.clj | 5 ++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 824af07..5c24dc2 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -33,6 +33,7 @@ A release with an intentional breaking changes is marked with: ** {issue}661[#661]: Fix `:fn/enabled`. ({person}dgr[@dgr]) ** {issue}663[#663]: `query` throws a more accurate exception with a more accurate error message when provided with an empty query vector. ({person}dgr[@dgr]) ** {issue}666[#666]: Previously, in some error conditions, Etaoin would throw a very generic `clojure.lang.Exception` object. Some of those cases have been replaced by throwing a map with Slingshot, providing more information about the problem. ({person}dgr[@dgr]) +** {issue}668[#668]: Throw an exception for unknown `:fn/*` keywords in map queries. * Docs ** {issue}656[#656]: Correctly describe behavior when query's parameter is a string. The User Guide and `query` doc strings say that a string passed to `query` is interpreted as an XPath expression. In fact, `query` interprets this as either XPath or CSS depending on the setting of the driver's `:locator` parameter, which can be changed. ({person}dgr[@dgr]) * Quality diff --git a/src/etaoin/impl/xpath.clj b/src/etaoin/impl/xpath.clj index 060788d..028ba50 100644 --- a/src/etaoin/impl/xpath.clj +++ b/src/etaoin/impl/xpath.clj @@ -1,6 +1,7 @@ (ns ^:no-doc etaoin.impl.xpath "A special module to work with XPath language." - (:require [clojure.string :as string])) + (:require [clojure.string :as string] + [slingshot.slingshot :refer [throw+]])) (set! *warn-on-reflection* true) @@ -49,7 +50,16 @@ (defmethod clause :default [[attr text]] - (node-equals (format "@%s" (to-str attr)) text)) + ;; If we fall through to the default case and yet the attribute + ;; looks like a query function, then the user probably has a typo + ;; in their program, so we throw. + ;; Else treat it like an attribute + (if (and (keyword? attr) (= (namespace attr) "fn")) + (throw+ {:type :etaoin/argument + :message "Unknown query function" + :fn attr + :arg text}) + (node-equals (format "@%s" (to-str attr)) text))) (defmethod clause :fn/text [[_ text]] diff --git a/test/etaoin/api_test.clj b/test/etaoin/api_test.clj index 522bb08..8d3bde1 100644 --- a/test/etaoin/api_test.clj +++ b/test/etaoin/api_test.clj @@ -935,7 +935,10 @@ ;; 3. malformed XPath ;; 4. malformed CSS ;; 5. query isn't a string, map, or vector. Perhaps a list and set. - ;; 6. bad :fn/... keywords + ;; 6. unknown :fn/... keywords + (testing "unknown :fn/* keywords" + ;; ":fn/indx" is probably a typo and the user really wants ":fn/index" + (is (thrown+? [:type :etaoin/argument] (e/query *driver* {:tag :div :fn/indx 1})))) ;; 7. vector queries with vector elements (vectors in vectors) ))