From 55d80a83563fcaf6ebaab71259451458f0924921 Mon Sep 17 00:00:00 2001 From: Brandon Correa <50252804+brandoncorrea@users.noreply.github.com> Date: Sun, 12 May 2024 14:22:23 -0500 Subject: [PATCH 1/7] Fix cljs macroexpansion in should-throw & update some other macros to only evaluate parameters once --- src/speclj/core.cljc | 99 ++++++++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 45 deletions(-) diff --git a/src/speclj/core.cljc b/src/speclj/core.cljc index 188954a..d8e9bd4 100644 --- a/src/speclj/core.cljc +++ b/src/speclj/core.cljc @@ -216,7 +216,7 @@ (-make-with name body `speclj.components/new-with-all true)) (defmacro ^:no-doc -to-s [thing] - `(if (nil? ~thing) "nil" (pr-str ~thing))) + `(if-some [thing# ~thing] (pr-str thing#) "nil")) (defmacro -fail "Useful for making custom assertions." @@ -224,23 +224,24 @@ `(throw (-new-failure ~message))) (defmacro ^:no-doc wrong-types [assertion a b] - `(let [type-a# (if (nil? ~a) "nil" (speclj.platform/type-name (type ~a))) - type-b# (if (nil? ~b) "nil" (speclj.platform/type-name (type ~b)))] + `(let [a# ~a + b# ~b + type-a# (if (nil? a#) "nil" (speclj.platform/type-name (type a#))) + type-b# (if (nil? b#) "nil" (speclj.platform/type-name (type b#)))] (str ~assertion " doesn't know how to handle these types: [" type-a# " " type-b# "]"))) (defmacro should "Asserts the truthy-ness of a form" [form] `(let [value# ~form] - (if-not value# + (when-not value# (-fail (str "Expected truthy but was: " (-to-s value#) ""))))) (defmacro should-not "Asserts the falsy-ness of a form" [form] - `(let [value# ~form] - (when value# - (-fail (str "Expected falsy but was: " (-to-s value#)))))) + `(when-let [value# ~form] + (-fail (str "Expected falsy but was: " (-to-s value#))))) (defmacro should= "Asserts that two forms evaluate to equal values, with the expected value as the first parameter." @@ -325,7 +326,7 @@ `(let [expected# ~expected actual# ~actual] (cond - (nil? actual#) nil ; automatic pass! + (nil? actual#) nil ; automatic pass! (and (string? expected#) (string? actual#)) (when (not (= -1 (.indexOf actual# expected#))) (-fail (str "Expected: " (-to-s expected#) speclj.platform/endl "not to be in: " (-to-s actual#) " (using .contains)"))) @@ -378,25 +379,28 @@ "Collection: " (-to-s coll#)))))))) (defmacro ^:no-doc -remove-first [coll value] - `(loop [coll# ~coll seen# []] - (if (empty? coll#) - seen# - (let [f# (first coll#)] - (if (= f# ~value) - (concat seen# (rest coll#)) - (recur (rest coll#) (conj seen# f#))))))) + `(let [value# ~value] + (loop [coll# ~coll seen# []] + (if (empty? coll#) + seen# + (let [f# (first coll#)] + (if (= f# value#) + (concat seen# (rest coll#)) + (recur (rest coll#) (conj seen# f#)))))))) (defmacro ^:no-doc -coll-difference [coll1 coll2] - `(if (map? ~coll1) - (first (clojure.data/diff ~coll1 ~coll2)) - (loop [match-with# ~coll1 match-against# ~coll2 diff# []] - (if (empty? match-with#) - diff# - (let [f# (first match-with#) - r# (rest match-with#)] - (if (some #(= % f#) match-against#) - (recur r# (-remove-first match-against# f#) diff#) - (recur r# match-against# (conj diff# f#)))))))) + `(let [coll1# ~coll1 + coll2# ~coll2] + (if (map? coll1#) + (first (clojure.data/diff coll1# coll2#)) + (loop [match-with# coll1# match-against# coll2# diff# []] + (if (empty? match-with#) + diff# + (let [f# (first match-with#) + r# (rest match-with#)] + (if (some #(= % f#) match-against#) + (recur r# (-remove-first match-against# f#) diff#) + (recur r# match-against# (conj diff# f#))))))))) (defmacro should-start-with "Assertion of prefix in strings and sequences. @@ -554,7 +558,7 @@ (defmacro ^:no-doc -create-should-throw-failure [expected actual expr] `(let [expected-name# (speclj.platform/type-name ~expected) expected-gaps# (apply str (repeat (count expected-name#) " ")) - actual-string# (if ~actual (pr-str ~actual) "")] + actual-string# (if-let [actual# ~actual] (pr-str actual#) "")] (-new-failure (str "Expected " expected-name# " thrown from: " (pr-str ~expr) speclj.platform/endl " " expected-gaps# " but got: " actual-string#)))) @@ -579,14 +583,15 @@ There are three options for passing different kinds of predicates: `(let [e# (should-throw ~throwable-type ~form) regex# (if-cljs js/RegExp java.util.regex.Pattern)] (try-catch-anything - (cond (instance? regex# ~predicate) - (should-not-be-nil (re-find ~predicate (speclj.platform/error-message e#))) + (let [predicate# ~predicate] + (cond (instance? regex# predicate#) + (should-not-be-nil (re-find predicate# (speclj.platform/error-message e#))) - (ifn? ~predicate) - (should= true (~predicate e#)) + (ifn? predicate#) + (should= true (predicate# e#)) - :else - (should= ~predicate (speclj.platform/error-message e#))) + :else + (should= predicate# (speclj.platform/error-message e#)))) (catch f# (-fail (str "Expected exception predicate didn't match" speclj.platform/endl (speclj.platform/error-message f#)))))))) @@ -811,30 +816,34 @@ There are three options for passing different kinds of predicates: (defmacro should< "Asserts that the first numeric form is less than the second numeric form, using the built-in < function." [a b] - `(cond - (not (and (number? ~a) (number? ~b))) (throw (-new-exception (wrong-types "should<" ~a ~b))) - :else (when-not (< ~a ~b) (-fail (str "expected " ~a " to be less than " ~b " but got: (< " ~a " " ~b ")"))))) + `(let [a# ~a b# ~b] + (if (and (number? a#) (number? b#)) + (when-not (< a# b#) (-fail (str "expected " a# " to be less than " b# " but got: (< " a# " " b# ")"))) + (throw (-new-exception (wrong-types "should<" a# b#)))))) (defmacro should> "Asserts that the first numeric form is greater than the second numeric form, using the built-in > function." [a b] - `(cond - (not (and (number? ~a) (number? ~b))) (throw (-new-exception (wrong-types "should>" ~a ~b))) - :else (when-not (> ~a ~b) (-fail (str "expected " ~a " to be greater than " ~b " but got: (> " ~a " " ~b ")"))))) + `(let [a# ~a b# ~b] + (if (and (number? a#) (number? b#)) + (when-not (> a# b#) (-fail (str "expected " a# " to be greater than " b# " but got: (> " a# " " b# ")"))) + (throw (-new-exception (wrong-types "should>" a# b#)))))) (defmacro should<= "Asserts that the first numeric form is less than or equal to the second numeric form, using the built-in <= function." [a b] - `(cond - (not (and (number? ~a) (number? ~b))) (throw (-new-exception (wrong-types "should<=" ~a ~b))) - :else (when-not (<= ~a ~b) (-fail (str "expected " ~a " to be less than or equal to " ~b " but got: (<= " ~a " " ~b ")"))))) + `(let [a# ~a b# ~b] + (if (and (number? a#) (number? b#)) + (when-not (<= a# b#) (-fail (str "expected " a# " to be less than or equal to " b# " but got: (<= " a# " " b# ")"))) + (throw (-new-exception (wrong-types "should<=" a# b#)))))) (defmacro should>= "Asserts that the first numeric form is greater than or equal to the second numeric form, using the built-in >= function." [a b] - `(cond - (not (and (number? ~a) (number? ~b))) (throw (-new-exception (wrong-types "should>=" ~a ~b))) - :else (when-not (>= ~a ~b) (-fail (str "expected " ~a " to be greater than or equal to " ~b " but got: (>= " ~a " " ~b ")"))))) + `(let [a# ~a b# ~b] + (if (and (number? a#) (number? b#)) + (when-not (>= a# b#) (-fail (str "expected " a# " to be greater than or equal to " b# " but got: (>= " a# " " b# ")"))) + (throw (-new-exception (wrong-types "should>=" a# b#)))))) (defmacro run-specs [] "If evaluated outside the context of a spec run, it will run all the specs that have been evaluated using the default @@ -845,5 +854,5 @@ are evaluated by evaluation the file as a script. Optional configuration parame `(if-cljs (comment "Ignoring run-specs for clojurescript") (do - (require '[speclj.cli]) ; require all speclj files + (require '[speclj.cli]) ; require all speclj files (speclj.run.standard/run-specs)))) From e54ea6a08013b2d254c3d78ef9a98352be67b5fc Mon Sep 17 00:00:00 2001 From: Brandon Correa <50252804+brandoncorrea@users.noreply.github.com> Date: Thu, 16 May 2024 12:07:59 -0500 Subject: [PATCH 2/7] Add steps for local reference --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 839714d..723df74 100644 --- a/README.md +++ b/README.md @@ -344,6 +344,20 @@ clj -T:build clean clj -M:test:cljs ``` +To include in a local project + +```bash +clj -T:build clean +clj -T:build javac +clj -T:build jar +``` + +In deps.edn + +```clojure +{speclj/speclj {:local/root "/path/to/speclj/target/speclj-3.4.6.jar"}} +``` + Make patches and submit them along with an issue (see below). ## Issues From 147556176faa01e32dffff00d7a7826ab57c22d6 Mon Sep 17 00:00:00 2001 From: Brandon Correa <50252804+brandoncorrea@users.noreply.github.com> Date: Thu, 16 May 2024 12:18:47 -0500 Subject: [PATCH 3/7] Upgrade clojure/script versions --- deps.edn | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deps.edn b/deps.edn index c19ba52..06c6ec1 100644 --- a/deps.edn +++ b/deps.edn @@ -3,14 +3,14 @@ :deps { fresh/fresh {:mvn/version "1.1.2"} mmargs/mmargs {:mvn/version "1.2.0"} - org.clojure/clojure {:mvn/version "1.11.1"} + org.clojure/clojure {:mvn/version "1.11.3"} trptcolin/versioneer {:mvn/version "0.1.1"} } :aliases { :test {:extra-deps { io.github.clojure/tools.build {:mvn/version "0.9.5"} - org.clojure/clojurescript {:mvn/version "1.11.60"} - cloverage/cloverage {:mvn/version "1.2.4"} + org.clojure/clojurescript {:mvn/version "1.11.132"} + cloverage/cloverage {:mvn/version "1.2.4"} } :extra-paths ["dev" "spec" "target/classes"]} :spec {:main-opts ["-m" "speclj.main" "-c"]} @@ -19,7 +19,7 @@ clj-commons/pomegranate {:mvn/version "1.2.23"}} :ns-default build :extra-paths ["dev"]} - :cov {:main-opts ["-m" "cloverage.coverage" "--runner" ":speclj" "-p" "src" "-s" "spec" "-e" "leiningen.spec" "--foo" "bar"]} + :cov {:main-opts ["-m" "cloverage.coverage" "--runner" ":speclj" "-p" "src" "-s" "spec" "-e" "leiningen.spec" "--foo" "bar"]} :codox {:extra-deps {codox/codox {:mvn/version "0.10.8"}} :exec-fn codox.main/generate-docs :exec-args {:source-paths ["src"] From 12f229bacfc0f11ce81516a392b846ca12814065 Mon Sep 17 00:00:00 2001 From: Brandon Correa <50252804+brandoncorrea@users.noreply.github.com> Date: Thu, 16 May 2024 13:20:08 -0500 Subject: [PATCH 4/7] Fix spec that was failing cljs with whitespace optimizations --- spec/speclj/core_spec.cljc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/speclj/core_spec.cljc b/spec/speclj/core_spec.cljc index 60a6121..bc15c3e 100644 --- a/spec/speclj/core_spec.cljc +++ b/spec/speclj/core_spec.cljc @@ -200,8 +200,9 @@ (swap! widget #(/ % 2))) (around-all [context] + (swap! widget #(- % 2)) (context)) - (swap! widget #(- % 2))) + ) (describe "previous after-all and around-all forms" (it "executes before after-alls regardless of definition order" From 94a33c049c45041c987f0011dad23e1f01e85b29 Mon Sep 17 00:00:00 2001 From: Brandon Correa <50252804+brandoncorrea@users.noreply.github.com> Date: Thu, 16 May 2024 13:22:27 -0500 Subject: [PATCH 5/7] 3.4.6 and 3.4.7 changes --- CHANGES.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index ecedac3..1b00e87 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,14 @@ +# 3.4.7 + +* fixes bug where `should-throw` would expand string predicates improperly under cljs whitespace optimizations. +* fixes `should<`, `should<=`, `should>`, `should>=`, and other macros to only evaluate forms once. +* upgrades to clojure 1.11.3 +* upgrades to clojurescript 1.11.132 + +# 3.4.6 + +* adds cloverage support + # 3.4.5 * 3.4.4 was a failed deploy... no compiled java code. From a21e05f2d356c13965ac542bf277fac2dc555ea4 Mon Sep 17 00:00:00 2001 From: Brandon Correa <50252804+brandoncorrea@users.noreply.github.com> Date: Fri, 17 May 2024 14:43:40 -0500 Subject: [PATCH 6/7] Add github test workflow --- .github/workflows/test.yml | 43 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..f4d7bc9 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,43 @@ +name: Run Specs + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: 21 + distribution: 'temurin' + + - name: Cache Clojure Dependencies + uses: actions/cache@v3 + with: + path: ~/.m2 + key: ${{ runner.os }}-deps-${{ hashFiles('**/deps.edn') }} + restore-keys: | + ${{ runner.os }}-deps- + + - name: Install Clojure CLI + run: curl -O https://download.clojure.org/install/linux-install-1.11.1.1119.sh && chmod +x linux-install-1.11.1.1119.sh && sudo ./linux-install-1.11.1.1119.sh + + - name: Build JAR + run: clojure -T:build jar + + - name: Install NPM Dependencies + run: npm install + + - name: Run Clojure Tests + run: clojure -M:test:spec + + - name: Run ClojureScript Tests + run: clojure -M:test:cljs once From e4440ee8adcbaa13e10015146d6f861dda2a5e49 Mon Sep 17 00:00:00 2001 From: Brandon Correa <50252804+brandoncorrea@users.noreply.github.com> Date: Fri, 17 May 2024 20:54:42 -0500 Subject: [PATCH 7/7] Upgrade github checkout and cache actions --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f4d7bc9..995d4cf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK 21 uses: actions/setup-java@v4 @@ -20,7 +20,7 @@ jobs: distribution: 'temurin' - name: Cache Clojure Dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.m2 key: ${{ runner.os }}-deps-${{ hashFiles('**/deps.edn') }}