<commit_before>(ns quil.snippet
  (:require [quil.core :as q]
            [quil.snippets.all-snippets :as as]
            [clojure.edn :as edn]
            [clojure.java.io :as io]
            [clojure.test :as t]
            [clojure.java.shell :as sh]
            [clojure.string :as string]
            [etaoin.api :as e]
            clojure.pprint))

(def default-size [500 500])

(def manual? (-> (System/getenv) (get "MANUAL") boolean))

(def tests-in-set 50)
(def current-test (atom -1))

(defn skip-automated-compare? [snippet-name]
  (contains? #{"current-frame-rate-target-frame-rate"
               "noise"
               "noise-detail"
               "random-2d"
               "random-3d"
               "random"
               "random-gaussian"
               "resize-sketch"
               "save"
               "time-and-date"} snippet-name))

(defn- compare-images [expected actual difference]
  (let [{:keys [err]} (sh/sh "compare" "-metric" "mae" expected actual difference)
        result        (second (re-find #"\((.*)\)" err))]
    (edn/read-string result)))

(defn- replace-suffix [file-name suffix]
  (string/replace file-name #"(\w+)\.(\w+)$" (str suffix ".$2")))

(defn assert-unchanged-snippet-output [name]
  (when-not (skip-automated-compare? name)
    (let [n          (str "snippet-snapshots/clj/" name)
          _          (q/save (str "resources/" n "-actual.png"))
          expected   (.getAbsolutePath (io/file (io/resource (str n "-expected.png"))))
          actual     (replace-suffix expected "actual")
          difference (replace-suffix expected "difference")
          result     (compare-images expected actual difference)
          threshold  0.02]
      (when (<= result threshold)
        (io/delete-file (io/file actual))
        (io/delete-file (io/file difference)))
      (t/is (<= result threshold)))))

(defn run-snippet-as-test [{:keys [ns name opts setup body body-str mouse-clicked]}]
  (let [result (promise)
        snip-name (str ns "/" name)]
    (println mouse-clicked)
    (println "Test:" snip-name)
    (when manual?
      (clojure.pprint/pprint body-str))
    (q/sketch
     :title snip-name
     :size (:size opts default-size)
     :renderer (:renderer opts :java2d)
     :setup (fn []
              (setup)
              (q/frame-rate 5))
     :mouse-clicked mouse-clicked
     :settings (fn []
                 (:settings opts))
     :draw (fn []
             (try
               (q/background 255)
               (body)
               (assert-unchanged-snippet-output name)
               (catch Exception e
                 (println "Error" e)
                 (.printStackTrace e)
                 (deliver result e))
               (finally
                 (when (not manual?)
                   (q/exit)))))
     :on-close #(deliver result nil))
    (t/is (nil? @result))))

(defn define-snippet-as-test [{:keys [ns name opts setup body] :as snippet}]
  (let [test-name (str (string/replace ns "." "_")
                       "_"
                       name)]
    (intern 'quil.snippet
            (vary-meta (symbol test-name) assoc
                       :test #(run-snippet-as-test snippet)
                       :test-set (let [cur (swap! current-test inc)
                                       set (quot cur tests-in-set)]
                                   (when (zero? (mod cur tests-in-set))
                                     (println "Test set" set (str " Run with: lein test :set-" set)))
                                   set))
            (fn []
              (q/sketch
               :title name
               :size default-size
               :setup (fn []
                        (q/frame-rate 5)
                        (setup))
               :renderer (:renderer opts :java2d)
               :draw body)))))

(doseq [snippet as/all-snippets]
  (define-snippet-as-test snippet))

(t/deftest all-snippets-map-to-function
  (doseq [{:keys [fns name]} as/all-snippets
          fn fns]
    (when (nil? (ns-resolve 'quil.core (symbol fn)))
      (throw (ex-info (str "Snippet '" name "' matches to non-existent function '" fn "'")
                      {}))))
  (t/is true))

(t/deftest ^:manual
  all-cljs-snippets-produce-expected-output
  (let [driver (e/firefox)
        threshold 0.0001]
    (e/go driver (str "http://localhost:3000/test.html"))
    (let [elements (e/query-all driver {:tag :option})
          names    (doall (map #(e/get-element-text-el driver %) elements))
          c        (count elements)]
      (dotimes [i c]
        (let [name       (nth names i)
              n          (str "snippet-snapshots/cljs/" name "-expected.png")
              expected   (.getAbsolutePath (io/file (io/resource n)))
              actual     (replace-suffix expected "actual")
              difference (replace-suffix expected "difference")]
          (when-not (skip-automated-compare? name)
            (e/go driver (str "http://localhost:3000/test.html#" i))
            (e/refresh driver)
            (e/screenshot-element driver {:tag :canvas} actual)
            (let [result (compare-images expected actual difference)]
              (when (<= result threshold)
                (io/delete-file (io/file actual))
                (io/delete-file (io/file difference)))
              (t/is (<= result threshold)
                    (str "Image comparison for " name " not within acceptable threshold: " threshold)))))))
    (e/quit driver)))<commit_msg>Rename ns alias to `etaoin` in `snippet.clj`.<commit_after>(ns quil.snippet
  (:require [quil.core :as q]
            [quil.snippets.all-snippets :as as]
            [clojure.edn :as edn]
            [clojure.java.io :as io]
            [clojure.test :as t]
            [clojure.java.shell :as sh]
            [clojure.string :as string]
            [etaoin.api :as etaoin]
            clojure.pprint))

(def default-size [500 500])

(def manual? (-> (System/getenv) (get "MANUAL") boolean))

(def tests-in-set 50)
(def current-test (atom -1))

(defn skip-automated-compare? [snippet-name]
  (contains? #{"current-frame-rate-target-frame-rate"
               "noise"
               "noise-detail"
               "random-2d"
               "random-3d"
               "random"
               "random-gaussian"
               "resize-sketch"
               "save"
               "time-and-date"} snippet-name))

(defn- compare-images [expected actual difference]
  (let [{:keys [err]} (sh/sh "compare" "-metric" "mae" expected actual difference)
        result        (second (re-find #"\((.*)\)" err))]
    (edn/read-string result)))

(defn- replace-suffix [file-name suffix]
  (string/replace file-name #"(\w+)\.(\w+)$" (str suffix ".$2")))

(defn assert-unchanged-snippet-output [name]
  (when-not (skip-automated-compare? name)
    (let [n          (str "snippet-snapshots/clj/" name)
          _          (q/save (str "resources/" n "-actual.png"))
          expected   (.getAbsolutePath (io/file (io/resource (str n "-expected.png"))))
          actual     (replace-suffix expected "actual")
          difference (replace-suffix expected "difference")
          result     (compare-images expected actual difference)
          threshold  0.02]
      (when (<= result threshold)
        (io/delete-file (io/file actual))
        (io/delete-file (io/file difference)))
      (t/is (<= result threshold)))))

(defn run-snippet-as-test [{:keys [ns name opts setup body body-str mouse-clicked]}]
  (let [result (promise)
        snip-name (str ns "/" name)]
    (println mouse-clicked)
    (println "Test:" snip-name)
    (when manual?
      (clojure.pprint/pprint body-str))
    (q/sketch
     :title snip-name
     :size (:size opts default-size)
     :renderer (:renderer opts :java2d)
     :setup (fn []
              (setup)
              (q/frame-rate 5))
     :mouse-clicked mouse-clicked
     :settings (fn []
                 (:settings opts))
     :draw (fn []
             (try
               (q/background 255)
               (body)
               (assert-unchanged-snippet-output name)
               (catch Exception e
                 (println "Error" e)
                 (.printStackTrace e)
                 (deliver result e))
               (finally
                 (when (not manual?)
                   (q/exit)))))
     :on-close #(deliver result nil))
    (t/is (nil? @result))))

(defn define-snippet-as-test [{:keys [ns name opts setup body] :as snippet}]
  (let [test-name (str (string/replace ns "." "_")
                       "_"
                       name)]
    (intern 'quil.snippet
            (vary-meta (symbol test-name) assoc
                       :test #(run-snippet-as-test snippet)
                       :test-set (let [cur (swap! current-test inc)
                                       set (quot cur tests-in-set)]
                                   (when (zero? (mod cur tests-in-set))
                                     (println "Test set" set (str " Run with: lein test :set-" set)))
                                   set))
            (fn []
              (q/sketch
               :title name
               :size default-size
               :setup (fn []
                        (q/frame-rate 5)
                        (setup))
               :renderer (:renderer opts :java2d)
               :draw body)))))

(doseq [snippet as/all-snippets]
  (define-snippet-as-test snippet))

(t/deftest all-snippets-map-to-function
  (doseq [{:keys [fns name]} as/all-snippets
          fn fns]
    (when (nil? (ns-resolve 'quil.core (symbol fn)))
      (throw (ex-info (str "Snippet '" name "' matches to non-existent function '" fn "'")
                      {}))))
  (t/is true))

(t/deftest ^:manual
  all-cljs-snippets-produce-expected-output
  (let [driver (etaoin/firefox)
        threshold 0.0001]
    (etaoin/go driver "http://localhost:3000/test.html")
    (let [elements (etaoin/query-all driver {:tag :option})
          names    (doall (map #(etaoin/get-element-text-el driver %) elements))]
      (dotimes [i (count elements)]
        (let [name       (nth names i)
              n          (str "snippet-snapshots/cljs/" name "-expected.png")
              expected   (.getAbsolutePath (io/file (io/resource n)))
              actual     (replace-suffix expected "actual")
              difference (replace-suffix expected "difference")]
          (when-not (skip-automated-compare? name)
            (etaoin/go driver (str "http://localhost:3000/test.html#" i))
            (etaoin/refresh driver)
            (etaoin/screenshot-element driver {:tag :canvas} actual)
            (let [result (compare-images expected actual difference)]
              (when (<= result threshold)
                (io/delete-file (io/file actual))
                (io/delete-file (io/file difference)))
              (t/is (<= result threshold)
                    (str "Image comparison for " name " not within acceptable threshold: " threshold)))))))
    (etaoin/quit driver)))
{'fraction_non_alphanumeric': 0.1402294663995629, 'fraction_numerical': 0.006374066654525588, 'mean_word_length': 1.6586782861292666, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '741886', 'n_tokens_mistral': 3398, 'n_tokens_neox': 3249, 'n_words': 840}