clojurescript

ClojureScript, a dialect of Clojure that compiles to JavaScript http://clojurescript.org | Currently at 1.10.879
johanmynhardt 2021-04-20T09:35:16.238200Z

I'm stuck. I'm trying to read an ES6 file that basically just contains a data structure. If it was JSON I could parse it that way. I suspect this is possible, but I'm not a ClojureScript expert and don't know where to start. My Google search results are not too fruitful and I'm wondering if I'm going at it in the wrong way?

thheller 2021-04-20T09:37:09.238600Z

read it at runtime or use it during compile time to use in your app?

johanmynhardt 2021-04-20T09:45:18.243100Z

I would say compile time, although it's an intermediate step to use it in Clojure. I'm trying to do infrequent conversions from such .js files to .edn for use in my main project (Clojure), so I figure it can be considered to be compile time. I started looking at ClojureScript because I couldn't find tools just in Clojure and figured ClojureScript does this all the time, somehow, if I'm not misunderstanding. I just can't figure out how exactly I would go about it.

johanmynhardt 2021-04-25T18:22:40.406300Z

Nice, so I got some time tonight to play around/figure out doing this. Wish I had rather spent Friday doing this! πŸ™ˆ

p-himik 2021-04-20T10:52:30.243400Z

Assuming you're using shadow-cljs, it should be possible, I think: https://shadow-cljs.github.io/docs/UsersGuide.html#_requiring_js

p-himik 2021-04-20T10:52:51.243600Z

You just require that JS file and use it via JS interop of just convert it with js->clj.

johanmynhardt 2021-04-20T10:57:55.243800Z

πŸ™ Thank you, this is most helpful. I'm going to have a look. I've parsed it by hand using regex as the structure was simple enough but it's not sustainable πŸ˜… I have to get a real solution.

πŸ‘ 1
Aron 2021-04-20T13:42:04.245100Z

What do people use for UI test automation? Because I am struggling with puppeteer, I get different results in headful and headless mode and it's impossible to know what's different.

Ronny Li 2021-04-20T14:37:00.246200Z

Somewhat off-topic but is anyone here using https://headlessui.dev/? What are your thoughts? We use Tailwind CSS and think it's brilliant so we're biased to think that Headless will be great too.

dnolen 2021-04-20T15:05:37.246900Z

@ashnur fwiw I don't believe in UI test automation

dnolen 2021-04-20T15:05:41.247100Z

too much work too brittle

πŸ‘ 3
dnolen 2021-04-20T15:06:27.247800Z

a better approach to higher quality UI work is to adopt a pure functional UI

dnolen 2021-04-20T15:06:51.248400Z

and for all components to be fully tested for the meaningful states in total isolation from all business logic

dnolen 2021-04-20T15:07:07.248800Z

Storybook.js and Devcards permit this style of UI development

dnolen 2021-04-20T15:08:35.250Z

then any UI issue that crops up had to been business logic

dnolen 2021-04-20T15:08:38.250200Z

not components

dnolen 2021-04-20T15:08:57.250900Z

and the business logic is easier to understand/discern

dnolen 2021-04-20T15:10:45.253Z

QA is necessary of course

dnolen 2021-04-20T15:11:02.253600Z

and maybe UI test automation can catch some QA issues - but I doubt it

dnolen 2021-04-20T15:11:13.254100Z

any serious app needs to run on too many different platforms, too many differents OSes etc.

dnolen 2021-04-20T15:11:20.254500Z

it's a waste of time

dnolen 2021-04-20T15:12:00.255Z

meaning the effort to set it all up is just enormous

dnolen 2021-04-20T15:12:01.255300Z

vs.

dnolen 2021-04-20T15:12:10.255700Z

what I'm saying above which is prevent writing bad code in the first place

dnolen 2021-04-20T15:12:29.256200Z

and then when you get to QA and human has to drive it - it's meaningful testing - not BS

dnolen 2021-04-20T15:15:49.258500Z

I'll reiterate something I've said before

dnolen 2021-04-20T15:16:12.259100Z

Devcards or Storybook.js is probably the most important change I've made to UI development since the appearance of React

dnolen 2021-04-20T15:16:44.260200Z

nothing else I've tried has been as transformative since ClojureScript+React

Aron 2021-04-20T15:17:00.260600Z

Thanks for taking the time to answer @dnolen. I am not writing these tests to achieve, as you write, 'higher quality UI', I am trying to not have to do these simple checks manually because it takes much more time like that.

dnolen 2021-04-20T15:17:22.260900Z

sure but I'm just saying - you're not going to save any time

dnolen 2021-04-20T15:17:39.261200Z

well maybe you will, or think you will

dnolen 2021-04-20T15:17:54.261700Z

but I've never been able to get it save me any time in 16 years

βž• 1
Aron 2021-04-20T15:18:11.262100Z

I am going to lose quality of life if I have to repeat the same 10000 actions every day

Aron 2021-04-20T15:19:14.264Z

so even if you are right and I am wrong about how much time it takes overall, the time I spent waiting for the tests (and writing them) to run is qualitatively different than the time I spent manually testing (and making humanly understandable but professionally very deteriorating mistakes)

dnolen 2021-04-20T15:19:14.264100Z

but the question you should be asking

2021-04-20T15:19:19.264500Z

Agree with dnolan, automated ui testing ime is always greatly more effort than reward.

βž• 1
dnolen 2021-04-20T15:19:22.264800Z

is why do you need to go through a flow

dnolen 2021-04-20T15:19:30.265300Z

again and again if it's not QA

dnolen 2021-04-20T15:19:33.265600Z

i.e. pre-ship time

Aron 2021-04-20T15:19:37.265700Z

because if I repeat the same actions, I will make mistakes, and get many more false positives and false negatives

dnolen 2021-04-20T15:19:46.266100Z

everything you do should be setup so you don't have retest anything

Aron 2021-04-20T15:19:47.266200Z

it is pre-ship time

dnolen 2021-04-20T15:20:18.267700Z

right there is no good answer for pre-ship time that I've seen other than manual QA

dnolen 2021-04-20T15:20:26.268Z

maybe AI one day

Aron 2021-04-20T15:20:30.268200Z

lol

Aron 2021-04-20T15:20:50.269Z

sorry, I can't restrain myself when people idolize AI like that

Aron 2021-04-20T15:21:15.269700Z

but that's beside the point, I see that people do not have the same problems as I have, again

dnolen 2021-04-20T15:21:26.270200Z

that was meant to be joke πŸ˜‰ and half-serious

dnolen 2021-04-20T15:21:43.270900Z

as in I don't see how it can be solved

Aron 2021-04-20T15:21:45.271100Z

πŸ™‚

dnolen 2021-04-20T15:21:46.271200Z

with existing methods

Aron 2021-04-20T15:22:31.272200Z

I know, I shouldn't be trying to create a fixed experience in the first place, people on the other side, using their own browsers should decide how the interface looks like, not us

Aron 2021-04-20T15:23:06.273200Z

but that's again, beside the point. I have very good experience with UI automation, I even used it in property based testing

Aron 2021-04-20T15:23:16.273600Z

this is the first time I have a redundant problem like this

2021-04-20T15:23:18.273900Z

another issue is when testing advanced compilation code - how can one do this without using a headless setup?

Aron 2021-04-20T15:23:21.274Z

in like 7 years

Aron 2021-04-20T15:35:42.284600Z

@dnolen fww, i did try to use devcards and storybooks but 1. neither worked well with react hooks the way I tried 2. after I did the nice components there, I had to insert my react code into the actual Django templates from which they are served and they got wrapped into this minimized css that the company had for 7 years now and it's not being touched, don't even have the un-minimized source for it afaik, and of course the major business logic is not how things look but how things interact, and since it's not just a REST api but also cookies and other parts of the page define the context, I really didn't see any point to not develop the app inside the page where it will appear anyway. This way at least I can test it when I am working on it. But because testing means testing with all kinds of different users that I have to create manually because there is no other way, most of the time I am not actually testing my work, just "preparing the backend state" for testing, because that defines fully the frontend state.

Aron 2021-04-20T15:38:01.286500Z

I did build a functional UI on datascript and mori and mercury in 2015 2016, the two packages had to be compiled together, and it was really verbose to use them from js at the time, but it worked nicely, didn't have to test the UI by actually clicking on things to see if they work

dnolen 2021-04-20T16:15:54.286900Z

@ashnur huh I don't understand your point about React Hooks, we use those those w/o issue

dnolen 2021-04-20T16:16:07.287200Z

but note we just write our components in JS

dnolen 2021-04-20T16:16:54.287600Z

I just don't believe in writing components where they are going to be anymore

dnolen 2021-04-20T16:17:04.288100Z

it just NxN problems

dnolen 2021-04-20T16:17:09.288300Z

vs. N

dnolen 2021-04-20T16:17:52.289100Z

In your case that N may be large - and maybe, in this instance UI automation is going to get you something

Aron 2021-04-20T16:21:34.289900Z

yeah, I am not testing components, I have about a dozen files, each just opens the page, performs a bunch of user actions on the whole page and reads content of the page

Aron 2021-04-20T16:22:42.291500Z

I see zero sense in testing components out of their context, they are never actually used like that in practice.

lilactown 2021-04-20T16:22:51.291700Z

we use CLJS + hooks + storybook in our apps

Aron 2021-04-20T16:23:10.292200Z

how do you write reusable stateful components

lilactown 2021-04-20T16:23:30.292900Z

we also use react-testing-library to test our components in isolation

Aron 2021-04-20T16:23:31.293Z

think something that handles a predictive input with arbitrary input text allowed

lilactown 2021-04-20T16:24:11.293800Z

🀷:skin-tone-2: same way we would build any reusable stateful component. use local state inside the component, provide props to control the behavior

Aron 2021-04-20T16:24:41.294500Z

yeah, so where is the local state, in a use-state hook in the top component?

lilactown 2021-04-20T16:24:43.294700Z

the link to headlessui.dev above is a good example of that

lilactown 2021-04-20T16:24:54.295Z

yeah

Aron 2021-04-20T16:25:37.295900Z

so, when you are in your editor, there is probably some repl connected to the browser runtime env?

lilactown 2021-04-20T16:26:17.296400Z

um, yes when I'm developing in our app project I typically have a REPL connected

lilactown 2021-04-20T16:26:41.297200Z

the REPL connection doesn't work with our storybook setup, but we mainly use it for documentation of our design library

Aron 2021-04-20T16:26:57.297600Z

and can you read current state of any shared component through your editor? I've been trying to see an example of that, especially with Storybooks

lilactown 2021-04-20T16:27:50.298600Z

I typically use React DevTools + the JS console to inspect the state of React components

lilactown 2021-04-20T16:28:22.299600Z

I have experimented with adding REPL support for inspecting the React tree but haven't found a really good interface to use it yet

Aron 2021-04-20T16:28:23.299700Z

I use (tap>) and shadow-cljs has a web ui where it is nicely browseable

Aron 2021-04-20T16:28:31.300100Z

and of course react devtools

Aron 2021-04-20T16:28:55.300500Z

the only solution is to not use hooks, this is why I said I couldn't make it work

Aron 2021-04-20T16:29:05.300800Z

@dnolen ☝️:skin-tone-2:

Aron 2021-04-20T16:29:25.301200Z

I only mean state hooks, not effect hooks

Aron 2021-04-20T16:29:59.302200Z

so obviously use-ref would work fine, but it's really a hassle to set it up, and I am very much dissillusioned with react since they removed resuming

lilactown 2021-04-20T16:30:44.303200Z

sounds like it's not that it didn't work i.e. you couldn't build an app with it, but that you didn't like the developer experience

lilactown 2021-04-20T16:30:49.303400Z

which is fair

lilactown 2021-04-20T16:31:42.304900Z

I find that using component local state is architecturally better for us so I'm willing to live without the ability to easily use the REPL for inspecting local component state

Aron 2021-04-20T16:31:48.305100Z

well, you have to choose, if I am not using react hooks the obvious choice is to not use react at all or use reagent

Aron 2021-04-20T16:33:04.305700Z

my issue with local state is this page https://reactjs.org/docs/lifting-state-up.html

Aron 2021-04-20T16:35:15.306Z

or more specifically, this issue answer https://github.com/facebook/react/issues/11527#issuecomment-360199710

Aron 2021-04-20T16:35:37.306400Z

> I want to highlight that in typical React apps that rely onΒ `setState()`Β this isΒ the single most common kind of React-specific refactoring that you would do on a daily basis.

Aron 2021-04-20T16:36:01.306700Z

I just don't want to.

dnolen 2021-04-20T16:41:04.307100Z

hrm I'm doing mostly React Native these days

dnolen 2021-04-20T16:41:14.307500Z

I didn't find any of the React Native "tools" useful

dnolen 2021-04-20T16:42:49.308700Z

so I don't know - I'm a minimalist

Aron 2021-04-20T16:45:04.309200Z

can I ask the same question from you? do you use atoms or something else for reusable component state?

Aron 2021-04-20T16:46:22.310400Z

reusable in the sense that the same namespace is used multiple times throughout the page with different state, but the logic is implemented only once and then gets required and filled out by other components

dnolen 2021-04-20T16:54:22.310900Z

all components are written in JS, verified on the device and simulators via Storybook.js

dnolen 2021-04-20T16:54:28.311100Z

all styling and theming is done via React context

dnolen 2021-04-20T16:54:48.311500Z

all components are Pure Components, using hooks for state only for internal stuff

1
dnolen 2021-04-20T16:54:54.311700Z

everything comes in via props

1
dnolen 2021-04-20T16:55:09.312100Z

everything most compose and must be representable in Storybook.js

dnolen 2021-04-20T16:55:23.312500Z

if you cannot create the state in Storybook - then it can't be created at all

dnolen 2021-04-20T16:55:30.312800Z

once this cycle is done

dnolen 2021-04-20T16:55:39.313100Z

we just adapt them to Reagent components

dnolen 2021-04-20T16:55:54.313500Z

then the "app" is only like a thousand lines of ClojureScript code

dnolen 2021-04-20T16:56:11.313800Z

even you have many screens and many states

dnolen 2021-04-20T16:57:01.314300Z

the ClojureScript code has no styling, no theming

dnolen 2021-04-20T16:57:07.314500Z

no presentation logic of any kind

dnolen 2021-04-20T16:57:21.314800Z

other than the highest level structure

dnolen 2021-04-20T16:57:47.315200Z

all routing is done via 10 lines of core.match

dnolen 2021-04-20T16:58:11.315700Z

any internal route is handled because none of the Pure Components have subview order

dnolen 2021-04-20T16:58:48.316200Z

so you can make the flow state machine w/ a ClojureScript map

dnolen 2021-04-20T16:58:54.316400Z

and change it to be any order you want

dnolen 2021-04-20T17:00:15.317Z

the only thing of interest here is that it's shockingly simple

dnolen 2021-04-20T17:00:45.317500Z

and probably this has lead to fewest bugs I've encountered on a UI project myself

dnolen 2021-04-20T17:01:02.317900Z

nearly all issues stem from larger integration problems - but that's to be expected

lilactown 2021-04-20T17:04:37.318200Z

sounds like a dream project πŸ˜„

dnolen 2021-04-20T17:05:56.318700Z

it would be nice to replace the Storybook.js stuff w/ ClojureScript but in the end it really doesn't matter much

dnolen 2021-04-20T17:06:20.319300Z

if you write only Pure Components it's feels more or less like ClojureScript

dnolen 2021-04-20T17:06:33.319700Z

no data transformation of any kind is allowed

dnolen 2021-04-20T17:06:57.320100Z

because of the ES6 iteration protocols, everything more or less works

dnolen 2021-04-20T17:07:39.320900Z

we have one tiny clever thing w/ React Context which we inject from CLJS to convert props at Pure Component boundary (since this is nested React components not nested Reagent components)

dnolen 2021-04-20T17:07:48.321200Z

but that was a couple of lines of code

lilactown 2021-04-20T17:28:01.321800Z

we did the same thing at my last company. design library in JS + storybook, product used CLJS

lilactown 2021-04-20T17:28:15.322200Z

however, the major reason we did that is we had other consumers of the design lib that had been written in JS

dpsutton 2021-04-20T17:30:04.322800Z

was wondering about that boundary between js objects/arrays and cljs immutable types

dpsutton 2021-04-20T17:30:15.323100Z

i imagine cljs-bean comes in handy?

djblue 2021-04-20T17:49:20.323500Z

An approach we are taking at work for e2e ui testings is allowing the test runner to introspect on the client state. This allows us to assert directly on app state instead of derived views. That also allows us to synchronize our ui interactions when we know the app is in a good state. Of course, the big assumption we make is that the mapping between app state and views is correct, which we mostly validate via unit tests.

djblue 2021-04-20T17:55:12.324400Z

Essentially the code looks like:

(defn e2e-test [driver user-story]
  (loop
    (let [state       (get-state driver)
          thing-to-do (next-thing-to-do state user-story)]
      (do-the-thing! driver thing-to-do)
      (when-not (done? driver user-story)
        (recur)))))

djblue 2021-04-20T17:57:20.325700Z

The nice thing here is that the user-story and state are both just data and the thing to do can be wait for now cause I can't currently do anything

Aron 2021-04-20T17:59:00.326700Z

I thought about that, but because this is embedded in a django app and sometimes I need to check if things become disabled or enabled, checking the state might not be enough

dnolen 2021-04-20T17:59:04.326800Z

@djblue right's more or less what I'm trying to suggest

dnolen 2021-04-20T17:59:32.327300Z

if your components are in Storybook.js that's strong evidence of the mapping

πŸ’― 1
dnolen 2021-04-20T17:59:56.327800Z

then you can just write simple tests about state transitions about data

dnolen 2021-04-20T18:01:02.328500Z

there are limits for our app though

dnolen 2021-04-20T18:01:14.328900Z

because we have a lot of native code integration, remote services

dnolen 2021-04-20T18:01:26.329200Z

and I'm not fan of mocked tests

πŸ’― 1
djblue 2021-04-20T18:05:41.331200Z

In my code example above the driver is a handle into a browser that's connected to our development environment so the app has access to all necessary services and we don't need to mock anything, and we can test actual integration at every level

djblue 2021-04-20T18:25:29.331300Z

Another point of note here is that the user story itself is actually a subset of the app state. This means we can leverage our UI to also update the user story when things do change.

fsd 2021-04-20T18:43:05.335900Z

Hello There, I am having problem setting the dates in ClojureScript, for some reason the application is keeps on setting previous date.

{
:start-date (js/Date. start-date) 
:end-date (js/Date. end-date)
}
Is this the correct way of setting the time? When I change my computer timezone to different location, the application timing starts working fine.
(println start-date)
-> #time/date "2021-05-10"

(js/console.log (js/Date. start-date))
Sun May 09 2021 20:00:00 GMT-0400 (Eastern Daylight Time)
Any help would be appreciated

p-himik 2021-04-20T18:44:11.336Z

What do you mean by "setting the time"? Setting it where, exactly?

fsd 2021-04-20T18:53:25.336200Z

for example I have #time/date β€œ2021-04-21” I am trying to convert this to as javascript new Date()

p-himik 2021-04-20T18:54:30.336400Z

It is that js/Date, most likely. It's just that println prints it that way. It's OK for println and js/console.log to output things differently.

fsd 2021-04-20T18:56:37.336600Z

is there any js/Date build in function in clojurescript that converts as following #inst β€œ2021-04-21T00:00:00.000-00:00”

p-himik 2021-04-20T18:59:22.337Z

I don't understand what you mean. You need some function to convert X to Y. What's (type X)? What's (type Y)? Just in case, here's my REPL:

cljs.user=> (js/Date.)
#inst "2021-04-20T18:58:34.940-00:00"

lilactown 2021-04-20T19:58:37.337200Z

what do you mean?

dpsutton 2021-04-20T20:00:41.337400Z

when calling cljs functions from js, ensuring that arrays becomes vectors, objects become maps, etc

raspasov 2021-04-20T20:13:55.337600Z

So you write JSX as opposed to using React CLJS interop?

raspasov 2021-04-20T20:23:37.338200Z

If you’re doing anything more than a trivial thing around dates, consider using a library.

raspasov 2021-04-20T20:23:58.338400Z

I use https://github.com/juxt/tick

raspasov 2021-04-20T20:24:21.338800Z

Works the same both in CLJ and CLJS, which is great.

lilactown 2021-04-20T20:55:37.339Z

it depends. I typically don't see the point in transforming to and from unless it's a necessary to interface with a particular part of a system

lilactown 2021-04-20T20:56:34.339300Z

i.e. if I'm getting some JSON from an endpoint and want to operate on it immutably in my UI, I'll do that transformation once on receiving and store it that way

lilactown 2021-04-20T20:57:29.339500Z

or, if I'm using some 3rd party library that takes as input a JS object based on some immutable data I have in hand, then I'll manually write the construction of the JS object

lilactown 2021-04-20T20:57:40.339700Z

clj->js and js->clj is a huge code smell to me IMO

lilactown 2021-04-20T20:58:14.339900Z

sometimes it doesn't matter, but too often it can lead to errors or performance problems

dpsutton 2021-04-20T21:02:10.340200Z

we have a query analyzer that we added in to the frontend. and it of course "speaks" clojure, being built in the backend. and the frontend is a react js app. there's a huge boundary of arrays and objects and those js types can't really flow through the backend

dpsutton 2021-04-20T21:02:37.340400Z

so it makes sense to put a boundary layer, strings to keywords in some places, arrays to vectors, etc

lilactown 2021-04-20T21:08:42.340600Z

yes, in that case I would make the layer very explicit

lilactown 2021-04-20T21:14:55.340800Z

it's very tempting to just (js->clj x :keywordize-keys true) and call it a day, but it makes it much more difficult to control the translation

lilactown 2021-04-20T21:15:28.341Z

you might find that the way the UI expresses certain things doesn't quite add up to what the analyzer expects and you end up having to translate it after the fact anyway