How to test a UI made with FRP, especially reactive-banana?

I am trying out reactive-banana, and struggling to figure out how to make the program testable. Is there some good reference on how to create dynamic UIs in reactive-banana with proper testing?

Specifically, the problem is that creating a view requires impure IO action. I found it quite hard to untangle the view from handling actions, which makes it harder to perform testing (which usually requires pure components). How should I go with this one?

1 Like

For now, I am going for making smaller units and making the unit polymorphic to the notion of “creating”.
Now it is something like

applyUpdate :: MomentIO a -> Event (UpdateOf a) -> MomentIO (Behavior (Vector a))

Now I can employ any a to test the function, not a view which requires expensive operation to construct.
Yet, this code still uses MomentIO which daunts me on how to test it.
How can I test this function?

1 Like

There are two functions, interpret for Moment, and interpretFrameworks for MomentIO, which allow you to test functions like this. :thinking: Perhaps these may suit your needs?

In general, testing an entire user interface with IO is difficult, as usual. Testing functions like Event a → Event b individually is easier and preferred.

2 Likes

Thank you! I have an idea on how to test it.
Now I have a question on discrete type. Why did it disappear, when it seems so useful to describe interactive behavior?

1 Like

I can’t remember a type like this — it was called Discrete? :sweat_smile:

One of the main ideas of Behavior is that it should not be possible to observe how often it “changes”, i.e. it should be impossible to distinguish the Behavior b :: Behavior Char defined by let b = pure 'a' from the one defined by b <- stepper 'a' ('a' <$ e) where e is any event. Semantically, these two definitions are equal — the Behavior has the value 'a' at any moment in time.

2 Likes

I understand that we need Behavior where changes cannot be observed. What I needed though was a behavior paired with an update event, which was called Discrete.

The usage was, basically, to have a record like

data Foo = MkFoo {
  bar :: Bar,
  bPropBaz :: Behavior Baz
  eFoobarClick :: Event ()
}

created by execute,
and extract both Behavior Bar and Behavior Baz from Discrete Foo.
Do you know better way to approach this problem?

1 Like

I would still like an answer to this one. Anyone used reactive-banana for UI?

What approach do other FRP libraries use?

1 Like