Fork me on GitHub
#re-frame
<
2018-01-11
>
cmal02:01:50

Thanks @mikethompson. Just feeling frustrating using D3.js with re-frame, because of the un-immutability nature of D3.js.

cmal02:01:33

BTW, do you have any examples about vega with re-frame?

mikethompson02:01:53

(previous link corrected)

cmal02:01:40

Thank you, @mikethompson. I will have a look.

genRaiy12:01:34

I tried phantom.js but it failed - does not support FormData 😱

genRaiy12:01:51

anyway, it turns out that headless chromium is a thing

genRaiy12:01:57

so that all works nicely

genRaiy12:01:47

in conjunction with puppeteer .. all can be ran in a CI

borkdude13:01:14

@raymcdermott We’re using headless Chrome, but headless Firefox is now also a thing

borkdude13:01:31

@raymcdermott running it in a Docker container, so nothing fancy to install on our CI server

borkdude13:01:25

several ways to do it, but we try to avoid node 🙂

genRaiy13:01:12

LOL I wonder why … it’s such a stable genius

borkdude13:01:09

This wrapper around webdriver API makes things easy for us: https://github.com/igrishaev/etaoin All from JVM -> Docker container running ChromeDriver / headless Chrome

borkdude13:01:36

There was also a good Clojure wrapper around Selenium but it was abandoned.

manutter5113:01:53

Wow, etaoin looks very interesting, thanks for mentioning it.

genRaiy14:01:37

so maybe I’m doing it wrong … can you drive the non-visuals (dispatch / subscribe) type tests from etaoin?

borkdude14:01:09

What does your test look like? As in, what does your assertion look like?

borkdude14:01:48

We don’t test at that level. Just “user visits this page, does this and that, and then this should be on the screen”.

borkdude14:01:41

But you could, using JS execution.

genRaiy14:01:32

I can’t add code snippets here

genRaiy14:01:48

I’ll put in the main page

borkdude14:01:05

or msg me privately, also fine

genRaiy15:01:20

I think the discussion is OK in the forum - no?

borkdude15:01:27

I think so.

borkdude14:01:42

@raymcdermott E.g. like this, you could execute JS:

(eta/js-execute
  *chrome*
  "$(\".title-text:contains('Frequency Table')\")[0].scrollIntoView()"))
(code is now obsolete, because etaoin has a scroll function now)

genRaiy14:01:19

seems not as good though 🙂

genRaiy14:01:58

using two tools is not the end of the world for sure

borkdude14:01:09

@raymcdermott why are you testing on this level instead of filling the form on the UI level?

genRaiy14:01:10

both methods of testing seem legit

borkdude14:01:40

sure, just curious. still need another form of testing on the UI level to ensure nothing breaks there

borkdude14:01:04

I guess it’s like unit vs integration testing, both have their purpose

borkdude14:01:33

but maybe node or something is a better fit for this kind of testing, since you don’t even need a browser for this

genRaiy14:01:26

re-frame is meant for browsers though and there are some things (like FormData for example) that might not work so easily on node.js

genRaiy14:01:49

I mean they might but that’s not the point of node

borkdude15:01:27

ok, you could start the test from within the app using etaoin js execution and then read the browser logs to see if the test ran ok or not.

borkdude15:01:20

I think my suggestion may be not a good one then, because we test on a higher level. Good luck!

borkdude16:01:14

(re 4:01PM, actually etaoin returns the result from the js expression as well, so if your tests are totally sync that would also work)

genRaiy16:01:12

@borkdude some things talk to servers async … but anyway who here wants to code in JS though? OK as a hack but would prefer to keep the code in CLJS and the infra can be node JS or browser JS as needed

genRaiy16:01:01

using npm / chrome are all a bit annoying

borkdude16:01:21

yeah, I meant your re-frame test. it says run-test-sync so I thought that could work

genRaiy16:01:24

it’s kind of shocking to me that a headless browser env is not first class for devs

genRaiy16:01:22

@borkdude I don’t know how that code helps tbh

genRaiy16:01:10

the js code with scrolltoview

genRaiy16:01:33

maybe it was just a sample of what was possible?

borkdude16:01:55

ok, it’s just showing how you can execute JS. In your case it would be (eta/js-execute “(whatever-test)“) and then assert from the JVM that everything is fine

borkdude16:01:22

FWIW, I’m using this Docker to spin up a headless chrome: https://hub.docker.com/r/robcherry/docker-chromedriver/

borkdude16:01:22

but during development I’m not using a headless one btw, I want to look at what it’s doing

genRaiy16:01:27

how does the JVM report on the tests?

genRaiy16:01:13

re non-headless … yes, sure

borkdude16:01:39

well, you can use regular clojure.test to drive etaoin. e.g. https://github.com/igrishaev/etaoin#writing-integration-tests-for-your-application but I’ve written my own glue between clojure.test and etaoin

borkdude16:01:00

you can do e.g. (is (= 3 (eta/js-execute "1+2"))), but I’m not sure how far you would get with that

genRaiy16:01:34

I’m getting confused about why I would use js-execute

genRaiy16:01:48

the other stuff all seems nice / legit

borkdude16:01:59

to execute your re-frame test inside the browser

genRaiy16:01:03

so I must be missing something obvious

borkdude16:01:58

I am assuming this code runs inside a browser where your app is loaded, no? https://clojurians.slack.com/files/U04V5V0V4/F8RCVN0JW/re-frame-tests.clj

genRaiy16:01:01

oh, I see - use that instead of Karma

genRaiy16:01:40

sorry, I was a bit slow there

borkdude16:01:45

right. but again, I’m not sure how nice that would be to work with. np

genRaiy16:01:47

ok, thanks though … I now get that it’s an option

genRaiy16:01:32

though does look a bit yucky tbh …. but then everything has some yuck on it 😉

borkdude16:01:53

it’s the law of conservation of yuck

genRaiy16:01:40

btw are you going to clojured?

borkdude16:01:57

I’m hesitant, because it’s only one day… the travel would be longer than the fun

genRaiy16:01:03

I know what you mean …. but we’re having a defn road trip … both Vijay and myself will be talking

borkdude16:01:31

I’m looking forward to the report in one of the next defn episodes!

genRaiy16:01:52

haha yes we will be sure to do that

genRaiy16:01:45

btw, the etaoin integration test is the first moment that I have used a dynamic var!

borkdude16:01:04

yeah, I’m also doing that

genRaiy16:01:05

scary 😱

borkdude16:01:20

actually in tests it’s the only place where I use it

genRaiy16:01:38

yes, should be safe

borkdude16:01:57

test code is more yuck-accepting

borkdude16:01:02

yuck-forgiving

genRaiy16:01:16

yuck-creating

genRaiy16:01:25

we need a yuck management system

genRaiy16:01:41

oh yeah - clojure 🙂

borkdude16:01:54

Clojure is the lotus built upon the mud

borkdude16:01:45

definitely coming to Dutch Clojure Days though

genRaiy16:01:09

likewise … so see you there

genRaiy16:01:26

should be a vegetable weekend to remember

borkdude16:01:41

betacarotene overdose

genRaiy16:01:49

friendly reminder - this is a not a porn server

genRaiy16:01:04

and the slack emoji set does not include a carrot!

borkdude16:01:24

who’s thinking of porn here then?

genRaiy16:01:49

betacarotene is my safe word

borkdude16:01:23

Btw, I hope you read the CoC (code of conduKt) for ClojureD?

genRaiy16:01:44

lol I’ll try to keep it clean

genRaiy16:01:57

but I see what you did there

borkdude16:01:06

Reinheitsgebot is a thing in Germany

genRaiy16:01:34

these are the marks of a truly civilised society

genRaiy17:01:04

no chlorine in the beer / chickens

genRaiy17:01:23

quick question ….

genRaiy17:01:33

assuming you have a login button

genRaiy17:01:45

how do you test for it’s visibility?

genRaiy17:01:05

(I can’t see a way to provide an ID in reframe)

genRaiy17:01:39

I have tried {:class :rc-button.btn.btn-default} without luck

genRaiy17:01:07

<button class="rc-button btn btn-default" style="flex: 0 0 auto;">Login</button>

genRaiy18:01:24

the class has spaces so I don’t know how to transpose that

borkdude19:01:55

do you mean from etaoin?

borkdude08:01:54

I do it like this:

(defn contains-text? [text]
  (format “//*[contains(text(),‘%s’)]” text))

(defn contains-class? [class]
  (format “//*[contains(@class, ‘%s’)]” class))

borkdude08:01:53

and then e.g.:

(eta/wait-exists *chrome* [{:tag :div :class “search-summary-text”}
                                 (contains-text? “results”)])

genRaiy08:01:32

ok, nice …. thanks, I’ll give it a shot

borkdude08:01:44

note that when you use :class it only matches on the full class, so this is a workaround for it

genRaiy08:01:37

hmmm doesn’t that effectively replace your contains-text function?

borkdude08:01:30

Not sure about that

genRaiy08:01:21

chasing the code, it runs query which seems to include matches like you have in your fn

genRaiy08:01:45

A query might be: - a string, so the current browser’s locator will be used. Examples: //div[@id=‘content’] for XPath, div.article for CSS selector

genRaiy08:01:21

anyway … I’ll give that a shot first and see how it goes 🙂

borkdude08:01:17

I gave you an example with a query.

[{:tag :div :class "search-summary-text"}
                                 (contains-text? "results")]
means: search for an element with class … which has a child element that contains text ….

borkdude08:01:50

has-class seems to do the same thing yeah, has-text is also there. It didn’t exist when I wrote this. I’m an early adopter 🙂

genRaiy08:01:14

haha well at least it means I’m not cracking up

borkdude08:01:12

cracking up?

genRaiy08:01:24

going crazy

genRaiy08:01:59

sorry I’m an idiom idiot

borkdude08:01:35

well, I learned English mainly by watching TV, but it only goes so far

genRaiy08:01:41

I tried to learn Flemish by watching TV but I can only endure one form of punishment at a time

genRaiy09:01:57

it’s actually even simpler …

genRaiy09:01:11

this works (wait-visible {:class "rc-button btn btn-default"})

borkdude09:01:05

yes, that also works, but you’d have to specify the full class. also visible can cause unexpected results, because in some cases the element never becomes visible. That’s why I use wait-exists instead

borkdude09:01:23

visible depends on the viewport your using

genRaiy09:01:28

sure … but in this case it must become visible (login) or we are screwed 😉

genRaiy09:01:47

but I take your general point

borkdude09:01:35

yeah, sometimes the user has to scroll a bit

borkdude09:01:19

working with the full class works, until you add a class… e.g. “active”, then it quickly breaks

genRaiy09:01:40

yeah, this is baby steps for me

genRaiy09:01:57

and babies fall over all the time

genRaiy09:01:10

but it’s exciting 🙂

borkdude09:01:21

yeah, it takes a few babies to get there, but it’s worth it

genRaiy09:01:13

thanks for picking me up off the floor and getting me walking again

borkdude09:01:07

The nice thing about etaoin is that it’s just a simple wrapper around an API, so if something is missing, just add a clj-http call somewhere

borkdude09:01:27

much better than Selenium Java crap if you ask me

borkdude10:01:35

Thanks for the heads up via Patreon 😛

borkdude11:01:26

Oh, I thought you sent it

borkdude11:01:32

but then it must be Vijay

genRaiy11:01:10

sent what?

genRaiy11:01:58

LOL yes he just informed me in another window

genRaiy11:01:42

if you have a question about the impact of post-Hegelian idealism on Clojure, now is your chance

genRaiy13:01:45

am trying to do an oauth2 flow using auth0 and it all works fine with chrome but fails when running headless …. have you seen anything like that?

genRaiy13:01:13

[ I can open an issue of course but just wondering ]

borkdude13:01:22

maybe it’s the visible/exists issue?

genRaiy13:01:45

I played with that in one or two steps without success

genRaiy13:01:54

but let me check

borkdude13:01:15

I’d also make a screenshot for debugging

borkdude13:01:52

+ you can execute some arbitrary js to test for elements etc. for debugging from the REPL

genRaiy13:01:42

seems like the auth0 overlay has to be visible

borkdude13:01:27

REPL your way through it

genRaiy13:01:08

I have used the REPL to build the script visually … I live the dream

borkdude13:01:57

How do Haskell people even get by. The type system doesn’t help you in any way with issues like this.

borkdude14:01:33

I mean any language without a real REPL

borkdude14:01:02

Don’t have anything to ask Zach, except to thank him for Aleph, the fundamental thing in Yada that we are gratefully using

genRaiy15:01:34

agreed on REPL

genRaiy15:01:57

you have time to think on Zach but yes, we are all grateful for aleph

genRaiy16:01:58

seems like the google oauth2 form changes whether visible or not 😞

genRaiy16:01:10

but yeah, amazing tools we have

borkdude16:01:33

didn’t understand

genRaiy16:01:21

when running chrome normally I get a different login form (different field names) from the one I get when running headless

borkdude16:01:41

ah tricky. whyyyyy.

genRaiy16:01:51

fuck knows

genRaiy16:01:12

but nice tools so that I could discover it 🙂

genRaiy16:01:44

being able to grab the html is killer