Fork me on GitHub
#fulcro
<
2018-09-27
>
veddha07:09:23

does fulcro have dangerouslySetInnerHTML like react?

claudiu08:09:53

@veddha.riady there is a mention in the docs (dom/style {:dangerouslySetInnerHTML {:__html (g/css (css/get-css component))}}) . Haven't tried, but should work across all dom elements.

veddha08:09:24

@claudiu okay,thank u so much

thheller08:09:34

@veddha.riady you are pretty much always better off using :ref and then setting the HTML manually

Pontus15:09:23

why is that better?

thheller16:09:33

more control .. and I guess it doesn't look so dangerous šŸ˜‰

šŸ˜„ 4
thheller08:09:25

(dom/style {:ref (fn [node] (set! (.-innerHTML node) "the-stuff"))})

kirill.salykin11:09:03

Hi, is there a way to check if any running ajax requests?

claudiu12:09:35

@kirill.salykin There is :ui/loading-data http://book.fulcrologic.com/#_global_network_activity_marker , think currently this is only for df/load

kirill.salykin12:09:05

is it possible to access this outside of the fuclro? I need to ensure that request done in integration testā€¦

claudiu12:09:32

You can get the state from the reconciler (prim/app-state reconciler)

kirill.salykin12:09:26

is there recommended way to test UI interactions with fulcro?

kirill.salykin12:09:33

w/o backend involved?

claudiu12:09:20

think this might be what you're looking for http://book.fulcrologic.com/#DevCards

kirill.salykin12:09:21

i meant unit test

kirill.salykin12:09:58

or the only way is to spin up browser and click everything with selenium?

claudiu12:09:45

ahh šŸ™‚ haven't given it much thought. Maybe there is something helpfull in the fulcro tests https://github.com/fulcrologic/fulcro/tree/develop/src/test .

kirill.salykin12:09:49

thanks, looking into this

claudiu12:09:26

Welcome. Also curious about this one. :)

kirill.salykin12:09:14

seems for UI interactions I need to use a browser, https://github.com/fulcrologic/fulcro/tree/develop/src/test - seems are unit tests for fulcro logic

claudiu12:09:42

Or nodejs :) shadow-cljs makes it really easy to have node scripts & fulcro behaves like in the browser (including dl/load & remote mutations)

kirill.salykin13:09:18

sounds interesting

kirill.salykin13:09:24

Iā€™ll dig into it

tony.kay14:09:16

@kirill.salykin ui based tests are, in my experience, expensive, flaky, and not worth the effort. Bugs worth CI are in logic.

kirill.salykin14:09:21

how do you recommend to test validation logic for instance

tony.kay14:09:51

Write and test the logic. Your Ui has hookup points. Manually check the hooks, and call it good.

tony.kay14:09:35

Ask yourself: is it really worth the time you're putting into the test? Where's the actual risk, and what is the cost/benefit of test. I've seen people spend days on tests that will never fail (for useful reasons), to protect logic that has little business risk... why???

tony.kay14:09:10

But if you need a ui full stack smoke test (useful), then you Need something that can drive a browser.

kirill.salykin14:09:19

fyi - this works pretty good fo rme

claudiu14:09:53

@tony.kay what are you're thoughts on a testing flow like

- create headless app with login page (nodejs) 
- add invalid user-name values in the state
- run send-form! mutation that does validation
- check the state to see that the error messages are in the right place
?

tony.kay14:09:01

Good to know

tony.kay14:09:09

@claudiu what i said above. Look at the cost/benefit. Judge if it is really worth your time. If it is a smoke test or fragile part of the system, or was cheap and easy to write, then it's fine. I prefer tests that are a bit more sustainable. UI tests break for invalid, time-wasting reasons. Was the server a little slow? Did your test not wait long enough? Do you really want your test suite running for many many minutes just to test the login screen? I don't know maybe you do.

tony.kay14:09:52

I almost never write ui driver tests. I've found them to cost way more than they help

tony.kay14:09:01

And a key designator there is "almost ". Sometimes they're super useful.

claudiu14:09:50

šŸ™‚ yep, almost never have time, so trying to think of ways that they can be cost efficient šŸ˜„

tony.kay14:09:12

The other aspect of UI based testing is you cannot test any sorts of failure behavior easily. Also, you're very quickly going to hit combinatorial explosions of tests that can be factored apart and unit tested much more easily. Just tons and tons of problems with treating it as a general purpose testing solution.

claudiu14:09:17

One tool that I found interesting that might be worth the effort https://jestjs.io/docs/en/snapshot-testing

tony.kay14:09:23

And then when your UI test fails, you have no idea why it failed. Was it an internal logic error? Did the test not wait long enough for a response? Was the database down for that test run? Did someone change the database schema? It's another time wasting effort of trying to figure out what the hell happened because your test really doesn't give you very much specificity. It just tells you something failed. Which is why I say they're great for smoke tests. They tell you "somethings wrong", but not really what

claudiu14:09:06

Sortha like image regression. State + component and test the tree against a previous version.

claudiu14:09:04

Since fulcro returna native react, there is a good chance jest would work right ?

claudiu14:09:02

Thinking of devcards woth possible states & jest to automate the testing that they have not changed

tony.kay15:09:22

Visual regression testing can tell you something changedā€¦but you get a lot of ā€œfalse alarmsā€ā€¦so you spend lots of time saying ā€œyep, that still looks rightā€. Again, cost/benefit. Try it, but measure objectively.

tony.kay15:09:23

As a person running a startup: if it doesnā€™t lead to new features or protect me from breaking things that would cost me more money later than the tests cost, then it isnā€™t worth it.

tony.kay15:09:51

The way I test, I write tests as I code against logic. The tests take no longer than the REPL playing that I would need to do anyway, but theyā€™re repeatable. Win-win. Zero additional cost, and CI protection.

claudiu15:09:59

Yep. In my case doing ui for personal projects. Dont have a time for tests (really slow as it is) but I am working aylt late hours so would really help to have sort of tests before deploys

tony.kay15:09:02

tests are importantā€¦the trick is to make testing affordable. Ideally leveraging current habits (e.g. REPL testing) into new ones (codified tests that are essentially your REPL examples).

claudiu15:09:02

By tests on logic do you mean app state & mutation implementations ?

tony.kay15:09:24

And any ancillary code that supports that. Yes.

claudiu15:09:02

Cool :) makes sense

tony.kay16:09:07

One more note: At some point someone has to use the UI and make sure it all works. The idea is that most breakage doesnā€™t happen on the UI itself. It happens as you evolve logic. So, well-named and directed tests give you detection of breakage there, and high specificity for what exactly broke.

tony.kay16:09:03

At one company I worked for we had a highy-used subsystem that was always getting bug reports. The logic was complex, and touching one thing typically caused another to break. The ā€œtestingā€ was manual, and of course only the ā€œnew fixā€ got checkedā€¦a user would report the breakage after days or even weeks if it was a corner case. The structure of the code was horrible, and it had been patched so many times as to make it untenable. I rewrote it. The most important part of the rewrite was fixing the structure of the code. Making it simple was the first and most important step. I turned about 2000 lines of spaghetti into a few hundred. I also wrote tests around each new well-structured bit. I actually didnā€™t touch the UI the entire time I rewrote it, but the new simpler structure was easily testable, and was super-well covered as a result. When I ran it, it worked as expected. Zero bugs I could see (though I already had high confidence because of my tests). Release to production: one issue report: It turned out that our specification for how it was supposed to work was wrong in one case (and I had a test proving I ā€œmiswroteā€ it). I fixed the test, fixed the logic. Released. A system that was the source of continual bug reports for years never caused a peep again, and there wasnā€™t a single UI test.

tony.kay16:09:45

And, I seriously doubt I could have written it any faster without testsā€¦the tests made it so I didnā€™t have to click in the UI and generate crap full-system test data, etc. Testing effectively was probably faster than doing it without tests.

tony.kay16:09:42

but it took me 3 years of practice, making crappy tests, and throwing tons of stuff away before that to get good enough at it to get that resultā€¦so thereā€™s that šŸ˜•

tony.kay16:09:12

we need better schools/training for this stuff

claudiu17:09:02

:) my experience with tests hasnt been that great. Full integration (including in memory db) was the only thing I liked & made sense. For js I see a lot of time colegues spend testing redux "selectors" and other stuff like that. And in python I actually have a project where tests are the problem :)) they don't really catch any bugs, but break even for trivial changes (a lot nested mocking in folder path)

claudiu17:09:37

Might be tha oop & mutabillity make things a lot harder than they need to be. In cljs seems a lot nicer & simpler

currentoor18:09:28

IMO, especially after reading Tonyā€™s tests in fuclro, testing is a skill that needs to be actively developed

currentoor18:09:16

not everyone writes tests of the same quality and most people write brittle tests that cost more than they give you

currentoor18:09:29

the problem is most people (including myself until recently) see writing tests as a chore/formality that they save until the end

baptiste-from-paris19:09:50

Hello friends, I am currently testing fulcro with pathom as a front-only app with a rest api. I managed to make a network query (one tv show) and itā€™s sub network query work. But as you can see on the :query part, I have to declare a join for :episodes but I only want it to load if a user click on a button, I am kind of lost if anyone can help šŸ™‚

(defsc Episode [this {:keys [tvmaze.episode/id tvmaze.episode/name]}]
  {:ident [:tvmaze.episode/id :tvmaze.episode/id]
   :query [:tvmaze.episode/id :tvmaze.episode/name]}
  (dom/ul nil
          (dom/li nil (str "Episode id : " id))
          (dom/li nil (str "Episode name : " name ))))


(def ui-episode (prim/factory Episode {:keyfn :tvmaze.episode/id}))


(defsc TvShow [this {:keys [tvmaze.show/id tvmaze.show/name tvmaze.show/language tvmaze.show/episodes]}]
  {:ident [:tvamaze.show/id :tvmaze.show/id]
   :query [:tvmaze.show/id :tvmaze.show/name :tvmaze.show/language
           {:tvmaze.show/episodes (prim/get-query Episode)}]}
  (dom/ul nil
          (dom/li nil (str "id : ") id)
          (dom/li nil (str "name : " name))
          (dom/li nil (str "language : " language))
          (map ui-episode episodes)))


(def ui-tv-show (prim/factory TvShow {:keyfn :tvmaze.show/id}))


(defsc Root [this {:keys [ui/react-key list/one]}]
  {:query [:ui/react-key
           {:list/one (prim/get-query TvShow)}]}
  (dom/div #js {:key react-key}
           "List of all TvShows that we-ve seen this year !"
           (ui-tv-show one)
           (dom/button #js {:onClick (fn [_]
                                       (df/load this [:tvmaze.show/id 1]
                                                TvShow
                                                {:target [:list/one]}))}
                       "Charger une tvShow")))

baptiste-from-paris19:09:34

I was thinking about dynamic queries but I am not sure itā€™s a ā€œvalidā€ use case

wilkerlucio19:09:48

@baptiste-from-paris I do some query post-processing for these kind of things, on the load fn of fulcro it supports :update-query, in which you get the query before it sends to the server and process as you wish

wilkerlucio19:09:25

what I do is mark the fields I don't wanna load right away as lazy (eg: [:eager (:lazy {:lazy-attribute true})])

baptiste-from-paris19:09:41

in the query itself ?

wilkerlucio19:09:43

then in my update-query function I strip all the lazy things (when I want to)

baptiste-from-paris19:09:07

ok perfect, thanks a lot again, I am going to try that

wilkerlucio19:09:22

this is how I end up writing, a real query example:

wilkerlucio19:09:24

[:purchase/id :rewards/purchase-labels :abrams.api/shard
                   (db.h/lazy :purchase.points/label)
                   ::db.h/mutation-response
                   {:ui/classify-dropdown (fp/get-query ui/Dropdown)}]

wilkerlucio19:09:31

the db.h/lazy will add the lazy param

wilkerlucio19:09:40

(defn lazy [x] (p/update-attribute-param x assoc ::lazy? true))

wilkerlucio19:09:46

p is from pathom

wilkerlucio19:09:57

and this is my remove-lazy fn:

wilkerlucio19:09:11

(defn remove-lazy [query]
  (->> (p/query->ast query)
       (p/transduce-children (remove (comp ::lazy? :params)))
       (p/ast->query)))

baptiste-from-paris19:09:57

so typically when you would do a prim/get-query all fields would be loaded right ?

baptiste-from-paris19:09:33

itā€™s only on the request post-processing side that you remove all that ?

wilkerlucio19:09:56

yeah, for loads you don't call get-query yourself right, fulcro does

wilkerlucio19:09:04

and this processing happens before the query is sent to the server

wilkerlucio19:09:13

so the server never sees the lazy fields on this case

baptiste-from-paris19:09:32

looks like desfsc is not finding param anymore nfo: defsc TvShow: [tvmaze.show/language] destructured in props but do(es) not appear in your query!

baptiste-from-paris19:09:57

Ok working perfectly @wilkerlucio, thanks a lot.

claudiu19:09:20

would :without http://book.fulcrologic.com/#_pruning_the_query work for these scenario also ?

wilkerlucio19:09:55

@claudiu without is too simplistic, it just removes all of that, and when you have a complex query that can be very hard to target what you want

wilkerlucio19:09:19

also, using without requires that the caller of load to know about what needs to be pruned, using the lazy the component tells it so it's not a concern of load caller anymore

claudiu19:09:18

ahh, got it. Really awesome, thank you šŸ™‚

baptiste-from-paris20:09:27

transduce-children is recursive it looked at all query params