Skip to content

Commit

Permalink
Merge pull request #183 from brandoncorrea/clr
Browse files Browse the repository at this point in the history
Add Support for ClojureCLR
  • Loading branch information
slagyr authored Jan 10, 2025
2 parents 5c79fdd + b26edf5 commit 8e37dca
Show file tree
Hide file tree
Showing 71 changed files with 1,908 additions and 919 deletions.
13 changes: 12 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ jobs:
java-version: 21
distribution: 'temurin'

- name: Prepare dotnet
uses: xt0rted/[email protected]

- name: Prepare Clojure CLR
run: |
dotnet tool install --global Clojure.Main --version 1.12.0-alpha10
dotnet tool install --global Clojure.Cljr --version 0.1.0-alpha5
- name: Cache Clojure Dependencies
uses: actions/cache@v4
with:
Expand All @@ -36,8 +44,11 @@ jobs:
- name: Install NPM Dependencies
run: npm install

- name: Run Clojure Tests
- name: Run Clojure JVM Tests
run: clojure -M:test:spec

- name: Run Clojure CLR Tests
run: cljr -M:test:spec

- name: Run ClojureScript Tests
run: clojure -M:test:cljs ci
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
.cpcache
.DS_Store
.idea
.lein*
.clj-kondo
.lsp
.specljs-timestamp
doc
node_modules
Expand Down
7 changes: 7 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# Next
* Replaces `SpecFailure` and `SpecPending` classes with `ex-info`
* Replaces `mmargs` library with a Clojure implementation
* Adds support for Clojure CLR
* Upgrades dependencies
* Removes clojure/java.data dependency

# 3.5.0

* migrates from deprecated make-fresh library to clojure.tools.namespace
Expand Down
51 changes: 36 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ It's a TDD/BDD framework for [Clojure](http://clojure.org/) and [Clojurescript](

[![Speclj Build](https://github.com/slagyr/speclj/actions/workflows/test.yml/badge.svg)](https://github.com/slagyr/speclj/actions/workflows/test.yml)

[Installation](#installation) | [Clojure](#clojure) | [ClojureScript](#clojurescript)
[Installation](#installation) | [Clojure](#clojure) | [ClojureScript](#clojurescript) | [Clojure CLR](#clojureclr)

# Installation

Expand Down Expand Up @@ -33,9 +33,9 @@ Include speclj in your `:dev` profile `:dependencies` and`:plugins`. Then change
```clojure
; - snip
:dependencies [[org.clojure/clojure "1.11.3"]]
:profiles {:dev {:dependencies [[speclj "3.4.9"]]}}
:plugins [[speclj "3.4.9"]]
:test-paths ["spec"]
:profiles {:dev {:dependencies [[speclj "3.4.9"]]}}
:plugins [[speclj "3.4.9"]]
:test-paths ["spec"]
```

## Manual installation
Expand Down Expand Up @@ -139,9 +139,9 @@ Add a `spec` alias to your `deps.edn`.

```clojure
{
:aliases {:spec {:main-opts ["-m" "speclj.main" "-c"]
:extra-deps {speclj/speclj {:mvn/version "3.4.9"}}
:extra-paths ["spec"]}}
:aliases {:spec {:main-opts ["-m" "speclj.main" "-c"]
:extra-deps {speclj/speclj {:mvn/version "3.4.9"}}
:extra-paths ["spec"]}}
}
```

Expand All @@ -152,6 +152,27 @@ clj -M:spec -a # auto running with doc output
clj -M:spec <OPTIONS>
```

### With `deps-clr.edn`

Install [Clojure CLR](https://github.com/clojure/clojure-clr) and [Clojure CLR CLI](https://github.com/clojure/clr.core.cli).

Add a `spec` alias to your `deps-clr.edn`.

```clojure
{
:aliases {:spec {:main-opts ["-m" "speclj.main" "-c"]
:extra-deps {io.github.slagyr/speclj {:git/tag "3.5.0" :git/sha "5c79fdd"}}
:extra-paths ["spec"]}}
}
```

Run specs.
```bash
cljr -M:spec # printing dots
cljr -M:spec -a # auto running with doc output
cljr -M:spec <OPTIONS>
```

### With Leiningen
Speclj includes a Leiningen task.

Expand Down Expand Up @@ -215,14 +236,14 @@ All your `speclj` code should go into a a directory named `spec` at the root of
[`lein-cljsbuild`](https://github.com/emezeske/lein-cljsbuild) is a Leiningen plugin that'll get you up and running with ClojureScript. You'll need to add a `:cljsbuild` configuration map to your `project.clj`.

```clojure
:plugins [[lein-cljsbuild "1.0.3"]]
:cljsbuild {:builds {:dev {:source-paths ["src/cljs" "spec/cljs"]
:compiler {:output-to "path/to/compiled.js"}
:plugins [[lein-cljsbuild "1.0.3"]]
:cljsbuild {:builds {:dev {:source-paths ["src/cljs" "spec/cljs"]
:compiler {:output-to "path/to/compiled.js"}
:notify-command ["phantomjs" "bin/speclj" "path/to/compiled.js"]}
:prod {:source-paths ["src/cljs"]
:compiler {:output-to "path/to/prod.js"
:compiler {:output-to "path/to/prod.js"
:optimizations :simple}}}
:test-commands {"test" ["phantomjs" "bin/speclj" "path/to/compiled.js"]}}
:test-commands {"test" ["phantomjs" "bin/speclj" "path/to/compiled.js"]}}
```
Speclj works by operating on your compiled ClojureScript. The `:notify-command` will execute the `bin/speclj` command after your cljs is compiled. The `bin/speclj` command will use speclj to evaluate your compiled ClojureScript.

Expand All @@ -239,7 +260,7 @@ var p = require('webpage').create();
var sys = require('system');

p.onConsoleMessage = function (x) {
fs.write("/dev/stdout", x, "w");
fs.write("/dev/stdout", x, "w");
};

p.injectJs(phantom.args[0]);
Expand Down Expand Up @@ -310,9 +331,9 @@ speclj 3.4.6 or above is included in the classpath and use Cloverage's `--runner
Here's an example alias for your `deps.edn`.

```clojure
{:aliases {:cov {:main-opts ["-m" "cloverage.coverage" "--runner" ":speclj" "-p" "src" "-s" "spec" ]
{:aliases {:cov {:main-opts ["-m" "cloverage.coverage" "--runner" ":speclj" "-p" "src" "-s" "spec"]
:extra-deps {cloverage/cloverage {:mvn/version "1.2.4"}
speclj/speclj {:mvn/version "3.4.9"}}}}}
speclj/speclj {:mvn/version "3.4.9"}}}}}
```

Sadly, Cloverage doesn't offer a way to pass arguments to the runner (Speclj in this case). Speclj will use the
Expand Down
4 changes: 4 additions & 0 deletions deps-clr.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{:paths ["src/clj" "src/cljc" "src/cljr"]
:deps {io.github.clojure/clr.tools.namespace {:git/tag "v1.5.4" :git/sha "46d81cb"}}
:aliases {:test {:extra-paths ["spec/clj" "spec/cljc" "spec/cljr"]}
:spec {:main-opts ["-m" "speclj.main" "-c"]}}}
19 changes: 9 additions & 10 deletions deps.edn
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
{
:paths ["src"]
:paths ["src/clj" "src/cljc" "src/cljvm" "src/cljs"]
:deps {
mmargs/mmargs {:mvn/version "1.2.0"}
org.clojure/clojure {:mvn/version "1.11.3"}
trptcolin/versioneer {:mvn/version "0.1.1"}
org.clojure/clojure {:mvn/version "1.12.0"}
trptcolin/versioneer {:mvn/version "0.1.1"}
org.clojure/tools.namespace {:mvn/version "1.5.0"}
}
:aliases {
:test {:extra-deps {
io.github.clojure/tools.build {:mvn/version "0.9.5"}
io.github.clojure/tools.build {:mvn/version "0.10.6"}
org.clojure/clojurescript {:mvn/version "1.11.132"}
cloverage/cloverage {:mvn/version "1.2.4"}
}
:extra-paths ["dev" "spec" "target/classes"]}
:extra-paths ["dev" "spec/clj" "spec/cljc" "spec/cljs" "spec/cljvm" "target/classes"]}
:spec {:main-opts ["-m" "speclj.main" "-c"]}
:cljs {:main-opts ["-m" "speclj.dev.cljs"]}
:build {:extra-deps {io.github.clojure/tools.build {:mvn/version "0.9.5"}
clj-commons/pomegranate {:mvn/version "1.2.23"}}
:build {:extra-deps {io.github.clojure/tools.build {:mvn/version "0.10.6"}
clj-commons/pomegranate {:mvn/version "1.2.24"}}
: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/clj" "-p" "src/cljc" "-p" "src/cljvm" "-s" "spec/clj" "-s" "spec/cljc" "-s" "spec/cljs" "-s" "spec/cljvm" "-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"]
:exec-args {:source-paths ["src/clj" "src/cljc" "src/cljvm"]
:output-path "doc"
:source-uri "https://github.com/slagyr/speclj/blob/master/{filepath}#L{line}"}
}
Expand Down
7 changes: 3 additions & 4 deletions dev/build.clj
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@

(defn javac [_]
(println "compiling java")
(b/javac {:src-dirs ["src"]
:class-dir class-dir
:basis basis
(b/javac {:src-dirs ["src/clj" "src/cljc" "src/cljvm"]
:class-dir class-dir
:basis basis
:javac-opts ["--release" "11"]}))

(defn jar [_]
Expand Down Expand Up @@ -68,4 +68,3 @@
(jar nil)
(println "deploying " (:coordinates deploy-config))
(aether/deploy deploy-config))

15 changes: 12 additions & 3 deletions dev/speclj/dev/cljs.clj
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
(ns speclj.dev.cljs
(:require [cljs.build.api :as api]
[clojure.java.io :as io]))

[clojure.java.io :as io])
(:import (cljs.closure Compilable Inputs)))

(def build-options
{:development {:optimizations :none
:output-to "target/specs.js"
:output-dir "target/cljs"
:sources ["spec/cljs" "spec/cljc"]
:cache-analysis true
:source-map true
:pretty-print true
Expand All @@ -18,6 +19,7 @@
:optimizations :advanced
:output-to "target/specs.js"
:output-dir "target/cljs"
:sources ["spec/cljs" "spec/cljc"]
:pretty-print false
:verbose false
:watch-fn (fn [] (println "Success!"))
Expand All @@ -36,8 +38,15 @@
(io/copy error (System/err))
(System/exit (.waitFor process))))

(deftype Sources [build-options]
Inputs
(-paths [_] (map io/file (:sources build-options)))
Compilable
(-compile [_ opts] (mapcat #(cljs.closure/compile-dir (io/file %) opts) (:sources build-options)))
(-find-sources [_ opts] (mapcat #(cljs.closure/-find-sources % opts) (:sources build-options))))

(defn -main [& args]
(let [build-key (->build-key (first args))
build (get build-options build-key)]
(api/build "spec" build)
(api/build (Sources. build) build)
(run-specs)))
4 changes: 2 additions & 2 deletions examples/failures/storm.clj
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@
(should-throw (+ 1 1)))

(it "fails to throw the right error"
(should-throw Exception (throw (Error. "oops"))))
(should-throw clojure.lang.ExceptionInfo (throw (Exception. "oops"))))

(it "fails to throw error with the right message"
(should-throw Exception "Howdy" (throw (Exception. "Hiya")))))


(run-specs)
(run-specs)
4 changes: 3 additions & 1 deletion examples/prime_factors/prime_factors.clj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
(recur (conj factors divisor) divisor (/ n divisor))
(recur factors (inc divisor) n)))))

(defn pow [x n] (apply * (repeat n (bigdec x))))

(describe "prime factors"
(it "factors 1"
(should= [] (factors-of 1)))
Expand Down Expand Up @@ -38,7 +40,7 @@
(should= [3 3] (factors-of 9)))

(it "factors 2^100"
(should= (repeat 100 2) (factors-of (Math/pow 2 100))))
(should= (repeat 100 2) (factors-of (pow 2 100))))

; MDM - This one takes a bit too long to participate in the spec suite
; (it "factors 2^19-1"
Expand Down
9 changes: 9 additions & 0 deletions spec/clj/speclj/event_spec.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
(ns speclj.event-spec
(:require [speclj.core :refer :all]
[speclj.event :as sut]))

(describe "Event"

(it "new-line"
(should= 10 sut/new-line))
)
49 changes: 49 additions & 0 deletions spec/clj/speclj/freshener_spec.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
(ns speclj.freshener-spec
(:require
[clojure.tools.namespace.dir :as dir]
[clojure.tools.namespace.repl :as repl]
[speclj.core :refer :all]
[speclj.freshener :refer :all]
[speclj.io :as io]
[speclj.platform :as platform]))

(def sample-dir (io/canonical-file (io/as-file "examples/sample")))

(defn write-file [dir name content]
(let [file (io/as-file dir name)]
(io/make-parents file)
(io/copy (io/make-input-stream (platform/get-bytes content) {}) file)
file))

(describe "Freshener"

(it "finds specified files by default"
(write-file sample-dir "portable.cljx" "I'm antiquated")
(let [files (find-files-in #".*\.cljx" sample-dir)]
(should-contain "portable.cljx" (set (map io/file-name files)))))

(it "first freshening adds files to listing"
(write-file sample-dir "a.clj" "I'm a clojure file")
(write-file sample-dir "b.cljc" "I'm a clojure common file")
(write-file sample-dir "c.cljx" "I'm neither")
(let [files (clj-files-in sample-dir)]
(should-contain "a.clj" (set (map io/file-name files)))
(should-contain "b.cljc" (set (map io/file-name files)))
(should-not-contain "c.cljx" (set (map io/file-name files)))))

(context "freshen"
(before
(repl/set-refresh-dirs sample-dir))

(it "new files are detected and added to tracker"
(repl/clear)
(freshen)
(should= 2 (count (::dir/files repl/refresh-tracker)))
(should-contain "a.clj" (set (map io/file-name (::dir/files repl/refresh-tracker))))
(should-contain "b.cljc" (set (map io/file-name (::dir/files repl/refresh-tracker)))))

(it "refresh dirs are updated to nil indicating the classpath"
(freshen)
(should= nil repl/refresh-dirs)))

(repl/clear))
29 changes: 29 additions & 0 deletions spec/clj/speclj/interval_spec.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
(ns speclj.interval-spec
(:require [speclj.core :refer :all]
[speclj.interval :as sut]
[speclj.platform :as platform]
[speclj.stub :as stub]
[speclj.thread :as thread]))

(describe "Interval"
(with-stubs)

(it "set-interval loops over handler"
(let [key (sut/set-interval 50 (stub :interval))]
(thread/sleep 100)
(sut/clear-interval key)
(let [invocations (count (stub/invocations-of :interval))]
(should<= 2 invocations)
(should>= 3 invocations))))

(it "unassigned"
(should-not-throw (sut/clear-interval "blah")))

(it "does not sleep for the interval when cleared"
(let [key (sut/set-interval 1000 #(thread/sleep 100))
start (platform/current-time)]
(thread/sleep 50)
(sut/clear-interval key)
(should= 0.1 (platform/secs-since start) 0.01)))

)
Loading

0 comments on commit 8e37dca

Please sign in to comment.