ClojureScript function is always executed - clojure

I'm learning ClojureScript, I have two functions that just change the content in the "root-app" div:
(ns blog.core)
(defn mount-components []
(let [content (js/document.getElementById "root-app")]
(while (.hasChildNodes content)
(.removeChild content (.-lastChild content)))
(.appendChild content (js/document.createTextNode "Wilkommen zu mein
ekelhaft blog!!"))))
(defn init! []
(def current_url js/window.location.href)
(if (clojure.string/includes? current_url "about")
(.log js/console (str "Whatever URL ->>>" js/window.location.href))
(mount-components)))
All works fine in http://localhost:3000/about because the "root-app" div exists in that page, but in http://localhost:3000/blog, I get the error message:
Because there is no such div in that page. All this is weird because it looks like ClojureScript in fact finds that:
(if (clojure.string/includes? current_url "about")
is actually false en the console.log is not printed.
My question is: why the function mount-components runs and sends the error message even when the conditional if is false? The weird thing is that the console.log:
(.log js/console (str "Whatever URL ->>>" js/window.location.href))
doesn't run but mount-components function does. I guess I'm not understanding the "sequence" in the way that ClojureScript works.

I'm not sure, but by your description, I think the logic you are thinking of and the logic you are actually testing are not the same. Your if statement looks for the word 'about' in the URL. If it is there, then it prints the console log i.e. it will be there for http://localhost:300/about. If it is NOT there, it will run the mount-components function, which looks for the div ID which you say is not included on the page, so you get the error. the mount-components is an ELSE statement and is therefore executed when the test is false.

The if form works like (if cond true-branch false-branch), so your (mount-component) is executed because it's in the false branch. Check out when, which only has a true branch.

Related

Clojure, re-graph fetched data from graphql successfully, but callback didn't activate

So I use re-graph version 0.1.11 and I try fetching data from the endpoint. After fetching data, I checked network tab in the browser and I found the expected data after that it should activate my callback function, but it doesn't seem to work (but sometimes it works and after refreshing the page a few times it doesn't work again). Here is the code.
;; how I init re-graph
(rf/dispatch [::re-graph/init
::conf/graphql-client-name
{:ws-url url
:http-url url
:ws-reconnect-timeout 500
:resume-subscriptions? true}])
(re-frame.core/reg-event-fx
::fetch-expected-data
(fn [cofx event]
(let [app-db (:db cofx)
some-params (-> event second (cljs.core/js->clj :keywordize-keys true))
token (-> app-db (lens/get-in (auth-db/lens-token :group-level-x)))]
(re-frame.core/dispatch
[:re-graph.core/query
::conf/graphql-client-name
"query findExpectedData($query: FetchExpectedDataInput!, $token: String!) {
findExpectedData(query: $query, token: $token){
value1
value2
...
}
}"
{:query some-params
:token token}
;; this is where the problem occurs
;; even though i found the data in the network tab, but
;; this callback doesn't seem to work (sometimes it works sometimes it doens't)
[::fetched-data-completed]]))))
(re-frame.core/reg-event-fx
::fetched-data-completed
(fn [cofx [_ {:keys [data errors] :as payload}]]
(let [app-db (:db cofx)
error-message (-> errors :errors first :message)]
(if (or (nil? errors) (empty? errors))
(do (bla bla when success))
(pr error-message)))))
I'm stuck with this problem for a few months. maybe because I fetch a lot of data at the same time? or could be something else anyone knows?. By the way the actual code I use defmacro, but it works the same way as the above code.
So I managed to find the answer to my own question. It seems like app-db has not been initialized properly so I fixed that problem and everything works fine. hope it helps someone who struggle with this problem.

How can I call a function in clojure and get a result?

I am trying to implement an amazon aws binding with Clojure, so that I can search for a book by sending an isbn and get an xml report of it. I am then trying to retrieve the salesrank and book title from the report. Here is what I am trying to use: https://github.com/FreeAgent/clj-amazon
Instead of using REPL, I made a core2.clj inside the src folder and added this code into it:
(ns clj_amazon.core2
(:use clj-amazon.core)
(:use clj-amazon.product-advertising)
(:gen-class))
(defn -main [& args]
(def ACCESS-KEY "my access code")
(def SECRET-KEY "my secret key" )
(def ASSOCIATE-ID "my id")
(def gibson-opus-search (with-signer (ACCESS-KEY, SECRET-KEY) (item-search :search-index "Books", :keywords "Neuromancer", :associate-tag ASSOCIATE-ID, :condition "New")))
(gibson-opus-search)
)
If I remove
(gibson-opus-search)
and run "lein run" in the command line, I get no errors. I have the correct access key/secret key, and it seems that the code is working fine. But I also get no report printed. I'm new to Clojure, so I'm not understanding what I should do next. I tried to call the function with
(gibson-opus-search)
, but then i get this error: wrong number of args(0) passed to persistentarraymap. How can I fix this?
You are defining gibson-opus-search with def which is for for assigning values, not defining functions. You need to define it with defn then call it with the right number of arguments.

Testing Timbre log outputs with Midje

I am using Timbre as a logging library but I am having issues testing it with Midje. I've got the following method and all I'm trying to do is asserting that Will be printed is printed.
(defn init [level]
(timbre/merge-config! {:output-fn my-output-fn})
(timbre/set-level! level)
(timbre/info "Will be printed")
(timbre/debug "Won't be printed"))
By wrapping (timbre/default-output-fn) around a function of my own my-output-fn, I am able to assert that only 1 out of 2 logs are printed, which is true:
(fact "print info but not debug"
(core/init :info) => nil
(provided
(core/my-output-fn anything) => irrelevant :times 1))
However I would like to make sure that the message being printed is Will be printed. I can't find any way of doing this, what would you do?
I am doing experiments in the following project https://github.com/stephanebruckert/timbre-midje
It is possible to validate the input of a function using Midje's as-checker prerequisite.
When you print the data that come into timbre/default-output-fn (I discovered this via your output-fn) you see it has the following structure:
{:hash_ #delay[{:status :pending, :val nil} 0x5ed805b1], :instant #inst "2016-10-14T17:07:16.779-00:00", :config {:level :info, ....
So the log-level is available in data. With as-checker the log level can be validated as follows:
(fact "print info but not debug"
(core/init :info) => nil
(provided
(timbre/default-output-fn anything ; opts is first argument
(as-checker (fn [data]
(= (-> data :config :level) ; get log level
:info)))) ; validate that it is info
=> anything :times 1)
(provided
(timbre/default-output-fn anything
(as-checker (fn [data]
(= (-> data :config :level)
:debug))))
=> anything :times 0))
Now, you wanted to check the content of the message. Not only the log level.
The actual message is not available in the opts or data passed toward default-output-fn. Looking around in the the Timbre code I saw it is available in a private function vargs->margs that takes an ?err, a msg-type and vargs. The vargs contain the message (in your case what comes in is for example :auto :p ["The message"]).
Via the as-checker approach the messages can be validated follows:
(fact "print Will be printed, not Won't be printed"
(core/init :info) => nil
(provided
(#'timbre/vargs->margs anything anything ["Will be printed"]) => {} :times 1)
(provided
(#'timbre/vargs->margs anything anything ["Won't be printed"]) => {} :times 0) )
Note that vargs->margs has to return a map, otherwise Timbre throws an exception in a later function.
This way it is validated that "Will be printed" is printed once, and "Won't be printed" is never printed.
#ErwinRooijakkers' idea worked but #ptaoussanis on Github has a good reason not to do it.
Please note that timbre/vargs->margs is private, and an implementation
detail. Its behaviour can change at any time without notice, would
strongly recommend not depending on it in any way.
It'd be possible to use a custom appender that sends output somewhere that are handy for your tests to analyse. You could setup these appenders as part of your test setup, and/or use something like timbre/with-config for the appropriate test calls.
So we can add an appender that passes the parameters to check (level message) to a stub.
core.clj
(defn init
([level]
(init level {}))
([level config]
(timbre/merge-config! config)
(timbre/set-level! level)
(timbre/info "will be printed")
(timbre/debug "won't be printed")))
core_test.clj
(:require [timbre-midje.core :as core]
[midje.sweet :refer :all]))
(defn log-stub [level message])
(def log-stub-appender
{:appenders
{:test-appender
{:enabled? true
:fn (fn [data] (log-stub (:level data) (:vargs data)))}}})
(fact "print info but not debug"
(core/init :info log-stub-appender) => nil
(provided
(log-stub :info ["will be printed"]) => irrelevant :times 1
(log-stub :debug ["won't be printed"]) => irrelevant :times 0))

Get information out of go block

I have the following ClojureScript code to make a POST request:
(defn perform-post [resource]
"Performs a post and returns the body :)"
(go (let [response (<! (http/post resource))]
(:body response))))
When I make a call to a resource which returns a number
(js/console.log (perform-post post-create-recipe-url))
This prints:
bufObject { buf={...}, n=1, cljs$lang$protocol_mask$partition0$=2,
more...}
bufObject { head=1, tail=0, length=1, meer...}
arr
["6276677237104933520", undefined]
I want to obtain the "6276677237104933520" (the post body) information as a "return" value.
How can I accomplish this? I tried <!! but it does not work since it is not defined.
Blocking semantics (<!!) is not available on ClojureScript platform.
You can retrieve value from a channel only within go block:
(go (js/console.log (<! (perform-post post-create-recipe-url))))

using clojurescript with jquery?

Here is what i am trying to do, I can replace Dom with jQuery, but I don't know how to get the Dom value. That's shame.
Gist
This is a gist which I followed it.
So I ask the origin author, but no response yet.
PS: I just want to try some cljs in browser, so I didn't use any lib like jayq.
I have tried something like (.val "yes"), but it seems to be wrong.
(ns hello-world.jquerytest)
(enable-console-print!)
(def jquery (js* "$"))
(defn x []
(->
(jquery ".meat")
(.html "yes")))
(jquery
(fn []
(x)
(-> (jquery "li.numbers")
(.html "pink")
(.append "banana"))))
Here is my answer based on Vanessa's comment
I tried
(defn x []
(->
(jquery ".meat")
(.html)
(println)))
It will print the value which I want.
If I am using doto
It will print #<[object Object]> in console which I do not want.
(defn x []
(->
(doto
(jquery ".meat")
(.html)
(println))))