Skip to content

Commit

Permalink
Merge pull request #178 from brandoncorrea/master
Browse files Browse the repository at this point in the history
Fixes macroexpansions and upgrades clojure(script) versions
  • Loading branch information
slagyr authored May 20, 2024
2 parents 018d40e + e4440ee commit 22d9ae5
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 50 deletions.
43 changes: 43 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -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@v4

- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: 21
distribution: 'temurin'

- name: Cache Clojure Dependencies
uses: actions/cache@v4
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
11 changes: 11 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions deps.edn
Original file line number Diff line number Diff line change
Expand Up @@ -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"]}
Expand All @@ -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"]
Expand Down
3 changes: 2 additions & 1 deletion spec/speclj/core_spec.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
99 changes: 54 additions & 45 deletions src/speclj/core.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -216,31 +216,32 @@
(-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."
[message]
`(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."
Expand Down Expand Up @@ -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)")))
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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) "<nothing thrown>")]
actual-string# (if-let [actual# ~actual] (pr-str actual#) "<nothing thrown>")]
(-new-failure (str "Expected " expected-name# " thrown from: " (pr-str ~expr) speclj.platform/endl
" " expected-gaps# " but got: " actual-string#))))

Expand All @@ -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#))))))))

Expand Down Expand Up @@ -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
Expand All @@ -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))))

0 comments on commit 22d9ae5

Please sign in to comment.