-
Notifications
You must be signed in to change notification settings - Fork 21
/
cljs_test.cljc
121 lines (111 loc) · 4.85 KB
/
cljs_test.cljc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
(ns matcher-combinators.cljs-test
#?(:cljs
(:require-macros [matcher-combinators.cljs-test]))
(:require [matcher-combinators.core :as core]
[matcher-combinators.dispatch :as dispatch]
[matcher-combinators.printer :as printer]
[matcher-combinators.parser]
[matcher-combinators.result :as result]
[cljs.test :as t :refer-macros [deftest is]]))
(defn with-file+line-info [report]
#?(:cljs (merge (t/file-and-line (js/Error.) 4) report)))
;; This technique was copied from https://github.com/tonsky/datascript
;; below is the reasoning from the datascript repo:
;; The matcher-combinators.cljs-test namespace exists only for the side
;; effect of extending the cljs.test/assert-expr multimethod.
;; This has to be done on the clj side of cljs compilation, and
;; so we have a separate namespace that is only loaded by cljs
;; via a :require-macros clause in datascript.test.core. This
;; means we have a clj namespace that should only be loaded by
;; cljs compilation.
#?(:clj (do
(defmethod t/assert-expr 'match? [_ msg form]
`(let [args# (list ~@(rest form))
[matcher# actual#] args#]
(cond
(not (= 2 (count args#)))
(clojure.test/do-report
{:type :fail
:message ~msg
:expected (symbol "`match?` expects 2 arguments: a `matcher` and the `actual`")
:actual (symbol (str (count args#) " were provided: " '~form))})
(core/matcher? matcher#)
(let [result# (core/match matcher# actual#)]
(t/do-report
(if (core/match? result#)
{:type :pass
:message ~msg
:expected '~form
:actual (list 'match? matcher# actual#)}
(with-file+line-info
{:type :matcher-combinators/mismatch
:message ~msg
:expected '~form
:actual (list '~'not (list 'match? matcher# actual#))
:markup (::result/value result#)}))))
:else
(t/do-report
{:type :fail
:message ~msg
:expected (str "The first argument of match? needs to be a matcher (implement the match protocol)")
:actual '~form}))))
(defmethod t/assert-expr 'match-with? [_ msg form]
`(clojure.test/do-report
{:type :fail
:message ~msg
:expected (symbol "`match-with?` not yet implemented for cljs")
:actual '~form}))
(defmethod t/assert-expr 'thrown-match? [_ msg form]
;; (is (thrown-with-match? exception-class matcher expr))
;; Asserts that evaluating expr throws an exception of class c.
;; Also asserts that the exception data satisfies the provided matcher.
(let [klass (nth form 1)
matcher (nth form 2)
body (nthnext form 3)]
`(try ~@body
(let [args# (list ~@(rest form))]
(if (not (= 3 (count args#)))
(clojure.test/do-report
{:type :fail
:message ~msg
:expected (symbol "`thrown-match?` expects 3 arguments: an exception class, a `matcher`, and the `actual`")
:actual (symbol (str (count args#) " were provided: " '~form))})
(t/do-report {:type :fail
:message ~msg
:expected '~form
:actual (symbol "the expected exception wasn't thrown")})))
(catch ~klass e#
(let [result# (core/match ~matcher (ex-data e#))]
(t/do-report
(if (core/match? result#)
{:type :pass
:message ~msg
:expected '~form
:actual (list 'thrown-match? ~klass ~matcher '~body)}
(with-file+line-info
{:type :matcher-combinators/exception-mismatch
:message ~msg
:expected '~form
:actual (list '~'not (list 'thrown-match? ~klass ~matcher '~body))
:ex-class ~klass
:markup (::result/value result#)}))))
e#))))))
#?(:cljs (do
(defmethod t/report [::t/default :matcher-combinators/exception-mismatch] [m]
(t/inc-report-counter! :fail)
(println "\nFAIL in" (t/testing-vars-str m))
(when (seq (:testing-contexts (t/get-current-env)))
(println (t/testing-contexts-str)))
(when-let [message (:message m)]
(println message))
(println (:ex-class m) "data mismatches:")
(printer/pretty-print (:markup m)))
(defmethod t/report [::t/default :matcher-combinators/mismatch] [m]
(t/inc-report-counter! :fail)
(println "\nFAIL in" (t/testing-vars-str m))
(when (seq (:testing-contexts (t/get-current-env)))
(println (t/testing-contexts-str)))
(when-let [message (:message m)]
(println message))
(println "mismatch:")
(printer/pretty-print (:markup m)))))