├── .gitignore ├── LICENSE ├── README.md ├── project.clj ├── src └── leiningen │ └── tach.clj └── test └── leiningen └── tach_test.clj /.gitignore: -------------------------------------------------------------------------------- 1 | /pom.xml 2 | /target 3 | /.lein-failures 4 | /.nrepl-port 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Eclipse Public License - v 1.0 2 | 3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC 4 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM 5 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 6 | 7 | 1. DEFINITIONS 8 | 9 | "Contribution" means: 10 | 11 | a) in the case of the initial Contributor, the initial code and documentation 12 | distributed under this Agreement, and 13 | b) in the case of each subsequent Contributor: 14 | i) changes to the Program, and 15 | ii) additions to the Program; 16 | 17 | where such changes and/or additions to the Program originate from and are 18 | distributed by that particular Contributor. A Contribution 'originates' 19 | from a Contributor if it was added to the Program by such Contributor 20 | itself or anyone acting on such Contributor's behalf. Contributions do not 21 | include additions to the Program which: (i) are separate modules of 22 | software distributed in conjunction with the Program under their own 23 | license agreement, and (ii) are not derivative works of the Program. 24 | 25 | "Contributor" means any person or entity that distributes the Program. 26 | 27 | "Licensed Patents" mean patent claims licensable by a Contributor which are 28 | necessarily infringed by the use or sale of its Contribution alone or when 29 | combined with the Program. 30 | 31 | "Program" means the Contributions distributed in accordance with this 32 | Agreement. 33 | 34 | "Recipient" means anyone who receives the Program under this Agreement, 35 | including all Contributors. 36 | 37 | 2. GRANT OF RIGHTS 38 | a) Subject to the terms of this Agreement, each Contributor hereby grants 39 | Recipient a non-exclusive, worldwide, royalty-free copyright license to 40 | reproduce, prepare derivative works of, publicly display, publicly 41 | perform, distribute and sublicense the Contribution of such Contributor, 42 | if any, and such derivative works, in source code and object code form. 43 | b) Subject to the terms of this Agreement, each Contributor hereby grants 44 | Recipient a non-exclusive, worldwide, royalty-free patent license under 45 | Licensed Patents to make, use, sell, offer to sell, import and otherwise 46 | transfer the Contribution of such Contributor, if any, in source code and 47 | object code form. This patent license shall apply to the combination of 48 | the Contribution and the Program if, at the time the Contribution is 49 | added by the Contributor, such addition of the Contribution causes such 50 | combination to be covered by the Licensed Patents. The patent license 51 | shall not apply to any other combinations which include the Contribution. 52 | No hardware per se is licensed hereunder. 53 | c) Recipient understands that although each Contributor grants the licenses 54 | to its Contributions set forth herein, no assurances are provided by any 55 | Contributor that the Program does not infringe the patent or other 56 | intellectual property rights of any other entity. Each Contributor 57 | disclaims any liability to Recipient for claims brought by any other 58 | entity based on infringement of intellectual property rights or 59 | otherwise. As a condition to exercising the rights and licenses granted 60 | hereunder, each Recipient hereby assumes sole responsibility to secure 61 | any other intellectual property rights needed, if any. For example, if a 62 | third party patent license is required to allow Recipient to distribute 63 | the Program, it is Recipient's responsibility to acquire that license 64 | before distributing the Program. 65 | d) Each Contributor represents that to its knowledge it has sufficient 66 | copyright rights in its Contribution, if any, to grant the copyright 67 | license set forth in this Agreement. 68 | 69 | 3. REQUIREMENTS 70 | 71 | A Contributor may choose to distribute the Program in object code form under 72 | its own license agreement, provided that: 73 | 74 | a) it complies with the terms and conditions of this Agreement; and 75 | b) its license agreement: 76 | i) effectively disclaims on behalf of all Contributors all warranties 77 | and conditions, express and implied, including warranties or 78 | conditions of title and non-infringement, and implied warranties or 79 | conditions of merchantability and fitness for a particular purpose; 80 | ii) effectively excludes on behalf of all Contributors all liability for 81 | damages, including direct, indirect, special, incidental and 82 | consequential damages, such as lost profits; 83 | iii) states that any provisions which differ from this Agreement are 84 | offered by that Contributor alone and not by any other party; and 85 | iv) states that source code for the Program is available from such 86 | Contributor, and informs licensees how to obtain it in a reasonable 87 | manner on or through a medium customarily used for software exchange. 88 | 89 | When the Program is made available in source code form: 90 | 91 | a) it must be made available under this Agreement; and 92 | b) a copy of this Agreement must be included with each copy of the Program. 93 | Contributors may not remove or alter any copyright notices contained 94 | within the Program. 95 | 96 | Each Contributor must identify itself as the originator of its Contribution, 97 | if 98 | any, in a manner that reasonably allows subsequent Recipients to identify the 99 | originator of the Contribution. 100 | 101 | 4. COMMERCIAL DISTRIBUTION 102 | 103 | Commercial distributors of software may accept certain responsibilities with 104 | respect to end users, business partners and the like. While this license is 105 | intended to facilitate the commercial use of the Program, the Contributor who 106 | includes the Program in a commercial product offering should do so in a manner 107 | which does not create potential liability for other Contributors. Therefore, 108 | if a Contributor includes the Program in a commercial product offering, such 109 | Contributor ("Commercial Contributor") hereby agrees to defend and indemnify 110 | every other Contributor ("Indemnified Contributor") against any losses, 111 | damages and costs (collectively "Losses") arising from claims, lawsuits and 112 | other legal actions brought by a third party against the Indemnified 113 | Contributor to the extent caused by the acts or omissions of such Commercial 114 | Contributor in connection with its distribution of the Program in a commercial 115 | product offering. The obligations in this section do not apply to any claims 116 | or Losses relating to any actual or alleged intellectual property 117 | infringement. In order to qualify, an Indemnified Contributor must: 118 | a) promptly notify the Commercial Contributor in writing of such claim, and 119 | b) allow the Commercial Contributor to control, and cooperate with the 120 | Commercial Contributor in, the defense and any related settlement 121 | negotiations. The Indemnified Contributor may participate in any such claim at 122 | its own expense. 123 | 124 | For example, a Contributor might include the Program in a commercial product 125 | offering, Product X. That Contributor is then a Commercial Contributor. If 126 | that Commercial Contributor then makes performance claims, or offers 127 | warranties related to Product X, those performance claims and warranties are 128 | such Commercial Contributor's responsibility alone. Under this section, the 129 | Commercial Contributor would have to defend claims against the other 130 | Contributors related to those performance claims and warranties, and if a 131 | court requires any other Contributor to pay any damages as a result, the 132 | Commercial Contributor must pay those damages. 133 | 134 | 5. NO WARRANTY 135 | 136 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN 137 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR 138 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, 139 | NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each 140 | Recipient is solely responsible for determining the appropriateness of using 141 | and distributing the Program and assumes all risks associated with its 142 | exercise of rights under this Agreement , including but not limited to the 143 | risks and costs of program errors, compliance with applicable laws, damage to 144 | or loss of data, programs or equipment, and unavailability or interruption of 145 | operations. 146 | 147 | 6. DISCLAIMER OF LIABILITY 148 | 149 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY 150 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, 151 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION 152 | LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 153 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 154 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE 155 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY 156 | OF SUCH DAMAGES. 157 | 158 | 7. GENERAL 159 | 160 | If any provision of this Agreement is invalid or unenforceable under 161 | applicable law, it shall not affect the validity or enforceability of the 162 | remainder of the terms of this Agreement, and without further action by the 163 | parties hereto, such provision shall be reformed to the minimum extent 164 | necessary to make such provision valid and enforceable. 165 | 166 | If Recipient institutes patent litigation against any entity (including a 167 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself 168 | (excluding combinations of the Program with other software or hardware) 169 | infringes such Recipient's patent(s), then such Recipient's rights granted 170 | under Section 2(b) shall terminate as of the date such litigation is filed. 171 | 172 | All Recipient's rights under this Agreement shall terminate if it fails to 173 | comply with any of the material terms or conditions of this Agreement and does 174 | not cure such failure in a reasonable period of time after becoming aware of 175 | such noncompliance. If all Recipient's rights under this Agreement terminate, 176 | Recipient agrees to cease use and distribution of the Program as soon as 177 | reasonably practicable. However, Recipient's obligations under this Agreement 178 | and any licenses granted by Recipient relating to the Program shall continue 179 | and survive. 180 | 181 | Everyone is permitted to copy and distribute copies of this Agreement, but in 182 | order to avoid inconsistency the Agreement is copyrighted and may only be 183 | modified in the following manner. The Agreement Steward reserves the right to 184 | publish new versions (including revisions) of this Agreement from time to 185 | time. No one other than the Agreement Steward has the right to modify this 186 | Agreement. The Eclipse Foundation is the initial Agreement Steward. The 187 | Eclipse Foundation may assign the responsibility to serve as the Agreement 188 | Steward to a suitable separate entity. Each new version of the Agreement will 189 | be given a distinguishing version number. The Program (including 190 | Contributions) may always be distributed subject to the version of the 191 | Agreement under which it was received. In addition, after a new version of the 192 | Agreement is published, Contributor may elect to distribute the Program 193 | (including its Contributions) under the new version. Except as expressly 194 | stated in Sections 2(a) and 2(b) above, Recipient receives no rights or 195 | licenses to the intellectual property of any Contributor under this Agreement, 196 | whether expressly, by implication, estoppel or otherwise. All rights in the 197 | Program not expressly granted under this Agreement are reserved. 198 | 199 | This Agreement is governed by the laws of the State of New York and the 200 | intellectual property laws of the United States of America. No party to this 201 | Agreement will bring a legal action under this Agreement more than one year 202 | after the cause of action arose. Each party waives its rights to a jury trial in 203 | any resulting litigation. 204 | 205 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tach 2 | 3 | Leiningen plugin for testing libraries targeting self-hosted ClojureScript. 4 | 5 | ## Usage 6 | 7 | Add `lein-tach` to your Leiningen `:plugins` vector. 8 | 9 | [![Clojars Project](https://img.shields.io/clojars/v/lein-tach.svg)](https://clojars.org/lein-tach) 10 | 11 | Then 12 | 13 | ``` 14 | lein tach lumo 15 | ``` 16 | 17 | or 18 | 19 | ``` 20 | lein tach planck 21 | ``` 22 | 23 | will cause Tach to execute your unit tests in [Lumo](https://github.com/anmonteiro/lumo) or [Planck](http://planck-repl.org). 24 | 25 | ## Example 26 | 27 | ``` 28 | $ lein tach lumo 29 | 30 | Testing my-lib.core-test 31 | 32 | Ran 42 tests containing 132 assertions. 33 | 0 failures, 0 errors. 34 | ``` 35 | 36 | ## Configuration 37 | 38 | Tach looks in your `project.clj` and extracts the following from the `:cljsbuild` configuration: 39 | 40 | - source paths (it uses the `:source-paths` value) 41 | - the main test runner namespace (assumed to be the one listed under `:main`) 42 | 43 | If needed, you can specify the `:cljsbuild` build identifier as the final argument as in: 44 | 45 | ``` 46 | lein tach lumo dev 47 | ``` 48 | 49 | You can explicitly set any of the Tach configuration values by including configuration like the following in your `project.clj` (all of the keys are optional): 50 | 51 | ``` 52 | :tach {:test-runner-ns 'my-lib.test-runner 53 | :source-paths ["src/cljs" "src/cljc"] 54 | :force-non-zero-exit-on-test-failure? true 55 | :cache? true 56 | :cache-path "/custom/path/to/cache_dir" 57 | :debug? true} 58 | ``` 59 | 60 | If either `:test-runner-ns` or `:source-paths`is specified, it overrides any value derived from `:cljsbuild`. 61 | 62 | The `:force-non-zero-exit-on-test-failure?` flag can be useful for CI builds: If set to `true`, it causes code like the following to be evaluated, which causes Lumo or Planck to exit with a non-zero code upon test failures: 63 | 64 | ```clojure 65 | (defmethod cljs.test/report [:cljs.test/default :end-run-tests] [m] 66 | (when-not (cljs.test/successful? m) 67 | (self-host-env-specific-exit 1))) 68 | ``` 69 | 70 | If you'd like to enable Lumo or Planck compilation caching, include `cache? true` and if you'd like to specify the directory to be used for caching, specify it via `:cache-path`. 71 | 72 | You can enable Tach diagnostic debug output by setting `:debug? true`. 73 | 74 | ## License 75 | 76 | Copyright © 2017–2020 Mike Fikes and Contributors 77 | 78 | Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version. 79 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject lein-tach "1.1.0" 2 | :description "Test libs targeting self-hosted ClojureScript." 3 | :url "https://github.com/mfikes/tach" 4 | :license {:name "Eclipse Public License" 5 | :url "http://www.eclipse.org/legal/epl-v10.html"} 6 | :eval-in-leiningen true) 7 | -------------------------------------------------------------------------------- /src/leiningen/tach.clj: -------------------------------------------------------------------------------- 1 | (ns leiningen.tach 2 | (:require 3 | [clojure.string :as string] 4 | [clojure.java.shell :as shell] 5 | [leiningen.core.main :as main] 6 | [leiningen.core.classpath :as classpath])) 7 | 8 | (def exit-code-failed-test 1) 9 | 10 | (defn clojurescript-jar? 11 | [jar-name] 12 | (boolean (re-matches #".*/clojurescript-.*\.jar" jar-name))) 13 | 14 | (defn clojure-jar? 15 | [jar-name] 16 | (boolean (re-matches #".*/clojure-.*\.jar" jar-name))) 17 | 18 | (defn render-classpath 19 | [cp] 20 | (str (string/join ":" cp))) 21 | 22 | (defn get-execution-environment 23 | [args] 24 | (when (empty? args) 25 | (throw (ex-info "No execution environment specified. Expected lumo or planck." {}))) 26 | (let [execution-environment (first args)] 27 | (when-not (#{"lumo" "planck"} execution-environment) 28 | (throw (ex-info "Execution enviromnents supported: lumo or planck" {:execution-environemnt execution-environment}))) 29 | execution-environment)) 30 | 31 | (defn render-require-test-runner-main 32 | [test-runner-main] 33 | (pr-str `(require '~test-runner-main))) 34 | 35 | (defn render-require-cljs-test 36 | [] 37 | (pr-str `(require 'cljs.test))) 38 | 39 | (defn render-require-planck-core 40 | [planck?] 41 | (pr-str (when planck? `(require 'planck.core)))) 42 | 43 | (defn render-inject-exit-handler 44 | [planck?] 45 | (pr-str `(do (defmethod cljs.test/report [:cljs.test/default :end-run-tests] [~'m] 46 | (when-not (cljs.test/successful? ~'m) 47 | ~(if planck? 48 | `(planck.core/exit ~exit-code-failed-test) 49 | `(.exit js/process ~exit-code-failed-test)))) 50 | nil))) 51 | 52 | (defn get-build 53 | [project args] 54 | (let [builds (get-in project [:cljsbuild :builds])] 55 | (if-some [build-id (second args)] 56 | (or (first (filter (fn [build] 57 | (= (:id build) build-id)) 58 | builds)) 59 | (->> builds 60 | (filter (fn [[id _]] (= (name id) build-id))) 61 | first 62 | second)) 63 | (first builds)))) 64 | 65 | (defn filtered-classpath 66 | [project] 67 | (->> (classpath/get-classpath project) 68 | (remove clojurescript-jar?) 69 | (remove clojure-jar?))) 70 | 71 | (defn unquoted 72 | [sym] 73 | (if (seq? sym) 74 | (second sym) 75 | sym)) 76 | 77 | (defn get-test-runner-ns 78 | [project build] 79 | (unquoted (or (get-in project [:tach :test-runner-ns]) 80 | (get-in build [:compiler :main])))) 81 | 82 | (defn get-source-paths 83 | [project build] 84 | (or (get-in project [:tach :source-paths]) 85 | (get-in build [:source-paths]))) 86 | 87 | (defn tach-debug? 88 | [project] 89 | (get-in project [:tach :debug?])) 90 | 91 | (defn tach-force-non-zero-exit-on-test-failure? 92 | [project] 93 | (get-in project [:tach :force-non-zero-exit-on-test-failure?])) 94 | 95 | (defn tach-cache? 96 | [project] 97 | (get-in project [:tach :cache?])) 98 | 99 | (defn tach-verbose? 100 | [project] 101 | (get-in project [:tach :verbose?])) 102 | 103 | (defn tach-repl? 104 | [project] 105 | (get-in project [:tach :repl])) 106 | 107 | (defn exit 108 | [code message] 109 | (println message) 110 | (if-not (zero? code) 111 | (main/exit code))) 112 | 113 | (defn build-command-line 114 | [project args] 115 | (let [build (get-build project args) 116 | _ (when (tach-debug? project) 117 | (println "Using this build: " (pr-str build))) 118 | test-runner-ns (get-test-runner-ns project build) 119 | source-paths (get-source-paths project build)] 120 | (when-not test-runner-ns 121 | (throw (ex-info "Failed to determine test runner namespace" {}))) 122 | (let [execution-environment (get-execution-environment args) 123 | planck? (= execution-environment "planck") 124 | run-tests (or (not planck?) (not (tach-repl? project))) 125 | command-line (concat 126 | [execution-environment 127 | (when (and (tach-verbose? project) planck?) 128 | "-v") 129 | "-q" 130 | "-c" (-> project filtered-classpath (concat source-paths) render-classpath)] 131 | (when (tach-cache? project) 132 | (if-let [cache-path (get-in project [:tach :cache-path])] 133 | ["--cache" cache-path] 134 | ["--auto-cache"])) 135 | (when run-tests 136 | (when (tach-force-non-zero-exit-on-test-failure? project) 137 | ["-e" (render-require-planck-core planck?) 138 | "-e" (render-require-cljs-test) 139 | "-e" (render-inject-exit-handler planck?)]) 140 | ["-e" (render-require-test-runner-main test-runner-ns)]))] 141 | command-line))) 142 | 143 | (defn tach 144 | [project & args] 145 | (let [command-line (build-command-line project args) 146 | _ (when (tach-debug? project) 147 | (apply println "Running\n" command-line)) 148 | result (apply shell/sh command-line)] 149 | (exit (:exit result) 150 | (str (:out result) (:err result))))) 151 | -------------------------------------------------------------------------------- /test/leiningen/tach_test.clj: -------------------------------------------------------------------------------- 1 | (ns leiningen.tach-test 2 | (:require 3 | [clojure.test :refer [deftest is]] 4 | [leiningen.tach :as tach]) 5 | (:import 6 | (clojure.lang ExceptionInfo))) 7 | 8 | (deftest clojurescript-jar?-test 9 | (is (tach/clojurescript-jar? "/foo/bar/clojurescript-1.2.3.jar")) 10 | (is (not (tach/clojurescript-jar? "/foo/bar/fipp-2.3.2.jar")))) 11 | 12 | (deftest render-classpath-test 13 | (is (= "a.jar:b.jar:/foo/src" 14 | (tach/render-classpath ["a.jar" "b.jar" "/foo/src"])))) 15 | 16 | (deftest get-execution-environment-test 17 | (is (thrown-with-msg? ExceptionInfo #"No execution environment.*" 18 | (tach/get-execution-environment []))) 19 | (is (thrown-with-msg? ExceptionInfo #"Execution enviromnents supported: lumo or planck" 20 | (tach/get-execution-environment ["bogus"]))) 21 | (is (= "lumo" (tach/get-execution-environment ["lumo"]))) 22 | (is (= "lumo" (tach/get-execution-environment ["lumo" "dev"]))) 23 | (is (= "planck" (tach/get-execution-environment ["planck"]))) 24 | (is (= "planck" (tach/get-execution-environment ["planck" "dev"])))) 25 | 26 | (deftest render-require-test-runner-main-test 27 | (is (= "(clojure.core/require (quote foo.core))" 28 | (tach/render-require-test-runner-main 'foo.core)))) 29 | 30 | (deftest render-require-cljs-test 31 | (is (= "(clojure.core/require (quote cljs.test))" 32 | (tach/render-require-cljs-test)))) 33 | 34 | (deftest render-require-planck-core-test 35 | (is (= "(clojure.core/require (quote planck.core))" 36 | (tach/render-require-planck-core true))) 37 | (is (= "nil" 38 | (tach/render-require-planck-core false)))) 39 | 40 | (deftest render-inject-exit-handler-test 41 | (is (= "(do (clojure.core/defmethod cljs.test/report [:cljs.test/default :end-run-tests] [m] (clojure.core/when-not (cljs.test/successful? m) (planck.core/exit 1))) nil)" 42 | (tach/render-inject-exit-handler true))) 43 | (is (= "(do (clojure.core/defmethod cljs.test/report [:cljs.test/default :end-run-tests] [m] (clojure.core/when-not (cljs.test/successful? m) (.exit js/process 1))) nil)" 44 | (tach/render-inject-exit-handler false)))) 45 | 46 | (deftest get-build-test 47 | (let [project 48 | '{:cljsbuild 49 | {:builds 50 | [{:id "dev" 51 | :source-paths ["src/test/cljs" "src/main/clojure/cljs"] 52 | :compiler {:main cljs.core.async.test-runner 53 | :asset-path "../out" 54 | :optimizations :none 55 | :output-to "tests.js" 56 | :output-dir "out"}} 57 | {:id "simple" 58 | :source-paths ["src/test/cljs" "src/main/clojure/cljs"] 59 | :compiler {:optimizations :simple 60 | :pretty-print true 61 | :static-fns true 62 | :output-to "tests.js" 63 | :output-dir "out-simp"}}]}}] 64 | (is (= '{:compiler {:asset-path "../out" 65 | :main cljs.core.async.test-runner 66 | :optimizations :none 67 | :output-dir "out" 68 | :output-to "tests.js"} 69 | :id "dev" 70 | :source-paths ["src/test/cljs" 71 | "src/main/clojure/cljs"]} 72 | (tach/get-build project ["planck"]))) 73 | (is (= '{:id "simple" 74 | :source-paths ["src/test/cljs" "src/main/clojure/cljs"] 75 | :compiler {:optimizations :simple 76 | :pretty-print true 77 | :static-fns true 78 | :output-to "tests.js" 79 | :output-dir "out-simp"}} 80 | (tach/get-build project ["planck" "simple"]))))) 81 | 82 | (deftest unquoted-test 83 | (is (= 'foo (tach/unquoted 'foo))) 84 | (is (= 'foo (tach/unquoted ''foo)))) 85 | 86 | (deftest get-test-runner-ns-test 87 | (let [project1 88 | '{:cljsbuild 89 | {:builds 90 | [{:id "dev" 91 | :source-paths ["src/test/cljs" "src/main/clojure/cljs"] 92 | :compiler {:main cljs.core.async.test-runner 93 | :asset-path "../out" 94 | :optimizations :none 95 | :output-to "tests.js" 96 | :output-dir "out"}}]}} 97 | project2 98 | '{:cljsbuild 99 | {:builds 100 | [{:id "dev" 101 | :source-paths ["src/test/cljs" "src/main/clojure/cljs"] 102 | :compiler {:main cljs.core.async.test-runner 103 | :asset-path "../out" 104 | :optimizations :none 105 | :output-to "tests.js" 106 | :output-dir "out"}}]} 107 | :tach {:test-runner-ns 'foo.core}} 108 | build 109 | '{:id "dev" 110 | :source-paths ["src/test/cljs" "src/main/clojure/cljs"] 111 | :compiler {:main cljs.core.async.test-runner 112 | :asset-path "../out" 113 | :optimizations :none 114 | :output-to "tests.js" 115 | :output-dir "out"}}] 116 | (is (= 'cljs.core.async.test-runner 117 | (tach/get-test-runner-ns project1 build))) 118 | (is (= 'foo.core 119 | (tach/get-test-runner-ns project2 build))))) 120 | 121 | (deftest get-source-paths-test 122 | (let [project1 123 | '{:cljsbuild 124 | {:builds 125 | [{:id "dev" 126 | :source-paths ["src/test/cljs" "src/main/clojure/cljs"] 127 | :compiler {:main cljs.core.async.test-runner 128 | :asset-path "../out" 129 | :optimizations :none 130 | :output-to "tests.js" 131 | :output-dir "out"}}]}} 132 | project2 133 | '{:cljsbuild 134 | {:builds 135 | [{:id "dev" 136 | :source-paths ["src/test/cljs" "src/main/clojure/cljs"] 137 | :compiler {:main cljs.core.async.test-runner 138 | :asset-path "../out" 139 | :optimizations :none 140 | :output-to "tests.js" 141 | :output-dir "out"}}]} 142 | :tach {:source-paths ["abc/def" "foo/bar"]}} 143 | build 144 | '{:id "dev" 145 | :source-paths ["src/test/cljs" "src/main/clojure/cljs"] 146 | :compiler {:main cljs.core.async.test-runner 147 | :asset-path "../out" 148 | :optimizations :none 149 | :output-to "tests.js" 150 | :output-dir "out"}}] 151 | (is (= ["src/test/cljs" "src/main/clojure/cljs"] 152 | (tach/get-source-paths project1 build))) 153 | (is (= ["abc/def" "foo/bar"] 154 | (tach/get-source-paths project2 build))))) 155 | 156 | (deftest tach-debug?-test 157 | (is (tach/tach-debug? {:tach {:debug? true}})) 158 | (is (not (tach/tach-debug? {:tach {}})))) 159 | 160 | (deftest tach-force-non-zero-exit-on-test-failure?-test 161 | (is (tach/tach-force-non-zero-exit-on-test-failure? {:tach {:force-non-zero-exit-on-test-failure? true}})) 162 | (is (not (tach/tach-force-non-zero-exit-on-test-failure? {:tach {}})))) 163 | 164 | (deftest tach-cache?-test 165 | (is (tach/tach-cache? {:tach {:cache? true}})) 166 | (is (not (tach/tach-cache? {:tach {}})))) 167 | 168 | (deftest tach-verbose?-test 169 | (let [tach-verbose {:tach {:verbose? true :test-runner-ns 'com.some.ns}} 170 | tach-not-verbose {:tach {}} 171 | execution-env "planck"] 172 | (is (tach/tach-verbose? tach-verbose)) 173 | (is (not (tach/tach-verbose? tach-not-verbose))) 174 | (is (= [execution-env "-v"] (take 2 (tach/build-command-line tach-verbose [execution-env])))))) 175 | 176 | (deftest tach-repl?-test 177 | (let [tach-repl {:tach {:repl true :test-runner-ns 'com.some.ns}} 178 | tach-no-repl {:tach {:test-runner-ns 'com.some.ns}} 179 | planck-env "planck" 180 | lumo-env "lumo" 181 | eval-arg "-e"] 182 | (is (tach/tach-repl? tach-repl)) 183 | (is (not (tach/tach-repl? tach-no-repl))) 184 | ; repl means we should not have the -e (evaluate) arg for planck 185 | (is (nil? (some #{eval-arg} (tach/build-command-line tach-repl [planck-env])))) 186 | ; no :repl means we should 187 | (is (not (nil? (some #{eval-arg} (tach/build-command-line tach-no-repl [planck-env]))))) 188 | ; :repl option should be ignored for lumo env 189 | (is (not (nil? (some #{eval-arg} (tach/build-command-line tach-repl [lumo-env]))))))) 190 | --------------------------------------------------------------------------------