Fork me on GitHub
#clojure-spec
<
2018-03-27
>
borkdude07:03:47

I think it doesn’t know how to generate a ratom from a predicate.

hkjels08:03:14

That springs another question though. How do I express that?

borkdude07:03:12

Maybe you should try making ::ratom with it’s own with-gen so that this with-gen also determines the contents of the ratom.

hkjels08:03:06

ahh, ofcourse. Thank you @borkdude

hkjels08:03:36

fails with the same message

borkdude08:03:26

@hkjels I made a small example in JVM Clojure which should be straightforward to port to cljs:

(s/def ::ratom
  (s/with-gen #(instance? clojure.lang.IAtom %)
    #(gen/fmap atom (gen/string-alphanumeric))))

(gen/sample (s/gen ::ratom))

;; (#atom["" 0x6ff87e8] #atom["" 0x710f246c] #atom["7" 0x43b11d93] #atom["N" 0x6fd3f101] #atom["k6" 0x15e9ebd4] #atom["xFdxB" 0x1dcd8141] #atom["" 0x56db5aee] #atom["J7" 0x26f0f2cd] #atom["67Pzk94" 0x7c1d0a8c] #atom["e" 0xdab4bc7])

hkjels08:03:44

(set? (deref %)) is what causes it to fail. I’ll digg a little further

borkdude08:03:03

@hkjels

(s/def ::set-ratom
  (s/with-gen (s/and #(instance? clojure.lang.IAtom %)
                     (fn [a]
                       (set? @a)))
    #(gen/fmap atom (gen/fmap set (gen/string-alphanumeric)))))

borkdude08:03:00

@hkjels You can check with gen/sample

borkdude09:03:43

(s/def ::id string?)
(s/def ::value string?)
(s/def ::label string?)

(s/def ::item (s/keys :req-un [::id ::value] :opt-un [::label]))

(s/def ::items
  (s/coll-of ::item :kind? set))

(take 2 (gen/sample (s/gen ::items))) ([{:id "", :value ""} {:id "", :value "", :label ""} {:id "", :value ""} {:id "", :value ""} {:id "", :value ""}] [{:id "", :value "", :label ""} {:id "", :value "6"} {:id "E", :value "2", :label ""} {:id "", :value "", :label "w"}])
Indeed, the generator doesn’t return sets

borkdude09:03:56

Don’t know if this is a bug or by design. Alex probably knows

borkdude09:03:24

@hkjels This is a workaround. Not pretty, but it works:

(s/def ::items
  (s/with-gen
    (s/coll-of ::item :kind? set)
    #(gen/fmap set (s/gen (s/coll-of ::item)))))
I’m not sure if there’s a better way as I’ve not used this part of spec much yet.

hkjels09:03:08

hey, that works

hkjels09:03:39

hmm, weird that (s/coll-of ::item :kind? set) does not return a set

hkjels09:03:47

that must be a bug right?

borkdude09:03:13

Don’t know. I’m sure Alex will reply later today

hkjels09:03:22

Thank you!

minimal09:03:35

@hkjels use a predicate like everything else: (s/coll-of ::item :kind set?)

minimal10:03:26

and it’s :kind, not :kind?:

hkjels10:03:49

ahh, that explains why it didn’t barf

minimal10:03:16

yeah, would be nice if it told you

borkdude10:03:26

ah I wasn’t awake enough to spot those typos 🙂

borkdude14:03:18

I like it how spec lets you specify things gradually or as fine-grained as you want

👍 8
manutter5119:03:15

My google-fu is failing me: I want to write a spec for a function that takes an atom (actually a Reagent atom). Is there a way to do that?

borkdude20:03:55

but IAtom will also do, but not specific to Reagent

bbrinck20:03:00

(s/def :test/ratom? #(instance? reagent.ratom/RAtom %))
(s/valid? :test/ratom? 1) ; false
(s/valid? :test/ratom? (r/atom nil)) ; true

manutter5120:03:07

Thanks much, I’ll see if I can get that to work. The tricky part is this all has to work in CLJS, but I want to match both regular atoms and Reagent atoms so I can pass in test dummies

borkdude20:03:37

then IAtom seems the right abstraction

bbrinck20:03:44

Arguably, testing anything more than the class isn’t very useful, but YMMV

bbrinck20:03:08

(I mean, testing the interface may be useful too, but the contents, maybe not so much)

borkdude20:03:15

yes, you can just as well create ratom dummies, so it’s a good question why you want to do that

bbrinck20:03:27

The advice I remember is that spec is mostly useful for testing values. Testing references is likely less useful

bbrinck20:03:10

since testing the reference at any point in time doesn’t say much about what it will become at any point in the future

bbrinck20:03:06

it might be more useful to spec the functions that mutate that reference, or, say, use spec in a validator

manutter5120:03:20

Yeah, that’s a good point, I could just use ratoms everywhere

manutter5120:03:36

That’s probably the best solution — tks much