day8 / re-frame-test

Cross platform (cljs and clj) utilities for testing re-frame applications
MIT License
109 stars 12 forks source link

Allow wait-for to match for the whole event vector #5

Closed vikeri closed 7 years ago

vikeri commented 7 years ago

First of all, awesome work! Really improved our testing setup.

If I understand correctly, wait-for can not take the whole event vector as a predicate but it only evaluates on the event key? For now I'm solving it using

(rf-test/wait-for [(fn [event]
                             (= event [:eventkw event-val]))]
          (is (= @mystate :expected/state)
            "It did not go into the correct state"))

Am I using re-frame in a strange way or could it be relevant to match it like this?

(rf-test/wait-for [[:eventkv event-val]]
          (is (= @mystate :expected/state)
            "It did not go into the correct state"))
samroberton commented 7 years ago

Glad to hear this is helping out with your testing. And thanks for the feedback.

Unfortunately, matching on the entire event vector like that would be ambiguous.

wait-for already accepts quite a variety of things for each of its arguments, as documented in the docstring: https://github.com/Day8/re-frame-test/blob/master/src/day8/re_frame/test.cljc#L230

One of those things is already a vector of event IDs to match against (this is basically just allowing a vector in place of a set for those who prefer it, since arguably the set literal notation comes with a connotation that you might be using the set as a short-hand way of supplying a function, but actually here set is special-cased).

So I don't see any way to distinguish between "the caller supplied a vector of event-ids and we should match against any of them" and "the caller supplied an event vector which should be matched in its entirety".

I think what you've got -- or I suppose perhaps (partial = [:eventkw event-val]) or #(= % [:eventkw event-val]) -- is about as concise as we can get for this. (Or alternatively obviously it would be possible to have your own wrapper around wait-for that made different choices about the form of its arguments: especially since wait-for's only real job is to act as sugar for wait-for*, allowing you to write the arguments a little more naturally/concisely.)

For what it's worth, I don't think you're necessarily using re-frame in a strange way. But if you are having to match the entire event vector before knowing it's safe to continue the body of wait-for, then that implies that there is some "important thing that happened in the timeline of my app" that's not being expressed as a named event in its own right. Without knowing exactly use case you have, obviously I'm just making sweeping generalised assumptions -- but I wonder whether that might sometimes point to a possibility that your code would be clearer by giving the thing you're waiting for a distinct name in any case?

In any case, I guess it's fair to say that wait-for is written on an assumption about the common case: where something is important enough that you can't continue your test until you know it's already happened, it's a fair bet that it's important enough for you to have given it its own name.

vikeri commented 7 years ago

Alright that makes sense, yeah regarding my events I have a little state machine abstraction that I have incorporated re-frame into. It processes events according to some rules and therefore I am using the same event key. I'll use your solution.

Another question, JVM testing!? Any example of how to set that up? Benefits? (I'm running the tests in node at the moment, which is good because node is super fast to fire up). Maybe I should open a separate issue asking for this to be documented?