Fork me on GitHub

does fulcro have dangerouslySetInnerHTML like react?


@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.


@claudiu okay,thank u so much


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


why is that better?


more control .. and I guess it doesn't look so dangerous 😉

😄 4

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


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


@kirill.salykin There is :ui/loading-data , think currently this is only for df/load


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


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


is there recommended way to test UI interactions with fulcro?


w/o backend involved?


think this might be what you're looking for


i meant unit test


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


ahh 🙂 haven't given it much thought. Maybe there is something helpfull in the fulcro tests .


thanks, looking into this


Welcome. Also curious about this one. :)


seems for UI interactions I need to use a browser, - seems are unit tests for fulcro logic


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


sounds interesting


I’ll dig into it


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


how do you recommend to test validation logic for instance


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


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???


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


fyi - this works pretty good fo rme


@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


Good to know


@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.


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


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


🙂 yep, almost never have time, so trying to think of ways that they can be cost efficient 😄


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.


One tool that I found interesting that might be worth the effort


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


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


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


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


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.


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.


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.


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


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).


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


And any ancillary code that supports that. Yes.


Cool :) makes sense


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.


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.


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.


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 😕


we need better schools/training for this stuff


:) 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)


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


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


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


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


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 []}]
  {:ident []
   :query [
           { (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}))

(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 [ 1]
                                                {:target [:list/one]}))}
                       "Charger une tvShow")))


I was thinking about dynamic queries but I am not sure it’s a “valid” use case


@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


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


in the query itself ?


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


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


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


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


the db.h/lazy will add the lazy param


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


p is from pathom


and this is my remove-lazy fn:


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


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


it’s only on the request post-processing side that you remove all that ?


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


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


so the server never sees the lazy fields on this case


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


Ok working perfectly @wilkerlucio, thanks a lot.


would :without work for these scenario also ?


@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


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


ahh, got it. Really awesome, thank you 🙂


transduce-children is recursive it looked at all query params