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

Add support for wide characters to fill functions #552

Merged
merged 10 commits into from
Apr 30, 2023
2 changes: 2 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ A release with an intentional breaking changes is marked with:

== Unreleased

* https://github.com/clj-commons/etaoin/pull/552[#552]: Add support for wide characters to input fill functions
(https://github.com/tupini07[@tupini07])
* bump all deps to current versions
* docs
** https://github.com/clj-commons/etaoin/issues/534[#534]: better describe `etaoin.api/select` and its alternatives
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
- include changes unrelated to the purpose of the PR. This includes changing the project version number, adding lines to the
`.gitignore` file, or changing the indentation or formatting.
- open a new PR if changes are requested. Just push to the same branch and the PR will be updated.
- ever force push on a PR, it makes it too hard to review.
- never force push on a PR, it makes it too hard to review.
- overuse vertical whitespace; avoid multiple sequential blank lines.

[1]: https://chris.beams.io/posts/git-commit/#seven-rules
Expand Down
1 change: 1 addition & 0 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ Can be `alpha`, `beta`, `rc1`, etc.
* https://github.com/kidd[Raimon Grau]
* https://github.com/verma[Uday Verma]
* https://github.com/mjmeintjes[Matt Meintjes]
* https://github.com/tupini07[Andrea Tupini]

=== Current Maintainers

Expand Down
26 changes: 25 additions & 1 deletion doc/01-user-guide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,27 @@ You can collect elements into a vector and arbitrarily interact with them at any

Some basic interactions are covered under <<querying>>, here we go into other types of interactions and more detail.

=== UNICODE and Emojis
As of this writing, Chrome and Edge https://bugs.chromium.org/p/chromedriver/issues/detail?id=2269[only support] filling inputs with UNICODE in the https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane[Basic Multilingual Plane].
This includes many characters, but not many emojis 😢.

Firefox and Safari seem to support UNICODE more generally 🙂.

[source,clojure]
----
(e/with-chrome driver
(e/go driver sample-page)
(e/fill driver :uname "ⱾⱺⱮⱸ ᢹⓂ Ᵽ")
(e/get-element-value driver :uname))
;; => "ⱾⱺⱮⱸ ᢹⓂ Ᵽ"

(e/with-firefox driver
(e/go driver sample-page)
(e/fill driver :uname "ⱾⱺⱮⱸ ᢹⓂ Ᵽ plus 👍🔥🙂")
(e/get-element-value driver :uname))
;; => "ⱾⱺⱮⱸ ᢹⓂ Ᵽ plus 👍🔥🙂"
----

=== Emulate how a Real Person Might Type

Real people type slowly and make mistakes.
Expand All @@ -861,6 +882,9 @@ which you can choose to override if you wish:

;; or just use default options by omitting them
(e/fill-human driver :uname " typing human defaults")

(e/get-element-value driver :uname)
;; => "soslowsobad typing human defaults"
----

For multiple inputs, use `fill-human-multi`
Expand Down Expand Up @@ -2132,7 +2156,7 @@ Example: `:log-level :err`

| `:all`

a| `driver-log-level` *WebDriver* minimal log level.
a| `:driver-log-level` *WebDriver* minimal log level.
values vary by browser driver vendor:

* chrome `"OFF"` `"SEVERE"` `"WARNING"` `"INFO"` or `"DEBUG"`
Expand Down
17 changes: 14 additions & 3 deletions src/etaoin/api.clj
Original file line number Diff line number Diff line change
Expand Up @@ -2809,8 +2809,19 @@
;; input
;;

(defn- codepoints
"Clojure returns a seq of chars for a string.
This does not handle wide (unicode) characters.
Here we return a seq of codepoint strings for string `s`."
[s]
(->> s
.codePoints
.iterator
iterator-seq
(map #(Character/toString %))))

(defn- make-input* [text & more]
(mapv str (apply str text more)))
(codepoints (apply str text more)))

(defmulti fill-el
"Have `driver` fill input element `el` with `text` (and optionally `more` text)."
Expand Down Expand Up @@ -2908,13 +2919,13 @@
wait-key (fn [] (wait (min (rand) pause-max)))]
(click-el driver el)
(wait-key)
(doseq [key text]
(doseq [c (codepoints text)]
(when (< (rand) mistake-prob)
(fill-el driver el (rand-char))
(wait-key)
(fill-el driver el k/backspace)
(wait-key))
(fill-el driver el key)
(fill-el driver el c)
(wait-key))))

(defn fill-human
Expand Down
37 changes: 34 additions & 3 deletions test/etaoin/api_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,11 @@
(-> e/get-url
(str/ends-with? "?login=1&password=2&message=3")
is)))
(testing "fill human multiple imputs"
(testing "fill human multiple inputs"
(doto *driver*
(e/fill-human-multi {:simple-input "login"
:simple-password "123"
:simple-textarea "text"})
:simple-password "123"
:simple-textarea "text"})
(e/click :simple-submit)
(e/when-safari (e/wait 3))
(-> e/get-url
Expand All @@ -125,6 +125,37 @@
(str/ends-with? "?login=1test2+A&password=&message=")
is))))

(deftest test-unicode-bmp-input
(let [data {:simple-input "ĩṋṗṵţ"
:simple-password "ǷḁṡṢẅỏṟƉ"
:simple-textarea "т️ẹẍṱảṙẸẚ"}]
(testing "fill-multi"
(e/fill-multi *driver* data)
(doseq [f [:simple-input :simple-password :simple-textarea]]
(is (= (f data) (e/get-element-value *driver* f)))))
(testing "fill-human-multi"
(e/refresh *driver*)
(e/fill-human-multi *driver* data)
(doseq [f [:simple-input :simple-password :simple-textarea]]
(is (= (f data) (e/get-element-value *driver* f)))))))

(deftest test-unicode-above-bmp-input
;; as of 2023-04-29 not supported on chrome and edge
;; https://bugs.chromium.org/p/chromedriver/issues/detail?id=2269
(when-not (#{:chrome :edge} (e/dispatch-driver *driver*))
(let [data {:simple-input "😊🍂input🍃"
:simple-password "🔆password☠️ "
:simple-textarea "🎉🚀textarea👀☀️"}]
(testing "fill-multi"
(e/fill-multi *driver* data)
(doseq [f [:simple-input :simple-password :simple-textarea]]
(is (= (f data) (e/get-element-value *driver* f)))))
(testing "fill-human-multi"
(e/refresh *driver*)
(e/fill-human-multi *driver* data)
(doseq [f [:simple-input :simple-password :simple-textarea]]
(is (= (f data) (e/get-element-value *driver* f))))))))

(deftest test-clear
(testing "simple clear"
(doto *driver*
Expand Down